<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2013, Institute for Artificial Intelligence,
 *  Universität Bremen.
 *  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 the Institute for Artificial Intelligence,
 *     Universität Bremen, 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.
 *********************************************************************/

/** \author Jan Winkler */

#include <plugins/ros/PluginROS.h>

namespace beliefstate {
  namespace plugins {
    PLUGIN_CLASS::PLUGIN_CLASS() {
      m_nhHandle = NULL;
      m_aspnAsyncSpinner = NULL;
      m_bRoslogMessages = false;

      this->setPluginVersion("0.9");
    }

    PLUGIN_CLASS::~PLUGIN_CLASS() {
      if(m_nhHandle) {
	delete m_nhHandle;
      }

      if(m_aspnAsyncSpinner) {
	delete m_aspnAsyncSpinner;
      }
    }

    Result PLUGIN_CLASS::init(int argc, char** argv) {
      Result resInit = defaultResult();

      CDesignator* cdConfig = this->getIndividualConfig();

      this->setSubscribedToEvent("add-image-from-file", true);
      this->setSubscribedToEvent("add-image-from-topic", true);
      this->setSubscribedToEvent("symbolic-create-designator", true);
      this->setSubscribedToEvent("interactive-callback", true);
      this->setSubscribedToEvent("status-message", true);

      if(!ros::ok()) {
	string strROSNodeName = cdConfig->stringValue("node-name");

	if(strROSNodeName == "") {
	  strROSNodeName = "beliefstate_ros";
	}

	this->info("Starting ROS node '" + strROSNodeName + "'.");

	ros::init(argc, argv, strROSNodeName);
	m_nhHandle = new ros::NodeHandle("~");

	if(ros::ok()) {
	  m_srvBeginContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("begin_context", &PLUGIN_CLASS::serviceCallbackBeginContext, this);
	  m_srvEndContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("end_context", &PLUGIN_CLASS::serviceCallbackEndContext, this);
	  m_srvAlterContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("alter_context", &PLUGIN_CLASS::serviceCallbackAlterContext, this);
	  m_pubLoggedDesignators = m_nhHandle->advertise<designator_integration_msgs::Designator>("/logged_designators", 1);
	  m_pubInteractiveCallback = m_nhHandle->advertise<designator_integration_msgs::Designator>("/interactive_callback", 1);

	  if(cdConfig->floatValue("roslog-messages") != 0) {
	    string strTopic = cdConfig->stringValue("roslog-topic");

	    if(strTopic != "") {
	      m_pubStatusMessages = m_nhHandle->advertise<rosgraph_msgs::Log>(strTopic, 1);
	      m_bRoslogMessages = true;
	    } else {
	      this->warn("You requested the status messages to be roslog'ged, but didn't specify a roslog topic. Ignoring the whole thing.");
	    }
	  }

	  int nThreads = 4;
	  if(cdConfig->childForKey("async-threads")) {
	    nThreads = cdConfig->floatValue("async-threads");
	  }

	  stringstream sts;
	  sts << nThreads;

	  this->info("ROS node started. Starting to spin (" + sts.str() + " threads).");
	  m_aspnAsyncSpinner = new ros::AsyncSpinner(nThreads);
	  m_aspnAsyncSpinner->start();
	} else {
	  resInit.bSuccess = false;
	  resInit.strErrorMessage = "Failed to start ROS node.";
	}
      } else {
      	this->warn("ROS node already started.");
      }

      return resInit;
    }

    Result PLUGIN_CLASS::deinit() {
      ros::shutdown();

      return defaultResult();
    }

    Result PLUGIN_CLASS::cycle() {
      Result resCycle = defaultResult();
      this->deployCycleData(resCycle);

      return resCycle;
    }

    bool PLUGIN_CLASS::serviceCallbackBeginContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evBeginContext = defaultEvent("begin-context");
      evBeginContext.nContextID = createContextID();
      evBeginContext.cdDesignator = new CDesignator(req.request.designator);

      stringstream sts;
      sts << evBeginContext.nContextID;

      this->info("When beginning context (ID = " + sts.str() + "), received " + this->getDesignatorTypeString(evBeginContext.cdDesignator) + " designator");
      this->deployEvent(evBeginContext);

      CDesignator *desigResponse = new CDesignator();
      desigResponse->setType(ACTION);
      desigResponse->setValue(string("_id"), evBeginContext.nContextID);

      res.response.designators.push_back(desigResponse->serializeToMessage());
      delete desigResponse;

      return true;
    }

    bool PLUGIN_CLASS::serviceCallbackEndContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evEndContext = defaultEvent("end-context");
      evEndContext.cdDesignator = new CDesignator(req.request.designator);

      int nContextID = (int)evEndContext.cdDesignator->floatValue("_id");
      stringstream sts;
      sts << nContextID;

      this->info("When ending context (ID = " + sts.str() + "), received " + this->getDesignatorTypeString(evEndContext.cdDesignator) + " designator");
      this->deployEvent(evEndContext);

      freeContextID(nContextID);

      return true;
    }

    bool PLUGIN_CLASS::serviceCallbackAlterContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evAlterContext = defaultEvent();
      evAlterContext.cdDesignator = new CDesignator(req.request.designator);

      this->info("When altering context, received " + this->getDesignatorTypeString(evAlterContext.cdDesignator) + " designator");

      string strCommand = evAlterContext.cdDesignator->stringValue("command");
      transform(strCommand.begin(), strCommand.end(), strCommand.begin(), ::tolower);

      if(strCommand == "add-image") {
	evAlterContext.strEventName = "add-image-from-topic";
	evAlterContext.nOpenRequestID = this->openNewRequestID();
      } else if(strCommand == "add-failure") {
	evAlterContext.strEventName = "add-failure";
      } else if(strCommand == "add-designator") {
	evAlterContext.strEventName = "add-designator";
      } else if(strCommand == "equate-designators") {
	evAlterContext.strEventName = "equate-designators";
      } else if(strCommand == "add-object") {
	evAlterContext.strEventName = "add-object";
      } else if(strCommand == "export-planlog") {
	evAlterContext.strEventName = "export-planlog";
      } else if(strCommand == "start-new-experiment") {
	evAlterContext.strEventName = "start-new-experiment";
      } else if(strCommand == "set-experiment-meta-data") {
	evAlterContext.strEventName = "set-experiment-meta-data";
      } else if(strCommand == "register-interactive-object") {
	evAlterContext.strEventName = "symbolic-add-object";
      } else if(strCommand == "unregister-interactive-object") {
	evAlterContext.strEventName = "symbolic-remove-object";
      } else if(strCommand == "set-interactive-object-menu") {
	evAlterContext.strEventName = "symbolic-set-interactive-object-menu";
      } else if(strCommand == "update-interactive-object-pose") {
	evAlterContext.strEventName = "symbolic-update-object-pose";
      } else {
	this->warn("Unknown command when altering context: '" + strCommand + "'");
      }

      this->deployEvent(evAlterContext, true);

      return true;
    }

    void PLUGIN_CLASS::consumeEvent(Event evEvent) {
      if(evEvent.bRequest == false) {
	this->closeRequestID(evEvent.nOpenRequestID);
      } else {
	if(evEvent.strEventName == "symbolic-create-designator") {
	  if(evEvent.cdDesignator) {
	    m_pubLoggedDesignators.publish(evEvent.cdDesignator->serializeToMessage());
	  }
	} else if(evEvent.strEventName == "interactive-callback") {
	  if(evEvent.cdDesignator) {
	    m_pubInteractiveCallback.publish(evEvent.cdDesignator->serializeToMessage());
	  }
	} else if(evEvent.strEventName == "status-message") {
	  if(m_bRoslogMessages) {
	    StatusMessage msgStatus = evEvent.msgStatusMessage;
	    rosgraph_msgs::Log rgmLogMessage;

	    if(msgStatus.bBold == true) {
	      rgmLogMessage.level = rosgraph_msgs::Log::WARN;
	    } else {
	      rgmLogMessage.level = rosgraph_msgs::Log::INFO;
	    }

	    rgmLogMessage.name = msgStatus.strPrefix;
	    rgmLogMessage.msg = msgStatus.strMessage;

	    m_pubStatusMessages.publish(rgmLogMessage);
	  }
	}
      }
    }

    Event PLUGIN_CLASS::consumeServiceEvent(ServiceEvent seServiceEvent) {
      Event evService = defaultEvent();

      this->info("Consume service event of type '" + seServiceEvent.strServiceName + "'!");

      return evService;
    }

    string PLUGIN_CLASS::getDesignatorTypeString(CDesignator* desigDesignator) {
      string strDesigType = "UNKNOWN";
      switch(desigDesignator->type()) {
      case ACTION:
	strDesigType = "ACTION";
	break;

      case OBJECT:
	strDesigType = "OBJECT";
	break;

      case LOCATION:
	strDesigType = "LOCATION";
	break;

      default:
	break;
      }

      return strDesigType;
    }
  }

  extern "C" plugins::PLUGIN_CLASS* createInstance() {
    return new plugins::PLUGIN_CLASS();
  }

  extern "C" void destroyInstance(plugins::PLUGIN_CLASS* icDestroy) {
    delete icDestroy;
  }
}
<commit_msg>Don't subscribe to status messages for now, as it disturbs normal status output<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2013, Institute for Artificial Intelligence,
 *  Universität Bremen.
 *  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 the Institute for Artificial Intelligence,
 *     Universität Bremen, 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.
 *********************************************************************/

/** \author Jan Winkler */

#include <plugins/ros/PluginROS.h>

namespace beliefstate {
  namespace plugins {
    PLUGIN_CLASS::PLUGIN_CLASS() {
      m_nhHandle = NULL;
      m_aspnAsyncSpinner = NULL;
      m_bRoslogMessages = false;

      this->setPluginVersion("0.9");
    }

    PLUGIN_CLASS::~PLUGIN_CLASS() {
      if(m_nhHandle) {
	delete m_nhHandle;
      }

      if(m_aspnAsyncSpinner) {
	delete m_aspnAsyncSpinner;
      }
    }

    Result PLUGIN_CLASS::init(int argc, char** argv) {
      Result resInit = defaultResult();

      CDesignator* cdConfig = this->getIndividualConfig();

      this->setSubscribedToEvent("add-image-from-file", true);
      this->setSubscribedToEvent("add-image-from-topic", true);
      this->setSubscribedToEvent("symbolic-create-designator", true);
      this->setSubscribedToEvent("interactive-callback", true);

      if(cdConfig->floatValue("roslog-messages") != 0) {
	this->setSubscribedToEvent("status-message", false);
      }

      if(!ros::ok()) {
	string strROSNodeName = cdConfig->stringValue("node-name");

	if(strROSNodeName == "") {
	  strROSNodeName = "beliefstate_ros";
	}

	this->info("Starting ROS node '" + strROSNodeName + "'.");

	ros::init(argc, argv, strROSNodeName);
	m_nhHandle = new ros::NodeHandle("~");

	if(ros::ok()) {
	  m_srvBeginContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("begin_context", &PLUGIN_CLASS::serviceCallbackBeginContext, this);
	  m_srvEndContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("end_context", &PLUGIN_CLASS::serviceCallbackEndContext, this);
	  m_srvAlterContext = m_nhHandle->advertiseService<PLUGIN_CLASS>("alter_context", &PLUGIN_CLASS::serviceCallbackAlterContext, this);
	  m_pubLoggedDesignators = m_nhHandle->advertise<designator_integration_msgs::Designator>("/logged_designators", 1);
	  m_pubInteractiveCallback = m_nhHandle->advertise<designator_integration_msgs::Designator>("/interactive_callback", 1);

	  if(cdConfig->floatValue("roslog-messages") != 0) {
	    string strTopic = cdConfig->stringValue("roslog-topic");

	    if(strTopic != "") {
	      m_pubStatusMessages = m_nhHandle->advertise<rosgraph_msgs::Log>(strTopic, 1);
	      m_bRoslogMessages = true;
	    } else {
	      this->warn("You requested the status messages to be roslog'ged, but didn't specify a roslog topic. Ignoring the whole thing.");
	    }
	  }

	  int nThreads = 4;
	  if(cdConfig->childForKey("async-threads")) {
	    nThreads = cdConfig->floatValue("async-threads");
	  }

	  stringstream sts;
	  sts << nThreads;

	  this->info("ROS node started. Starting to spin (" + sts.str() + " threads).");
	  m_aspnAsyncSpinner = new ros::AsyncSpinner(nThreads);
	  m_aspnAsyncSpinner->start();
	} else {
	  resInit.bSuccess = false;
	  resInit.strErrorMessage = "Failed to start ROS node.";
	}
      } else {
      	this->warn("ROS node already started.");
      }

      return resInit;
    }

    Result PLUGIN_CLASS::deinit() {
      ros::shutdown();

      return defaultResult();
    }

    Result PLUGIN_CLASS::cycle() {
      Result resCycle = defaultResult();
      this->deployCycleData(resCycle);

      return resCycle;
    }

    bool PLUGIN_CLASS::serviceCallbackBeginContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evBeginContext = defaultEvent("begin-context");
      evBeginContext.nContextID = createContextID();
      evBeginContext.cdDesignator = new CDesignator(req.request.designator);

      stringstream sts;
      sts << evBeginContext.nContextID;

      this->info("When beginning context (ID = " + sts.str() + "), received " + this->getDesignatorTypeString(evBeginContext.cdDesignator) + " designator");
      this->deployEvent(evBeginContext);

      CDesignator *desigResponse = new CDesignator();
      desigResponse->setType(ACTION);
      desigResponse->setValue(string("_id"), evBeginContext.nContextID);

      res.response.designators.push_back(desigResponse->serializeToMessage());
      delete desigResponse;

      return true;
    }

    bool PLUGIN_CLASS::serviceCallbackEndContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evEndContext = defaultEvent("end-context");
      evEndContext.cdDesignator = new CDesignator(req.request.designator);

      int nContextID = (int)evEndContext.cdDesignator->floatValue("_id");
      stringstream sts;
      sts << nContextID;

      this->info("When ending context (ID = " + sts.str() + "), received " + this->getDesignatorTypeString(evEndContext.cdDesignator) + " designator");
      this->deployEvent(evEndContext);

      freeContextID(nContextID);

      return true;
    }

    bool PLUGIN_CLASS::serviceCallbackAlterContext(designator_integration_msgs::DesignatorCommunication::Request &req, designator_integration_msgs::DesignatorCommunication::Response &res) {
      Event evAlterContext = defaultEvent();
      evAlterContext.cdDesignator = new CDesignator(req.request.designator);

      this->info("When altering context, received " + this->getDesignatorTypeString(evAlterContext.cdDesignator) + " designator");

      string strCommand = evAlterContext.cdDesignator->stringValue("command");
      transform(strCommand.begin(), strCommand.end(), strCommand.begin(), ::tolower);

      if(strCommand == "add-image") {
	evAlterContext.strEventName = "add-image-from-topic";
	evAlterContext.nOpenRequestID = this->openNewRequestID();
      } else if(strCommand == "add-failure") {
	evAlterContext.strEventName = "add-failure";
      } else if(strCommand == "add-designator") {
	evAlterContext.strEventName = "add-designator";
      } else if(strCommand == "equate-designators") {
	evAlterContext.strEventName = "equate-designators";
      } else if(strCommand == "add-object") {
	evAlterContext.strEventName = "add-object";
      } else if(strCommand == "export-planlog") {
	evAlterContext.strEventName = "export-planlog";
      } else if(strCommand == "start-new-experiment") {
	evAlterContext.strEventName = "start-new-experiment";
      } else if(strCommand == "set-experiment-meta-data") {
	evAlterContext.strEventName = "set-experiment-meta-data";
      } else if(strCommand == "register-interactive-object") {
	evAlterContext.strEventName = "symbolic-add-object";
      } else if(strCommand == "unregister-interactive-object") {
	evAlterContext.strEventName = "symbolic-remove-object";
      } else if(strCommand == "set-interactive-object-menu") {
	evAlterContext.strEventName = "symbolic-set-interactive-object-menu";
      } else if(strCommand == "update-interactive-object-pose") {
	evAlterContext.strEventName = "symbolic-update-object-pose";
      } else {
	this->warn("Unknown command when altering context: '" + strCommand + "'");
      }

      this->deployEvent(evAlterContext, true);

      return true;
    }

    void PLUGIN_CLASS::consumeEvent(Event evEvent) {
      if(evEvent.bRequest == false) {
	this->closeRequestID(evEvent.nOpenRequestID);
      } else {
	if(evEvent.strEventName == "symbolic-create-designator") {
	  if(evEvent.cdDesignator) {
	    m_pubLoggedDesignators.publish(evEvent.cdDesignator->serializeToMessage());
	  }
	} else if(evEvent.strEventName == "interactive-callback") {
	  if(evEvent.cdDesignator) {
	    m_pubInteractiveCallback.publish(evEvent.cdDesignator->serializeToMessage());
	  }
	} else if(evEvent.strEventName == "status-message") {
	  if(m_bRoslogMessages) {
	    StatusMessage msgStatus = evEvent.msgStatusMessage;
	    rosgraph_msgs::Log rgmLogMessage;

	    if(msgStatus.bBold == true) {
	      rgmLogMessage.level = rosgraph_msgs::Log::WARN;
	    } else {
	      rgmLogMessage.level = rosgraph_msgs::Log::INFO;
	    }

	    rgmLogMessage.name = msgStatus.strPrefix;
	    rgmLogMessage.msg = msgStatus.strMessage;

	    m_pubStatusMessages.publish(rgmLogMessage);
	  }
	}
      }
    }

    Event PLUGIN_CLASS::consumeServiceEvent(ServiceEvent seServiceEvent) {
      Event evService = defaultEvent();

      this->info("Consume service event of type '" + seServiceEvent.strServiceName + "'!");

      return evService;
    }

    string PLUGIN_CLASS::getDesignatorTypeString(CDesignator* desigDesignator) {
      string strDesigType = "UNKNOWN";
      switch(desigDesignator->type()) {
      case ACTION:
	strDesigType = "ACTION";
	break;

      case OBJECT:
	strDesigType = "OBJECT";
	break;

      case LOCATION:
	strDesigType = "LOCATION";
	break;

      default:
	break;
      }

      return strDesigType;
    }
  }

  extern "C" plugins::PLUGIN_CLASS* createInstance() {
    return new plugins::PLUGIN_CLASS();
  }

  extern "C" void destroyInstance(plugins::PLUGIN_CLASS* icDestroy) {
    delete icDestroy;
  }
}
<|endoftext|>


<commit_before>#include <nan.h>
#include <v8.h>
#include <poppler.h>
#include <cairo.h>
#include <cairo-svg.h>

namespace sspdf {

using v8::Local;
using v8::Value;
using v8::Function;
using v8::Exception;
using v8::Isolate;
using v8::Object;
using v8::Array;
using v8::Uint8Array;
using Nan::Callback;
using Nan::GetFunction;
using Nan::Set;
using Nan::Null;
using Nan::New;
using Nan::AsyncWorker;
using Nan::HandleScope;
using Nan::ThrowTypeError;
using Nan::Persistent;
using Nan::ObjectWrap;

const char* MSG_EXCEPTION_ZEROLEN =  "Zero length buffer provided.";

class PdfssWorker : public AsyncWorker {
  public:
    char* pdfData = NULL;
    Persistent<Uint8Array>* pdfBuffer = NULL;
    size_t pdfLen = 0;
    double pw, ph;
    char* txt;
    PopplerRectangle* rects;
    guint rectLen;
    char* error = NULL;
    int destPage;
    PdfssWorker(Callback* cb, Persistent<Uint8Array>* pdfBuffer, int destPage)
      : AsyncWorker(cb) {
      this->destPage = destPage;
      this->pdfBuffer = pdfBuffer;
      Local<Uint8Array> hPdf = New<Uint8Array>(*pdfBuffer);
      this->pdfLen = (*hPdf)->ByteLength();
      if (this->pdfLen == 0) {
        this->error = new char[strlen(MSG_EXCEPTION_ZEROLEN)];
        strcpy(this->error, MSG_EXCEPTION_ZEROLEN);
      } else {
        this->pdfData = (((char*)(*(*hPdf)->Buffer())->GetContents().Data())) + (*hPdf)->ByteOffset();
      }
    }

    void Execute () {
      if (this->error != NULL) {
        return;
      }
      GError* gerror = NULL;
      PopplerDocument* pd = poppler_document_new_from_data(this->pdfData, this->pdfLen, NULL, &gerror);
      if (pd == NULL) {
        this->error = new char[strlen(gerror->message)];
        strcpy(this->error, gerror->message);
        g_error_free(gerror);
        gerror = NULL;
        return;
      }
      PopplerPage* pg = poppler_document_get_page(pd, this->destPage);
      poppler_page_get_size(pg, &this->pw, &this->ph);
      this->txt = poppler_page_get_text(pg);
      poppler_page_get_text_layout(pg, &this->rects, &this->rectLen);
    }

    void HandleOKCallback () {
      HandleScope scope;
      Local<Object> obj;
      Local<Array> rects;
      Local<Value> argv[] = {
        Null(), Null()
      };
      if (this->error == NULL) {
        obj = New<Object>();
        Set(obj, New<v8::String>("pw").ToLocalChecked(), New<v8::Number>(this->pw));
        Set(obj, New<v8::String>("ph").ToLocalChecked(), New<v8::Number>(this->ph));
        Set(obj, New<v8::String>("txt").ToLocalChecked(), New<v8::String>(this->txt).ToLocalChecked());
        rects = New<v8::Array>(this->rectLen);
        for (guint i = 0; i < this->rectLen; i ++) {
          Local<Object> xy = New<Object>();
          Set(xy, New<v8::String>("x1").ToLocalChecked(), New<v8::Number>(this->rects[i].x1));
          Set(xy, New<v8::String>("y1").ToLocalChecked(), New<v8::Number>(this->rects[i].y1));
          Set(xy, New<v8::String>("x2").ToLocalChecked(), New<v8::Number>(this->rects[i].x2));
          Set(xy, New<v8::String>("y2").ToLocalChecked(), New<v8::Number>(this->rects[i].y2));
          Set(rects, New<v8::Number>(i), xy);
        }
        Set(obj, New<v8::String>("rects").ToLocalChecked(), rects);
        g_free(this->rects);
        argv[1] = obj;
      } else {
        argv[0] = v8::Exception::Error(New<v8::String>(this->error).ToLocalChecked());
        delete this->error;
        this->error = NULL;
      }
      this->callback->Call(2, argv);
      if (this->pdfBuffer != NULL) {
        this->pdfBuffer->Reset();
        delete this->pdfBuffer;
        this->pdfBuffer = NULL;
      }
    }
};

NAN_METHOD(getPage) {
  if (info.Length() != 3) {
    ThrowTypeError("getPage(pdfBuffer, pageNum, callback)");
    return;
  }
  if (!info[0]->IsUint8Array()) {
    ThrowTypeError("arg[0] is not a buffer.");
    return;
  }
  if (!info[1]->IsInt32()) {
    ThrowTypeError("arg[1] is not a int32.");
    return;
  }
  if (!info[2]->IsFunction()) {
    ThrowTypeError("arg[2] is not a function.");
    return;
  }
  int pn = (int)(*info[1].As<v8::Number>())->Value();
  if (pn < 0) {
    ThrowTypeError("arg[1] shouldn't be < 0.");
    return;
  }
  Callback *callback = new Callback(info[2].As<Function>());
  AsyncQueueWorker(new PdfssWorker(callback, new Persistent<Uint8Array>(info[0].As<Uint8Array>()), pn));
}

NAN_MODULE_INIT(Init) {
  Set(target
    , New<v8::String>("getPage").ToLocalChecked()
    , New<v8::FunctionTemplate>(getPage)->GetFunction());
}

NODE_MODULE(sspdf, Init)

}
<commit_msg>sspdf.getPage return svg<commit_after>#include <nan.h>
#include <v8.h>
#include <poppler.h>
#include <cairo.h>
#include <cairo-svg.h>
#include <vector>

namespace sspdf {

using v8::Local;
using v8::Value;
using v8::Function;
using v8::Exception;
using v8::Isolate;
using v8::Object;
using v8::Array;
using v8::Uint8Array;
using v8::ArrayBuffer;
using Nan::Callback;
using Nan::GetFunction;
using Nan::Set;
using Nan::Null;
using Nan::New;
using Nan::AsyncWorker;
using Nan::HandleScope;
using Nan::ThrowTypeError;
using Nan::Persistent;
using Nan::ObjectWrap;
using std::vector;

const char* MSG_EXCEPTION_ZEROLEN =  "Zero length buffer provided.";

class PdfssWorker : public AsyncWorker {
  public:
    char* pdfData = NULL;
    size_t pdfLen = 0;
    double pw, ph;
    char* txt;
    PopplerRectangle* rects;
    guint rectLen;
    char* error = NULL;
    int destPage;
    vector<char> svgData;
    PdfssWorker(Callback* cb, Local<Uint8Array> hPdf, int destPage)
      : AsyncWorker(cb) {
      this->destPage = destPage;
      this->pdfLen = (*hPdf)->ByteLength();
      if (this->pdfLen == 0) {
        this->error = new char[strlen(MSG_EXCEPTION_ZEROLEN)];
        strcpy(this->error, MSG_EXCEPTION_ZEROLEN);
      } else {
        char* pdfData = (((char*)(*(*hPdf)->Buffer())->GetContents().Data())) + (*hPdf)->ByteOffset();
        this->pdfData = new char[this->pdfLen];
        memcpy(this->pdfData, pdfData, this->pdfLen);
      }
    }

    void Execute () {
      if (this->error != NULL) {
        return;
      }
      GError* gerror = NULL;
      PopplerDocument* pd = poppler_document_new_from_data(this->pdfData, this->pdfLen, NULL, &gerror);
      if (pd == NULL) {
        this->error = new char[strlen(gerror->message)];
        strcpy(this->error, gerror->message);
        g_error_free(gerror);
        gerror = NULL;
        return;
      }
      PopplerPage* pg = poppler_document_get_page(pd, this->destPage);
      poppler_page_get_size(pg, &this->pw, &this->ph);
      this->txt = poppler_page_get_text(pg);
      poppler_page_get_text_layout(pg, &this->rects, &this->rectLen);

      cairo_surface_t* svgSurface = cairo_svg_surface_create_for_stream((cairo_write_func_t) PdfssWorker::writeFunc, this, this->pw, this->ph);
      cairo_t* svg = cairo_create(svgSurface);
      poppler_page_render(pg, svg);
      cairo_surface_destroy(svgSurface);
      cairo_destroy(svg);

      // g_free(pg); ( led to crash )
      // g_free(pd);
    }

    void HandleOKCallback () {
      HandleScope scope;
      Local<Object> obj;
      Local<Array> rects;
      Local<Value> argv[] = {
        Null(), Null()
      };
      if (this->error == NULL) {
        obj = New<Object>();
        Set(obj, New<v8::String>("pw").ToLocalChecked(), New<v8::Number>(this->pw));
        Set(obj, New<v8::String>("ph").ToLocalChecked(), New<v8::Number>(this->ph));
        Set(obj, New<v8::String>("txt").ToLocalChecked(), New<v8::String>(this->txt).ToLocalChecked());
        rects = New<v8::Array>(this->rectLen);
        for (guint i = 0; i < this->rectLen; i ++) {
          Local<Object> xy = New<Object>();
          Set(xy, New<v8::String>("x1").ToLocalChecked(), New<v8::Number>(this->rects[i].x1));
          Set(xy, New<v8::String>("y1").ToLocalChecked(), New<v8::Number>(this->rects[i].y1));
          Set(xy, New<v8::String>("x2").ToLocalChecked(), New<v8::Number>(this->rects[i].x2));
          Set(xy, New<v8::String>("y2").ToLocalChecked(), New<v8::Number>(this->rects[i].y2));
          Set(rects, New<v8::Number>(i), xy);
        }
        Set(obj, New<v8::String>("rects").ToLocalChecked(), rects);
        g_free(this->rects);
        argv[1] = obj;

        Local<ArrayBuffer> svgABuffer = ArrayBuffer::New(Isolate::GetCurrent(), this->svgData.size());
        char* svgBuffer = (char*)((*svgABuffer)->GetContents().Data());
        memcpy(svgBuffer, &(*this->svgData.begin()), this->svgData.size());

        if (this->svgData.size() > 0) {
          auto ml = node::Buffer::Copy(Isolate::GetCurrent(), &(*this->svgData.begin()), this->svgData.size());
          if (ml.IsEmpty()) {
            argv[0] = v8::Exception::Error(New<v8::String>("Can't return svg data.").ToLocalChecked());
          } else {
            Set(obj, New<v8::String>("svg").ToLocalChecked(), ml.ToLocalChecked());
          }
        } else {
          Set(obj, New<v8::String>("svg").ToLocalChecked(), Null());
        }
      } else {
        argv[0] = v8::Exception::Error(New<v8::String>(this->error).ToLocalChecked());
        delete this->error;
        this->error = NULL;
      }
      this->callback->Call(2, argv);
      if (this->pdfData != NULL) {
        delete this->pdfData;
        this->pdfData = NULL;
      }
    }
    static cairo_status_t writeFunc (void* closure, const unsigned char* data, unsigned int length) {
      PdfssWorker* worker = (PdfssWorker*) closure;
      worker->svgData.reserve(worker->svgData.size() + length);
      for (unsigned int i = 0; i < length; i ++) {
        worker->svgData.push_back(data[i]);
      }
      return CAIRO_STATUS_SUCCESS;
    }
};

NAN_METHOD(getPage) {
  if (info.Length() != 3) {
    ThrowTypeError("getPage(pdfBuffer, pageNum, callback)");
    return;
  }
  if (!info[0]->IsUint8Array()) {
    ThrowTypeError("arg[0] is not a buffer.");
    return;
  }
  if (!info[1]->IsInt32()) {
    ThrowTypeError("arg[1] is not a int32.");
    return;
  }
  if (!info[2]->IsFunction()) {
    ThrowTypeError("arg[2] is not a function.");
    return;
  }
  int pn = (int)(*info[1].As<v8::Number>())->Value();
  if (pn < 0) {
    ThrowTypeError("arg[1] shouldn't be < 0.");
    return;
  }
  auto pdfBuffer = info[0].As<Uint8Array>();
  if (pdfBuffer.IsEmpty()) {
    ThrowTypeError("arg[0] can't resolve.");
    return;
  }
  Callback *callback = new Callback(info[2].As<Function>());
  AsyncQueueWorker(new PdfssWorker(callback, pdfBuffer, pn));
}

NAN_MODULE_INIT(Init) {
  Set(target
    , New<v8::String>("getPage").ToLocalChecked()
    , New<v8::FunctionTemplate>(getPage)->GetFunction());
}

NODE_MODULE(sspdf, Init)

}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2017 Social Robotics Lab, Yale University
 * Author: Alessandro Roncone
 * email:  alessandro.roncone@yale.edu
 * website: www.scazlab.yale.edu
 * Permission is granted to copy, distribute, and/or modify this program
 * under the terms of the GNU Lesser General Public License, version 2.1 or any
 * later version published by the Free Software Foundation.
 *
 * 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
**/

#include "robot_utils/particle_thread.h"

/*****************************************************************************/
/*                             ParticleThread                                */
/*****************************************************************************/

ParticleThread::ParticleThread(std::string _name, double _thread_rate,
                               bool _rviz_visual) : name(_name), r(_thread_rate),
                               is_running(false), is_closing(false),
                               rviz_visual(_rviz_visual), start_time(ros::Time::now()),
                               is_particle_set(false), rviz_pub(_name)
{

}

void ParticleThread::internalThread()
{
    start_time = ros::Time::now();

    while(ros::ok() && not is_closing.get())
    {
        // ROS_INFO("Running..");
        Eigen::VectorXd new_pt;

        updateParticle(new_pt);
        setCurrPoint(new_pt);

        // ROS_INFO_STREAM("New particle position: " << getCurrPoint().transpose());

        r.sleep();
    }
}

bool ParticleThread::start()
{
    if (is_particle_set.get() && not is_running.get())
    {
        is_closing.set(false);
        thread     = std::thread(&ParticleThread::internalThread, this);
        is_running.set(true);

        if (rviz_visual) { rviz_pub.start(); };

        return true;
    }
    else
    {
        return false;
    }
}

bool ParticleThread::stop()
{
    is_closing.set(true);
    is_running.set(false);
    is_particle_set.set(false);

    if (rviz_visual) { rviz_pub.stop(); };

    if (thread.joinable())
    {
        thread.join();
    }

    is_closing.set(false);

    return true;
}

double ParticleThread::getRate()
{
    return 1/r.expectedCycleTime().toSec();
}

void ParticleThread::setMarker()
{
    Eigen::Vector3d _curr_pt = getCurrPoint();

    geometry_msgs::Pose mrk_pos;
    mrk_pos.position.x = _curr_pt[0];
    mrk_pos.position.y = _curr_pt[1];
    mrk_pos.position.z = _curr_pt[2];

    RVIZMarker curr_mrk(mrk_pos, ColorRGBA(0.0, 1.0, 1.0), 0.03);

    rviz_pub.setMarkers(std::vector<RVIZMarker>{curr_mrk});
}

Eigen::VectorXd ParticleThread::getCurrPoint()
{
    return curr_pt.get();
}

bool ParticleThread::setCurrPoint(const Eigen::VectorXd& _curr_pt)
{
    if (rviz_visual) { setMarker(); };

    return curr_pt.set(_curr_pt);
}

ParticleThread::~ParticleThread()
{
    stop();
}

/*****************************************************************************/
/*                           ParticleThreadImpl                              */
/*****************************************************************************/
ParticleThreadImpl::ParticleThreadImpl(std::string _name, double _thread_rate,
                                       bool _rviz_visual) :
                                       ParticleThread(_name, _thread_rate, _rviz_visual)
{
    is_particle_set.set(true);
}

bool ParticleThreadImpl::updateParticle(Eigen::VectorXd& _new_pt)
{
    _new_pt = Eigen::Vector3d(1.0, 1.0, 1.0);

    return true;
}

/*****************************************************************************/
/*                          LinearPointParticle                              */
/*****************************************************************************/

LinearPointParticle::LinearPointParticle(std::string _name, double _thread_rate,
                                         bool _rviz_visual) :
                                         ParticleThread(_name, _thread_rate, _rviz_visual),
                                         speed(double(0.0)), start_pt(Eigen::Vector3d(0.0, 0.0, 0.0)),
                                         des_pt(Eigen::Vector3d(0.0, 0.0, 0.0))
{

}

bool LinearPointParticle::updateParticle(Eigen::VectorXd& _new_pt)
{
    double elap_time = (ros::Time::now() - start_time).toSec();

    Eigen::Vector3d p_sd = des_pt.get() - start_pt.get();

    // We model the particle as a 3D point that moves toward the
    // target with a straight trajectory and constant speed.
    _new_pt = start_pt.get() + p_sd / p_sd.norm() * speed.get() * elap_time;

    Eigen::Vector3d p_cd = des_pt.get() - _new_pt;

    // Check if the current position is overshooting the desired position
    // By checking the sign of the cosine of the angle between p_sd and p_cd
    // This would mean equal to 1 within some small epsilon (1e-8)
    if ((p_sd.dot(p_cd))/(p_sd.norm()*p_cd.norm()) - 1 <  EPSILON &&
        (p_sd.dot(p_cd))/(p_sd.norm()*p_cd.norm()) - 1 > -EPSILON)
    {
        return true;
    }

    _new_pt = des_pt.get();
    return false;
}

void LinearPointParticle::setMarker()
{
    ParticleThread::setMarker();

    Eigen::Vector3d _des_pt = des_pt.get();

    geometry_msgs::Pose mrk_pos;
    mrk_pos.position.x = _des_pt[0];
    mrk_pos.position.y = _des_pt[1];
    mrk_pos.position.z = _des_pt[2];

    RVIZMarker des_mrk(mrk_pos, ColorRGBA(1.0, 1.0, 0.0));

    rviz_pub.push_back(des_mrk);
}

bool LinearPointParticle::setupParticle(const Eigen::Vector3d& _start_pt,
                                        const Eigen::Vector3d&   _des_pt,
                                        double _speed)
{
    start_pt.set(_start_pt);
      des_pt.set(  _des_pt);
       speed.set(   _speed);

    is_particle_set.set(true);

    return true;
}

LinearPointParticle::~LinearPointParticle()
{

}

<commit_msg>[particle_thread] Costmetic changes<commit_after>/**
 * Copyright (C) 2017 Social Robotics Lab, Yale University
 * Author: Alessandro Roncone
 * email:  alessandro.roncone@yale.edu
 * website: www.scazlab.yale.edu
 * Permission is granted to copy, distribute, and/or modify this program
 * under the terms of the GNU Lesser General Public License, version 2.1 or any
 * later version published by the Free Software Foundation.
 *
 * 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
**/

#include "robot_utils/particle_thread.h"

/*****************************************************************************/
/*                             ParticleThread                                */
/*****************************************************************************/
ParticleThread::ParticleThread(std::string _name, double _thread_rate, bool _rviz_visual) :
                               name(_name), r(_thread_rate), is_running(false), is_closing(false),
                               rviz_visual(_rviz_visual), start_time(ros::Time::now()),
                               is_particle_set(false), rviz_pub(_name)
{

}

void ParticleThread::internalThread()
{
    start_time = ros::Time::now();

    while(ros::ok() && not is_closing.get())
    {
        // ROS_INFO("Running..");
        Eigen::VectorXd new_pt;

        updateParticle(new_pt);
        setCurrPoint(new_pt);

        // ROS_INFO_STREAM("New particle position: " << getCurrPoint().transpose());

        r.sleep();
    }
}

bool ParticleThread::start()
{
    if (is_particle_set.get() && not is_running.get())
    {
        is_closing.set(false);
        thread     = std::thread(&ParticleThread::internalThread, this);
        is_running.set(true);

        if (rviz_visual) { rviz_pub.start(); };

        return true;
    }
    else
    {
        return false;
    }
}

bool ParticleThread::stop()
{
    is_closing.set(true);
    is_running.set(false);
    is_particle_set.set(false);

    if (rviz_visual) { rviz_pub.stop(); };

    if (thread.joinable())
    {
        thread.join();
    }

    is_closing.set(false);

    return true;
}

double ParticleThread::getRate()
{
    return 1/r.expectedCycleTime().toSec();
}

void ParticleThread::setMarker()
{
    Eigen::Vector3d _curr_pt = getCurrPoint();

    geometry_msgs::Pose mrk_pos;
    mrk_pos.position.x = _curr_pt[0];
    mrk_pos.position.y = _curr_pt[1];
    mrk_pos.position.z = _curr_pt[2];

    RVIZMarker curr_mrk(mrk_pos, ColorRGBA(0.0, 1.0, 1.0), 0.03);

    rviz_pub.setMarkers(std::vector<RVIZMarker>{curr_mrk});
}

Eigen::VectorXd ParticleThread::getCurrPoint()
{
    return curr_pt.get();
}

bool ParticleThread::setCurrPoint(const Eigen::VectorXd& _curr_pt)
{
    if (rviz_visual) { setMarker(); };

    return curr_pt.set(_curr_pt);
}

ParticleThread::~ParticleThread()
{
    stop();
}

/*****************************************************************************/
/*                           ParticleThreadImpl                              */
/*****************************************************************************/
ParticleThreadImpl::ParticleThreadImpl(std::string _name, double _thread_rate, bool _rviz_visual) :
                                       ParticleThread(_name, _thread_rate, _rviz_visual)
{
    is_particle_set.set(true);
}

bool ParticleThreadImpl::updateParticle(Eigen::VectorXd& _new_pt)
{
    _new_pt = Eigen::Vector3d(1.0, 1.0, 1.0);

    return true;
}

/*****************************************************************************/
/*                          LinearPointParticle                              */
/*****************************************************************************/
LinearPointParticle::LinearPointParticle(std::string _name, double _thread_rate, bool _rviz_visual) :
                                         ParticleThread(_name, _thread_rate, _rviz_visual),
                                         speed(double(0.0)), start_pt(Eigen::Vector3d(0.0, 0.0, 0.0)),
                                         des_pt(Eigen::Vector3d(0.0, 0.0, 0.0))
{

}

bool LinearPointParticle::updateParticle(Eigen::VectorXd& _new_pt)
{
    double elap_time = (ros::Time::now() - start_time).toSec();

    Eigen::Vector3d p_sd = des_pt.get() - start_pt.get();

    // We model the particle as a 3D point that moves toward the
    // target with a straight trajectory and constant speed.
    _new_pt = start_pt.get() + p_sd / p_sd.norm() * speed.get() * elap_time;

    Eigen::Vector3d p_cd = des_pt.get() - _new_pt;

    // Check if the current position is overshooting the desired position
    // By checking the sign of the cosine of the angle between p_sd and p_cd
    // This would mean equal to 1 within some small epsilon (1e-8)
    if ((p_sd.dot(p_cd))/(p_sd.norm()*p_cd.norm()) - 1 <  EPSILON &&
        (p_sd.dot(p_cd))/(p_sd.norm()*p_cd.norm()) - 1 > -EPSILON)
    {
        return true;
    }

    _new_pt = des_pt.get();
    return false;
}

void LinearPointParticle::setMarker()
{
    ParticleThread::setMarker();

    Eigen::Vector3d _des_pt = des_pt.get();

    geometry_msgs::Pose mrk_pos;
    mrk_pos.position.x = _des_pt[0];
    mrk_pos.position.y = _des_pt[1];
    mrk_pos.position.z = _des_pt[2];

    RVIZMarker des_mrk(mrk_pos, ColorRGBA(1.0, 1.0, 0.0));

    rviz_pub.push_back(des_mrk);
}

bool LinearPointParticle::setupParticle(const Eigen::Vector3d& _start_pt,
                                        const Eigen::Vector3d&   _des_pt,
                                        double _speed)
{
    start_pt.set(_start_pt);
      des_pt.set(  _des_pt);
       speed.set(   _speed);

    is_particle_set.set(true);

    return true;
}

LinearPointParticle::~LinearPointParticle()
{

}

<|endoftext|>


<commit_before>//
//  poVideoPlayer.cpp
//  VideoPlayer
//
//  Created by Stephen Varga on 6/17/14.
//
//

#include "poVideoPlayer.h"

namespace po {
    VideoPlayerRef VideoPlayer::create() {
        VideoPlayerRef ref = VideoPlayerRef(new VideoPlayer());
        ref->setup();
        return ref;
    }

    VideoPlayer::VideoPlayer()
    {
    }

    void VideoPlayer::update()
    {
        if(mVideo && mVideo->checkNewFrame()) mVideoTex = mVideo->getTexture();
    }

    ci::Rectf VideoPlayer::getBounds()
    {
        if(mVideo) return mVideo->getBounds();
        return ci::Rectf(0,0,0,0);
    }

    void VideoPlayer::draw()
    {
        if(mVideoTex) {
            ci::gl::color(ci::ColorA(getFillColor(), getAppliedAlpha()));
            ci::gl::draw(mVideoTex);
        }
    }

    void VideoPlayer::load(const ci::fs::path &moviePath)
    {
        try {
            mVideo = ci::qtime::MovieGl::create(moviePath);
        }
        catch( ... ) {
            ci::app::console() << "Unable to load the movie from location " << moviePath << std::endl;
            mVideo->reset();
            mVideoTex.reset();
        }
    }

    void VideoPlayer::load(const ci::DataSourceRef data)
    {
        try {
            mVideo = ci::qtime::MovieGl::create(data);
        }
        catch( ... ) {
            ci::app::console() << "Unable to load the movie from location " << data << std::endl;
            mVideo.reset();
            mVideoTex.reset();
        }
    }

    void VideoPlayer::unload() {
        mVideo.reset();
        mVideoTex.reset();
    }
}<commit_msg>Changed pointer to dot syntax when resetting var<commit_after>//
//  poVideoPlayer.cpp
//  VideoPlayer
//
//  Created by Stephen Varga on 6/17/14.
//
//

#include "poVideoPlayer.h"

namespace po {
    VideoPlayerRef VideoPlayer::create() {
        VideoPlayerRef ref = VideoPlayerRef(new VideoPlayer());
        ref->setup();
        return ref;
    }

    VideoPlayer::VideoPlayer()
    {
    }

    void VideoPlayer::update()
    {
        if(mVideo && mVideo->checkNewFrame()) mVideoTex = mVideo->getTexture();
    }

    ci::Rectf VideoPlayer::getBounds()
    {
        if(mVideo) return mVideo->getBounds();
        return ci::Rectf(0,0,0,0);
    }

    void VideoPlayer::draw()
    {
        if(mVideoTex) {
            ci::gl::color(ci::ColorA(getFillColor(), getAppliedAlpha()));
            ci::gl::draw(mVideoTex);
        }
    }

    void VideoPlayer::load(const ci::fs::path &moviePath)
    {
        try {
            mVideo = ci::qtime::MovieGl::create(moviePath);
        }
        catch( ... ) {
            ci::app::console() << "Unable to load the movie from location " << moviePath << std::endl;
            mVideo.reset();
            mVideoTex.reset();
        }
    }

    void VideoPlayer::load(const ci::DataSourceRef data)
    {
        try {
            mVideo = ci::qtime::MovieGl::create(data);
        }
        catch( ... ) {
            ci::app::console() << "Unable to load the movie from location " << data << std::endl;
            mVideo.reset();
            mVideoTex.reset();
        }
    }

    void VideoPlayer::unload() {
        mVideo.reset();
        mVideoTex.reset();
    }
}<|endoftext|>


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

#include <cstdlib>
// emscripten
#include <emscripten/bind.h>
#include <emscripten/val.h>
// libvpx
#include "vpxenc.h"
#include "vpx/vp8cx.h"
// libwebm
#include "mkvmuxer.hpp"
// libyuv
#include "libyuv.h"
// Our MyMkvWriters
#include "./mkvwriter/mymkvwriter.hpp"
#include "./mkvwriter/mymkvstreamwriter.hpp"

using namespace emscripten;
using namespace mkvmuxer;

int vpx_img_plane_width(const vpx_image_t *img, int plane);
int vpx_img_plane_height(const vpx_image_t *img, int plane);
void clear_image(vpx_image_t *img) ;

class WebmEncoder {
  public:
    WebmEncoder(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate, bool realtime, bool klive, val cb);
    ~WebmEncoder();
    bool addRGBAFrame(std::string rgba);
    bool finalize();
    std::string lastError();

  private:
    bool InitCodec(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate);
    bool InitMkvWriter(bool klive, val cb);
    bool InitImageBuffer();

    bool RGBAtoVPXImage(const uint8_t *data);
    bool EncodeFrame(vpx_image_t *img, int frame_cnt);

    vpx_codec_ctx_t ctx;
    unsigned int frame_cnt = 0;
    vpx_codec_enc_cfg_t cfg;
    vpx_codec_iface_t* iface = vpx_codec_vp8_cx();
    vpx_image_t *img;
    std::string last_error;
    IMkvWriter *mkv_writer;
    Segment *main_segment;
    bool realtime = false;
};

WebmEncoder::WebmEncoder(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate_kbps, bool realtime_, bool klive, val cb): realtime(realtime_) {

  if(!InitCodec(timebase_num, timebase_den, width, height, bitrate_kbps)) {
    throw last_error;
  }
  if(!InitMkvWriter(klive, cb)) {
    throw last_error;
  }
  if(!InitImageBuffer()) {
    throw last_error;
  }
}

WebmEncoder::~WebmEncoder() {
  vpx_img_free(img);
  delete main_segment;
  if(realtime) {
    delete (MyMkvStreamWriter*)mkv_writer;
  } else {
    delete (MyMkvWriter*)mkv_writer;
  }
}

bool WebmEncoder::addRGBAFrame(std::string rgba) {
  RGBAtoVPXImage((const uint8_t*) rgba.c_str());
  if(!EncodeFrame(img, frame_cnt++)) {
    return false;
  }
  if(realtime) {
    ((MyMkvStreamWriter*)mkv_writer)->Notify();
  }
  return true;
}

bool WebmEncoder::finalize() {
  if(!EncodeFrame(NULL, -1)) {
    last_error = "Could not encode flush frame";
    return false;
  }

  if(!main_segment->Finalize()) {
    last_error = "Could not finalize mkv";
    return false;
  }
  if(realtime) {
    ((MyMkvStreamWriter*)mkv_writer)->Notify();
  } else {
    ((MyMkvWriter*)mkv_writer)->Notify();
  }
  return true;
}

std::string WebmEncoder::lastError() {
  return std::string(last_error);
}

bool WebmEncoder::EncodeFrame(vpx_image_t *img, int frame_cnt) {
  vpx_codec_iter_t iter = NULL;
  const vpx_codec_cx_pkt_t *pkt;
  vpx_codec_err_t err;

  err = vpx_codec_encode(
    &ctx,
    img,
    frame_cnt, /* time of frame */
    1, /* length of frame */
    0, /* flags. Use VPX_EFLAG_FORCE_KF to force a keyframe. */
    realtime ? VPX_DL_REALTIME : VPX_DL_BEST_QUALITY
  );
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }
  while((pkt = vpx_codec_get_cx_data(&ctx, &iter)) != NULL) {
    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
      continue;
    }
    auto frame_size = pkt->data.frame.sz;
    auto is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
    if(!main_segment->AddFrame(
      (uint8_t*) pkt->data.frame.buf,
      pkt->data.frame.sz,
      1, /* track id */
      pkt->data.frame.pts * 1000000000ULL * cfg.g_timebase.num/cfg.g_timebase.den,
      is_keyframe
    )) {
      last_error = "Could not add frame";
      return false;
    }
  }
  return true;
}

bool WebmEncoder::InitCodec(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate) {
  vpx_codec_err_t err;
  err = vpx_codec_enc_config_default(iface, &cfg, 0);
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }

  cfg.g_timebase.num = timebase_num;
  cfg.g_timebase.den = timebase_den;
  cfg.g_w = width;
  cfg.g_h = height;
  cfg.rc_target_bitrate = bitrate;

  err = vpx_codec_enc_init(
    &ctx,
    iface,
    &cfg,
    0 /* flags */
  );
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }
  return true;
}

bool WebmEncoder::InitMkvWriter(bool klive, val cb) {
  if(realtime) {
    mkv_writer = new MyMkvStreamWriter(cb);
  } else {
    mkv_writer = new MyMkvWriter(cb);
  }
  main_segment = new Segment();
  if(!main_segment->Init(mkv_writer)) {
    last_error = "Could not initialize main segment";
    return false;
  }
  if(main_segment->AddVideoTrack(cfg.g_w, cfg.g_h, 1 /* track id */) == 0) {
    last_error = "Could not add video track";
    return false;
  }
  main_segment->set_mode(klive ? Segment::Mode::kLive : Segment::Mode::kFile);
  auto info = main_segment->GetSegmentInfo();
  // Branding, yo
  auto muxing_app = std::string(info->muxing_app()) + " but in wasm";
  auto writing_app = std::string(info->writing_app()) + " but in wasm";
  info->set_writing_app(writing_app.c_str());
  info->set_muxing_app(muxing_app.c_str());
  return true;
}

bool WebmEncoder::InitImageBuffer() {
  img = vpx_img_alloc(
    NULL, /* allocate buffer on the heap */
    VPX_IMG_FMT_I420,
    cfg.g_w,
    cfg.g_h,
    0 /* align. simple_encoder says 1? */
  );
  if(img == NULL) {
    last_error = "Could not allocate vpx image buffer";
    return false;
  }
  return true;
}

bool WebmEncoder::RGBAtoVPXImage(const uint8_t *rgba) {
  clear_image(img);
  // litten endian BGRA means it is ARGB in memory
  if(
    libyuv::BGRAToI420(
      // Since we are ignoring opacity anyways (currently), we can use
      // this nasty nasty trick to avoid reshuffling the entire memory
      // from RGBA to ARGB.
      rgba-1,
      cfg.g_w*4,
      img->planes[VPX_PLANE_Y],
      img->stride[VPX_PLANE_Y],
      img->planes[VPX_PLANE_U],
      img->stride[VPX_PLANE_U],
      img->planes[VPX_PLANE_V],
      img->stride[VPX_PLANE_V],
      cfg.g_w,
      cfg.g_h
    ) != 0) {
    last_error = "Could not convert to I420";
    return false;
  }
  return true;
}

int vpx_img_plane_width(const vpx_image_t *img, int plane) {
  if ((plane == 1 || plane == 2) && img->x_chroma_shift > 0 )
    return (img->d_w + 1) >> img->x_chroma_shift;
  else
    return img->d_w;
}

int vpx_img_plane_height(const vpx_image_t *img, int plane) {
  if ((plane == 1 || plane == 2) && img->y_chroma_shift > 0)
    return (img->d_h + 1) >> img->y_chroma_shift;
  else
    return img->d_h;
}

void clear_image(vpx_image_t *img) {
  for(int plane = 0; plane < 4; plane++) {
    auto *row = img->planes[plane];
    if(!row) {
      continue;
    }
    auto plane_width = vpx_img_plane_width(img, plane);
    auto plane_height = vpx_img_plane_height(img, plane);
    uint8_t value = plane == 3 ? 1 : 0;
    for(int y = 0; y < plane_height; y++) {
      memset(row, value, plane_width);
      row += img->stride[plane];
    }
  }
}

EMSCRIPTEN_BINDINGS(my_module) {
  class_<WebmEncoder>("WebmEncoder")
    .constructor<int, int, unsigned int, unsigned int, unsigned int, bool, bool, val>()
    .function("addRGBAFrame", &WebmEncoder::addRGBAFrame)
    .function("finalize", &WebmEncoder::finalize)
    .function("lastError", &WebmEncoder::lastError);
}
<commit_msg>Fix finalization of video<commit_after>/**
 * Copyright 2018 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdlib>
// emscripten
#include <emscripten/bind.h>
#include <emscripten/val.h>
// libvpx
#include "vpxenc.h"
#include "vpx/vp8cx.h"
// libwebm
#include "mkvmuxer.hpp"
// libyuv
#include "libyuv.h"
// Our MyMkvWriters
#include "./mkvwriter/mymkvwriter.hpp"
#include "./mkvwriter/mymkvstreamwriter.hpp"

using namespace emscripten;
using namespace mkvmuxer;

int vpx_img_plane_width(const vpx_image_t *img, int plane);
int vpx_img_plane_height(const vpx_image_t *img, int plane);
void clear_image(vpx_image_t *img) ;

class WebmEncoder {
  public:
    WebmEncoder(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate, bool realtime, bool klive, val cb);
    ~WebmEncoder();
    bool addRGBAFrame(std::string rgba);
    bool finalize();
    std::string lastError();

  private:
    bool InitCodec(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate);
    bool InitMkvWriter(bool klive, val cb);
    bool InitImageBuffer();

    bool RGBAtoVPXImage(const uint8_t *data);
    bool EncodeFrame(vpx_image_t *img);

    vpx_codec_ctx_t ctx;
    unsigned int frame_cnt = 0;
    vpx_codec_enc_cfg_t cfg;
    vpx_codec_iface_t* iface = vpx_codec_vp8_cx();
    vpx_image_t *img;
    std::string last_error;
    IMkvWriter *mkv_writer;
    Segment *main_segment;
    bool realtime = false;
};

WebmEncoder::WebmEncoder(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate_kbps, bool realtime_, bool klive, val cb): realtime(realtime_) {

  if(!InitCodec(timebase_num, timebase_den, width, height, bitrate_kbps)) {
    throw last_error;
  }
  if(!InitMkvWriter(klive, cb)) {
    throw last_error;
  }
  if(!InitImageBuffer()) {
    throw last_error;
  }
}

WebmEncoder::~WebmEncoder() {
  vpx_img_free(img);
  delete main_segment;
  if(realtime) {
    delete (MyMkvStreamWriter*)mkv_writer;
  } else {
    delete (MyMkvWriter*)mkv_writer;
  }
}

bool WebmEncoder::addRGBAFrame(std::string rgba) {
  RGBAtoVPXImage((const uint8_t*) rgba.c_str());
  if(!EncodeFrame(img)) {
    return false;
  }
  if(realtime) {
    ((MyMkvStreamWriter*)mkv_writer)->Notify();
  }
  return true;
}

bool WebmEncoder::finalize() {
  if(!EncodeFrame(NULL)) {
    last_error = "Could not encode flush frame";
    return false;
  }

  if(!main_segment->Finalize()) {
    last_error = "Could not finalize mkv";
    return false;
  }
  if(realtime) {
    ((MyMkvStreamWriter*)mkv_writer)->Notify();
  } else {
    ((MyMkvWriter*)mkv_writer)->Notify();
  }
  return true;
}

std::string WebmEncoder::lastError() {
  return std::string(last_error);
}

bool WebmEncoder::EncodeFrame(vpx_image_t *img) {
  vpx_codec_iter_t iter = NULL;
  const vpx_codec_cx_pkt_t *pkt;
  vpx_codec_err_t err;

  err = vpx_codec_encode(
    &ctx,
    img,
    frame_cnt, /* time of frame */
    1, /* length of frame */
    0, /* flags. Use VPX_EFLAG_FORCE_KF to force a keyframe. */
    realtime ? VPX_DL_REALTIME : VPX_DL_BEST_QUALITY
  );
  frame_cnt++;
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }
  while((pkt = vpx_codec_get_cx_data(&ctx, &iter)) != NULL) {
    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
      continue;
    }
    auto frame_size = pkt->data.frame.sz;
    auto is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
    if(!main_segment->AddFrame(
      (uint8_t*) pkt->data.frame.buf,
      pkt->data.frame.sz,
      1, /* track id */
      pkt->data.frame.pts * 1000000000ULL * cfg.g_timebase.num/cfg.g_timebase.den,
      is_keyframe
    )) {
      last_error = "Could not add frame";
      return false;
    }
  }
  return true;
}

bool WebmEncoder::InitCodec(int timebase_num, int timebase_den, unsigned int width, unsigned int height, unsigned int bitrate) {
  vpx_codec_err_t err;
  err = vpx_codec_enc_config_default(iface, &cfg, 0);
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }

  cfg.g_timebase.num = timebase_num;
  cfg.g_timebase.den = timebase_den;
  cfg.g_w = width;
  cfg.g_h = height;
  cfg.rc_target_bitrate = bitrate;

  err = vpx_codec_enc_init(
    &ctx,
    iface,
    &cfg,
    0 /* flags */
  );
  if(err != VPX_CODEC_OK) {
    last_error = std::string(vpx_codec_err_to_string(err));
    return false;
  }
  return true;
}

bool WebmEncoder::InitMkvWriter(bool klive, val cb) {
  if(realtime) {
    mkv_writer = new MyMkvStreamWriter(cb);
  } else {
    mkv_writer = new MyMkvWriter(cb);
  }
  main_segment = new Segment();
  if(!main_segment->Init(mkv_writer)) {
    last_error = "Could not initialize main segment";
    return false;
  }
  if(main_segment->AddVideoTrack(cfg.g_w, cfg.g_h, 1 /* track id */) == 0) {
    last_error = "Could not add video track";
    return false;
  }
  main_segment->set_mode(klive ? Segment::Mode::kLive : Segment::Mode::kFile);
  auto info = main_segment->GetSegmentInfo();
  // Branding, yo
  auto muxing_app = std::string(info->muxing_app()) + " but in wasm";
  auto writing_app = std::string(info->writing_app()) + " but in wasm";
  info->set_writing_app(writing_app.c_str());
  info->set_muxing_app(muxing_app.c_str());
  return true;
}

bool WebmEncoder::InitImageBuffer() {
  img = vpx_img_alloc(
    NULL, /* allocate buffer on the heap */
    VPX_IMG_FMT_I420,
    cfg.g_w,
    cfg.g_h,
    0 /* align. simple_encoder says 1? */
  );
  if(img == NULL) {
    last_error = "Could not allocate vpx image buffer";
    return false;
  }
  return true;
}

bool WebmEncoder::RGBAtoVPXImage(const uint8_t *rgba) {
  clear_image(img);
  // litten endian BGRA means it is ARGB in memory
  if(
    libyuv::BGRAToI420(
      // Since we are ignoring opacity anyways (currently), we can use
      // this nasty nasty trick to avoid reshuffling the entire memory
      // from RGBA to ARGB.
      rgba-1,
      cfg.g_w*4,
      img->planes[VPX_PLANE_Y],
      img->stride[VPX_PLANE_Y],
      img->planes[VPX_PLANE_U],
      img->stride[VPX_PLANE_U],
      img->planes[VPX_PLANE_V],
      img->stride[VPX_PLANE_V],
      cfg.g_w,
      cfg.g_h
    ) != 0) {
    last_error = "Could not convert to I420";
    return false;
  }
  return true;
}

int vpx_img_plane_width(const vpx_image_t *img, int plane) {
  if ((plane == 1 || plane == 2) && img->x_chroma_shift > 0 )
    return (img->d_w + 1) >> img->x_chroma_shift;
  else
    return img->d_w;
}

int vpx_img_plane_height(const vpx_image_t *img, int plane) {
  if ((plane == 1 || plane == 2) && img->y_chroma_shift > 0)
    return (img->d_h + 1) >> img->y_chroma_shift;
  else
    return img->d_h;
}

void clear_image(vpx_image_t *img) {
  for(int plane = 0; plane < 4; plane++) {
    auto *row = img->planes[plane];
    if(!row) {
      continue;
    }
    auto plane_width = vpx_img_plane_width(img, plane);
    auto plane_height = vpx_img_plane_height(img, plane);
    uint8_t value = plane == 3 ? 1 : 0;
    for(int y = 0; y < plane_height; y++) {
      memset(row, value, plane_width);
      row += img->stride[plane];
    }
  }
}

EMSCRIPTEN_BINDINGS(my_module) {
  class_<WebmEncoder>("WebmEncoder")
    .constructor<int, int, unsigned int, unsigned int, unsigned int, bool, bool, val>()
    .function("addRGBAFrame", &WebmEncoder::addRGBAFrame)
    .function("finalize", &WebmEncoder::finalize)
    .function("lastError", &WebmEncoder::lastError);
}
<|endoftext|>


<commit_before>// The main caffe test code. Your test cpp code should include this hpp
// to allow a main function to be compiled into the binary.

#include "caffe/caffe.hpp"
#include "caffe/test/test_caffe_main.hpp"

namespace caffe {
#ifndef CPU_ONLY
  cudaDeviceProp CAFFE_TEST_CUDA_PROP;
#endif
}

#ifndef CPU_ONLY
using caffe::CAFFE_TEST_CUDA_PROP;
#endif

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  caffe::GlobalInit(&argc, &argv);
#ifndef CPU_ONLY
  // Before starting testing, let's first print out a few cuda defice info.
  int device;
  cudaGetDeviceCount(&device);
  cout << "Cuda number of devices: " << device << endl;
  if (argc > 1) {
    // Use the given device
    device = atoi(argv[1]);
    cudaSetDevice(device);
    cout << "Setting to use device " << device << endl;
  } else if (CUDA_TEST_DEVICE >= 0) {
    // Use the device assigned in build configuration; but with a lower priority
    device = CUDA_TEST_DEVICE;
  }
  cudaGetDevice(&device);
  cout << "Current device id: " << device << endl;
  cudaGetDeviceProperties(&CAFFE_TEST_CUDA_PROP, device);
  cout << "Current device name: " << CAFFE_TEST_CUDA_PROP.name << endl;
#endif
  // invoke the test.
  return RUN_ALL_TESTS();
}
<commit_msg>Remove misleading comment from a test file<commit_after>#include "caffe/caffe.hpp"
#include "caffe/test/test_caffe_main.hpp"

namespace caffe {
#ifndef CPU_ONLY
  cudaDeviceProp CAFFE_TEST_CUDA_PROP;
#endif
}

#ifndef CPU_ONLY
using caffe::CAFFE_TEST_CUDA_PROP;
#endif

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  caffe::GlobalInit(&argc, &argv);
#ifndef CPU_ONLY
  // Before starting testing, let's first print out a few cuda defice info.
  int device;
  cudaGetDeviceCount(&device);
  cout << "Cuda number of devices: " << device << endl;
  if (argc > 1) {
    // Use the given device
    device = atoi(argv[1]);
    cudaSetDevice(device);
    cout << "Setting to use device " << device << endl;
  } else if (CUDA_TEST_DEVICE >= 0) {
    // Use the device assigned in build configuration; but with a lower priority
    device = CUDA_TEST_DEVICE;
  }
  cudaGetDevice(&device);
  cout << "Current device id: " << device << endl;
  cudaGetDeviceProperties(&CAFFE_TEST_CUDA_PROP, device);
  cout << "Current device name: " << CAFFE_TEST_CUDA_PROP.name << endl;
#endif
  // invoke the test.
  return RUN_ALL_TESTS();
}
<|endoftext|>


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

#include <GL/freeglut.h>

#include "WindowImp.h"
#include "Test.util.h"

using namespace org::w3c::dom::bootstrap;
using namespace org::w3c::dom;

extern html::Window window;

void reshape(int w, int h)
{
    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, w, h, 0, -1000.0, 1.0);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->render();
    glutSwapBuffers();  // This would block until the sync happens
}

unsigned getCharKeyCode(int key)
{
    // US Qwerty
    static unsigned map[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 12, 13, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 27, 0, 0, 0, 0,
        32, 49 /* ! */, 222 /* " */, 51 /* # */, 52 /* $ */, 53 /* % */, 55 /* & */, 222 /* ' */,
        57 /* ( */, 48 /* ) */, 56 /* * */, 187 /* + */, 188 /* , */, 189 /* - */, 190 /* . */, 191 /* / */,
        48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */, 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
        56 /* 8 */, 57 /* 9 */, 186 /* : */, 186 /* ; */, 188 /* < */, 187 /* = */, 190 /* > */, 191 /* ? */,
        50 /* @ */, 65 /* A */, 66 /* B */, 67 /* C */, 68 /* D */, 69 /* E */, 70 /* F */, 71 /* G */,
        72 /* H */, 73 /* I */, 74 /* J */, 75 /* K */, 76 /* L */, 77 /* M */, 78 /* N */, 79 /* O */,
        80 /* P */, 81 /* Q */, 82 /* R */, 83 /* S */, 84 /* T */, 85 /* U */, 86 /* V */, 87 /* W */,
        88 /* X */, 89 /* Y */, 90 /* Z */, 219 /* [ */, 220 /* \ */, 221 /* ] */, 54 /* ^ */, 189 /* _ */,
        192 /* ` */, 65 /* a */, 66 /* b */, 67 /* c */, 68 /* d */, 69 /* e */, 70 /* f */, 71 /* g */,
        72 /* h */, 73 /* i */, 74 /* j */, 75 /* k */, 76 /* l */, 77 /* m */, 78 /* n */, 79 /* o */,
        80 /* p */, 81 /* q */, 82 /* r */, 83 /* s */, 84 /* t */, 85 /* u */, 86 /* v */, 87 /* w */,
        88 /* x */, 89 /* y */, 90 /* z */, 219 /* { */, 220 /* | */, 221 /* } */, 192 /* ~ */, 46 /* DEL */
    };
    static_assert(sizeof map /sizeof map[0] == 128, "invalid map");
    return (0 <= key && key <= 127) ? map[key] : 0;
}

void keyboard(unsigned char key, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->keydown(key, getCharKeyCode(key), glutGetModifiers());
}

void keyboardUp(unsigned char key, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->keyup(key, getCharKeyCode(key), glutGetModifiers());
}

unsigned getSpecialKeyCode(int key)
{
    switch (key) {
    case GLUT_KEY_F1:
        return 112;
    case GLUT_KEY_F2:
        return 113;
    case GLUT_KEY_F3:
        return 114;
    case GLUT_KEY_F4:
        return 115;
    case GLUT_KEY_F5:
        return 116;
    case GLUT_KEY_F6:
        return 117;
    case GLUT_KEY_F7:
        return 118;
    case GLUT_KEY_F8:
        return 119;
    case GLUT_KEY_F9:
        return 120;
    case GLUT_KEY_F10:
        return 121;
    case GLUT_KEY_F11:
        return 122;
    case GLUT_KEY_F12:
        return 123;
    case GLUT_KEY_LEFT:
        return 37;
    case GLUT_KEY_UP:
        return 38;
    case GLUT_KEY_RIGHT:
        return 39;
    case GLUT_KEY_DOWN:
        return 40;
    case GLUT_KEY_PAGE_UP:
        return 33;
    case GLUT_KEY_PAGE_DOWN:
        return 34;
    case GLUT_KEY_HOME:
        return 36;
    case GLUT_KEY_END:
        return 35;
    case GLUT_KEY_INSERT:
        return 45;
    case 109:  // Num Lock
        return 144;
    default:
        return 0;
    }
}

void special(int key, int x, int y)
{
    unsigned keycode = getSpecialKeyCode(key);
    if (keycode) {
        if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
            imp->keydown(0, keycode, glutGetModifiers());
    }
}

void specialUp(int key, int x, int y)
{
    unsigned keycode = getSpecialKeyCode(key);
    if (keycode) {
        if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
            imp->keyup(0, keycode, glutGetModifiers());
    }
}

void mouse(int button, int state, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->mouse(button, state, x, y, glutGetModifiers());
}

void mouseMove(int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->mouseMove(x, y, glutGetModifiers());
}

void timer(int value)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self())) {
        if (imp->poll())
            glutPostRedisplay();
    }
    glutTimerFunc(50, timer, 0);
    // TODO: do GC here or maybe in the idle proc
 }

void init(int argc, char* argv[])
{
    glutInit(&argc, argv);

    GLint buffers, samples;
    glGetIntegerv(GL_SAMPLE_BUFFERS, &buffers);
    glGetIntegerv(GL_SAMPLES, &samples);
    std::cout << "GL_SAMPLE_BUFFERS = " << buffers << ", GL_SAMPLES = " << samples << '\n';
    if (1 <= GL_SAMPLE_BUFFERS && 2 <= samples)
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
    else
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(816, 1056);
    glutCreateWindow(argv[0]);
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glEnable(GL_TEXTURE_2D);
    glDepthFunc(GL_LEQUAL);
    glDisable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_ALPHA_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(special);
    glutSpecialUpFunc(specialUp);
    glutMouseFunc(mouse);
    glutMotionFunc(mouseMove);
    glutPassiveMotionFunc(mouseMove);
    glutTimerFunc(50, timer, 0);
    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
    if (1 <= GL_SAMPLE_BUFFERS && 2 <= samples) {
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
    }
}<commit_msg>(init) : Enable GLUT_MULTISAMPLE for now. We will revisit this issue later.<commit_after>/*
 * Copyright 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <GL/freeglut.h>

#include "WindowImp.h"
#include "Test.util.h"

using namespace org::w3c::dom::bootstrap;
using namespace org::w3c::dom;

extern html::Window window;

void reshape(int w, int h)
{
    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, w, h, 0, -1000.0, 1.0);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->render();
    glutSwapBuffers();  // This would block until the sync happens
}

unsigned getCharKeyCode(int key)
{
    // US Qwerty
    static unsigned map[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 12, 13, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 27, 0, 0, 0, 0,
        32, 49 /* ! */, 222 /* " */, 51 /* # */, 52 /* $ */, 53 /* % */, 55 /* & */, 222 /* ' */,
        57 /* ( */, 48 /* ) */, 56 /* * */, 187 /* + */, 188 /* , */, 189 /* - */, 190 /* . */, 191 /* / */,
        48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */, 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
        56 /* 8 */, 57 /* 9 */, 186 /* : */, 186 /* ; */, 188 /* < */, 187 /* = */, 190 /* > */, 191 /* ? */,
        50 /* @ */, 65 /* A */, 66 /* B */, 67 /* C */, 68 /* D */, 69 /* E */, 70 /* F */, 71 /* G */,
        72 /* H */, 73 /* I */, 74 /* J */, 75 /* K */, 76 /* L */, 77 /* M */, 78 /* N */, 79 /* O */,
        80 /* P */, 81 /* Q */, 82 /* R */, 83 /* S */, 84 /* T */, 85 /* U */, 86 /* V */, 87 /* W */,
        88 /* X */, 89 /* Y */, 90 /* Z */, 219 /* [ */, 220 /* \ */, 221 /* ] */, 54 /* ^ */, 189 /* _ */,
        192 /* ` */, 65 /* a */, 66 /* b */, 67 /* c */, 68 /* d */, 69 /* e */, 70 /* f */, 71 /* g */,
        72 /* h */, 73 /* i */, 74 /* j */, 75 /* k */, 76 /* l */, 77 /* m */, 78 /* n */, 79 /* o */,
        80 /* p */, 81 /* q */, 82 /* r */, 83 /* s */, 84 /* t */, 85 /* u */, 86 /* v */, 87 /* w */,
        88 /* x */, 89 /* y */, 90 /* z */, 219 /* { */, 220 /* | */, 221 /* } */, 192 /* ~ */, 46 /* DEL */
    };
    static_assert(sizeof map /sizeof map[0] == 128, "invalid map");
    return (0 <= key && key <= 127) ? map[key] : 0;
}

void keyboard(unsigned char key, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->keydown(key, getCharKeyCode(key), glutGetModifiers());
}

void keyboardUp(unsigned char key, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->keyup(key, getCharKeyCode(key), glutGetModifiers());
}

unsigned getSpecialKeyCode(int key)
{
    switch (key) {
    case GLUT_KEY_F1:
        return 112;
    case GLUT_KEY_F2:
        return 113;
    case GLUT_KEY_F3:
        return 114;
    case GLUT_KEY_F4:
        return 115;
    case GLUT_KEY_F5:
        return 116;
    case GLUT_KEY_F6:
        return 117;
    case GLUT_KEY_F7:
        return 118;
    case GLUT_KEY_F8:
        return 119;
    case GLUT_KEY_F9:
        return 120;
    case GLUT_KEY_F10:
        return 121;
    case GLUT_KEY_F11:
        return 122;
    case GLUT_KEY_F12:
        return 123;
    case GLUT_KEY_LEFT:
        return 37;
    case GLUT_KEY_UP:
        return 38;
    case GLUT_KEY_RIGHT:
        return 39;
    case GLUT_KEY_DOWN:
        return 40;
    case GLUT_KEY_PAGE_UP:
        return 33;
    case GLUT_KEY_PAGE_DOWN:
        return 34;
    case GLUT_KEY_HOME:
        return 36;
    case GLUT_KEY_END:
        return 35;
    case GLUT_KEY_INSERT:
        return 45;
    case 109:  // Num Lock
        return 144;
    default:
        return 0;
    }
}

void special(int key, int x, int y)
{
    unsigned keycode = getSpecialKeyCode(key);
    if (keycode) {
        if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
            imp->keydown(0, keycode, glutGetModifiers());
    }
}

void specialUp(int key, int x, int y)
{
    unsigned keycode = getSpecialKeyCode(key);
    if (keycode) {
        if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
            imp->keyup(0, keycode, glutGetModifiers());
    }
}

void mouse(int button, int state, int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->mouse(button, state, x, y, glutGetModifiers());
}

void mouseMove(int x, int y)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self()))
        imp->mouseMove(x, y, glutGetModifiers());
}

void timer(int value)
{
    if (WindowImp* imp = static_cast<WindowImp*>(window.self())) {
        if (imp->poll())
            glutPostRedisplay();
    }
    glutTimerFunc(50, timer, 0);
    // TODO: do GC here or maybe in the idle proc
 }

void init(int argc, char* argv[])
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);

    glutInitWindowSize(816, 1056);
    glutCreateWindow(argv[0]);
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glEnable(GL_TEXTURE_2D);
    glDepthFunc(GL_LEQUAL);
    glDisable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_ALPHA_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(special);
    glutSpecialUpFunc(specialUp);
    glutMouseFunc(mouse);
    glutMotionFunc(mouseMove);
    glutPassiveMotionFunc(mouseMove);
    glutTimerFunc(50, timer, 0);
    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);

    glEnable(GL_MULTISAMPLE);
    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
<|endoftext|>


<commit_before>#include "sprites.h"
#include "Graphics.h"
#include "Text.h"
#include <cstdio>
#include <cstdarg>
#include <string>

#define TEXT WalrusRPG::Graphics::Text
#define GRAPHICS WalrusRPG::Graphics

void TEXT::print_char(char c, unsigned x, unsigned y)
{
    GRAPHICS::Rect_t rect;
    rect.w = 8;
    rect.h = 8;
    rect.x = (c % 16) * 8;
    rect.y = (c / 16) * 8;
    draw_sprite_sheet(font, x, y, &rect);
}

void TEXT::print_string(const char *str, unsigned x, unsigned y)
{
    GRAPHICS::Rect_t rect;
    rect.w = 8;
    rect.h = 8;
    for (unsigned index = 0; str[index]; index++)
    {
        char c = str[index];
        rect.x = (c % 16) * 8;
        rect.y = (c / 16) * 8;
        draw_sprite_sheet(font, x, y, &rect);
        x += 8;
    }
}

void TEXT::print_string(const std::string &str, unsigned x, unsigned y) {
  TEXT::print_string(str.c_str(), x, y);
}

void TEXT::print_format(unsigned x, unsigned y, const char *format, ...) {
	char buffer[256] = "";
	va_list args;
	va_start(args, format);
	vsnprintf(buffer, 256, format, args);
	print_string(buffer, x, y);
}

void TEXT::print_format(unsigned x, unsigned y, const std::string &format, ...) {
  TEXT::print_format(x, y, format.c_str());
}
<commit_msg>Format<commit_after>#include "sprites.h"
#include "Graphics.h"
#include "Text.h"
#include <cstdio>
#include <cstdarg>
#include <string>

#define TEXT WalrusRPG::Graphics::Text
#define GRAPHICS WalrusRPG::Graphics

void TEXT::print_char(char c, unsigned x, unsigned y)
{
    GRAPHICS::Rect_t rect;
    rect.w = 8;
    rect.h = 8;
    rect.x = (c % 16) * 8;
    rect.y = (c / 16) * 8;
    draw_sprite_sheet(font, x, y, &rect);
}

void TEXT::print_string(const char *str, unsigned x, unsigned y)
{
    GRAPHICS::Rect_t rect;
    rect.w = 8;
    rect.h = 8;
    for (unsigned index = 0; str[index]; index++)
    {
        char c = str[index];
        rect.x = (c % 16) * 8;
        rect.y = (c / 16) * 8;
        draw_sprite_sheet(font, x, y, &rect);
        x += 8;
    }
}

void TEXT::print_string(const std::string &str, unsigned x, unsigned y)
{
    TEXT::print_string(str.c_str(), x, y);
}

void TEXT::print_format(unsigned x, unsigned y, const char *format, ...)
{
    char buffer[256] =
        "";
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, 256, format, args);
    print_string(buffer, x, y);
}

void TEXT::print_format(unsigned x, unsigned y, const std::string &format, ...)
{
    TEXT::print_format(x, y, format.c_str());
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "MainScene.h"

Scene* MainScene::createScene()
{
    auto scene = Scene::create();

    auto layer = MainScene::create();

    scene->addChild(layer);

    return scene;
}

bool MainScene::init()
{
	if (!Layer::init())
	{
		return false;
	}

	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

	auto closeItem = MenuItemImage::create(
		"CloseNormal.png",
		"CloseSelected.png",
		CC_CALLBACK_1(MainScene::menuCloseCallback, this));

	closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
		origin.y + closeItem->getContentSize().height / 2));

	auto menu = Menu::create(closeItem, NULL);
	menu->setPosition(Vec2::ZERO);
	this->addChild(menu, 1);
}

void MainScene::menuCloseCallback(Ref* pSender)
{
    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
<commit_msg>particle<commit_after>#include "stdafx.h"
#include "MainScene.h"

Scene* MainScene::createScene()
{
    auto scene = Scene::create();

    auto layer = MainScene::create();

    scene->addChild(layer);

    return scene;
}

bool MainScene::init()
{
	if (!Layer::init())
	{
		return false;
	}

	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

	auto closeItem = MenuItemImage::create(
		"CloseNormal.png",
		"CloseSelected.png",
		CC_CALLBACK_1(MainScene::menuCloseCallback, this));

	closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
		origin.y + closeItem->getContentSize().height / 2));

	auto menu = Menu::create(closeItem, NULL);
	menu->setPosition(Vec2::ZERO);
	this->addChild(menu, 1);

	ParticleFireworks* particle = ParticleFireworks::create();
	particle->setAngle(60);
	particle->setEmissionRate(500);
	particle->setGravity(Vec2::ZERO);
	this->addChild(particle);
}

void MainScene::menuCloseCallback(Ref* pSender)
{
    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of the copyright holder 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 HOLDER 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.
 */

/**
 * @file
 * @brief
 *   This file includes the platform-specific initializers.
 */

#include "openthread-posix-config.h"
#include "platform-posix.h"

#include <assert.h>

#include <openthread-core-config.h>
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/uart.h>

#include "common/code_utils.hpp"

uint64_t gNodeId = 0;

otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
{
    otInstance *        instance = nullptr;
    ot::Posix::RadioUrl radioUrl(aPlatformConfig->mRadioUrl);

#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeInit(static_cast<uint16_t>(atoi(radioUrl.GetValue("forkpty-arg"))));
#endif

    VerifyOrDie(radioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
    platformAlarmInit(aPlatformConfig->mSpeedUpFactor, aPlatformConfig->mRealTimeSignal);
    platformRadioInit(&radioUrl);
    platformRandomInit();

    instance = otInstanceInitSingle();
    assert(instance != nullptr);

#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifInit(instance, aPlatformConfig->mInterfaceName);
#elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpInit(aPlatformConfig->mInterfaceName);
#endif

    return instance;
}

void otSysDeinit(void)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeDeinit();
#endif
    platformRadioDeinit();
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifDeinit();
#endif
    IgnoreError(otPlatUartDisable());
}

#if OPENTHREAD_POSIX_VIRTUAL_TIME
/**
 * This function try selecting the given file descriptors in nonblocking mode.
 *
 * @param[inout]    aReadFdSet   A pointer to the read file descriptors.
 * @param[inout]    aWriteFdSet  A pointer to the write file descriptors.
 * @param[inout]    aErrorFdSet  A pointer to the error file descriptors.
 * @param[in]       aMaxFd       The max file descriptor.
 *
 * @returns The value returned from select().
 *
 */
static int trySelect(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int aMaxFd)
{
    struct timeval timeout          = {0, 0};
    fd_set         originReadFdSet  = *aReadFdSet;
    fd_set         originWriteFdSet = *aWriteFdSet;
    fd_set         originErrorFdSet = *aErrorFdSet;
    int            rval;

    rval = select(aMaxFd + 1, aReadFdSet, aWriteFdSet, aErrorFdSet, &timeout);

    if (rval == 0)
    {
        *aReadFdSet  = originReadFdSet;
        *aWriteFdSet = originWriteFdSet;
        *aErrorFdSet = originErrorFdSet;
    }

    return rval;
}
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME

void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop)
{
    platformAlarmUpdateTimeout(&aMainloop->mTimeout);
    platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                            &aMainloop->mMaxFd);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                             &aMainloop->mMaxFd);
#endif
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd,
                           &aMainloop->mTimeout);
#else
    platformRadioUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout);
#endif

    if (otTaskletsArePending(aInstance))
    {
        aMainloop->mTimeout.tv_sec  = 0;
        aMainloop->mTimeout.tv_usec = 0;
    }
}

int otSysMainloopPoll(otSysMainloopContext *aMainloop)
{
    int rval;

#if OPENTHREAD_POSIX_VIRTUAL_TIME
    if (timerisset(&aMainloop->mTimeout))
    {
        // Make sure there are no data ready in UART
        rval = trySelect(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, aMainloop->mMaxFd);

        if (rval == 0)
        {
            bool noWrite = true;

            // If there are write requests, the device is supposed to wake soon
            for (int i = 0; i < aMainloop->mMaxFd + 1; ++i)
            {
                if (FD_ISSET(i, &aMainloop->mWriteFdSet))
                {
                    noWrite = false;
                    break;
                }
            }

            if (noWrite)
            {
                virtualTimeSendSleepEvent(&aMainloop->mTimeout);
            }

            rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet,
                          &aMainloop->mErrorFdSet, nullptr);
        }
    }
    else
#endif
    {
        rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                      &aMainloop->mTimeout);
    }

    return rval;
}

void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#else
    platformRadioProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet);
#endif
    platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
    platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpProcess(aInstance, &aMainloop->mReadFdSet);
#endif
}
<commit_msg>[otns] implement `otPlatOtnsStatus` for posix (#5357)<commit_after>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. 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.
 *  3. Neither the name of the copyright holder 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 HOLDER 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.
 */

/**
 * @file
 * @brief
 *   This file includes the platform-specific initializers.
 */

#include "openthread-posix-config.h"
#include "platform-posix.h"

#include <assert.h>

#include <openthread-core-config.h>
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/otns.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/uart.h>

#include "common/code_utils.hpp"

uint64_t gNodeId = 0;

otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
{
    otInstance *        instance = nullptr;
    ot::Posix::RadioUrl radioUrl(aPlatformConfig->mRadioUrl);

#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeInit(static_cast<uint16_t>(atoi(radioUrl.GetValue("forkpty-arg"))));
#endif

    VerifyOrDie(radioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
    platformAlarmInit(aPlatformConfig->mSpeedUpFactor, aPlatformConfig->mRealTimeSignal);
    platformRadioInit(&radioUrl);
    platformRandomInit();

    instance = otInstanceInitSingle();
    assert(instance != nullptr);

#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifInit(instance, aPlatformConfig->mInterfaceName);
#elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpInit(aPlatformConfig->mInterfaceName);
#endif

    return instance;
}

void otSysDeinit(void)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeDeinit();
#endif
    platformRadioDeinit();
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifDeinit();
#endif
    IgnoreError(otPlatUartDisable());
}

#if OPENTHREAD_POSIX_VIRTUAL_TIME
/**
 * This function try selecting the given file descriptors in nonblocking mode.
 *
 * @param[inout]    aReadFdSet   A pointer to the read file descriptors.
 * @param[inout]    aWriteFdSet  A pointer to the write file descriptors.
 * @param[inout]    aErrorFdSet  A pointer to the error file descriptors.
 * @param[in]       aMaxFd       The max file descriptor.
 *
 * @returns The value returned from select().
 *
 */
static int trySelect(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int aMaxFd)
{
    struct timeval timeout          = {0, 0};
    fd_set         originReadFdSet  = *aReadFdSet;
    fd_set         originWriteFdSet = *aWriteFdSet;
    fd_set         originErrorFdSet = *aErrorFdSet;
    int            rval;

    rval = select(aMaxFd + 1, aReadFdSet, aWriteFdSet, aErrorFdSet, &timeout);

    if (rval == 0)
    {
        *aReadFdSet  = originReadFdSet;
        *aWriteFdSet = originWriteFdSet;
        *aErrorFdSet = originErrorFdSet;
    }

    return rval;
}
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME

void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop)
{
    platformAlarmUpdateTimeout(&aMainloop->mTimeout);
    platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                            &aMainloop->mMaxFd);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                             &aMainloop->mMaxFd);
#endif
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd,
                           &aMainloop->mTimeout);
#else
    platformRadioUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout);
#endif

    if (otTaskletsArePending(aInstance))
    {
        aMainloop->mTimeout.tv_sec  = 0;
        aMainloop->mTimeout.tv_usec = 0;
    }
}

int otSysMainloopPoll(otSysMainloopContext *aMainloop)
{
    int rval;

#if OPENTHREAD_POSIX_VIRTUAL_TIME
    if (timerisset(&aMainloop->mTimeout))
    {
        // Make sure there are no data ready in UART
        rval = trySelect(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, aMainloop->mMaxFd);

        if (rval == 0)
        {
            bool noWrite = true;

            // If there are write requests, the device is supposed to wake soon
            for (int i = 0; i < aMainloop->mMaxFd + 1; ++i)
            {
                if (FD_ISSET(i, &aMainloop->mWriteFdSet))
                {
                    noWrite = false;
                    break;
                }
            }

            if (noWrite)
            {
                virtualTimeSendSleepEvent(&aMainloop->mTimeout);
            }

            rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet,
                          &aMainloop->mErrorFdSet, nullptr);
        }
    }
    else
#endif
    {
        rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
                      &aMainloop->mTimeout);
    }

    return rval;
}

void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
    virtualTimeProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#else
    platformRadioProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet);
#endif
    platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
    platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
    platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
    platformUdpProcess(aInstance, &aMainloop->mReadFdSet);
#endif
}

#if OPENTHREAD_CONFIG_OTNS_ENABLE

void otPlatOtnsStatus(const char *aStatus)
{
    otLogOtns("[OTNS] %s", aStatus);
}

#endif
<|endoftext|>