<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_LIST_HPP
#define REALM_LIST_HPP

#include <realm/link_view.hpp>

#include <memory>

namespace realm {
class ObjectSchema;
class Realm;

class List {
public:
    List(std::shared_ptr<Realm> r, const ObjectSchema& s, LinkViewRef l) noexcept;
    ~List();

    const ObjectSchema& get_object_schema() const { return *m_object_schema; }
    const std::shared_ptr<Realm>& realm() const { return m_realm; }

    size_t size() const;
    Row get(size_t row_ndx) const;
    void set(size_t row_ndx, size_t target_row_ndx);

    void add(size_t target_row_ndx);
    void remove(size_t list_ndx);
    void insert(size_t list_ndx, size_t target_row_ndx);

    Query get_query() const;
    void verify_in_tranaction() const;

    // These are implemented in object_accessor.hpp
    template <typename ValueType, typename ContextType>
    void add(ContextType ctx, ValueType value);

    template <typename ValueType, typename ContextType>
    void insert(ContextType ctx, ValueType value, size_t list_ndx);

    template <typename ValueType, typename ContextType>
    void set(ContextType ctx, ValueType value, size_t list_ndx);

private:
    std::shared_ptr<Realm> m_realm;
    const ObjectSchema* m_object_schema;
    LinkViewRef m_link_view;

    void verify_valid_row(size_t row_ndx, bool insertion = false) const;
    void verify_attached() const;
};
}

#endif /* REALM_LIST_HPP */
<commit_msg>Change List::realm() to List::get_realm() for consistency<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_LIST_HPP
#define REALM_LIST_HPP

#include <realm/link_view.hpp>

#include <memory>

namespace realm {
class ObjectSchema;
class Realm;

class List {
public:
    List(std::shared_ptr<Realm> r, const ObjectSchema& s, LinkViewRef l) noexcept;
    ~List();

    const ObjectSchema& get_object_schema() const { return *m_object_schema; }
    const std::shared_ptr<Realm>& get_realm() const { return m_realm; }
    Query get_query() const;

    size_t size() const;
    Row get(size_t row_ndx) const;
    void set(size_t row_ndx, size_t target_row_ndx);

    void add(size_t target_row_ndx);
    void remove(size_t list_ndx);
    void insert(size_t list_ndx, size_t target_row_ndx);

    void verify_in_tranaction() const;

    // These are implemented in object_accessor.hpp
    template <typename ValueType, typename ContextType>
    void add(ContextType ctx, ValueType value);

    template <typename ValueType, typename ContextType>
    void insert(ContextType ctx, ValueType value, size_t list_ndx);

    template <typename ValueType, typename ContextType>
    void set(ContextType ctx, ValueType value, size_t list_ndx);

private:
    std::shared_ptr<Realm> m_realm;
    const ObjectSchema* m_object_schema;
    LinkViewRef m_link_view;

    void verify_valid_row(size_t row_ndx, bool insertion = false) const;
    void verify_attached() const;
};
}

#endif /* REALM_LIST_HPP */
<|endoftext|>


<commit_before>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {

    try {
        Inotify notify;

        InotifyWatch watch(file, IN_ALL_EVENTS);
        notify.Add(watch);
        for (;;) {
            std::cout << "Child: Watching again" << std::endl;
            notify.WaitForEvents();

            size_t count = notify.GetEventCount();
            while (count > 0) {
                InotifyEvent event;
                bool got_event = notify.GetEvent(&event);

                if (got_event) {
                    std::string mask_str;
                    event.DumpTypes(mask_str);

                    std::string filename = event.GetName();
                    std::cout << "event mask: \"" << mask_str << "\", ";
                    std::cout << "filename: \"" << filename << "\"" << std::endl;
                }

                count--;
            }
        }
    } catch (InotifyException &e) {
        std::cerr << "Inotify exception occured: " << e.GetMessage() << std::endl;
    } catch (std::exception &e) {
        std::cerr << "STL exception occured: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown exception occured" << std::endl;
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
            std::cout << "Watch thread shutdown" << std::endl;
        }
        break;

        default: // parent
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<commit_msg>debug<commit_after>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {

    try {
        Inotify notify;

        InotifyWatch watch(file, IN_ALL_EVENTS);
        notify.Add(watch);
        for (;;) {
            std::cout << "Child: Watching again" << std::endl;
            notify.WaitForEvents();

            size_t count = notify.GetEventCount();
            while (count > 0) {
                InotifyEvent event;
                bool got_event = notify.GetEvent(&event);

                if (got_event) {
                    std::string mask_str;
                    event.DumpTypes(mask_str);

                    std::string filename = event.GetName();
                    std::cout << "event mask: \"" << mask_str << "\", ";
                    std::cout << "filename: \"" << filename << "\"" << std::endl;
                    *fragHasChanged = true;
                }

                count--;
            }
        }
    } catch (InotifyException &e) {
        std::cerr << "Inotify exception occured: " << e.GetMessage() << std::endl;
    } catch (std::exception &e) {
        std::cerr << "STL exception occured: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown exception occured" << std::endl;
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
            std::cout << "Watch thread shutdown" << std::endl;
        }
        break;

        default: // parent
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<|endoftext|>


<commit_before>/*

  Adapted from here:
  http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue

*/

#include <assert.h>
#include <iostream>
#include <thread>

#define ERROR_NO_ERROR 0
#define ERROR_BAD_PARAMS -1
#define ERROR_FULL -2
#define ERROR_EMPTY -3

template<typename T>
class ring_buffer_t
{
public:

    ring_buffer_t(
        size_t size) :
        _size(size + 1), // need one extra element for a guard
        _mask(size),
        _buffer(reinterpret_cast<buffer_elem_t*>(new buffer_elem_aligned_t[_size])),
        _head(0),
        _tail(0)
    {
        assert(size >= 2);
        memset(_buffer, 0, sizeof(buffer_elem_t) * _size);
    }

    ~ring_buffer_t()
    {
        delete[] _buffer;
    }

    int
    enqueue(
        const T& input)
    {
        buffer_elem_t* elem;
        size_t         insert_pos = _head.load(std::memory_order_relaxed);

        for (;;) {
            // grab the element at index _head
            elem = &_buffer[insert_pos & _mask];

            // grab the sequence of the element at head
            size_t seq = elem->sequence.load(std::memory_order_acquire);

            int diff = seq - insert_pos;
            // if sequence and insert position are the same then we know no other thread is attempting to mutate that element
            if (diff == 0) {

                // if _head hasn't been modified since we last checked, increment it so that we have it to ourselves
                if (_head.compare_exchange_weak(insert_pos, insert_pos + 1, std::memory_order_relaxed)) {
                    break;
                }
                // someone else wrote to _head and beat us to the punch. spin
            }
            else if (diff < 0) {
                // queue is full
                return ERROR_FULL;
            }
            else {
                // someone was in the process of reading from _head. spin
                insert_pos = _head.load(std::memory_order_relaxed);
            }

            // yield so that another thread can use the CPU core
            // this is a noop if no other thread is waiting
            std::this_thread::yield();
        }

        // the element is all ours, set the data and close the transaction by setting sequence.
        elem->data = input;
        elem->sequence.store(insert_pos + 1, std::memory_order_release);
        return ERROR_NO_ERROR;
    }

    bool
    dequeue(
        T& output)
    {
        buffer_elem_t* elem;
        size_t         read_pos = _head.load(std::memory_order_relaxed);
        for (;;) {
            elem = &_buffer[read_pos & _mask];
            size_t sequence = entry->sequence.load(std::memory_order_acquire);
            int diff = seq - read_pos + 1;

            if (dif == 0) {
                if (_tail.compare_exchange_weak(read_pos, read_pos + 1, std::memory_order_relaxed)) {
                    break;
                }
            }
            else if (dif < 0) {
                // queue is empty
                return ERROR_EMPTY;
            }
            else {
                // someone was in the process writing to _tail. spin
                read_pos = _tail.load(std::memory_order_relaxed);
            }

            // yield so that another thread can use the CPU core
            // this is a noop if no other thread is waiting
            std::this_thread::yield();
        }

        output = cell->data;
        entry->sequence.store(read_pos + _mask + 1, std::memory_order_release);
        return true;
    }

private:

    struct buffer_elem_t
    {
        std::atomic<size_t>   sequence;
        T                     data;
    };

    typedef typename std::aligned_storage<sizeof(buffer_elem_t), std::alignment_of<buffer_elem_t>::value>::type buffer_elem_aligned_t;

    const size_t   _size;
    const size_t   _mask;
    buffer_elem_t* _buffer;

    std::atomic<size_t>  _head;
    std::atomic<size_t>  _tail;

    ring_buffer_t(const ring_buffer_t&) {}
    void operator=(const ring_buffer_t&) {}
};

int
main()
{
    ring_buffer_t<int> buffer(2);
    std::cout << "value 0: " << buffer.enqueue(0) << std::endl;
    std::cout << "value 1: " << buffer.enqueue(1) << std::endl;
    std::cout << "value 2: " << buffer.enqueue(2) << std::endl;
}
<commit_msg>replace ring buffer with SPSC queue<commit_after>/*

  SPSC queue adapted from here:
  http://cbloomrants.blogspot.com/2009/02/02-26-09-low-level-threading-part-51.html

*/

#include <assert.h>
#include <iostream>
#include <thread>

template<typename T>
class spsc_queue_t
{
public:

    spsc_queue_t() :
        _head(reinterpret_cast<buffer_node_t*>(new buffer_node_aligned_t)),
        _tail(_head.load(std::memory_order_relaxed))
    {}

    ~spsc_queue_t()
    {
        T output;
        while (this->dequeue(output)) {}
        buffer_node_t* front = _head.load(std::memory_order_relaxed);
        delete front;
    }

    void
    enqueue(
        const T& input)
    {
        buffer_node_t* node = reinterpret_cast<buffer_node_t*>(new buffer_node_aligned_t);
        node->data = input;
        node->next.store(NULL, std::memory_order_relaxed);

        buffer_node_t* back = _tail.load(std::memory_order_relaxed);
        back->next.store(node, std::memory_order_release);
        _tail.store(node, std::memory_order_relaxed);
    }

    bool
    dequeue(
        T& output)
    {
        buffer_node_t* front = _head.load(std::memory_order_relaxed);
        buffer_node_t* next = front->next.load(std::memory_order_acquire);
        if (next == NULL) {
            // buffer is empty
            return false;
        }
        output = next->data;
        _head.store(next, std::memory_order_release);
        delete front;
        return true;
    }

private:

    struct buffer_node_t
    {
        buffer_node_t() :
            next(NULL)
        {}

        std::atomic<buffer_node_t*> next;
        T                           data;
    };

    typedef typename std::aligned_storage<sizeof(buffer_node_t), std::alignment_of<buffer_node_t>::value>::type buffer_node_aligned_t;

    std::atomic<buffer_node_t*> _head;
    std::atomic<buffer_node_t*> _tail;

    spsc_queue_t(const spsc_queue_t&) {}
    void operator=(const spsc_queue_t&) {}
};

int
main()
{
    spsc_queue_t<int>* buffer = new spsc_queue_t<int>();
    buffer->enqueue(0);
    buffer->enqueue(1);
    buffer->enqueue(2);
    buffer->enqueue(3);

    int output = -1;
    std::cout << "value 0: " << buffer->dequeue(output) << " " << output << std::endl;
    std::cout << "value 1: " << buffer->dequeue(output) << " " << output << std::endl;
    std::cout << "value 2: " << buffer->dequeue(output) << " " << output << std::endl;
    delete buffer;
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2014 Marianne Gagnon

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 <cstdlib>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <vector>
#include "Settings.h"

#include "Utils.h"
#include "DylibBundler.h"

/*
 TODO
 - what happens if a library is not remembered by full path but only name? (support improved, still not perfect)
 - could get mixed up if symlink and original are not in the same location (won't happen for UNIX prefixes like /usr/, but in random directories?)

 FIXME: why does it copy plugins i try to fix to the libs directory?

 */

const std::string VERSION = "0.4.1";

// FIXME - no memory management is done at all (anyway the program closes immediately so who cares?)

std::string installPath = "";

void showHelp()
{
    std::cout << "dylibbundler " << VERSION << std::endl;
    std::cout << "dylibbundler is a utility that helps bundle dynamic libraries inside mac OS X app bundles.\n" << std::endl;

    std::cout << "-x, --fix-file <file to fix (executable or app plug-in)>" << std::endl;
    std::cout << "-b, --bundle-deps" << std::endl;
    std::cout << "-d, --dest-dir <directory to send bundled libraries (relative to cwd)>" << std::endl;
    std::cout << "-p, --install-path <'inner' path of bundled libraries (usually relative to executable, by default '@executable_path/../libs/')>" << std::endl;
    std::cout << "-of, --overwrite-files (allow overwriting files in output directory)" << std::endl;
    std::cout << "-od, --overwrite-dir (totally overwrite output directory if it already exists. implies --create-dir)" << std::endl;
    std::cout << "-cd, --create-dir (creates output directory if necessary)" << std::endl;
    std::cout << "-i, --ignore <location to ignore> (will ignore libraries in this directory)" << std::endl;
    std::cout << "-h, --help" << std::endl;
}

int main (int argc, char * const argv[])
{

    // parse arguments
    for(int i=0; i<argc; i++)
    {
        if(strcmp(argv[i],"-x")==0 or strcmp(argv[i],"--fix-file")==0)
        {
            i++;
            Settings::addFileToFix(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-b")==0 or strcmp(argv[i],"--bundle-deps")==0)
        {
            Settings::bundleLibs(true);
            continue;
        }
        else if(strcmp(argv[i],"-p")==0 or strcmp(argv[i],"--install-path")==0)
        {
            i++;
            Settings::inside_lib_path(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-i")==0 or strcmp(argv[i],"--ignore")==0)
        {
            i++;
            Settings::ignore_prefix(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-d")==0 or strcmp(argv[i],"--dest-dir")==0)
        {
            i++;
            Settings::destFolder(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-of")==0 or strcmp(argv[i],"--overwrite-files")==0)
        {
            Settings::canOverwriteFiles(true);
            continue;
        }
        else if(strcmp(argv[i],"-od")==0 or strcmp(argv[i],"--overwrite-dir")==0)
        {
            Settings::canOverwriteDir(true);
            Settings::canCreateDir(true);
            continue;
        }
        else if(strcmp(argv[i],"-cd")==0 or strcmp(argv[i],"--create-dir")==0)
        {
            Settings::canCreateDir(true);
            continue;
        }
        else if(strcmp(argv[i],"-h")==0 or strcmp(argv[i],"--help")==0)
        {
            showHelp();
            exit(0);
        }
        else if(i>0)
        {
            // if we meet an unknown flag, abort
            // ignore first one cause it's usually the path to the executable
            std::cerr << "Unknown flag " << argv[i] << std::endl << std::endl;
            showHelp();
            exit(1);
        }
    }

    if(not Settings::bundleLibs() and Settings::fileToFixAmount()<1)
    {
        showHelp();
        exit(0);
    }

    std::cout << "* Collecting dependencies"; fflush(stdout);

    const int amount = Settings::fileToFixAmount();
    for(int n=0; n<amount; n++)
        collectDependencies(Settings::fileToFix(n));

    collectSubDependencies();
    doneWithDeps_go();

    return 0;
}
<commit_msg>Set version to git<commit_after>/*
The MIT License (MIT)

Copyright (c) 2014 Marianne Gagnon

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 <cstdlib>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <vector>
#include "Settings.h"

#include "Utils.h"
#include "DylibBundler.h"

/*
 TODO
 - what happens if a library is not remembered by full path but only name? (support improved, still not perfect)
 - could get mixed up if symlink and original are not in the same location (won't happen for UNIX prefixes like /usr/, but in random directories?)

 FIXME: why does it copy plugins i try to fix to the libs directory?

 */

const std::string VERSION = "git";

// FIXME - no memory management is done at all (anyway the program closes immediately so who cares?)

std::string installPath = "";

void showHelp()
{
    std::cout << "dylibbundler " << VERSION << std::endl;
    std::cout << "dylibbundler is a utility that helps bundle dynamic libraries inside mac OS X app bundles.\n" << std::endl;

    std::cout << "-x, --fix-file <file to fix (executable or app plug-in)>" << std::endl;
    std::cout << "-b, --bundle-deps" << std::endl;
    std::cout << "-d, --dest-dir <directory to send bundled libraries (relative to cwd)>" << std::endl;
    std::cout << "-p, --install-path <'inner' path of bundled libraries (usually relative to executable, by default '@executable_path/../libs/')>" << std::endl;
    std::cout << "-of, --overwrite-files (allow overwriting files in output directory)" << std::endl;
    std::cout << "-od, --overwrite-dir (totally overwrite output directory if it already exists. implies --create-dir)" << std::endl;
    std::cout << "-cd, --create-dir (creates output directory if necessary)" << std::endl;
    std::cout << "-i, --ignore <location to ignore> (will ignore libraries in this directory)" << std::endl;
    std::cout << "-h, --help" << std::endl;
}

int main (int argc, char * const argv[])
{

    // parse arguments
    for(int i=0; i<argc; i++)
    {
        if(strcmp(argv[i],"-x")==0 or strcmp(argv[i],"--fix-file")==0)
        {
            i++;
            Settings::addFileToFix(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-b")==0 or strcmp(argv[i],"--bundle-deps")==0)
        {
            Settings::bundleLibs(true);
            continue;
        }
        else if(strcmp(argv[i],"-p")==0 or strcmp(argv[i],"--install-path")==0)
        {
            i++;
            Settings::inside_lib_path(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-i")==0 or strcmp(argv[i],"--ignore")==0)
        {
            i++;
            Settings::ignore_prefix(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-d")==0 or strcmp(argv[i],"--dest-dir")==0)
        {
            i++;
            Settings::destFolder(argv[i]);
            continue;
        }
        else if(strcmp(argv[i],"-of")==0 or strcmp(argv[i],"--overwrite-files")==0)
        {
            Settings::canOverwriteFiles(true);
            continue;
        }
        else if(strcmp(argv[i],"-od")==0 or strcmp(argv[i],"--overwrite-dir")==0)
        {
            Settings::canOverwriteDir(true);
            Settings::canCreateDir(true);
            continue;
        }
        else if(strcmp(argv[i],"-cd")==0 or strcmp(argv[i],"--create-dir")==0)
        {
            Settings::canCreateDir(true);
            continue;
        }
        else if(strcmp(argv[i],"-h")==0 or strcmp(argv[i],"--help")==0)
        {
            showHelp();
            exit(0);
        }
        else if(i>0)
        {
            // if we meet an unknown flag, abort
            // ignore first one cause it's usually the path to the executable
            std::cerr << "Unknown flag " << argv[i] << std::endl << std::endl;
            showHelp();
            exit(1);
        }
    }

    if(not Settings::bundleLibs() and Settings::fileToFixAmount()<1)
    {
        showHelp();
        exit(0);
    }

    std::cout << "* Collecting dependencies"; fflush(stdout);

    const int amount = Settings::fileToFixAmount();
    for(int n=0; n<amount; n++)
        collectDependencies(Settings::fileToFix(n));

    collectSubDependencies();
    doneWithDeps_go();

    return 0;
}
<|endoftext|>


<commit_before>#include <limits>
#include <iostream>
#include <fstream>
#include <vector>

#include <algorithm>
#ifdef _WIN32

#ifndef EFU_SIMPLEREADHKLMKEY_H
#include "simple_read_hklm_key.h"
#endif

#ifndef EFU_WINERRORSTRING_H
#include "win_error_string.h"
#endif

#endif

#ifndef EFU_TARGET_H
#include "target.h"
#endif

#ifndef EFU_EFULAUNCHER_H
#include "efulauncher.h"
#endif

#ifndef EFU_CURLEASY_H
#include "curleasy.h"
#endif

bool confirm()
{
    char c;
    do
    {
        std::cin >> c;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        c = static_cast<char>(tolower(c));
    } while (c != 'y' && c != 'n');
    return c == 'y';
}

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;
    bool arg_errors = false;

#ifdef _WIN32
    const std::string nwn_bin("nwmain.exe");
#else
    const std::string nwn_bin("nwmain");
#endif
    std::string nwn_root_dir("./");

    std::string cmd_line(" +connect nwn.efupw.com:5121");

    const std::vector<std::string> args(argv + 1, argv + argc);

    std::cout << "Processing command line arguments." << std::endl;

#ifdef CPP11_FOR_EACH
    for (const auto arg : args)
#else
    std::for_each(args.cbegin(), args.cend(),
            [&cmd_line, &nwn_root_dir, &arg_errors](const std::string &arg)
#endif
    {
        if (arg.find("-dmpass") == 0)
        {
            auto cmd(split(arg, '='));
            if (cmd.size() == 2)
            {
                cmd_line.append(" -dmc +password " + cmd.at(1));
            }
            else
            {
                std::cout << "-dmpass specified but no value given. Use\n"\
                    "-dmpass=mypassword" <<std::endl;
                arg_errors = true;
            }
        }
        else if (arg.find("-nwn") == 0)
        {
            auto cmd(split(arg, '='));
            if (cmd.size() == 2)
            {
                nwn_root_dir = cmd.at(1);
            }
            else
            {
                std::cout << "-nwn specified but no value given. Use\n"\
                    "-nwn=\"path\\to\\NWN\\directory\\\"" <<std::endl;
                arg_errors = true;
            }
        }
        else
        {
            std::cout << "Ignoring unrecognized argument: " << arg
                << std::endl;
            arg_errors = true;
        }
    }
#ifndef CPP11_FOR_EACH
    );
#endif

    if (arg_errors)
    {
        std::cout << "Argument errors. Press a key to continue." << std::endl;
        std::cin.get();
    }

#ifdef _WIN32
    std::ifstream nwn(nwn_root_dir + nwn_bin, std::ios::binary);

    if (!nwn && nwn_root_dir != "./")
    {
        std::cout << nwn_root_dir << " not detected as NWN root directory."\
            "\nTrying current launcher directory...\n";
        nwn_root_dir = "./";
        nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);
    }

    if (!nwn)
    {
        std::cout << "Current launcher directory not detected as NWN root"\
            " directory.";
        nwn_root_dir = "C:/NeverwinterNights/NWN/";
        std::cout << "\nTrying " << nwn_root_dir << "... ";
        nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);

        if (!nwn)
        {
            std::cout << "not found.\nSearching registry... ";
            SimpleReadHKLMKey reg("SOFTWARE\\BioWare\\NWN\\Neverwinter",
                "Location");
            if (reg.good())
            {
                nwn_root_dir = reg.str();
                std::cout << "key found.";
                auto path_sep = nwn_root_dir.at(nwn_root_dir.size() - 1);
                if (path_sep != '/' && path_sep != '\\')
                {
                    nwn_root_dir.append("/");
                }
                std::cout << "\nTrying " << nwn_root_dir << "... ";
                nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);
                if (!nwn)
                {
                    std::cout << "not found.";
                }
            }
            else
            {
                std::cout << "no key found.";
            }
        }
    }

    if (nwn)
    {
        std::cout << nwn_root_dir + nwn_bin << " found." << std::endl;
    }
    else
    {
        std::cout << "\n\nNWN root directory not found, known"\
            " options exhausted."\
            "\nThe launcher will not be able to download files to the correct"\
            " location or"\
            "\nlaunch Neverwinter Nights, however, the launcher"\
            " may still download files to"\
            "\nthe current directory and you can"\
            " move them manually afterwards. To avoid this"\
            "\nin the future"\
            " either move the launcher to the NWN root directory containing"\
            "\nnwmain.exe or pass the -nwn=C:/NeverwinterNights/NWN flag to"\
            " the launcher"\
            "\nexecutable, substituting the correct path, quoted"\
            " if it contains spaces:"\
            "\n\t-nwn=\"X:/Games/Neverwinter Nights/NWN\"."\
            "\n/ and \\ are interchangeable."\
            "\nWould you like to download files anyway (y/n)?" << std::endl;
        if (!confirm())
        {
            std::cout << "Exiting EfU Launcher. Goodbye!" << std::endl;
            return 0;
        }
        nwn_root_dir = "./";
    }
#endif

    EfuLauncher l(nwn_root_dir,
            "https://raw.github.com/commonquail/efulauncher/"\
            "master/versioncheck");

    if (l.has_update())
    {
        std::cout << "A new version of the launcher is available. Please"\
            " download it at https://github.com/commonquail/efulauncher/"\
            "releases. Press any key to exit." << std::endl;
        std::cin.get();
        return 0;
        /*
        std::cout << "A new version of the launcher is available."\
            " Would you like to download it (y/n)?" << std::endl;
        bool download(confirm());
        if (!download)
        {
            std::cout << "It is strongly recommended to always use"\
                " the latest launcher. Would you like to download it (y/n)?"
                << std::endl;
            download = confirm();
        }
        if (download)
        {
            // Download.
            std::cout << "Downloading new launcher..." << std::endl;
            if (l.get_update())
            {
                std::cout << "Done. Please extract and run the new launcher." << std::endl;
            }
            return 0;
        }
        */
    }

    try
    {
        l.stat_targets();
        std::cout << "Done." << std::endl;
    }
    catch (std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }

#ifdef _WIN32
    if (nwn)
    {
        std::cout << "Launching " << nwn_root_dir + nwn_bin << "..." << std::endl;

        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ::ZeroMemory(&pi, sizeof(pi));
        ::ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);

        auto nwn_path(nwn_root_dir + nwn_bin);
        cmd_line = nwn_path + cmd_line;

        BOOL success = ::CreateProcess(
            const_cast<char *>(nwn_path.c_str()),
            const_cast<char *>(cmd_line.c_str()),
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            const_cast<char *>(nwn_root_dir.c_str()),           // Starting directory
            &si, &pi);
        if (success)
        {
            ::CloseHandle(pi.hProcess);
            ::CloseHandle(pi.hThread);
        }
        else
        {
            WinErrorString we;
            std::cout << we.str() << std::endl;
        }
    }
#endif

    return 0;
}
<commit_msg>Fix whitespace.<commit_after>#include <limits>
#include <iostream>
#include <fstream>
#include <vector>

#include <algorithm>
#ifdef _WIN32

#ifndef EFU_SIMPLEREADHKLMKEY_H
#include "simple_read_hklm_key.h"
#endif

#ifndef EFU_WINERRORSTRING_H
#include "win_error_string.h"
#endif

#endif

#ifndef EFU_TARGET_H
#include "target.h"
#endif

#ifndef EFU_EFULAUNCHER_H
#include "efulauncher.h"
#endif

#ifndef EFU_CURLEASY_H
#include "curleasy.h"
#endif

bool confirm()
{
    char c;
    do
    {
        std::cin >> c;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        c = static_cast<char>(tolower(c));
    } while (c != 'y' && c != 'n');
    return c == 'y';
}

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;
    bool arg_errors = false;

#ifdef _WIN32
    const std::string nwn_bin("nwmain.exe");
#else
    const std::string nwn_bin("nwmain");
#endif
    std::string nwn_root_dir("./");

    std::string cmd_line(" +connect nwn.efupw.com:5121");

    const std::vector<std::string> args(argv + 1, argv + argc);

    std::cout << "Processing command line arguments." << std::endl;

#ifdef CPP11_FOR_EACH
    for (const auto arg : args)
#else
    std::for_each(args.cbegin(), args.cend(),
            [&cmd_line, &nwn_root_dir, &arg_errors]
            (const std::string &arg)
#endif
    {
        if (arg.find("-dmpass") == 0)
        {
            auto cmd(split(arg, '='));
            if (cmd.size() == 2)
            {
                cmd_line.append(" -dmc +password " + cmd.at(1));
            }
            else
            {
                std::cout << "-dmpass specified but no value given. Use\n"\
                    "-dmpass=mypassword" <<std::endl;
                arg_errors = true;
            }
        }
        else if (arg.find("-nwn") == 0)
        {
            auto cmd(split(arg, '='));
            if (cmd.size() == 2)
            {
                nwn_root_dir = cmd.at(1);
            }
            else
            {
                std::cout << "-nwn specified but no value given. Use\n"\
                    "-nwn=\"path\\to\\NWN\\directory\\\"" <<std::endl;
                arg_errors = true;
            }
        }
        else
        {
            std::cout << "Ignoring unrecognized argument: " << arg
                << std::endl;
            arg_errors = true;
        }
    }
#ifndef CPP11_FOR_EACH
    );
#endif

    if (arg_errors)
    {
        std::cout << "Argument errors. Press a key to continue." << std::endl;
        std::cin.get();
    }

#ifdef _WIN32
    std::ifstream nwn(nwn_root_dir + nwn_bin, std::ios::binary);

    if (!nwn && nwn_root_dir != "./")
    {
        std::cout << nwn_root_dir << " not detected as NWN root directory."\
            "\nTrying current launcher directory...\n";
        nwn_root_dir = "./";
        nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);
    }

    if (!nwn)
    {
        std::cout << "Current launcher directory not detected as NWN root"\
            " directory.";
        nwn_root_dir = "C:/NeverwinterNights/NWN/";
        std::cout << "\nTrying " << nwn_root_dir << "... ";
        nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);

        if (!nwn)
        {
            std::cout << "not found.\nSearching registry... ";
            SimpleReadHKLMKey reg("SOFTWARE\\BioWare\\NWN\\Neverwinter",
                "Location");
            if (reg.good())
            {
                nwn_root_dir = reg.str();
                std::cout << "key found.";
                auto path_sep = nwn_root_dir.at(nwn_root_dir.size() - 1);
                if (path_sep != '/' && path_sep != '\\')
                {
                    nwn_root_dir.append("/");
                }
                std::cout << "\nTrying " << nwn_root_dir << "... ";
                nwn.open(nwn_root_dir + nwn_bin, std::ios::binary);
                if (!nwn)
                {
                    std::cout << "not found.";
                }
            }
            else
            {
                std::cout << "no key found.";
            }
        }
    }

    if (nwn)
    {
        std::cout << nwn_root_dir + nwn_bin << " found." << std::endl;
    }
    else
    {
        std::cout << "\n\nNWN root directory not found, known"\
            " options exhausted."\
            "\nThe launcher will not be able to download files to the correct"\
            " location or"\
            "\nlaunch Neverwinter Nights, however, the launcher"\
            " may still download files to"\
            "\nthe current directory and you can"\
            " move them manually afterwards. To avoid this"\
            "\nin the future"\
            " either move the launcher to the NWN root directory containing"\
            "\nnwmain.exe or pass the -nwn=C:/NeverwinterNights/NWN flag to"\
            " the launcher"\
            "\nexecutable, substituting the correct path, quoted"\
            " if it contains spaces:"\
            "\n\t-nwn=\"X:/Games/Neverwinter Nights/NWN\"."\
            "\n/ and \\ are interchangeable."\
            "\nWould you like to download files anyway (y/n)?" << std::endl;
        if (!confirm())
        {
            std::cout << "Exiting EfU Launcher. Goodbye!" << std::endl;
            return 0;
        }
        nwn_root_dir = "./";
    }
#endif

    EfuLauncher l(nwn_root_dir,
            "https://raw.github.com/commonquail/efulauncher/"\
            "master/versioncheck");

    if (l.has_update())
    {
        std::cout << "A new version of the launcher is available. Please"\
            " download it at https://github.com/commonquail/efulauncher/"\
            "releases. Press any key to exit." << std::endl;
        std::cin.get();
        return 0;
        /*
        std::cout << "A new version of the launcher is available."\
            " Would you like to download it (y/n)?" << std::endl;
        bool download(confirm());
        if (!download)
        {
            std::cout << "It is strongly recommended to always use"\
                " the latest launcher. Would you like to download it (y/n)?"
                << std::endl;
            download = confirm();
        }
        if (download)
        {
            // Download.
            std::cout << "Downloading new launcher..." << std::endl;
            if (l.get_update())
            {
                std::cout << "Done. Please extract and run the new launcher." << std::endl;
            }
            return 0;
        }
        */
    }

    try
    {
        l.stat_targets();
        std::cout << "Done." << std::endl;
    }
    catch (std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }

#ifdef _WIN32
    if (nwn)
    {
        std::cout << "Launching " << nwn_root_dir + nwn_bin << "..." << std::endl;

        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ::ZeroMemory(&pi, sizeof(pi));
        ::ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);

        auto nwn_path(nwn_root_dir + nwn_bin);
        cmd_line = nwn_path + cmd_line;

        BOOL success = ::CreateProcess(
            const_cast<char *>(nwn_path.c_str()),
            const_cast<char *>(cmd_line.c_str()),
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            const_cast<char *>(nwn_root_dir.c_str()),           // Starting directory
            &si, &pi);
        if (success)
        {
            ::CloseHandle(pi.hProcess);
            ::CloseHandle(pi.hThread);
        }
        else
        {
            WinErrorString we;
            std::cout << we.str() << std::endl;
        }
    }
#endif

    return 0;
}
<|endoftext|>


<commit_before>/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
  Example uses a static library to show off generate_arduino_library().

  This example code is in the public domain.
 */
#if ARDUINO >= 100
    #include "Arduino.h"
#else
    #include "WProgram.h"
#endif

#include "dimmer.h"

byte ledPin = 13;
byte zcPin =  2;
byte zcOutPin = 8;

void pciSetup(byte pin)
{
  //*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  //PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  //PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}

#include <stdarg.h>
void _printf(char *fmt, ... ){
  char buf[128]; // resulting string limited to 128 chars
  va_list args;
  va_start (args, fmt );
  vsnprintf(buf, 128, fmt, args);
  va_end (args);
  Serial.print(buf);
}

// we need fundamental FILE definitions and printf declarations
#include <stdio.h>

// create a FILE structure to reference our UART output function
static FILE uartout = {0} ;

// create a output function
// This works because Serial.write, although of
// type virtual, already exists.
static int uart_putchar (char c, FILE *stream)
{
  Serial.write(c) ;
  return 0 ;
}

/** SSR library **/

void setup() {

 // Start the UART
 Serial.begin(115200) ;
  Serial.setTimeout(-1);

 // fill in the UART file descriptor with pointer to writer.
  fdev_setup_stream (&uartout, uart_putchar, NULL,
  _FDEV_SETUP_WRITE);

  // The uart is the standard output device STDOUT.
  stdout = &uartout ;

  printf("setup\n\r");
    //blink_setup(); // Setup for blinking
  pinMode(ledPin, OUTPUT);
  pinMode(zcPin, INPUT_PULLUP);
  //pinMode(zcOutPin, OUTPUT);
  //pciSetup(zcPin);

  dimmer_init();

  dimmer_set(PHASE_LEADING_EDGE, CHANNEL1, 144);
  dimmer_set(PHASE_LEADING_EDGE, CHANNEL2, 200);
  dimmer_set(FULL_WAVE_BURST, CHANNEL3, 128);
  dimmer_set(HALF_WAVE_BURST, CHANNEL4, 64);
}

char uart_getchar(void) {
  loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
  return UDR0;
}

void _read_line(char *buffer, uint8_t len) {
  do {
    *buffer = uart_getchar();
    if (*buffer == 13) {
      printf("this is it\n\r");
      *buffer = '\0';
      return;
    }
    buffer++;
  } while (--len > 0);
  return;
}

// LINE: [CHANNEL_NR] [ON/OFF] [VALUE]
//             1         1        3

#define LINE_LENGTH 8

void loop() {
  char buffer[8];
  printf("start\n\r");

  Serial.readBytes(buffer, 7);
  buffer[7] = '\0';

  //_read_line(buffer, LINE_LENGTH);

  printf("read: %s\n\r", buffer);

  t_channel_nr channel_nr = buffer[0] - '0';
  t_action action = buffer[2] - '0';
  uint8_t value = atoi(&buffer[4]);

  printf("channel: %u action: %u value: %u\n\r", channel_nr, action, value);
}
<commit_msg>add comments for driver.<commit_after>/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
  Example uses a static library to show off generate_arduino_library().

  This example code is in the public domain.
 */
#if ARDUINO >= 100
    #include "Arduino.h"
#else
    #include "WProgram.h"
#endif

#include "dimmer.h"

byte ledPin = 13;
byte zcPin =  2;
byte zcOutPin = 8;

void pciSetup(byte pin)
{
  //*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  //PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  //PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}

#include <stdarg.h>
void _printf(char *fmt, ... ){
  char buf[128]; // resulting string limited to 128 chars
  va_list args;
  va_start (args, fmt );
  vsnprintf(buf, 128, fmt, args);
  va_end (args);
  Serial.print(buf);
}

// we need fundamental FILE definitions and printf declarations
#include <stdio.h>

// create a FILE structure to reference our UART output function
static FILE uartout = {0} ;

// create a output function
// This works because Serial.write, although of
// type virtual, already exists.
static int uart_putchar (char c, FILE *stream)
{
  Serial.write(c) ;
  return 0 ;
}

/** SSR library **/

void setup() {

 // Start the UART
 Serial.begin(115200) ;
  Serial.setTimeout(-1);

 // fill in the UART file descriptor with pointer to writer.
  fdev_setup_stream (&uartout, uart_putchar, NULL,
  _FDEV_SETUP_WRITE);

  // The uart is the standard output device STDOUT.
  stdout = &uartout ;

  printf("setup\n\r");
    //blink_setup(); // Setup for blinking
  pinMode(ledPin, OUTPUT);
  pinMode(zcPin, INPUT_PULLUP);
  //pinMode(zcOutPin, OUTPUT);
  //pciSetup(zcPin);

  // thats it!
  // FROM HERE
  dimmer_init();
  dimmer_set(PHASE_TRAILING_EDGE, CHANNEL1, 1);
  // TO HERE

  dimmer_set(PHASE_LEADING_EDGE, CHANNEL2, 200);
  dimmer_set(FULL_WAVE_BURST, CHANNEL3, 128);
  dimmer_set(HALF_WAVE_BURST, CHANNEL4, 64);
}

char uart_getchar(void) {
  loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
  return UDR0;
}

void _read_line(char *buffer, uint8_t len) {
  do {
    *buffer = uart_getchar();
    if (*buffer == 13) {
      printf("this is it\n\r");
      *buffer = '\0';
      return;
    }
    buffer++;
  } while (--len > 0);
  return;
}

// LINE: [CHANNEL_NR] [ON/OFF] [VALUE]
//             1         1        3

#define LINE_LENGTH 8

void loop() {
  char buffer[8];
  printf("start\n\r");

  Serial.readBytes(buffer, 7);
  buffer[7] = '\0';

  //_read_line(buffer, LINE_LENGTH);

  printf("read: %s\n\r", buffer);

  t_channel_nr channel_nr = buffer[0] - '0';
  t_action action = buffer[2] - '0';
  uint8_t value = atoi(&buffer[4]);

  printf("channel: %u action: %u value: %u\n\r", channel_nr, action, value);
}
<|endoftext|>


<commit_before>#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include <lua/lua.hpp>

#include "terrian_config.hpp"
#include "matrixstacksingleton.hpp"
#include "polygon.hpp"
#include "logiccontext.hpp"
#include "visualcontext.hpp"
#include "heightmap.hpp"
#include "line.hpp"
#include "triangle.hpp"
#include "luae/script.hpp"
#include "luae/scriptmanager.hpp"
#include "luae/scriptheightmap.hpp"
#include "luae/scriptriangle.hpp"

//For stringifying preprocessor values
#define xstr(s) str(s)
     #define str(s) #s
#define concat(first, second) first second

static struct LogicContext logicContext;
static glm::vec3 ray_world;

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
	glm::vec3 up = glm::vec3(glm::vec4(0.0, 1.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 down = glm::vec3(glm::vec4(0.0, -1.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 left = glm::vec3(glm::vec4(-1.0, 0.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 right = glm::vec3(glm::vec4(1.0, 0.0, 0.0, 1.0) * logicContext.modelview);
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
	if (key == GLFW_KEY_SPACE && action == GLFW_PRESS){
		printf("Triangle 1 Model Matrix: %s\n", glm::to_string(logicContext.modelview).c_str());
	}
	if(key == GLFW_KEY_R && action == GLFW_RELEASE){
		logicContext.modelview = glm::mat4();

	}
	if(key == GLFW_KEY_LEFT && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, up);
	}
	else if(key == GLFW_KEY_RIGHT && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, down);
	}
	else if(key == GLFW_KEY_LEFT && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, left * 0.1f);
	}
	else if(key == GLFW_KEY_RIGHT && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, right * 0.1f);
	}
	if(key == GLFW_KEY_UP && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, up * 0.1f);
	}
	else if(key == GLFW_KEY_DOWN && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, down * 0.1f);
	}
	else if(key == GLFW_KEY_UP && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, left);
	}
	else if(key == GLFW_KEY_DOWN && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, right);

	}
}
static void calcWorldPickRay(GLFWwindow *window){
	//Build ray from mouse
	double mouseX;
	double mouseY;

	glfwGetCursorPos(window, &mouseX, &mouseY);

	glm::vec4 ray_clip = glm::vec4((2.0f * mouseX) / VisualContext::width - 1.0f, 1.0f - (2.0f * mouseY) / VisualContext::height, -1.0f, 1.0f);

	glm::vec4 ray_eye = glm::inverse(VisualContext::projection_matrix) * ray_clip;
	ray_eye.z = -1.0f;
	ray_eye.w = 1.0f;

	ray_world = glm::vec3(glm::inverse(logicContext.modelview) * ray_eye);
	//		ray_world = glm::normalize(ray_world);

}

int main(void) {

	GLFWwindow *window = VisualContext::CreateGLFWWindow(key_callback);
	GLuint shader_program = VisualContext::make_shader_program(concat(xstr(SHADERS_DIR), "/shader.vert"), concat(xstr(SHADERS_DIR), "/shader.frag"));
	glUseProgram(shader_program);
	GLuint vertShaderLocation = glGetAttribLocation(shader_program, "vert");
	GLuint uloc_project   = glGetUniformLocation(shader_program, "project");
	GLuint uloc_modelview = glGetUniformLocation(shader_program, "modelview");

	/* Compute the projection matrix */
	VisualContext::projection_matrix = glm::perspective(VisualContext::view_angle, VisualContext::aspect_ratio, VisualContext::z_near, VisualContext::z_far);
	logicContext.uloc_modelview = uloc_modelview;

	/* Set the camera position  */
	logicContext.modelview = glm::translate(logicContext.modelview, glm::vec3(0.0f, 0.0f, -20.0f));
	logicContext.modelview = glm::rotate(logicContext.modelview, 0.0f, glm::vec3(-1.0f, 0.0f, 0.0f));

	/*
	HeightmapSettings heightmapSettings;

	heightmapSettings.widthDensity = 10;
	heightmapSettings.origin = glm::vec3(0.0f, 0.0f, 0.0f);

	Heightmap heightmap(heightmapSettings);
	heightmap.build(heightmapSettings);
	heightmap.setShaderLocations(vertShaderLocation);
	heightmap.rotate(glm::vec3(1,0,0), -1.57f);
	*/

	glViewport(0,0,VisualContext::width, VisualContext::height);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	Line worldLine;
	worldLine.buildStatic();
	worldLine.setShaderLocations(vertShaderLocation);

	lua_State* l = Luae::ScriptManager::instance()->getState();
	Luae::ScriptTriangle::AddToLib();
	Luae::Script* script = Luae::Script::Load("triangle_drawing.lua");
	script->call("init");
	lua_getglobal(l, "triangle");
	Triangle* triangle = *(Triangle**)lua_touserdata(l,-1);

	glEnable(GL_MULTISAMPLE);

	while (!glfwWindowShouldClose(window)) {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glPolygonMode(GL_FRONT, GL_FILL);
		glUniformMatrix4fv(uloc_project, 1, GL_FALSE, glm::value_ptr(VisualContext::projection_matrix));

		calcWorldPickRay(window);
		glm::vec3 rayWordEndPoint = glm::vec3(glm::vec4(0.0f, 0.0f, -100.0f, 1.0f) * logicContext.modelview);

		worldLine.setStartEnd(ray_world, rayWordEndPoint);
		worldLine.update(&logicContext);
		worldLine.draw(&logicContext);

		triangle->update(&logicContext);
		triangle->draw(&logicContext);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);

	glfwTerminate();
	return 0;
}
<commit_msg>Now using rendering queue based on IPolygon interface<commit_after>#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include <lua/lua.hpp>
#include <vector>
#include <fmt/format.h>

#include "terrian_config.hpp"
#include "matrixstacksingleton.hpp"
#include "IPolygon.hpp"
#include "polygon.hpp"
#include "logiccontext.hpp"
#include "visualcontext.hpp"
#include "heightmap.hpp"
#include "line.hpp"
#include "triangle.hpp"
#include "addtodrawqueue.hpp"
#include "luae/script.hpp"
#include "luae/scriptmanager.hpp"
#include "luae/scriptheightmap.hpp"
#include "luae/scriptriangle.hpp"

//For stringifying preprocessor values
#define xstr(s) str(s)
     #define str(s) #s
#define concat(first, second) first second

static struct LogicContext logicContext;
static glm::vec3 ray_world;

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
	glm::vec3 up = glm::vec3(glm::vec4(0.0, 1.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 down = glm::vec3(glm::vec4(0.0, -1.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 left = glm::vec3(glm::vec4(-1.0, 0.0, 0.0, 1.0) * logicContext.modelview);
	glm::vec3 right = glm::vec3(glm::vec4(1.0, 0.0, 0.0, 1.0) * logicContext.modelview);
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
	if (key == GLFW_KEY_SPACE && action == GLFW_PRESS){
		printf("Triangle 1 Model Matrix: %s\n", glm::to_string(logicContext.modelview).c_str());
	}
	if(key == GLFW_KEY_R && action == GLFW_RELEASE){
		logicContext.modelview = glm::mat4();

	}
	if(key == GLFW_KEY_LEFT && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, up);
	}
	else if(key == GLFW_KEY_RIGHT && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, down);
	}
	else if(key == GLFW_KEY_LEFT && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, left * 0.1f);
	}
	else if(key == GLFW_KEY_RIGHT && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, right * 0.1f);
	}
	if(key == GLFW_KEY_UP && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, up * 0.1f);
	}
	else if(key == GLFW_KEY_DOWN && mods == 0){
		logicContext.modelview = glm::translate(logicContext.modelview, down * 0.1f);
	}
	else if(key == GLFW_KEY_UP && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, left);
	}
	else if(key == GLFW_KEY_DOWN && mods == GLFW_MOD_SHIFT){
		logicContext.modelview = glm::rotate(logicContext.modelview, 0.1f, right);

	}
}
static void calcWorldPickRay(GLFWwindow *window){
	//Build ray from mouse
	double mouseX;
	double mouseY;

	glfwGetCursorPos(window, &mouseX, &mouseY);

	glm::vec4 ray_clip = glm::vec4((2.0f * mouseX) / VisualContext::width - 1.0f, 1.0f - (2.0f * mouseY) / VisualContext::height, -1.0f, 1.0f);

	glm::vec4 ray_eye = glm::inverse(VisualContext::projection_matrix) * ray_clip;
	ray_eye.z = -1.0f;
	ray_eye.w = 1.0f;

	ray_world = glm::vec3(glm::inverse(logicContext.modelview) * ray_eye);
	//		ray_world = glm::normalize(ray_world);

}

int main(void) {

	GLFWwindow *window = VisualContext::CreateGLFWWindow(key_callback);
	GLuint shader_program = VisualContext::make_shader_program(concat(xstr(SHADERS_DIR), "/shader.vert"), concat(xstr(SHADERS_DIR), "/shader.frag"));
	glUseProgram(shader_program);
	GLuint vertShaderLocation = glGetAttribLocation(shader_program, "vert");
	GLuint uloc_project   = glGetUniformLocation(shader_program, "project");
	GLuint uloc_modelview = glGetUniformLocation(shader_program, "modelview");
	std::vector<IPolygon*> drawQueue;
	AddToDrawQueueCommand::SetQueue(&drawQueue);

	/* Compute the projection matrix */
	VisualContext::projection_matrix = glm::perspective(VisualContext::view_angle, VisualContext::aspect_ratio, VisualContext::z_near, VisualContext::z_far);
	logicContext.uloc_modelview = uloc_modelview;

	/* Set the camera position  */
	logicContext.modelview = glm::translate(logicContext.modelview, glm::vec3(0.0f, 0.0f, -20.0f));
	logicContext.modelview = glm::rotate(logicContext.modelview, 0.0f, glm::vec3(-1.0f, 0.0f, 0.0f));

	/*
	HeightmapSettings heightmapSettings;

	heightmapSettings.widthDensity = 10;
	heightmapSettings.origin = glm::vec3(0.0f, 0.0f, 0.0f);

	Heightmap heightmap(heightmapSettings);
	heightmap.build(heightmapSettings);
	heightmap.setShaderLocations(vertShaderLocation);
	heightmap.rotate(glm::vec3(1,0,0), -1.57f);
	*/

	glViewport(0,0,VisualContext::width, VisualContext::height);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	Line worldLine;
	worldLine.buildStatic();
	worldLine.setShaderLocations(vertShaderLocation);

	lua_State* l = Luae::ScriptManager::instance()->getState();
	Luae::ScriptTriangle::AddToLib();
	Luae::Script* script = Luae::Script::Load("triangle_drawing.lua");
	script->call("init");
	//lua_getglobal(l, "triangle");
	//Triangle* triangle = *(Triangle**)lua_touserdata(l,-1);
	//drawQueue.push_back(triangle);
//	AddToDrawQueueCommand addTriangle(triangle);
//	addTriangle.execute();

	glEnable(GL_MULTISAMPLE);

	while (!glfwWindowShouldClose(window)) {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glPolygonMode(GL_FRONT, GL_FILL);
		glUniformMatrix4fv(uloc_project, 1, GL_FALSE, glm::value_ptr(VisualContext::projection_matrix));

		calcWorldPickRay(window);
		glm::vec3 rayWordEndPoint = glm::vec3(glm::vec4(0.0f, 0.0f, -100.0f, 1.0f) * logicContext.modelview);

		worldLine.setStartEnd(ray_world, rayWordEndPoint);
		worldLine.update(&logicContext);
		worldLine.draw(&logicContext);

		//triangle->update(&logicContext);
		//triangle->draw(&logicContext);

		int i = 0;
		for(std::vector<IPolygon*>::iterator drawHost = drawQueue.begin();
				drawHost != drawQueue.end();
				drawHost++){
			(*drawHost)->update(&logicContext);
			(*drawHost)->draw(&logicContext);
			i++;
		//	fmt::printf("Draw call #: %d\n", i);
		}

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);

	glfwTerminate();
	return 0;
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------------------------------------
//
/// @PROJECT		gtest-gui
/// @BRIEF		main file for gtest-gui
/// @DETAILS
//
//--------------------------------------------------------------------------------------------------
//
// The MIT License (MIT)
//
// 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.
//
//--------------------------------------------------------------------------------------------------
//
// ATTRIBUTION:
// Parts of this work have been adapted from:
//
//--------------------------------------------------------------------------------------------------
//
// Copyright (c) 2016 Nic Holthaus
//
//--------------------------------------------------------------------------------------------------

//------------------------------
//	INCLUDE
//------------------------------

// Qt
#include <QApplication>
#include <QtGlobal>

// gtest-gui
#include "appinfo.h"
#include "mainwindow.h"

int main(int argc, char *argv[])
{
	Q_INIT_RESOURCE(resources);

// Enable high-DPI scaling with Qt 5.6+
#if QT_VERSION >= 050600
	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

	QApplication app(argc, argv);
	app.setOrganizationName(APPINFO::organization);
	app.setOrganizationDomain(APPINFO::oranizationDomain);
	app.setApplicationName(APPINFO::name);
	app.setApplicationVersion(APPINFO::version);
	MainWindow mainWin;
	mainWin.show();
	return app.exec();
}<commit_msg>another attempt at QT version check.<commit_after>//--------------------------------------------------------------------------------------------------
//
/// @PROJECT		gtest-gui
/// @BRIEF		main file for gtest-gui
/// @DETAILS
//
//--------------------------------------------------------------------------------------------------
//
// The MIT License (MIT)
//
// 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.
//
//--------------------------------------------------------------------------------------------------
//
// ATTRIBUTION:
// Parts of this work have been adapted from:
//
//--------------------------------------------------------------------------------------------------
//
// Copyright (c) 2016 Nic Holthaus
//
//--------------------------------------------------------------------------------------------------

//------------------------------
//	INCLUDE
//------------------------------

// Qt
#include <QApplication>
#include <QDebug>
#include <QtGlobal>

// gtest-gui
#include "appinfo.h"
#include "mainwindow.h"

int main(int argc, char *argv[])
{
	Q_INIT_RESOURCE(resources);

// Enable high-DPI scaling with Qt 5.6+
#if (QT_VERSION >= QT_VERSION_CHECK(5,6,0))
	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

	QApplication app(argc, argv);
	app.setOrganizationName(APPINFO::organization);
	app.setOrganizationDomain(APPINFO::oranizationDomain);
	app.setApplicationName(APPINFO::name);
	app.setApplicationVersion(APPINFO::version);
	MainWindow mainWin;
	mainWin.show();
	return app.exec();
}<|endoftext|>


<commit_before>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {

    try {
        Inotify notify;

        InotifyWatch watch(file, IN_ALL_EVENTS);
        notify.Add(watch);
        for (;;) {
            std::cout << "Child: Watching again" << std::endl;
            notify.WaitForEvents();

            size_t count = notify.GetEventCount();
            while (count > 0) {
                InotifyEvent event;
                bool got_event = notify.GetEvent(&event);

                if (got_event) {
                    std::string mask_str;
                    event.DumpTypes(mask_str);

                    std::string filename = event.GetName();
                    std::cout << "event mask: \"" << mask_str << "\", ";
                    std::cout << "filename: \"" << filename << "\"" << std::endl;
                    *fragHasChanged = true;
                }

                count--;
            }
        }
    } catch (InotifyException &e) {
        std::cerr << "Inotify exception occured: " << e.GetMessage() << std::endl;
    } catch (std::exception &e) {
        std::cerr << "STL exception occured: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown exception occured" << std::endl;
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
            std::cout << "Watch thread shutdown" << std::endl;
        }
        break;

        default: // parent
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<commit_msg>debug<commit_after>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {

    try {
        Inotify notify;

        InotifyWatch watch(file, IN_MODIFY);
        notify.Add(watch);
        for (;;) {
            std::cout << "Child: Watching again" << std::endl;
            notify.WaitForEvents();

            size_t count = notify.GetEventCount();
            while (count > 0) {
                InotifyEvent event;
                bool got_event = notify.GetEvent(&event);

                if (got_event) {
                    std::string mask_str;
                    event.DumpTypes(mask_str);

                    std::string filename = event.GetName();
                    std::cout << "event mask: \"" << mask_str << "\", ";
                    std::cout << "filename: \"" << filename << "\"" << std::endl;
                    *fragHasChanged = true;
                }

                count--;
            }
        }
    } catch (InotifyException &e) {
        std::cerr << "Inotify exception occured: " << e.GetMessage() << std::endl;
    } catch (std::exception &e) {
        std::cerr << "STL exception occured: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown exception occured" << std::endl;
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
            std::cout << "Watch thread shutdown" << std::endl;
        }
        break;

        default: // parent
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<|endoftext|>