<commit_before>/*
 *  DriftingGratingStimulus.cpp
 *  MWorksCore
 *
 *  Created by bkennedy on 8/26/08.
 *  Copyright 2008 MIT. All rights reserved.
 *
 */

#include "DriftingGratingStimulus.h"

BEGIN_NAMESPACE_MW

const std::string DriftingGratingStimulus::DIRECTION("direction");
const std::string DriftingGratingStimulus::STARTING_PHASE("starting_phase");
const std::string DriftingGratingStimulus::FREQUENCY("spatial_frequency");
const std::string DriftingGratingStimulus::SPEED("speed");
const std::string DriftingGratingStimulus::GRATING_TYPE("grating_type");
const std::string DriftingGratingStimulus::MASK("mask");
const std::string DriftingGratingStimulus::INVERTED("inverted");
const std::string DriftingGratingStimulus::STD_DEV("std_dev");
const std::string DriftingGratingStimulus::MEAN("mean");

void DriftingGratingStimulus::describeComponent(ComponentInfo &info) {
    DriftingGratingStimulusBase::describeComponent(info);

    info.setSignature("stimulus/drifting_grating");

    info.addParameter(DIRECTION, "0.0");
    info.addParameter(STARTING_PHASE, "0.0");
    info.addParameter(FREQUENCY);
    info.addParameter(SPEED);
    info.addParameter(GRATING_TYPE);
    info.addParameter(MASK);
    info.addParameter(INVERTED, "NO");
    info.addParameter(STD_DEV, "1.0");
    info.addParameter(MEAN, "0.0");

    // This is no longer used but may be present in old experiments
    info.addIgnoredParameter("grating_sample_rate");
}

auto DriftingGratingStimulus::gratingTypeFromName(const std::string &name) -> GratingType {
    if (name == "sinusoid") {
        return GratingType::sinusoid;
    } else if (name == "square") {
        return GratingType::square;
    } else if (name == "triangle") {
        return GratingType::triangle;
    } else if (name == "sawtooth") {
        return GratingType::sawtooth;
    }
    throw SimpleException("Invalid grating type", name);
};

auto DriftingGratingStimulus::maskTypeFromName(const std::string &name) -> MaskType {
    if (name == "rectangle") {
        return MaskType::rectangle;
    } else if (name == "ellipse") {
        return MaskType::ellipse;
    } else if (name == "gaussian") {
        return MaskType::gaussian;
    }
    throw SimpleException("Invalid mask type", name);
};

DriftingGratingStimulus::DriftingGratingStimulus(const ParameterValueMap &parameters) :
    DriftingGratingStimulusBase(parameters),
    direction_in_degrees(registerVariable(parameters[DIRECTION])),
    starting_phase(registerVariable(parameters[STARTING_PHASE])),
    spatial_frequency(registerVariable(parameters[FREQUENCY])),
    speed(registerVariable(parameters[SPEED])),
    gratingTypeName(parameters[GRATING_TYPE].str()),
    gratingType(gratingTypeFromName(gratingTypeName)),
    maskTypeName(parameters[MASK].str()),
    maskType(maskTypeFromName(maskTypeName)),
    inverted(registerVariable(parameters[INVERTED])),
    std_dev(registerVariable(parameters[STD_DEV])),
    mean(registerVariable(parameters[MEAN]))
{ }

Datum DriftingGratingStimulus::getCurrentAnnounceDrawData() {
    boost::mutex::scoped_lock locker(stim_lock);

    Datum announceData = DriftingGratingStimulusBase::getCurrentAnnounceDrawData();

    announceData.addElement(STIM_TYPE, "drifting_grating");
    announceData.addElement(DIRECTION, last_direction_in_degrees);
    announceData.addElement(STARTING_PHASE, last_starting_phase);
    announceData.addElement("current_phase", last_phase);
    announceData.addElement(FREQUENCY, last_spatial_frequency);
    announceData.addElement(SPEED, last_speed);
    announceData.addElement(GRATING_TYPE, gratingTypeName);
    announceData.addElement(MASK, maskTypeName);

    if (gratingType == GratingType::sawtooth) {
        announceData.addElement(INVERTED, last_inverted);
    }

    if (maskType == MaskType::gaussian) {
        announceData.addElement(STD_DEV, last_std_dev);
        announceData.addElement(MEAN, last_mean);
    }

    return announceData;
}

gl::Shader DriftingGratingStimulus::getVertexShader() const {
    static const std::string source
    (R"(
     uniform mat4 mvpMatrix;

     in vec4 vertexPosition;
     in float gratingCoord;
     in vec2 maskCoords;

     out float gratingVaryingCoord;
     out vec2 maskVaryingCoords;

     void main() {
         gl_Position = mvpMatrix * vertexPosition;
         gratingVaryingCoord = gratingCoord;
         maskVaryingCoords = maskCoords;
     }
     )");

    return gl::createShader(GL_VERTEX_SHADER, source);
}

gl::Shader DriftingGratingStimulus::getFragmentShader() const {
    static const std::string source
    (R"(
     const int sinusoidGrating = 1;
     const int squareGrating = 2;
     const int triangleGrating = 3;
     const int sawtoothGrating = 4;

     const int rectangleMask = 1;
     const int ellipseMask = 2;
     const int gaussianMask = 3;

     const vec2 maskCenter = vec2(0.5, 0.5);
     const float maskRadius = 0.5;
     const float pi = 3.14159265358979323846264338327950288;

     uniform int gratingType;
     uniform int maskType;
     uniform vec4 color;
     uniform bool inverted;
     uniform float stdDev;
     uniform float mean;

     in float gratingVaryingCoord;
     in vec2 maskVaryingCoords;

     out vec4 fragColor;

     void main() {
         if (maskVaryingCoords.x < 0.0 || maskVaryingCoords.x > 1.0 ||
             maskVaryingCoords.y < 0.0 || maskVaryingCoords.y > 1.0)
         {
             discard;
         }

         float maskValue;
         switch (maskType) {
             case rectangleMask:
                 maskValue = 1.0;
                 break;

             case ellipseMask: {
                 //
                 // For an explanation of the edge-smoothing technique used here, see either of the following:
                 // https://rubendv.be/blog/opengl/drawing-antialiased-circles-in-opengl/
                 // http://www.numb3r23.net/2015/08/17/using-fwidth-for-distance-based-anti-aliasing/
                 //
                 float dist = distance(maskVaryingCoords, maskCenter);
                 float delta = fwidth(dist);
                 if (dist > maskRadius) {
                     discard;
                 }
                 maskValue = 1.0 - smoothstep(maskRadius - delta, maskRadius, dist);
                 break;
             }

             case gaussianMask: {
                 float s = stdDev;
                 float u = mean;
                 float d = distance(maskVaryingCoords, maskCenter) / maskRadius;
                 maskValue = (1/(s*sqrt(2*pi)))*exp(-1*(d-u)*(d-u)/(2*s*s));
                 break;
             }
         }

         float normGratingCoord = mod(gratingVaryingCoord, 1);
         float gratingValue;
         switch (gratingType) {
             case sinusoidGrating:
                 gratingValue = 0.5*(1+cos(2*pi*normGratingCoord));
                 break;

             case squareGrating:
                 if (cos(2*pi*normGratingCoord) > 0) {
                     gratingValue = 1.0;
                 } else {
                     gratingValue = 0.0;
                 }
                 break;

             case triangleGrating:
                 if (normGratingCoord < 0.5) {
                     gratingValue = (0.5 - normGratingCoord) / 0.5;
                 } else {
                     gratingValue = (normGratingCoord - 0.5) / 0.5;
                 }
                 break;

             case sawtoothGrating:
                 if (inverted) {
                     gratingValue = 1.0 - normGratingCoord;
                 } else {
                     gratingValue = normGratingCoord;
                 }
                 break;
         }

         fragColor.rgb = gratingValue * color.rgb;
         fragColor.a = color.a * maskValue;
     }
     )");

    return gl::createShader(GL_FRAGMENT_SHADER, source);
}

auto DriftingGratingStimulus::getVertexPositions() const -> VertexPositionArray {
    return VertexPositionArray {
        -0.5f, -0.5f,
         0.5f, -0.5f,
        -0.5f,  0.5f,
         0.5f,  0.5f
    };
}

GLKMatrix4 DriftingGratingStimulus::getCurrentMVPMatrix(const GLKMatrix4 &projectionMatrix) const {
    auto currentMVPMatrix = GLKMatrix4Translate(projectionMatrix, current_posx, current_posy, 0.0);
    currentMVPMatrix = GLKMatrix4Rotate(currentMVPMatrix, GLKMathDegreesToRadians(current_rot), 0.0, 0.0, 1.0);
    auto scale_size = std::max(current_sizex, current_sizey);
    return GLKMatrix4Scale(currentMVPMatrix, scale_size, scale_size, 1.0);
}

void DriftingGratingStimulus::prepare(const boost::shared_ptr<StimulusDisplay> &display) {
    boost::mutex::scoped_lock locker(stim_lock);

    ColoredTransformStimulus::prepare(display);

    glUniform1i(glGetUniformLocation(program, "gratingType"), int(gratingType));
    glUniform1i(glGetUniformLocation(program, "maskType"), int(maskType));

    invertedUniformLocation = glGetUniformLocation(program, "inverted");
    stdDevUniformLocation = glGetUniformLocation(program, "stdDev");
    meanUniformLocation = glGetUniformLocation(program, "mean");

    glGenBuffers(1, &gratingCoordBuffer);
    gl::BufferBinding<GL_ARRAY_BUFFER> arrayBufferBinding(gratingCoordBuffer);
    GLint gratingCoordAttribLocation = glGetAttribLocation(program, "gratingCoord");
    glEnableVertexAttribArray(gratingCoordAttribLocation);
    glVertexAttribPointer(gratingCoordAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);

    glGenBuffers(1, &maskCoordsBuffer);
    arrayBufferBinding.bind(maskCoordsBuffer);
    GLint maskCoordsAttribLocation = glGetAttribLocation(program, "maskCoords");
    glEnableVertexAttribArray(maskCoordsAttribLocation);
    glVertexAttribPointer(maskCoordsAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
}

void DriftingGratingStimulus::destroy(const boost::shared_ptr<StimulusDisplay> &display) {
    boost::mutex::scoped_lock locker(stim_lock);

    glDeleteBuffers(1, &maskCoordsBuffer);
    glDeleteBuffers(1, &gratingCoordBuffer);

    ColoredTransformStimulus::destroy(display);
}

void DriftingGratingStimulus::preDraw(const boost::shared_ptr<StimulusDisplay> &display) {
    ColoredTransformStimulus::preDraw(display);

    glUniform1i(invertedUniformLocation, current_inverted);
    glUniform1f(stdDevUniformLocation, current_std_dev);
    glUniform1f(meanUniformLocation, current_mean);

    // here's the description of this equation
    // starting_phase is in degrees ->  degrees*pi/180 = radians
    //
    // speed is in degrees/second
    // spatial_frequency is in cycles/degree
    // elapsed_time is time since the start the 'play' in us
    // us/100000 = seconds
    //
    // degrees   cycles    1 second    pi radians
    // ------- * ------ * ---------- * ----------- * us = radians of phase
    //    s      degree   1000000 us   180 degrees
    //
    // multiply by -1 so it the grating goes in the correct direction
    MWTime elapsed_time = getElapsedTime();
    double elapsed_seconds = (double)elapsed_time /  (double)1000000;
    const double phase = -1*(current_starting_phase*(M_PI/180.) + current_speed*current_spatial_frequency*(2.*M_PI)*elapsed_seconds);
    const double direction_in_radians = current_direction_in_degrees*(M_PI/180.);

    const float f = std::cos(direction_in_radians);
    const float g = std::sin(direction_in_radians);
    const float d = ((f+g)-1)/2;
    const float grating_bl = 0-d;
    const float grating_br = grating_bl+f;
    const float grating_tr = 1+d;
    const float grating_tl = grating_bl+g;

    const float phase_proportion = phase/(2*M_PI);
    const float cycle_proportion = current_spatial_frequency * std::max(current_sizex, current_sizey);

    std::array<GLfloat, 4 * 1> gratingCoord = {
        (cycle_proportion * grating_bl) + phase_proportion,
        (cycle_proportion * grating_br) + phase_proportion,
        (cycle_proportion * grating_tl) + phase_proportion,
        (cycle_proportion * grating_tr) + phase_proportion
    };
    gl::BufferBinding<GL_ARRAY_BUFFER> arrayBufferBinding(gratingCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gratingCoord), gratingCoord.data(), GL_STREAM_DRAW);

    const double aspect = current_sizex / current_sizey;
    float mask_x_offset = 0;
    float mask_y_offset = 0;
    if (aspect > 1.0) {
        mask_y_offset = (aspect - 1.0) / 2.0;
    } else if (aspect < 1.0) {
        mask_x_offset = (1.0/aspect - 1.0) / 2.0;
    }

    std::array<GLfloat, 4 * 2> maskCoords = {
        0 - mask_x_offset, 0 - mask_y_offset,
        1 + mask_x_offset, 0 - mask_y_offset,
        0 - mask_x_offset, 1 + mask_y_offset,
        1 + mask_x_offset, 1 + mask_y_offset
    };
    arrayBufferBinding.bind(maskCoordsBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(maskCoords), maskCoords.data(), GL_STREAM_DRAW);

    last_phase = phase*(180/M_PI);
}

void DriftingGratingStimulus::drawFrame(boost::shared_ptr<StimulusDisplay> display) {
    current_direction_in_degrees = direction_in_degrees->getValue().getFloat();
    current_starting_phase = starting_phase->getValue().getFloat();
    current_spatial_frequency = spatial_frequency->getValue().getFloat();
    current_speed = speed->getValue().getFloat();
    current_inverted = inverted->getValue().getBool();
    current_std_dev = std_dev->getValue().getFloat();
    current_mean = mean->getValue().getFloat();

    ColoredTransformStimulus::draw(display);

    last_direction_in_degrees = current_direction_in_degrees;
    last_starting_phase = current_starting_phase;
    last_spatial_frequency = current_spatial_frequency;
    last_speed = current_speed;
    last_inverted = current_inverted;
    last_std_dev = current_std_dev;
    last_mean = current_mean;
}

END_NAMESPACE_MW

<commit_msg>Fixed some errors raised when compiling and running drifting grating's fragment shader on iOS<commit_after>/*
 *  DriftingGratingStimulus.cpp
 *  MWorksCore
 *
 *  Created by bkennedy on 8/26/08.
 *  Copyright 2008 MIT. All rights reserved.
 *
 */

#include "DriftingGratingStimulus.h"

BEGIN_NAMESPACE_MW

const std::string DriftingGratingStimulus::DIRECTION("direction");
const std::string DriftingGratingStimulus::STARTING_PHASE("starting_phase");
const std::string DriftingGratingStimulus::FREQUENCY("spatial_frequency");
const std::string DriftingGratingStimulus::SPEED("speed");
const std::string DriftingGratingStimulus::GRATING_TYPE("grating_type");
const std::string DriftingGratingStimulus::MASK("mask");
const std::string DriftingGratingStimulus::INVERTED("inverted");
const std::string DriftingGratingStimulus::STD_DEV("std_dev");
const std::string DriftingGratingStimulus::MEAN("mean");

void DriftingGratingStimulus::describeComponent(ComponentInfo &info) {
    DriftingGratingStimulusBase::describeComponent(info);

    info.setSignature("stimulus/drifting_grating");

    info.addParameter(DIRECTION, "0.0");
    info.addParameter(STARTING_PHASE, "0.0");
    info.addParameter(FREQUENCY);
    info.addParameter(SPEED);
    info.addParameter(GRATING_TYPE);
    info.addParameter(MASK);
    info.addParameter(INVERTED, "NO");
    info.addParameter(STD_DEV, "1.0");
    info.addParameter(MEAN, "0.0");

    // This is no longer used but may be present in old experiments
    info.addIgnoredParameter("grating_sample_rate");
}

auto DriftingGratingStimulus::gratingTypeFromName(const std::string &name) -> GratingType {
    if (name == "sinusoid") {
        return GratingType::sinusoid;
    } else if (name == "square") {
        return GratingType::square;
    } else if (name == "triangle") {
        return GratingType::triangle;
    } else if (name == "sawtooth") {
        return GratingType::sawtooth;
    }
    throw SimpleException("Invalid grating type", name);
};

auto DriftingGratingStimulus::maskTypeFromName(const std::string &name) -> MaskType {
    if (name == "rectangle") {
        return MaskType::rectangle;
    } else if (name == "ellipse") {
        return MaskType::ellipse;
    } else if (name == "gaussian") {
        return MaskType::gaussian;
    }
    throw SimpleException("Invalid mask type", name);
};

DriftingGratingStimulus::DriftingGratingStimulus(const ParameterValueMap &parameters) :
    DriftingGratingStimulusBase(parameters),
    direction_in_degrees(registerVariable(parameters[DIRECTION])),
    starting_phase(registerVariable(parameters[STARTING_PHASE])),
    spatial_frequency(registerVariable(parameters[FREQUENCY])),
    speed(registerVariable(parameters[SPEED])),
    gratingTypeName(parameters[GRATING_TYPE].str()),
    gratingType(gratingTypeFromName(gratingTypeName)),
    maskTypeName(parameters[MASK].str()),
    maskType(maskTypeFromName(maskTypeName)),
    inverted(registerVariable(parameters[INVERTED])),
    std_dev(registerVariable(parameters[STD_DEV])),
    mean(registerVariable(parameters[MEAN]))
{ }

Datum DriftingGratingStimulus::getCurrentAnnounceDrawData() {
    boost::mutex::scoped_lock locker(stim_lock);

    Datum announceData = DriftingGratingStimulusBase::getCurrentAnnounceDrawData();

    announceData.addElement(STIM_TYPE, "drifting_grating");
    announceData.addElement(DIRECTION, last_direction_in_degrees);
    announceData.addElement(STARTING_PHASE, last_starting_phase);
    announceData.addElement("current_phase", last_phase);
    announceData.addElement(FREQUENCY, last_spatial_frequency);
    announceData.addElement(SPEED, last_speed);
    announceData.addElement(GRATING_TYPE, gratingTypeName);
    announceData.addElement(MASK, maskTypeName);

    if (gratingType == GratingType::sawtooth) {
        announceData.addElement(INVERTED, last_inverted);
    }

    if (maskType == MaskType::gaussian) {
        announceData.addElement(STD_DEV, last_std_dev);
        announceData.addElement(MEAN, last_mean);
    }

    return announceData;
}

gl::Shader DriftingGratingStimulus::getVertexShader() const {
    static const std::string source
    (R"(
     uniform mat4 mvpMatrix;

     in vec4 vertexPosition;
     in float gratingCoord;
     in vec2 maskCoords;

     out float gratingVaryingCoord;
     out vec2 maskVaryingCoords;

     void main() {
         gl_Position = mvpMatrix * vertexPosition;
         gratingVaryingCoord = gratingCoord;
         maskVaryingCoords = maskCoords;
     }
     )");

    return gl::createShader(GL_VERTEX_SHADER, source);
}

gl::Shader DriftingGratingStimulus::getFragmentShader() const {
    static const std::string source
    (R"(
     const int sinusoidGrating = 1;
     const int squareGrating = 2;
     const int triangleGrating = 3;
     const int sawtoothGrating = 4;

     const int rectangleMask = 1;
     const int ellipseMask = 2;
     const int gaussianMask = 3;

     const vec2 maskCenter = vec2(0.5, 0.5);
     const float maskRadius = 0.5;
     const float pi = 3.14159265358979323846264338327950288;

     uniform int gratingType;
     uniform int maskType;
     uniform vec4 color;
     uniform bool inverted;
     uniform float stdDev;
     uniform float mean;

     in float gratingVaryingCoord;
     in vec2 maskVaryingCoords;

     out vec4 fragColor;

     void main() {
         if (maskVaryingCoords.x < 0.0 || maskVaryingCoords.x > 1.0 ||
             maskVaryingCoords.y < 0.0 || maskVaryingCoords.y > 1.0)
         {
             discard;
         }

         float maskValue;
         float dist;
         float delta;
         switch (maskType) {
             case rectangleMask:
                 maskValue = 1.0;
                 break;

             case ellipseMask:
                 //
                 // For an explanation of the edge-smoothing technique used here, see either of the following:
                 // https://rubendv.be/blog/opengl/drawing-antialiased-circles-in-opengl/
                 // http://www.numb3r23.net/2015/08/17/using-fwidth-for-distance-based-anti-aliasing/
                 //
                 dist = distance(maskVaryingCoords, maskCenter);
                 delta = fwidth(dist);
                 if (dist > maskRadius) {
                     discard;
                 }
                 maskValue = 1.0 - smoothstep(maskRadius - delta, maskRadius, dist);
                 break;

             case gaussianMask:
                 dist = distance(maskVaryingCoords, maskCenter) / maskRadius;
                 maskValue = ((1.0 / (stdDev * sqrt(2.0 * pi))) *
                              exp(-1.0 * (dist - mean) * (dist - mean) / (2.0 * stdDev * stdDev)));
                 break;
         }

         float normGratingCoord = mod(gratingVaryingCoord, 1.0);
         float gratingValue;
         switch (gratingType) {
             case sinusoidGrating:
                 gratingValue = 0.5*(1.0+cos(2.0*pi*normGratingCoord));
                 break;

             case squareGrating:
                 if (cos(2.0*pi*normGratingCoord) > 0.0) {
                     gratingValue = 1.0;
                 } else {
                     gratingValue = 0.0;
                 }
                 break;

             case triangleGrating:
                 if (normGratingCoord < 0.5) {
                     gratingValue = (0.5 - normGratingCoord) / 0.5;
                 } else {
                     gratingValue = (normGratingCoord - 0.5) / 0.5;
                 }
                 break;

             case sawtoothGrating:
                 if (inverted) {
                     gratingValue = 1.0 - normGratingCoord;
                 } else {
                     gratingValue = normGratingCoord;
                 }
                 break;
         }

         fragColor.rgb = gratingValue * color.rgb;
         fragColor.a = color.a * maskValue;
     }
     )");

    return gl::createShader(GL_FRAGMENT_SHADER, source);
}

auto DriftingGratingStimulus::getVertexPositions() const -> VertexPositionArray {
    return VertexPositionArray {
        -0.5f, -0.5f,
         0.5f, -0.5f,
        -0.5f,  0.5f,
         0.5f,  0.5f
    };
}

GLKMatrix4 DriftingGratingStimulus::getCurrentMVPMatrix(const GLKMatrix4 &projectionMatrix) const {
    auto currentMVPMatrix = GLKMatrix4Translate(projectionMatrix, current_posx, current_posy, 0.0);
    currentMVPMatrix = GLKMatrix4Rotate(currentMVPMatrix, GLKMathDegreesToRadians(current_rot), 0.0, 0.0, 1.0);
    auto scale_size = std::max(current_sizex, current_sizey);
    return GLKMatrix4Scale(currentMVPMatrix, scale_size, scale_size, 1.0);
}

void DriftingGratingStimulus::prepare(const boost::shared_ptr<StimulusDisplay> &display) {
    boost::mutex::scoped_lock locker(stim_lock);

    ColoredTransformStimulus::prepare(display);

    glUniform1i(glGetUniformLocation(program, "gratingType"), int(gratingType));
    glUniform1i(glGetUniformLocation(program, "maskType"), int(maskType));

    invertedUniformLocation = glGetUniformLocation(program, "inverted");
    stdDevUniformLocation = glGetUniformLocation(program, "stdDev");
    meanUniformLocation = glGetUniformLocation(program, "mean");

    glGenBuffers(1, &gratingCoordBuffer);
    gl::BufferBinding<GL_ARRAY_BUFFER> arrayBufferBinding(gratingCoordBuffer);
    GLint gratingCoordAttribLocation = glGetAttribLocation(program, "gratingCoord");
    glEnableVertexAttribArray(gratingCoordAttribLocation);
    glVertexAttribPointer(gratingCoordAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);

    glGenBuffers(1, &maskCoordsBuffer);
    arrayBufferBinding.bind(maskCoordsBuffer);
    GLint maskCoordsAttribLocation = glGetAttribLocation(program, "maskCoords");
    glEnableVertexAttribArray(maskCoordsAttribLocation);
    glVertexAttribPointer(maskCoordsAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
}

void DriftingGratingStimulus::destroy(const boost::shared_ptr<StimulusDisplay> &display) {
    boost::mutex::scoped_lock locker(stim_lock);

    glDeleteBuffers(1, &maskCoordsBuffer);
    glDeleteBuffers(1, &gratingCoordBuffer);

    ColoredTransformStimulus::destroy(display);
}

void DriftingGratingStimulus::preDraw(const boost::shared_ptr<StimulusDisplay> &display) {
    ColoredTransformStimulus::preDraw(display);

    glUniform1i(invertedUniformLocation, current_inverted);
    glUniform1f(stdDevUniformLocation, current_std_dev);
    glUniform1f(meanUniformLocation, current_mean);

    // here's the description of this equation
    // starting_phase is in degrees ->  degrees*pi/180 = radians
    //
    // speed is in degrees/second
    // spatial_frequency is in cycles/degree
    // elapsed_time is time since the start the 'play' in us
    // us/100000 = seconds
    //
    // degrees   cycles    1 second    pi radians
    // ------- * ------ * ---------- * ----------- * us = radians of phase
    //    s      degree   1000000 us   180 degrees
    //
    // multiply by -1 so it the grating goes in the correct direction
    MWTime elapsed_time = getElapsedTime();
    double elapsed_seconds = (double)elapsed_time /  (double)1000000;
    const double phase = -1*(current_starting_phase*(M_PI/180.) + current_speed*current_spatial_frequency*(2.*M_PI)*elapsed_seconds);
    const double direction_in_radians = current_direction_in_degrees*(M_PI/180.);

    const float f = std::cos(direction_in_radians);
    const float g = std::sin(direction_in_radians);
    const float d = ((f+g)-1)/2;
    const float grating_bl = 0-d;
    const float grating_br = grating_bl+f;
    const float grating_tr = 1+d;
    const float grating_tl = grating_bl+g;

    const float phase_proportion = phase/(2*M_PI);
    const float cycle_proportion = current_spatial_frequency * std::max(current_sizex, current_sizey);

    std::array<GLfloat, 4 * 1> gratingCoord = {
        (cycle_proportion * grating_bl) + phase_proportion,
        (cycle_proportion * grating_br) + phase_proportion,
        (cycle_proportion * grating_tl) + phase_proportion,
        (cycle_proportion * grating_tr) + phase_proportion
    };
    gl::BufferBinding<GL_ARRAY_BUFFER> arrayBufferBinding(gratingCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gratingCoord), gratingCoord.data(), GL_STREAM_DRAW);

    const double aspect = current_sizex / current_sizey;
    float mask_x_offset = 0;
    float mask_y_offset = 0;
    if (aspect > 1.0) {
        mask_y_offset = (aspect - 1.0) / 2.0;
    } else if (aspect < 1.0) {
        mask_x_offset = (1.0/aspect - 1.0) / 2.0;
    }

    std::array<GLfloat, 4 * 2> maskCoords = {
        0 - mask_x_offset, 0 - mask_y_offset,
        1 + mask_x_offset, 0 - mask_y_offset,
        0 - mask_x_offset, 1 + mask_y_offset,
        1 + mask_x_offset, 1 + mask_y_offset
    };
    arrayBufferBinding.bind(maskCoordsBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(maskCoords), maskCoords.data(), GL_STREAM_DRAW);

    last_phase = phase*(180/M_PI);
}

void DriftingGratingStimulus::drawFrame(boost::shared_ptr<StimulusDisplay> display) {
    current_direction_in_degrees = direction_in_degrees->getValue().getFloat();
    current_starting_phase = starting_phase->getValue().getFloat();
    current_spatial_frequency = spatial_frequency->getValue().getFloat();
    current_speed = speed->getValue().getFloat();
    current_inverted = inverted->getValue().getBool();
    current_std_dev = std_dev->getValue().getFloat();
    current_mean = mean->getValue().getFloat();

    ColoredTransformStimulus::draw(display);

    last_direction_in_degrees = current_direction_in_degrees;
    last_starting_phase = current_starting_phase;
    last_spatial_frequency = current_spatial_frequency;
    last_speed = current_speed;
    last_inverted = current_inverted;
    last_std_dev = current_std_dev;
    last_mean = current_mean;
}

END_NAMESPACE_MW

<|endoftext|>


<commit_before>/**********************************************************************
 * $Id:
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Geometry.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/MultiPolygon.h>
#include <geos/geom/prep/PreparedPolygon.h>
#include <geos/geom/prep/PreparedPolygonContainsProperly.h>
#include <geos/geom/prep/PreparedPolygonPredicate.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/SegmentStringUtil.h>
#include <geos/noding/FastSegmentSetIntersectionFinder.h>

namespace geos {
namespace geom { // geos.geom
namespace prep { // geos.geom.prep
//
// private:
//

//
// protected:
//

//
// public:
//
bool
PreparedPolygonContainsProperly::containsProperly( const geom::Geometry * geom)
{
	// Do point-in-poly tests first, since they are cheaper and may result
	// in a quick negative result.
	// If a point of any test components does not lie in target, result is false
	bool isAllInPrepGeomArea = isAllTestComponentsInTargetInterior( geom);
	if ( !isAllInPrepGeomArea )
		return false;

	// If any segments intersect, result is false
	noding::SegmentString::ConstVect lineSegStr;
	noding::SegmentStringUtil::extractSegmentStrings( geom, lineSegStr);
	bool segsIntersect = prepPoly->getIntersectionFinder()->intersects( &lineSegStr);

	for ( size_t i = 0, ni = lineSegStr.size(); i < ni; i++ )
		delete lineSegStr[ i ];

	if (segsIntersect)
		return false;

	if (	geom->getGeometryTypeId() == GeometryTypeId::GEOS_MULTIPOLYGON
		||	geom->getGeometryTypeId() == GeometryTypeId::GEOS_POLYGON )
	{
		// TODO: generalize this to handle GeometryCollections
		bool isTargetGeomInTestArea = isAnyTargetComponentInTestArea( geom, prepPoly->getRepresentativePoints());
		if (isTargetGeomInTestArea)
			return false;
	}

	return true;
}

} // namespace geos.geom.prep
} // namespace geos.geom
} // namespace geos

/**********************************************************************
 * $Log$
 *
 **********************************************************************/
<commit_msg>Fixed extra qualifications in /geom/prep/PreparedPolygonContainsProperly.<commit_after>/**********************************************************************
 * $Id:
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Geometry.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/MultiPolygon.h>
#include <geos/geom/prep/PreparedPolygon.h>
#include <geos/geom/prep/PreparedPolygonContainsProperly.h>
#include <geos/geom/prep/PreparedPolygonPredicate.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/SegmentStringUtil.h>
#include <geos/noding/FastSegmentSetIntersectionFinder.h>

namespace geos {
namespace geom { // geos.geom
namespace prep { // geos.geom.prep
//
// private:
//

//
// protected:
//

//
// public:
//
bool
PreparedPolygonContainsProperly::containsProperly( const geom::Geometry * geom)
{
	// Do point-in-poly tests first, since they are cheaper and may result
	// in a quick negative result.
	// If a point of any test components does not lie in target, result is false
	bool isAllInPrepGeomArea = isAllTestComponentsInTargetInterior( geom);
	if ( !isAllInPrepGeomArea )
		return false;

	// If any segments intersect, result is false
	noding::SegmentString::ConstVect lineSegStr;
	noding::SegmentStringUtil::extractSegmentStrings( geom, lineSegStr);
	bool segsIntersect = prepPoly->getIntersectionFinder()->intersects( &lineSegStr);

	for ( size_t i = 0, ni = lineSegStr.size(); i < ni; i++ )
		delete lineSegStr[ i ];

	if (segsIntersect)
		return false;

	if (	geom->getGeometryTypeId() == geos::geom::GEOS_MULTIPOLYGON
		||	geom->getGeometryTypeId() == geos::geom::GEOS_POLYGON )
	{
		// TODO: generalize this to handle GeometryCollections
		bool isTargetGeomInTestArea = isAnyTargetComponentInTestArea( geom, prepPoly->getRepresentativePoints());
		if (isTargetGeomInTestArea)
			return false;
	}

	return true;
}

} // namespace geos.geom.prep
} // namespace geos.geom
} // namespace geos

/**********************************************************************
 * $Log$
 *
 **********************************************************************/
<|endoftext|>


<commit_before>#include <string>
#include <sstream>
#include <iostream>
#include <utility>
#include "texture.hpp"
#include "vfs.hpp"
#include "gl.hpp"

#define STB_IMAGE_IMPLEMENTATION
#define STBI_NO_STDIO
//exclude image formats
#define STBI_NO_PIC
#define STBI_NO_PNM
#define STBI_NO_PSD
#define STBI_NO_GIF
// This leaves us with the following supported image formats:
// jpg  png  bmp  tga  hdr
#include "stb_image.h"

namespace MgCore
{
    static int _texCount = 0;
    static GLuint _currentBoundtexture = 0;

    // I'm putting this back here for now ill add it a cmake option to provide either STB or png+
    // Then it will be uncommented.
    // Image loadPNG(std::string filename)
    // {
    //     std::istringstream file(MgCore::read_file( filename ));
    //     png::image<png::rgba_pixel> image(file);

    //     auto pixelBuffer = image.get_pixbuf();

    //     Image imgData;

    //     imgData.width = image.get_width();
    //     imgData.height = image.get_height();
    //     imgData.length = imgData.width * imgData.height * 4;
    //     std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
    //     imgData.pixelData = std::move(data);

    //     int i = 0;

    //     for (int x = 0;x < imgData.width; x++) {
    //         for (int y = 0; y < imgData.height; y++) {
    //             auto pixel = pixelBuffer.get_pixel(x, y);
    //             i = 4 * (y * imgData.width + x);

    //             imgData.pixelData[i+0] = pixel.red;
    //             imgData.pixelData[i+1] = pixel.green;
    //             imgData.pixelData[i+2] = pixel.blue;
    //             imgData.pixelData[i+3] = pixel.alpha;

    //         }
    //     }
    //     return imgData;
    // }

    Image loadSTB(std::string filename)
    {
        std::string mem_buf = MgCore::read_file( filename );

        Image imgData;

        std::unique_ptr<unsigned char[]> conv_mem( new unsigned char[ mem_buf.size() ]() );

        // to prevent potential issues convert each value seperately
        // one could cast the int* to unsigned int* however this could have issues as there seems
        // to be platform differances on how  it's imeplemented.
        for (int i = 0; i < mem_buf.size(); i++) {
            conv_mem[i] = static_cast<unsigned int>(mem_buf[i]);
        }

        unsigned char *img_buf;
        int comp;

        img_buf = stbi_load_from_memory( &conv_mem[0], mem_buf.size(), &imgData.width, &imgData.height, &comp, 0 );

        if ( img_buf == NULL )
            std::cout << "Failed to get image data" << std::endl;

        imgData.length = imgData.width * imgData.height * 4;
        std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
        imgData.pixelData = std::move(data);

        // We have to copy the data out of the returned data from stb.
        // This was an issue with the previous implementation where the data was destroyed before
        // opengl could copy the data to the gpu. OpenGL may even require the image data to be persistant
        // cpu side if not it may be a good idea to do so anyways.
        int i = 0;

        for (int i = 0; i < (imgData.width*4)*imgData.height; i++) {
            imgData.pixelData[i+0] = img_buf[i+0];
            imgData.pixelData[i+1] = img_buf[i+1];
            imgData.pixelData[i+2] = img_buf[i+2];
            if (comp == 4) {
                imgData.pixelData[i+3] = img_buf[i+3];
            } else {
                imgData.pixelData[i+3] = 255U;
            }
        }
        stbi_image_free( img_buf );
        return imgData;
    }

    Texture::Texture(std::string path, ShaderProgram *program)
    : m_path(path), m_program(program)
    {
        _texCount++;
        m_texUnitID = _texCount;

        m_image = MgCore::loadSTB(m_path);

        m_texSampID = m_program->uniform_attribute("textureSampler");

        GLuint texid;
        glGenTextures(1, &texid);
        m_texID = texid;
        glBindTexture(GL_TEXTURE_2D, m_texID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width, m_image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(m_image.pixelData.get())[0]);
    }

    void Texture::bind()
    {
        if (_currentBoundtexture != m_texUnitID) {
            _currentBoundtexture = m_texUnitID;

            glActiveTexture(GL_TEXTURE0+m_texUnitID);
            glBindTexture(GL_TEXTURE_2D, m_texID);
            m_program->set_uniform(m_texSampID, m_texUnitID);
            std::cout << "Texture bound" << std::endl;

        }
    }
}<commit_msg>Fix loop count by 4 derp.<commit_after>#include <string>
#include <sstream>
#include <iostream>
#include <utility>
#include "texture.hpp"
#include "vfs.hpp"

#define STB_IMAGE_IMPLEMENTATION
#define STBI_NO_STDIO
//exclude image formats
#define STBI_NO_PIC
#define STBI_NO_PNM
#define STBI_NO_PSD
#define STBI_NO_GIF
// This leaves us with the following supported image formats:
// jpg  png  bmp  tga  hdr
#include "stb_image.h"

namespace MgCore
{
    static int _texCount = 0;
    static GLuint _currentBoundtexture = 0;

    // I'm putting this back here for now ill add it a cmake option to provide either STB or png+
    // Then it will be uncommented.
    // Image loadPNG(std::string filename)
    // {
    //     std::istringstream file(MgCore::read_file( filename ));
    //     png::image<png::rgba_pixel> image(file);

    //     auto pixelBuffer = image.get_pixbuf();

    //     Image imgData;

    //     imgData.width = image.get_width();
    //     imgData.height = image.get_height();
    //     imgData.length = imgData.width * imgData.height * 4;
    //     std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
    //     imgData.pixelData = std::move(data);

    //     int i = 0;

    //     for (int x = 0;x < imgData.width; x++) {
    //         for (int y = 0; y < imgData.height; y++) {
    //             auto pixel = pixelBuffer.get_pixel(x, y);
    //             i = 4 * (y * imgData.width + x);

    //             imgData.pixelData[i+0] = pixel.red;
    //             imgData.pixelData[i+1] = pixel.green;
    //             imgData.pixelData[i+2] = pixel.blue;
    //             imgData.pixelData[i+3] = pixel.alpha;

    //         }
    //     }
    //     return imgData;
    // }

    Image loadSTB(std::string filename)
    {
        std::string mem_buf = MgCore::read_file( filename );

        Image imgData;

        std::unique_ptr<unsigned char[]> conv_mem( new unsigned char[ mem_buf.size() ]() );

        // to prevent potential issues convert each value seperately
        // one could cast the int* to unsigned int* however this could have large issues there can be
        // platform differances on how this is imeplemented.
        for (int i = 0; i < mem_buf.size(); i++) {
            conv_mem[i] = static_cast<unsigned int>(mem_buf[i]);
        }

        unsigned char *img_buf;
        int comp;

        img_buf = stbi_load_from_memory( &conv_mem[0], mem_buf.size(), &imgData.width, &imgData.height, &comp, 0 );

        if ( img_buf == NULL )
            std::cout << "Failed to get image data" << std::endl;

        imgData.length = imgData.width * imgData.height * 4;
        std::unique_ptr<unsigned char[]> data(new unsigned char[imgData.length]());
        imgData.pixelData = std::move(data);

        // We have to copy the data out of the returned data from stb.
        // This was an issue with the previous implementation where the data was destroyed before
        // opengl could copy the data to the gpu. OpenGL may even require the image data to be persistant
        // cpu side if not it may be a good idea to do so anyways.
        int i = 0;
        // currently the main reason the loop is setup like this, is that it makes it a bit easier to convert RGB to RGBA.
        for (int i; i < (imgData.width*4)*imgData.height; i+=4) {
            imgData.pixelData[i+0] = img_buf[i+0];
            imgData.pixelData[i+1] = img_buf[i+1];
            imgData.pixelData[i+2] = img_buf[i+2];
            if (comp == 4) {
                imgData.pixelData[i+3] = img_buf[i+3];
            } else {
                imgData.pixelData[i+3] = 255U;
            }
        }
        stbi_image_free( img_buf );
        return imgData;
    }

    Texture::Texture(std::string path, ShaderProgram *program)
    : m_path(path), m_program(program)
    {
        _texCount++;
        m_texUnitID = _texCount;

        m_image = MgCore::loadSTB(m_path);

        m_texSampID = m_program->uniform_attribute("textureSampler");

        GLuint texid;
        glGenTextures(1, &texid);
        m_texID = texid;
        glBindTexture(GL_TEXTURE_2D, m_texID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width, m_image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(m_image.pixelData.get())[0]);
    }

    void Texture::bind()
    {
        if (_currentBoundtexture != m_texUnitID) {
            _currentBoundtexture = m_texUnitID;

            glActiveTexture(GL_TEXTURE0+m_texUnitID);
            glBindTexture(GL_TEXTURE_2D, m_texID);
            m_program->set_uniform(m_texSampID, m_texUnitID);
            std::cout << "Texture bound" << std::endl;

        }
    }
}<|endoftext|>


<commit_before>#ifndef HTTP_HH
#define HTTP_HH

#include <string>
#include <vector>
#include <stdexcept>

#include "http_parser.h"
#include "error.hh"

// TODO: define exceptions

typedef std::pair<std::string, std::string> header_pair;
typedef std::vector<header_pair> header_list;

struct http_base {
    header_list headers;
    bool complete;
    std::string body;
    size_t body_length;

    http_base() : complete(false), body_length(0) {}

    void set_header(const std::string &field, const std::string &value);
    void set_header(const std::string &field, unsigned long long value);
    void append_header(const std::string &field, const std::string &value);
    void append_header(const std::string &field, unsigned long long value);
    header_list::iterator find_header(const std::string &field);
    bool remove_header(const std::string &field);
    std::string header_string(const std::string &field) const;
    unsigned long long header_ull(const std::string &field) const;

    void normalize_headers();
    void set_body(const std::string &body_) {
        body = body_;
        body_length = body.size();
        remove_header("Content-Length");
        append_header("Content-Length", body_length);
    }
};

struct http_request : http_base {
    std::string method;
    std::string uri;
    std::string http_version;

    http_request() {}
    http_request(const std::string &method_,
        const std::string &uri_,
        const std::string &http_version_ = "HTTP/1.1")
        : method(method_), uri(uri_), http_version(http_version_) {}

    void clear() {
        headers.clear();
        complete = false;
        method.clear();
        uri.clear();
        http_version.clear();
        body.clear();
        body_length = 0;
    }

    void parser_init(struct http_parser *p);
    bool parse(struct http_parser *p, const char *data, size_t len);

    std::string data() const;
};

struct http_response : http_base {
    std::string http_version;
    unsigned long status_code;
    std::string reason;
    http_request *req;

    http_response(http_request *req_) : req(req_) {}

    http_response(unsigned long status_code_ = 200,
        const std::string &reason_ = "OK",
        const std::string &http_version_ = "HTTP/1.1")
        : http_version(http_version_),
        status_code(status_code_),
        reason(reason_),
        req(NULL)
        {}

    void clear() {
        headers.clear();
        http_version.clear();
        status_code = 0;
        reason.clear();
        body.clear();
        body_length = 0;
    }

    void parser_init(struct http_parser *p);
    bool parse(struct http_parser *p, const char *data, size_t len);

    std::string data() const;
};

#endif // HTTP_HH
<commit_msg>allow headers to be passed to constructor<commit_after>#ifndef HTTP_HH
#define HTTP_HH

#include <string>
#include <vector>
#include <stdexcept>
#include <stdarg.h>

#include "http_parser.h"
#include "error.hh"

// TODO: define exceptions

typedef std::pair<std::string, std::string> header_pair;
typedef std::vector<header_pair> header_list;

struct http_base {
    header_list headers;
    bool complete;
    std::string body;
    size_t body_length;

    http_base() : complete(false), body_length(0) {}

    void set_header(const std::string &field, const std::string &value);
    void set_header(const std::string &field, unsigned long long value);
    void append_header(const std::string &field, const std::string &value);
    void append_header(const std::string &field, unsigned long long value);
    header_list::iterator find_header(const std::string &field);
    bool remove_header(const std::string &field);
    std::string header_string(const std::string &field) const;
    unsigned long long header_ull(const std::string &field) const;

    void normalize_headers();
    void set_body(const std::string &body_) {
        body = body_;
        body_length = body.size();
        remove_header("Content-Length");
        append_header("Content-Length", body_length);
    }
};

struct http_request : http_base {
    std::string method;
    std::string uri;
    std::string http_version;

    http_request() {}
    http_request(const std::string &method_,
        const std::string &uri_,
        const std::string &http_version_ = "HTTP/1.1")
        : method(method_), uri(uri_), http_version(http_version_) {}

    void clear() {
        headers.clear();
        complete = false;
        method.clear();
        uri.clear();
        http_version.clear();
        body.clear();
        body_length = 0;
    }

    void parser_init(struct http_parser *p);
    bool parse(struct http_parser *p, const char *data, size_t len);

    std::string data() const;
};

struct http_response : http_base {
    std::string http_version;
    unsigned long status_code;
    std::string reason;
    http_request *req;

    http_response(http_request *req_) : req(req_) {}

    http_response(unsigned long status_code_ = 200,
        const std::string &reason_ = "OK",
        const std::string &http_version_ = "HTTP/1.1",
        unsigned int nheaders = 0,
        ...) // headers
        : http_version(http_version_),
        status_code(status_code_),
        reason(reason_),
        req(NULL)
    {
        va_list ap;
        va_start(ap, nheaders);
        for (;nheaders > 0;--nheaders) {
            const char *header_name = va_arg(ap, const char *);
            const char *header_value = va_arg(ap, const char *);
            append_header(header_name, header_value);
        }
        va_end(ap);
    }

    void clear() {
        headers.clear();
        http_version.clear();
        status_code = 0;
        reason.clear();
        body.clear();
        body_length = 0;
    }

    void parser_init(struct http_parser *p);
    bool parse(struct http_parser *p, const char *data, size_t len);

    std::string data() const;
};

#endif // HTTP_HH
<|endoftext|>


<commit_before>#include "VTKImageImporter.hpp"
using namespace fast;

void VTKImageImporter::setInput(vtkSmartPointer<vtkImageData> image) {
    mInput = image;
    mIsModified = true;
}

Image2D::pointer VTKImageImporter::getOutput() {
    if(mTempOutput.isValid()) {
        mTempOutput->addParent(mPtr.lock());

        Image2D::pointer newSmartPtr;
        newSmartPtr.swap(mTempOutput);

        return newSmartPtr;
    } else {
        return mOutput.lock();
    }
}

VTKImageImporter::VTKImageImporter() {
    mTempOutput = Image2D::New();
    mOutput = mTempOutput;
}

void VTKImageImporter::execute() {
    // Make sure VTK data is up to date
    mInput->Update();

    int * size = mInput->GetDimensions();

    Image2D::pointer output = mOutput.lock();

    output->createImage(size[0]-1, size[1]-1);
    ImageAccess2D access = output->getImageAccess(ACCESS_READ);
    float * fastPixelData = (float *)access.get();
    for(int x = 0; x < output->getWidth(); x++) {
    for(int y = 0; y < output->getHeight(); y++) {
        float * pixel = static_cast<float*>(mInput->GetScalarPointer(x,output->getHeight()-y,0));
        fastPixelData[x+y*output->getWidth()] = pixel[0];
    }}
}
<commit_msg>fixed some compiler warnings<commit_after>#include "VTKImageImporter.hpp"
using namespace fast;

void VTKImageImporter::setInput(vtkSmartPointer<vtkImageData> image) {
    mInput = image;
    mIsModified = true;
}

Image2D::pointer VTKImageImporter::getOutput() {
    if(mTempOutput.isValid()) {
        mTempOutput->addParent(mPtr.lock());

        Image2D::pointer newSmartPtr;
        newSmartPtr.swap(mTempOutput);

        return newSmartPtr;
    } else {
        return mOutput.lock();
    }
}

VTKImageImporter::VTKImageImporter() {
    mTempOutput = Image2D::New();
    mOutput = mTempOutput;
}

void VTKImageImporter::execute() {
    // Make sure VTK data is up to date
    mInput->Update();

    int * size = mInput->GetDimensions();

    Image2D::pointer output = mOutput.lock();

    output->createImage(size[0]-1, size[1]-1);
    ImageAccess2D access = output->getImageAccess(ACCESS_READ);
    float * fastPixelData = (float *)access.get();
    for(unsigned int x = 0; x < output->getWidth(); x++) {
    for(unsigned int y = 0; y < output->getHeight(); y++) {
        float * pixel = static_cast<float*>(mInput->GetScalarPointer(x,output->getHeight()-y,0));
        fastPixelData[x+y*output->getWidth()] = pixel[0];
    }}
}
<|endoftext|>


<commit_before><commit_msg>renaming<commit_after><|endoftext|>


<commit_before>#include <sqlite3.h>
#include <algorithm>

#include "ace/OS_NS_sys_time.h"

#include "log.h"

#include "json/reader.h"
#include "json/value.h"

#include "DataStore.h"
#include "QueryHandlerFactory.h"
#include "QueryHandler.h"

#include "DataStoreConstants.h"

using namespace ammo::gateway;

DataStoreReceiver::DataStoreReceiver (void)
  : db_ (0),
    stmt_ (0)
{
}

DataStoreReceiver::~DataStoreReceiver (void)
{
  LOG_DEBUG ("Closing Data Store Service database...");

  sqlite3_close (db_);
}

void
DataStoreReceiver::onConnect (GatewayConnector * /* sender */)
{
}

void
DataStoreReceiver::onDisconnect (GatewayConnector * /* sender */)
{
}

void
DataStoreReceiver::onPushDataReceived (GatewayConnector * /* sender */,
                                       PushData &pushData)
{
  LOG_TRACE ("Received " << pushData);
  bool good_data_store = true;

  if (pushData.mimeType.find (PVT_CONTACTS_DATA_TYPE) == 0)
    {
      good_data_store = this->pushContactData (pushData);
    }
  else
    {
      good_data_store = this->pushGeneralData (pushData);
    }

	if (good_data_store)
	  {
      LOG_DEBUG ("data store successful");
    }
}

void
DataStoreReceiver::onPullRequestReceived (GatewayConnector *sender,
                                          PullRequest &pullReq)
{
  LOG_TRACE ("pull request received");

  if (sender == 0)
    {
      LOG_WARN ("Sender is null, no responses will be sent");
    }

  LOG_DEBUG ("Data type: " << pullReq.mimeType);

  QueryHandlerFactory factory;
  QueryHandler *handler = factory.createHandler (db_, sender, pullReq);

  handler->handleQuery ();

  delete handler;
  handler = 0;
}

void
DataStoreReceiver::db_filepath (const std::string &path)
{
  db_filepath_ = path;
}

bool
DataStoreReceiver::init (void)
{
  std::string filepath (db_filepath_);
  filepath += "DataStore_db.sql3";

//  LOG_DEBUG ("full path = " << filepath.c_str ());

  int status = sqlite3_open (filepath.c_str (), &db_);

  if (status != 0)
    {
      LOG_ERROR ("Data Store Service - " << sqlite3_errmsg (db_));
      return false;
    }

  const char *data_tbl_str =
	  "CREATE TABLE IF NOT EXISTS data_table ("
	  "uri TEXT,"
	  "mime_type TEXT,"
	  "origin_user TEXT,"
	  "tv_sec INTEGER NOT NULL,"
	  "tv_usec INTEGER,"
	  "data BLOB)";

  return this->createTable (data_tbl_str, "data");
}

bool
DataStoreReceiver::pushContactData (const ammo::gateway::PushData &pushData)
{
  Json::Value root;

  if (!this->parseJson (pushData.data, root))
    {
      return false;
    }

  PrivateContact info;
  this->contactFromJson (root, info);

  // SQL table names can't contain '.', so we append the chars of
  // the arg we use for the table name to the query string,
  // while replacing '.' with '_'.
  std::string tbl_name = pushData.originUsername;
  std::replace_if (tbl_name.begin (),
                   tbl_name.end (),
                   std::bind2nd (std::equal_to<char> (), '.'),
                   '_');

  // 2011-06-21 - not using the last 2 columns at this point.
	std::string contacts_tbl_str ("CREATE TABLE IF NOT EXISTS ");
	contacts_tbl_str += tbl_name;
  contacts_tbl_str += " ("
    "uri TEXT,"
	  "first_name TEXT,"
	  "middle_initial TEXT,"
	  "last_name TEXT,"
	  "rank TEXT,"
	  "call_sign TEXT,"
	  "branch TEXT,"
	  "unit TEXT,"
	  "email TEXT,"
	  "phone TEXT,"
	  "photo BLOB,"
	  "insignia BLOB)";

  if (!this->createTable (contacts_tbl_str.c_str (), "contacts"))
    {
      return false;
    }

  std::string insert_str ("insert into ");
  insert_str += tbl_name;
  insert_str += " values (?,?,?,?,?,?,?,?,?,?,?,?)";

  int status =
	  sqlite3_prepare (db_, insert_str.c_str (), -1, &stmt_, 0);

  if (status != SQLITE_OK)
    {
      LOG_ERROR ("Private contact push - "
                 << "prep of sqlite statement failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

  const char *insert_type = "Private contact";

  bool good_binds =
    this->bind_text (1, pushData.uri, insert_type, "uri")
    && this->bind_text (2, info.first_name, insert_type, "first name")
    && this->bind_text (3, info.middle_initial, insert_type, "middle initial")
    && this->bind_text (4, info.last_name, insert_type, "last name")
    && this->bind_text (5, info.rank, insert_type, "rank")
    && this->bind_text (6, info.call_sign, insert_type, "call sign")
    && this->bind_text (7, info.branch, insert_type, "branch")
    && this->bind_text (8, info.unit, insert_type, "unit")
    && this->bind_text (9, info.email, insert_type, "email")
    && this->bind_text (10, info.phone, insert_type, "phone");

	if (good_binds)
	  {
      status = sqlite3_step (stmt_);

      if (status != SQLITE_DONE)
        {
          LOG_ERROR ("Private contact push - "
                     << "insert operation failed: "
                     << sqlite3_errmsg (db_));

          return false;
        }
    }

  return good_binds;
}

bool
DataStoreReceiver::pushGeneralData (const ammo::gateway::PushData &pushData)
{
  ACE_Time_Value tv (ACE_OS::gettimeofday ());

  int status =
	  sqlite3_prepare (db_,
			               "insert into data_table values (?,?,?,?,?,?)",
			               -1,
			               &stmt_,
			               0);

  if (status != SQLITE_OK)
    {
      LOG_ERROR ("Data push - "
                 << "prep of sqlite statement failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

  const char *insert_type = "Data";

  bool good_binds =
    this->bind_text (1, pushData.uri, insert_type, "URI")
    && this->bind_text (2, pushData.mimeType, insert_type, "data type")
    && this->bind_text (3, pushData.originUsername, insert_type, "origin user")
    && this->bind_int (4, tv.sec (), insert_type, "timestamp sec")
    && this->bind_int (5, tv.usec (), insert_type, "timestamp usec")
    && this->bind_blob (6,
                        pushData.data.data (),
                        pushData.data.length (),
                        insert_type,
                        "data");

  if (good_binds)
    {
      status = sqlite3_step (stmt_);

      if (status != SQLITE_DONE)
        {
          LOG_ERROR ("Data push - "
                     << "insert operation failed: "
                     << sqlite3_errmsg (db_));

          return false;
        }
    }

  return true;
}

bool
DataStoreReceiver::parseJson (const std::string &input,
                              Json::Value& root)
{
  Json::Reader jsonReader;
  bool parseSuccess = jsonReader.parse (input, root);

  if (!parseSuccess)
    {
      LOG_ERROR ("JSON parsing error:"
                 << jsonReader.getFormatedErrorMessages ());

      return parseSuccess;
    }

  LOG_DEBUG ("Parsed JSON: " << root.toStyledString ());
  return parseSuccess;
}

void
DataStoreReceiver::contactFromJson (const Json::Value &jsonRoot,
                                    PrivateContact &info)
{
  info.first_name = jsonRoot["first_name"].asString ();
  info.middle_initial = jsonRoot["middle_initial"].asString ();
  info.last_name = jsonRoot["last_name"].asString ();
  info.rank = jsonRoot["rank"].asString ();
  info.call_sign = jsonRoot["call_sign"].asString ();
  info.branch = jsonRoot["branch"].asString ();
  info.unit = jsonRoot["unit"].asString ();
  info.email = jsonRoot["email"].asString ();
  info.phone = jsonRoot["phone"].asString ();
}

bool
DataStoreReceiver::createTable (const char *tbl_string,
                                const char *msg)
{
  char *db_err = 0;

  sqlite3_exec (db_, tbl_string, 0, 0, &db_err);

  if (db_err != 0)
	  {
	    LOG_ERROR ("Data Store Service " << msg << " table - " << db_err);
			return false;
	  }

	LOG_DEBUG ("Data Store Service " << msg << " table opened successfully...");

  return true;
}

bool
DataStoreReceiver::bind_text (int column,
                              const std::string &text,
                              const char *push_type,
                              const char *column_name)
{
  // Must make sure that stmt_ is prepared before this call.
  int status =
	  sqlite3_bind_text (stmt_,
					             column,
					             text.c_str (),
					             text.length (),
					             SQLITE_STATIC);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
		             << column_name << " bind failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

	return true;
}

bool
DataStoreReceiver::bind_int (int column,
                             int val,
                             const char *push_type,
                             const char *column_name)
{
  // Must make sure that stmt_ is prepared before this call.
  int status = sqlite3_bind_int (stmt_, column, val);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
                 << column_name << " bind failed: "
                 << sqlite3_errmsg (db_));

      return false;
    }

  return true;
}

bool
DataStoreReceiver::bind_blob (int column,
                              const void *val,
                              int size,
                              const char *push_type,
                              const char *column_name)
{
  int status =
	  sqlite3_bind_blob (stmt_,
					             column,
					             val,
					             size,
					             SQLITE_STATIC);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
                 << column_name << " bind failed: "
                 << sqlite3_errmsg (db_));

      return false;
    }

  return true;
}

<commit_msg>Added debug output of query string on incoming pullRequest<commit_after>#include <sqlite3.h>
#include <algorithm>

#include "ace/OS_NS_sys_time.h"

#include "log.h"

#include "json/reader.h"
#include "json/value.h"

#include "DataStore.h"
#include "QueryHandlerFactory.h"
#include "QueryHandler.h"

#include "DataStoreConstants.h"

using namespace ammo::gateway;

DataStoreReceiver::DataStoreReceiver (void)
  : db_ (0),
    stmt_ (0)
{
}

DataStoreReceiver::~DataStoreReceiver (void)
{
  LOG_DEBUG ("Closing Data Store Service database...");

  sqlite3_close (db_);
}

void
DataStoreReceiver::onConnect (GatewayConnector * /* sender */)
{
}

void
DataStoreReceiver::onDisconnect (GatewayConnector * /* sender */)
{
}

void
DataStoreReceiver::onPushDataReceived (GatewayConnector * /* sender */,
                                       PushData &pushData)
{
  LOG_TRACE ("Received " << pushData);
  bool good_data_store = true;

  if (pushData.mimeType.find (PVT_CONTACTS_DATA_TYPE) == 0)
    {
      good_data_store = this->pushContactData (pushData);
    }
  else
    {
      good_data_store = this->pushGeneralData (pushData);
    }

	if (good_data_store)
	  {
      LOG_DEBUG ("data store successful");
    }
}

void
DataStoreReceiver::onPullRequestReceived (GatewayConnector *sender,
                                          PullRequest &pullReq)
{
  LOG_TRACE ("pull request received");

  if (sender == 0)
    {
      LOG_WARN ("Sender is null, no responses will be sent");
    }

  LOG_DEBUG ("Data type: " << pullReq.mimeType);
  LOG_DEBUG ("query string: " << pullReq.query);

  QueryHandlerFactory factory;
  QueryHandler *handler = factory.createHandler (db_, sender, pullReq);

  handler->handleQuery ();

  delete handler;
  handler = 0;
}

void
DataStoreReceiver::db_filepath (const std::string &path)
{
  db_filepath_ = path;
}

bool
DataStoreReceiver::init (void)
{
  std::string filepath (db_filepath_);
  filepath += "DataStore_db.sql3";

//  LOG_DEBUG ("full path = " << filepath.c_str ());

  int status = sqlite3_open (filepath.c_str (), &db_);

  if (status != 0)
    {
      LOG_ERROR ("Data Store Service - " << sqlite3_errmsg (db_));
      return false;
    }

  const char *data_tbl_str =
	  "CREATE TABLE IF NOT EXISTS data_table ("
	  "uri TEXT,"
	  "mime_type TEXT,"
	  "origin_user TEXT,"
	  "tv_sec INTEGER NOT NULL,"
	  "tv_usec INTEGER,"
	  "data BLOB)";

  return this->createTable (data_tbl_str, "data");
}

bool
DataStoreReceiver::pushContactData (const ammo::gateway::PushData &pushData)
{
  Json::Value root;

  if (!this->parseJson (pushData.data, root))
    {
      return false;
    }

  PrivateContact info;
  this->contactFromJson (root, info);

  // SQL table names can't contain '.', so we append the chars of
  // the arg we use for the table name to the query string,
  // while replacing '.' with '_'.
  std::string tbl_name = pushData.originUsername;
  std::replace_if (tbl_name.begin (),
                   tbl_name.end (),
                   std::bind2nd (std::equal_to<char> (), '.'),
                   '_');

  // 2011-06-21 - not using the last 2 columns at this point.
	std::string contacts_tbl_str ("CREATE TABLE IF NOT EXISTS ");
	contacts_tbl_str += tbl_name;
  contacts_tbl_str += " ("
    "uri TEXT,"
	  "first_name TEXT,"
	  "middle_initial TEXT,"
	  "last_name TEXT,"
	  "rank TEXT,"
	  "call_sign TEXT,"
	  "branch TEXT,"
	  "unit TEXT,"
	  "email TEXT,"
	  "phone TEXT,"
	  "photo BLOB,"
	  "insignia BLOB)";

  if (!this->createTable (contacts_tbl_str.c_str (), "contacts"))
    {
      return false;
    }

  std::string insert_str ("insert into ");
  insert_str += tbl_name;
  insert_str += " values (?,?,?,?,?,?,?,?,?,?,?,?)";

  int status =
	  sqlite3_prepare (db_, insert_str.c_str (), -1, &stmt_, 0);

  if (status != SQLITE_OK)
    {
      LOG_ERROR ("Private contact push - "
                 << "prep of sqlite statement failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

  const char *insert_type = "Private contact";

  bool good_binds =
    this->bind_text (1, pushData.uri, insert_type, "uri")
    && this->bind_text (2, info.first_name, insert_type, "first name")
    && this->bind_text (3, info.middle_initial, insert_type, "middle initial")
    && this->bind_text (4, info.last_name, insert_type, "last name")
    && this->bind_text (5, info.rank, insert_type, "rank")
    && this->bind_text (6, info.call_sign, insert_type, "call sign")
    && this->bind_text (7, info.branch, insert_type, "branch")
    && this->bind_text (8, info.unit, insert_type, "unit")
    && this->bind_text (9, info.email, insert_type, "email")
    && this->bind_text (10, info.phone, insert_type, "phone");

	if (good_binds)
	  {
      status = sqlite3_step (stmt_);

      if (status != SQLITE_DONE)
        {
          LOG_ERROR ("Private contact push - "
                     << "insert operation failed: "
                     << sqlite3_errmsg (db_));

          return false;
        }
    }

  return good_binds;
}

bool
DataStoreReceiver::pushGeneralData (const ammo::gateway::PushData &pushData)
{
  ACE_Time_Value tv (ACE_OS::gettimeofday ());

  int status =
	  sqlite3_prepare (db_,
			               "insert into data_table values (?,?,?,?,?,?)",
			               -1,
			               &stmt_,
			               0);

  if (status != SQLITE_OK)
    {
      LOG_ERROR ("Data push - "
                 << "prep of sqlite statement failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

  const char *insert_type = "Data";

  bool good_binds =
    this->bind_text (1, pushData.uri, insert_type, "URI")
    && this->bind_text (2, pushData.mimeType, insert_type, "data type")
    && this->bind_text (3, pushData.originUsername, insert_type, "origin user")
    && this->bind_int (4, tv.sec (), insert_type, "timestamp sec")
    && this->bind_int (5, tv.usec (), insert_type, "timestamp usec")
    && this->bind_blob (6,
                        pushData.data.data (),
                        pushData.data.length (),
                        insert_type,
                        "data");

  if (good_binds)
    {
      status = sqlite3_step (stmt_);

      if (status != SQLITE_DONE)
        {
          LOG_ERROR ("Data push - "
                     << "insert operation failed: "
                     << sqlite3_errmsg (db_));

          return false;
        }
    }

  return true;
}

bool
DataStoreReceiver::parseJson (const std::string &input,
                              Json::Value& root)
{
  Json::Reader jsonReader;
  bool parseSuccess = jsonReader.parse (input, root);

  if (!parseSuccess)
    {
      LOG_ERROR ("JSON parsing error:"
                 << jsonReader.getFormatedErrorMessages ());

      return parseSuccess;
    }

  LOG_DEBUG ("Parsed JSON: " << root.toStyledString ());
  return parseSuccess;
}

void
DataStoreReceiver::contactFromJson (const Json::Value &jsonRoot,
                                    PrivateContact &info)
{
  info.first_name = jsonRoot["first_name"].asString ();
  info.middle_initial = jsonRoot["middle_initial"].asString ();
  info.last_name = jsonRoot["last_name"].asString ();
  info.rank = jsonRoot["rank"].asString ();
  info.call_sign = jsonRoot["call_sign"].asString ();
  info.branch = jsonRoot["branch"].asString ();
  info.unit = jsonRoot["unit"].asString ();
  info.email = jsonRoot["email"].asString ();
  info.phone = jsonRoot["phone"].asString ();
}

bool
DataStoreReceiver::createTable (const char *tbl_string,
                                const char *msg)
{
  char *db_err = 0;

  sqlite3_exec (db_, tbl_string, 0, 0, &db_err);

  if (db_err != 0)
	  {
	    LOG_ERROR ("Data Store Service " << msg << " table - " << db_err);
			return false;
	  }

	LOG_DEBUG ("Data Store Service " << msg << " table opened successfully...");

  return true;
}

bool
DataStoreReceiver::bind_text (int column,
                              const std::string &text,
                              const char *push_type,
                              const char *column_name)
{
  // Must make sure that stmt_ is prepared before this call.
  int status =
	  sqlite3_bind_text (stmt_,
					             column,
					             text.c_str (),
					             text.length (),
					             SQLITE_STATIC);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
		             << column_name << " bind failed: "
		             << sqlite3_errmsg (db_));

      return false;
    }

	return true;
}

bool
DataStoreReceiver::bind_int (int column,
                             int val,
                             const char *push_type,
                             const char *column_name)
{
  // Must make sure that stmt_ is prepared before this call.
  int status = sqlite3_bind_int (stmt_, column, val);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
                 << column_name << " bind failed: "
                 << sqlite3_errmsg (db_));

      return false;
    }

  return true;
}

bool
DataStoreReceiver::bind_blob (int column,
                              const void *val,
                              int size,
                              const char *push_type,
                              const char *column_name)
{
  int status =
	  sqlite3_bind_blob (stmt_,
					             column,
					             val,
					             size,
					             SQLITE_STATIC);

  if (status != SQLITE_OK)
    {
      LOG_ERROR (push_type << " push - "
                 << column_name << " bind failed: "
                 << sqlite3_errmsg (db_));

      return false;
    }

  return true;
}

<|endoftext|>


<commit_before>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2015 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <cstdint>

namespace sfe
{
    namespace
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        void ass_log(int ass_level, const char *fmt, va_list args, void *data)
        {
            char buffer[4096];

            vsnprintf(buffer, sizeof(buffer), fmt, args);
            sfeLogDebug(buffer);
        }
#endif
    }

    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer),
        m_delegate(delegate),
        m_library(nullptr),
        m_renderer(nullptr),
        m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB) == 0)
        {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log, nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

            ass_set_fonts(m_renderer, NULL, NULL , 1, NULL, 1);
            ass_set_margins(m_renderer, 10, 0, 0, 0);

            ass_process_codec_private(m_track, reinterpret_cast<char*>(m_stream->codec->subtitle_header), m_stream->codec->subtitle_header_size);
#else
            throw std::runtime_error("Non-bitmap subtitle stream detected but ASS support is disabled. Cannot use stream.");
#endif
		}
    }

    SubtitleStream::~SubtitleStream()
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}
#endif
    }

    void SubtitleStream::setRenderingFrame(int width, int height)
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        ass_set_frame_size(m_renderer, width, height);
#endif
    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> iter = m_pendingSubtitles.front();

#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
                //this is the case for ass subtitles
                if (iter->type==ASS)
                {
                    int change = 0;
                    ASS_Image* img = ass_render_frame(m_renderer, m_track, m_timer->getOffset().asMilliseconds(), &change);

                    if (change)
                    {

                        for (; img; img->next)
                        {
                            uint8_t     r = img->color >> 24,
                                        g = img->color >> 16 & 255,
                                        b = img->color >> 8 & 255,
                                        a = 255 - (img->color & 255);

                            sf::Image buffer;
                            buffer.create(img->w, img->h);

                            iter->positions.push_back(sf::Vector2i(img->dst_x, img->dst_y));

                            for (int y = 0; y < img->h; ++y)
                            {
                                const unsigned char *map = img->bitmap + y * img->stride;

                                for (int x = 0; x < img->w; ++x)
                                {
                                    uint8_t alpha = ((unsigned)a * *map++)/255;
                                    buffer.setPixel(x, y, sf::Color(r,g,b,alpha));
                                }
                            }

                            img = img->next;

                            iter->sprites.push_back(sf::Sprite());
                            iter->textures.push_back(sf::Texture());

                            sf::Sprite& sprite = iter->sprites.back();
                            sf::Texture& texture = iter->textures.back();

                            texture.create(buffer.getSize().x, buffer.getSize().y);
                            texture.update(buffer);
                            texture.setSmooth(true);

                            sprite.setTexture(texture);
                        }
                    }
                }
#endif

                m_delegate.didUpdateSubtitle(*this, iter->sprites, iter->positions);
                m_visibleSubtitles.push_back(iter);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded,m_track);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {
            AVSubtitleRect* subItem = sub->rects[i];

            if (subItem->type == SUBTITLE_BITMAP)
            {
                type = BITMAP;
                sprites.push_back(sf::Sprite());
                textures.push_back(sf::Texture());

                sf::Sprite& sprite = sprites.back();
                sf::Texture& texture = textures.back();

                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
            else
            {
                type = ASS;
                ass_process_data(track, subItem->ass, strlen(subItem->ass));

                succeeded = true;
            }
#endif
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
        m_pendingSubtitles.clear();
        m_visibleSubtitles.clear();
    }

    bool SubtitleStream::fastForward(sf::Time targetPosition)
    {
        while(hasPackets())
        {
            onGetData();
        }

		std::list< std::shared_ptr<SubtitleData>>::iterator it = m_visibleSubtitles.begin();
		while (it != m_visibleSubtitles.end())
		{
			//erase subs that are deleted before the targetPosition
			if (it->get()->end<targetPosition)
				it = m_visibleSubtitles.erase(it);
			else
				++it;
		}

		it = m_pendingSubtitles.begin();
		while (it != m_pendingSubtitles.end())
		{
			//erase subs that are deleted before the targetPosition
			if (it->get()->end<targetPosition)
				it = m_pendingSubtitles.erase(it);
			else
				++it;
		}

        return true;
	}
}
<commit_msg>#7 Cleaning<commit_after>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2015 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <cstdint>

namespace sfe
{
    namespace
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        void ass_log(int ass_level, const char *fmt, va_list args, void *data)
        {
            char buffer[4096];

            vsnprintf(buffer, sizeof(buffer), fmt, args);
            sfeLogDebug(buffer);
        }
#endif
    }

    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer),
        m_delegate(delegate),
        m_library(nullptr),
        m_renderer(nullptr),
        m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB) == 0)
        {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log, nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

            ass_set_fonts(m_renderer, NULL, NULL , 1, NULL, 1);
            ass_set_margins(m_renderer, 10, 0, 0, 0);

            ass_process_codec_private(m_track, reinterpret_cast<char*>(m_stream->codec->subtitle_header),
                                      m_stream->codec->subtitle_header_size);
#else
            throw std::runtime_error("Non-bitmap subtitle stream detected but ASS support is disabled. Cannot use stream.");
#endif
		}
    }

    SubtitleStream::~SubtitleStream()
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}
#endif
    }

    void SubtitleStream::setRenderingFrame(int width, int height)
    {
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
        ass_set_frame_size(m_renderer, width, height);
#endif
    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_pendingSubtitles.front();

#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
                //this is the case for ass subtitles
                if (subtitle->type == ASS)
                {
                    int changed = 0;
                    ASS_Image* layer = ass_render_frame(m_renderer, m_track,
                                                      m_timer->getOffset().asMilliseconds(),
                                                      &changed);

                    if (changed)
                    {

                        for (; layer; layer = layer->next)
                        {
                            if (layer->w == 0 || layer->h == 0)
                                continue;

                            const uint8_t red   =   layer->color >> 24;
                            const uint8_t green =   layer->color >> 16 & 255;
                            const uint8_t blue  =   layer->color >> 8 & 255;
                            const uint8_t alpha =   255 - (layer->color & 255);

                            sf::Image image;
                            image.create(layer->w, layer->h);

                            for (int y = 0; y < layer->h; ++y)
                            {
                                const unsigned char *map = layer->bitmap + y * layer->stride;

                                for (int x = 0; x < layer->w; ++x)
                                {
                                    const uint8_t mappedAlpha = ((unsigned)alpha * *map++)/255;
                                    image.setPixel(x, y, sf::Color(red, green, blue, mappedAlpha));
                                }
                            }

                            subtitle->positions.push_back(sf::Vector2i(layer->dst_x, layer->dst_y));
                            subtitle->sprites.push_back(sf::Sprite());
                            subtitle->textures.push_back(sf::Texture());

                            sf::Sprite& sprite = subtitle->sprites.back();
                            sf::Texture& texture = subtitle->textures.back();

                            texture.loadFromImage(image);
                            texture.setSmooth(true);
                            sprite.setTexture(texture);
                        }
                    }
                }
#endif

                m_delegate.didUpdateSubtitle(*this, subtitle->sprites, subtitle->positions);
                m_visibleSubtitles.push_back(subtitle);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded,m_track);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {
            AVSubtitleRect* subItem = sub->rects[i];

            if (subItem->type == SUBTITLE_BITMAP)
            {
                type = BITMAP;
                sprites.push_back(sf::Sprite());
                textures.push_back(sf::Texture());

                sf::Sprite& sprite = sprites.back();
                sf::Texture& texture = textures.back();

                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
#ifdef SFEMOVIE_ENABLE_ASS_SUBTITLES
            else
            {
                type = ASS;
                ass_process_data(track, subItem->ass, strlen(subItem->ass));

                succeeded = true;
            }
#endif
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
        m_pendingSubtitles.clear();
        m_visibleSubtitles.clear();
    }

    bool SubtitleStream::fastForward(sf::Time targetPosition)
    {
        while(hasPackets())
        {
            onGetData();
        }

		std::list< std::shared_ptr<SubtitleData>>::iterator it = m_visibleSubtitles.begin();
		while (it != m_visibleSubtitles.end())
		{
			//erase subs that are deleted before the targetPosition
			if (it->get()->end<targetPosition)
				it = m_visibleSubtitles.erase(it);
			else
				++it;
		}

		it = m_pendingSubtitles.begin();
		while (it != m_pendingSubtitles.end())
		{
			//erase subs that are deleted before the targetPosition
			if (it->get()->end<targetPosition)
				it = m_pendingSubtitles.erase(it);
			else
				++it;
		}

        return true;
	}
}
<|endoftext|>


<commit_before>#include "TMControlGraph.h"

void TMControlGraph::operator+= (const pair<string, TMCommand>& cmd) throw (CommandAlreadyExist) {
    addNewCmd(cmd);
}

void TMControlGraph::addNewCmd(const pair<string, TMCommand>& cmd) throw (CommandAlreadyExist) {
    string commandName (cmd.first);
    TMCommand commandBody (cmd.second);
    TMStringCharPair cmdNameAndFromState (commandName, commandBody.getFromState());
    checkIfIsUnique(cmdNameAndFromState);
    appendCmd(cmdNameAndFromState, commandBody);
}

void TMControlGraph::checkIfIsUnique(const TMStringCharPair& cmdNameAndFromState) throw (CommandAlreadyExist) {

}

void TMControlGraph::appendCmd(TMStringCharPair& cmdNameAndFromState, TMCommand& commandBody) {
    graph[cmdNameAndFromState] = commandBody;
}
<commit_msg>[ADD] checking if command already exist<commit_after>#include "TMControlGraph.h"

void TMControlGraph::operator+= (const pair<string, TMCommand>& cmd) throw (CommandAlreadyExist) {
    addNewCmd(cmd);
}

void TMControlGraph::addNewCmd(const pair<string, TMCommand>& cmd) throw (CommandAlreadyExist) {
    string commandName (cmd.first);
    TMCommand commandBody (cmd.second);
    TMStringCharPair cmdNameAndFromState (commandName, commandBody.getFromState());
    checkIfIsUnique(cmdNameAndFromState);
    appendCmd(cmdNameAndFromState, commandBody);
}

void TMControlGraph::checkIfIsUnique(const TMStringCharPair& cmdNameAndFromState) throw (CommandAlreadyExist) {
    size_t numberOfOccurences = graph.count(cmdNameAndFromState);
    if (numberOfOccurences >= 1) throw CommandAlreadyExist();
}

void TMControlGraph::appendCmd(TMStringCharPair& cmdNameAndFromState, TMCommand& commandBody) {
    graph[cmdNameAndFromState] = commandBody;
}
<|endoftext|>