<commit_before>/*  Sirikata
 *  main.cpp
 *
 *  Copyright (c) 2008, Daniel Reiter Horn
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <oh/Platform.hpp>
#include <util/RoutableMessageHeader.hpp>
#include <options/Options.hpp>
#include <util/PluginManager.hpp>
#include <oh/SimulationFactory.hpp>

#include <task/EventManager.hpp>
#include <task/WorkQueue.hpp>
#include "CDNConfig.hpp"

#include <oh/ObjectHost.hpp>
#include <oh/LightInfo.hpp>
#include <oh/TopLevelSpaceConnection.hpp>
#include <oh/SpaceConnection.hpp>
#include <oh/HostedObject.hpp>
#include <oh/SpaceIDMap.hpp>
#include <network/IOServiceFactory.hpp>
#include <ObjectHost_Sirikata.pbj.hpp>

namespace Sirikata {

using Task::GenEventManager;
using Transfer::TransferManager;

OptionValue *cdnConfigFile;
OptionValue *floatExcept;
InitializeGlobalOptions main_options("",
//    simulationPlugins=new OptionValue("simulationPlugins","ogregraphics",OptionValueType<String>(),"List of plugins that handle simulation."),
    cdnConfigFile=new OptionValue("cdnConfig","cdn = ($import=cdn.txt)",OptionValueType<String>(),"CDN configuration."),
    floatExcept=new OptionValue("sigfpe","false",OptionValueType<bool>(),"Enable floating point exceptions"),
    NULL
);

std::string cut(const std::string &source, std::string::size_type start, std::string::size_type end) {
	using namespace std;
    while (isspace(source[start]) && start < end) {
        ++start;
    }
    while (end > start && isspace(source[end-1])) {
        --end;
    }
    return source.substr(start,end-start);
}

namespace {
typedef std::map<OptionMapPtr, std::string> GlobalMap;
std::ostream &display (std::ostream &os, const OptionMap &om, const GlobalMap &globals, int level) {
    int numspaces = level*4;
    for (OptionMap::const_iterator iter = om.begin(); iter != om.end(); ++iter) {
        OptionMapPtr child = (*iter).second;
        os << std::string(numspaces, ' ');
        os << (*iter).first << " = ";
        GlobalMap::const_iterator globaliter = globals.find(child);
        if (level>0 && globaliter != globals.end()) {
            os << "$" << (*globaliter).second;
        } else {
            os << child->getValue();
            if (!child->empty()) {
                os << "(" << std::endl;
                display(os,*child,globals,level+1);
                os << std::string(numspaces, ' ');
                os << ")";
            }
        }
        os << std::endl;
    }
    return os;
}
}
std::ostream &operator<< (std::ostream &os, const OptionMap &om) {
    GlobalMap globals;
    for (OptionMap::const_iterator iter = om.begin(); iter != om.end(); ++iter) {
        globals[(*iter).second] = (*iter).first;
    }
    return display(os, om, globals, 0);
}

enum ParseState {KEYSTATE, EQSTATE, VALUESTATE, NUMSTATES };

void handleCommand(const std::string &input, const OptionMapPtr &globalvariables, const OptionMapPtr &options, std::string::size_type &pos, const std::string &key, const std::string &value) {
    if (key == "$import") {
        std::string::size_type slash = value.rfind('/');
        std::string::size_type backslash = value.rfind('\\');
        if (slash == std::string::npos && backslash ==std::string::npos) {
            std::string fname = "./" + value;
            if (value.find(".txt")!=std::string::npos) {
                FILE *fp = NULL;
                for (int i = 0; i < 4 && fp == NULL; i++) {
                    fp = fopen(fname.c_str(),"rt");
                    fname = "./."+fname;
                }
                std::string str;
                while (fp && !feof(fp)) {
                    char buf[1024];
                    int numread = fread(buf, 1, 1024, fp);
                    if (numread <= 0) {
                        break;
                    }
                    str += std::string(buf, buf+numread);
                }
                if (fp) {
                    fclose(fp);
                } else {
                    SILOG(main,error,"Configuration file "<<value<<" does not exist");
                }
                std::string::size_type subpos = 0;
                // current level becomes the global level.
                parseConfig(str, options, options, subpos);
            }
        }
    } else {
        SILOG(main,error,"Unknown command "<<key<<"("<<value<<")");
    }
}

void parseConfig(
        const std::string &input,
        const OptionMapPtr &globalvariables,
        const OptionMapPtr &options,
        std::string::size_type &pos)
{
    std::string::size_type len = input.length();
    std::string key;
    std::string::size_type beginpos = pos;
    OptionMapPtr currentValue;
    /* states:
       0 = Key, looking for '='
       1 = Looking for value, but have not encountered whitespace.
       2 = Value, will end at next whitespace character.
    */
    ParseState state = KEYSTATE;
    for (; pos <= len; ++pos) {
        char ch;
        if (pos >= len) {
            ch = ')';
        } else {
            ch = input[pos];
        }
        if (state==KEYSTATE && ch == '#') {
            /* comment up to ')' */
            for (; pos < len; ++pos) {
                if (input[pos]=='\n') break;
            }
            beginpos = pos;
        } else if (ch == '(' || ch==')' || (state != KEYSTATE && isspace(ch))) {
            if (state == VALUESTATE) {
                std::string value(cut(input, beginpos, pos));
                if (value.length()) {
                    OptionMapPtr toInsert;
                    if (value[0]=='$') {
                        toInsert = (*globalvariables).get(value.substr(1));
                        if (!toInsert) {
                            toInsert = OptionMapPtr(new OptionMap);
                            (*globalvariables).put(value.substr(1), toInsert);
                        }
                    }
                    if (key.length() && key[0]=='$') {
                        handleCommand(input,globalvariables,options,pos,key,value);
                    } else {
                        if (!toInsert) {
                            toInsert = (*options).get(key);
                            if (!toInsert) {
                                toInsert = OptionMapPtr(new OptionMap(value));
                            }
                        }
                        currentValue = options->put(key, toInsert);
                    }
                    state = KEYSTATE;
                }
                beginpos = pos+1;
           }
            if (ch == '(') {
                if (!currentValue) {
                    currentValue = options->get(key);
                    if (!currentValue) {
                        currentValue = options->put(key, OptionMapPtr(new OptionMap));
                    }
                }
                /* Note: If you have KEY = $variable ( key1=value1 key2=value2 ) will add key1 and key2 to variable as well. */
                pos++;
                parseConfig(input, globalvariables, currentValue, pos);
                beginpos = pos+1;
                state = KEYSTATE;
            } else if (ch == ')') {
                break;
            }
        } else if (state == KEYSTATE && ch=='=') {
            key = cut(input, beginpos, pos);
            state = EQSTATE;
            beginpos = pos+1;
            currentValue = OptionMapPtr();
        } else if (state == EQSTATE && !isspace(ch)) {
            state = VALUESTATE;
        }
    }
}

}

#ifdef __GNUC__
#include <fenv.h>
#endif

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

    int myargc = argc+2;
    const char **myargv = new const char*[myargc];
    memcpy(myargv, argv, argc*sizeof(const char*));
    myargv[argc] = "--moduleloglevel";
    myargv[argc+1] = "transfer=fatal,ogre=fatal,task=fatal,resource=fatal";

    using namespace Sirikata;
    PluginManager plugins;
    plugins.load ( DynamicLibrary::filename("ogregraphics") );
    plugins.load ( DynamicLibrary::filename("bulletphysics") );
    OptionSet::getOptions ( "" )->parse ( myargc,myargv );

#ifdef __GNUC__
    if (floatExcept->as<bool>()) {
        feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
    }
#endif

    OptionMapPtr transferOptions (new OptionMap);
    {
        std::string contents(cdnConfigFile->as<String>());
        std::string::size_type pos(0);
        parseConfig(contents, transferOptions, transferOptions, pos);
        std::cout << *transferOptions;
    }

    initializeProtocols();

    Network::IOService *ioServ = Network::IOServiceFactory::makeIOService();

    SpaceID mainSpace(UUID("12345678-1111-1111-1111-DEFA01759ACE",UUID::HumanReadable()));
    SpaceIDMap *spaceMap = new SpaceIDMap;
    spaceMap->insert(mainSpace, Network::Address("127.0.0.1","5943"));

    ObjectHost *oh = new ObjectHost(spaceMap, ioServ);
    {//to deallocate HostedObjects before armageddon
    HostedObjectPtr firstObject (HostedObject::construct<HostedObject>(oh));
    firstObject->initializeConnect(
            UUID::random(),
            Location(Vector3d(0, ((double)(time(NULL)%10)) - 5 , 0), Quaternion::identity(),
                     Vector3f(0.2,0,0), Vector3f(0,0,1), 0.),
            "meru://daniel@/cube.mesh",
            BoundingSphere3f(Vector3f::nil(),1),
            NULL,
            mainSpace);
    firstObject->setScale(Vector3f(3,3,3));

    HostedObjectPtr secondObject (HostedObject::construct<HostedObject>(oh));
    secondObject->initializeConnect(
        UUID::random(),
        Location(Vector3d(0,0,25), Quaternion::identity(),
                 Vector3f(0.1,0,0), Vector3f(0,0,1), 0.),
        "",
        BoundingSphere3f(Vector3f::nil(),0),
        NULL,
        mainSpace);

    HostedObjectPtr thirdObject (HostedObject::construct<HostedObject>(oh));
    {
        LightInfo li;
        li.setLightDiffuseColor(Color(0.976471, 0.992157, 0.733333));
        li.setLightAmbientColor(Color(.24,.25,.18));
        li.setLightSpecularColor(Color(0,0,0));
        li.setLightShadowColor(Color(0,0,0));
        li.setLightPower(1.0);
        li.setLightRange(75);
        li.setLightFalloff(1,0,0.03);
        li.setLightSpotlightCone(30,40,1);
        li.setCastsShadow(true);
        thirdObject->initializeConnect(
            UUID::random(),
            Location(Vector3d(10,0,10), Quaternion::identity(),
                     Vector3f::nil(), Vector3f(0,0,1), 0.),
            "",
            BoundingSphere3f(Vector3f::nil(),0),
            &li,
            mainSpace);
    }
    ProxyManager *provider = oh->getProxyManager(mainSpace);

    Task::WorkQueue *workQueue = new Task::LockFreeWorkQueue;
    Task::GenEventManager *eventManager = new Task::GenEventManager(workQueue);
    TransferManager *tm;
    try {
        tm = initializeTransferManager((*transferOptions)["cdn"], eventManager);
    } catch (OptionDoesNotExist &err) {
        SILOG(input,fatal,"Fatal Error: Failed to load CDN config: " << err.what());
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
        return 1;
    }
    OptionSet::getOptions("")->parse(myargc,myargv);
    String graphicsCommandArguments;
    {
        std::ostringstream os;
        os << "--transfermanager=" << tm << " ";
        os << "--eventmanager=" << eventManager << " ";
        os << "--workqueue=" << workQueue << " ";
        graphicsCommandArguments = os.str();
    }
    if (!provider) {
        SILOG(cppoh,error,"Failed to get TopLevelSpaceConnection for main space "<<mainSpace);
    }
    String graphicsPluginName ( "ogregraphics" );
    String physicsPluginName ( "bulletphysics" );
    SILOG(cppoh,error,"dbm: initializing graphics");
    TimeSteppedSimulation *graphicsSystem=
        SimulationFactory::getSingleton()
        .getConstructor ( graphicsPluginName ) ( provider,graphicsCommandArguments );
    SILOG(cppoh,error,"dbm: initializing physics");
    TimeSteppedSimulation *physicsSystem=
        SimulationFactory::getSingleton()
        .getConstructor ( physicsPluginName ) ( provider,graphicsCommandArguments );
    if (!physicsSystem) {
        SILOG(cppoh,error,"physicsSystem NULL!");
    }
    else {
        SILOG(cppoh,error,"physicsSystem: " << std::hex << (unsigned long)physicsSystem);
    }
    if ( graphicsSystem ) {
        while ( graphicsSystem->tick() ) {
            physicsSystem->tick();
            Network::IOServiceFactory::pollService(ioServ);
        }
    } else {
        SILOG(cppoh,error,"Fatal Error: Unable to load OGRE Graphics plugin. The PATH environment variable is ignored, so make sure you have copied the DLLs from dependencies/ogre/bin/ into the current directory. Sorry about this!");
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
    }
    delete graphicsSystem;

    delete eventManager;
    delete workQueue;
    }
    plugins.gc();
    SimulationFactory::destroy();

    delete oh;
    Network::IOServiceFactory::destroyIOService(ioServ);
    delete spaceMap;

    delete []myargv;

    return 0;
}
<commit_msg>Mac does not define feenableexcept()<commit_after>/*  Sirikata
 *  main.cpp
 *
 *  Copyright (c) 2008, Daniel Reiter Horn
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <oh/Platform.hpp>
#include <util/RoutableMessageHeader.hpp>
#include <options/Options.hpp>
#include <util/PluginManager.hpp>
#include <oh/SimulationFactory.hpp>

#include <task/EventManager.hpp>
#include <task/WorkQueue.hpp>
#include "CDNConfig.hpp"

#include <oh/ObjectHost.hpp>
#include <oh/LightInfo.hpp>
#include <oh/TopLevelSpaceConnection.hpp>
#include <oh/SpaceConnection.hpp>
#include <oh/HostedObject.hpp>
#include <oh/SpaceIDMap.hpp>
#include <network/IOServiceFactory.hpp>
#include <ObjectHost_Sirikata.pbj.hpp>

namespace Sirikata {

using Task::GenEventManager;
using Transfer::TransferManager;

OptionValue *cdnConfigFile;
OptionValue *floatExcept;
InitializeGlobalOptions main_options("",
//    simulationPlugins=new OptionValue("simulationPlugins","ogregraphics",OptionValueType<String>(),"List of plugins that handle simulation."),
    cdnConfigFile=new OptionValue("cdnConfig","cdn = ($import=cdn.txt)",OptionValueType<String>(),"CDN configuration."),
    floatExcept=new OptionValue("sigfpe","false",OptionValueType<bool>(),"Enable floating point exceptions"),
    NULL
);

std::string cut(const std::string &source, std::string::size_type start, std::string::size_type end) {
	using namespace std;
    while (isspace(source[start]) && start < end) {
        ++start;
    }
    while (end > start && isspace(source[end-1])) {
        --end;
    }
    return source.substr(start,end-start);
}

namespace {
typedef std::map<OptionMapPtr, std::string> GlobalMap;
std::ostream &display (std::ostream &os, const OptionMap &om, const GlobalMap &globals, int level) {
    int numspaces = level*4;
    for (OptionMap::const_iterator iter = om.begin(); iter != om.end(); ++iter) {
        OptionMapPtr child = (*iter).second;
        os << std::string(numspaces, ' ');
        os << (*iter).first << " = ";
        GlobalMap::const_iterator globaliter = globals.find(child);
        if (level>0 && globaliter != globals.end()) {
            os << "$" << (*globaliter).second;
        } else {
            os << child->getValue();
            if (!child->empty()) {
                os << "(" << std::endl;
                display(os,*child,globals,level+1);
                os << std::string(numspaces, ' ');
                os << ")";
            }
        }
        os << std::endl;
    }
    return os;
}
}
std::ostream &operator<< (std::ostream &os, const OptionMap &om) {
    GlobalMap globals;
    for (OptionMap::const_iterator iter = om.begin(); iter != om.end(); ++iter) {
        globals[(*iter).second] = (*iter).first;
    }
    return display(os, om, globals, 0);
}

enum ParseState {KEYSTATE, EQSTATE, VALUESTATE, NUMSTATES };

void handleCommand(const std::string &input, const OptionMapPtr &globalvariables, const OptionMapPtr &options, std::string::size_type &pos, const std::string &key, const std::string &value) {
    if (key == "$import") {
        std::string::size_type slash = value.rfind('/');
        std::string::size_type backslash = value.rfind('\\');
        if (slash == std::string::npos && backslash ==std::string::npos) {
            std::string fname = "./" + value;
            if (value.find(".txt")!=std::string::npos) {
                FILE *fp = NULL;
                for (int i = 0; i < 4 && fp == NULL; i++) {
                    fp = fopen(fname.c_str(),"rt");
                    fname = "./."+fname;
                }
                std::string str;
                while (fp && !feof(fp)) {
                    char buf[1024];
                    int numread = fread(buf, 1, 1024, fp);
                    if (numread <= 0) {
                        break;
                    }
                    str += std::string(buf, buf+numread);
                }
                if (fp) {
                    fclose(fp);
                } else {
                    SILOG(main,error,"Configuration file "<<value<<" does not exist");
                }
                std::string::size_type subpos = 0;
                // current level becomes the global level.
                parseConfig(str, options, options, subpos);
            }
        }
    } else {
        SILOG(main,error,"Unknown command "<<key<<"("<<value<<")");
    }
}

void parseConfig(
        const std::string &input,
        const OptionMapPtr &globalvariables,
        const OptionMapPtr &options,
        std::string::size_type &pos)
{
    std::string::size_type len = input.length();
    std::string key;
    std::string::size_type beginpos = pos;
    OptionMapPtr currentValue;
    /* states:
       0 = Key, looking for '='
       1 = Looking for value, but have not encountered whitespace.
       2 = Value, will end at next whitespace character.
    */
    ParseState state = KEYSTATE;
    for (; pos <= len; ++pos) {
        char ch;
        if (pos >= len) {
            ch = ')';
        } else {
            ch = input[pos];
        }
        if (state==KEYSTATE && ch == '#') {
            /* comment up to ')' */
            for (; pos < len; ++pos) {
                if (input[pos]=='\n') break;
            }
            beginpos = pos;
        } else if (ch == '(' || ch==')' || (state != KEYSTATE && isspace(ch))) {
            if (state == VALUESTATE) {
                std::string value(cut(input, beginpos, pos));
                if (value.length()) {
                    OptionMapPtr toInsert;
                    if (value[0]=='$') {
                        toInsert = (*globalvariables).get(value.substr(1));
                        if (!toInsert) {
                            toInsert = OptionMapPtr(new OptionMap);
                            (*globalvariables).put(value.substr(1), toInsert);
                        }
                    }
                    if (key.length() && key[0]=='$') {
                        handleCommand(input,globalvariables,options,pos,key,value);
                    } else {
                        if (!toInsert) {
                            toInsert = (*options).get(key);
                            if (!toInsert) {
                                toInsert = OptionMapPtr(new OptionMap(value));
                            }
                        }
                        currentValue = options->put(key, toInsert);
                    }
                    state = KEYSTATE;
                }
                beginpos = pos+1;
           }
            if (ch == '(') {
                if (!currentValue) {
                    currentValue = options->get(key);
                    if (!currentValue) {
                        currentValue = options->put(key, OptionMapPtr(new OptionMap));
                    }
                }
                /* Note: If you have KEY = $variable ( key1=value1 key2=value2 ) will add key1 and key2 to variable as well. */
                pos++;
                parseConfig(input, globalvariables, currentValue, pos);
                beginpos = pos+1;
                state = KEYSTATE;
            } else if (ch == ')') {
                break;
            }
        } else if (state == KEYSTATE && ch=='=') {
            key = cut(input, beginpos, pos);
            state = EQSTATE;
            beginpos = pos+1;
            currentValue = OptionMapPtr();
        } else if (state == EQSTATE && !isspace(ch)) {
            state = VALUESTATE;
        }
    }
}

}

#ifdef __GNUC__
#include <fenv.h>
#endif

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

    int myargc = argc+2;
    const char **myargv = new const char*[myargc];
    memcpy(myargv, argv, argc*sizeof(const char*));
    myargv[argc] = "--moduleloglevel";
    myargv[argc+1] = "transfer=fatal,ogre=fatal,task=fatal,resource=fatal";

    using namespace Sirikata;
    PluginManager plugins;
    plugins.load ( DynamicLibrary::filename("ogregraphics") );
    plugins.load ( DynamicLibrary::filename("bulletphysics") );
    OptionSet::getOptions ( "" )->parse ( myargc,myargv );

#ifdef __GNUC__
#ifndef __APPLE__
    if (floatExcept->as<bool>()) {
        feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
    }
#endif
#endif

    OptionMapPtr transferOptions (new OptionMap);
    {
        std::string contents(cdnConfigFile->as<String>());
        std::string::size_type pos(0);
        parseConfig(contents, transferOptions, transferOptions, pos);
        std::cout << *transferOptions;
    }

    initializeProtocols();

    Network::IOService *ioServ = Network::IOServiceFactory::makeIOService();

    SpaceID mainSpace(UUID("12345678-1111-1111-1111-DEFA01759ACE",UUID::HumanReadable()));
    SpaceIDMap *spaceMap = new SpaceIDMap;
    spaceMap->insert(mainSpace, Network::Address("127.0.0.1","5943"));

    ObjectHost *oh = new ObjectHost(spaceMap, ioServ);
    {//to deallocate HostedObjects before armageddon
    HostedObjectPtr firstObject (HostedObject::construct<HostedObject>(oh));
    firstObject->initializeConnect(
            UUID::random(),
            Location(Vector3d(0, ((double)(time(NULL)%10)) - 5 , 0), Quaternion::identity(),
                     Vector3f(0.2,0,0), Vector3f(0,0,1), 0.),
            "meru://daniel@/cube.mesh",
            BoundingSphere3f(Vector3f::nil(),1),
            NULL,
            mainSpace);
    firstObject->setScale(Vector3f(3,3,3));

    HostedObjectPtr secondObject (HostedObject::construct<HostedObject>(oh));
    secondObject->initializeConnect(
        UUID::random(),
        Location(Vector3d(0,0,25), Quaternion::identity(),
                 Vector3f(0.1,0,0), Vector3f(0,0,1), 0.),
        "",
        BoundingSphere3f(Vector3f::nil(),0),
        NULL,
        mainSpace);

    HostedObjectPtr thirdObject (HostedObject::construct<HostedObject>(oh));
    {
        LightInfo li;
        li.setLightDiffuseColor(Color(0.976471, 0.992157, 0.733333));
        li.setLightAmbientColor(Color(.24,.25,.18));
        li.setLightSpecularColor(Color(0,0,0));
        li.setLightShadowColor(Color(0,0,0));
        li.setLightPower(1.0);
        li.setLightRange(75);
        li.setLightFalloff(1,0,0.03);
        li.setLightSpotlightCone(30,40,1);
        li.setCastsShadow(true);
        thirdObject->initializeConnect(
            UUID::random(),
            Location(Vector3d(10,0,10), Quaternion::identity(),
                     Vector3f::nil(), Vector3f(0,0,1), 0.),
            "",
            BoundingSphere3f(Vector3f::nil(),0),
            &li,
            mainSpace);
    }
    ProxyManager *provider = oh->getProxyManager(mainSpace);

    Task::WorkQueue *workQueue = new Task::LockFreeWorkQueue;
    Task::GenEventManager *eventManager = new Task::GenEventManager(workQueue);
    TransferManager *tm;
    try {
        tm = initializeTransferManager((*transferOptions)["cdn"], eventManager);
    } catch (OptionDoesNotExist &err) {
        SILOG(input,fatal,"Fatal Error: Failed to load CDN config: " << err.what());
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
        return 1;
    }
    OptionSet::getOptions("")->parse(myargc,myargv);
    String graphicsCommandArguments;
    {
        std::ostringstream os;
        os << "--transfermanager=" << tm << " ";
        os << "--eventmanager=" << eventManager << " ";
        os << "--workqueue=" << workQueue << " ";
        graphicsCommandArguments = os.str();
    }
    if (!provider) {
        SILOG(cppoh,error,"Failed to get TopLevelSpaceConnection for main space "<<mainSpace);
    }
    String graphicsPluginName ( "ogregraphics" );
    String physicsPluginName ( "bulletphysics" );
    SILOG(cppoh,error,"dbm: initializing graphics");
    TimeSteppedSimulation *graphicsSystem=
        SimulationFactory::getSingleton()
        .getConstructor ( graphicsPluginName ) ( provider,graphicsCommandArguments );
    SILOG(cppoh,error,"dbm: initializing physics");
    TimeSteppedSimulation *physicsSystem=
        SimulationFactory::getSingleton()
        .getConstructor ( physicsPluginName ) ( provider,graphicsCommandArguments );
    if (!physicsSystem) {
        SILOG(cppoh,error,"physicsSystem NULL!");
    }
    else {
        SILOG(cppoh,error,"physicsSystem: " << std::hex << (unsigned long)physicsSystem);
    }
    if ( graphicsSystem ) {
        while ( graphicsSystem->tick() ) {
            physicsSystem->tick();
            Network::IOServiceFactory::pollService(ioServ);
        }
    } else {
        SILOG(cppoh,error,"Fatal Error: Unable to load OGRE Graphics plugin. The PATH environment variable is ignored, so make sure you have copied the DLLs from dependencies/ogre/bin/ into the current directory. Sorry about this!");
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
    }
    delete graphicsSystem;

    delete eventManager;
    delete workQueue;
    }
    plugins.gc();
    SimulationFactory::destroy();

    delete oh;
    Network::IOServiceFactory::destroyIOService(ioServ);
    delete spaceMap;

    delete []myargv;

    return 0;
}
<|endoftext|>


<commit_before>#include "Segmentation.h"
#include "Lab.h"
#include "RGB.h"

template <>
double
Segmentation<ImgClass::RGB>::distance(const ImgClass::RGB& lvalue, const ImgClass::RGB& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.R - rvalue.R)
	    + SQUARE(lvalue.G - rvalue.G)
	    + SQUARE(lvalue.B - rvalue.B));
}

template <>
double
Segmentation<ImgClass::RGB>::normalized_distance(const ImgClass::RGB& lvalue, const ImgClass::RGB& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.R - rvalue.R)
	    + SQUARE(lvalue.G - rvalue.G)
	    + SQUARE(lvalue.B - rvalue.B));
}

template <>
double
Segmentation<ImgClass::Lab>::distance(const ImgClass::Lab& lvalue, const ImgClass::Lab& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.L - rvalue.L)
	    + SQUARE(lvalue.a - rvalue.a)
	    + SQUARE(lvalue.b - rvalue.b));
}

template <>
double
Segmentation<ImgClass::Lab>::normalized_distance(const ImgClass::Lab& lvalue, const ImgClass::Lab& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.L - rvalue.L)
	    + SQUARE(lvalue.a - rvalue.a)
	    + SQUARE(lvalue.b - rvalue.b)) / 100.0;
}

/*
 * std::vector<double> kernel has kernel radius for each dimensions.
 * The values it needs are below:
 *	_kernel_spatial : the spatial radius of mean shift kernel
 *	_kernel_intensity : the norm threshold of mean shift kernel in L*a*b* space
 */
template <> // Specialized for ImgClass::RGB<double>
const ImgClass::Segmentation::tuple<ImgClass::RGB>
Segmentation<ImgClass::RGB>::MeanShift(const int x, const int y, std::vector<VECTOR_2D<int> >& pel_list, int Iter_Max)
{
	const double radius_spatial_squared = SQUARE(_kernel_spatial);
	const double radius_intensity_squared = SQUARE(_kernel_intensity);
	const double displacement_min = SQUARE(0.01);
	ImgClass::Segmentation::tuple<ImgClass::RGB> tuple;
	// Initialize
	tuple.spatial = VECTOR_2D<double>(static_cast<double>(x), static_cast<double>(y));
	tuple.color = _image.get(x, y);
	// Iterate until it converge
	for (int i = 0; i < Iter_Max; i++) {
		double N = 0.0;
		ImgClass::RGB sum_diff(0.0, 0.0, 0.0);
		VECTOR_2D<double> sum_d(0.0, 0.0);
		for (size_t n = 0; n < pel_list.size(); n++) {
			VECTOR_2D<int> r(
			    static_cast<int>(round(tuple.spatial.x) + pel_list[n].x),
			    static_cast<int>(round(tuple.spatial.y) + pel_list[n].y));
			if (0 <= r.x && r.x < _width && 0 <= r.y && r.y < _height) {
				ImgClass::RGB diff(_image.get(r.x, r.y) - tuple.color);
				VECTOR_2D<double> d(r.x - tuple.spatial.x, r.y - tuple.spatial.y);
				double ratio_intensity = norm_squared(diff) / radius_intensity_squared;
				double ratio_spatial = norm_squared(d) / radius_spatial_squared;
				if (ratio_intensity <= 1.0 && ratio_spatial <= 1.0) {
					double coeff = 1.0 - (ratio_intensity * ratio_spatial);
					N += coeff;
					sum_diff += diff * coeff;
					sum_d += d * coeff;
				}
			}
		}
		tuple.color += sum_diff / N;
		VECTOR_2D<double> displacement(sum_d.x / N, sum_d.y / N);
		tuple.spatial += displacement;
		if (norm_squared(sum_diff /N) * norm_squared(displacement) < displacement_min) {
			break;
		}
	}
	return tuple;
}

/*
 * std::vector<double> kernel has kernel radius for each dimensions.
 * The values it needs are below:
 *	_kernel_spatial : the spatial radius of mean shift kernel
 *	_kernel_intensity : the norm threshold of mean shift kernel in L*a*b* space
 */
template <> // Specialized for ImgClass::Lab
const ImgClass::Segmentation::tuple<ImgClass::Lab>
Segmentation<ImgClass::Lab>::MeanShift(const int x, const int y, std::vector<VECTOR_2D<int> >& pel_list, int Iter_Max)
{
	const double radius_spatial_squared = SQUARE(_kernel_spatial);
	const double radius_intensity_squared = SQUARE(100.0 * _kernel_intensity);
	const double displacement_min = SQUARE(0.001);
	ImgClass::Segmentation::tuple<ImgClass::Lab> tuple;

	// Initialize
	tuple.spatial = VECTOR_2D<double>(static_cast<double>(x), static_cast<double>(y));
	tuple.color = _image.get(x, y);
	// Iterate until it converge
	for (int i = 0; i < Iter_Max; i++) {
		double N = 0.0;
		ImgClass::Lab sum_diff(0.0, 0.0, 0.0);
		VECTOR_2D<double> sum_d(0.0, 0.0);
		for (size_t n = 0; n < pel_list.size(); n++) {
			VECTOR_2D<int> r(
			    static_cast<int>(round(tuple.spatial.x) + pel_list[n].x),
			    static_cast<int>(round(tuple.spatial.y) + pel_list[n].y));
			if (0 <= r.x && r.x < _width && 0 <= r.y && r.y < _height) {
				ImgClass::Lab diff(_image.get(r.x, r.y) - tuple.color);
				//diff.L /= 2.0; // Difference of Lighting is not so important in segmentation
				VECTOR_2D<double> d(r.x - tuple.spatial.x, r.y - tuple.spatial.y);
				double ratio_intensity = norm_squared(diff) / radius_intensity_squared;
				double ratio_spatial = norm_squared(d) / radius_spatial_squared;
				if (ratio_intensity <= 1.0 && ratio_spatial <= 1.0) {
					double coeff = 1.0 - (ratio_intensity * ratio_spatial);
					N += coeff;
					sum_diff += diff * coeff;
					sum_d += d * coeff;
				}
			}
		}
		tuple.color += sum_diff / N;
		VECTOR_2D<double> displacement(sum_d.x / N, sum_d.y / N);
		tuple.spatial += displacement;
		if (norm_squared(sum_diff / N) * norm_squared(displacement) < displacement_min) {
			break;
		}
	}
	return tuple;
}

<commit_msg>Bug Fix<commit_after>#include "Segmentation.h"
#include "Lab.h"
#include "RGB.h"

template <>
double
Segmentation<ImgClass::RGB>::distance(const ImgClass::RGB& lvalue, const ImgClass::RGB& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.R - rvalue.R)
	    + SQUARE(lvalue.G - rvalue.G)
	    + SQUARE(lvalue.B - rvalue.B));
}

template <>
double
Segmentation<ImgClass::RGB>::normalized_distance(const ImgClass::RGB& lvalue, const ImgClass::RGB& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.R - rvalue.R)
	    + SQUARE(lvalue.G - rvalue.G)
	    + SQUARE(lvalue.B - rvalue.B));
}

template <>
double
Segmentation<ImgClass::Lab>::distance(const ImgClass::Lab& lvalue, const ImgClass::Lab& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.L - rvalue.L)
	    + SQUARE(lvalue.a - rvalue.a)
	    + SQUARE(lvalue.b - rvalue.b));
}

template <>
double
Segmentation<ImgClass::Lab>::normalized_distance(const ImgClass::Lab& lvalue, const ImgClass::Lab& rvalue)
{
	return sqrt(
	    SQUARE(lvalue.L - rvalue.L)
	    + SQUARE(lvalue.a - rvalue.a)
	    + SQUARE(lvalue.b - rvalue.b)) / 100.0;
}

/*
 * std::vector<double> kernel has kernel radius for each dimensions.
 * The values it needs are below:
 *	_kernel_spatial : the spatial radius of mean shift kernel
 *	_kernel_intensity : the norm threshold of mean shift kernel in L*a*b* space
 */
template <> // Specialized for ImgClass::RGB<double>
const ImgClass::Segmentation::tuple<ImgClass::RGB>
Segmentation<ImgClass::RGB>::MeanShift(const int x, const int y, std::vector<VECTOR_2D<int> >& pel_list, int Iter_Max)
{
	const double radius_spatial_squared = SQUARE(_kernel_spatial);
	const double radius_intensity_squared = SQUARE(_kernel_intensity);
	const double displacement_min = SQUARE(0.01);
	ImgClass::Segmentation::tuple<ImgClass::RGB> tuple;
	// Initialize
	tuple.spatial = VECTOR_2D<double>(static_cast<double>(x), static_cast<double>(y));
	tuple.color = _image.get(x, y);
	// Iterate until it converge
	for (int i = 0; i < Iter_Max; i++) {
		double N = 0.0;
		ImgClass::RGB sum_diff(0.0, 0.0, 0.0);
		VECTOR_2D<double> sum_d(0.0, 0.0);
		for (size_t n = 0; n < pel_list.size(); n++) {
			VECTOR_2D<int> r(
			    static_cast<int>(round(tuple.spatial.x) + pel_list[n].x),
			    static_cast<int>(round(tuple.spatial.y) + pel_list[n].y));
			if (0 <= r.x && r.x < _width && 0 <= r.y && r.y < _height) {
				ImgClass::RGB diff(_image.get(r.x, r.y) - tuple.color);
				VECTOR_2D<double> d(r.x - tuple.spatial.x, r.y - tuple.spatial.y);
				double ratio_intensity = norm_squared(diff) / radius_intensity_squared;
				double ratio_spatial = norm_squared(d) / radius_spatial_squared;
				if (ratio_intensity <= 1.0 && ratio_spatial <= 1.0) {
					double coeff = 1.0 - (ratio_intensity * ratio_spatial);
					N += coeff;
					sum_diff += diff * coeff;
					sum_d += d * coeff;
				}
			}
		}
		tuple.color += sum_diff / N;
		VECTOR_2D<double> displacement(sum_d.x / N, sum_d.y / N);
		tuple.spatial += displacement;
		if (norm_squared(sum_diff /N) * norm_squared(displacement) < displacement_min) {
			break;
		}
	}
	return tuple;
}

/*
 * std::vector<double> kernel has kernel radius for each dimensions.
 * The values it needs are below:
 *	_kernel_spatial : the spatial radius of mean shift kernel
 *	_kernel_intensity : the norm threshold of mean shift kernel in L*a*b* space
 */
template <> // Specialized for ImgClass::Lab
const ImgClass::Segmentation::tuple<ImgClass::Lab>
Segmentation<ImgClass::Lab>::MeanShift(const int x, const int y, std::vector<VECTOR_2D<int> >& pel_list, int Iter_Max)
{
	const double radius_spatial_squared = SQUARE(_kernel_spatial);
	const double radius_intensity_squared = SQUARE(100.0 * _kernel_intensity);
	const double displacement_min = SQUARE(0.001);
	ImgClass::Segmentation::tuple<ImgClass::Lab> tuple;

	// Initialize
	tuple.spatial = VECTOR_2D<double>(static_cast<double>(x), static_cast<double>(y));
	tuple.color = _image.get(x, y);
	// Iterate until it converge
	for (int i = 0; i < Iter_Max; i++) {
		double N = 0.0;
		ImgClass::Lab sum_diff(0.0, 0.0, 0.0);
		VECTOR_2D<double> sum_d(0.0, 0.0);
		for (size_t n = 0; n < pel_list.size(); n++) {
			VECTOR_2D<int> r(
			    static_cast<int>(round(tuple.spatial.x) + pel_list[n].x),
			    static_cast<int>(round(tuple.spatial.y) + pel_list[n].y));
			if (0 <= r.x && r.x < _width && 0 <= r.y && r.y < _height) {
				ImgClass::Lab diff(_image.get(r.x, r.y) - tuple.color);
				diff.L *= 0.8; // Difference of Lighting is not so important in segmentation
				VECTOR_2D<double> d(r.x - tuple.spatial.x, r.y - tuple.spatial.y);
				double ratio_intensity = norm_squared(diff) / radius_intensity_squared;
				double ratio_spatial = norm_squared(d) / radius_spatial_squared;
				if (ratio_intensity <= 1.0 && ratio_spatial <= 1.0) {
					double coeff = 1.0 - (ratio_intensity * ratio_spatial);
					N += coeff;
					sum_diff += diff * coeff;
					sum_d += d * coeff;
				}
			}
		}
		tuple.color += sum_diff / N;
		VECTOR_2D<double> displacement(sum_d.x / N, sum_d.y / N);
		tuple.spatial += displacement;
		if (norm_squared(sum_diff / N) * norm_squared(displacement) < displacement_min) {
			break;
		}
	}
	return tuple;
}

<|endoftext|>


<commit_before>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
    #include <SDL.h>
    #include <SDL_thread.h>
    #include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
    #ifndef RUNNINGONINTEL
    #define RUNNINGONINTEL
    #endif
#else
    #ifndef RUNNINGONPI
    #define RUNNINGONPI
    #endif
    #include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

//attempting double buffer
IplImage threadImage1;
IplImage threadImage2;
IplImage threadImage3;
bool updatedImage = false;
int bufferNumber = 1;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
int cameraHeight;
int cameraWidth;
int noSongs;

SDL_Thread* SDLCameraThread;
SDL_Thread* SDLMusicThread;

int quit;

/***********************************************************************
/*                          SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
    bool success = true;

    if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if (window == NULL)
        {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else
        {
            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            if (renderer == NULL)
            {
                printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
                success = false;
            }
            else
            {
                SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
            }
        }
    }
    return success;
}

bool init_CameraSettings()
{
    int w, h;
    bool success = true;
    SDL_GetWindowSize(window, &w, &h);
    videoRect.x = 0;
    videoRect.y = 0;
    videoRect.w = w;
    videoRect.h = h-50; //change 50 to whatever height we want for the PI cam

    cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

    printf("Camera Width %d, Camera Height %d \n",cameraWidth,cameraHeight);
    return success;
}

int cameraWorker(void* data)
{
    while (!quit)
    {
        cap >> frame;
        if(bufferNumber == 1)
        {
            threadImage2 = frame;
            bufferNumber = 2;
        }
        else if (bufferNumber == 2)
        {
            threadImage3 = frame;
            bufferNumber = 3;
        }
        else
        {
            threadImage1 = frame;
            bufferNumber = 1;
        }
        updatedImage = true;
    }
    return 0;
}

// Shows an individual frame of the supplied video
int show_Camera()
{
    IplImage* img = NULL;
    if(updatedImage == true)
    {
        updatedImage = false;
        if(bufferNumber == 1)
        {
            img = &threadImage1;
        }
        else if (bufferNumber == 2)
        {
            img = &threadImage2;
        }
        else
        {
            img = &threadImage3;
        }
        SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
            img->width,
            img->height,
            img->depth * img->nChannels,
            img->widthStep,
            0xff0000, 0x00ff00, 0x0000ff, 0
            );

        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
        surface = NULL;
        SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
        SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
        SDL_DestroyTexture(texture);
        return 1;
    }

    return 0;
}

void processEvents()
{
    SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    printf("SDL_QUIT was called\n");
                    signalToQuit();
                    close();
                    break;

                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:
                            printf("Esc was Pressed!\n");
                            signalToQuit();
                            close();
                            break;
                        case SDLK_LEFT:
                            printf("Left arrow was Pressed!\n");
                            previousSong();
                            break;
                        case SDLK_RIGHT:
                            printf("Right arrow was Pressed!\n");
                            nextSong();
                            break;
                        case SDLK_UP:
                            changeVolume(0.1);
                            break;
                        case SDLK_DOWN:
                            changeVolume(-0.1);
                            break;
                        case SDLK_SPACE:
                            printf("Space was pressed!\n");
                            playPause();
                    }
            }
        }
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
    quit = true;
    songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
    closeSongPlayer();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    SDL_Quit();
    exit(0);
}

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

    if (!init_SDL())
    {
        fprintf(stderr, "Could not initialize SDL!\n");
        return -1;
    }
    if (!cap.isOpened())
    {
        fprintf(stderr, "Failed to load file!\n");
        return -1;
    }
    if (!init_CameraSettings())
    {
        fprintf(stderr, "Failed to load settings!\n");
        return -1;
    }

    initSongPlayer();
    noSongs = loadSong((char *)currentSong().c_str());

    SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
    if (!noSongs)
        SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

    int screenUpdate = 0;

    while (!quit)
    {
        screenUpdate = show_Camera();
        processEvents();
        if (screenUpdate == 1)
        {
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
            SDL_RenderPresent(renderer);
            SDL_RenderClear(renderer);
        }
    }

    SDL_WaitThread(SDLCameraThread, NULL);
    if (!noSongs)
        SDL_WaitThread(SDLMusicThread, NULL);
    return 0;
}
<commit_msg>Made SDL launch full screen<commit_after>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
    #include <SDL.h>
    #include <SDL_thread.h>
    #include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
    #ifndef RUNNINGONINTEL
    #define RUNNINGONINTEL
    #endif
#else
    #ifndef RUNNINGONPI
    #define RUNNINGONPI
    #endif
    #include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

//attempting double buffer
IplImage threadImage1;
IplImage threadImage2;
IplImage threadImage3;
bool updatedImage = false;
int bufferNumber = 1;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
int cameraHeight;
int cameraWidth;
int noSongs;

SDL_Thread* SDLCameraThread;
SDL_Thread* SDLMusicThread;

int quit;

/***********************************************************************
/*                          SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
    bool success = true;

    if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_FULLSCREEN);
        if (window == NULL)
        {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else
        {
            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            if (renderer == NULL)
            {
                printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
                success = false;
            }
            else
            {
                SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
            }
        }
    }
    return success;
}

bool init_CameraSettings()
{
    int w, h;
    bool success = true;
    SDL_GetWindowSize(window, &w, &h);
    videoRect.x = 0;
    videoRect.y = 0;
    videoRect.w = w;
    videoRect.h = h-50; //change 50 to whatever height we want for the PI cam

    cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

    printf("Camera Width %d, Camera Height %d \n",cameraWidth,cameraHeight);
    return success;
}

int cameraWorker(void* data)
{
    while (!quit)
    {
        cap >> frame;
        if(bufferNumber == 1)
        {
            threadImage2 = frame;
            bufferNumber = 2;
        }
        else if (bufferNumber == 2)
        {
            threadImage3 = frame;
            bufferNumber = 3;
        }
        else
        {
            threadImage1 = frame;
            bufferNumber = 1;
        }
        updatedImage = true;
    }
    return 0;
}

// Shows an individual frame of the supplied video
int show_Camera()
{
    IplImage* img = NULL;
    if(updatedImage == true)
    {
        updatedImage = false;
        if(bufferNumber == 1)
        {
            img = &threadImage1;
        }
        else if (bufferNumber == 2)
        {
            img = &threadImage2;
        }
        else
        {
            img = &threadImage3;
        }
        SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
            img->width,
            img->height,
            img->depth * img->nChannels,
            img->widthStep,
            0xff0000, 0x00ff00, 0x0000ff, 0
            );

        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
        surface = NULL;
        SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
        SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
        SDL_DestroyTexture(texture);
        return 1;
    }

    return 0;
}

void processEvents()
{
    SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    printf("SDL_QUIT was called\n");
                    signalToQuit();
                    close();
                    break;

                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:
                            printf("Esc was Pressed!\n");
                            signalToQuit();
                            close();
                            break;
                        case SDLK_LEFT:
                            printf("Left arrow was Pressed!\n");
                            previousSong();
                            break;
                        case SDLK_RIGHT:
                            printf("Right arrow was Pressed!\n");
                            nextSong();
                            break;
                        case SDLK_UP:
                            changeVolume(0.1);
                            break;
                        case SDLK_DOWN:
                            changeVolume(-0.1);
                            break;
                        case SDLK_SPACE:
                            printf("Space was pressed!\n");
                            playPause();
                    }
            }
        }
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
    quit = true;
    songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
    closeSongPlayer();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    SDL_Quit();
    exit(0);
}

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

    if (!init_SDL())
    {
        fprintf(stderr, "Could not initialize SDL!\n");
        return -1;
    }
    if (!cap.isOpened())
    {
        fprintf(stderr, "Failed to load file!\n");
        return -1;
    }
    if (!init_CameraSettings())
    {
        fprintf(stderr, "Failed to load settings!\n");
        return -1;
    }

    initSongPlayer();
    noSongs = loadSong((char *)currentSong().c_str());

    SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
    if (!noSongs)
        SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

    int screenUpdate = 0;

    while (!quit)
    {
        screenUpdate = show_Camera();
        processEvents();
        if (screenUpdate == 1)
        {
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
            SDL_RenderPresent(renderer);
            SDL_RenderClear(renderer);
        }
    }

    SDL_WaitThread(SDLCameraThread, NULL);
    if (!noSongs)
        SDL_WaitThread(SDLMusicThread, NULL);
    return 0;
}
<|endoftext|>


<commit_before>/*
 *  colourcombo.cpp  -  colour selection combo box
 *  Program:  kalarm
 *  (C) 2001 - 2003 by David Jarvie  software@astrojar.org.uk
 *
 *  Some code taken from kdelibs/kdeui/kcolorcombo.cpp in the KDE libraries:
 *  Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <qpainter.h>

#include <klocale.h>
#include <kcolordialog.h>

#include "kalarmapp.h"
#include "preferences.h"
#include "colourcombo.h"

ColourCombo::ColourCombo(QWidget* parent, const char* name, const QColor& defaultColour)
	: QComboBox(parent, name),
	  mColourList(theApp()->preferences()->messageColours()),
	  mSelectedColour(defaultColour),
	  mCustomColour(255, 255, 255),
	  mReadOnly(false),
	  mDisabled(false)
{
	addColours();
	connect(this, SIGNAL(activated(int)), SLOT(slotActivated(int)));
	connect(this, SIGNAL(highlighted(int)), SLOT(slotHighlighted(int)));
	connect(theApp()->preferences(), SIGNAL(preferencesChanged()), SLOT(slotPreferencesChanged()));
}

void ColourCombo::setColour(const QColor& colour)
{
	mSelectedColour = colour;
	addColours();
}

/******************************************************************************
*  Set a new colour selection.
*/
void ColourCombo::setColours(const ColourList& colours)
{
	mColourList = colours;
	if (mSelectedColour != mCustomColour
	&&  !mColourList.contains(mSelectedColour))
	{
		// The current colour has been deleted
		mSelectedColour = mColourList.count() ? mColourList.first() : mCustomColour;
	}
	addColours();
}

/******************************************************************************
*  Called when the user changes the preference settings.
*  If the colour list has changed, update the colours displayed.
*/
void ColourCombo::slotPreferencesChanged()
{
	const ColourList& prefColours = theApp()->preferences()->messageColours();
	if (prefColours != mColourList)
		setColours(prefColours);      // update the display with the new colours
}

/******************************************************************************
*  Enable or disable the control.
*  If it is disabled, its colour is set to the dialog background colour.
*/
void ColourCombo::setEnabled(bool enable)
{
	if (enable  &&  mDisabled)
	{
		mDisabled = false;
		setColour(mSelectedColour);
	}
	else if (!enable  &&  !mDisabled)
	{
		mSelectedColour = color();
		int end = count();
		if (end > 1)
		{
			// Add a dialog background colour item
			QPixmap pm = *pixmap(1);
			pm.fill(paletteBackgroundColor());
			insertItem(pm);
			setCurrentItem(end);
		}
		mDisabled = true;
	}
	QComboBox::setEnabled(enable);
}

void ColourCombo::slotActivated(int index)
{
	if (index)
		mSelectedColour = mColourList[index - 1];
	else
	{
		if (KColorDialog::getColor(mCustomColour, this) == QDialog::Accepted)
		{
			QRect rect;
			drawCustomItem(rect, false);
		}
		mSelectedColour = mCustomColour;
	}
	emit activated(mSelectedColour);
}

void ColourCombo::slotHighlighted(int index)
{
	mSelectedColour = index ? mColourList[index - 1] : mCustomColour;
	emit highlighted(mSelectedColour);
}

/******************************************************************************
*  Initialise the items in the combo box to one for each colour in the list.
*/
void ColourCombo::addColours()
{
	clear();

	for (ColourList::const_iterator it = mColourList.begin();  ;  ++it)
	{
		if (it == mColourList.end())
		{
			mCustomColour = mSelectedColour;
			break;
		}
		if (mSelectedColour == *it)
			break;
	}

	QRect rect;
	drawCustomItem(rect, true);

	QPainter painter;
	QPixmap pixmap(rect.width(), rect.height());
	int i = 1;
	for (ColourList::const_iterator it = mColourList.begin();  it != mColourList.end();  ++i, ++it)
	{
		painter.begin(&pixmap);
		QBrush brush(*it);
		painter.fillRect(rect, brush);
		painter.end();

		insertItem(pixmap);
		pixmap.detach();

		if (*it == mSelectedColour.rgb())
			setCurrentItem(i);
	}
}

void ColourCombo::drawCustomItem(QRect& rect, bool insert)
{
	QPen pen;
	if (qGray(mCustomColour.rgb()) < 128)
		pen.setColor(Qt::white);
	else
		pen.setColor(Qt::black);

	QPainter painter;
	QFontMetrics fm = QFontMetrics(painter.font());
	rect.setRect(0, 0, width(), fm.height() + 4);
	QPixmap pixmap(rect.width(), rect.height());

	painter.begin(&pixmap);
	QBrush brush(mCustomColour);
	painter.fillRect(rect, brush);
	painter.setPen(pen);
	painter.drawText(2, fm.ascent() + 2, i18n("Custom..."));
	painter.end();

	if (insert)
		insertItem(pixmap);
	else
		changeItem(pixmap, 0);
	pixmap.detach();
}

void ColourCombo::setReadOnly(bool ro)
{
	mReadOnly = ro;
}

void ColourCombo::resizeEvent(QResizeEvent* re)
{
	QComboBox::resizeEvent(re);
	addColours();
}

void ColourCombo::mousePressEvent(QMouseEvent* e)
{
	if (mReadOnly)
	{
		// Swallow up the event if it's the left button
		if (e->button() == LeftButton)
			return;
	}
	QComboBox::mousePressEvent(e);
}

void ColourCombo::mouseReleaseEvent(QMouseEvent* e)
{
	if (!mReadOnly)
		QComboBox::mouseReleaseEvent(e);
}

void ColourCombo::mouseMoveEvent(QMouseEvent* e)
{
	if (!mReadOnly)
		QComboBox::mouseMoveEvent(e);
}

void ColourCombo::keyPressEvent(QKeyEvent* e)
{
	if (!mReadOnly)
		QComboBox::keyPressEvent(e);
}

void ColourCombo::keyReleaseEvent(QKeyEvent* e)
{
	if (!mReadOnly)
		QComboBox::keyReleaseEvent(e);
}
#include "colourcombo.moc"
<commit_msg>Tidy up access to preferences<commit_after>/*
 *  colourcombo.cpp  -  colour selection combo box
 *  Program:  kalarm
 *  (C) 2001, 2002, 2003 by David Jarvie <software@astrojar.org.uk>
 *
 *  Some code taken from kdelibs/kdeui/kcolorcombo.cpp in the KDE libraries:
 *  Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <qpainter.h>

#include <klocale.h>
#include <kcolordialog.h>

#include "kalarmapp.h"
#include "preferences.h"
#include "colourcombo.moc"

ColourCombo::ColourCombo(QWidget* parent, const char* name, const QColor& defaultColour)
	: QComboBox(parent, name),
	  mColourList(Preferences::instance()->messageColours()),
	  mSelectedColour(defaultColour),
	  mCustomColour(255, 255, 255),
	  mReadOnly(false),
	  mDisabled(false)
{
	addColours();
	connect(this, SIGNAL(activated(int)), SLOT(slotActivated(int)));
	connect(this, SIGNAL(highlighted(int)), SLOT(slotHighlighted(int)));
	connect(Preferences::instance(), SIGNAL(preferencesChanged()), SLOT(slotPreferencesChanged()));
}

void ColourCombo::setColour(const QColor& colour)
{
	mSelectedColour = colour;
	addColours();
}

/******************************************************************************
*  Set a new colour selection.
*/
void ColourCombo::setColours(const ColourList& colours)
{
	mColourList = colours;
	if (mSelectedColour != mCustomColour
	&&  !mColourList.contains(mSelectedColour))
	{
		// The current colour has been deleted
		mSelectedColour = mColourList.count() ? mColourList.first() : mCustomColour;
	}
	addColours();
}

/******************************************************************************
*  Called when the user changes the preference settings.
*  If the colour list has changed, update the colours displayed.
*/
void ColourCombo::slotPreferencesChanged()
{
	const ColourList& prefColours = Preferences::instance()->messageColours();
	if (prefColours != mColourList)
		setColours(prefColours);      // update the display with the new colours
}

/******************************************************************************
*  Enable or disable the control.
*  If it is disabled, its colour is set to the dialog background colour.
*/
void ColourCombo::setEnabled(bool enable)
{
	if (enable  &&  mDisabled)
	{
		mDisabled = false;
		setColour(mSelectedColour);
	}
	else if (!enable  &&  !mDisabled)
	{
		mSelectedColour = color();
		int end = count();
		if (end > 1)
		{
			// Add a dialog background colour item
			QPixmap pm = *pixmap(1);
			pm.fill(paletteBackgroundColor());
			insertItem(pm);
			setCurrentItem(end);
		}
		mDisabled = true;
	}
	QComboBox::setEnabled(enable);
}

void ColourCombo::slotActivated(int index)
{
	if (index)
		mSelectedColour = mColourList[index - 1];
	else
	{
		if (KColorDialog::getColor(mCustomColour, this) == QDialog::Accepted)
		{
			QRect rect;
			drawCustomItem(rect, false);
		}
		mSelectedColour = mCustomColour;
	}
	emit activated(mSelectedColour);
}

void ColourCombo::slotHighlighted(int index)
{
	mSelectedColour = index ? mColourList[index - 1] : mCustomColour;
	emit highlighted(mSelectedColour);
}

/******************************************************************************
*  Initialise the items in the combo box to one for each colour in the list.
*/
void ColourCombo::addColours()
{
	clear();

	for (ColourList::const_iterator it = mColourList.begin();  ;  ++it)
	{
		if (it == mColourList.end())
		{
			mCustomColour = mSelectedColour;
			break;
		}
		if (mSelectedColour == *it)
			break;
	}

	QRect rect;
	drawCustomItem(rect, true);

	QPainter painter;
	QPixmap pixmap(rect.width(), rect.height());
	int i = 1;
	for (ColourList::const_iterator it = mColourList.begin();  it != mColourList.end();  ++i, ++it)
	{
		painter.begin(&pixmap);
		QBrush brush(*it);
		painter.fillRect(rect, brush);
		painter.end();

		insertItem(pixmap);
		pixmap.detach();

		if (*it == mSelectedColour.rgb())
			setCurrentItem(i);
	}
}

void ColourCombo::drawCustomItem(QRect& rect, bool insert)
{
	QPen pen;
	if (qGray(mCustomColour.rgb()) < 128)
		pen.setColor(Qt::white);
	else
		pen.setColor(Qt::black);

	QPainter painter;
	QFontMetrics fm = QFontMetrics(painter.font());
	rect.setRect(0, 0, width(), fm.height() + 4);
	QPixmap pixmap(rect.width(), rect.height());

	painter.begin(&pixmap);
	QBrush brush(mCustomColour);
	painter.fillRect(rect, brush);
	painter.setPen(pen);
	painter.drawText(2, fm.ascent() + 2, i18n("Custom..."));
	painter.end();

	if (insert)
		insertItem(pixmap);
	else
		changeItem(pixmap, 0);
	pixmap.detach();
}

void ColourCombo::setReadOnly(bool ro)
{
	mReadOnly = ro;
}

void ColourCombo::resizeEvent(QResizeEvent* re)
{
	QComboBox::resizeEvent(re);
	addColours();
}

void ColourCombo::mousePressEvent(QMouseEvent* e)
{
	if (mReadOnly)
	{
		// Swallow up the event if it's the left button
		if (e->button() == LeftButton)
			return;
	}
	QComboBox::mousePressEvent(e);
}

void ColourCombo::mouseReleaseEvent(QMouseEvent* e)
{
	if (!mReadOnly)
		QComboBox::mouseReleaseEvent(e);
}

void ColourCombo::mouseMoveEvent(QMouseEvent* e)
{
	if (!mReadOnly)
		QComboBox::mouseMoveEvent(e);
}

void ColourCombo::keyPressEvent(QKeyEvent* e)
{
	if (!mReadOnly)
		QComboBox::keyPressEvent(e);
}

void ColourCombo::keyReleaseEvent(QKeyEvent* e)
{
	if (!mReadOnly)
		QComboBox::keyReleaseEvent(e);
}
<|endoftext|>


<commit_before>#include "arpTable.hpp"

using namespace std;
using namespace headers;

constexpr array<uint8_t, 6> ARPTable::nextHop::invalidMac;

void ARPTable::createCurrentTable(std::shared_ptr<RoutingTable> routingTable){
	logDebug("ARPTable::createCurrentTable constructing tables for mapping");

	// create a new table;
	shared_ptr<table> newTable = make_shared<table>(std::vector<nextHop>(), directlyConnected);
	auto next_hop_addresses = routingTable->getNextHopMapping();

	newTable->nextHops.resize(next_hop_addresses->size());
	for(auto nh : *next_hop_addresses){
		if(nh.interface->netmapIndex == uint16_t_max){
			logDebug("invalid nh interface");
			abort();
		}
		newTable->nextHops[nh.index].netmapInterface = nh.interface->netmapIndex;
		//newTable->nextHops[nh.index].mac = {{0}}; // just initialize
		for(int i=0; i<6; i++){
			newTable->nextHops[nh.index].mac[i] = 0;
		}
		if(mapping.count(nh.nh_ip)){
			newTable->nextHops[nh.index].mac = mapping[nh.nh_ip].mac;
		}
	}

	currentTable = newTable;
};

void ARPTable::prepareRequest(uint32_t ip, uint16_t iface, frame& frame){
	logDebug("ARPTable::prepareRequest Preparing ARP request now");

	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	shared_ptr<Interface> iface_ptr;
	for(auto i : interfaces){
		if(i->netmapIndex == iface){
			iface_ptr = i;
			break;
		}
	}

	if(iface_ptr == nullptr){
		abort();
	}

	ether_hdr->s_mac = iface_ptr->mac;
	for(int i=0; i<6; i++){
		ether_hdr->d_mac[i] = 0xff;
	}
	ether_hdr->ethertype = htons(0x0806);

	arp_hdr->hw_type = htons(0x0001);
	arp_hdr->proto_type = htons(0x0800);
	arp_hdr->hw_len = 6;
	arp_hdr->proto_len = 4;
	arp_hdr->op = htons(arp::OP_REQUEST);

	arp_hdr->s_hw_addr = iface_ptr->mac;
	if(iface_ptr->IPs.empty()){
		fatal("Cannot send ARP request without an IP address on interface");
	}
	arp_hdr->s_proto_addr = htonl(iface_ptr->IPs.front());
	for(int i=0; i<6; i++){
		arp_hdr->t_hw_addr[i] = 0;
	}
	arp_hdr->t_proto_addr = ip;

	frame.len = sizeof(ether) + sizeof(arp);
}

void ARPTable::handleReply(frame& frame){
	logDebug("ARPTable::handleReply Looking at ARP reply now");

	// ARP is stateless -> doesn't mapper if we actually sent a request
	uint32_t ip;
	std::array<uint8_t, 6> mac;
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleReply()");
		return;
	}

	if(ntohs(arp_hdr->op) != arp::OP_REPLY){
		// This is not a reply
		logErr("Frame falsely sent to ARPTable::handleReply()");
		return;
	}

	ip = ntohl(arp_hdr->s_proto_addr);
	mac = arp_hdr->s_hw_addr;

	nextHop nextHop;

	nextHop.mac = mac;
	nextHop.netmapInterface = frame.iface & frame::IFACE_ID;

	auto next_hop_addresses = routingTable->getNextHopMapping();

	// Check if this is a registered next hop
	for(auto& nh : *next_hop_addresses){
		if(nh.nh_ip == ip && nh.interface->netmapIndex == (frame.iface & frame::IFACE_ID)){
			mapping.insert({ip, nextHop});
			currentTable->nextHops[nh.index].mac = mac;

			return;
		}
	}

	// In case we reach this, the node is directly connected
	directlyConnected.insert({ip, nextHop});
}

void ARPTable::handleRequest(frame& frame){
	logDebug("ARPTable::handleRequest looking at request now");
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleRequest()");
		return;
	}

	if(ntohs(arp_hdr->op) != arp::OP_REQUEST){
		logErr("Frame falsely sent to ARPTable::handleRequest()");
		return;
	}

	shared_ptr<Interface> iface_ptr;
	for(auto i : interfaces){
		if(i->netmapIndex == (frame.iface & frame::IFACE_ID)){
			iface_ptr = i;
			break;
		}
	}

	if(iface_ptr == nullptr){
		abort();
	}

	// Check if we are asked
	if(!count(iface_ptr->IPs.begin(), iface_ptr->IPs.end(),
			ntohl(arp_hdr->t_proto_addr))){
		logDebug("Got ARP request for some other node (IP: "
				 + ip_to_str(ntohl(arp_hdr->t_proto_addr)) + "), discarding");
		frame.iface = frame::IFACE_DISCARD;
		return;
	}

	// Turn the request into a reply
	arp_hdr->op = htons(arp::OP_REPLY);

	arp_hdr->t_hw_addr = arp_hdr->s_hw_addr;
	uint32_t t_ip = arp_hdr->t_proto_addr;
	arp_hdr->t_proto_addr = arp_hdr->s_proto_addr;

	arp_hdr->s_hw_addr = iface_ptr->mac;
	arp_hdr->s_proto_addr = t_ip;

	ether_hdr->s_mac = iface_ptr->mac;
	for(int i=0; i<6; i++){
		ether_hdr->d_mac[i] = 0xff;
	}

}

void ARPTable::handleFrame(frame& frame){
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleFrame()");
		return;
	}

	if(ntohs(arp_hdr->op) == arp::OP_REQUEST){
		handleRequest(frame);
	} else if(ntohs(arp_hdr->op) == arp::OP_REPLY){
		handleReply(frame);
	} else {
		logErr("Unknown ARP OP detected");
	}
}
<commit_msg>save pointer to current routing table in ARPTable<commit_after>#include "arpTable.hpp"

using namespace std;
using namespace headers;

constexpr array<uint8_t, 6> ARPTable::nextHop::invalidMac;

void ARPTable::createCurrentTable(std::shared_ptr<RoutingTable> routingTable){
	logDebug("ARPTable::createCurrentTable constructing tables for mapping");
	this->routingTable = routingTable;

	// create a new table;
	shared_ptr<table> newTable = make_shared<table>(std::vector<nextHop>(), directlyConnected);
	auto next_hop_addresses = routingTable->getNextHopMapping();

	newTable->nextHops.resize(next_hop_addresses->size());
	for(auto nh : *next_hop_addresses){
		if(nh.interface->netmapIndex == uint16_t_max){
			logDebug("invalid nh interface");
			abort();
		}
		newTable->nextHops[nh.index].netmapInterface = nh.interface->netmapIndex;
		//newTable->nextHops[nh.index].mac = {{0}}; // just initialize
		for(int i=0; i<6; i++){
			newTable->nextHops[nh.index].mac[i] = 0;
		}
		if(mapping.count(nh.nh_ip)){
			newTable->nextHops[nh.index].mac = mapping[nh.nh_ip].mac;
		}
	}

	currentTable = newTable;
};

void ARPTable::prepareRequest(uint32_t ip, uint16_t iface, frame& frame){
	logDebug("ARPTable::prepareRequest Preparing ARP request now");

	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	shared_ptr<Interface> iface_ptr;
	for(auto i : interfaces){
		if(i->netmapIndex == iface){
			iface_ptr = i;
			break;
		}
	}

	if(iface_ptr == nullptr){
		abort();
	}

	ether_hdr->s_mac = iface_ptr->mac;
	for(int i=0; i<6; i++){
		ether_hdr->d_mac[i] = 0xff;
	}
	ether_hdr->ethertype = htons(0x0806);

	arp_hdr->hw_type = htons(0x0001);
	arp_hdr->proto_type = htons(0x0800);
	arp_hdr->hw_len = 6;
	arp_hdr->proto_len = 4;
	arp_hdr->op = htons(arp::OP_REQUEST);

	arp_hdr->s_hw_addr = iface_ptr->mac;
	if(iface_ptr->IPs.empty()){
		fatal("Cannot send ARP request without an IP address on interface");
	}
	arp_hdr->s_proto_addr = htonl(iface_ptr->IPs.front());
	for(int i=0; i<6; i++){
		arp_hdr->t_hw_addr[i] = 0;
	}
	arp_hdr->t_proto_addr = ip;

	frame.len = sizeof(ether) + sizeof(arp);
}

void ARPTable::handleReply(frame& frame){
	logDebug("ARPTable::handleReply Looking at ARP reply now");

	// ARP is stateless -> doesn't mapper if we actually sent a request
	uint32_t ip;
	std::array<uint8_t, 6> mac;
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleReply()");
		return;
	}

	if(ntohs(arp_hdr->op) != arp::OP_REPLY){
		// This is not a reply
		logErr("Frame falsely sent to ARPTable::handleReply()");
		return;
	}

	ip = ntohl(arp_hdr->s_proto_addr);
	mac = arp_hdr->s_hw_addr;

	nextHop nextHop;

	nextHop.mac = mac;
	nextHop.netmapInterface = frame.iface & frame::IFACE_ID;

	auto next_hop_addresses = routingTable->getNextHopMapping();

	// Check if this is a registered next hop
	for(auto& nh : *next_hop_addresses){
		if(nh.nh_ip == ip && nh.interface->netmapIndex == (frame.iface & frame::IFACE_ID)){
			mapping.insert({ip, nextHop});
			currentTable->nextHops[nh.index].mac = mac;

			return;
		}
	}

	// In case we reach this, the node is directly connected
	directlyConnected.insert({ip, nextHop});
}

void ARPTable::handleRequest(frame& frame){
	logDebug("ARPTable::handleRequest looking at request now");
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleRequest()");
		return;
	}

	if(ntohs(arp_hdr->op) != arp::OP_REQUEST){
		logErr("Frame falsely sent to ARPTable::handleRequest()");
		return;
	}

	shared_ptr<Interface> iface_ptr;
	for(auto i : interfaces){
		if(i->netmapIndex == (frame.iface & frame::IFACE_ID)){
			iface_ptr = i;
			break;
		}
	}

	if(iface_ptr == nullptr){
		abort();
	}

	// Check if we are asked
	if(!count(iface_ptr->IPs.begin(), iface_ptr->IPs.end(),
			ntohl(arp_hdr->t_proto_addr))){
		logDebug("Got ARP request for some other node (IP: "
				 + ip_to_str(ntohl(arp_hdr->t_proto_addr)) + "), discarding");
		frame.iface = frame::IFACE_DISCARD;
		return;
	}

	// Turn the request into a reply
	arp_hdr->op = htons(arp::OP_REPLY);

	arp_hdr->t_hw_addr = arp_hdr->s_hw_addr;
	uint32_t t_ip = arp_hdr->t_proto_addr;
	arp_hdr->t_proto_addr = arp_hdr->s_proto_addr;

	arp_hdr->s_hw_addr = iface_ptr->mac;
	arp_hdr->s_proto_addr = t_ip;

	ether_hdr->s_mac = iface_ptr->mac;
	for(int i=0; i<6; i++){
		ether_hdr->d_mac[i] = 0xff;
	}

}

void ARPTable::handleFrame(frame& frame){
	ether* ether_hdr = reinterpret_cast<ether*>(frame.buf_ptr);
	arp* arp_hdr = reinterpret_cast<arp*>(frame.buf_ptr + sizeof(ether));

	if(ether_hdr->ethertype != htons(0x0806)){
		logErr("Frame falsely sent to ARPTable::handleFrame()");
		return;
	}

	if(ntohs(arp_hdr->op) == arp::OP_REQUEST){
		handleRequest(frame);
	} else if(ntohs(arp_hdr->op) == arp::OP_REPLY){
		handleReply(frame);
	} else {
		logErr("Unknown ARP OP detected");
	}
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "plugin.h"
#include "EditorTab.h"
#include "rapidjson/document.h"

#include<vector>

#define IDS_MENU_TEXT 1
#define IDS_STATUSMESSAGE 2
#define IDI_ICON 101

std::vector<HWND> windows_;
EditorStatus status_;
bool restoring_;

void StoreEditorStatus()
{
	if (restoring_)
	{
		return;
	}

	EditorStatus status;

	for (int i = 0; i < windows_.size(); i++)
	{
		HWND hwnd = windows_[i];

		LRESULT count = Editor_Info(hwnd, MI_GET_DOC_COUNT, 0);

		for (int i = 0; i < count; i++)
		{
			wchar_t fileNameRaw[2048];
			LRESULT result = Editor_DocInfo(hwnd, i, MI_GET_FILE_NAME, (LPARAM)fileNameRaw);
			auto docHandle = Editor_Info(hwnd, MI_INDEX_TO_DOC, i);

			std::wstring fileName(fileNameRaw);
			std::wstring& id = std::to_wstring(docHandle);
			status.AddTab(EditorTab(fileName, id));
		}
	}

	std::locale::global(std::locale("japanese"));
	auto json = EditorStatus::SerializeToJson(status);
	{
		std::wofstream ofs(L"C:\\temp\\test.json", std::ios::out);
		ofs << json;
	}
}

int restoreCounter_ = 0;

void RestoreEditorStatus()
{
	restoring_ = true;
	restoreCounter_ = 0;
	std::locale::global(std::locale("japanese"));
	std::wstring json(L"");
	{
		std::wifstream ifs(L"C:\\temp\\test.json", std::ios::in);
		json.append(std::istreambuf_iterator<wchar_t>(ifs), std::istreambuf_iterator<wchar_t>());
	}

	auto status = EditorStatus::DeserializeFromJson(json);
	for (auto it = status.Tabs().begin(); it != status.Tabs().end(); it++)
	{
		auto& filePath = it->GetFilePath();

		if (PathFileExists(filePath.c_str()))
		{
			wchar_t currentFileName[1024];
			auto result = Editor_Info(windows_[0], MI_GET_FILE_NAME, (LPARAM)currentFileName);
			if (lstrlenW(currentFileName) != 0 || Editor_GetModified(windows_[0]))
			{
				Editor_New(windows_[0]);
			}
			Editor_LoadFile(windows_[0], filePath.c_str());
		}
	}
	restoring_ = false;
	StoreEditorStatus();
}

// -----------------------------------------------------------------------------
// OnCommand
// プラグインを実行した時に呼び出されます
// パラメータ
//   hwnd: ウィンドウのハンドル

EXTERN_C void WINAPI OnCommand(HWND hwnd)
{
	//Editor_DocInfo(hwnd, 0, MI_CLOSE_DOC, 0);
	return;
	MessageBox(hwnd, L"Hello World!", L"基本的なサンプル", MB_OK);
	RestoreEditorStatus();

	std::locale::global(std::locale("japanese"));
	//Editor_DocSaveFile(hwnd, 0, L"C:\\temp\\a.txt");

	std::wofstream ofs(L"C:\\work\\mery-plugin-sdk\\SDK\\C\\Basic\\storedContent\\aaaa.txt");

	LRESULT count = Editor_Info(hwnd, MI_GET_DOC_COUNT, 0);

	std::wstring fileNameSum(L"");

	for (int i = 0; i < count; i++)
	{
		wchar_t fileName[2048];
		LRESULT result = Editor_DocInfo(hwnd, i, MI_GET_FILE_NAME, (LPARAM)fileName);

		std::wstring fileName2(fileName);
		fileNameSum += fileName2;
		fileNameSum += L"\r\n";

		UINT_PTR lineCount = Editor_GetDocLines(hwnd, i, POS_LOGICAL);
		for (uint32_t lineIndex = 0; lineIndex < lineCount; lineIndex++)
		{
			GET_LINE_INFO lineInfo;
			lineInfo.cch = 0;
			lineInfo.yLine = lineIndex;
			lineInfo.flags = FLAG_LOGICAL;
			UINT_PTR size = Editor_GetLine(hwnd, &lineInfo, nullptr);
			wchar_t* szLine = new wchar_t[size];
			lineInfo.cch = size;
			Editor_GetLine(hwnd, &lineInfo, szLine);
			ofs << szLine << std::endl;
			delete szLine;
		}
	}
	ofs.close();

	MessageBox(hwnd, fileNameSum.c_str(), L"Hello World!", MB_OK);
}

// -----------------------------------------------------------------------------
// QueryStatus
//   プラグインが実行可能か、またはチェックされた状態かを調べます
// パラメータ
//   hwnd:      ウィンドウのハンドル
//   pbChecked: チェックの状態
// 戻り値
//   実行可能であればTrueを返します

EXTERN_C BOOL WINAPI QueryStatus(HWND hwnd, LPBOOL pbChecked)
{
	return true;
}

// -----------------------------------------------------------------------------
// GetMenuTextID
//   メニューに表示するテキストのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetMenuTextID()
{
	return IDS_MENU_TEXT;
}

// -----------------------------------------------------------------------------
// GetStatusMessageID
//   ツールチップに表示するテキストのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetStatusMessageID()
{
	return IDS_STATUSMESSAGE;
}

// -----------------------------------------------------------------------------
// GetIconID
//   ツールバーに表示するアイコンのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetIconID()
{
	return IDI_ICON;
}

// -----------------------------------------------------------------------------
// OnEvents
//   イベントが発生した時に呼び出されます
// パラメータ
//   hwnd:   ウィンドウのハンドル
//   nEvent: イベントの種類
//   lParam: メッセージ特有の追加情報
// 備考
//   EVENT_CREATE:             エディタを起動した時
//   EVENT_CLOSE:              エディタを終了した時
//   EVENT_CREATE_FRAME:       フレームを作成された時
//   EVENT_CLOSE_FRAME:        フレームが破棄された時
//   EVENT_SET_FOCUS:          フォーカスを取得した時
//   EVENT_KILL_FOCUS:         フォーカスを失った時
//   EVENT_FILE_OPENED:        ファイルを開いた時
//   EVENT_FILE_SAVED:         ファイルを保存した時
//   EVENT_MODIFIED:           更新の状態が変更された時
//   EVENT_CARET_MOVED:        カーソルが移動した時
//   EVENT_SCROLL:             スクロールされた時
//   EVENT_SEL_CHANGED:        選択範囲が変更された時
//   EVENT_CHANGED:            テキストが変更された時
//   EVENT_CHAR:               文字が入力された時
//   EVENT_MODE_CHANGED:       編集モードが変更された時
//   EVENT_DOC_SEL_CHANGED:    アクティブな文書が変更された時
//   EVENT_DOC_CLOSE:          文書を閉じた時
//   EVENT_TAB_MOVED:          タブが移動された時
//   EVENT_CUSTOM_BAR_CLOSING: カスタムバーを閉じようとした時
//   EVENT_CUSTOM_BAR_CLOSED:  カスタムバーを閉じた時
//   EVENT_TOOL_BAR_CLOSED:    ツールバーを閉じた時
//   EVENT_TOOL_BAR_SHOW:      ツールバーが表示された時
//   EVENT_IDLE:               アイドル時

EXTERN_C void WINAPI OnEvents(HWND hwnd, UINT nEvent, LPARAM lParam)
{
	//std::ifstream ifs("C:\\work\\mery-plugin-sdk\\SDK\\C\\Basic\\sampleData\\data.json");
	//std::istreambuf_iterator<char> it(ifs);
	//std::istreambuf_iterator<char> last;
	//std::string str(it, last);

	//rapidjson::Document doc;
	//doc.Parse(str.c_str());
	if (nEvent == EVENT_CREATE_FRAME)
	{
		//Editor_LoadFile(hwnd, L"C:\\Users\\taka\\Downloads\\Mery\\Mery.txt");
		windows_.push_back(hwnd);
		RestoreEditorStatus();
	}
	if (nEvent == EVENT_DOC_SEL_CHANGED)
	{
		//状態の記憶
		StoreEditorStatus();
	}

	if (nEvent == EVENT_CHANGED)
	{
		//時間経過でアクティブ文書のバックアップ
	}
	if (nEvent == EVENT_CREATE) { OutputDebugString(L"エディタを起動した時\n"); }
	if (nEvent == EVENT_CLOSE) { OutputDebugString(L"エディタを終了した時\n"); }
	if (nEvent == EVENT_CREATE_FRAME) { OutputDebugString(L"フレームを作成された時\n"); }
	if (nEvent == EVENT_CLOSE_FRAME) { OutputDebugString(L"フレームが破棄された時\n"); }
	if (nEvent == EVENT_SET_FOCUS) { OutputDebugString(L"フォーカスを取得した時\n"); }
	if (nEvent == EVENT_KILL_FOCUS) { OutputDebugString(L"フォーカスを失った時\n"); }
	if (nEvent == EVENT_FILE_OPENED) { OutputDebugString(L"ファイルを開いた時\n"); }
	if (nEvent == EVENT_FILE_SAVED) { OutputDebugString(L"ファイルを保存した時\n"); }
	if (nEvent == EVENT_MODIFIED) { OutputDebugString(L"更新の状態が変更された時\n"); }
	if (nEvent == EVENT_CARET_MOVED) { OutputDebugString(L"カーソルが移動した時\n"); }
	if (nEvent == EVENT_SCROLL) { OutputDebugString(L"スクロールされた時\n"); }
	if (nEvent == EVENT_SEL_CHANGED) { OutputDebugString(L"選択範囲が変更された時\n"); }
	if (nEvent == EVENT_CHANGED) { OutputDebugString(L"テキストが変更された時\n"); }
	if (nEvent == EVENT_CHAR) { OutputDebugString(L"文字が入力された時\n"); }
	if (nEvent == EVENT_MODE_CHANGED) { OutputDebugString(L"編集モードが変更された時\n"); }
	if (nEvent == EVENT_DOC_SEL_CHANGED) { OutputDebugString(L"アクティブな文書が変更された時\n"); }
	if (nEvent == EVENT_DOC_CLOSE) { OutputDebugString(L"文書を閉じた時\n"); }
	if (nEvent == EVENT_TAB_MOVED) { OutputDebugString(L"タブが移動された時\n"); }
	if (nEvent == EVENT_CUSTOM_BAR_CLOSING) { OutputDebugString(L"カスタムバーを閉じようとした時\n"); }
	if (nEvent == EVENT_CUSTOM_BAR_CLOSED) { OutputDebugString(L"カスタムバーを閉じた時\n"); }
	if (nEvent == EVENT_TOOL_BAR_CLOSED) { OutputDebugString(L"ツールバーを閉じた時\n"); }
	if (nEvent == EVENT_TOOL_BAR_SHOW) { OutputDebugString(L"ツールバーが表示された時\n"); }
	//if (nEvent == EVENT_IDLE) { OutputDebugString(L"アイドル時\n"); }

}

// -----------------------------------------------------------------------------
// PluginProc
//   プラグインに送られるメッセージを処理します
// パラメータ
//   hwnd:   ウィンドウのハンドル
//   nMsg:   メッセージ
//   wParam: メッセージ特有の追加情報
//   lParam: メッセージ特有の追加情報
// 戻り値
//   メッセージにより異なります

EXTERN_C LRESULT WINAPI PluginProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	wchar_t szName[] = L"基本的なサンプル";
	wchar_t szVersion[] = L"Version 2.0.0.0";
	switch(nMsg)
	{
	case MP_GET_NAME:
		if(lParam != 0)
			lstrcpynW(LPWSTR(lParam), szName, wParam);
		return wcslen(szName);
	case MP_GET_VERSION:
		if(lParam != 0)
			lstrcpynW(LPWSTR(lParam), szVersion, wParam);
		return wcslen(szVersion);
	}
	return	0;
}
<commit_msg>Change plugin data path to appData<commit_after>#include "stdafx.h"
#include "plugin.h"
#include "EditorTab.h"
#include "rapidjson/document.h"

#include<vector>

#define IDS_MENU_TEXT 1
#define IDS_STATUSMESSAGE 2
#define IDI_ICON 101

std::vector<HWND> windows_;
EditorStatus status_;
bool restoring_;

void StoreEditorStatus()
{
	if (restoring_)
	{
		return;
	}

	EditorStatus status;

	for (int i = 0; i < windows_.size(); i++)
	{
		HWND hwnd = windows_[i];

		LRESULT count = Editor_Info(hwnd, MI_GET_DOC_COUNT, 0);

		for (int i = 0; i < count; i++)
		{
			wchar_t fileNameRaw[2048];
			LRESULT result = Editor_DocInfo(hwnd, i, MI_GET_FILE_NAME, (LPARAM)fileNameRaw);
			auto docHandle = Editor_Info(hwnd, MI_INDEX_TO_DOC, i);

			std::wstring fileName(fileNameRaw);
			std::wstring& id = std::to_wstring(docHandle);
			status.AddTab(EditorTab(fileName, id));
		}
	}

	wchar_t pluginDataDir[1024];
	::PathCombine(pluginDataDir, _wgetenv(L"APPDATA"), L"Mery");
	if (!PathIsDirectory(pluginDataDir))
	{
		CreateDirectory(pluginDataDir, NULL);
	}
	::PathCombine(pluginDataDir, pluginDataDir, L"plugins");
	if (!PathIsDirectory(pluginDataDir))
	{
		CreateDirectory(pluginDataDir, NULL);
	}
	::PathCombine(pluginDataDir, pluginDataDir, L"ResumeMeryPlugin");
	if (!PathIsDirectory(pluginDataDir))
	{
		CreateDirectory(pluginDataDir, NULL);
	}

	std::locale::global(std::locale("japanese"));
	auto json = EditorStatus::SerializeToJson(status);
	{
		wchar_t statusFilePath[1024];
		::PathCombine(statusFilePath, pluginDataDir, L"status.json");

		std::wofstream ofs(statusFilePath, std::ios::out);
		ofs << json;
	}
}

int restoreCounter_ = 0;

void RestoreEditorStatus()
{
	restoring_ = true;
	restoreCounter_ = 0;
	std::locale::global(std::locale("japanese"));
	std::wstring json(L"");
	{
		wchar_t statusFilePath[1024];
		::PathCombine(statusFilePath, _wgetenv(L"APPDATA"), L"Mery\\plugins\\ResumeMeryPlugin\\status.json");

		std::wifstream ifs(statusFilePath, std::ios::in);
		if (ifs.fail())
		{
			restoring_ = false;
			return;
		}
		json.append(std::istreambuf_iterator<wchar_t>(ifs), std::istreambuf_iterator<wchar_t>());
	}

	auto status = EditorStatus::DeserializeFromJson(json);
	for (auto it = status.Tabs().begin(); it != status.Tabs().end(); it++)
	{
		auto& filePath = it->GetFilePath();

		if (PathFileExists(filePath.c_str()))
		{
			wchar_t currentFileName[1024];
			auto result = Editor_Info(windows_[0], MI_GET_FILE_NAME, (LPARAM)currentFileName);
			if (lstrlenW(currentFileName) != 0 || Editor_GetModified(windows_[0]))
			{
				Editor_New(windows_[0]);
			}
			Editor_LoadFile(windows_[0], filePath.c_str());
		}
	}
	restoring_ = false;
	StoreEditorStatus();
}

// -----------------------------------------------------------------------------
// OnCommand
// プラグインを実行した時に呼び出されます
// パラメータ
//   hwnd: ウィンドウのハンドル

EXTERN_C void WINAPI OnCommand(HWND hwnd)
{
	//Editor_DocInfo(hwnd, 0, MI_CLOSE_DOC, 0);
	return;
	//MessageBox(hwnd, L"Hello World!", L"基本的なサンプル", MB_OK);
	//RestoreEditorStatus();

	//std::locale::global(std::locale("japanese"));

	//std::wofstream ofs(L"C:\\work\\mery-plugin-sdk\\SDK\\C\\Basic\\storedContent\\aaaa.txt");

	//LRESULT count = Editor_Info(hwnd, MI_GET_DOC_COUNT, 0);

	//std::wstring fileNameSum(L"");

	//for (int i = 0; i < count; i++)
	//{
	//	wchar_t fileName[2048];
	//	LRESULT result = Editor_DocInfo(hwnd, i, MI_GET_FILE_NAME, (LPARAM)fileName);

	//	std::wstring fileName2(fileName);
	//	fileNameSum += fileName2;
	//	fileNameSum += L"\r\n";

	//	UINT_PTR lineCount = Editor_GetDocLines(hwnd, i, POS_LOGICAL);
	//	for (uint32_t lineIndex = 0; lineIndex < lineCount; lineIndex++)
	//	{
	//		GET_LINE_INFO lineInfo;
	//		lineInfo.cch = 0;
	//		lineInfo.yLine = lineIndex;
	//		lineInfo.flags = FLAG_LOGICAL;
	//		UINT_PTR size = Editor_GetLine(hwnd, &lineInfo, nullptr);
	//		wchar_t* szLine = new wchar_t[size];
	//		lineInfo.cch = size;
	//		Editor_GetLine(hwnd, &lineInfo, szLine);
	//		ofs << szLine << std::endl;
	//		delete szLine;
	//	}
	//}
	//ofs.close();

	//MessageBox(hwnd, fileNameSum.c_str(), L"Hello World!", MB_OK);
}

// -----------------------------------------------------------------------------
// QueryStatus
//   プラグインが実行可能か、またはチェックされた状態かを調べます
// パラメータ
//   hwnd:      ウィンドウのハンドル
//   pbChecked: チェックの状態
// 戻り値
//   実行可能であればTrueを返します

EXTERN_C BOOL WINAPI QueryStatus(HWND hwnd, LPBOOL pbChecked)
{
	return true;
}

// -----------------------------------------------------------------------------
// GetMenuTextID
//   メニューに表示するテキストのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetMenuTextID()
{
	return IDS_MENU_TEXT;
}

// -----------------------------------------------------------------------------
// GetStatusMessageID
//   ツールチップに表示するテキストのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetStatusMessageID()
{
	return IDS_STATUSMESSAGE;
}

// -----------------------------------------------------------------------------
// GetIconID
//   ツールバーに表示するアイコンのリソース識別子を取得します
// 戻り値
//   リソース識別子

EXTERN_C UINT WINAPI GetIconID()
{
	return IDI_ICON;
}

// -----------------------------------------------------------------------------
// OnEvents
//   イベントが発生した時に呼び出されます
// パラメータ
//   hwnd:   ウィンドウのハンドル
//   nEvent: イベントの種類
//   lParam: メッセージ特有の追加情報
// 備考
//   EVENT_CREATE:             エディタを起動した時
//   EVENT_CLOSE:              エディタを終了した時
//   EVENT_CREATE_FRAME:       フレームを作成された時
//   EVENT_CLOSE_FRAME:        フレームが破棄された時
//   EVENT_SET_FOCUS:          フォーカスを取得した時
//   EVENT_KILL_FOCUS:         フォーカスを失った時
//   EVENT_FILE_OPENED:        ファイルを開いた時
//   EVENT_FILE_SAVED:         ファイルを保存した時
//   EVENT_MODIFIED:           更新の状態が変更された時
//   EVENT_CARET_MOVED:        カーソルが移動した時
//   EVENT_SCROLL:             スクロールされた時
//   EVENT_SEL_CHANGED:        選択範囲が変更された時
//   EVENT_CHANGED:            テキストが変更された時
//   EVENT_CHAR:               文字が入力された時
//   EVENT_MODE_CHANGED:       編集モードが変更された時
//   EVENT_DOC_SEL_CHANGED:    アクティブな文書が変更された時
//   EVENT_DOC_CLOSE:          文書を閉じた時
//   EVENT_TAB_MOVED:          タブが移動された時
//   EVENT_CUSTOM_BAR_CLOSING: カスタムバーを閉じようとした時
//   EVENT_CUSTOM_BAR_CLOSED:  カスタムバーを閉じた時
//   EVENT_TOOL_BAR_CLOSED:    ツールバーを閉じた時
//   EVENT_TOOL_BAR_SHOW:      ツールバーが表示された時
//   EVENT_IDLE:               アイドル時

EXTERN_C void WINAPI OnEvents(HWND hwnd, UINT nEvent, LPARAM lParam)
{
	//std::ifstream ifs("C:\\work\\mery-plugin-sdk\\SDK\\C\\Basic\\sampleData\\data.json");
	//std::istreambuf_iterator<char> it(ifs);
	//std::istreambuf_iterator<char> last;
	//std::string str(it, last);

	//rapidjson::Document doc;
	//doc.Parse(str.c_str());
	if (nEvent == EVENT_CREATE_FRAME)
	{
		//Editor_LoadFile(hwnd, L"C:\\Users\\taka\\Downloads\\Mery\\Mery.txt");
		windows_.push_back(hwnd);
		RestoreEditorStatus();
	}
	if (nEvent == EVENT_DOC_SEL_CHANGED)
	{
		//状態の記憶
		StoreEditorStatus();
	}

	if (nEvent == EVENT_CHANGED)
	{
		//時間経過でアクティブ文書のバックアップ
	}
	if (nEvent == EVENT_CREATE) { OutputDebugString(L"エディタを起動した時\n"); }
	if (nEvent == EVENT_CLOSE) { OutputDebugString(L"エディタを終了した時\n"); }
	if (nEvent == EVENT_CREATE_FRAME) { OutputDebugString(L"フレームを作成された時\n"); }
	if (nEvent == EVENT_CLOSE_FRAME) { OutputDebugString(L"フレームが破棄された時\n"); }
	if (nEvent == EVENT_SET_FOCUS) { OutputDebugString(L"フォーカスを取得した時\n"); }
	if (nEvent == EVENT_KILL_FOCUS) { OutputDebugString(L"フォーカスを失った時\n"); }
	if (nEvent == EVENT_FILE_OPENED) { OutputDebugString(L"ファイルを開いた時\n"); }
	if (nEvent == EVENT_FILE_SAVED) { OutputDebugString(L"ファイルを保存した時\n"); }
	if (nEvent == EVENT_MODIFIED) { OutputDebugString(L"更新の状態が変更された時\n"); }
	if (nEvent == EVENT_CARET_MOVED) { OutputDebugString(L"カーソルが移動した時\n"); }
	if (nEvent == EVENT_SCROLL) { OutputDebugString(L"スクロールされた時\n"); }
	if (nEvent == EVENT_SEL_CHANGED) { OutputDebugString(L"選択範囲が変更された時\n"); }
	if (nEvent == EVENT_CHANGED) { OutputDebugString(L"テキストが変更された時\n"); }
	if (nEvent == EVENT_CHAR) { OutputDebugString(L"文字が入力された時\n"); }
	if (nEvent == EVENT_MODE_CHANGED) { OutputDebugString(L"編集モードが変更された時\n"); }
	if (nEvent == EVENT_DOC_SEL_CHANGED) { OutputDebugString(L"アクティブな文書が変更された時\n"); }
	if (nEvent == EVENT_DOC_CLOSE) { OutputDebugString(L"文書を閉じた時\n"); }
	if (nEvent == EVENT_TAB_MOVED) { OutputDebugString(L"タブが移動された時\n"); }
	if (nEvent == EVENT_CUSTOM_BAR_CLOSING) { OutputDebugString(L"カスタムバーを閉じようとした時\n"); }
	if (nEvent == EVENT_CUSTOM_BAR_CLOSED) { OutputDebugString(L"カスタムバーを閉じた時\n"); }
	if (nEvent == EVENT_TOOL_BAR_CLOSED) { OutputDebugString(L"ツールバーを閉じた時\n"); }
	if (nEvent == EVENT_TOOL_BAR_SHOW) { OutputDebugString(L"ツールバーが表示された時\n"); }
	//if (nEvent == EVENT_IDLE) { OutputDebugString(L"アイドル時\n"); }

}

// -----------------------------------------------------------------------------
// PluginProc
//   プラグインに送られるメッセージを処理します
// パラメータ
//   hwnd:   ウィンドウのハンドル
//   nMsg:   メッセージ
//   wParam: メッセージ特有の追加情報
//   lParam: メッセージ特有の追加情報
// 戻り値
//   メッセージにより異なります

EXTERN_C LRESULT WINAPI PluginProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	wchar_t szName[] = L"基本的なサンプル";
	wchar_t szVersion[] = L"Version 2.0.0.0";
	switch(nMsg)
	{
	case MP_GET_NAME:
		if(lParam != 0)
			lstrcpynW(LPWSTR(lParam), szName, wParam);
		return wcslen(szName);
	case MP_GET_VERSION:
		if(lParam != 0)
			lstrcpynW(LPWSTR(lParam), szVersion, wParam);
		return wcslen(szVersion);
	}
	return	0;
}
<|endoftext|>