<commit_before>// This file is part of Fuxedo
// Copyright (C) 2017 Aivars Kalvans <aivars.kalvans@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <clara.hpp>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

#include "mib.h"
#include "ubbreader.h"

#include "misc.h"

size_t filesize(const std::string &filename) {
  std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
  return in.tellg();
}

tuxconfig getconfig(ubbconfig *ubb) {
  auto outfile = std::getenv("TUXCONFIG");
  if (outfile == nullptr) {
    throw std::runtime_error("TUXCONFIG environment variable required");
  }

  std::ifstream fin;
  fin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  fin.open(outfile);

  tuxconfig tuxcfg;
  fin.read(reinterpret_cast<char *>(&tuxcfg), sizeof(tuxcfg));

  auto size = filesize(outfile);
  if (tuxcfg.size != size) {
    throw std::runtime_error("Bad TUXCONFIG signature, invalid file");
  }

  if (ubb != nullptr) {
    ubbreader p(fin);
    *ubb = p.parse();
  }

  return tuxcfg;
}

template <class T>
size_t init(T &t, size_t size, size_t off) {
  t.len = 0;
  t.size = size;
  t.off = off;
  return nearest64(t.size * sizeof(typename T::value_type));
}

size_t mib::needed(const tuxconfig &cfg) {
  return nearest64(sizeof(mibmem)) +
         nearest64(cfg.maxservers * sizeof(server)) +
         nearest64(cfg.maxqueues * sizeof(queue)) +
         nearest64(cfg.maxservices * sizeof(service)) +
         nearest64(cfg.maxservers * cfg.maxservices * sizeof(advertisement)) +
         nearest64(cfg.maxgroups * sizeof(group)) +
         nearest64(cfg.maxaccessers * sizeof(client));
}

void mib::init_memory() {
  auto off = nearest64(sizeof(mibmem));
  off += init(mem_->servers, cfg_.maxservers, off - offsetof(mibmem, servers));
  off += init(mem_->queues, cfg_.maxqueues, off - offsetof(mibmem, queues));
  off +=
      init(mem_->services, cfg_.maxservices, off - offsetof(mibmem, services));
  off += init(mem_->groups, cfg_.maxgroups, off - offsetof(mibmem, groups));
  off += init(mem_->advertisements, cfg_.maxservers * cfg_.maxservices,
              off - offsetof(mibmem, advertisements));
  off +=
      init(mem_->clients, cfg_.maxaccessers, off - offsetof(mibmem, clients));
}

size_t mib::find_advertisement(size_t service, size_t queue) {
  for (size_t i = 0; i < advertisements().len(); i++) {
    auto &advertisement = advertisements().at(i);
    if (advertisement.service == service && advertisement.queue == queue) {
      return i;
    }
  }
  return badoff;
}

void mib::advertise(const std::string &servicename, size_t queue) {
  auto service = find_service(servicename);
  if (service == badoff) {
    service = make_service(servicename);
  }
  if (find_advertisement(service, queue) == badoff) {
    auto &advertisement = advertisements().at(advertisements().len());
    advertisement.service = service;
    advertisement.queue = queue;
    services().at(service).revision++;
    advertisements().len()++;
  }
}

void mib::unadvertise(const std::string &servicename, size_t queue) {
  auto service = find_service(servicename);
  if (service == badoff) {
    throw std::logic_error("Unknown service");
  }
  auto advertisement = find_advertisement(service, queue);
  if (advertisement != badoff) {
  }
  throw std::logic_error("Service not advertised");
}

size_t mib::find_queue(const std::string &rqaddr) {
  for (size_t i = 0; i < queues().len(); i++) {
    if (rqaddr == queues().at(i).rqaddr) {
      return i;
    }
  }
  return badoff;
}

size_t mib::make_queue(const std::string &rqaddr) {
  if (find_queue(rqaddr) != badoff) {
    throw std::logic_error("Duplicate queue");
  }

  auto &queue = queues().at(queues().len());
  checked_copy(rqaddr, queue.rqaddr);
  queue.msqid = -1;
  return queues().len()++;
}

size_t mib::find_server(uint16_t srvid, uint16_t grpno) {
  for (size_t i = 0; i < servers().len(); i++) {
    auto &server = servers().at(i);
    if (server.srvid == srvid && server.grpno == grpno) {
      return i;
    }
  }
  return badoff;
}

size_t mib::make_server(uint16_t srvid, uint16_t grpno,
                        const std::string &servername, const std::string &clopt,
                        const std::string &rqaddr) {
  if (find_server(srvid, grpno) != badoff) {
    throw std::logic_error("Duplicate server");
  }

  auto &server = servers().at(servers().len());
  server.srvid = srvid;
  server.grpno = grpno;
  checked_copy(servername, server.servername);
  checked_copy(clopt, server.clopt);

  server.rqaddr = find_queue(rqaddr);
  if (server.rqaddr == badoff) {
    server.rqaddr = make_queue(rqaddr);
  }
  return servers().len()++;
}

size_t mib::find_service(const char *servicename) {
  for (size_t i = 0; i < services().len(); i++) {
    if (strcmp(servicename, services().at(i).servicename) == 0) {
      return i;
    }
  }
  return badoff;
}
size_t mib::find_service(const std::string &servicename) {
  return find_service(servicename.c_str());
}

size_t mib::make_client(pid_t pid) {
  for (size_t i = 0; i < clients().len(); i++) {
    if (clients().at(i).pid == 0) {
      clients().at(i).pid = pid;
      return i;
    }
  }
  auto &client = clients().at(clients().len());
  client.pid = pid;
  return clients().len()++;
}

size_t mib::make_service(const std::string &servicename) {
  if (find_service(servicename) != badoff) {
    throw std::logic_error("Duplicate service");
  }

  auto &service = services().at(services().len());
  checked_copy(servicename, service.servicename);
  return services().len()++;
}

int mib::make_service_rqaddr(size_t server) {
  auto &queue = queues().at(servers().at(server).rqaddr);
  std::cout << queue.rqaddr << "  " << queue.msqid << std::endl;
  if (queue.msqid == -1) {
    queue.msqid = fux::ipc::qcreate();
    if (queue.msqid == -1) {
      throw std::system_error(errno, std::system_category());
    }
  }
  return queue.msqid;
}

void mib::remove() {
  for (size_t i = 0; i < queues().len(); i++) {
    auto msqid = queues().at(i).msqid;
    if (msqid != -1) {
      msgctl(msqid, IPC_RMID, NULL);
      queues().at(i).msqid = -1;
    }
  }
  for (size_t i = 0; i < clients().len(); i++) {
    auto msqid = clients().at(i).rpid;
    if (msqid != -1) {
      msgctl(msqid, IPC_RMID, NULL);
      clients().at(i).rpid = -1;
    }
  }
  fux::ipc::semrm(mem_->mainsem);
  shmctl(shmid_, IPC_RMID, NULL);
}

void ubb2mib(ubbconfig &u, mib &m);

mib &getmib() {
  static std::unique_ptr<mib> mibcon;

  if (!mibcon.get()) {
    auto cfg = getconfig();
    mibcon = std::make_unique<mib>(cfg);
    mibcon->connect();
    if (mibcon->servers().len() == 0) {
      ubbconfig u;
      getconfig(&u);
      ubb2mib(u, *mibcon.get());
    }
  }

  return *mibcon.get();
}
<commit_msg>add cstddef include for offsetof<commit_after>// This file is part of Fuxedo
// Copyright (C) 2017 Aivars Kalvans <aivars.kalvans@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <clara.hpp>
#include <cstdlib>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

#include "mib.h"
#include "ubbreader.h"

#include "misc.h"

size_t filesize(const std::string &filename) {
  std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
  return in.tellg();
}

tuxconfig getconfig(ubbconfig *ubb) {
  auto outfile = std::getenv("TUXCONFIG");
  if (outfile == nullptr) {
    throw std::runtime_error("TUXCONFIG environment variable required");
  }

  std::ifstream fin;
  fin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  fin.open(outfile);

  tuxconfig tuxcfg;
  fin.read(reinterpret_cast<char *>(&tuxcfg), sizeof(tuxcfg));

  auto size = filesize(outfile);
  if (tuxcfg.size != size) {
    throw std::runtime_error("Bad TUXCONFIG signature, invalid file");
  }

  if (ubb != nullptr) {
    ubbreader p(fin);
    *ubb = p.parse();
  }

  return tuxcfg;
}

template <class T>
size_t init(T &t, size_t size, size_t off) {
  t.len = 0;
  t.size = size;
  t.off = off;
  return nearest64(t.size * sizeof(typename T::value_type));
}

size_t mib::needed(const tuxconfig &cfg) {
  return nearest64(sizeof(mibmem)) +
         nearest64(cfg.maxservers * sizeof(server)) +
         nearest64(cfg.maxqueues * sizeof(queue)) +
         nearest64(cfg.maxservices * sizeof(service)) +
         nearest64(cfg.maxservers * cfg.maxservices * sizeof(advertisement)) +
         nearest64(cfg.maxgroups * sizeof(group)) +
         nearest64(cfg.maxaccessers * sizeof(client));
}

void mib::init_memory() {
  auto off = nearest64(sizeof(mibmem));
  off += init(mem_->servers, cfg_.maxservers, off - offsetof(mibmem, servers));
  off += init(mem_->queues, cfg_.maxqueues, off - offsetof(mibmem, queues));
  off +=
      init(mem_->services, cfg_.maxservices, off - offsetof(mibmem, services));
  off += init(mem_->groups, cfg_.maxgroups, off - offsetof(mibmem, groups));
  off += init(mem_->advertisements, cfg_.maxservers * cfg_.maxservices,
              off - offsetof(mibmem, advertisements));
  off +=
      init(mem_->clients, cfg_.maxaccessers, off - offsetof(mibmem, clients));
}

size_t mib::find_advertisement(size_t service, size_t queue) {
  for (size_t i = 0; i < advertisements().len(); i++) {
    auto &advertisement = advertisements().at(i);
    if (advertisement.service == service && advertisement.queue == queue) {
      return i;
    }
  }
  return badoff;
}

void mib::advertise(const std::string &servicename, size_t queue) {
  auto service = find_service(servicename);
  if (service == badoff) {
    service = make_service(servicename);
  }
  if (find_advertisement(service, queue) == badoff) {
    auto &advertisement = advertisements().at(advertisements().len());
    advertisement.service = service;
    advertisement.queue = queue;
    services().at(service).revision++;
    advertisements().len()++;
  }
}

void mib::unadvertise(const std::string &servicename, size_t queue) {
  auto service = find_service(servicename);
  if (service == badoff) {
    throw std::logic_error("Unknown service");
  }
  auto advertisement = find_advertisement(service, queue);
  if (advertisement != badoff) {
  }
  throw std::logic_error("Service not advertised");
}

size_t mib::find_queue(const std::string &rqaddr) {
  for (size_t i = 0; i < queues().len(); i++) {
    if (rqaddr == queues().at(i).rqaddr) {
      return i;
    }
  }
  return badoff;
}

size_t mib::make_queue(const std::string &rqaddr) {
  if (find_queue(rqaddr) != badoff) {
    throw std::logic_error("Duplicate queue");
  }

  auto &queue = queues().at(queues().len());
  checked_copy(rqaddr, queue.rqaddr);
  queue.msqid = -1;
  return queues().len()++;
}

size_t mib::find_server(uint16_t srvid, uint16_t grpno) {
  for (size_t i = 0; i < servers().len(); i++) {
    auto &server = servers().at(i);
    if (server.srvid == srvid && server.grpno == grpno) {
      return i;
    }
  }
  return badoff;
}

size_t mib::make_server(uint16_t srvid, uint16_t grpno,
                        const std::string &servername, const std::string &clopt,
                        const std::string &rqaddr) {
  if (find_server(srvid, grpno) != badoff) {
    throw std::logic_error("Duplicate server");
  }

  auto &server = servers().at(servers().len());
  server.srvid = srvid;
  server.grpno = grpno;
  checked_copy(servername, server.servername);
  checked_copy(clopt, server.clopt);

  server.rqaddr = find_queue(rqaddr);
  if (server.rqaddr == badoff) {
    server.rqaddr = make_queue(rqaddr);
  }
  return servers().len()++;
}

size_t mib::find_service(const char *servicename) {
  for (size_t i = 0; i < services().len(); i++) {
    if (strcmp(servicename, services().at(i).servicename) == 0) {
      return i;
    }
  }
  return badoff;
}
size_t mib::find_service(const std::string &servicename) {
  return find_service(servicename.c_str());
}

size_t mib::make_client(pid_t pid) {
  for (size_t i = 0; i < clients().len(); i++) {
    if (clients().at(i).pid == 0) {
      clients().at(i).pid = pid;
      return i;
    }
  }
  auto &client = clients().at(clients().len());
  client.pid = pid;
  return clients().len()++;
}

size_t mib::make_service(const std::string &servicename) {
  if (find_service(servicename) != badoff) {
    throw std::logic_error("Duplicate service");
  }

  auto &service = services().at(services().len());
  checked_copy(servicename, service.servicename);
  return services().len()++;
}

int mib::make_service_rqaddr(size_t server) {
  auto &queue = queues().at(servers().at(server).rqaddr);
  std::cout << queue.rqaddr << "  " << queue.msqid << std::endl;
  if (queue.msqid == -1) {
    queue.msqid = fux::ipc::qcreate();
    if (queue.msqid == -1) {
      throw std::system_error(errno, std::system_category());
    }
  }
  return queue.msqid;
}

void mib::remove() {
  for (size_t i = 0; i < queues().len(); i++) {
    auto msqid = queues().at(i).msqid;
    if (msqid != -1) {
      msgctl(msqid, IPC_RMID, NULL);
      queues().at(i).msqid = -1;
    }
  }
  for (size_t i = 0; i < clients().len(); i++) {
    auto msqid = clients().at(i).rpid;
    if (msqid != -1) {
      msgctl(msqid, IPC_RMID, NULL);
      clients().at(i).rpid = -1;
    }
  }
  fux::ipc::semrm(mem_->mainsem);
  shmctl(shmid_, IPC_RMID, NULL);
}

void ubb2mib(ubbconfig &u, mib &m);

mib &getmib() {
  static std::unique_ptr<mib> mibcon;

  if (!mibcon.get()) {
    auto cfg = getconfig();
    mibcon = std::make_unique<mib>(cfg);
    mibcon->connect();
    if (mibcon->servers().len() == 0) {
      ubbconfig u;
      getconfig(&u);
      ubb2mib(u, *mibcon.get());
    }
  }

  return *mibcon.get();
}
<|endoftext|>


<commit_before>#include "move.hh"
#include "move_word_p.hh"

namespace vick {
namespace move {

boost::optional< std::shared_ptr<change> > mvbw(contents& contents, boost::optional<int> op) {
    if(op and op.get() < 0) return mvfw(contents, -op.get());
    int num = op ? op.get() : 1;
    if(num == 0) return boost::none;
    //move back one then
    //if delimitor then move back until no delimitor
    //else if whitespace then move back until not whitespace then
    //   move back consistently over delimitors or word chars
    //else /*word char*/ move back until not word char or
    //   whitespace
    //move forward one
    #define boundsCheck if((static_cast<move_ts>(contents.y) < 0) or     \
                           (contents.y == 0 and contents.x == 0) or      \
                           (contents.x == 0 and not isWhitespace(ch))) { \
            if(contents.x == contents.cont[contents.y].size() - 1)       \
                mvf(contents);                                           \
            return boost::none;                                          \
        }
    #define ch contents.cont[contents.y][contents.x]
    mvb(contents);
    while(isWhitespace(ch)) {
        mvb(contents);
        boundsCheck;
    }
    if(isDeliminator(ch)) {
        do {
            mvb(contents);
            if((static_cast<move_ts>(contents.y) < 0) or
               (contents.y == 0 and contents.x == 0) or
               (contents.x == 0 and not isWhitespace(ch))) {
                mvf(contents);
                return boost::none;
            }
        } while(isDeliminator(ch));
        mvf(contents);
    } else {
        if(contents.x == 0 and contents.cont[contents.y].size()) return boost::none;
        do {
            mvb(contents);
            boundsCheck;
        } while(!isDeliminator(ch) && !isWhitespace(ch));
        mvf(contents);
    }
    if(num > 1) mvbw(contents,num - 1);
    return boost::none;
    #undef boundsCheck
    #undef ch
}

}
}
<commit_msg>Prevent potential segfaults in `mvbw()` by immediately exiting if at (0,0)<commit_after>#include "move.hh"
#include "move_word_p.hh"

namespace vick {
namespace move {

boost::optional< std::shared_ptr<change> > mvbw(contents& contents, boost::optional<int> op) {
    if(op and op.get() < 0) return mvfw(contents, -op.get());
    int num = op ? op.get() : 1;
    if(num == 0) return boost::none;
    //move back one then
    //if delimitor then move back until no delimitor
    //else if whitespace then move back until not whitespace then
    //   move back consistently over delimitors or word chars
    //else /*word char*/ move back until not word char or
    //   whitespace
    //move forward one
    #define boundsCheck if((static_cast<move_ts>(contents.y) < 0) or     \
                           (contents.y == 0 and contents.x == 0) or      \
                           (contents.x == 0 and not isWhitespace(ch))) { \
            if(contents.x == contents.cont[contents.y].size() - 1)       \
                mvf(contents);                                           \
            return boost::none;                                          \
        }
    #define ch contents.cont[contents.y][contents.x]
    if(contents.y == 0 and contents.x == 0) return boost::none;
    mvb(contents);
    while(isWhitespace(ch)) {
        mvb(contents);
        boundsCheck;
    }
    if(isDeliminator(ch)) {
        do {
            mvb(contents);
            if((static_cast<move_ts>(contents.y) < 0) or
               (contents.y == 0 and contents.x == 0) or
               (contents.x == 0 and not isWhitespace(ch))) {
                mvf(contents);
                return boost::none;
            }
        } while(isDeliminator(ch));
        mvf(contents);
    } else {
        if(contents.x == 0 and contents.cont[contents.y].size()) return boost::none;
        do {
            mvb(contents);
            boundsCheck;
        } while(!isDeliminator(ch) && !isWhitespace(ch));
        mvf(contents);
    }
    if(num > 1) mvbw(contents,num - 1);
    return boost::none;
    #undef boundsCheck
    #undef ch
}

}
}
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 by Contributors
 * \file cli_main.cc
 * \brief The command line interface program of xgboost.
 *  This file is not included in dynamic library.
 */
// Copyright 2014 by Contributors
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#define NOMINMAX

#include <xgboost/learner.h>
#include <xgboost/data.h>
#include <xgboost/logging.h>
#include <dmlc/timer.h>
#include <iomanip>
#include <ctime>
#include <string>
#include <cstdio>
#include <cstring>
#include <vector>
#include "./common/sync.h"
#include "./common/config.h"

namespace xgboost {

enum CLITask {
  kTrain = 0,
  kDumpModel = 1,
  kPredict = 2
};

struct CLIParam : public dmlc::Parameter<CLIParam> {
  /*! \brief the task name */
  int task;
  /*! \brief whether silent */
  int silent;
  /*! \brief whether evaluate training statistics */
  bool eval_train;
  /*! \brief number of boosting iterations */
  int num_round;
  /*! \brief the period to save the model, 0 means only save the final round model */
  int save_period;
  /*! \brief the path of training set */
  std::string train_path;
  /*! \brief path of test dataset */
  std::string test_path;
  /*! \brief the path of test model file, or file to restart training */
  std::string model_in;
  /*! \brief the path of final model file, to be saved */
  std::string model_out;
  /*! \brief the path of directory containing the saved models */
  std::string model_dir;
  /*! \brief name of predict file */
  std::string name_pred;
  /*! \brief data split mode */
  int dsplit;
  /*!\brief limit number of trees in prediction */
  int ntree_limit;
  /*!\brief whether to directly output margin value */
  bool pred_margin;
  /*! \brief whether dump statistics along with model */
  int dump_stats;
  /*! \brief what format to dump the model in */
  std::string dump_format;
  /*! \brief name of feature map */
  std::string name_fmap;
  /*! \brief name of dump file */
  std::string name_dump;
  /*! \brief the paths of validation data sets */
  std::vector<std::string> eval_data_paths;
  /*! \brief the names of the evaluation data used in output log */
  std::vector<std::string> eval_data_names;
  /*! \brief all the configurations */
  std::vector<std::pair<std::string, std::string> > cfg;

  // declare parameters
  DMLC_DECLARE_PARAMETER(CLIParam) {
    // NOTE: declare everything except eval_data_paths.
    DMLC_DECLARE_FIELD(task).set_default(kTrain)
        .add_enum("train", kTrain)
        .add_enum("dump", kDumpModel)
        .add_enum("pred", kPredict)
        .describe("Task to be performed by the CLI program.");
    DMLC_DECLARE_FIELD(silent).set_default(0).set_range(0, 2)
        .describe("Silent level during the task.");
    DMLC_DECLARE_FIELD(eval_train).set_default(false)
        .describe("Whether evaluate on training data during training.");
    DMLC_DECLARE_FIELD(num_round).set_default(10).set_lower_bound(1)
        .describe("Number of boosting iterations");
    DMLC_DECLARE_FIELD(save_period).set_default(0).set_lower_bound(0)
        .describe("The period to save the model, 0 means only save final model.");
    DMLC_DECLARE_FIELD(train_path).set_default("NULL")
        .describe("Training data path.");
    DMLC_DECLARE_FIELD(test_path).set_default("NULL")
        .describe("Test data path.");
    DMLC_DECLARE_FIELD(model_in).set_default("NULL")
        .describe("Input model path, if any.");
    DMLC_DECLARE_FIELD(model_out).set_default("NULL")
        .describe("Output model path, if any.");
    DMLC_DECLARE_FIELD(model_dir).set_default("./")
        .describe("Output directory of period checkpoint.");
    DMLC_DECLARE_FIELD(name_pred).set_default("pred.txt")
        .describe("Name of the prediction file.");
    DMLC_DECLARE_FIELD(dsplit).set_default(0)
        .add_enum("auto", 0)
        .add_enum("col", 1)
        .add_enum("row", 2)
        .describe("Data split mode.");
    DMLC_DECLARE_FIELD(ntree_limit).set_default(0).set_lower_bound(0)
        .describe("Number of trees used for prediction, 0 means use all trees.");
    DMLC_DECLARE_FIELD(pred_margin).set_default(false)
        .describe("Whether to predict margin value instead of probability.");
    DMLC_DECLARE_FIELD(dump_stats).set_default(false)
        .describe("Whether dump the model statistics.");
    DMLC_DECLARE_FIELD(dump_format).set_default("text")
        .describe("What format to dump the model in.");
    DMLC_DECLARE_FIELD(name_fmap).set_default("NULL")
        .describe("Name of the feature map file.");
    DMLC_DECLARE_FIELD(name_dump).set_default("dump.txt")
        .describe("Name of the output dump text file.");
    // alias
    DMLC_DECLARE_ALIAS(train_path, data);
    DMLC_DECLARE_ALIAS(test_path, test:data);
    DMLC_DECLARE_ALIAS(name_fmap, fmap);
  }
  // customized configure function of CLIParam
  inline void Configure(const std::vector<std::pair<std::string, std::string> >& cfg) {
    this->cfg = cfg;
    this->InitAllowUnknown(cfg);
    for (const auto& kv : cfg) {
      if (!strncmp("eval[", kv.first.c_str(), 5)) {
        char evname[256];
        CHECK_EQ(sscanf(kv.first.c_str(), "eval[%[^]]", evname), 1)
            << "must specify evaluation name for display";
        eval_data_names.emplace_back(evname);
        eval_data_paths.push_back(kv.second);
      }
    }
    // constraint.
    if (name_pred == "stdout") {
      save_period = 0;
      silent = 1;
    }
    if (dsplit == 0 && rabit::IsDistributed()) {
      dsplit = 2;
    }
    if (rabit::GetRank() != 0) {
      silent = 2;
    }
  }
};

DMLC_REGISTER_PARAMETER(CLIParam);

void CLITrain(const CLIParam& param) {
  const double tstart_data_load = dmlc::GetTime();
  if (rabit::IsDistributed()) {
    std::string pname = rabit::GetProcessorName();
    LOG(CONSOLE) << "start " << pname << ":" << rabit::GetRank();
  }
  // load in data.
  std::shared_ptr<DMatrix> dtrain(
      DMatrix::Load(param.train_path, param.silent != 0, param.dsplit == 2));
  std::vector<std::shared_ptr<DMatrix> > deval;
  std::vector<std::shared_ptr<DMatrix> > cache_mats;
  std::vector<DMatrix*> eval_datasets;
  cache_mats.push_back(dtrain);
  for (size_t i = 0; i < param.eval_data_names.size(); ++i) {
    deval.emplace_back(
        std::shared_ptr<DMatrix>(DMatrix::Load(param.eval_data_paths[i],
                                               param.silent != 0, param.dsplit == 2)));
    eval_datasets.push_back(deval.back().get());
    cache_mats.push_back(deval.back());
  }
  std::vector<std::string> eval_data_names = param.eval_data_names;
  if (param.eval_train) {
    eval_datasets.push_back(dtrain.get());
    eval_data_names.emplace_back("train");
  }
  // initialize the learner.
  std::unique_ptr<Learner> learner(Learner::Create(cache_mats));
  int version = rabit::LoadCheckPoint(learner.get());
  if (version == 0) {
    // initialize the model if needed.
    if (param.model_in != "NULL") {
      std::unique_ptr<dmlc::Stream> fi(
          dmlc::Stream::Create(param.model_in.c_str(), "r"));
      learner->Load(fi.get());
      learner->Configure(param.cfg);
    } else {
      learner->Configure(param.cfg);
      learner->InitModel();
    }
  }
  if (param.silent == 0) {
    LOG(INFO) << "Loading data: " << dmlc::GetTime() - tstart_data_load << " sec";
  }
  // start training.
  const double start = dmlc::GetTime();
  for (int i = version / 2; i < param.num_round; ++i) {
    double elapsed = dmlc::GetTime() - start;
    if (version % 2 == 0) {
      if (param.silent == 0) {
        LOG(CONSOLE) << "boosting round " << i << ", " << elapsed << " sec elapsed";
      }
      learner->UpdateOneIter(i, dtrain.get());
      if (learner->AllowLazyCheckPoint()) {
        rabit::LazyCheckPoint(learner.get());
      } else {
        rabit::CheckPoint(learner.get());
      }
      version += 1;
    }
    CHECK_EQ(version, rabit::VersionNumber());
    std::string res = learner->EvalOneIter(i, eval_datasets, eval_data_names);
    if (rabit::IsDistributed()) {
      if (rabit::GetRank() == 0) {
        LOG(TRACKER) << res;
      }
    } else {
      if (param.silent < 2) {
        LOG(CONSOLE) << res;
      }
    }
    if (param.save_period != 0 &&
        (i + 1) % param.save_period == 0 &&
        rabit::GetRank() == 0) {
      std::ostringstream os;
      os << param.model_dir << '/'
         << std::setfill('0') << std::setw(4)
         << i + 1 << ".model";
      std::unique_ptr<dmlc::Stream> fo(
          dmlc::Stream::Create(os.str().c_str(), "w"));
      learner->Save(fo.get());
    }

    if (learner->AllowLazyCheckPoint()) {
      rabit::LazyCheckPoint(learner.get());
    } else {
      rabit::CheckPoint(learner.get());
    }
    version += 1;
    CHECK_EQ(version, rabit::VersionNumber());
  }
  // always save final round
  if ((param.save_period == 0 || param.num_round % param.save_period != 0) &&
      param.model_out != "NONE" &&
      rabit::GetRank() == 0) {
    std::ostringstream os;
    if (param.model_out == "NULL") {
      os << param.model_dir << '/'
         << std::setfill('0') << std::setw(4)
         << param.num_round << ".model";
    } else {
      os << param.model_out;
    }
    std::unique_ptr<dmlc::Stream> fo(
        dmlc::Stream::Create(os.str().c_str(), "w"));
    learner->Save(fo.get());
  }

  if (param.silent == 0) {
    double elapsed = dmlc::GetTime() - start;
    LOG(CONSOLE) << "update end, " << elapsed << " sec in all";
  }
}

void CLIDumpModel(const CLIParam& param) {
  FeatureMap fmap;
  if (param.name_fmap != "NULL") {
    std::unique_ptr<dmlc::Stream> fs(
        dmlc::Stream::Create(param.name_fmap.c_str(), "r"));
    dmlc::istream is(fs.get());
    fmap.LoadText(is);
  }
  // load model
  CHECK_NE(param.model_in, "NULL")
      << "Must specify model_in for dump";
  std::unique_ptr<Learner> learner(Learner::Create({}));
  std::unique_ptr<dmlc::Stream> fi(
      dmlc::Stream::Create(param.model_in.c_str(), "r"));
  learner->Configure(param.cfg);
  learner->Load(fi.get());
  // dump data
  std::vector<std::string> dump = learner->DumpModel(
      fmap, param.dump_stats, param.dump_format);
  std::unique_ptr<dmlc::Stream> fo(
      dmlc::Stream::Create(param.name_dump.c_str(), "w"));
  dmlc::ostream os(fo.get());
  if (param.dump_format == "json") {
    os << "[" << std::endl;
    for (size_t i = 0; i < dump.size(); ++i) {
      if (i != 0) os << "," << std::endl;
      os << dump[i];  // Dump the previously generated JSON here
    }
    os << std::endl << "]" << std::endl;
  } else {
    for (size_t i = 0; i < dump.size(); ++i) {
      os << "booster[" << i << "]:\n";
      os << dump[i];
    }
  }
  // force flush before fo destruct.
  os.set_stream(nullptr);
}

void CLIPredict(const CLIParam& param) {
  CHECK_NE(param.test_path, "NULL")
      << "Test dataset parameter test:data must be specified.";
  // load data
  std::unique_ptr<DMatrix> dtest(
      DMatrix::Load(param.test_path, param.silent != 0, param.dsplit == 2));
  // load model
  CHECK_NE(param.model_in, "NULL")
      << "Must specify model_in for predict";
  std::unique_ptr<Learner> learner(Learner::Create({}));
  std::unique_ptr<dmlc::Stream> fi(
      dmlc::Stream::Create(param.model_in.c_str(), "r"));
  learner->Load(fi.get());
  learner->Configure(param.cfg);

  if (param.silent == 0) {
    LOG(CONSOLE) << "start prediction...";
  }
  HostDeviceVector<bst_float> preds;
  learner->Predict(dtest.get(), param.pred_margin, &preds, param.ntree_limit);
  if (param.silent == 0) {
    LOG(CONSOLE) << "writing prediction to " << param.name_pred;
  }
  std::unique_ptr<dmlc::Stream> fo(
      dmlc::Stream::Create(param.name_pred.c_str(), "w"));
  dmlc::ostream os(fo.get());
  for (bst_float p : preds.HostVector()) {
    os << p << '\n';
  }
  // force flush before fo destruct.
  os.set_stream(nullptr);
}

int CLIRunTask(int argc, char *argv[]) {
  if (argc < 2) {
    printf("Usage: <config>\n");
    return 0;
  }
  rabit::Init(argc, argv);

  std::vector<std::pair<std::string, std::string> > cfg;
  cfg.emplace_back("seed", "0");

  common::ConfigIterator itr(argv[1]);
  while (itr.Next()) {
    cfg.emplace_back(std::string(itr.Name()), std::string(itr.Val()));
  }

  for (int i = 2; i < argc; ++i) {
    char name[256], val[256];
    if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {
      cfg.emplace_back(std::string(name), std::string(val));
    }
  }
  CLIParam param;
  param.Configure(cfg);

  switch (param.task) {
    case kTrain: CLITrain(param); break;
    case kDumpModel: CLIDumpModel(param); break;
    case kPredict: CLIPredict(param); break;
  }
  rabit::Finalize();
  return 0;
}
}  // namespace xgboost

int main(int argc, char *argv[]) {
  return xgboost::CLIRunTask(argc, argv);
}
<commit_msg>Save outputs in high precision in CLI prediction (#3356)<commit_after>/*!
 * Copyright 2014 by Contributors
 * \file cli_main.cc
 * \brief The command line interface program of xgboost.
 *  This file is not included in dynamic library.
 */
// Copyright 2014 by Contributors
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#define NOMINMAX

#include <xgboost/learner.h>
#include <xgboost/data.h>
#include <xgboost/logging.h>
#include <dmlc/timer.h>
#include <iomanip>
#include <ctime>
#include <string>
#include <cstdio>
#include <cstring>
#include <vector>
#include "./common/sync.h"
#include "./common/config.h"

namespace xgboost {

enum CLITask {
  kTrain = 0,
  kDumpModel = 1,
  kPredict = 2
};

struct CLIParam : public dmlc::Parameter<CLIParam> {
  /*! \brief the task name */
  int task;
  /*! \brief whether silent */
  int silent;
  /*! \brief whether evaluate training statistics */
  bool eval_train;
  /*! \brief number of boosting iterations */
  int num_round;
  /*! \brief the period to save the model, 0 means only save the final round model */
  int save_period;
  /*! \brief the path of training set */
  std::string train_path;
  /*! \brief path of test dataset */
  std::string test_path;
  /*! \brief the path of test model file, or file to restart training */
  std::string model_in;
  /*! \brief the path of final model file, to be saved */
  std::string model_out;
  /*! \brief the path of directory containing the saved models */
  std::string model_dir;
  /*! \brief name of predict file */
  std::string name_pred;
  /*! \brief data split mode */
  int dsplit;
  /*!\brief limit number of trees in prediction */
  int ntree_limit;
  /*!\brief whether to directly output margin value */
  bool pred_margin;
  /*! \brief whether dump statistics along with model */
  int dump_stats;
  /*! \brief what format to dump the model in */
  std::string dump_format;
  /*! \brief name of feature map */
  std::string name_fmap;
  /*! \brief name of dump file */
  std::string name_dump;
  /*! \brief the paths of validation data sets */
  std::vector<std::string> eval_data_paths;
  /*! \brief the names of the evaluation data used in output log */
  std::vector<std::string> eval_data_names;
  /*! \brief all the configurations */
  std::vector<std::pair<std::string, std::string> > cfg;

  // declare parameters
  DMLC_DECLARE_PARAMETER(CLIParam) {
    // NOTE: declare everything except eval_data_paths.
    DMLC_DECLARE_FIELD(task).set_default(kTrain)
        .add_enum("train", kTrain)
        .add_enum("dump", kDumpModel)
        .add_enum("pred", kPredict)
        .describe("Task to be performed by the CLI program.");
    DMLC_DECLARE_FIELD(silent).set_default(0).set_range(0, 2)
        .describe("Silent level during the task.");
    DMLC_DECLARE_FIELD(eval_train).set_default(false)
        .describe("Whether evaluate on training data during training.");
    DMLC_DECLARE_FIELD(num_round).set_default(10).set_lower_bound(1)
        .describe("Number of boosting iterations");
    DMLC_DECLARE_FIELD(save_period).set_default(0).set_lower_bound(0)
        .describe("The period to save the model, 0 means only save final model.");
    DMLC_DECLARE_FIELD(train_path).set_default("NULL")
        .describe("Training data path.");
    DMLC_DECLARE_FIELD(test_path).set_default("NULL")
        .describe("Test data path.");
    DMLC_DECLARE_FIELD(model_in).set_default("NULL")
        .describe("Input model path, if any.");
    DMLC_DECLARE_FIELD(model_out).set_default("NULL")
        .describe("Output model path, if any.");
    DMLC_DECLARE_FIELD(model_dir).set_default("./")
        .describe("Output directory of period checkpoint.");
    DMLC_DECLARE_FIELD(name_pred).set_default("pred.txt")
        .describe("Name of the prediction file.");
    DMLC_DECLARE_FIELD(dsplit).set_default(0)
        .add_enum("auto", 0)
        .add_enum("col", 1)
        .add_enum("row", 2)
        .describe("Data split mode.");
    DMLC_DECLARE_FIELD(ntree_limit).set_default(0).set_lower_bound(0)
        .describe("Number of trees used for prediction, 0 means use all trees.");
    DMLC_DECLARE_FIELD(pred_margin).set_default(false)
        .describe("Whether to predict margin value instead of probability.");
    DMLC_DECLARE_FIELD(dump_stats).set_default(false)
        .describe("Whether dump the model statistics.");
    DMLC_DECLARE_FIELD(dump_format).set_default("text")
        .describe("What format to dump the model in.");
    DMLC_DECLARE_FIELD(name_fmap).set_default("NULL")
        .describe("Name of the feature map file.");
    DMLC_DECLARE_FIELD(name_dump).set_default("dump.txt")
        .describe("Name of the output dump text file.");
    // alias
    DMLC_DECLARE_ALIAS(train_path, data);
    DMLC_DECLARE_ALIAS(test_path, test:data);
    DMLC_DECLARE_ALIAS(name_fmap, fmap);
  }
  // customized configure function of CLIParam
  inline void Configure(const std::vector<std::pair<std::string, std::string> >& cfg) {
    this->cfg = cfg;
    this->InitAllowUnknown(cfg);
    for (const auto& kv : cfg) {
      if (!strncmp("eval[", kv.first.c_str(), 5)) {
        char evname[256];
        CHECK_EQ(sscanf(kv.first.c_str(), "eval[%[^]]", evname), 1)
            << "must specify evaluation name for display";
        eval_data_names.emplace_back(evname);
        eval_data_paths.push_back(kv.second);
      }
    }
    // constraint.
    if (name_pred == "stdout") {
      save_period = 0;
      silent = 1;
    }
    if (dsplit == 0 && rabit::IsDistributed()) {
      dsplit = 2;
    }
    if (rabit::GetRank() != 0) {
      silent = 2;
    }
  }
};

DMLC_REGISTER_PARAMETER(CLIParam);

void CLITrain(const CLIParam& param) {
  const double tstart_data_load = dmlc::GetTime();
  if (rabit::IsDistributed()) {
    std::string pname = rabit::GetProcessorName();
    LOG(CONSOLE) << "start " << pname << ":" << rabit::GetRank();
  }
  // load in data.
  std::shared_ptr<DMatrix> dtrain(
      DMatrix::Load(param.train_path, param.silent != 0, param.dsplit == 2));
  std::vector<std::shared_ptr<DMatrix> > deval;
  std::vector<std::shared_ptr<DMatrix> > cache_mats;
  std::vector<DMatrix*> eval_datasets;
  cache_mats.push_back(dtrain);
  for (size_t i = 0; i < param.eval_data_names.size(); ++i) {
    deval.emplace_back(
        std::shared_ptr<DMatrix>(DMatrix::Load(param.eval_data_paths[i],
                                               param.silent != 0, param.dsplit == 2)));
    eval_datasets.push_back(deval.back().get());
    cache_mats.push_back(deval.back());
  }
  std::vector<std::string> eval_data_names = param.eval_data_names;
  if (param.eval_train) {
    eval_datasets.push_back(dtrain.get());
    eval_data_names.emplace_back("train");
  }
  // initialize the learner.
  std::unique_ptr<Learner> learner(Learner::Create(cache_mats));
  int version = rabit::LoadCheckPoint(learner.get());
  if (version == 0) {
    // initialize the model if needed.
    if (param.model_in != "NULL") {
      std::unique_ptr<dmlc::Stream> fi(
          dmlc::Stream::Create(param.model_in.c_str(), "r"));
      learner->Load(fi.get());
      learner->Configure(param.cfg);
    } else {
      learner->Configure(param.cfg);
      learner->InitModel();
    }
  }
  if (param.silent == 0) {
    LOG(INFO) << "Loading data: " << dmlc::GetTime() - tstart_data_load << " sec";
  }
  // start training.
  const double start = dmlc::GetTime();
  for (int i = version / 2; i < param.num_round; ++i) {
    double elapsed = dmlc::GetTime() - start;
    if (version % 2 == 0) {
      if (param.silent == 0) {
        LOG(CONSOLE) << "boosting round " << i << ", " << elapsed << " sec elapsed";
      }
      learner->UpdateOneIter(i, dtrain.get());
      if (learner->AllowLazyCheckPoint()) {
        rabit::LazyCheckPoint(learner.get());
      } else {
        rabit::CheckPoint(learner.get());
      }
      version += 1;
    }
    CHECK_EQ(version, rabit::VersionNumber());
    std::string res = learner->EvalOneIter(i, eval_datasets, eval_data_names);
    if (rabit::IsDistributed()) {
      if (rabit::GetRank() == 0) {
        LOG(TRACKER) << res;
      }
    } else {
      if (param.silent < 2) {
        LOG(CONSOLE) << res;
      }
    }
    if (param.save_period != 0 &&
        (i + 1) % param.save_period == 0 &&
        rabit::GetRank() == 0) {
      std::ostringstream os;
      os << param.model_dir << '/'
         << std::setfill('0') << std::setw(4)
         << i + 1 << ".model";
      std::unique_ptr<dmlc::Stream> fo(
          dmlc::Stream::Create(os.str().c_str(), "w"));
      learner->Save(fo.get());
    }

    if (learner->AllowLazyCheckPoint()) {
      rabit::LazyCheckPoint(learner.get());
    } else {
      rabit::CheckPoint(learner.get());
    }
    version += 1;
    CHECK_EQ(version, rabit::VersionNumber());
  }
  // always save final round
  if ((param.save_period == 0 || param.num_round % param.save_period != 0) &&
      param.model_out != "NONE" &&
      rabit::GetRank() == 0) {
    std::ostringstream os;
    if (param.model_out == "NULL") {
      os << param.model_dir << '/'
         << std::setfill('0') << std::setw(4)
         << param.num_round << ".model";
    } else {
      os << param.model_out;
    }
    std::unique_ptr<dmlc::Stream> fo(
        dmlc::Stream::Create(os.str().c_str(), "w"));
    learner->Save(fo.get());
  }

  if (param.silent == 0) {
    double elapsed = dmlc::GetTime() - start;
    LOG(CONSOLE) << "update end, " << elapsed << " sec in all";
  }
}

void CLIDumpModel(const CLIParam& param) {
  FeatureMap fmap;
  if (param.name_fmap != "NULL") {
    std::unique_ptr<dmlc::Stream> fs(
        dmlc::Stream::Create(param.name_fmap.c_str(), "r"));
    dmlc::istream is(fs.get());
    fmap.LoadText(is);
  }
  // load model
  CHECK_NE(param.model_in, "NULL")
      << "Must specify model_in for dump";
  std::unique_ptr<Learner> learner(Learner::Create({}));
  std::unique_ptr<dmlc::Stream> fi(
      dmlc::Stream::Create(param.model_in.c_str(), "r"));
  learner->Configure(param.cfg);
  learner->Load(fi.get());
  // dump data
  std::vector<std::string> dump = learner->DumpModel(
      fmap, param.dump_stats, param.dump_format);
  std::unique_ptr<dmlc::Stream> fo(
      dmlc::Stream::Create(param.name_dump.c_str(), "w"));
  dmlc::ostream os(fo.get());
  if (param.dump_format == "json") {
    os << "[" << std::endl;
    for (size_t i = 0; i < dump.size(); ++i) {
      if (i != 0) os << "," << std::endl;
      os << dump[i];  // Dump the previously generated JSON here
    }
    os << std::endl << "]" << std::endl;
  } else {
    for (size_t i = 0; i < dump.size(); ++i) {
      os << "booster[" << i << "]:\n";
      os << dump[i];
    }
  }
  // force flush before fo destruct.
  os.set_stream(nullptr);
}

void CLIPredict(const CLIParam& param) {
  CHECK_NE(param.test_path, "NULL")
      << "Test dataset parameter test:data must be specified.";
  // load data
  std::unique_ptr<DMatrix> dtest(
      DMatrix::Load(param.test_path, param.silent != 0, param.dsplit == 2));
  // load model
  CHECK_NE(param.model_in, "NULL")
      << "Must specify model_in for predict";
  std::unique_ptr<Learner> learner(Learner::Create({}));
  std::unique_ptr<dmlc::Stream> fi(
      dmlc::Stream::Create(param.model_in.c_str(), "r"));
  learner->Load(fi.get());
  learner->Configure(param.cfg);

  if (param.silent == 0) {
    LOG(CONSOLE) << "start prediction...";
  }
  HostDeviceVector<bst_float> preds;
  learner->Predict(dtest.get(), param.pred_margin, &preds, param.ntree_limit);
  if (param.silent == 0) {
    LOG(CONSOLE) << "writing prediction to " << param.name_pred;
  }
  std::unique_ptr<dmlc::Stream> fo(
      dmlc::Stream::Create(param.name_pred.c_str(), "w"));
  dmlc::ostream os(fo.get());
  for (bst_float p : preds.HostVector()) {
    os << std::setprecision(std::numeric_limits<bst_float>::max_digits10 + 2)
       << p << '\n';
  }
  // force flush before fo destruct.
  os.set_stream(nullptr);
}

int CLIRunTask(int argc, char *argv[]) {
  if (argc < 2) {
    printf("Usage: <config>\n");
    return 0;
  }
  rabit::Init(argc, argv);

  std::vector<std::pair<std::string, std::string> > cfg;
  cfg.emplace_back("seed", "0");

  common::ConfigIterator itr(argv[1]);
  while (itr.Next()) {
    cfg.emplace_back(std::string(itr.Name()), std::string(itr.Val()));
  }

  for (int i = 2; i < argc; ++i) {
    char name[256], val[256];
    if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {
      cfg.emplace_back(std::string(name), std::string(val));
    }
  }
  CLIParam param;
  param.Configure(cfg);

  switch (param.task) {
    case kTrain: CLITrain(param); break;
    case kDumpModel: CLIDumpModel(param); break;
    case kPredict: CLIPredict(param); break;
  }
  rabit::Finalize();
  return 0;
}
}  // namespace xgboost

int main(int argc, char *argv[]) {
  return xgboost::CLIRunTask(argc, argv);
}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>

#include "clutter.hpp"
#include "actor.hpp"
#include "container.hpp"
#include "group.hpp"
#include "stage.hpp"
#include "rectangle.hpp"
#include "text.hpp"
#include "texture.hpp"
#include "state.hpp"
#include "media.hpp"

#if ENABLE_CLUTTER_GST
#include "gst/gst.hpp"
#include "gst/video-texture.hpp"
#endif

#if ENABLE_WIDGET
#include "widgets/FlickView.hpp"
#endif

namespace clutter {

using namespace node;
using namespace v8;

static Handle<Value> ClutterInit(const Arguments& args)
{
	HandleScope scope;

	return scope.Close(Integer::New(clutter_init(NULL, NULL)));
}

static Handle<Value> ClutterMain(const Arguments& args)
{
	clutter_main();

	return Undefined();
}

static Handle<Value> SetUseARGBVisual(const Arguments& args)
{
	if (args[0]->IsBoolean()) {
		clutter_x11_set_use_argb_visual(args[0]->ToBoolean()->Value());
	}

	return Undefined();
}

static Handle<Value> ClutterMainQuit(const Arguments& args)
{
	clutter_main_quit();

	return Undefined();
}

extern "C" {
	static void init(Handle<Object> target)
	{
		HandleScope scope;

		/* Error conditions for initializing*/
		CLUTTER_DEFINE_CONSTANT(target, "INIT_SUCCESS", CLUTTER_INIT_SUCCESS);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_UNKNOWN", CLUTTER_INIT_ERROR_UNKNOWN);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_THREADS", CLUTTER_INIT_ERROR_THREADS);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_BACKEND", CLUTTER_INIT_ERROR_BACKEND);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_INTERNAL", CLUTTER_INIT_ERROR_INTERNAL);

		/* ClutterGravity */
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NONE", CLUTTER_GRAVITY_NONE);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NORTH", CLUTTER_GRAVITY_NORTH);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NORTH_EAST", CLUTTER_GRAVITY_NORTH_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_EAST", CLUTTER_GRAVITY_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH_EAST", CLUTTER_GRAVITY_SOUTH_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH", CLUTTER_GRAVITY_SOUTH);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH_WEST", CLUTTER_GRAVITY_SOUTH_WEST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_CENTER", CLUTTER_GRAVITY_CENTER);

		/* ClutterRotateAxis */
		CLUTTER_DEFINE_CONSTANT(target, "X_AXIS", CLUTTER_X_AXIS);
		CLUTTER_DEFINE_CONSTANT(target, "Y_AXIS", CLUTTER_Y_AXIS);
		CLUTTER_DEFINE_CONSTANT(target, "Z_AXIS", CLUTTER_Z_AXIS);

		/* ClutterRotateDirection */
		CLUTTER_DEFINE_CONSTANT(target, "ROTATE_CW", CLUTTER_ROTATE_CW);
		CLUTTER_DEFINE_CONSTANT(target, "ROTATE_CCW", CLUTTER_ROTATE_CCW);

		/* ClutterAlpha */
		CLUTTER_DEFINE_CONSTANT(target, "CUSTOM_MODE", CLUTTER_CUSTOM_MODE);

		/* linear */
		CLUTTER_DEFINE_CONSTANT(target, "LINEAR", CLUTTER_LINEAR);

		/* quadratic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUAD", CLUTTER_EASE_IN_QUAD);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUAD", CLUTTER_EASE_OUT_QUAD);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUAD", CLUTTER_EASE_IN_OUT_QUAD);

		/* cubic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_CUBIC", CLUTTER_EASE_IN_CUBIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_CUBIC", CLUTTER_EASE_OUT_CUBIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_CUBIC", CLUTTER_EASE_IN_OUT_CUBIC);

		/* quartic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUART", CLUTTER_EASE_IN_QUART);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUART", CLUTTER_EASE_OUT_QUART);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUART", CLUTTER_EASE_IN_OUT_QUART);

		/* quintic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUINT", CLUTTER_EASE_IN_QUINT);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUINT", CLUTTER_EASE_OUT_QUINT);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUINT", CLUTTER_EASE_IN_OUT_QUINT);

		/* sinusoidal */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_SINE", CLUTTER_EASE_IN_SINE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_SINE", CLUTTER_EASE_OUT_SINE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_SINE", CLUTTER_EASE_IN_OUT_SINE);

		/* exponential */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_EXPO", CLUTTER_EASE_IN_EXPO);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_EXPO", CLUTTER_EASE_OUT_EXPO);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_EXPO", CLUTTER_EASE_IN_OUT_EXPO);

		/* circular */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_CIRC", CLUTTER_EASE_IN_CIRC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_CIRC", CLUTTER_EASE_OUT_CIRC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_CIRC", CLUTTER_EASE_IN_OUT_CIRC);

		/* elastic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_ELASTIC", CLUTTER_EASE_IN_ELASTIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_ELASTIC", CLUTTER_EASE_OUT_ELASTIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_ELASTIC", CLUTTER_EASE_IN_OUT_ELASTIC);

		/* overshooting cubic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_BACK", CLUTTER_EASE_IN_BACK);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_BACK", CLUTTER_EASE_OUT_BACK);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_BACK", CLUTTER_EASE_IN_OUT_BACK);

		/* exponentially decaying parabolic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_BOUNCE", CLUTTER_EASE_IN_BOUNCE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_BOUNCE", CLUTTER_EASE_OUT_BOUNCE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_BOUNCE", CLUTTER_EASE_IN_OUT_BOUNCE);

		/* Effect */
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_CUSTOM", NODE_CLUTTER_EFFECT_CUSTOM);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_BLUR", NODE_CLUTTER_EFFECT_BLUR);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_COLORIZE", NODE_CLUTTER_EFFECT_COLORIZE);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_DESATURATE", NODE_CLUTTER_EFFECT_DESATURATE);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_PAGE_TURN", NODE_CLUTTER_EFFECT_PAGE_TURN);

		/* own events */
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_DESTROY", NODE_CLUTTER_EVENT_DESTROY);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_SHOW", NODE_CLUTTER_EVENT_SHOW);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_HIDE", NODE_CLUTTER_EVENT_HIDE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_PRESS", NODE_CLUTTER_EVENT_PRESS);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_RELEASE", NODE_CLUTTER_EVENT_RELEASE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_CLICK", NODE_CLUTTER_EVENT_CLICK);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_LONG_PRESS", NODE_CLUTTER_EVENT_LONG_PRESS);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_ENTER", NODE_CLUTTER_EVENT_ENTER);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_LEAVE", NODE_CLUTTER_EVENT_LEAVE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_MOTION", NODE_CLUTTER_EVENT_MOTION);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_DRAG", NODE_CLUTTER_EVENT_DRAG);

		/* Action state */
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_QUERY", CLUTTER_LONG_PRESS_QUERY);
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_ACTIVATE", CLUTTER_LONG_PRESS_ACTIVATE);
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_CANCEL", CLUTTER_LONG_PRESS_CANCEL);

		/* Animation */
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_PLAY", NODE_CLUTTER_ANIMATION_PLAY);
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_PAUSE", NODE_CLUTTER_ANIMATION_PAUSE);
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_STOP", NODE_CLUTTER_ANIMATION_STOP);

		NODE_SET_METHOD(target, "init", ClutterInit);
		NODE_SET_METHOD(target, "main", ClutterMain);
		NODE_SET_METHOD(target, "quit", ClutterMainQuit);
		NODE_SET_METHOD(target, "useARGB", SetUseARGBVisual);

		Actor::Initialize(target);
		Container::Initialize(target);
		Group::Initialize(target);
		Stage::Initialize(target);
		Rectangle::Initialize(target);
		Text::Initialize(target);
		Texture::Initialize(target);
		State::Initialize(target);

#if ENABLE_CLUTTER_GST
		Gst::Initialize(target);
		GstVideoTexture::Initialize(target);
#endif

#if ENABLE_WIDGET
		FlickView::Initialize(target);
#endif
	}

	NODE_MODULE(clutter, init);
}

}
<commit_msg>replace clutter_main() with g_main_context to avoid process hangging<commit_after>#include <v8.h>
#include <node.h>
#include <ev.h>
#include <stdlib.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>

#include "clutter.hpp"
#include "actor.hpp"
#include "container.hpp"
#include "group.hpp"
#include "stage.hpp"
#include "rectangle.hpp"
#include "text.hpp"
#include "texture.hpp"
#include "state.hpp"
#include "media.hpp"

#if ENABLE_CLUTTER_GST
#include "gst/gst.hpp"
#include "gst/video-texture.hpp"
#endif

#if ENABLE_WIDGET
#include "widgets/FlickView.hpp"
#endif

namespace clutter {

using namespace node;
using namespace v8;

struct econtext {
	GPollFD *pfd;
	ev_io *iow;
	int nfd, afd;
	gint maxpri;

	ev_prepare pw;
	ev_check cw;
	ev_timer tw;

	GMainContext *gc;
};

static struct econtext default_context;

static void timer_cb(EV_P_ ev_timer *w, int revents) {
  /* nop */
}

static void io_cb(EV_P_ ev_io *w, int revents) {
  /* nop */
}

static void prepare_cb(EV_P_ ev_prepare *w, int revents)
{
	struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, pw));
	gint timeout;
	int i;

	g_main_context_dispatch(ctx->gc);

	g_main_context_prepare(ctx->gc, &ctx->maxpri);

	while(ctx->afd < (ctx->nfd = g_main_context_query(
		ctx->gc,
		ctx->maxpri,
		&timeout,
		ctx->pfd,
		ctx->afd))) {

		free (ctx->pfd);
		free (ctx->iow);

		ctx->afd = 1;
		while (ctx->afd < ctx->nfd)
			ctx->afd <<= 1;

		ctx->pfd = (GPollFD*) malloc(ctx->afd * sizeof (GPollFD));
		ctx->iow = (ev_io*) malloc(ctx->afd * sizeof (ev_io));
	}

	for (i = 0; i < ctx->nfd; ++i) {
		GPollFD *pfd = ctx->pfd + i;
		ev_io *iow = ctx->iow + i;

		pfd->revents = 0;

		ev_io_init(iow,
			io_cb,
			pfd->fd,
			(pfd->events & G_IO_IN ? EV_READ : 0)
			| (pfd->events & G_IO_OUT ? EV_WRITE : 0));

		iow->data = (void *)pfd;
		ev_set_priority(iow, EV_MINPRI);
		ev_io_start(EV_A_ iow);
	}

	if (timeout >= 0) {
		ev_timer_set(&ctx->tw, timeout * 1e-3, 0.);
		ev_timer_start(EV_A_ &ctx->tw);
	}
}

static void check_cb(EV_P_ ev_check *w, int revents)
{
	struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, cw));
	int i;

	for (i = 0; i < ctx->nfd; ++i) {
		ev_io *iow = ctx->iow + i;

		if (ev_is_pending(iow)) {
			GPollFD *pfd = ctx->pfd + i;
			int revents = ev_clear_pending(EV_A_ iow);

			pfd->revents |= pfd->events & ((revents & EV_READ ? G_IO_IN : 0) | (revents & EV_WRITE ? G_IO_OUT : 0));
		}

		ev_io_stop(EV_A_ iow);
	}

	if (ev_is_active(&ctx->tw))
		ev_timer_stop(EV_A_ &ctx->tw);

	g_main_context_check(ctx->gc, ctx->maxpri, ctx->pfd, ctx->nfd);
}

static void ContextInit()
{
	GMainContext *gc = g_main_context_default();
	struct econtext *ctx = &default_context;

	if (!g_thread_supported())
		g_thread_init(NULL);

	g_main_context_acquire(gc);
	ctx->gc = g_main_context_ref(gc);
	ctx->nfd = 0;
	ctx->afd = 0;
	ctx->iow = 0;
	ctx->pfd = 0;

	ev_prepare_init(&ctx->pw, prepare_cb);
	ev_set_priority(&ctx->pw, EV_MINPRI);
	ev_prepare_start(EV_DEFAULT_UC_ &ctx->pw);
	ev_unref(EV_DEFAULT_UC);

	ev_check_init(&ctx->cw, check_cb);
	ev_set_priority(&ctx->cw, EV_MAXPRI);
	ev_check_start(EV_DEFAULT_UC_ &ctx->cw);
	ev_unref(EV_DEFAULT_UC);

	ev_init(&ctx->tw, timer_cb);
	ev_set_priority(&ctx->tw, EV_MINPRI);
}

static Handle<Value> ClutterInit(const Arguments& args)
{
	HandleScope scope;

	return scope.Close(Integer::New(clutter_init(NULL, NULL)));
}

static Handle<Value> ClutterMain(const Arguments& args)
{
	HandleScope scope;

	ev_ref(EV_DEFAULT_UC);

	return Undefined();
}

static Handle<Value> SetUseARGBVisual(const Arguments& args)
{
	if (args[0]->IsBoolean()) {
		clutter_x11_set_use_argb_visual(args[0]->ToBoolean()->Value());
	}

	return Undefined();
}

static Handle<Value> ClutterMainQuit(const Arguments& args)
{
	clutter_main_quit();

	ev_unref(EV_DEFAULT_UC);

	return Undefined();
}

extern "C" {
	static void init(Handle<Object> target)
	{
		HandleScope scope;

		/* Error conditions for initializing*/
		CLUTTER_DEFINE_CONSTANT(target, "INIT_SUCCESS", CLUTTER_INIT_SUCCESS);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_UNKNOWN", CLUTTER_INIT_ERROR_UNKNOWN);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_THREADS", CLUTTER_INIT_ERROR_THREADS);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_BACKEND", CLUTTER_INIT_ERROR_BACKEND);
		CLUTTER_DEFINE_CONSTANT(target, "INIT_INTERNAL", CLUTTER_INIT_ERROR_INTERNAL);

		/* ClutterGravity */
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NONE", CLUTTER_GRAVITY_NONE);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NORTH", CLUTTER_GRAVITY_NORTH);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_NORTH_EAST", CLUTTER_GRAVITY_NORTH_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_EAST", CLUTTER_GRAVITY_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH_EAST", CLUTTER_GRAVITY_SOUTH_EAST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH", CLUTTER_GRAVITY_SOUTH);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_SOUTH_WEST", CLUTTER_GRAVITY_SOUTH_WEST);
		CLUTTER_DEFINE_CONSTANT(target, "GRAVITY_CENTER", CLUTTER_GRAVITY_CENTER);

		/* ClutterRotateAxis */
		CLUTTER_DEFINE_CONSTANT(target, "X_AXIS", CLUTTER_X_AXIS);
		CLUTTER_DEFINE_CONSTANT(target, "Y_AXIS", CLUTTER_Y_AXIS);
		CLUTTER_DEFINE_CONSTANT(target, "Z_AXIS", CLUTTER_Z_AXIS);

		/* ClutterRotateDirection */
		CLUTTER_DEFINE_CONSTANT(target, "ROTATE_CW", CLUTTER_ROTATE_CW);
		CLUTTER_DEFINE_CONSTANT(target, "ROTATE_CCW", CLUTTER_ROTATE_CCW);

		/* ClutterAlpha */
		CLUTTER_DEFINE_CONSTANT(target, "CUSTOM_MODE", CLUTTER_CUSTOM_MODE);

		/* linear */
		CLUTTER_DEFINE_CONSTANT(target, "LINEAR", CLUTTER_LINEAR);

		/* quadratic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUAD", CLUTTER_EASE_IN_QUAD);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUAD", CLUTTER_EASE_OUT_QUAD);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUAD", CLUTTER_EASE_IN_OUT_QUAD);

		/* cubic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_CUBIC", CLUTTER_EASE_IN_CUBIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_CUBIC", CLUTTER_EASE_OUT_CUBIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_CUBIC", CLUTTER_EASE_IN_OUT_CUBIC);

		/* quartic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUART", CLUTTER_EASE_IN_QUART);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUART", CLUTTER_EASE_OUT_QUART);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUART", CLUTTER_EASE_IN_OUT_QUART);

		/* quintic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_QUINT", CLUTTER_EASE_IN_QUINT);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_QUINT", CLUTTER_EASE_OUT_QUINT);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_QUINT", CLUTTER_EASE_IN_OUT_QUINT);

		/* sinusoidal */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_SINE", CLUTTER_EASE_IN_SINE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_SINE", CLUTTER_EASE_OUT_SINE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_SINE", CLUTTER_EASE_IN_OUT_SINE);

		/* exponential */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_EXPO", CLUTTER_EASE_IN_EXPO);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_EXPO", CLUTTER_EASE_OUT_EXPO);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_EXPO", CLUTTER_EASE_IN_OUT_EXPO);

		/* circular */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_CIRC", CLUTTER_EASE_IN_CIRC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_CIRC", CLUTTER_EASE_OUT_CIRC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_CIRC", CLUTTER_EASE_IN_OUT_CIRC);

		/* elastic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_ELASTIC", CLUTTER_EASE_IN_ELASTIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_ELASTIC", CLUTTER_EASE_OUT_ELASTIC);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_ELASTIC", CLUTTER_EASE_IN_OUT_ELASTIC);

		/* overshooting cubic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_BACK", CLUTTER_EASE_IN_BACK);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_BACK", CLUTTER_EASE_OUT_BACK);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_BACK", CLUTTER_EASE_IN_OUT_BACK);

		/* exponentially decaying parabolic */
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_BOUNCE", CLUTTER_EASE_IN_BOUNCE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_OUT_BOUNCE", CLUTTER_EASE_OUT_BOUNCE);
		CLUTTER_DEFINE_CONSTANT(target, "EASE_IN_OUT_BOUNCE", CLUTTER_EASE_IN_OUT_BOUNCE);

		/* Effect */
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_CUSTOM", NODE_CLUTTER_EFFECT_CUSTOM);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_BLUR", NODE_CLUTTER_EFFECT_BLUR);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_COLORIZE", NODE_CLUTTER_EFFECT_COLORIZE);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_DESATURATE", NODE_CLUTTER_EFFECT_DESATURATE);
		CLUTTER_DEFINE_CONSTANT(target, "EFFECT_PAGE_TURN", NODE_CLUTTER_EFFECT_PAGE_TURN);

		/* own events */
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_DESTROY", NODE_CLUTTER_EVENT_DESTROY);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_SHOW", NODE_CLUTTER_EVENT_SHOW);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_HIDE", NODE_CLUTTER_EVENT_HIDE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_PRESS", NODE_CLUTTER_EVENT_PRESS);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_RELEASE", NODE_CLUTTER_EVENT_RELEASE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_CLICK", NODE_CLUTTER_EVENT_CLICK);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_LONG_PRESS", NODE_CLUTTER_EVENT_LONG_PRESS);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_ENTER", NODE_CLUTTER_EVENT_ENTER);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_LEAVE", NODE_CLUTTER_EVENT_LEAVE);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_MOTION", NODE_CLUTTER_EVENT_MOTION);
		CLUTTER_DEFINE_CONSTANT(target, "EVENT_DRAG", NODE_CLUTTER_EVENT_DRAG);

		/* Action state */
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_QUERY", CLUTTER_LONG_PRESS_QUERY);
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_ACTIVATE", CLUTTER_LONG_PRESS_ACTIVATE);
		CLUTTER_DEFINE_CONSTANT(target, "ACTION_STATE_LONG_PRESS_CANCEL", CLUTTER_LONG_PRESS_CANCEL);

		/* Animation */
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_PLAY", NODE_CLUTTER_ANIMATION_PLAY);
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_PAUSE", NODE_CLUTTER_ANIMATION_PAUSE);
		CLUTTER_DEFINE_CONSTANT(target, "ANIMATION_STOP", NODE_CLUTTER_ANIMATION_STOP);

		NODE_SET_METHOD(target, "init", ClutterInit);
		NODE_SET_METHOD(target, "main", ClutterMain);
		NODE_SET_METHOD(target, "quit", ClutterMainQuit);
		NODE_SET_METHOD(target, "useARGB", SetUseARGBVisual);

		Actor::Initialize(target);
		Container::Initialize(target);
		Group::Initialize(target);
		Stage::Initialize(target);
		Rectangle::Initialize(target);
		Text::Initialize(target);
		Texture::Initialize(target);
		State::Initialize(target);

#if ENABLE_CLUTTER_GST
		Gst::Initialize(target);
		GstVideoTexture::Initialize(target);
#endif

#if ENABLE_WIDGET
		FlickView::Initialize(target);
#endif

		ContextInit();
	}

	NODE_MODULE(clutter, init);
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include <gl/egl-implementation.h>

// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/dali-vector.h>

// INTERNAL INCLUDES
#include <gl/gl-implementation.h>
#include <gl/egl-debug.h>

// EGL constants use C style casts
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

#define TEST_EGL_ERROR(lastCommand) \
{ \
  EGLint err = eglGetError(); \
  if (err != EGL_SUCCESS) \
  { \
    DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
    Egl::PrintError(err); \
    DALI_ASSERT_ALWAYS(0 && "EGL error"); \
  } \
}

EglImplementation::EglImplementation( unsigned int multiSamplingLevel )
  : mEglNativeDisplay(0),
    mEglNativeWindow(0),
    mCurrentEglNativePixmap(0),
    mEglDisplay(0),
    mEglConfig(0),
    mEglContext(0),
    mCurrentEglSurface(0),
    mGlesInitialized(false),
    mIsOwnSurface(true),
    mContextCurrent(false),
    mIsWindow(true),
    mColorDepth(COLOR_DEPTH_24),
    mMultiSamplingLevel( multiSamplingLevel )
{
}

EglImplementation::~EglImplementation()
{
  TerminateGles();
}

bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
{
  if ( !mGlesInitialized )
  {
    mEglNativeDisplay = display;

    //@todo see if we can just EGL_DEFAULT_DISPLAY instead
    mEglDisplay = eglGetDisplay(mEglNativeDisplay);
    EGLint error = eglGetError();

    if( mEglDisplay == NULL && error != EGL_SUCCESS )
    {
      throw Dali::DaliException( "", "OpenGL ES is not supported");
    }

    EGLint majorVersion = 0;
    EGLint minorVersion = 0;
    if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
    {
      return false;
    }
    eglBindAPI(EGL_OPENGL_ES_API);

    mContextAttribs.Clear();

#if DALI_GLES_VERSION >= 30

    mContextAttribs.Reserve(5);
    mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
    mContextAttribs.PushBack( DALI_GLES_VERSION / 10 );
    mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
    mContextAttribs.PushBack( DALI_GLES_VERSION % 10 );

#else // DALI_GLES_VERSION >= 30

    mContextAttribs.Reserve(3);
    mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
    mContextAttribs.PushBack( 2 );

#endif // DALI_GLES_VERSION >= 30

    mContextAttribs.PushBack( EGL_NONE );

    mGlesInitialized = true;
    mIsOwnSurface = isOwnSurface;
  }

  return mGlesInitialized;
}

bool EglImplementation::CreateContext()
{
  // make sure a context isn't created twice
  DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );

  mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
  TEST_EGL_ERROR("eglCreateContext render thread");

  DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );

  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));

  return true;
}

void EglImplementation::DestroyContext()
{
  DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );

  eglDestroyContext( mEglDisplay, mEglContext );
  mEglContext = 0;
}

void EglImplementation::DestroySurface()
{
  if(mIsOwnSurface && mCurrentEglSurface)
  {
    eglDestroySurface( mEglDisplay, mCurrentEglSurface );
    mCurrentEglSurface = 0;
  }
}

void EglImplementation::MakeContextCurrent()
{
  mContextCurrent = true;

  if(mIsOwnSurface)
  {
    eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext );
  }

  EGLint error = eglGetError();

  if ( error != EGL_SUCCESS )
  {
    Egl::PrintError(error);

    DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
  }

  // We want to display this information all the time, so use the LogMessage directly
  Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n"
      "            Vendor:        %s\n"
      "            Version:       %s\n"
      "            Client APIs:   %s\n"
      "            Extensions:    %s\n",
      eglQueryString(mEglDisplay, EGL_VENDOR),
      eglQueryString(mEglDisplay, EGL_VERSION),
      eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
      eglQueryString(mEglDisplay, EGL_EXTENSIONS));
}

void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglSurface )
{
  mCurrentEglNativePixmap = pixmap;
  mCurrentEglSurface = eglSurface;

  if(mIsOwnSurface)
  {
    eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext );
  }

  EGLint error = eglGetError();

  if ( error != EGL_SUCCESS )
  {
    Egl::PrintError(error);

    DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
  }
}

void EglImplementation::MakeContextNull()
{
  mContextCurrent = false;
  // clear the current context
  eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
}

void EglImplementation::TerminateGles()
{
  if ( mGlesInitialized )
  {
    // in latest Mali DDK (r2p3 ~ r3p0 in April, 2012),
    // MakeContextNull should be called before eglDestroy surface
    // to prevent crash in _mali_surface_destroy_callback
    MakeContextNull();

    if(mIsOwnSurface && mCurrentEglSurface)
    {
      eglDestroySurface(mEglDisplay, mCurrentEglSurface);
    }
    eglDestroyContext(mEglDisplay, mEglContext);

    eglTerminate(mEglDisplay);

    mEglDisplay = NULL;
    mEglConfig  = NULL;
    mEglContext = NULL;
    mCurrentEglSurface = NULL;

    mGlesInitialized = false;
  }
}

bool EglImplementation::IsGlesInitialized() const
{
  return mGlesInitialized;
}

void EglImplementation::SwapBuffers()
{
  eglSwapBuffers( mEglDisplay, mCurrentEglSurface );
}

void EglImplementation::CopyBuffers()
{
  eglCopyBuffers( mEglDisplay, mCurrentEglSurface, mCurrentEglNativePixmap );
}

void EglImplementation::WaitGL()
{
  eglWaitGL();
}

void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
{
  if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
  {
    return;
  }

  mIsWindow = isWindowType;

  EGLint numConfigs;
  Vector<EGLint> configAttribs;
  configAttribs.Reserve(31);

  if(isWindowType)
  {
    configAttribs.PushBack( EGL_SURFACE_TYPE );
    configAttribs.PushBack( EGL_WINDOW_BIT );
  }
  else
  {
    configAttribs.PushBack( EGL_SURFACE_TYPE );
    configAttribs.PushBack( EGL_PIXMAP_BIT );
  }

  configAttribs.PushBack( EGL_RENDERABLE_TYPE );

#if DALI_GLES_VERSION >= 30

#ifdef _ARCH_ARM_
  configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
#else
  // There is a bug in the desktop emulator
  // Requesting for ES3 causes eglCreateContext even though it allows to ask
  // for a configuration that supports GLES 3.0
  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
#endif // _ARCH_ARM_

#else // DALI_GLES_VERSION >= 30

  Integration::Log::LogMessage( Integration::Log::DebugInfo, "Using OpenGL ES 2 \n" );
  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );

#endif //DALI_GLES_VERSION >= 30

#if DALI_GLES_VERSION >= 30
// TODO: enable this flag when it becomes supported
//  configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
//  configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
#endif //DALI_GLES_VERSION >= 30

  configAttribs.PushBack( EGL_RED_SIZE );
  configAttribs.PushBack( 8 );
  configAttribs.PushBack( EGL_GREEN_SIZE );
  configAttribs.PushBack( 8 );
  configAttribs.PushBack( EGL_BLUE_SIZE );
  configAttribs.PushBack( 8 );

  configAttribs.PushBack( EGL_ALPHA_SIZE );
#ifdef _ARCH_ARM_
  configAttribs.PushBack( (depth == COLOR_DEPTH_32) ? 8 : 0 );
#else
  // There is a bug in the desktop emulator
  // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing
  configAttribs.PushBack( 0 );
#endif // _ARCH_ARM_

  configAttribs.PushBack( EGL_DEPTH_SIZE );
  configAttribs.PushBack( 24 );
  configAttribs.PushBack( EGL_STENCIL_SIZE );
  configAttribs.PushBack( 8 );
#ifndef DALI_PROFILE_UBUNTU
  configAttribs.PushBack( EGL_SAMPLES );
  configAttribs.PushBack( mMultiSamplingLevel );
  configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
  configAttribs.PushBack( 1 );
#endif // DALI_PROFILE_UBUNTU
  configAttribs.PushBack( EGL_NONE );

  if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
  {
    EGLint error = eglGetError();
    switch (error)
    {
      case EGL_BAD_DISPLAY:
      {
        DALI_LOG_ERROR("Display is not an EGL display connection\n");
        break;
      }
      case EGL_BAD_ATTRIBUTE:
      {
        DALI_LOG_ERROR("The parameter configAttribs contains an invalid frame buffer configuration attribute or an attribute value that is unrecognized or out of range\n");
        break;
      }
      case EGL_NOT_INITIALIZED:
      {
        DALI_LOG_ERROR("Display has not been initialized\n");
        break;
      }
      case EGL_BAD_PARAMETER:
      {
        DALI_LOG_ERROR("The parameter numConfig is NULL\n");
        break;
      }
      default:
      {
        DALI_LOG_ERROR("Unknown error.\n");
      }
    }
    DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
  }

  if ( numConfigs != 1 )
  {
    DALI_LOG_ERROR("No configurations found.\n");

    TEST_EGL_ERROR("eglChooseConfig");
  }
}

void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
{
  DALI_ASSERT_ALWAYS( ( mCurrentEglSurface == 0 ) && "EGL surface already exists" );

  mEglNativeWindow = window;
  mColorDepth = depth;
  mIsWindow = true;

  // egl choose config
  ChooseConfig(mIsWindow, mColorDepth);

  mCurrentEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
  TEST_EGL_ERROR("eglCreateWindowSurface");

  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" );
}

EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
{
  mCurrentEglNativePixmap = pixmap;
  mColorDepth = depth;
  mIsWindow = false;

  // egl choose config
  ChooseConfig(mIsWindow, mColorDepth);

  mCurrentEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL );
  TEST_EGL_ERROR("eglCreatePixmapSurface");

  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create pixmap surface failed" );

  return mCurrentEglSurface;
}

bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
{
  bool contextLost = false;

  // display connection has not changed, then we can just create a new surface
  //  the surface is bound to the context, so set the context to null
  MakeContextNull();

  // destroy the surface
  DestroySurface();

  // create the EGL surface
  CreateSurfaceWindow( window, mColorDepth );

  // set the context to be current with the new surface
  MakeContextCurrent();

  return contextLost;
}

bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSurface& eglSurface )
{
  bool contextLost = false;

  // display connection has not changed, then we can just create a new surface
  // create the EGL surface
  eglSurface = CreateSurfacePixmap( pixmap, mColorDepth );

  // set the eglSurface to be current
  MakeCurrent( pixmap, eglSurface );

  return contextLost;
}

EGLDisplay EglImplementation::GetDisplay() const
{
  return mEglDisplay;
}

EGLDisplay EglImplementation::GetContext() const
{
  return mEglContext;
}

} // namespace Adaptor

} // namespace Internal

} // namespace Dali

#pragma GCC diagnostic pop
<commit_msg>Fixed crash issues<commit_after>/*
 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include <gl/egl-implementation.h>

// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/dali-vector.h>

// INTERNAL INCLUDES
#include <gl/gl-implementation.h>
#include <gl/egl-debug.h>

// EGL constants use C style casts
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

#define TEST_EGL_ERROR(lastCommand) \
{ \
  EGLint err = eglGetError(); \
  if (err != EGL_SUCCESS) \
  { \
    DALI_LOG_ERROR("EGL error after %s\n", lastCommand); \
    Egl::PrintError(err); \
    DALI_ASSERT_ALWAYS(0 && "EGL error"); \
  } \
}

EglImplementation::EglImplementation( unsigned int multiSamplingLevel )
  : mEglNativeDisplay(0),
    mEglNativeWindow(0),
    mCurrentEglNativePixmap(0),
    mEglDisplay(0),
    mEglConfig(0),
    mEglContext(0),
    mCurrentEglSurface(0),
    mGlesInitialized(false),
    mIsOwnSurface(true),
    mContextCurrent(false),
    mIsWindow(true),
    mColorDepth(COLOR_DEPTH_24),
    mMultiSamplingLevel( multiSamplingLevel )
{
}

EglImplementation::~EglImplementation()
{
  TerminateGles();
}

bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
{
  if ( !mGlesInitialized )
  {
    mEglNativeDisplay = display;

    //@todo see if we can just EGL_DEFAULT_DISPLAY instead
    mEglDisplay = eglGetDisplay(mEglNativeDisplay);
    EGLint error = eglGetError();

    if( mEglDisplay == NULL && error != EGL_SUCCESS )
    {
      throw Dali::DaliException( "", "OpenGL ES is not supported");
    }

    EGLint majorVersion = 0;
    EGLint minorVersion = 0;
    if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
    {
      return false;
    }
    eglBindAPI(EGL_OPENGL_ES_API);

    mContextAttribs.Clear();

#if DALI_GLES_VERSION >= 30

    mContextAttribs.Reserve(5);
    mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
    mContextAttribs.PushBack( DALI_GLES_VERSION / 10 );
    mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
    mContextAttribs.PushBack( DALI_GLES_VERSION % 10 );

#else // DALI_GLES_VERSION >= 30

    mContextAttribs.Reserve(3);
    mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
    mContextAttribs.PushBack( 2 );

#endif // DALI_GLES_VERSION >= 30

    mContextAttribs.PushBack( EGL_NONE );

    mGlesInitialized = true;
    mIsOwnSurface = isOwnSurface;
  }

  return mGlesInitialized;
}

bool EglImplementation::CreateContext()
{
  // make sure a context isn't created twice
  DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );

  mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
  TEST_EGL_ERROR("eglCreateContext render thread");

  DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );

  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
  DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));

  return true;
}

void EglImplementation::DestroyContext()
{
  DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );

  eglDestroyContext( mEglDisplay, mEglContext );
  mEglContext = 0;
}

void EglImplementation::DestroySurface()
{
  if(mIsOwnSurface && mCurrentEglSurface)
  {
    // Make context null to prevent crash in driver side
    MakeContextNull();
    eglDestroySurface( mEglDisplay, mCurrentEglSurface );
    mCurrentEglSurface = 0;
  }
}

void EglImplementation::MakeContextCurrent()
{
  mContextCurrent = true;

  if(mIsOwnSurface)
  {
    eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext );
  }

  EGLint error = eglGetError();

  if ( error != EGL_SUCCESS )
  {
    Egl::PrintError(error);

    DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
  }

  // We want to display this information all the time, so use the LogMessage directly
  Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n"
      "            Vendor:        %s\n"
      "            Version:       %s\n"
      "            Client APIs:   %s\n"
      "            Extensions:    %s\n",
      eglQueryString(mEglDisplay, EGL_VENDOR),
      eglQueryString(mEglDisplay, EGL_VERSION),
      eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
      eglQueryString(mEglDisplay, EGL_EXTENSIONS));
}

void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglSurface )
{
  mCurrentEglNativePixmap = pixmap;
  mCurrentEglSurface = eglSurface;

  if(mIsOwnSurface)
  {
    eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext );
  }

  EGLint error = eglGetError();

  if ( error != EGL_SUCCESS )
  {
    Egl::PrintError(error);

    DALI_ASSERT_ALWAYS(false && "MakeCurrent failed!");
  }
}

void EglImplementation::MakeContextNull()
{
  mContextCurrent = false;
  // clear the current context
  eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
}

void EglImplementation::TerminateGles()
{
  if ( mGlesInitialized )
  {
    // Make context null to prevent crash in driver side
    MakeContextNull();

    if(mIsOwnSurface && mCurrentEglSurface)
    {
      eglDestroySurface(mEglDisplay, mCurrentEglSurface);
    }
    eglDestroyContext(mEglDisplay, mEglContext);

    eglTerminate(mEglDisplay);

    mEglDisplay = NULL;
    mEglConfig  = NULL;
    mEglContext = NULL;
    mCurrentEglSurface = NULL;

    mGlesInitialized = false;
  }
}

bool EglImplementation::IsGlesInitialized() const
{
  return mGlesInitialized;
}

void EglImplementation::SwapBuffers()
{
  eglSwapBuffers( mEglDisplay, mCurrentEglSurface );
}

void EglImplementation::CopyBuffers()
{
  eglCopyBuffers( mEglDisplay, mCurrentEglSurface, mCurrentEglNativePixmap );
}

void EglImplementation::WaitGL()
{
  eglWaitGL();
}

void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
{
  if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
  {
    return;
  }

  mIsWindow = isWindowType;

  EGLint numConfigs;
  Vector<EGLint> configAttribs;
  configAttribs.Reserve(31);

  if(isWindowType)
  {
    configAttribs.PushBack( EGL_SURFACE_TYPE );
    configAttribs.PushBack( EGL_WINDOW_BIT );
  }
  else
  {
    configAttribs.PushBack( EGL_SURFACE_TYPE );
    configAttribs.PushBack( EGL_PIXMAP_BIT );
  }

  configAttribs.PushBack( EGL_RENDERABLE_TYPE );

#if DALI_GLES_VERSION >= 30

#ifdef _ARCH_ARM_
  configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
#else
  // There is a bug in the desktop emulator
  // Requesting for ES3 causes eglCreateContext even though it allows to ask
  // for a configuration that supports GLES 3.0
  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
#endif // _ARCH_ARM_

#else // DALI_GLES_VERSION >= 30

  Integration::Log::LogMessage( Integration::Log::DebugInfo, "Using OpenGL ES 2 \n" );
  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );

#endif //DALI_GLES_VERSION >= 30

#if DALI_GLES_VERSION >= 30
// TODO: enable this flag when it becomes supported
//  configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR );
//  configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR );
#endif //DALI_GLES_VERSION >= 30

  configAttribs.PushBack( EGL_RED_SIZE );
  configAttribs.PushBack( 8 );
  configAttribs.PushBack( EGL_GREEN_SIZE );
  configAttribs.PushBack( 8 );
  configAttribs.PushBack( EGL_BLUE_SIZE );
  configAttribs.PushBack( 8 );

  configAttribs.PushBack( EGL_ALPHA_SIZE );
#ifdef _ARCH_ARM_
  configAttribs.PushBack( (depth == COLOR_DEPTH_32) ? 8 : 0 );
#else
  // There is a bug in the desktop emulator
  // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing
  configAttribs.PushBack( 0 );
#endif // _ARCH_ARM_

  configAttribs.PushBack( EGL_DEPTH_SIZE );
  configAttribs.PushBack( 24 );
  configAttribs.PushBack( EGL_STENCIL_SIZE );
  configAttribs.PushBack( 8 );
#ifndef DALI_PROFILE_UBUNTU
  configAttribs.PushBack( EGL_SAMPLES );
  configAttribs.PushBack( mMultiSamplingLevel );
  configAttribs.PushBack( EGL_SAMPLE_BUFFERS );
  configAttribs.PushBack( 1 );
#endif // DALI_PROFILE_UBUNTU
  configAttribs.PushBack( EGL_NONE );

  if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
  {
    EGLint error = eglGetError();
    switch (error)
    {
      case EGL_BAD_DISPLAY:
      {
        DALI_LOG_ERROR("Display is not an EGL display connection\n");
        break;
      }
      case EGL_BAD_ATTRIBUTE:
      {
        DALI_LOG_ERROR("The parameter configAttribs contains an invalid frame buffer configuration attribute or an attribute value that is unrecognized or out of range\n");
        break;
      }
      case EGL_NOT_INITIALIZED:
      {
        DALI_LOG_ERROR("Display has not been initialized\n");
        break;
      }
      case EGL_BAD_PARAMETER:
      {
        DALI_LOG_ERROR("The parameter numConfig is NULL\n");
        break;
      }
      default:
      {
        DALI_LOG_ERROR("Unknown error.\n");
      }
    }
    DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
  }

  if ( numConfigs != 1 )
  {
    DALI_LOG_ERROR("No configurations found.\n");

    TEST_EGL_ERROR("eglChooseConfig");
  }
}

void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
{
  DALI_ASSERT_ALWAYS( ( mCurrentEglSurface == 0 ) && "EGL surface already exists" );

  mEglNativeWindow = window;
  mColorDepth = depth;
  mIsWindow = true;

  // egl choose config
  ChooseConfig(mIsWindow, mColorDepth);

  mCurrentEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, mEglNativeWindow, NULL );
  TEST_EGL_ERROR("eglCreateWindowSurface");

  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" );
}

EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
{
  mCurrentEglNativePixmap = pixmap;
  mColorDepth = depth;
  mIsWindow = false;

  // egl choose config
  ChooseConfig(mIsWindow, mColorDepth);

  mCurrentEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL );
  TEST_EGL_ERROR("eglCreatePixmapSurface");

  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create pixmap surface failed" );

  return mCurrentEglSurface;
}

bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
{
  bool contextLost = false;

  // display connection has not changed, then we can just create a new surface
  //  the surface is bound to the context, so set the context to null
  MakeContextNull();

  // destroy the surface
  DestroySurface();

  // create the EGL surface
  CreateSurfaceWindow( window, mColorDepth );

  // set the context to be current with the new surface
  MakeContextCurrent();

  return contextLost;
}

bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSurface& eglSurface )
{
  bool contextLost = false;

  // display connection has not changed, then we can just create a new surface
  // create the EGL surface
  eglSurface = CreateSurfacePixmap( pixmap, mColorDepth );

  // set the eglSurface to be current
  MakeCurrent( pixmap, eglSurface );

  return contextLost;
}

EGLDisplay EglImplementation::GetDisplay() const
{
  return mEglDisplay;
}

EGLDisplay EglImplementation::GetContext() const
{
  return mEglContext;
}

} // namespace Adaptor

} // namespace Internal

} // namespace Dali

#pragma GCC diagnostic pop
<|endoftext|>


<commit_before>#include <DpaHandler.h>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <thread>
#include "DpaLibraryDemo.h"

/********************************************************************************
 * Select type of demo.
********************************************************************************/
//#define SPI_DEMO
#define CDC_DEMO

DpaLibraryDemo* demo_;
//CDCImpl* cdc_parser_;
//CdcDpaInterface* communication_interface_;

#ifdef CDC_DEMO

#include "CdcDpaInterface.h"

int CdcDemoMain();

#define DemoMain()    CdcDemoMain()

#endif /* CDC_DEMO */

#ifdef SPI_DEMO

#include <SpiDpaInterface.h>
#include <sysfs_gpio.h>

int SpiDpaDemoMain();

#define DemoMain()	SpiDpaDemoMain()

#endif /* SPI_DEMO */

int main() {
  std::cout << "Start demo\n";
  DemoMain();
  return 0;
}

/*****************************************************************************
 * CDC DEMO
*****************************************************************************/
#ifdef CDC_DEMO

int CdcDemoMain() {
  CdcDpaInterface* cdcDpaInterface = new CdcDpaInterface();

  try {
	cdcDpaInterface->Open("/dev/ttyACM0");
  }
  catch (...) {
	goto Error_End;
  }

  demo_ = new DpaLibraryDemo(cdcDpaInterface);

  demo_->Start();

  std::cout << "That's all for today...";

  Error_End:
  delete cdcDpaInterface;
  delete demo_;
}

#endif

/*****************************************************************************
 * SPI DEMO
*****************************************************************************/
#ifdef SPI_DEMO

/** Reset GPIO. */
#define RESET_GPIO (23)
/** SPI CE GPIO. */
#define RPIIO_PIN_CE0 (8)

int SpiDpaDemoMain() {
  SpiDpaInterface dpaInterface;

  //We prepared demo for Rasperry Pi3
  //enable CE0 for TR communication
  auto initResult = gpio_setup(RPIIO_PIN_CE0, GPIO_DIRECTION_OUT, 0);
  if (initResult < 0) {
	return -1;
  }

  // enable PWR for TR communication
  initResult = gpio_setup(RESET_GPIO, GPIO_DIRECTION_OUT, 1);
  if (initResult < 0) {
	gpio_cleanup(RPIIO_PIN_CE0);
	return -1;
  }

  try {
	dpaInterface.Open("/dev/spidev0.0");
	demo_ = new DpaLibraryDemo(&dpaInterface);
	demo_->Start();
  } catch (...) {
	// clean the mess in all cases
  }

  dpaInterface.Close();
  delete demo_;

  // destroy used rpi_io library
  gpio_cleanup(RESET_GPIO);
  gpio_cleanup(RPIIO_PIN_CE0);

}
#endif

DpaLibraryDemo::DpaLibraryDemo(DpaInterface* communication_interface)
	: dpa_handler_(nullptr) {
  dpaInterface_ = communication_interface;
}

DpaLibraryDemo::~DpaLibraryDemo() {
  delete dpa_handler_;
}

void DpaLibraryDemo::Start() {
  try {
	dpa_handler_ = new DpaHandler(dpaInterface_);
	dpa_handler_->RegisterAsyncMessageHandler(std::bind(&DpaLibraryDemo::UnexpectedMessage,
														this,
														std::placeholders::_1));
  }
  catch (std::invalid_argument& ae) {
	std::cout << "There was an error during DPA handler creation.\n";
  }

  dpa_handler_->Timeout(10);    // Default timeout is infinite

  int16_t i = 100;
  //wait for a while, there could be some unread message in CDC
  std::this_thread::sleep_for(std::chrono::seconds(1));

  while (i--) {
	PulseLed(0x00, kLedRed);    // Pulse with red led on coordinator
	PulseLed(0x00, kLedGreen);    // Pulse with green led on coordinator
	PulseLed(0x03, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0x03, kLedGreen);    // Pulse with green led on node with address 3
	PulseLed(0xFF, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0xFF, kLedGreen);    // Pulse with green led on node with address 3
	ReadTemperature(0x03);        // Get temperature from node with address 3
  }
}

void DpaLibraryDemo::PulseLed(uint16_t address, LedColor color) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  if (color == kLedRed)
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDR;
  else
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDG;

  packet.DpaRequestPacket_t.PCMD = CMD_LED_PULSE;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);
}

void DpaLibraryDemo::ExecuteCommand(DpaMessage& message) {
  static uint16_t sent_messages = 0;
  static uint16_t timeouts = 0;
  try {
	dpa_handler_->SendDpaMessage(message);
  }
  catch (std::logic_error& le) {
	std::cout << "Send error occured: " << le.what() << "\n";
	return;
  }

  ++sent_messages;

  while (dpa_handler_->IsDpaMessageInProgress()) {
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kTimeout) {
	++timeouts;
	std::cout << message.NodeAddress()
			  << " - Timeout ..."
			  << sent_messages
			  << ':'
			  << timeouts
			  << '\n';
  }

}
void DpaLibraryDemo::UnexpectedMessage(const DpaMessage& message) {
  std::cout << "Unexpected message received.\n";
}

void DpaLibraryDemo::ReadTemperature(uint16_t address) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  packet.DpaRequestPacket_t.PNUM = PNUM_THERMOMETER;

  packet.DpaRequestPacket_t.PCMD = CMD_THERMOMETER_READ;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kProcessed) {
	int16_t temperature =
		dpa_handler_->CurrentRequest().ResponseMessage().DpaPacket().DpaResponsePacket_t.DpaMessage.PerThermometerRead_Response.IntegerValue;
	std::cout << "Temperature: "
			  << std::dec << temperature << " °C\n";
  }
}
<commit_msg>Demo for CDC interface.<commit_after>#include <DpaHandler.h>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <thread>
#include "DpaLibraryDemo.h"

/********************************************************************************
 * Select type of demo.
********************************************************************************/
//#define SPI_DEMO
#define CDC_DEMO

DpaLibraryDemo* demo_;

#ifdef CDC_DEMO

#include "CdcDpaInterface.h"

int CdcDemoMain();

#define DemoMain()    CdcDemoMain()

#endif /* CDC_DEMO */

#ifdef SPI_DEMO

#include <SpiDpaInterface.h>
#include <sysfs_gpio.h>

int SpiDpaDemoMain();

#define DemoMain()	SpiDpaDemoMain()

#endif /* SPI_DEMO */

int main() {
  std::cout << "Start demo\n";
  DemoMain();
  return 0;
}

/*****************************************************************************
 * CDC DEMO
*****************************************************************************/
#ifdef CDC_DEMO

int CdcDemoMain() {
  CdcDpaInterface cdcDpaInterface;

  try {
	cdcDpaInterface.Open("/dev/ttyACM0");
  }
  catch (...) {
	return -1;
  }

  demo_ = new DpaLibraryDemo(&cdcDpaInterface);

  demo_->Start();

  std::cout << "That's all for today...";

  return 0;
}

#endif

/*****************************************************************************
 * SPI DEMO
*****************************************************************************/
#ifdef SPI_DEMO

/** Reset GPIO. */
#define RESET_GPIO (23)
/** SPI CE GPIO. */
#define RPIIO_PIN_CE0 (8)

int SpiDpaDemoMain() {
  SpiDpaInterface dpaInterface;

  //We prepared demo for Rasperry Pi3
  //enable CE0 for TR communication
  auto initResult = gpio_setup(RPIIO_PIN_CE0, GPIO_DIRECTION_OUT, 0);
  if (initResult < 0) {
	return -1;
  }

  // enable PWR for TR communication
  initResult = gpio_setup(RESET_GPIO, GPIO_DIRECTION_OUT, 1);
  if (initResult < 0) {
	gpio_cleanup(RPIIO_PIN_CE0);
	return -1;
  }

  try {
	dpaInterface.Open("/dev/spidev0.0");
	demo_ = new DpaLibraryDemo(&dpaInterface);
	demo_->Start();
  } catch (...) {
	// clean the mess in all cases
  }

  dpaInterface.Close();
  delete demo_;

  // destroy used rpi_io library
  gpio_cleanup(RESET_GPIO);
  gpio_cleanup(RPIIO_PIN_CE0);

}
#endif

DpaLibraryDemo::DpaLibraryDemo(DpaInterface* communication_interface)
	: dpa_handler_(nullptr) {
  dpaInterface_ = communication_interface;
}

DpaLibraryDemo::~DpaLibraryDemo() {
  delete dpa_handler_;
}

void DpaLibraryDemo::Start() {
  try {
	dpa_handler_ = new DpaHandler(dpaInterface_);
	dpa_handler_->RegisterAsyncMessageHandler(std::bind(&DpaLibraryDemo::UnexpectedMessage,
														this,
														std::placeholders::_1));
  }
  catch (std::invalid_argument& ae) {
	std::cout << "There was an error during DPA handler creation.\n";
  }

  dpa_handler_->Timeout(10);    // Default timeout is infinite

  int16_t i = 100;
  //wait for a while, there could be some unread message in CDC
  std::this_thread::sleep_for(std::chrono::seconds(1));

  while (i--) {
	PulseLed(0x00, kLedRed);    // Pulse with red led on coordinator
	PulseLed(0x00, kLedGreen);    // Pulse with green led on coordinator
	PulseLed(0x03, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0x03, kLedGreen);    // Pulse with green led on node with address 3
	PulseLed(0xFF, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0xFF, kLedGreen);    // Pulse with green led on node with address 3
	ReadTemperature(0x03);        // Get temperature from node with address 3
  }
}

void DpaLibraryDemo::PulseLed(uint16_t address, LedColor color) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  if (color == kLedRed)
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDR;
  else
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDG;

  packet.DpaRequestPacket_t.PCMD = CMD_LED_PULSE;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);
}

void DpaLibraryDemo::ExecuteCommand(DpaMessage& message) {
  static uint16_t sent_messages = 0;
  static uint16_t timeouts = 0;
  try {
	dpa_handler_->SendDpaMessage(message);
  }
  catch (std::logic_error& le) {
	std::cout << "Send error occured: " << le.what() << "\n";
	return;
  }

  ++sent_messages;

  while (dpa_handler_->IsDpaMessageInProgress()) {
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kTimeout) {
	++timeouts;
	std::cout << message.NodeAddress()
			  << " - Timeout ..."
			  << sent_messages
			  << ':'
			  << timeouts
			  << '\n';
  }

}
void DpaLibraryDemo::UnexpectedMessage(const DpaMessage& message) {
  std::cout << "Unexpected message received.\n";
}

void DpaLibraryDemo::ReadTemperature(uint16_t address) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  packet.DpaRequestPacket_t.PNUM = PNUM_THERMOMETER;

  packet.DpaRequestPacket_t.PCMD = CMD_THERMOMETER_READ;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kProcessed) {
	int16_t temperature =
		dpa_handler_->CurrentRequest().ResponseMessage().DpaPacket().DpaResponsePacket_t.DpaMessage.PerThermometerRead_Response.IntegerValue;
	std::cout << "Temperature: "
			  << std::dec << temperature << " °C\n";
  }
}
<|endoftext|>