<commit_before>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvcore/Debug.h>
#include <nvcore/Library.h>
#include "CudaUtils.h"

#if defined HAVE_CUDA
#include <cuda_runtime_api.h>
#endif

using namespace nv;
using namespace cuda;

#if NV_OS_WIN32

#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>

static bool isWindowsVista()
{
	OSVERSIONINFO osvi;
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

	::GetVersionEx(&osvi);
	return osvi.dwMajorVersion >= 6;
}

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

static bool isWow32()
{
	LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");

	BOOL bIsWow64 = FALSE;

	if (NULL != fnIsWow64Process)
	{
		if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
		{
			// Assume 32 bits.
			return true;
		}
	}

	return !bIsWow64;
}

#endif

#include <stdio.h>

static bool isCudaDriverAvailable(uint version)
{
#if NV_OS_WIN32
	Library nvcuda("nvcuda.dll");
#else
	Library nvcuda(NV_LIBRARY_NAME(cuda));
#endif

	if (!nvcuda.isValid())
	{
		return false;
	}

	if (version >= 2000)
	{
		void * address = nvcuda.bindSymbol("cuStreamCreate");
		if (address == NULL) return false;
	}

	if (version >= 2010)
	{
		void * address = nvcuda.bindSymbol("cuModuleLoadDataEx");
		if (address == NULL) return false;
	}

	return true;
}

/// Determine if CUDA is available.
bool nv::cuda::isHardwarePresent()
{
#if defined HAVE_CUDA
#if NV_OS_WIN32
	//if (isWindowsVista()) return false;
	//if (isWindowsVista() || !isWow32()) return false;
#endif
	int count = deviceCount();
	if (count == 1)
	{
		// Make sure it's not an emulation device.
		cudaDeviceProp deviceProp;
		cudaGetDeviceProperties(&deviceProp, 0);

		// deviceProp.name != Device Emulation (CPU)
		if (deviceProp.major == -1 || deviceProp.minor == -1)
		{
			return false;
		}

		// Make sure that CUDA driver matches CUDA runtime.
		if (!isCudaDriverAvailable(CUDART_VERSION))
		{
			return false;
		}

		// @@ Make sure that warp size == 32
	}

	return count > 0;
#else
	return false;
#endif
}

/// Get number of CUDA enabled devices.
int nv::cuda::deviceCount()
{
#if defined HAVE_CUDA
	int gpuCount = 0;

	cudaError_t result = cudaGetDeviceCount(&gpuCount);

	if (result == cudaSuccess)
	{
		return gpuCount;
	}
#endif
	return 0;
}

int nv::cuda::getFastestDevice()
{
	int max_gflops_device = 0;
#if defined HAVE_CUDA
	int max_gflops = 0;

	const int device_count = deviceCount();
	int current_device = 0;
	while (current_device < device_count)
	{
		cudaDeviceProp device_properties;
		cudaGetDeviceProperties(&device_properties, current_device);
		int gflops = device_properties.multiProcessorCount * device_properties.clockRate;

		if (device_properties.major != -1 && device_properties.minor != -1)
		{
			if( gflops > max_gflops )
			{
				max_gflops = gflops;
				max_gflops_device = current_device;
			}
		}

		current_device++;
	}
#endif
	return max_gflops_device;
}

/// Activate the given devices.
bool nv::cuda::setDevice(int i)
{
	nvCheck(i < deviceCount());
#if defined HAVE_CUDA
	cudaError_t result = cudaSetDevice(i);
	return result == cudaSuccess;
#else
	return false;
#endif
}
<commit_msg>Update version checking code.<commit_after>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvcore/Debug.h>
#include <nvcore/Library.h>
#include "CudaUtils.h"

#if defined HAVE_CUDA
#include <cuda.h>
#include <cuda_runtime_api.h>
#endif

using namespace nv;
using namespace cuda;

/* @@ Move this to win32 utils or somewhere else.
#if NV_OS_WIN32

#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>

static bool isWindowsVista()
{
	OSVERSIONINFO osvi;
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

	::GetVersionEx(&osvi);
	return osvi.dwMajorVersion >= 6;
}

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

static bool isWow32()
{
	LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");

	BOOL bIsWow64 = FALSE;

	if (NULL != fnIsWow64Process)
	{
		if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
		{
			// Assume 32 bits.
			return true;
		}
	}

	return !bIsWow64;
}

#endif
*/

static bool isCudaDriverAvailable(int version)
{
#if NV_OS_WIN32
	Library nvcuda("nvcuda.dll");
#else
	Library nvcuda(NV_LIBRARY_NAME(cuda));
#endif

	if (!nvcuda.isValid())
	{
		return false;
	}

	if (version >= 2000)
	{
		void * address = nvcuda.bindSymbol("cuStreamCreate");
		if (address == NULL) return false;
	}

	if (version >= 2010)
	{
		void * address = nvcuda.bindSymbol("cuModuleLoadDataEx");
		if (address == NULL) return false;
	}

	if (version >= 2020)
	{
		typedef CUresult (CUDAAPI * PFCU_DRIVERGETVERSION)(int * version);

		PFCU_DRIVERGETVERSION driverGetVersion = (PFCU_DRIVERGETVERSION)nvcuda.bindSymbol("cuDriverGetVersion");
		if (driverGetVersion == NULL) return false;

		int driverVersion;
		if (driverGetVersion(&driverVersion) != CUDA_SUCCESS) return false;

		return driverVersion >= version;
	}

	return false;
}

/// Determine if CUDA is available.
bool nv::cuda::isHardwarePresent()
{
#if defined HAVE_CUDA
#if NV_OS_WIN32
	//if (isWindowsVista()) return false;
	//if (isWindowsVista() || !isWow32()) return false;
#endif
	int count = deviceCount();
	if (count == 1)
	{
		// Make sure it's not an emulation device.
		cudaDeviceProp deviceProp;
		cudaGetDeviceProperties(&deviceProp, 0);

		// deviceProp.name != Device Emulation (CPU)
		if (deviceProp.major == -1 || deviceProp.minor == -1)
		{
			return false;
		}

		// Make sure that CUDA driver matches CUDA runtime.
		if (!isCudaDriverAvailable(CUDART_VERSION))
		{
			return false;
		}

		// @@ Make sure that warp size == 32
	}

	return count > 0;
#else
	return false;
#endif
}

/// Get number of CUDA enabled devices.
int nv::cuda::deviceCount()
{
#if defined HAVE_CUDA
	int gpuCount = 0;

	cudaError_t result = cudaGetDeviceCount(&gpuCount);

	if (result == cudaSuccess)
	{
		return gpuCount;
	}
#endif
	return 0;
}

int nv::cuda::getFastestDevice()
{
	int max_gflops_device = 0;
#if defined HAVE_CUDA
	int max_gflops = 0;

	const int device_count = deviceCount();
	int current_device = 0;
	while (current_device < device_count)
	{
		cudaDeviceProp device_properties;
		cudaGetDeviceProperties(&device_properties, current_device);
		int gflops = device_properties.multiProcessorCount * device_properties.clockRate;

		if (device_properties.major != -1 && device_properties.minor != -1)
		{
			if( gflops > max_gflops )
			{
				max_gflops = gflops;
				max_gflops_device = current_device;
			}
		}

		current_device++;
	}
#endif
	return max_gflops_device;
}

/// Activate the given devices.
bool nv::cuda::setDevice(int i)
{
	nvCheck(i < deviceCount());
#if defined HAVE_CUDA
	cudaError_t result = cudaSetDevice(i);
	return result == cudaSuccess;
#else
	return false;
#endif
}
<|endoftext|>


<commit_before>// sdl_main.cpp

#ifdef _WIN32
#  define WINDOWS_LEAN_AND_MEAN
#  define NOMINMAX
#  include <windows.h>
#endif

#include <GL/glew.h>
#include <SDL.h>
#include <SDL_syswm.h>
#undef main

#include "ShaderFunctions.h"
#include "Timer.h"

Timer g_timer;
int winw = 800;
int winh = 600;

struct Shadertoy {
    GLuint prog;
	GLuint progsound;
	GLint uloc_iResolution;
	GLint uloc_iGlobalTime;
	GLint uloc_iBlockOffset;
	GLint uloc_iSampleRate;
};

Shadertoy g_toy;

void keyboard(const SDL_Event& event, int key, int codes, int action, int mods)
{
    (void)codes;
    (void)mods;

    if (action == SDL_KEYDOWN)
    {
        switch (key)
        {
        default:
            break;

        case SDLK_ESCAPE:
            SDL_Quit();
            exit(0);
            break;
        }
    }
}

void PollEvents()
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
            keyboard(event, event.key.keysym.sym, 0, event.key.type, 0);
            break;

        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP:
            break;

        case SDL_MOUSEMOTION:
            break;

        case SDL_MOUSEWHEEL:
            break;

        case SDL_WINDOWEVENT:
            break;

        case SDL_QUIT:
            exit(0);
            break;

        default:
            break;
        }
    }
}

void display()
{
    glUseProgram(g_toy.prog);
    if (g_toy.uloc_iResolution > -1) glUniform3f(g_toy.uloc_iResolution, (float)winw, (float)winh, 1.f);
    if (g_toy.uloc_iGlobalTime > -1) glUniform1f(g_toy.uloc_iGlobalTime, g_timer.seconds());
    glRecti(-1,-1,1,1);
}

//
// Audio
//

struct
{
    SDL_AudioSpec spec;
    Uint8 *sound;               /* Pointer to wave data */
    Uint32 soundlen;            /* Length of wave data */
    int soundpos;               /* Current play position */
} wave;

void SDLCALL fillerup(void *unused, Uint8 * stream, int len)
{
    Uint8 *waveptr;
    int waveleft;

    waveptr = wave.sound + wave.soundpos;
    waveleft = wave.soundlen - wave.soundpos;

    while (waveleft <= len) { // wrap condition
        SDL_memcpy(stream, waveptr, waveleft);
        stream += waveleft;
        len -= waveleft;
        waveptr = wave.sound;
        waveleft = wave.soundlen;
        wave.soundpos = 0;
    }
    SDL_memcpy(stream, waveptr, len);
    wave.soundpos += len;
}

void play_audio()
{
    wave.spec.freq = 44100;
    wave.spec.format = AUDIO_U8; //AUDIO_S16LSB;
    wave.spec.channels = 2;
    wave.spec.callback = fillerup;

    const int mPlayTime = 60; // Shadertoy gives 60 seconds of audio
    wave.soundlen = mPlayTime * wave.spec.freq;
    wave.sound = new Uint8[2*wave.soundlen];
    glViewport(0,0,512,512);
    glUseProgram(g_toy.progsound);

    unsigned char mData[512*512*4];
    int mTmpBufferSamples = 262144;
    int mPlaySamples = wave.soundlen;
    int numBlocks = mPlaySamples / mTmpBufferSamples;
    for (int j=0; j<numBlocks; ++j)
    {
        int off = j * mTmpBufferSamples;
        if (g_toy.uloc_iBlockOffset > -1) glUniform1f(g_toy.uloc_iBlockOffset, (float)off / (float)wave.spec.freq);

        glRecti(-1,-1,1,1);
        // mData: Uint8Array[1048576]
        glReadPixels(0,0,512,512, GL_RGBA, GL_UNSIGNED_BYTE, mData);
        for (int i = 0; i<mTmpBufferSamples; ++i)
        {
            const float aL = -1.0f + 2.0f*((float)mData[4 * i + 0] + 256.0f*(float)mData[4 * i + 1]) / 65535.0f;
            const float aR = -1.0f + 2.0f*((float)mData[4 * i + 2] + 256.0f*(float)mData[4 * i + 3]) / 65535.0f;
            wave.sound[2*(off + i)  ] = (unsigned char)(.5f*(1.f+aL) * 255.f);
            wave.sound[2*(off + i)+1] = (unsigned char)(.5f*(1.f+aR) * 255.f);
        }
    }

    if (SDL_OpenAudio(&wave.spec, NULL) < 0)
    {
        SDL_FreeWAV(wave.sound);
        SDL_Quit();
        exit(2);
    }

    SDL_PauseAudio(0); // Start playing
}

int main(void)
{
    ///@todo cmd line aargs

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        return false;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    int winw = 800;
    int winh = 600;

    SDL_Window* pWindow = SDL_CreateWindow(
        "kinderegg",
        100,100,
        winw, winh,
        SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    // thank you http://www.brandonfoltz.com/2013/12/example-using-opengl-3-0-with-sdl2-and-glew/
    SDL_GLContext glContext = SDL_GL_CreateContext(pWindow);
    if (glContext == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 0;
    }

    const unsigned char *version = glGetString(GL_VERSION);
    if (version == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 1;
    }

    SDL_GL_MakeCurrent(pWindow, glContext);

    // Don't forget to initialize Glew, turn glewExperimental on to
    // avoid problems fetching function pointers...
    glewExperimental = GL_TRUE;
    const GLenum l_Result = glewInit();
    if (l_Result != GLEW_OK)
    {
        exit(EXIT_FAILURE);
    }

    g_toy.prog = makeShaderByName("basic");
    g_toy.uloc_iResolution = glGetUniformLocation(g_toy.prog, "iResolution");
    g_toy.uloc_iGlobalTime = glGetUniformLocation(g_toy.prog, "iGlobalTime");
    g_toy.progsound = makeShaderByName("basicsound");
    g_toy.uloc_iBlockOffset = glGetUniformLocation(g_toy.progsound, "iBlockOffset");
    g_toy.uloc_iSampleRate = glGetUniformLocation(g_toy.progsound, "iSampleRate");

    play_audio();
    glViewport(0,0, winw, winh);

    int quit = 0;
    while (quit == 0)
    {
        PollEvents();
        display();
        SDL_GL_SwapWindow(pWindow);
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(pWindow);
    SDL_CloseAudio();
    SDL_FreeWAV(wave.sound);
    SDL_Quit();
}
<commit_msg>Allocate sound temp buffer on heap instead of stack.<commit_after>// sdl_main.cpp

#ifdef _WIN32
#  define WINDOWS_LEAN_AND_MEAN
#  define NOMINMAX
#  include <windows.h>
#endif

#include <GL/glew.h>
#include <SDL.h>
#include <SDL_syswm.h>
#undef main

#include "ShaderFunctions.h"
#include "Timer.h"

Timer g_timer;
int winw = 800;
int winh = 600;

struct Shadertoy {
    GLuint prog;
    GLuint progsound;
    GLint uloc_iResolution;
    GLint uloc_iGlobalTime;
    GLint uloc_iBlockOffset;
    GLint uloc_iSampleRate;
};

Shadertoy g_toy;

void keyboard(const SDL_Event& event, int key, int codes, int action, int mods)
{
    (void)codes;
    (void)mods;

    if (action == SDL_KEYDOWN)
    {
        switch (key)
        {
        default:
            break;

        case SDLK_ESCAPE:
            SDL_Quit();
            exit(0);
            break;
        }
    }
}

void PollEvents()
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
            keyboard(event, event.key.keysym.sym, 0, event.key.type, 0);
            break;

        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP:
            break;

        case SDL_MOUSEMOTION:
            break;

        case SDL_MOUSEWHEEL:
            break;

        case SDL_WINDOWEVENT:
            break;

        case SDL_QUIT:
            exit(0);
            break;

        default:
            break;
        }
    }
}

void display()
{
    glUseProgram(g_toy.prog);
    if (g_toy.uloc_iResolution > -1) glUniform3f(g_toy.uloc_iResolution, (float)winw, (float)winh, 1.f);
    if (g_toy.uloc_iGlobalTime > -1) glUniform1f(g_toy.uloc_iGlobalTime, g_timer.seconds());
    glRecti(-1,-1,1,1);
}

//
// Audio
//

struct
{
    SDL_AudioSpec spec;
    Uint8 *sound;               /* Pointer to wave data */
    Uint32 soundlen;            /* Length of wave data */
    int soundpos;               /* Current play position */
} wave;

void SDLCALL fillerup(void *unused, Uint8 * stream, int len)
{
    Uint8 *waveptr;
    int waveleft;

    waveptr = wave.sound + wave.soundpos;
    waveleft = wave.soundlen - wave.soundpos;

    while (waveleft <= len) { // wrap condition
        SDL_memcpy(stream, waveptr, waveleft);
        stream += waveleft;
        len -= waveleft;
        waveptr = wave.sound;
        waveleft = wave.soundlen;
        wave.soundpos = 0;
    }
    SDL_memcpy(stream, waveptr, len);
    wave.soundpos += len;
}

void play_audio()
{
    wave.spec.freq = 44100;
    wave.spec.format = AUDIO_U8; //AUDIO_S16LSB;
    wave.spec.channels = 2;
    wave.spec.callback = fillerup;

    const int mPlayTime = 60; // Shadertoy gives 60 seconds of audio
    wave.soundlen = mPlayTime * wave.spec.freq;
    wave.sound = new Uint8[2*wave.soundlen];
    glViewport(0,0,512,512);
    glUseProgram(g_toy.progsound);

    unsigned char* mData = new unsigned char[512*512*4];
    int mTmpBufferSamples = 262144;
    int mPlaySamples = wave.soundlen;
    int numBlocks = mPlaySamples / mTmpBufferSamples;
    for (int j=0; j<numBlocks; ++j)
    {
        int off = j * mTmpBufferSamples;
        if (g_toy.uloc_iBlockOffset > -1) glUniform1f(g_toy.uloc_iBlockOffset, (float)off / (float)wave.spec.freq);

        glRecti(-1,-1,1,1);
        // mData: Uint8Array[1048576]
        glReadPixels(0,0,512,512, GL_RGBA, GL_UNSIGNED_BYTE, mData);
        for (int i = 0; i<mTmpBufferSamples; ++i)
        {
            const float aL = -1.0f + 2.0f*((float)mData[4 * i + 0] + 256.0f*(float)mData[4 * i + 1]) / 65535.0f;
            const float aR = -1.0f + 2.0f*((float)mData[4 * i + 2] + 256.0f*(float)mData[4 * i + 3]) / 65535.0f;
            wave.sound[2*(off + i)  ] = (unsigned char)(.5f*(1.f+aL) * 255.f);
            wave.sound[2*(off + i)+1] = (unsigned char)(.5f*(1.f+aR) * 255.f);
        }
    }
    delete [] mData;

    if (SDL_OpenAudio(&wave.spec, NULL) < 0)
    {
        SDL_FreeWAV(wave.sound);
        SDL_Quit();
        exit(2);
    }

    SDL_PauseAudio(0); // Start playing
}

int main(void)
{
    ///@todo cmd line aargs

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        return false;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    int winw = 800;
    int winh = 600;

    SDL_Window* pWindow = SDL_CreateWindow(
        "kinderegg",
        100,100,
        winw, winh,
        SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    // thank you http://www.brandonfoltz.com/2013/12/example-using-opengl-3-0-with-sdl2-and-glew/
    SDL_GLContext glContext = SDL_GL_CreateContext(pWindow);
    if (glContext == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 0;
    }

    const unsigned char *version = glGetString(GL_VERSION);
    if (version == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 1;
    }

    SDL_GL_MakeCurrent(pWindow, glContext);

    // Don't forget to initialize Glew, turn glewExperimental on to
    // avoid problems fetching function pointers...
    glewExperimental = GL_TRUE;
    const GLenum l_Result = glewInit();
    if (l_Result != GLEW_OK)
    {
        exit(EXIT_FAILURE);
    }

    g_toy.prog = makeShaderByName("basic");
    g_toy.uloc_iResolution = glGetUniformLocation(g_toy.prog, "iResolution");
    g_toy.uloc_iGlobalTime = glGetUniformLocation(g_toy.prog, "iGlobalTime");
    g_toy.progsound = makeShaderByName("basicsound");
    g_toy.uloc_iBlockOffset = glGetUniformLocation(g_toy.progsound, "iBlockOffset");
    g_toy.uloc_iSampleRate = glGetUniformLocation(g_toy.progsound, "iSampleRate");

    play_audio();
    glViewport(0,0, winw, winh);

    int quit = 0;
    while (quit == 0)
    {
        PollEvents();
        display();
        SDL_GL_SwapWindow(pWindow);
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(pWindow);
    SDL_CloseAudio();
    SDL_FreeWAV(wave.sound);
    SDL_Quit();
}
<|endoftext|>


<commit_before>// sdl_main.cpp

#ifdef _WIN32
#  define WINDOWS_LEAN_AND_MEAN
#  define NOMINMAX
#  include <windows.h>
#endif

#include <GL/glew.h>
#include <SDL.h>
#include <SDL_syswm.h>
#undef main

#include "ShaderFunctions.h"
#include "Timer.h"

Timer g_timer;
int winw = 800;
int winh = 600;

struct Shadertoy {
    GLuint prog;
    GLint uloc_iResolution;
    GLint uloc_iGlobalTime;
};

Shadertoy g_toy;

void PollEvents()
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
            break;

        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP:
            break;

        case SDL_MOUSEMOTION:
            break;

        case SDL_MOUSEWHEEL:
            break;

        case SDL_WINDOWEVENT:
            break;

        case SDL_QUIT:
            exit(0);
            break;

        default:
            break;
        }
    }
}

void display()
{
    glUseProgram(g_toy.prog);
    if (g_toy.uloc_iResolution > -1) glUniform3f(g_toy.uloc_iResolution, (float)winw, (float)winh, 1.f);
    if (g_toy.uloc_iGlobalTime > -1) glUniform1f(g_toy.uloc_iGlobalTime, g_timer.seconds());
    glRecti(-1,-1,1,1);
}

int main(void)
{
    ///@todo cmd line aargs

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        return false;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    int winw = 800;
    int winh = 600;

    SDL_Window* pWindow = SDL_CreateWindow(
        "kinderegg",
        100,100,
        winw, winh,
        SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    // thank you http://www.brandonfoltz.com/2013/12/example-using-opengl-3-0-with-sdl2-and-glew/
    SDL_GLContext glContext = SDL_GL_CreateContext(pWindow);
    if (glContext == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 0;
    }

    const unsigned char *version = glGetString(GL_VERSION);
    if (version == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 1;
    }

    SDL_GL_MakeCurrent(pWindow, glContext);

    // Don't forget to initialize Glew, turn glewExperimental on to
    // avoid problems fetching function pointers...
    glewExperimental = GL_TRUE;
    const GLenum l_Result = glewInit();
    if (l_Result != GLEW_OK)
    {
        exit(EXIT_FAILURE);
    }

    g_toy.prog = makeShaderByName("basic");
    g_toy.uloc_iResolution = glGetUniformLocation(g_toy.prog, "iResolution");
    g_toy.uloc_iGlobalTime = glGetUniformLocation(g_toy.prog, "iGlobalTime");

    int quit = 0;
    while (quit == 0)
    {
        PollEvents();
        display();
        SDL_GL_SwapWindow(pWindow);
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(pWindow);

    SDL_Quit();
}
<commit_msg>Add in basic audio init and callback to SDL main.<commit_after>// sdl_main.cpp

#ifdef _WIN32
#  define WINDOWS_LEAN_AND_MEAN
#  define NOMINMAX
#  include <windows.h>
#endif

#include <GL/glew.h>
#include <SDL.h>
#include <SDL_syswm.h>
#undef main

#include "ShaderFunctions.h"
#include "Timer.h"

Timer g_timer;
int winw = 800;
int winh = 600;

struct Shadertoy {
    GLuint prog;
    GLint uloc_iResolution;
    GLint uloc_iGlobalTime;
};

Shadertoy g_toy;

void PollEvents()
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
        case SDL_KEYUP:
            break;

        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP:
            break;

        case SDL_MOUSEMOTION:
            break;

        case SDL_MOUSEWHEEL:
            break;

        case SDL_WINDOWEVENT:
            break;

        case SDL_QUIT:
            exit(0);
            break;

        default:
            break;
        }
    }
}

void display()
{
    glUseProgram(g_toy.prog);
    if (g_toy.uloc_iResolution > -1) glUniform3f(g_toy.uloc_iResolution, (float)winw, (float)winh, 1.f);
    if (g_toy.uloc_iGlobalTime > -1) glUniform1f(g_toy.uloc_iGlobalTime, g_timer.seconds());
    glRecti(-1,-1,1,1);
}

//
// Audio
//

// prototype for our audio callback
void my_audio_callback(void *userdata, Uint8 *stream, int len);

const int samps = 1024*8; // 65536 bytes appears to be max chunk size
const int bufSz = samps*sizeof(Sint16); //*channels
Uint8 *sound_buffer = NULL;
Uint32 audio_pos = 0;
int counter = 0;

void play_audio()
{
    sound_buffer = new Uint8[bufSz];
    audio_pos = 0;

    static SDL_AudioSpec wav_spec;
    wav_spec.freq = 44100;
    wav_spec.format = AUDIO_S16LSB;
    wav_spec.channels = 1;
    wav_spec.samples = samps;
    wav_spec.callback = my_audio_callback;
    wav_spec.userdata = NULL;

    // Open the audio device
    if ( SDL_OpenAudio(&wav_spec, NULL) < 0 )
    {
        fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
        exit(-1);
    }
    SDL_PauseAudio(0); // Start playing
}

int cb = 0;

// audio callback function
// here you have to copy the data of your audio buffer into the requesting audio buffer (stream)
// you should only copy as much as the requested length (len)
void my_audio_callback(void *userdata, Uint8 *stream, int len)
{
    printf("   callback:  %x  %d  counter:%d   ap: %d\n", stream, len, counter, audio_pos);

    double pi = 3.1415;
    double Hz = 440 * ((cb%2)+1);// + (counter/256);
    double A = 32767;
    double SR = 44100;
    double F=2*pi*Hz/SR;

    Sint16* stream16 = reinterpret_cast<Sint16*>(sound_buffer);
    const int len16 = len / sizeof(Sint16);
    for (int z = 0; z<len16; z++)
    {
        counter++;
        stream16[z] = (Sint16) A*sin(F*(double)counter);
    }

    // Loop to beginning of buffer
    if (audio_pos + len > bufSz)
    {
        audio_pos = 0;
    }

    SDL_memset(stream, 0, len);
    const Uint8* apos = sound_buffer + audio_pos;
    //SDL_memcpy (stream, apos, len);                  // simply copy from one buffer into the other
    SDL_MixAudio(stream, apos, len, SDL_MIX_MAXVOLUME);// mix from one buffer into another

    audio_pos += len;
    ++cb;
}

int main(void)
{
    ///@todo cmd line aargs

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        return false;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    int winw = 800;
    int winh = 600;

    SDL_Window* pWindow = SDL_CreateWindow(
        "kinderegg",
        100,100,
        winw, winh,
        SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    // thank you http://www.brandonfoltz.com/2013/12/example-using-opengl-3-0-with-sdl2-and-glew/
    SDL_GLContext glContext = SDL_GL_CreateContext(pWindow);
    if (glContext == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 0;
    }

    const unsigned char *version = glGetString(GL_VERSION);
    if (version == NULL)
    {
        printf("There was an error creating the OpenGL context!\n");
        return 1;
    }

    SDL_GL_MakeCurrent(pWindow, glContext);

    // Don't forget to initialize Glew, turn glewExperimental on to
    // avoid problems fetching function pointers...
    glewExperimental = GL_TRUE;
    const GLenum l_Result = glewInit();
    if (l_Result != GLEW_OK)
    {
        exit(EXIT_FAILURE);
    }

    g_toy.prog = makeShaderByName("basic");
    g_toy.uloc_iResolution = glGetUniformLocation(g_toy.prog, "iResolution");
    g_toy.uloc_iGlobalTime = glGetUniformLocation(g_toy.prog, "iGlobalTime");

    //play_audio();

    int quit = 0;
    while (quit == 0)
    {
        PollEvents();
        display();
        SDL_GL_SwapWindow(pWindow);
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(pWindow);
    SDL_CloseAudio();
    SDL_Quit();
}
<|endoftext|>


<commit_before>/*
* oxygenwindowmanager.cpp
* pass some window mouse press/release/move event actions to window manager
* -------------------
*
* Copyright (c) 2010 Cédric Bellegarde <gnumdk@gmail.com>
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* Largely inspired from Qtcurve style
* Copyright (C) Craig Drummond, 2003 - 2010 craig.p.drummond@gmail.com
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenwindowmanager.h"
#include "oxygenstyle.h"
#include "config.h"

#include <gdk/gdkx.h>

namespace Oxygen
{

    //_________________________________________________
    WindowManager::WindowManager( void ):
        _mode( Full ),
        _drag( false ),
        _dragDistance( 4 ),
        _dragDelay( 500 ),
        _widget( 0L ),
        _x(-1),
        _y(-1)
    { initializeBlackList(); }

    //_________________________________________________
    WindowManager::~WindowManager( void )
    {
        _map.disconnectAll();
        _map.clear();
    }

    //_________________________________________________
    void WindowManager::registerWidget( GtkWidget* widget )
    {

        if( _map.contains( widget ) || widgetIsBlackListed( widget ) ) return;

        // Window with no decorations (set by app), let window manage it self
        if( GTK_IS_WINDOW( widget ) && !gtk_window_get_decorated( GTK_WINDOW( widget ) ) ) return;

        // widgets used in tabs also must be ignored (happens, unfortunately)
        GtkWidget* parent( gtk_widget_get_parent( widget ) );
        if( GTK_IS_NOTEBOOK( parent ) && Gtk::gtk_notebook_is_tab_label( GTK_NOTEBOOK( parent ), widget ) )
        { return; }

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::registerWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // Force widget to listen to relevant events
        gtk_widget_add_events( widget,
            GDK_BUTTON_RELEASE_MASK |
            GDK_BUTTON_PRESS_MASK   |
            GDK_LEAVE_NOTIFY_MASK   |
            GDK_BUTTON1_MOTION_MASK );

        // allocate new Data object
        Data& data( _map.registerWidget( widget ) );

        // connect signals
        if( _mode != Disabled ) connect( widget, data );

    }

    //_________________________________________________
    void WindowManager::unregisterWidget( GtkWidget* widget )
    {
        if( !_map.contains( widget ) ) return;

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::unregisterWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        _map.value( widget ).disconnect( widget );
        _map.erase( widget );

        if( _widget == widget )
        {
            _widget = 0L;
            _x = -1;
            _y = -1;
            _drag = false;
        }

    }

    //_________________________________________________
    void WindowManager::setMode( WindowManager::Mode mode )
    {
        if( mode == _mode ) return;

        // connect/disconnect all data in map, based on new and old mode
        if( mode == Disabled ) { _map.disconnectAll(); }
        else if( _mode == Disabled )
        {
            DataMap<Data>::Map& map( _map.map() );
            for( DataMap<Data>::Map::iterator iter = map.begin(); iter != map.end(); ++iter )
            { connect( iter->first, iter->second ); }
        }

        // assign new mode
        _mode = mode;

    }

    //_________________________________________________
    gboolean WindowManager::wmStyleSet( GtkWidget* widget, GtkStyle* , gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmDestroy( GtkWidget* widget, gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmButtonPress(GtkWidget *widget, GdkEventButton* event, gpointer data )
    {

        if( event->type == GDK_BUTTON_PRESS && event->button == Gtk::LeftButton )
        {

            #if OXYGEN_DEBUG
            std::cout << "Oxygen::WindowManager::wmButtonPress - "
                << widget
                << "(" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " " << gtk_widget_get_name( widget )
                << std::endl;
            #endif

            return static_cast<WindowManager*>(data)->isWindowDragWidget( widget, event );

        } else return false;

    }

    //_________________________________________________
    gboolean WindowManager::wmButtonRelease(GtkWidget *widget, GdkEventButton*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmLeave(GtkWidget *widget, GdkEventCrossing*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmMotion( GtkWidget *widget, GdkEventMotion* event, gpointer data )
    { return static_cast<WindowManager*>(data)->startDrag( widget, event ); }

    //_________________________________________________________________
    gboolean WindowManager::startDelayedDrag( gpointer data )
    {
        static_cast<WindowManager*>( data )->startDrag();
        return FALSE;
    }

    //_________________________________________________
    bool WindowManager::isWindowDragWidget( GtkWidget* widget, GdkEventButton* event )
    {
        if( _mode == Disabled ) return false;
        else if( (!_drag) && withinWidget(widget, event ) && useEvent( widget, event ) )
        {

            // store widget and event position
            _widget = widget;
            _x = int(event->x_root);
            _y = int(event->y_root);

            // start timer
            if( _timer.isRunning() ) _timer.stop();
            _timer.start( _dragDelay, (GSourceFunc)startDelayedDrag, this );

            // enable drag and accept
            _drag = true;

            /*
            always return false for GtkNotebook to avoid conflicts
            note: in principle it should be safe to return false anyway
            since window drag is supposed to occur on events for which
            nothing else is done (Hugo)
            */
            if( GTK_IS_NOTEBOOK( widget ) ) return false;
            else return true;

        } else return false;
    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, GdkEventMotion* event )
    {

        // make sure drag is enabled
        if( !_drag ) return false;

        // check displacement with respect to drag start
        const int distance( abs( _x - int(event->x_root) ) + abs( _y - int(event->y_root) ) );

        if( distance > 0 && _timer.isRunning() ) _timer.stop();
        if( distance < _dragDistance ) return false;

        // start drag from current position
        return startDrag( widget, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, int x, int y )
    {
        // create xevent and send.
        XEvent     xev;
        GtkWindow  *topLevel = GTK_WINDOW( gtk_widget_get_toplevel( widget ) );
        GdkWindow  *window = gtk_widget_get_window( GTK_WIDGET( topLevel ) );
        GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( topLevel ) );
        GdkWindow  *root = gdk_screen_get_root_window( gtk_window_get_screen( topLevel ) );

        xev.xclient.type = ClientMessage;
        xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_MOVERESIZE");
        xev.xclient.display = GDK_DISPLAY_XDISPLAY(display);
        xev.xclient.window = GDK_WINDOW_XID(window);
        xev.xclient.format = 32;
        xev.xclient.data.l[0] = x;
        xev.xclient.data.l[1] = y;
        xev.xclient.data.l[2] = 8; // NET::Move
        xev.xclient.data.l[3] = Button1;
        xev.xclient.data.l[4] = 0;
        XUngrabPointer(GDK_DISPLAY_XDISPLAY(display), CurrentTime);

        XSendEvent(
            GDK_DISPLAY_XDISPLAY(display),
            GDK_WINDOW_XID(root),
            False,
            SubstructureRedirectMask | SubstructureNotifyMask,
            &xev);

        // force a release as some widgets miss it...
        wmButtonRelease( widget, 0L, this );
        return true;
    }

    //_________________________________________________
    bool WindowManager::finishDrag( GtkWidget* widget )
    {

        _widget = 0L;
        _x = -1;
        _y = -1;

        if( _drag )
        {

            gtk_grab_remove(widget);
            gdk_pointer_ungrab( CurrentTime );
            _drag = false;

            /*
            always return false for GtkNotebook to avoid conflicts
            note: in principle it should be safe to return false anyway
            since window drag is supposed to occur on events for which
            nothing else is done (Hugo)
            */
            if( GTK_IS_NOTEBOOK( widget ) ) return false;
            else return true;

        } else return false;

    }

    //_________________________________________________
    bool WindowManager::withinWidget( GtkWidget* widget, GdkEventButton* event ) const
    {

        // get widget window
        GdkWindow *window( gtk_widget_get_parent_window( widget ) );

        // Some widgets aren't realized (GeditWindow for exemple) ...
        if( !window ) return true;

        GtkAllocation allocation;

        if( GTK_IS_NOTEBOOK( widget ) )
        {

            Gtk::gtk_notebook_get_tabbar_rect( GTK_NOTEBOOK( widget ), &allocation );

        } else {

            #if GTK_CHECK_VERSION(2, 18, 0)
            gtk_widget_get_allocation( widget, &allocation );
            #else
            allocation = widget->allocation;
            #endif

        }

        // Need to get absolute coordinates
        int nx(0);
        int ny(0);
        gdk_window_get_origin(window, &nx, &ny );
        allocation.x += nx;
        allocation.y += ny;

        return Gtk::gdk_rectangle_contains( &allocation, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________
    bool WindowManager::useEvent( GtkWidget* widget, GdkEventButton* event ) const
    {

        // check against mode
        if( _mode == Disabled ) return false;
        if( _mode == Minimal && !( GTK_IS_TOOLBAR( widget ) || GTK_IS_MENU_BAR( widget ) ) ) return false;

        // always accept if widget is not a container
        if( !GTK_IS_CONTAINER( widget ) ) return true;

        // if widget is a notebook, accept if there is no hovered tab
        if( GTK_IS_NOTEBOOK( widget ) )
        {

            return
                ( !Gtk::gtk_notebook_has_visible_arrows( GTK_NOTEBOOK( widget ) ) ) &&
                Style::instance().animations().tabWidgetEngine().contains( widget ) &&
                Style::instance().animations().tabWidgetEngine().hoveredTab( widget ) == -1;
        }

        return childrenUseEvent( widget, event, false );

    }

    //_________________________________________________
    bool WindowManager::childrenUseEvent( GtkWidget* widget, GdkEventButton* event, bool inNoteBook ) const
    {
        // accept, by default
        bool usable = true;

        // get children and check
        GList *children = gtk_container_get_children( GTK_CONTAINER( widget ) );
        for( GList *child = g_list_first( children ); child && usable ; child = g_list_next( child ) )
        {

            // cast child to GtkWidget
            if( !GTK_IS_WIDGET( child->data ) ) continue;
            GtkWidget* childWidget( GTK_WIDGET( child->data ) );

            // check widget state and type
            if( gtk_widget_get_state( childWidget ) == GTK_STATE_PRELIGHT ) {

                // if widget is prelight, we don't need to check where event happen,
                // any prelight widget indicate we can't do a move
                usable = false;

            } else if( GTK_IS_NOTEBOOK( childWidget ) ) {

                inNoteBook = true;

            } else if( event && withinWidget( childWidget, event ) ) {

                #if OXYGEN_DEBUG
                std::cout << "Oxygen::WindowManager::childrenUseEvent - "
                    << widget
                    << "(" << G_OBJECT_TYPE_NAME( childWidget ) << ")"
                    << " " << gtk_widget_get_name( childWidget )
                    << std::endl;
                #endif

                GdkWindow *window = gtk_widget_get_window( childWidget );
                if( window && gdk_window_is_visible( window ) )
                {

                    // check against black-list
                    if( widgetIsBlackListed( childWidget ) )
                    {

                        usable = false;

                    } else if( GTK_IS_BUTTON( childWidget ) && gtk_widget_get_state( childWidget ) != GTK_STATE_INSENSITIVE ) {

                        usable = false;

                    } else if( gtk_widget_get_events ( childWidget ) & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK) ) {

                        // widget listening to press event
                        usable = false;

                    } else if( GTK_IS_MENU_ITEM( childWidget ) ) {

                        // deal with menu item, GtkMenuItem only listen to
                        // GDK_BUTTON_PRESS_MASK when state == GTK_STATE_PRELIGHT
                        // so previous check are invalids :(
                        usable = false;

                    } else if( GTK_IS_SCROLLED_WINDOW( childWidget ) && ( !inNoteBook || gtk_widget_is_focus( childWidget ) ) ) {

                        // Scrolled do not send release events
                        // to parents so not usable
                        usable = false;

                    }
                }
            }

            // if child is a container and event has been accepted so far, also check it, recursively
            if( usable && GTK_IS_CONTAINER( childWidget ) )
            { usable = childrenUseEvent( childWidget, event, inNoteBook); }

        }

        // free list
        if( children ) g_list_free( children );

        return usable;
    }

    //_________________________________________________
    void WindowManager::initializeBlackList( void )
    {
        // clear list
        _blackList.clear();
        _blackList.push_back( "GtkPizza" );
        _blackList.push_back( "MetaFrames" );
        _blackList.push_back( "GladeDesignLayout" );
    }

    //________________________________________________________________________________
    void WindowManager::connect( GtkWidget* widget, WindowManager::Data& data )
    {
        data._destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( wmDestroy ), this );
        data._styleId.connect( G_OBJECT( widget ), "style-set", G_CALLBACK( wmStyleSet ), this );

        data._pressId.connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( wmButtonPress ), this );
        data._releaseId.connect( G_OBJECT( widget ), "button-release-event", G_CALLBACK( wmButtonRelease ), this );
        data._leaveId.connect( G_OBJECT( widget ), "leave-notify-event", G_CALLBACK( wmLeave ), this );
        data._motionId.connect( G_OBJECT( widget ), "motion-notify-event", G_CALLBACK( wmMotion ), this );
    }

    //_________________________________________________
    void WindowManager::Data::disconnect( GtkWidget* )
    {

        _leaveId.disconnect();
        _destroyId.disconnect();
        _pressId.disconnect();
        _releaseId.disconnect();
        _motionId.disconnect();
        _styleId.disconnect();

    }

}
<commit_msg>Revert "Always return false even when triggering window drag events in GtkNotebook, to prevent some conflicts"<commit_after>/*
* oxygenwindowmanager.cpp
* pass some window mouse press/release/move event actions to window manager
* -------------------
*
* Copyright (c) 2010 Cédric Bellegarde <gnumdk@gmail.com>
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* Largely inspired from Qtcurve style
* Copyright (C) Craig Drummond, 2003 - 2010 craig.p.drummond@gmail.com
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenwindowmanager.h"
#include "oxygenstyle.h"
#include "config.h"

#include <gdk/gdkx.h>

namespace Oxygen
{

    //_________________________________________________
    WindowManager::WindowManager( void ):
        _mode( Full ),
        _drag( false ),
        _dragDistance( 4 ),
        _dragDelay( 500 ),
        _widget( 0L ),
        _x(-1),
        _y(-1)
    { initializeBlackList(); }

    //_________________________________________________
    WindowManager::~WindowManager( void )
    {
        _map.disconnectAll();
        _map.clear();
    }

    //_________________________________________________
    void WindowManager::registerWidget( GtkWidget* widget )
    {

        if( _map.contains( widget ) || widgetIsBlackListed( widget ) ) return;

        // Window with no decorations (set by app), let window manage it self
        if( GTK_IS_WINDOW( widget ) && !gtk_window_get_decorated( GTK_WINDOW( widget ) ) ) return;

        // widgets used in tabs also must be ignored (happens, unfortunately)
        GtkWidget* parent( gtk_widget_get_parent( widget ) );
        if( GTK_IS_NOTEBOOK( parent ) && Gtk::gtk_notebook_is_tab_label( GTK_NOTEBOOK( parent ), widget ) )
        { return; }

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::registerWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // Force widget to listen to relevant events
        gtk_widget_add_events( widget,
            GDK_BUTTON_RELEASE_MASK |
            GDK_BUTTON_PRESS_MASK   |
            GDK_LEAVE_NOTIFY_MASK   |
            GDK_BUTTON1_MOTION_MASK );

        // allocate new Data object
        Data& data( _map.registerWidget( widget ) );

        // connect signals
        if( _mode != Disabled ) connect( widget, data );

    }

    //_________________________________________________
    void WindowManager::unregisterWidget( GtkWidget* widget )
    {
        if( !_map.contains( widget ) ) return;

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::unregisterWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        _map.value( widget ).disconnect( widget );
        _map.erase( widget );

        if( _widget == widget )
        {
            _widget = 0L;
            _x = -1;
            _y = -1;
            _drag = false;
        }

    }

    //_________________________________________________
    void WindowManager::setMode( WindowManager::Mode mode )
    {
        if( mode == _mode ) return;

        // connect/disconnect all data in map, based on new and old mode
        if( mode == Disabled ) { _map.disconnectAll(); }
        else if( _mode == Disabled )
        {
            DataMap<Data>::Map& map( _map.map() );
            for( DataMap<Data>::Map::iterator iter = map.begin(); iter != map.end(); ++iter )
            { connect( iter->first, iter->second ); }
        }

        // assign new mode
        _mode = mode;

    }

    //_________________________________________________
    gboolean WindowManager::wmStyleSet( GtkWidget* widget, GtkStyle* , gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmDestroy( GtkWidget* widget, gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmButtonPress(GtkWidget *widget, GdkEventButton* event, gpointer data )
    {

        if( event->type == GDK_BUTTON_PRESS && event->button == Gtk::LeftButton )
        {

            #if OXYGEN_DEBUG
            std::cout << "Oxygen::WindowManager::wmButtonPress - "
                << widget
                << "(" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " " << gtk_widget_get_name( widget )
                << std::endl;
            #endif

            return static_cast<WindowManager*>(data)->isWindowDragWidget( widget, event );

        } else return false;

    }

    //_________________________________________________
    gboolean WindowManager::wmButtonRelease(GtkWidget *widget, GdkEventButton*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmLeave(GtkWidget *widget, GdkEventCrossing*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmMotion( GtkWidget *widget, GdkEventMotion* event, gpointer data )
    { return static_cast<WindowManager*>(data)->startDrag( widget, event ); }

    //_________________________________________________________________
    gboolean WindowManager::startDelayedDrag( gpointer data )
    {
        static_cast<WindowManager*>( data )->startDrag();
        return FALSE;
    }

    //_________________________________________________
    bool WindowManager::isWindowDragWidget( GtkWidget* widget, GdkEventButton* event )
    {
        if( _mode == Disabled ) return false;
        else if( (!_drag) && withinWidget(widget, event ) && useEvent( widget, event ) )
        {

            // store widget and event position
            _widget = widget;
            _x = int(event->x_root);
            _y = int(event->y_root);

            // start timer
            if( _timer.isRunning() ) _timer.stop();
            _timer.start( _dragDelay, (GSourceFunc)startDelayedDrag, this );

            // enable drag and accept
            _drag = true;
            return true;

        } else return false;
    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, GdkEventMotion* event )
    {

        // make sure drag is enabled
        if( !_drag ) return false;

        // check displacement with respect to drag start
        const int distance( abs( _x - int(event->x_root) ) + abs( _y - int(event->y_root) ) );

        if( distance > 0 && _timer.isRunning() ) _timer.stop();
        if( distance < _dragDistance ) return false;

        // start drag from current position
        return startDrag( widget, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, int x, int y )
    {
        // create xevent and send.
        XEvent     xev;
        GtkWindow  *topLevel = GTK_WINDOW( gtk_widget_get_toplevel( widget ) );
        GdkWindow  *window = gtk_widget_get_window( GTK_WIDGET( topLevel ) );
        GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( topLevel ) );
        GdkWindow  *root = gdk_screen_get_root_window( gtk_window_get_screen( topLevel ) );

        xev.xclient.type = ClientMessage;
        xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_MOVERESIZE");
        xev.xclient.display = GDK_DISPLAY_XDISPLAY(display);
        xev.xclient.window = GDK_WINDOW_XID(window);
        xev.xclient.format = 32;
        xev.xclient.data.l[0] = x;
        xev.xclient.data.l[1] = y;
        xev.xclient.data.l[2] = 8; // NET::Move
        xev.xclient.data.l[3] = Button1;
        xev.xclient.data.l[4] = 0;
        XUngrabPointer(GDK_DISPLAY_XDISPLAY(display), CurrentTime);

        XSendEvent(
            GDK_DISPLAY_XDISPLAY(display),
            GDK_WINDOW_XID(root),
            False,
            SubstructureRedirectMask | SubstructureNotifyMask,
            &xev);

        // force a release as some widgets miss it...
        wmButtonRelease( widget, 0L, this );
        return true;
    }

    //_________________________________________________
    bool WindowManager::finishDrag( GtkWidget* widget )
    {

        _widget = 0L;
        _x = -1;
        _y = -1;

        if( _drag )
        {

            gtk_grab_remove(widget);
            gdk_pointer_ungrab( CurrentTime );
            _drag = false;
            return true;

        } else return false;

    }

    //_________________________________________________
    bool WindowManager::withinWidget( GtkWidget* widget, GdkEventButton* event ) const
    {

        // get widget window
        GdkWindow *window( gtk_widget_get_parent_window( widget ) );

        // Some widgets aren't realized (GeditWindow for exemple) ...
        if( !window ) return true;

        GtkAllocation allocation;

        if( GTK_IS_NOTEBOOK( widget ) )
        {

            Gtk::gtk_notebook_get_tabbar_rect( GTK_NOTEBOOK( widget ), &allocation );

        } else {

            #if GTK_CHECK_VERSION(2, 18, 0)
            gtk_widget_get_allocation( widget, &allocation );
            #else
            allocation = widget->allocation;
            #endif

        }

        // Need to get absolute coordinates
        int nx(0);
        int ny(0);
        gdk_window_get_origin(window, &nx, &ny );
        allocation.x += nx;
        allocation.y += ny;

        return Gtk::gdk_rectangle_contains( &allocation, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________
    bool WindowManager::useEvent( GtkWidget* widget, GdkEventButton* event ) const
    {

        // check against mode
        if( _mode == Disabled ) return false;
        if( _mode == Minimal && !( GTK_IS_TOOLBAR( widget ) || GTK_IS_MENU_BAR( widget ) ) ) return false;

        // always accept if widget is not a container
        if( !GTK_IS_CONTAINER( widget ) ) return true;

        // if widget is a notebook, accept if there is no hovered tab
        if( GTK_IS_NOTEBOOK( widget ) )
        {

            return
                ( !Gtk::gtk_notebook_has_visible_arrows( GTK_NOTEBOOK( widget ) ) ) &&
                Style::instance().animations().tabWidgetEngine().contains( widget ) &&
                Style::instance().animations().tabWidgetEngine().hoveredTab( widget ) == -1;
        }

        return childrenUseEvent( widget, event, false );

    }

    //_________________________________________________
    bool WindowManager::childrenUseEvent( GtkWidget* widget, GdkEventButton* event, bool inNoteBook ) const
    {
        // accept, by default
        bool usable = true;

        // get children and check
        GList *children = gtk_container_get_children( GTK_CONTAINER( widget ) );
        for( GList *child = g_list_first( children ); child && usable ; child = g_list_next( child ) )
        {

            // cast child to GtkWidget
            if( !GTK_IS_WIDGET( child->data ) ) continue;
            GtkWidget* childWidget( GTK_WIDGET( child->data ) );

            // check widget state and type
            if( gtk_widget_get_state( childWidget ) == GTK_STATE_PRELIGHT ) {

                // if widget is prelight, we don't need to check where event happen,
                // any prelight widget indicate we can't do a move
                usable = false;

            } else if( GTK_IS_NOTEBOOK( childWidget ) ) {

                inNoteBook = true;

            } else if( event && withinWidget( childWidget, event ) ) {

                #if OXYGEN_DEBUG
                std::cout << "Oxygen::WindowManager::childrenUseEvent - "
                    << widget
                    << "(" << G_OBJECT_TYPE_NAME( childWidget ) << ")"
                    << " " << gtk_widget_get_name( childWidget )
                    << std::endl;
                #endif

                GdkWindow *window = gtk_widget_get_window( childWidget );
                if( window && gdk_window_is_visible( window ) )
                {

                    // check against black-list
                    if( widgetIsBlackListed( childWidget ) )
                    {

                        usable = false;

                    } else if( GTK_IS_BUTTON( childWidget ) && gtk_widget_get_state( childWidget ) != GTK_STATE_INSENSITIVE ) {

                        usable = false;

                    } else if( gtk_widget_get_events ( childWidget ) & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK) ) {

                        // widget listening to press event
                        usable = false;

                    } else if( GTK_IS_MENU_ITEM( childWidget ) ) {

                        // deal with menu item, GtkMenuItem only listen to
                        // GDK_BUTTON_PRESS_MASK when state == GTK_STATE_PRELIGHT
                        // so previous check are invalids :(
                        usable = false;

                    } else if( GTK_IS_SCROLLED_WINDOW( childWidget ) && ( !inNoteBook || gtk_widget_is_focus( childWidget ) ) ) {

                        // Scrolled do not send release events
                        // to parents so not usable
                        usable = false;

                    }
                }
            }

            // if child is a container and event has been accepted so far, also check it, recursively
            if( usable && GTK_IS_CONTAINER( childWidget ) )
            { usable = childrenUseEvent( childWidget, event, inNoteBook); }

        }

        // free list
        if( children ) g_list_free( children );

        return usable;
    }

    //_________________________________________________
    void WindowManager::initializeBlackList( void )
    {
        // clear list
        _blackList.clear();
        _blackList.push_back( "GtkPizza" );
        _blackList.push_back( "MetaFrames" );
        _blackList.push_back( "GladeDesignLayout" );
    }

    //________________________________________________________________________________
    void WindowManager::connect( GtkWidget* widget, WindowManager::Data& data )
    {
        data._destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( wmDestroy ), this );
        data._styleId.connect( G_OBJECT( widget ), "style-set", G_CALLBACK( wmStyleSet ), this );

        data._pressId.connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( wmButtonPress ), this );
        data._releaseId.connect( G_OBJECT( widget ), "button-release-event", G_CALLBACK( wmButtonRelease ), this );
        data._leaveId.connect( G_OBJECT( widget ), "leave-notify-event", G_CALLBACK( wmLeave ), this );
        data._motionId.connect( G_OBJECT( widget ), "motion-notify-event", G_CALLBACK( wmMotion ), this );
    }

    //_________________________________________________
    void WindowManager::Data::disconnect( GtkWidget* )
    {

        _leaveId.disconnect();
        _destroyId.disconnect();
        _pressId.disconnect();
        _releaseId.disconnect();
        _motionId.disconnect();
        _styleId.disconnect();

    }

}
<|endoftext|>


<commit_before>/**
 * \file PancakeTest.cpp
 *
 * Some simple tests to make sure the pancake domain works properly.
 *
 * \author eaburns
 * \date 18-01-2010
 */

#include "pancake/PancakeTypes.hpp"
#include "pancake/PancakeState.hpp"

#include <stdlib.h>

int main(void)
{
	boost::array<Pancake, 14> cakes;

	for (unsigned int i = 0; i < 14; i += 1)
		cakes[i] = i +  1;

 	PancakeState14 s(cakes);

	std::cout << s << std::endl;
	std::cout << s.flip(4) << std::endl;
	std::cout << s.flip(5) << std::endl;

	return EXIT_FAILURE;
}
<commit_msg>Exit the pancake test with success instead of failure and print the hash values too.<commit_after>/**
 * \file PancakeTest.cpp
 *
 * Some simple tests to make sure the pancake domain works properly.
 *
 * \author eaburns
 * \date 18-01-2010
 */

#include "pancake/PancakeTypes.hpp"
#include "pancake/PancakeState.hpp"

#include <stdlib.h>

int main(void)
{
	boost::array<Pancake, 14> cakes;

	for (unsigned int i = 0; i < 14; i += 1)
		cakes[i] = i +  1;

 	PancakeState14 s(cakes);

	std::cout << s.get_hash_value() << ": " << s << std::endl;
	std::cout << s s.get_hash_value() << ": " <<.flip(4) << std::endl;
	std::cout << s s.get_hash_value() << ": " <<.flip(5) << std::endl;

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "ccode.hpp"

#include <kdblogger.h>

namespace
{

/**
 * @brief Cast a character to an unsigned character.
 *
 * @param character This parameter specifies the character this function casts to an unsigned value.
 *
 * @return A unsigned character corresponding to the given argument
 */
inline constexpr unsigned char operator"" _uc (char character) noexcept
{
	return static_cast<unsigned char> (character);
}

/**
 * @brief This function maps hex characters to integer numbers.
 *
 * @pre The specified character has to be between
 *
 *      - `'0'`–`'9'`,
 *      - `'a'`-`'f'`, or
 *      - `'A'`-`'F'`
 *
 *     .
 *
 * @param character This argument specifies the (hexadecimal) character this function converts.
 *
 * @return An integer number between `0` and `15` if the precondition is valid or `0` otherwise
 */
inline int elektraHexcodeConvFromHex (char character)
{
	if (character >= '0' && character <= '9') return character - '0';
	if (character >= 'a' && character <= 'f') return character - 'a' + 10;
	if (character >= 'A' && character <= 'F') return character - 'A' + 10;

	return 0; /* Unknown escape char */
}

} // end namespace

using namespace ckdb;
extern "C" {

/**
 * @brief This function sets default values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with default values.
 */
void setDefaultConfig (CCodeData * const mapping)
{
	unsigned char pairs[][2] = { { '\b'_uc, 'b'_uc }, { '\t'_uc, 't'_uc }, { '\n'_uc, 'n'_uc },  { '\v'_uc, 'v'_uc },
				     { '\f'_uc, 'f'_uc }, { '\r'_uc, 'r'_uc }, { '\\'_uc, '\\'_uc }, { '\''_uc, '\''_uc },
				     { '\"'_uc, '"'_uc }, { '\0'_uc, '0'_uc } };

	for (size_t pair = 0; pair < sizeof (pairs) / sizeof (pairs[0]); pair++)
	{
		unsigned char character = pairs[pair][0];
		unsigned char replacement = pairs[pair][1];

		mapping->encode[character] = replacement;
		mapping->decode[replacement] = character;
	}
}

/**
 * @brief This function sets values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with the values specified in `config`.
 * @param config This key set stores the character mappings this function stores inside `mappings`.
 * @param root This key stores the root key for the character mapping stored in `config`.
 */
void readConfig (CCodeData * const mapping, KeySet * const config, Key const * const root)
{
	Key const * key = 0;
	while ((key = ksNext (config)) != 0)
	{
		/* Ignore keys that are not directly below the config root key or have an incorrect size */
		if (keyRel (root, key) != 1 || keyGetBaseNameSize (key) != 3 || keyGetValueSize (key) != 3) continue;

		int character = elektraHexcodeConvFromHex (keyBaseName (key)[1]);
		character += elektraHexcodeConvFromHex (keyBaseName (key)[0]) * 16;

		int replacement = elektraHexcodeConvFromHex (keyString (key)[1]);
		replacement += elektraHexcodeConvFromHex (keyString (key)[0]) * 16;

		/* Hexencode this character! */
		mapping->encode[character & 255] = replacement;
		mapping->decode[replacement & 255] = character;
	}
}

/**
 * @brief This function replaces escaped character in a key value with unescaped characters.
 *
 * The function stores the unescaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be as large as the key value’s size.
 *
 * @param key This key holds the value this function decodes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode the value of the given key.
 */
void elektraCcodeDecode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	size_t const SIZE = keyGetValueSize (key) - 1;
	size_t out = 0;
	for (size_t in = 0; in < SIZE; ++in)
	{
		unsigned char character = value[in];

		if (character == mapping->escape)
		{
			++in; /* Advance twice */
			character = value[in];

			mapping->buffer[out] = mapping->decode[character & 255];
		}
		else
		{
			mapping->buffer[out] = character;
		}
		++out; /* Only one char is written */
	}

	mapping->buffer[out] = 0; // null termination for keyString()

	keySetRaw (key, mapping->buffer, out + 1);
}

/**
 * @brief This function replaces unescaped character in a key value with escaped characters.
 *
 * The function stores the escaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as the key value’s size.
 *
 * @param key This key stores the value this function escapes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode the value of the given key.
 */
void elektraCcodeEncode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	size_t const SIZE = keyGetValueSize (key);
	size_t out = 0;
	for (size_t in = 0; in < SIZE - 1; ++in)
	{
		unsigned char character = value[in];

		if (mapping->encode[character])
		{
			mapping->buffer[out + 1] = mapping->encode[character];
			// Escape char
			mapping->buffer[out] = mapping->escape;
			out += 2;
		}
		else
		{
			// just copy one character
			mapping->buffer[out] = value[in];
			// advance out cursor
			out++;
		}
	}

	mapping->buffer[out] = 0; // null termination for keyString()

	keySetRaw (key, mapping->buffer, out + 1);
}

// ====================
// = Plugin Interface =
// ====================

/** @see elektraDocOpen */
int elektraCcodeOpen (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * mapping = new CCodeData ();

	/* Store for later use...*/
	elektraPluginSetData (handle, mapping);

	KeySet * config = elektraPluginGetConfig (handle);

	Key * escape = ksLookupByName (config, "/escape", 0);
	mapping->escape = '\\';
	if (escape && keyGetBaseNameSize (escape) && keyGetValueSize (escape) == 3)
	{
		int escapeChar = elektraHexcodeConvFromHex (keyString (escape)[1]);
		escapeChar += elektraHexcodeConvFromHex (keyString (escape)[0]) * 16;

		mapping->escape = escapeChar & 255;
	}
	ELEKTRA_LOG_DEBUG ("Use “%c” as escape character", mapping->escape);

	Key * root = ksLookupByName (config, "/chars", 0);

	if (root)
	{
		readConfig (mapping, config, root);
	}
	else
	{
		setDefaultConfig (mapping);
	}

	return 0;
}

/** @see elektraDocClose */
int elektraCcodeClose (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));

	delete[](mapping->buffer);
	delete (mapping);

	return 0;
}

/** @see elektraDocGet */
int elektraCcodeGet (Plugin * handle, KeySet * returned, Key * parentKey)
{
	/* get all keys */

	if (!strcmp (keyName (parentKey), "system/elektra/modules/ccode"))
	{
		KeySet * pluginConfig =
			ksNew (30, keyNew ("system/elektra/modules/ccode", KEY_VALUE, "ccode plugin waits for your orders", KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports", KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/open", KEY_FUNC, elektraCcodeOpen, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/close", KEY_FUNC, elektraCcodeClose, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/get", KEY_FUNC, elektraCcodeGet, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/set", KEY_FUNC, elektraCcodeSet, KEY_END),
#include "readme_ccode.c"
			       keyNew ("system/elektra/modules/ccode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, pluginConfig);
		ksDel (pluginConfig);
		return 1;
	}

	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t valsize = keyGetValueSize (key);
		if (valsize > mapping->bufferSize)
		{
			mapping->bufferSize = valsize;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeDecode (key, mapping);
	}

	return 1; /* success */
}

/** @see elektraDocSet */
int elektraCcodeSet (Plugin * handle, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
{
	/* set all keys */
	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t valsize = keyGetValueSize (key);
		if (valsize * 2 > mapping->bufferSize)
		{
			mapping->bufferSize = valsize * 2;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeEncode (key, mapping);
	}

	return 1; /* success */
}

Plugin * ELEKTRA_PLUGIN_EXPORT (ccode)
{
	// clang-format off
	return elektraPluginExport("ccode",
		ELEKTRA_PLUGIN_OPEN,	&elektraCcodeOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraCcodeClose,
		ELEKTRA_PLUGIN_GET,	&elektraCcodeGet,
		ELEKTRA_PLUGIN_SET,	&elektraCcodeSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<commit_msg>CCode: Use macros for return values<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "ccode.hpp"

#include <kdblogger.h>

namespace
{

/**
 * @brief Cast a character to an unsigned character.
 *
 * @param character This parameter specifies the character this function casts to an unsigned value.
 *
 * @return A unsigned character corresponding to the given argument
 */
inline constexpr unsigned char operator"" _uc (char character) noexcept
{
	return static_cast<unsigned char> (character);
}

/**
 * @brief This function maps hex characters to integer numbers.
 *
 * @pre The specified character has to be between
 *
 *      - `'0'`–`'9'`,
 *      - `'a'`-`'f'`, or
 *      - `'A'`-`'F'`
 *
 *     .
 *
 * @param character This argument specifies the (hexadecimal) character this function converts.
 *
 * @return An integer number between `0` and `15` if the precondition is valid or `0` otherwise
 */
inline int elektraHexcodeConvFromHex (char character)
{
	if (character >= '0' && character <= '9') return character - '0';
	if (character >= 'a' && character <= 'f') return character - 'a' + 10;
	if (character >= 'A' && character <= 'F') return character - 'A' + 10;

	return 0; /* Unknown escape char */
}

} // end namespace

using namespace ckdb;
extern "C" {

/**
 * @brief This function sets default values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with default values.
 */
void setDefaultConfig (CCodeData * const mapping)
{
	unsigned char pairs[][2] = { { '\b'_uc, 'b'_uc }, { '\t'_uc, 't'_uc }, { '\n'_uc, 'n'_uc },  { '\v'_uc, 'v'_uc },
				     { '\f'_uc, 'f'_uc }, { '\r'_uc, 'r'_uc }, { '\\'_uc, '\\'_uc }, { '\''_uc, '\''_uc },
				     { '\"'_uc, '"'_uc }, { '\0'_uc, '0'_uc } };

	for (size_t pair = 0; pair < sizeof (pairs) / sizeof (pairs[0]); pair++)
	{
		unsigned char character = pairs[pair][0];
		unsigned char replacement = pairs[pair][1];

		mapping->encode[character] = replacement;
		mapping->decode[replacement] = character;
	}
}

/**
 * @brief This function sets values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with the values specified in `config`.
 * @param config This key set stores the character mappings this function stores inside `mappings`.
 * @param root This key stores the root key for the character mapping stored in `config`.
 */
void readConfig (CCodeData * const mapping, KeySet * const config, Key const * const root)
{
	Key const * key = 0;
	while ((key = ksNext (config)) != 0)
	{
		/* Ignore keys that are not directly below the config root key or have an incorrect size */
		if (keyRel (root, key) != 1 || keyGetBaseNameSize (key) != 3 || keyGetValueSize (key) != 3) continue;

		int character = elektraHexcodeConvFromHex (keyBaseName (key)[1]);
		character += elektraHexcodeConvFromHex (keyBaseName (key)[0]) * 16;

		int replacement = elektraHexcodeConvFromHex (keyString (key)[1]);
		replacement += elektraHexcodeConvFromHex (keyString (key)[0]) * 16;

		/* Hexencode this character! */
		mapping->encode[character & 255] = replacement;
		mapping->decode[replacement & 255] = character;
	}
}

/**
 * @brief This function replaces escaped character in a key value with unescaped characters.
 *
 * The function stores the unescaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be as large as the key value’s size.
 *
 * @param key This key holds the value this function decodes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode the value of the given key.
 */
void elektraCcodeDecode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	size_t const SIZE = keyGetValueSize (key) - 1;
	size_t out = 0;
	for (size_t in = 0; in < SIZE; ++in)
	{
		unsigned char character = value[in];

		if (character == mapping->escape)
		{
			++in; /* Advance twice */
			character = value[in];

			mapping->buffer[out] = mapping->decode[character & 255];
		}
		else
		{
			mapping->buffer[out] = character;
		}
		++out; /* Only one char is written */
	}

	mapping->buffer[out] = 0; // null termination for keyString()

	keySetRaw (key, mapping->buffer, out + 1);
}

/**
 * @brief This function replaces unescaped character in a key value with escaped characters.
 *
 * The function stores the escaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as the key value’s size.
 *
 * @param key This key stores the value this function escapes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode the value of the given key.
 */
void elektraCcodeEncode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	size_t const SIZE = keyGetValueSize (key);
	size_t out = 0;
	for (size_t in = 0; in < SIZE - 1; ++in)
	{
		unsigned char character = value[in];

		if (mapping->encode[character])
		{
			mapping->buffer[out + 1] = mapping->encode[character];
			// Escape char
			mapping->buffer[out] = mapping->escape;
			out += 2;
		}
		else
		{
			// just copy one character
			mapping->buffer[out] = value[in];
			// advance out cursor
			out++;
		}
	}

	mapping->buffer[out] = 0; // null termination for keyString()

	keySetRaw (key, mapping->buffer, out + 1);
}

// ====================
// = Plugin Interface =
// ====================

/** @see elektraDocOpen */
int elektraCcodeOpen (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * mapping = new CCodeData ();

	/* Store for later use...*/
	elektraPluginSetData (handle, mapping);

	KeySet * config = elektraPluginGetConfig (handle);

	Key * escape = ksLookupByName (config, "/escape", 0);
	mapping->escape = '\\';
	if (escape && keyGetBaseNameSize (escape) && keyGetValueSize (escape) == 3)
	{
		int escapeChar = elektraHexcodeConvFromHex (keyString (escape)[1]);
		escapeChar += elektraHexcodeConvFromHex (keyString (escape)[0]) * 16;

		mapping->escape = escapeChar & 255;
	}
	ELEKTRA_LOG_DEBUG ("Use “%c” as escape character", mapping->escape);

	Key * root = ksLookupByName (config, "/chars", 0);

	if (root)
	{
		readConfig (mapping, config, root);
	}
	else
	{
		setDefaultConfig (mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocClose */
int elektraCcodeClose (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));

	delete[](mapping->buffer);
	delete (mapping);

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocGet */
int elektraCcodeGet (Plugin * handle, KeySet * returned, Key * parentKey)
{
	/* get all keys */

	if (!strcmp (keyName (parentKey), "system/elektra/modules/ccode"))
	{
		KeySet * pluginConfig =
			ksNew (30, keyNew ("system/elektra/modules/ccode", KEY_VALUE, "ccode plugin waits for your orders", KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports", KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/open", KEY_FUNC, elektraCcodeOpen, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/close", KEY_FUNC, elektraCcodeClose, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/get", KEY_FUNC, elektraCcodeGet, KEY_END),
			       keyNew ("system/elektra/modules/ccode/exports/set", KEY_FUNC, elektraCcodeSet, KEY_END),
#include "readme_ccode.c"
			       keyNew ("system/elektra/modules/ccode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, pluginConfig);
		ksDel (pluginConfig);
		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}

	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t valsize = keyGetValueSize (key);
		if (valsize > mapping->bufferSize)
		{
			mapping->bufferSize = valsize;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeDecode (key, mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

/** @see elektraDocSet */
int elektraCcodeSet (Plugin * handle, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
{
	/* set all keys */
	CCodeData * mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t valsize = keyGetValueSize (key);
		if (valsize * 2 > mapping->bufferSize)
		{
			mapping->bufferSize = valsize * 2;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeEncode (key, mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (ccode)
{
	// clang-format off
	return elektraPluginExport("ccode",
		ELEKTRA_PLUGIN_OPEN,	&elektraCcodeOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraCcodeClose,
		ELEKTRA_PLUGIN_GET,	&elektraCcodeGet,
		ELEKTRA_PLUGIN_SET,	&elektraCcodeSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<|endoftext|>


<commit_before>#include <stdexcept>
#include "Logger.hpp"

using namespace std;

Logger* Logger::pInstance = nullptr;

mutex Logger::sMutex;

Logger& Logger::instance()
{
    lock_guard<mutex> guard(sMutex);
    if (pInstance == nullptr)
        pInstance = new Logger();
    return *pInstance;
}

Logger::Logger() { }

void Logger::log(const string& inMessage)
{
    lock_guard<mutex> guard(sMutex);
    std::cout << inMessage << std::endl;
}<commit_msg>Correcting case of header file.<commit_after>#include <stdexcept>
#include "logger.hpp"

using namespace std;

Logger* Logger::pInstance = nullptr;

mutex Logger::sMutex;

Logger& Logger::instance()
{
    lock_guard<mutex> guard(sMutex);
    if (pInstance == nullptr)
        pInstance = new Logger();
    return *pInstance;
}

Logger::Logger() { }

void Logger::log(const string& inMessage)
{
    lock_guard<mutex> guard(sMutex);
    std::cout << inMessage << std::endl;
}
<|endoftext|>