<commit_before>#include <nex/math/gjk.h>

namespace nx
{

GJK::GJK() :
    mSimplexBits(0),
    mMaxLengthSq(0),
    mClosestPoint(vec3f())
{
    for (int i = 0; i < 4; i++) {
        mYLengthSq[i] = 0;
        for (int j = 0; j < 4; j++) {
            mEdgeLengthSq[i][j] = 0;
        }
    }
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 4; j++) {
            mDet[i][j] = 0;
        }
    }
}

void GJK::reset()
{
    mSimplexBits = 0;
    mMaxLengthSq = 0.0f;
}

bool GJK::addSupportPoint(const vec3f& newPoint)
{
    int index1 = (mBitsToIndices[mSimplexBits ^ 15] & 7) - 1;

    mY[index1] = newPoint;
    mYLengthSq[index1] = newPoint.lengthSquared();

    int num = mBitsToIndices[mSimplexBits];
    while (num != 0)
    {
        int index2 = (num & 7) - 1;
        vec3f vector3 = mY[index2] - newPoint;
        mEdges[index2][index1] = vector3;
        mEdges[index1][index2] = -vector3;
        mEdgeLengthSq[index1][index2] = mEdgeLengthSq[index2][index1] = vector3.lengthSquared();
        num >>= 3;
    }

    updateDeterminant(index1);

    return updateSimplex(index1);
}

void GJK::updateDeterminant(int xmIdx)
{
    int index1 = 1 << xmIdx;

    mDet[index1][xmIdx] = 1.0f;

    int num1 = mBitsToIndices[mSimplexBits];
    int num2 = num1;
    int num3 = 0;

    while (num2 != 0)
    {
        int index2 = (num2 & 7) - 1;
        int num4 = 1 << index2;
        int index3 = num4 | index1;

        mDet[index3][index2] = vec3f::dot(mEdges[xmIdx][index2], mY[xmIdx]);
        mDet[index3][xmIdx] = vec3f::dot(mEdges[index2][xmIdx], mY[index2]);

        int num5 = num1;
        for (int index4 = 0; index4 < num3; ++index4)
        {
            int index5 = (num5 & 7) - 1;
            int num6 = 1 << index5;
            int index6 = index3 | num6;
            int index7 =  mEdgeLengthSq[index2][index5] <  mEdgeLengthSq[xmIdx][index5] ? index2 : xmIdx;
            mDet[index6][index5] =  ( mDet[index3][index2] *  vec3f::dot(mEdges[index7][index5], mY[index2]) +  mDet[index3][xmIdx] *  vec3f::dot(mEdges[index7][index5], mY[xmIdx]));
            int index8 =  mEdgeLengthSq[index5][index2] <  mEdgeLengthSq[xmIdx][index2] ? index5 : xmIdx;
            mDet[index6][index2] =  ( mDet[num6 | index1][index5] *  vec3f::dot(mEdges[index8][index2], mY[index5]) +  mDet[num6 | index1][xmIdx] *  vec3f::dot(mEdges[index8][index2], mY[xmIdx]));
            int index9 =  mEdgeLengthSq[index2][xmIdx] <  mEdgeLengthSq[index5][xmIdx] ? index2 : index5;
            mDet[index6][xmIdx] =  ( mDet[num4 | num6][index5] *  vec3f::dot(mEdges[index9][xmIdx], mY[index5]) +  mDet[num4 | num6][index2] *  vec3f::dot(mEdges[index9][xmIdx], mY[index2]));
            num5 >>= 3;
        }
        num2 >>= 3;
        ++num3;
    }
    if ((mSimplexBits | index1) != 15)
        return;
    int index10 =  mEdgeLengthSq[1][0] <  mEdgeLengthSq[2][0] ? ( mEdgeLengthSq[1][0] <  mEdgeLengthSq[3][0] ? 1 : 3) : ( mEdgeLengthSq[2][0] <  mEdgeLengthSq[3][0] ? 2 : 3);
    mDet[15][0] =  ( mDet[14][1] *  vec3f::dot(mEdges[index10][0], mY[1]) +  mDet[14][2] *  vec3f::dot(mEdges[index10][0], mY[2]) +  mDet[14][3] *  vec3f::dot(mEdges[index10][0], mY[3]));
    int index11 =  mEdgeLengthSq[0][1] <  mEdgeLengthSq[2][1] ? ( mEdgeLengthSq[0][1] <  mEdgeLengthSq[3][1] ? 0 : 3) : ( mEdgeLengthSq[2][1] <  mEdgeLengthSq[3][1] ? 2 : 3);
    mDet[15][1] =  ( mDet[13][0] *  vec3f::dot(mEdges[index11][1], mY[0]) +  mDet[13][2] *  vec3f::dot(mEdges[index11][1], mY[2]) +  mDet[13][3] *  vec3f::dot(mEdges[index11][1], mY[3]));
    int index12 =  mEdgeLengthSq[0][2] <  mEdgeLengthSq[1][2] ? ( mEdgeLengthSq[0][2] <  mEdgeLengthSq[3][2] ? 0 : 3) : ( mEdgeLengthSq[1][2] <  mEdgeLengthSq[3][2] ? 1 : 3);
    mDet[15][2] =  ( mDet[11][0] *  vec3f::dot(mEdges[index12][2], mY[0]) +  mDet[11][1] *  vec3f::dot(mEdges[index12][2], mY[1]) +  mDet[11][3] *  vec3f::dot(mEdges[index12][2], mY[3]));
    int index13 =  mEdgeLengthSq[0][3] <  mEdgeLengthSq[1][3] ? ( mEdgeLengthSq[0][3] <  mEdgeLengthSq[2][3] ? 0 : 2) : ( mEdgeLengthSq[1][3] <  mEdgeLengthSq[2][3] ? 1 : 2);
    mDet[15][3] =  ( mDet[7][0] *  vec3f::dot(mEdges[index13][3], mY[0]) +  mDet[7][1] *  vec3f::dot(mEdges[index13][3], mY[1]) +  mDet[7][2] *  vec3f::dot(mEdges[index13][3], mY[2]));
}

bool GJK::updateSimplex(int newIndex)
{
    int yBits = mSimplexBits | 1 << newIndex;
    int xBits = 1 << newIndex;
    for (int index = mSimplexBits; index != 0; --index)
    {
        if ((index & yBits) == index && satisfiesRule(index | xBits, yBits))
        {
            mSimplexBits = index | xBits;
            mClosestPoint = computeClosestPoint();
            return true;
        }
    }

    bool flag = false;
    if (satisfiesRule(xBits, yBits))
    {
        mSimplexBits = xBits;
        mClosestPoint = mY[newIndex];
        mMaxLengthSq = mYLengthSq[newIndex];
        flag = true;
    }

    return flag;
}

vec3f GJK::computeClosestPoint()
{
    float num1 = 0.0f;

    vec3f zero(0.0f);

    mMaxLengthSq = 0.0f;
    int num2 = mBitsToIndices[mSimplexBits];
    while (num2 != 0)
    {
        int index = (num2 & 7) - 1;
        float num3 = this.det[this.simplexBits][index];
        num1 += num3;
        zero += this.y[index] * num3;
        mMaxLengthSq = MathHelper.Max(this.maxLengthSq, this.yLengthSq[index]);
        num2 >>= 3;
    }
    return zero / num1;
}

bool GJK::satisfiesRule(int xBits, int yBits)
{

}

} //namespace nx
<commit_msg>Implemented the gjk algorithm.<commit_after>#include <nex/math/gjk.h>
#include <nex/math/mathhelper.h>

namespace nx
{

GJK::GJK() :
    mSimplexBits(0),
    mMaxLengthSq(0),
    mClosestPoint(vec3f())
{
    for (int i = 0; i < 4; i++) {
        mYLengthSq[i] = 0;
        for (int j = 0; j < 4; j++) {
            mEdgeLengthSq[i][j] = 0;
        }
    }
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 4; j++) {
            mDet[i][j] = 0;
        }
    }
}

void GJK::reset()
{
    mSimplexBits = 0;
    mMaxLengthSq = 0.0f;
}

bool GJK::addSupportPoint(const vec3f& newPoint)
{
    int index1 = (mBitsToIndices[mSimplexBits ^ 15] & 7) - 1;

    mY[index1] = newPoint;
    mYLengthSq[index1] = newPoint.lengthSquared();

    int num = mBitsToIndices[mSimplexBits];
    while (num != 0)
    {
        int index2 = (num & 7) - 1;
        vec3f vector3 = mY[index2] - newPoint;
        mEdges[index2][index1] = vector3;
        mEdges[index1][index2] = -vector3;
        mEdgeLengthSq[index1][index2] = mEdgeLengthSq[index2][index1] = vector3.lengthSquared();
        num >>= 3;
    }

    updateDeterminant(index1);

    return updateSimplex(index1);
}

void GJK::updateDeterminant(int xmIdx)
{
    int index1 = 1 << xmIdx;

    mDet[index1][xmIdx] = 1.0f;

    int num1 = mBitsToIndices[mSimplexBits];
    int num2 = num1;
    int num3 = 0;

    while (num2 != 0)
    {
        int index2 = (num2 & 7) - 1;
        int num4 = 1 << index2;
        int index3 = num4 | index1;

        mDet[index3][index2] = vec3f::dot(mEdges[xmIdx][index2], mY[xmIdx]);
        mDet[index3][xmIdx] = vec3f::dot(mEdges[index2][xmIdx], mY[index2]);

        int num5 = num1;
        for (int index4 = 0; index4 < num3; ++index4)
        {
            int index5 = (num5 & 7) - 1;
            int num6 = 1 << index5;
            int index6 = index3 | num6;
            int index7 = mEdgeLengthSq[index2][index5] < mEdgeLengthSq[xmIdx][index5] ? index2 : xmIdx;

            mDet[index6][index5] = (mDet[index3][index2] * vec3f::dot(mEdges[index7][index5], mY[index2]) + mDet[index3][xmIdx] * vec3f::dot(mEdges[index7][index5], mY[xmIdx]));

            int index8 = mEdgeLengthSq[index5][index2] < mEdgeLengthSq[xmIdx][index2] ? index5 : xmIdx;

            mDet[index6][index2] = (mDet[num6 | index1][index5] * vec3f::dot(mEdges[index8][index2], mY[index5]) + mDet[num6 | index1][xmIdx] * vec3f::dot(mEdges[index8][index2], mY[xmIdx]));

            int index9 = mEdgeLengthSq[index2][xmIdx] < mEdgeLengthSq[index5][xmIdx] ? index2 : index5;

            mDet[index6][xmIdx] = (mDet[num4 | num6][index5] * vec3f::dot(mEdges[index9][xmIdx], mY[index5]) + mDet[num4 | num6][index2] * vec3f::dot(mEdges[index9][xmIdx], mY[index2]));
            num5 >>= 3;
        }
        num2 >>= 3;
        ++num3;
    }
    if ((mSimplexBits | index1) != 15)
        return;
    int index10 = mEdgeLengthSq[1][0] < mEdgeLengthSq[2][0] ? (mEdgeLengthSq[1][0] < mEdgeLengthSq[3][0] ? 1 : 3) : (mEdgeLengthSq[2][0] < mEdgeLengthSq[3][0] ? 2 : 3);

    mDet[15][0] = (mDet[14][1] * vec3f::dot(mEdges[index10][0], mY[1]) + mDet[14][2] * vec3f::dot(mEdges[index10][0], mY[2]) + mDet[14][3] * vec3f::dot(mEdges[index10][0], mY[3]));

    int index11 = mEdgeLengthSq[0][1] < mEdgeLengthSq[2][1] ? (mEdgeLengthSq[0][1] < mEdgeLengthSq[3][1] ? 0 : 3) : (mEdgeLengthSq[2][1] < mEdgeLengthSq[3][1] ? 2 : 3);

    mDet[15][1] = (mDet[13][0] * vec3f::dot(mEdges[index11][1], mY[0]) + mDet[13][2] * vec3f::dot(mEdges[index11][1], mY[2]) + mDet[13][3] * vec3f::dot(mEdges[index11][1], mY[3]));

    int index12 = mEdgeLengthSq[0][2] < mEdgeLengthSq[1][2] ? (mEdgeLengthSq[0][2] < mEdgeLengthSq[3][2] ? 0 : 3) : (mEdgeLengthSq[1][2] < mEdgeLengthSq[3][2] ? 1 : 3);

    mDet[15][2] = (mDet[11][0] * vec3f::dot(mEdges[index12][2], mY[0]) + mDet[11][1] * vec3f::dot(mEdges[index12][2], mY[1]) + mDet[11][3] * vec3f::dot(mEdges[index12][2], mY[3]));

    int index13 = mEdgeLengthSq[0][3] < mEdgeLengthSq[1][3] ? (mEdgeLengthSq[0][3] < mEdgeLengthSq[2][3] ? 0 : 2) : (mEdgeLengthSq[1][3] < mEdgeLengthSq[2][3] ? 1 : 2);
    mDet[15][3] = (mDet[7][0] * vec3f::dot(mEdges[index13][3], mY[0]) + mDet[7][1] * vec3f::dot(mEdges[index13][3], mY[1]) + mDet[7][2] * vec3f::dot(mEdges[index13][3], mY[2]));
}

bool GJK::updateSimplex(int newIndex)
{
    int yBits = mSimplexBits | 1 << newIndex;
    int xBits = 1 << newIndex;
    for (int index = mSimplexBits; index != 0; --index)
    {
        if ((index & yBits) == index && satisfiesRule(index | xBits, yBits))
        {
            mSimplexBits = index | xBits;
            mClosestPoint = computeClosestPoint();
            return true;
        }
    }

    bool flag = false;
    if (satisfiesRule(xBits, yBits))
    {
        mSimplexBits = xBits;
        mClosestPoint = mY[newIndex];
        mMaxLengthSq = mYLengthSq[newIndex];
        flag = true;
    }

    return flag;
}

vec3f GJK::computeClosestPoint()
{
    float num1 = 0.0f;

    vec3f zero(0.0f);

    mMaxLengthSq = 0.0f;
    int num2 = mBitsToIndices[mSimplexBits];
    while (num2 != 0)
    {
        int index = (num2 & 7) - 1;
        float num3 = mDet[mSimplexBits][index];
        num1 += num3;
        zero += mY[index] * num3;
        mMaxLengthSq = max(mMaxLengthSq, mYLengthSq[index]);
        num2 >>= 3;
    }
    return zero / num1;
}

bool GJK::satisfiesRule(int xBits, int yBits)
{
    bool flag = true;

    int num1 = mBitsToIndices[yBits];
    while (num1 != 0)
    {
        int index = (num1 & 7) - 1;
        int num2 = 1 << index;
        if ((num2 & xBits) != 0)
        {
            if (mDet[xBits][index] <= 0.0)
            {
                flag = false;
                break;
            }
        }
        else if (mDet[xBits | num2][index] > 0.0)
        {
            flag = false;
            break;
        }
        num1 >>= 3;
    }
    return flag;
}

} //namespace nx
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "common/config.h"
#include "common/ceph_argparse.h"
#include "global/global_init.h"
#include "mon/MonMap.h"

void usage()
{
  cout << " usage: [--print] [--create [--clobber]] [--add name 1.2.3.4:567] [--rm name] <mapfilename>" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  DEFINE_CONF_VARS(usage);

  const char *me = argv[0];

  const char *fn = 0;
  bool print = false;
  bool create = false;
  bool clobber = false;
  bool modified = false;
  map<string,entity_addr_t> add;
  list<string> rm;

  global_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
	      CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
  common_init_finish(g_ceph_context);
  FOR_EACH_ARG(args) {
    if (CEPH_ARGPARSE_EQ("help", '\0')) {
      usage();
    } else if (CEPH_ARGPARSE_EQ("print", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&print, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("create", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&create, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("clobber", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&clobber, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("add", '\0')) {
      if (++i >= args.size())
	usage();
      string name = args[i];
      if (++i >= args.size())
	usage();
      entity_addr_t addr;
      if (!addr.parse(args[i])) {
	cerr << me << ": invalid ip:port '" << args[i] << "'" << std::endl;
	return -1;
      }
      if (addr.get_port() == 0)
	addr.set_port(CEPH_MON_PORT);
      add[name] = addr;
      modified = true;
    } else if (CEPH_ARGPARSE_EQ("rm", '\0')) {
      if (++i >= args.size())
	usage();
      string name = args[i];
      rm.push_back(name);
      modified = true;
    } else if (!fn)
      fn = args[i];
    else {
      cout << "invalid argument: '" << args[i] << "'" << std::endl;
      usage();
    }
  }
  if (!fn)
    usage();

  MonMap monmap(ceph_clock_now(g_ceph_context));

  cout << me << ": monmap file " << fn << std::endl;

  int r = 0;
  if (!(create && clobber)) {
    try {
      r = monmap.read(fn);
    } catch (...) {
      cerr << me << ": unable to read monmap file" << std::endl;
      return -1;
    }
  }

  char buf[80];
  if (!create && r < 0) {
    cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
    return -1;
  }
  else if (create && !clobber && r == 0) {
    cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
    return -1;
  }

  if (create) {
    srand(getpid() + time(0));
    monmap.generate_fsid();
    cout << me << ": generated fsid " << monmap.fsid << std::endl;
    modified++;
  }

  for (map<string,entity_addr_t>::iterator p = add.begin(); p != add.end(); p++) {
    if (monmap.contains(p->first)) {
      cerr << me << ": map already contains mon." << p->first << std::endl;
      usage();
    }
    if (monmap.contains(p->second)) {
      cerr << me << ": map already contains " << p->second << std::endl;
      usage();
    }
    monmap.add(p->first, p->second);
  }
  for (list<string>::iterator p = rm.begin(); p != rm.end(); p++) {
    cout << me << ": removing " << *p << std::endl;
    if (!monmap.contains(*p)) {
      cerr << me << ": map does not contain " << *p << std::endl;
      usage();
    }
    monmap.remove(*p);
  }

  if (!print && !modified)
    usage();

  if (modified)
    monmap.epoch++;

  if (print)
    monmap.print(cout);

  if (modified) {
    // write it out
    cout << me << ": writing epoch " << monmap.epoch
	 << " to " << fn
	 << " (" << monmap.size() << " monitors)"
	 << std::endl;
    int r = monmap.write(fn);
    if (r < 0) {
      cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
      return 1;
    }
  }

  return 0;
}
<commit_msg>monmaptool: don't inc bool<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "common/config.h"
#include "common/ceph_argparse.h"
#include "global/global_init.h"
#include "mon/MonMap.h"

void usage()
{
  cout << " usage: [--print] [--create [--clobber]] [--add name 1.2.3.4:567] [--rm name] <mapfilename>" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  DEFINE_CONF_VARS(usage);

  const char *me = argv[0];

  const char *fn = 0;
  bool print = false;
  bool create = false;
  bool clobber = false;
  bool modified = false;
  map<string,entity_addr_t> add;
  list<string> rm;

  global_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
	      CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
  common_init_finish(g_ceph_context);
  FOR_EACH_ARG(args) {
    if (CEPH_ARGPARSE_EQ("help", '\0')) {
      usage();
    } else if (CEPH_ARGPARSE_EQ("print", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&print, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("create", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&create, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("clobber", '\0')) {
      CEPH_ARGPARSE_SET_ARG_VAL(&clobber, OPT_BOOL);
    } else if (CEPH_ARGPARSE_EQ("add", '\0')) {
      if (++i >= args.size())
	usage();
      string name = args[i];
      if (++i >= args.size())
	usage();
      entity_addr_t addr;
      if (!addr.parse(args[i])) {
	cerr << me << ": invalid ip:port '" << args[i] << "'" << std::endl;
	return -1;
      }
      if (addr.get_port() == 0)
	addr.set_port(CEPH_MON_PORT);
      add[name] = addr;
      modified = true;
    } else if (CEPH_ARGPARSE_EQ("rm", '\0')) {
      if (++i >= args.size())
	usage();
      string name = args[i];
      rm.push_back(name);
      modified = true;
    } else if (!fn)
      fn = args[i];
    else {
      cout << "invalid argument: '" << args[i] << "'" << std::endl;
      usage();
    }
  }
  if (!fn)
    usage();

  MonMap monmap(ceph_clock_now(g_ceph_context));

  cout << me << ": monmap file " << fn << std::endl;

  int r = 0;
  if (!(create && clobber)) {
    try {
      r = monmap.read(fn);
    } catch (...) {
      cerr << me << ": unable to read monmap file" << std::endl;
      return -1;
    }
  }

  char buf[80];
  if (!create && r < 0) {
    cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
    return -1;
  }
  else if (create && !clobber && r == 0) {
    cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
    return -1;
  }

  if (create) {
    srand(getpid() + time(0));
    monmap.generate_fsid();
    cout << me << ": generated fsid " << monmap.fsid << std::endl;
    modified = true;
  }

  for (map<string,entity_addr_t>::iterator p = add.begin(); p != add.end(); p++) {
    if (monmap.contains(p->first)) {
      cerr << me << ": map already contains mon." << p->first << std::endl;
      usage();
    }
    if (monmap.contains(p->second)) {
      cerr << me << ": map already contains " << p->second << std::endl;
      usage();
    }
    monmap.add(p->first, p->second);
  }
  for (list<string>::iterator p = rm.begin(); p != rm.end(); p++) {
    cout << me << ": removing " << *p << std::endl;
    if (!monmap.contains(*p)) {
      cerr << me << ": map does not contain " << *p << std::endl;
      usage();
    }
    monmap.remove(*p);
  }

  if (!print && !modified)
    usage();

  if (modified)
    monmap.epoch++;

  if (print)
    monmap.print(cout);

  if (modified) {
    // write it out
    cout << me << ": writing epoch " << monmap.epoch
	 << " to " << fn
	 << " (" << monmap.size() << " monitors)"
	 << std::endl;
    int r = monmap.write(fn);
    if (r < 0) {
      cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl;
      return 1;
    }
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Temp & partially revert of cl https://codereview.chromium.org/1109333002, which caused regression crbug.com/493292.<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"
#include "otbImage.h"
#include "otbFunctionToImageFilter.h"
#include "otbSarParametricMapFunction.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "itkPointSet.h"

int otbSarParametricMapFunctionToImageFilter(int argc, char * argv[])
{
  const unsigned int Dimension = 2;
  typedef float                                                                     PixelType;
  typedef otb::Image<PixelType, Dimension>                                          InputImageType;
  typedef InputImageType::IndexType                                                 IndexType;
  typedef otb::Image<PixelType, Dimension>                                          OutputImageType;
  typedef otb::ImageFileReader<InputImageType>                                      ReaderType;
  typedef otb::StreamingImageFileWriter<OutputImageType>                            WriterType;
  typedef otb::SarParametricMapFunction<InputImageType>                             FunctionType;
  typedef otb::FunctionToImageFilter<InputImageType, OutputImageType, FunctionType> FilterType;
  typedef FunctionType::PointSetType                                                PointSetType;

  // Instantiating object
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();
  PointSetType::Pointer points = PointSetType::New();

  reader->SetFileName(argv[1]);
  writer->SetFileName(argv[2]);
  filter->SetInput(reader->GetOutput());

  FunctionType::Pointer function = FunctionType::New();
  function->SetInputImage(reader->GetOutput());

  /** Test on some indexes and some physical coordinates*/
  InputImageType::SizeType size;
  FunctionType::PointType  p0;
  IndexType                index;
  PixelType                value;

  p0[0] = static_cast<unsigned int>(0);
  p0[1] = static_cast<unsigned int>(0);
  value = 10.0;
  points->SetPoint(0, p0);
  points->SetPointData(0, value);

  p0[0] = static_cast<unsigned int>(50);
  p0[1] = static_cast<unsigned int>(50);
  value = 100.0;
  points->SetPoint(1, p0);
  points->SetPointData(1, value);

  p0[0] = static_cast<unsigned int>(100);
  p0[1] = static_cast<unsigned int>(100);
  value = 50.0;
  points->SetPoint(3, p0);
  points->SetPointData(1, value);

  function->SetPointSet(points);

  IndexType       polynomalSize;
  polynomalSize[0] = 2;
  polynomalSize[1] = 0;
  function->SetPolynomalSize(polynomalSize);

  std::cout << function << std::endl;

  filter->SetFunction(function);

  writer->SetInput(filter->GetOutput());
  writer->SetNumberOfStreamDivisions(2);
  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>WRG: unused variable<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"
#include "otbImage.h"
#include "otbFunctionToImageFilter.h"
#include "otbSarParametricMapFunction.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "itkPointSet.h"

int otbSarParametricMapFunctionToImageFilter(int argc, char * argv[])
{
  const unsigned int Dimension = 2;
  typedef float                                                                     PixelType;
  typedef otb::Image<PixelType, Dimension>                                          InputImageType;
  typedef InputImageType::IndexType                                                 IndexType;
  typedef otb::Image<PixelType, Dimension>                                          OutputImageType;
  typedef otb::ImageFileReader<InputImageType>                                      ReaderType;
  typedef otb::StreamingImageFileWriter<OutputImageType>                            WriterType;
  typedef otb::SarParametricMapFunction<InputImageType>                             FunctionType;
  typedef otb::FunctionToImageFilter<InputImageType, OutputImageType, FunctionType> FilterType;
  typedef FunctionType::PointSetType                                                PointSetType;

  // Instantiating object
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();
  PointSetType::Pointer points = PointSetType::New();

  reader->SetFileName(argv[1]);
  writer->SetFileName(argv[2]);
  filter->SetInput(reader->GetOutput());

  FunctionType::Pointer function = FunctionType::New();
  function->SetInputImage(reader->GetOutput());

  /** Test on some indexes and some physical coordinates*/
  FunctionType::PointType  p0;
  PixelType                value;

  p0[0] = static_cast<unsigned int>(0);
  p0[1] = static_cast<unsigned int>(0);
  value = 10.0;
  points->SetPoint(0, p0);
  points->SetPointData(0, value);

  p0[0] = static_cast<unsigned int>(50);
  p0[1] = static_cast<unsigned int>(50);
  value = 100.0;
  points->SetPoint(1, p0);
  points->SetPointData(1, value);

  p0[0] = static_cast<unsigned int>(100);
  p0[1] = static_cast<unsigned int>(100);
  value = 50.0;
  points->SetPoint(3, p0);
  points->SetPointData(1, value);

  function->SetPointSet(points);

  IndexType       polynomalSize;
  polynomalSize[0] = 2;
  polynomalSize[1] = 0;
  function->SetPolynomalSize(polynomalSize);

  std::cout << function << std::endl;

  filter->SetFunction(function);

  writer->SetInput(filter->GetOutput());
  writer->SetNumberOfStreamDivisions(2);
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// STL
#include <cassert>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <string>
// Boost (Extended STL)
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
// Boost Python
#include <boost/python.hpp>
// Boost Accumulators
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/service/Logger.hpp>
// RMOL
#include <rmol/RMOL_Service.hpp>
#include <rmol/config/rmol-paths.hpp>

// Aliases for namespaces
namespace ba = boost::accumulators;

// //////// Specific type definitions ///////
typedef unsigned int NbOfRuns_T;

// /////////////////////////////////////////////////////
namespace RMOL {

  /**
   * @brief Wrapper structure around the C++ API, so as to expose a Python API.
   */
  struct RMOLer {
  public:
    /**
     * Wrapper around the optimisation use case.
     */
    std::string rmol (const int& iRandomDraws, const short& iMethod,
                      const double& iCapacity) {
      std::ostringstream oStream;

      // Sanity check
      if (_logOutputStream == NULL) {
        oStream << "The log filepath is not valid." << std::endl;
        return oStream.str();
      }
      assert (_logOutputStream != NULL);

      try {

        // DEBUG
        *_logOutputStream << "Optimisation for " << iRandomDraws << " draws, "
                          << "capacity of " << iCapacity
                          << ", and with the following method: "
                          << iMethod << std::endl;

        if (_rmolService == NULL) {
          oStream << "The RMOL service has not been initialised, "
                  << "i.e., the init() method has not been called "
                  << "correctly on the RMOLer object. Please "
                  << "check that all the parameters are not empty and "
                  << "point to actual files.";
          *_logOutputStream << oStream.str();
          return oStream.str();
        }
        assert (_rmolService != NULL);

        switch (iMethod) {
        case 0: {
          // Calculate the optimal protections by the Monte Carlo
          // Integration approach
          _rmolService->optimize<OptimizationType::OPT_MC> (iRandomDraws);
          break;
        }
        case 1: {
          // Calculate the optimal protections by DP.
          _rmolService->optimize<OptimizationType::OPT_DP>();
          break;
        }
        case 2: {
          // Calculate the Bid-Price Vector by EMSR
          _rmolService->optimize<OptimizationType::HEUR_EMSR>();
          break;
        }
        case 3: {
          // Calculate the protections by EMSR-a
          _rmolService->optimize<OptimizationType::HEUR_EMSRA>();
          break;
        }
        case 4: {
          // Calculate the protections by EMSR-b
          _rmolService->optimize<OptimizationType::HEUR_EMSRB>();
          break;
        }
        default: {
          _rmolService->optimize<OptimizationType::OPT_MC> (iRandomDraws);
        }
        }

        // DEBUG
        *_logOutputStream << "End of the optimisation." << std::endl;

        // DEBUG
        *_logOutputStream << "RMOL output: "
                          << oStream.str() << std::endl;

      } catch (const stdair::RootException& eRMOLError) {
        oStream << "RMOL error: "  << eRMOLError.what() << std::endl;

      } catch (const std::exception& eStdError) {
        oStream << "Error: "  << eStdError.what() << std::endl;

      } catch (...) {
        oStream << "Unknown error" << std::endl;
      }

      //
      oStream << "RMOL has completed the generation of the booking "
              << "requests. See the log file for more details." << std::endl;

      return oStream.str();
    }

  public:
    /** Default constructor. */
    RMOLer() : _rmolService (NULL), _logOutputStream (NULL) {
    }

    /** Default copy constructor. */
    RMOLer (const RMOLer& iRMOLer)
      : _rmolService (iRMOLer._rmolService),
        _logOutputStream (iRMOLer._logOutputStream) {
    }

    /** Default constructor. */
    ~RMOLer() {
      _rmolService = NULL;
      _logOutputStream = NULL;
    }

    /**
     * Wrapper around the search use case.
     */
    bool init (const std::string& iLogFilepath,
               const short& iCapacity, const bool isBuiltin,
               const stdair::Filename_T& iInputFilename) {
      bool isEverythingOK = true;

      try {

        // Check that the file path given as input corresponds to an actual file
        const bool isWriteable = (iLogFilepath.empty() == false);
        // stdair::BasFileMgr::isWriteable (iLogFilepath);
        if (isWriteable == false) {
          isEverythingOK = false;
          return isEverythingOK;
        }

        // Set the log parameters
        _logOutputStream = new std::ofstream;
        assert (_logOutputStream != NULL);

        // Open and clean the log outputfile
        _logOutputStream->open (iLogFilepath.c_str());
        _logOutputStream->clear();

        // DEBUG
        *_logOutputStream << "Python wrapper initialisation" << std::endl;
        const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG,
                                               *_logOutputStream);

        // Initialise the context
        _rmolService = new RMOL_Service (lLogParams);
        assert (_rmolService != NULL);

        // Check wether or not a (CSV) input file should be read
        if (isBuiltin == true) {
          // Create sample BOM objects
          _rmolService->buildSampleBom();

        } else {
          // Create the RMOL objects from the input CSV file
          _rmolService->parseAndLoad (iCapacity, iInputFilename);
        }

        // DEBUG
        *_logOutputStream << "Python wrapper initialised" << std::endl;

      } catch (const stdair::RootException& eRMOLError) {
        *_logOutputStream << "RMOL error: "  << eRMOLError.what()
                          << std::endl;

      } catch (const std::exception& eStdError) {
        *_logOutputStream << "Error: "  << eStdError.what() << std::endl;

      } catch (...) {
        *_logOutputStream << "Unknown error" << std::endl;
      }

      return isEverythingOK;
    }

  private:
    /** Handle on the RMOL services (API). */
    RMOL_Service* _rmolService;
    std::ofstream* _logOutputStream;
  };

}

// /////////////////////////////////////////////////////////////
BOOST_PYTHON_MODULE(pyrmol) {
  boost::python::class_<RMOL::RMOLer> ("RMOLer")
    .def ("rmol", &RMOL::RMOLer::rmol)
    .def ("init", &RMOL::RMOLer::init);
}
<commit_msg>[Dev] Suppressed a unused and deprecated header dependency<commit_after>// STL
#include <cassert>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <string>
// Boost (Extended STL)
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
// Boost Python
#include <boost/python.hpp>
// Boost Accumulators
#include <boost/accumulators/accumulators.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/service/Logger.hpp>
// RMOL
#include <rmol/RMOL_Service.hpp>
#include <rmol/config/rmol-paths.hpp>

// Aliases for namespaces
namespace ba = boost::accumulators;

// //////// Specific type definitions ///////
typedef unsigned int NbOfRuns_T;

// /////////////////////////////////////////////////////
namespace RMOL {

  /**
   * @brief Wrapper structure around the C++ API, so as to expose a Python API.
   */
  struct RMOLer {
  public:
    /**
     * Wrapper around the optimisation use case.
     */
    std::string rmol (const int& iRandomDraws, const short& iMethod,
                      const double& iCapacity) {
      std::ostringstream oStream;

      // Sanity check
      if (_logOutputStream == NULL) {
        oStream << "The log filepath is not valid." << std::endl;
        return oStream.str();
      }
      assert (_logOutputStream != NULL);

      try {

        // DEBUG
        *_logOutputStream << "Optimisation for " << iRandomDraws << " draws, "
                          << "capacity of " << iCapacity
                          << ", and with the following method: "
                          << iMethod << std::endl;

        if (_rmolService == NULL) {
          oStream << "The RMOL service has not been initialised, "
                  << "i.e., the init() method has not been called "
                  << "correctly on the RMOLer object. Please "
                  << "check that all the parameters are not empty and "
                  << "point to actual files.";
          *_logOutputStream << oStream.str();
          return oStream.str();
        }
        assert (_rmolService != NULL);

        switch (iMethod) {
        case 0: {
          // Calculate the optimal protections by the Monte Carlo
          // Integration approach
          _rmolService->optimize<OptimizationType::OPT_MC> (iRandomDraws);
          break;
        }
        case 1: {
          // Calculate the optimal protections by DP.
          _rmolService->optimize<OptimizationType::OPT_DP>();
          break;
        }
        case 2: {
          // Calculate the Bid-Price Vector by EMSR
          _rmolService->optimize<OptimizationType::HEUR_EMSR>();
          break;
        }
        case 3: {
          // Calculate the protections by EMSR-a
          _rmolService->optimize<OptimizationType::HEUR_EMSRA>();
          break;
        }
        case 4: {
          // Calculate the protections by EMSR-b
          _rmolService->optimize<OptimizationType::HEUR_EMSRB>();
          break;
        }
        default: {
          _rmolService->optimize<OptimizationType::OPT_MC> (iRandomDraws);
        }
        }

        // DEBUG
        *_logOutputStream << "End of the optimisation." << std::endl;

        // DEBUG
        *_logOutputStream << "RMOL output: "
                          << oStream.str() << std::endl;

      } catch (const stdair::RootException& eRMOLError) {
        oStream << "RMOL error: "  << eRMOLError.what() << std::endl;

      } catch (const std::exception& eStdError) {
        oStream << "Error: "  << eStdError.what() << std::endl;

      } catch (...) {
        oStream << "Unknown error" << std::endl;
      }

      //
      oStream << "RMOL has completed the generation of the booking "
              << "requests. See the log file for more details." << std::endl;

      return oStream.str();
    }

  public:
    /** Default constructor. */
    RMOLer() : _rmolService (NULL), _logOutputStream (NULL) {
    }

    /** Default copy constructor. */
    RMOLer (const RMOLer& iRMOLer)
      : _rmolService (iRMOLer._rmolService),
        _logOutputStream (iRMOLer._logOutputStream) {
    }

    /** Default constructor. */
    ~RMOLer() {
      _rmolService = NULL;
      _logOutputStream = NULL;
    }

    /**
     * Wrapper around the search use case.
     */
    bool init (const std::string& iLogFilepath,
               const short& iCapacity, const bool isBuiltin,
               const stdair::Filename_T& iInputFilename) {
      bool isEverythingOK = true;

      try {

        // Check that the file path given as input corresponds to an actual file
        const bool isWriteable = (iLogFilepath.empty() == false);
        // stdair::BasFileMgr::isWriteable (iLogFilepath);
        if (isWriteable == false) {
          isEverythingOK = false;
          return isEverythingOK;
        }

        // Set the log parameters
        _logOutputStream = new std::ofstream;
        assert (_logOutputStream != NULL);

        // Open and clean the log outputfile
        _logOutputStream->open (iLogFilepath.c_str());
        _logOutputStream->clear();

        // DEBUG
        *_logOutputStream << "Python wrapper initialisation" << std::endl;
        const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG,
                                               *_logOutputStream);

        // Initialise the context
        _rmolService = new RMOL_Service (lLogParams);
        assert (_rmolService != NULL);

        // Check wether or not a (CSV) input file should be read
        if (isBuiltin == true) {
          // Create sample BOM objects
          _rmolService->buildSampleBom();

        } else {
          // Create the RMOL objects from the input CSV file
          _rmolService->parseAndLoad (iCapacity, iInputFilename);
        }

        // DEBUG
        *_logOutputStream << "Python wrapper initialised" << std::endl;

      } catch (const stdair::RootException& eRMOLError) {
        *_logOutputStream << "RMOL error: "  << eRMOLError.what()
                          << std::endl;

      } catch (const std::exception& eStdError) {
        *_logOutputStream << "Error: "  << eStdError.what() << std::endl;

      } catch (...) {
        *_logOutputStream << "Unknown error" << std::endl;
      }

      return isEverythingOK;
    }

  private:
    /** Handle on the RMOL services (API). */
    RMOL_Service* _rmolService;
    std::ofstream* _logOutputStream;
  };

}

// /////////////////////////////////////////////////////////////
BOOST_PYTHON_MODULE(pyrmol) {
  boost::python::class_<RMOL::RMOLer> ("RMOLer")
    .def ("rmol", &RMOL::RMOLer::rmol)
    .def ("init", &RMOL::RMOLer::init);
}
<|endoftext|>


<commit_before>// This code is in the public domain -- Ignacio Castao <castano@gmail.com>

#pragma once
#ifndef NV_CORE_ARRAY_INL
#define NV_CORE_ARRAY_INL

#include "Array.h"

#include "Stream.h"
#include "Utils.h" // swap

#include <string.h>	// memmove
#include <new> // for placement new

namespace nv
{

    // Push an element at the end of the vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::push_back( const T & val )
    {
#if 1
        nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size);

        uint old_size = m_size;
        uint new_size = m_size + 1;

        setArraySize(new_size);

        construct_range(m_buffer, new_size, old_size, val);
#else
        uint new_size = m_size + 1;

        if (new_size > m_capacity)
        {
            // @@ Is there any way to avoid this copy?
            // @@ Can we create a copy without side effects? Ie. without calls to constructor/destructor. Use alloca + memcpy?
            // @@ Assert instead of copy?
            const T copy(val);	// create a copy in case value is inside of this array.

            setArraySize(new_size);

            new (m_buffer+new_size-1) T(copy);
        }
        else
        {
            m_size = new_size;
            new(m_buffer+new_size-1) T(val);
        }
#endif // 0/1
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::pushBack( const T & val )
    {
        push_back(val);
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::append( const T & val )
    {
        push_back(val);
    }

    // Qt like push operator.
    template <typename T>
    NV_FORCEINLINE Array<T> & Array<T>::operator<< ( T & t )
    {
        push_back(t);
        return *this;
    }

    // Pop the element at the end of the vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::pop_back()
    {
        nvDebugCheck( m_size > 0 );
        resize( m_size - 1 );
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::popBack()
    {
        pop_back();
    }

    // Get back element.
    template <typename T>
    NV_FORCEINLINE const T & Array<T>::back() const
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[m_size-1];
    }

    // Get back element.
    template <typename T>
    NV_FORCEINLINE T & Array<T>::back()
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[m_size-1];
    }

    // Get front element.
    template <typename T>
    NV_FORCEINLINE const T & Array<T>::front() const
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[0];
    }

    // Get front element.
    template <typename T>
    NV_FORCEINLINE T & Array<T>::front()
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[0];
    }

    // Check if the given element is contained in the array.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::contains(const T & e) const
    {
        return find(e, NULL);
    }

    // Return true if element found.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::find(const T & element, uint * indexPtr) const
    {
        return find(element, 0, m_size, indexPtr);
    }

    // Return true if element found within the given range.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::find(const T & element, uint begin, uint end, uint * indexPtr) const
    {
        return ::nv::find(element, m_buffer, begin, end, indexPtr);
    }

    // Remove the element at the given index. This is an expensive operation!
    template <typename T>
    void Array<T>::removeAt(uint index)
    {
        nvDebugCheck(index >= 0 && index < m_size);

        if (m_size == 1) {
            clear();
        }
        else {
            m_buffer[index].~T();

            memmove(m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index));
            m_size--;
        }
    }

    // Remove the first instance of the given element.
    template <typename T>
    bool Array<T>::remove(const T & element)
    {
        uint index;
        if (find(element, &index)) {
            removeAt(index);
            return true;
        }
        return false;
    }

    // Insert the given element at the given index shifting all the elements up.
    template <typename T>
    void Array<T>::insertAt(uint index, const T & val/*=T()*/)
    {
        nvDebugCheck( index >= 0 && index <= m_size );

        setArraySize(m_size + 1);

        if (index < m_size - 1) {
            memmove(m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index));
        }

        // Copy-construct into the newly opened slot.
        new(m_buffer+index) T(val);
    }

    // Append the given data to our vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::append(const Array<T> & other)
    {
        append(other.m_buffer, other.m_size);
    }

    // Append the given data to our vector.
    template <typename T>
    void Array<T>::append(const T other[], uint count)
    {
        if (count > 0) {
            const uint old_size = m_size;

            setArraySize(m_size + count);

            for (uint i = 0; i < count; i++ ) {
                new(m_buffer + old_size + i) T(other[i]);
            }
        }
    }

    // Remove the given element by replacing it with the last one.
    template <typename T>
    void Array<T>::replaceWithLast(uint index)
    {
        nvDebugCheck( index < m_size );
        nv::swap(m_buffer[index], back());
        (m_buffer+m_size-1)->~T();
        m_size--;
    }

    // Resize the vector preserving existing elements.
    template <typename T>
    void Array<T>::resize(uint new_size)
    {
        uint old_size = m_size;

        // Destruct old elements (if we're shrinking).
        destroy_range(m_buffer, new_size, old_size);

        setArraySize(new_size);

        // Call default constructors
        construct_range(m_buffer, new_size, old_size);
    }

    // Resize the vector preserving existing elements and initializing the
    // new ones with the given value.
    template <typename T>
    void Array<T>::resize(uint new_size, const T & elem)
    {
        nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size);

        uint old_size = m_size;

        // Destruct old elements (if we're shrinking).
        destroy_range(m_buffer, new_size, old_size);

        setArraySize(new_size);

        // Call copy constructors
        construct_range(m_buffer, new_size, old_size, elem);
    }

    // Fill array with the given value.
    template <typename T>
    void Array<T>::fill(const T & elem)
    {
        fill(m_buffer, m_size, elem)
    }

    // Clear the buffer.
    template <typename T>
    NV_FORCEINLINE void Array<T>::clear()
    {
        nvDebugCheck(isValidPtr(m_buffer));

        // Destruct old elements
        destroy_range(m_buffer, 0, m_size);

        m_size = 0;
    }

    // Shrink the allocated vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::shrink()
    {
        if (m_size < m_capacity) {
            setArrayCapacity(m_size);
        }
    }

    // Preallocate space.
    template <typename T>
    NV_FORCEINLINE void Array<T>::reserve(uint desired_size)
    {
        if (desired_size > m_capacity) {
            setArrayCapacity(desired_size);
        }
    }

    // Copy elements to this array. Resizes it if needed.
    template <typename T>
    NV_FORCEINLINE void Array<T>::copy(const T * data, uint count)
    {
#if 1   // More simple, but maybe not be as efficient?
        destroy_range(m_buffer, 0, m_size);

        setArraySize(count);

        construct_range(m_buffer, count, 0, data);
#else
        const uint old_size = m_size;

        destroy_range(m_buffer, count, old_size);

        setArraySize(count);

        copy_range(m_buffer, data, old_size);

        construct_range(m_buffer, count, old_size, data);
#endif
    }

    // Assignment operator.
    template <typename T>
    NV_FORCEINLINE Array<T> & Array<T>::operator=( const Array<T> & a )
    {
        copy(a.m_buffer, a.m_size);
        return *this;
    }

    // Release ownership of allocated memory and returns pointer to it.
    template <typename T>
    T * Array<T>::release() {
        T * tmp = m_buffer;
        m_buffer = NULL;
        m_capacity = 0;
        m_size = 0;
        return tmp;
    }

    // Change array size.
    template <typename T>
    inline void Array<T>::setArraySize(uint new_size) {
        m_size = new_size;

        if (new_size > m_capacity) {
            uint new_buffer_size;
            if (m_capacity == 0) {
                // first allocation is exact
                new_buffer_size = new_size;
            }
            else {
                // following allocations grow array by 25%
                new_buffer_size = new_size + (new_size >> 2);
            }

            setArrayCapacity( new_buffer_size );
        }
    }

    // Change array capacity.
    template <typename T>
    inline void Array<T>::setArrayCapacity(uint new_capacity) {
        nvDebugCheck(new_capacity >= m_size);

        if (new_capacity == 0) {
            // free the buffer.
            if (m_buffer != NULL) {
                free<T>(m_buffer);
                m_buffer = NULL;
            }
        }
        else {
            // realloc the buffer
            m_buffer = realloc<T>(m_buffer, new_capacity);
        }

        m_capacity = new_capacity;
    }

    // Array serialization.
    template <typename Typ>
    inline Stream & operator<< ( Stream & s, Array<Typ> & p )
    {
        if (s.isLoading()) {
            uint size;
            s << size;
            p.resize( size );
        }
        else {
            s << p.m_size;
        }

        for (uint i = 0; i < p.m_size; i++) {
            s << p.m_buffer[i];
        }

        return s;
    }

    // Swap the members of the two given vectors.
    template <typename Typ>
    inline void swap(Array<Typ> & a, Array<Typ> & b)
    {
        nv::swap(a.m_buffer, b.m_buffer);
        nv::swap(a.m_capacity, b.m_capacity);
        nv::swap(a.m_size, b.m_size);
    }

} // nv namespace

#endif // NV_CORE_ARRAY_INL
<commit_msg>Add missing semicolon. Fixes issue 179.<commit_after>// This code is in the public domain -- Ignacio Castao <castano@gmail.com>

#pragma once
#ifndef NV_CORE_ARRAY_INL
#define NV_CORE_ARRAY_INL

#include "Array.h"

#include "Stream.h"
#include "Utils.h" // swap

#include <string.h>	// memmove
#include <new> // for placement new

namespace nv
{

    // Push an element at the end of the vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::push_back( const T & val )
    {
#if 1
        nvDebugCheck(&val < m_buffer || &val > m_buffer+m_size);

        uint old_size = m_size;
        uint new_size = m_size + 1;

        setArraySize(new_size);

        construct_range(m_buffer, new_size, old_size, val);
#else
        uint new_size = m_size + 1;

        if (new_size > m_capacity)
        {
            // @@ Is there any way to avoid this copy?
            // @@ Can we create a copy without side effects? Ie. without calls to constructor/destructor. Use alloca + memcpy?
            // @@ Assert instead of copy?
            const T copy(val);	// create a copy in case value is inside of this array.

            setArraySize(new_size);

            new (m_buffer+new_size-1) T(copy);
        }
        else
        {
            m_size = new_size;
            new(m_buffer+new_size-1) T(val);
        }
#endif // 0/1
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::pushBack( const T & val )
    {
        push_back(val);
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::append( const T & val )
    {
        push_back(val);
    }

    // Qt like push operator.
    template <typename T>
    NV_FORCEINLINE Array<T> & Array<T>::operator<< ( T & t )
    {
        push_back(t);
        return *this;
    }

    // Pop the element at the end of the vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::pop_back()
    {
        nvDebugCheck( m_size > 0 );
        resize( m_size - 1 );
    }
    template <typename T>
    NV_FORCEINLINE void Array<T>::popBack()
    {
        pop_back();
    }

    // Get back element.
    template <typename T>
    NV_FORCEINLINE const T & Array<T>::back() const
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[m_size-1];
    }

    // Get back element.
    template <typename T>
    NV_FORCEINLINE T & Array<T>::back()
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[m_size-1];
    }

    // Get front element.
    template <typename T>
    NV_FORCEINLINE const T & Array<T>::front() const
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[0];
    }

    // Get front element.
    template <typename T>
    NV_FORCEINLINE T & Array<T>::front()
    {
        nvDebugCheck( m_size > 0 );
        return m_buffer[0];
    }

    // Check if the given element is contained in the array.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::contains(const T & e) const
    {
        return find(e, NULL);
    }

    // Return true if element found.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::find(const T & element, uint * indexPtr) const
    {
        return find(element, 0, m_size, indexPtr);
    }

    // Return true if element found within the given range.
    template <typename T>
    NV_FORCEINLINE bool Array<T>::find(const T & element, uint begin, uint end, uint * indexPtr) const
    {
        return ::nv::find(element, m_buffer, begin, end, indexPtr);
    }

    // Remove the element at the given index. This is an expensive operation!
    template <typename T>
    void Array<T>::removeAt(uint index)
    {
        nvDebugCheck(index >= 0 && index < m_size);

        if (m_size == 1) {
            clear();
        }
        else {
            m_buffer[index].~T();

            memmove(m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index));
            m_size--;
        }
    }

    // Remove the first instance of the given element.
    template <typename T>
    bool Array<T>::remove(const T & element)
    {
        uint index;
        if (find(element, &index)) {
            removeAt(index);
            return true;
        }
        return false;
    }

    // Insert the given element at the given index shifting all the elements up.
    template <typename T>
    void Array<T>::insertAt(uint index, const T & val/*=T()*/)
    {
        nvDebugCheck( index >= 0 && index <= m_size );

        setArraySize(m_size + 1);

        if (index < m_size - 1) {
            memmove(m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index));
        }

        // Copy-construct into the newly opened slot.
        new(m_buffer+index) T(val);
    }

    // Append the given data to our vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::append(const Array<T> & other)
    {
        append(other.m_buffer, other.m_size);
    }

    // Append the given data to our vector.
    template <typename T>
    void Array<T>::append(const T other[], uint count)
    {
        if (count > 0) {
            const uint old_size = m_size;

            setArraySize(m_size + count);

            for (uint i = 0; i < count; i++ ) {
                new(m_buffer + old_size + i) T(other[i]);
            }
        }
    }

    // Remove the given element by replacing it with the last one.
    template <typename T>
    void Array<T>::replaceWithLast(uint index)
    {
        nvDebugCheck( index < m_size );
        nv::swap(m_buffer[index], back());
        (m_buffer+m_size-1)->~T();
        m_size--;
    }

    // Resize the vector preserving existing elements.
    template <typename T>
    void Array<T>::resize(uint new_size)
    {
        uint old_size = m_size;

        // Destruct old elements (if we're shrinking).
        destroy_range(m_buffer, new_size, old_size);

        setArraySize(new_size);

        // Call default constructors
        construct_range(m_buffer, new_size, old_size);
    }

    // Resize the vector preserving existing elements and initializing the
    // new ones with the given value.
    template <typename T>
    void Array<T>::resize(uint new_size, const T & elem)
    {
        nvDebugCheck(&elem < m_buffer || &elem > m_buffer+m_size);

        uint old_size = m_size;

        // Destruct old elements (if we're shrinking).
        destroy_range(m_buffer, new_size, old_size);

        setArraySize(new_size);

        // Call copy constructors
        construct_range(m_buffer, new_size, old_size, elem);
    }

    // Fill array with the given value.
    template <typename T>
    void Array<T>::fill(const T & elem)
    {
        fill(m_buffer, m_size, elem);
    }

    // Clear the buffer.
    template <typename T>
    NV_FORCEINLINE void Array<T>::clear()
    {
        nvDebugCheck(isValidPtr(m_buffer));

        // Destruct old elements
        destroy_range(m_buffer, 0, m_size);

        m_size = 0;
    }

    // Shrink the allocated vector.
    template <typename T>
    NV_FORCEINLINE void Array<T>::shrink()
    {
        if (m_size < m_capacity) {
            setArrayCapacity(m_size);
        }
    }

    // Preallocate space.
    template <typename T>
    NV_FORCEINLINE void Array<T>::reserve(uint desired_size)
    {
        if (desired_size > m_capacity) {
            setArrayCapacity(desired_size);
        }
    }

    // Copy elements to this array. Resizes it if needed.
    template <typename T>
    NV_FORCEINLINE void Array<T>::copy(const T * data, uint count)
    {
#if 1   // More simple, but maybe not be as efficient?
        destroy_range(m_buffer, 0, m_size);

        setArraySize(count);

        construct_range(m_buffer, count, 0, data);
#else
        const uint old_size = m_size;

        destroy_range(m_buffer, count, old_size);

        setArraySize(count);

        copy_range(m_buffer, data, old_size);

        construct_range(m_buffer, count, old_size, data);
#endif
    }

    // Assignment operator.
    template <typename T>
    NV_FORCEINLINE Array<T> & Array<T>::operator=( const Array<T> & a )
    {
        copy(a.m_buffer, a.m_size);
        return *this;
    }

    // Release ownership of allocated memory and returns pointer to it.
    template <typename T>
    T * Array<T>::release() {
        T * tmp = m_buffer;
        m_buffer = NULL;
        m_capacity = 0;
        m_size = 0;
        return tmp;
    }

    // Change array size.
    template <typename T>
    inline void Array<T>::setArraySize(uint new_size) {
        m_size = new_size;

        if (new_size > m_capacity) {
            uint new_buffer_size;
            if (m_capacity == 0) {
                // first allocation is exact
                new_buffer_size = new_size;
            }
            else {
                // following allocations grow array by 25%
                new_buffer_size = new_size + (new_size >> 2);
            }

            setArrayCapacity( new_buffer_size );
        }
    }

    // Change array capacity.
    template <typename T>
    inline void Array<T>::setArrayCapacity(uint new_capacity) {
        nvDebugCheck(new_capacity >= m_size);

        if (new_capacity == 0) {
            // free the buffer.
            if (m_buffer != NULL) {
                free<T>(m_buffer);
                m_buffer = NULL;
            }
        }
        else {
            // realloc the buffer
            m_buffer = realloc<T>(m_buffer, new_capacity);
        }

        m_capacity = new_capacity;
    }

    // Array serialization.
    template <typename Typ>
    inline Stream & operator<< ( Stream & s, Array<Typ> & p )
    {
        if (s.isLoading()) {
            uint size;
            s << size;
            p.resize( size );
        }
        else {
            s << p.m_size;
        }

        for (uint i = 0; i < p.m_size; i++) {
            s << p.m_buffer[i];
        }

        return s;
    }

    // Swap the members of the two given vectors.
    template <typename Typ>
    inline void swap(Array<Typ> & a, Array<Typ> & b)
    {
        nv::swap(a.m_buffer, b.m_buffer);
        nv::swap(a.m_capacity, b.m_capacity);
        nv::swap(a.m_size, b.m_size);
    }

} // nv namespace

#endif // NV_CORE_ARRAY_INL
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <node_object_wrap.h>
#include <queue>

#include "lib/RtMidi/RtMidi.h"
#include "lib/RtMidi/RtMidi.cpp"

using namespace node;

#define SAFE_NODE_SET_PROTOTYPE_METHOD(templ, name, callback)             \
do {                                                                      \
  v8::Local<v8::Signature> __callback##_SIG = v8::Signature::New(templ);  \
  v8::Local<v8::FunctionTemplate> __callback##_TEM =                      \
    v8::FunctionTemplate::New(callback, v8::Handle<v8::Value>(),          \
                          __callback##_SIG);                              \
  templ->PrototypeTemplate()->Set(v8::String::NewSymbol(name),            \
                                  __callback##_TEM);                      \
} while (0)

class NodeMidiOutput : ObjectWrap
{
private:
    RtMidiOut* out;
public:
    static v8::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        v8::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);

        s_ct = v8::Persistent<v8::FunctionTemplate>::New(t);
        s_ct->InstanceTemplate()->SetInternalFieldCount(1);
        s_ct->SetClassName(v8::String::NewSymbol("NodeMidiOutput"));

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortCount", GetPortCount);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortName", GetPortName);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openPort", OpenPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openVirtualPort", OpenVirtualPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "closePort", ClosePort);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "sendMessage", SendMessage);

        target->Set(v8::String::NewSymbol("output"),
                    s_ct->GetFunction());
    }

    NodeMidiOutput()
    {
        out = new RtMidiOut();
    }

    ~NodeMidiOutput()
    {
        delete out;
    }

    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = new NodeMidiOutput();
        output->Wrap(args.This());
        return args.This();
    }

    static v8::Handle<v8::Value> GetPortCount(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        v8::Local<v8::Integer> result = v8::Uint32::New(output->out->getPortCount());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> GetPortName(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        v8::Local<v8::String> result = v8::String::New(output->out->getPortName(portNumber).c_str());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> OpenPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        output->out->openPort(portNumber);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> OpenVirtualPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsString()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be a string")));
        }
        std::string name(*v8::String::AsciiValue(args[0]));
        output->out->openVirtualPort(name);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> ClosePort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        output->out->closePort();
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> SendMessage(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsArray()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an array")));
        }
        v8::Local<v8::Object> message = args[0]->ToObject();
        size_t messageLength = message->Get(v8::String::New("length"))->Int32Value();
        std::vector<unsigned char> messageOutput;
        for (size_t i = 0; i != messageLength; ++i) {
            messageOutput.push_back(message->Get(v8::Integer::New(i))->Int32Value());
        }
        output->out->sendMessage(&messageOutput);
        return scope.Close(v8::Undefined());
    }
};

static v8::Persistent<v8::String> emit_symbol;

class NodeMidiInput : public ObjectWrap
{
private:
    RtMidiIn* in;

public:
    ev_async* message_async;
    pthread_mutex_t message_mutex;

    struct MidiMessage
    {
        double deltaTime;
        std::vector<unsigned char> message;
    };
    std::queue<MidiMessage*> message_queue;

    static v8::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        v8::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);

        s_ct = v8::Persistent<v8::FunctionTemplate>::New(t);
        s_ct->InstanceTemplate()->SetInternalFieldCount(1);

        emit_symbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("emit"));

        s_ct->SetClassName(v8::String::NewSymbol("NodeMidiInput"));

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortCount", GetPortCount);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortName", GetPortName);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openPort", OpenPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openVirtualPort", OpenVirtualPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "closePort", ClosePort);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "ignoreTypes", IgnoreTypes);

        target->Set(v8::String::NewSymbol("input"),
                    s_ct->GetFunction());
    }

    NodeMidiInput()
    {
        in = new RtMidiIn();
        pthread_mutex_init(&message_mutex, NULL);
        message_async = new ev_async();
    }

    ~NodeMidiInput()
    {
        in->closePort();
        ev_async_stop(EV_DEFAULT_UC_ message_async);
        delete message_async;
        delete in;
        pthread_mutex_destroy(&message_mutex);
    }

    static void EmitMessage(EV_P_ ev_async *w, int revents)
    {
        v8::HandleScope scope;
        NodeMidiInput *input = static_cast<NodeMidiInput*>(w->data);
        pthread_mutex_lock(&input->message_mutex);
        while (!input->message_queue.empty())
        {
            MidiMessage* message = input->message_queue.front();
            v8::Local<v8::Value> args[3];
            args[0]= v8::String::New("message");
            args[1] = v8::Local<v8::Value>::New(v8::Number::New(message->deltaTime));
            size_t count = message->message.size();
            v8::Local<v8::Array> data = v8::Array::New(count);
            for (size_t i = 0; i < count; ++i) {
                data->Set(v8::Number::New(i), v8::Integer::New(message->message[i]));
            }
            args[2] = v8::Local<v8::Value>::New(data);
            v8::Local<v8::Value> emit_v = input->handle_->Get(emit_symbol);
            if (emit_v->IsFunction()) {
                v8::Local<v8::Function> emit=v8::Local<v8::Function>::Cast(emit_v);
                v8::TryCatch tc;
                emit->Call(input->handle_,3,args);
                if (tc.HasCaught()){
                    node::FatalException(tc);
               }
            }
            input->message_queue.pop();
            delete message;
        }
        pthread_mutex_unlock(&input->message_mutex);
    }

    static void Callback(double deltaTime, std::vector<unsigned char> *message, void *userData)
    {
        NodeMidiInput *input = static_cast<NodeMidiInput*>(userData);
        MidiMessage* data = new MidiMessage();
        data->deltaTime = deltaTime;
        data->message = *message;
        pthread_mutex_lock(&input->message_mutex);
        input->message_queue.push(data);
        pthread_mutex_unlock(&input->message_mutex);
        ev_async_send(EV_DEFAULT_UC_ input->message_async);
    }

    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = new NodeMidiInput();
        input->message_async->data = input;
        ev_async_init(input->message_async, NodeMidiInput::EmitMessage);
        ev_async_start(EV_DEFAULT_UC_ input->message_async);
        ev_unref(EV_DEFAULT_UC);
        input->Wrap(args.This());
        return args.This();
    }

    static v8::Handle<v8::Value> GetPortCount(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        v8::Local<v8::Integer> result = v8::Uint32::New(input->in->getPortCount());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> GetPortName(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        v8::Local<v8::String> result = v8::String::New(input->in->getPortName(portNumber).c_str());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> OpenPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, ObjectWrap::Unwrap<NodeMidiInput>(args.This()));
        input->in->openPort(portNumber);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> OpenVirtualPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsString()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be a string")));
        }
        std::string name(*v8::String::AsciiValue(args[0]));
        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, ObjectWrap::Unwrap<NodeMidiInput>(args.This()));
        input->in->openVirtualPort(name);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> ClosePort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        input->Unref();
        input->in->closePort();
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> IgnoreTypes(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() != 3 || !args[0]->IsBoolean() || !args[1]->IsBoolean() || !args[2]->IsBoolean()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("Arguments must be boolean")));
        }
        bool filter_sysex = args[0]->BooleanValue();
        bool filter_timing = args[1]->BooleanValue();
        bool filter_sensing = args[2]->BooleanValue();
        input->in->ignoreTypes(filter_sysex, filter_timing, filter_sensing);
        return scope.Close(v8::Undefined());
    }
};

v8::Persistent<v8::FunctionTemplate> NodeMidiOutput::s_ct;
v8::Persistent<v8::FunctionTemplate> NodeMidiInput::s_ct;

extern "C" {
    void init (v8::Handle<v8::Object> target)
    {
        NodeMidiOutput::Init(target);
        NodeMidiInput::Init(target);
    }

    NODE_MODULE(nodemidi, init);
}
<commit_msg>switch from libev to libuv, and allow to share the source to build an internal module (currently required on win32)<commit_after>#include <v8.h>
#include <node.h>
#include <node_object_wrap.h>
#include <queue>
#include <uv.h>

#ifdef _WIN32
#define __WINDOWS_MM__
#include "pthread.h"
#endif

#ifdef __APPLE_
#define __MACOSX_CORE__
#endif

#ifdef __gnu_linux__
#define __LINUX_ALSASEQ__
#endif

#include "lib/RtMidi/RtMidi.h"
#include "lib/RtMidi/RtMidi.cpp"

#ifdef BUILD_EXTERNAL_MODULE
using namespace node;

#else
namespace node {

#endif

#define SAFE_NODE_SET_PROTOTYPE_METHOD(templ, name, callback)             \
do {                                                                      \
  v8::Local<v8::Signature> __callback##_SIG = v8::Signature::New(templ);  \
  v8::Local<v8::FunctionTemplate> __callback##_TEM =                      \
    v8::FunctionTemplate::New(callback, v8::Handle<v8::Value>(),          \
                          __callback##_SIG);                              \
  templ->PrototypeTemplate()->Set(v8::String::NewSymbol(name),            \
                                  __callback##_TEM);                      \
} while (0)

class NodeMidiOutput : ObjectWrap
{
private:
    RtMidiOut* out;
public:
    static v8::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        v8::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);

        s_ct = v8::Persistent<v8::FunctionTemplate>::New(t);
        s_ct->InstanceTemplate()->SetInternalFieldCount(1);
        s_ct->SetClassName(v8::String::NewSymbol("NodeMidiOutput"));

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortCount", GetPortCount);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortName", GetPortName);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openPort", OpenPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openVirtualPort", OpenVirtualPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "closePort", ClosePort);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "sendMessage", SendMessage);

        target->Set(v8::String::NewSymbol("output"),
                    s_ct->GetFunction());
    }

    NodeMidiOutput()
    {
        out = new RtMidiOut();
    }

    ~NodeMidiOutput()
    {
        delete out;
    }

    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = new NodeMidiOutput();
        output->Wrap(args.This());
        return args.This();
    }

    static v8::Handle<v8::Value> GetPortCount(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        v8::Local<v8::Integer> result = v8::Uint32::New(output->out->getPortCount());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> GetPortName(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        v8::Local<v8::String> result = v8::String::New(output->out->getPortName(portNumber).c_str());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> OpenPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        output->out->openPort(portNumber);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> OpenVirtualPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsString()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be a string")));
        }
        std::string name(*v8::String::AsciiValue(args[0]));
        output->out->openVirtualPort(name);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> ClosePort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        output->out->closePort();
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> SendMessage(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiOutput* output = ObjectWrap::Unwrap<NodeMidiOutput>(args.This());
        if (args.Length() == 0 || !args[0]->IsArray()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an array")));
        }
        v8::Local<v8::Object> message = args[0]->ToObject();
        size_t messageLength = message->Get(v8::String::New("length"))->Int32Value();
        std::vector<unsigned char> messageOutput;
        for (size_t i = 0; i != messageLength; ++i) {
            messageOutput.push_back(message->Get(v8::Integer::New(i))->Int32Value());
        }
        output->out->sendMessage(&messageOutput);
        return scope.Close(v8::Undefined());
    }
};

static v8::Persistent<v8::String> emit_symbol;

class NodeMidiInput : public ObjectWrap
{
private:
    RtMidiIn* in;

public:
    uv_async_t message_async;
    pthread_mutex_t message_mutex;

    struct MidiMessage
    {
        double deltaTime;
        std::vector<unsigned char> message;
    };
    std::queue<MidiMessage*> message_queue;

    static v8::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        v8::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);

        s_ct = v8::Persistent<v8::FunctionTemplate>::New(t);
        s_ct->InstanceTemplate()->SetInternalFieldCount(1);

        emit_symbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("emit"));

        s_ct->SetClassName(v8::String::NewSymbol("NodeMidiInput"));

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortCount", GetPortCount);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "getPortName", GetPortName);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openPort", OpenPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "openVirtualPort", OpenVirtualPort);
        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "closePort", ClosePort);

        SAFE_NODE_SET_PROTOTYPE_METHOD(s_ct, "ignoreTypes", IgnoreTypes);

        target->Set(v8::String::NewSymbol("input"),
                    s_ct->GetFunction());
    }

    NodeMidiInput()
    {
        in = new RtMidiIn();
        pthread_mutex_init(&message_mutex, NULL);
    }

    ~NodeMidiInput()
    {
        in->closePort();
// not sure im doing the right thing here for uv the two next lines
//      ev_async_stop(EV_DEFAULT_UC_ message_async);
        delete &message_async;
        delete in;
        pthread_mutex_destroy(&message_mutex);
    }

    static void EmitMessage(uv_async_t *w, int status)
    {
        assert(status == 0);
        v8::HandleScope scope;
        NodeMidiInput *input = static_cast<NodeMidiInput*>(w->data);
        pthread_mutex_lock(&input->message_mutex);
        while (!input->message_queue.empty())
        {
            MidiMessage* message = input->message_queue.front();
            v8::Local<v8::Value> args[3];
            args[0]= v8::String::New("message");
            args[1] = v8::Local<v8::Value>::New(v8::Number::New(message->deltaTime));
            size_t count = message->message.size();
            v8::Local<v8::Array> data = v8::Array::New(count);
            for (size_t i = 0; i < count; ++i) {
                data->Set(v8::Number::New(i), v8::Integer::New(message->message[i]));
            }
            args[2] = v8::Local<v8::Value>::New(data);
            v8::Local<v8::Value> emit_v = input->handle_->Get(emit_symbol);
            if (emit_v->IsFunction()) {
                v8::Local<v8::Function> emit=v8::Local<v8::Function>::Cast(emit_v);
                v8::TryCatch tc;
                emit->Call(input->handle_,3,args);
                if (tc.HasCaught()){
                    node::FatalException(tc);
               }
            }
            input->message_queue.pop();
            delete message;
        }
        pthread_mutex_unlock(&input->message_mutex);
    }

    static void Callback(double deltaTime, std::vector<unsigned char> *message, void *userData)
    {
        NodeMidiInput *input = static_cast<NodeMidiInput*>(userData);
        MidiMessage* data = new MidiMessage();
        data->deltaTime = deltaTime;
        data->message = *message;
        pthread_mutex_lock(&input->message_mutex);
        input->message_queue.push(data);
        pthread_mutex_unlock(&input->message_mutex);
        uv_async_send(&input->message_async);
    }

    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = new NodeMidiInput();
        input->message_async.data = input;
        uv_async_init(uv_default_loop(),&input->message_async, NodeMidiInput::EmitMessage);
        uv_unref(uv_default_loop());
        input->Wrap(args.This());
        return args.This();
    }

    static v8::Handle<v8::Value> GetPortCount(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        v8::Local<v8::Integer> result = v8::Uint32::New(input->in->getPortCount());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> GetPortName(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        v8::Local<v8::String> result = v8::String::New(input->in->getPortName(portNumber).c_str());
        return scope.Close(result);
    }

    static v8::Handle<v8::Value> OpenPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsUint32()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be an integer")));
        }
        unsigned int portNumber = args[0]->Uint32Value();
        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, ObjectWrap::Unwrap<NodeMidiInput>(args.This()));
        input->in->openPort(portNumber);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> OpenVirtualPort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() == 0 || !args[0]->IsString()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("First argument must be a string")));
        }
        std::string name(*v8::String::AsciiValue(args[0]));
        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, ObjectWrap::Unwrap<NodeMidiInput>(args.This()));
        input->in->openVirtualPort(name);
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> ClosePort(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        input->Unref();
        input->in->closePort();
        return scope.Close(v8::Undefined());
    }

    static v8::Handle<v8::Value> IgnoreTypes(const v8::Arguments& args)
    {
        v8::HandleScope scope;
        NodeMidiInput* input = ObjectWrap::Unwrap<NodeMidiInput>(args.This());
        if (args.Length() != 3 || !args[0]->IsBoolean() || !args[1]->IsBoolean() || !args[2]->IsBoolean()) {
            return ThrowException(v8::Exception::TypeError(
                v8::String::New("Arguments must be boolean")));
        }
        bool filter_sysex = args[0]->BooleanValue();
        bool filter_timing = args[1]->BooleanValue();
        bool filter_sensing = args[2]->BooleanValue();
        input->in->ignoreTypes(filter_sysex, filter_timing, filter_sensing);
        return scope.Close(v8::Undefined());
    }
};

v8::Persistent<v8::FunctionTemplate> NodeMidiOutput::s_ct;
v8::Persistent<v8::FunctionTemplate> NodeMidiInput::s_ct;

#ifdef BUILD_EXTERNAL_MODULE
extern "C" {
    void init (v8::Handle<v8::Object> target)
    {
        NodeMidiOutput::Init(target);
        NodeMidiInput::Init(target);
    }
    NODE_MODULE(nodemidi, init);
}

#else
    void InitMidi (v8::Handle<v8::Object> target)
    {
        NodeMidiOutput::Init(target);
        NodeMidiInput::Init(target);
    }
} // namespace node

NODE_MODULE(node_midi, node::InitMidi);

#endif
<|endoftext|>


<commit_before>#include "QGCHilFlightGearConfiguration.h"

#include "MainWindow.h"

// Various settings groups and keys
const char* QGCHilFlightGearConfiguration::_settingsGroup =                 "QGC_HILCONFIG_FLIGHTGEAR";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupFixedWing =  "FIXED_WING";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupQuadRotor =  "QUADROTOR";
const char* QGCHilFlightGearConfiguration::_aircraftKey =                   "AIRCRAFT";
const char* QGCHilFlightGearConfiguration::_optionsKey =                    "OPTIONS";
const char* QGCHilFlightGearConfiguration::_barometerOffsetKey =            "BARO_OFFSET";
const char* QGCHilFlightGearConfiguration::_sensorHilKey =                  "SENSOR_HIL";

// Default set of optional command line parameters. If FlightGear won't run HIL without it it should go into
// the QGCFlightGearLink code instead.
const char* QGCHilFlightGearConfiguration::_defaultOptions = "--roll=0 --pitch=0 --vc=0 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --prop:/sim/frame-rate-throttle-hz=30 --control=mouse --disable-sound --disable-random-objects --disable-ai-traffic --shading-flat --fog-disable --disable-specular-highlight --disable-random-objects --disable-panel --disable-clouds --fdm=jsb --units-meters --enable-terrasync";

QGCHilFlightGearConfiguration::QGCHilFlightGearConfiguration(UAS* mav, QWidget *parent) :
    QWidget(parent),
    _mav(mav),
    _mavSettingsSubGroup(NULL),
    _resetOptionsAction(tr("Reset to default options"), this)

{
    Q_ASSERT(_mav);

    _ui.setupUi(this);

    QStringList items;
    if (_mav->getSystemType() == MAV_TYPE_FIXED_WING)
    {
        items << "EasyStar";
        items << "Rascal110-JSBSim";
        items << "c172p";
        items << "YardStik";
        items << "Malolo1";
        _mavSettingsSubGroup = _mavSettingsSubGroupFixedWing;
    }
    else if (_mav->getSystemType() == MAV_TYPE_QUADROTOR)
    {
        items << "arducopter";
        _mavSettingsSubGroup = _mavSettingsSubGroupQuadRotor;
    }
    else
    {
        // FIXME: Should disable all input, won't work. Show error message in the status label thing.
        items << "<aircraft>";
    }
    _ui.aircraftComboBox->addItems(items);

    QSettings settings;
    settings.beginGroup(_settingsGroup);
    settings.beginGroup(_mavSettingsSubGroup);
    QString aircraft = settings.value(_aircraftKey).toString();
    QString options = settings.value(_optionsKey).toString();
    QString baroOffset = settings.value(_barometerOffsetKey).toString();
    bool sensorHil = settings.value(_sensorHilKey, QVariant(true)).toBool();
    settings.endGroup();
    settings.endGroup();

    if (!aircraft.isEmpty()) {
        int index = _ui.aircraftComboBox->findText(aircraft);
        if (index != -1) {
            _ui.aircraftComboBox->setCurrentIndex(index);
        }
    }
    if (options.isEmpty()) {
        options = _defaultOptions;
    }
    _ui.optionsPlainTextEdit->setPlainText(options);
    _ui.barometerOffsetLineEdit->setText(baroOffset);
    _ui.sensorHilCheckBox->setChecked(sensorHil);

    // Provide an option on the context menu to reset the option back to default
    _ui.optionsPlainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
    bool success = connect(&_resetOptionsAction, SIGNAL(triggered()), this, SLOT(_setDefaultOptions()));
    Q_ASSERT(success);
    success = connect(_ui.optionsPlainTextEdit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(_showContextMenu(const QPoint &)));
    Q_ASSERT(success);
}

QGCHilFlightGearConfiguration::~QGCHilFlightGearConfiguration()
{
    QString aircraft = _ui.aircraftComboBox->currentText();
    QString options = _ui.optionsPlainTextEdit->toPlainText();
    QString baroOffset = _ui.barometerOffsetLineEdit->text();
    bool sensorHil = _ui.sensorHilCheckBox->isChecked();

    QSettings settings;
    settings.beginGroup(_settingsGroup);
    settings.beginGroup(_mavSettingsSubGroup);

    if (aircraft.isEmpty()) {
        settings.remove(_aircraftKey);
    } else {
        settings.setValue(_aircraftKey, aircraft);
    }

    if (options.isEmpty() || options == _defaultOptions) {
        settings.remove(_optionsKey);
    } else {
        settings.setValue(_optionsKey, options);
    }

    // Double QVariant is to convert from string to float. It will change to 0.0 if invalid.
    settings.setValue(_barometerOffsetKey, QVariant(QVariant(baroOffset).toFloat()));

    settings.setValue(_sensorHilKey, QVariant(sensorHil));

    settings.endGroup();
    settings.endGroup();
}

void QGCHilFlightGearConfiguration::on_startButton_clicked()
{
    //XXX check validity of inputs
    QString options = _ui.optionsPlainTextEdit->toPlainText();
    options.append(" --aircraft=" + _ui.aircraftComboBox->currentText());
    _mav->enableHilFlightGear(true, options, _ui.sensorHilCheckBox->isChecked(), this);
}

void QGCHilFlightGearConfiguration::on_stopButton_clicked()
{
    _mav->stopHil();
}

void QGCHilFlightGearConfiguration::on_barometerOffsetLineEdit_textChanged(const QString& baroOffset)
{
    emit barometerOffsetChanged(baroOffset.toFloat());
}

void QGCHilFlightGearConfiguration::_showContextMenu(const QPoint &pt)
{
    QMenu* menu = _ui.optionsPlainTextEdit->createStandardContextMenu();
    menu->addAction(&_resetOptionsAction);
    menu->exec(_ui.optionsPlainTextEdit->mapToGlobal(pt));
    delete menu;
}

void QGCHilFlightGearConfiguration::_setDefaultOptions(void)
{
    _ui.optionsPlainTextEdit->setPlainText(_defaultOptions);
}

<commit_msg>commit<commit_after>#include "QGCHilFlightGearConfiguration.h"

#include "MainWindow.h"

// Various settings groups and keys
const char* QGCHilFlightGearConfiguration::_settingsGroup =                 "QGC_HILCONFIG_FLIGHTGEAR";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupFixedWing =  "FIXED_WING";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupQuadRotor =  "QUADROTOR";
const char* QGCHilFlightGearConfiguration::_aircraftKey =                   "AIRCRAFT";
const char* QGCHilFlightGearConfiguration::_optionsKey =                    "OPTIONS";
const char* QGCHilFlightGearConfiguration::_barometerOffsetKey =            "BARO_OFFSET";
const char* QGCHilFlightGearConfiguration::_sensorHilKey =                  "SENSOR_HIL";

// Default set of optional command line parameters. If FlightGear won't run HIL without it it should go into
// the QGCFlightGearLink code instead.
const char* QGCHilFlightGearConfiguration::_defaultOptions = "--roll=0 --pitch=0 --vc=0 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --prop:/sim/frame-rate-throttle-hz=30 --control=mouse --disable-sound --disable-random-objects --disable-ai-traffic --shading-flat --fog-disable --disable-specular-highlight --disable-panel --disable-clouds --fdm=jsb --units-meters --enable-terrasync";

QGCHilFlightGearConfiguration::QGCHilFlightGearConfiguration(UAS* mav, QWidget *parent) :
    QWidget(parent),
    _mav(mav),
    _mavSettingsSubGroup(NULL),
    _resetOptionsAction(tr("Reset to default options"), this)

{
    Q_ASSERT(_mav);

    _ui.setupUi(this);

    QStringList items;
    if (_mav->getSystemType() == MAV_TYPE_FIXED_WING)
    {
        items << "EasyStar";
        items << "Rascal110-JSBSim";
        items << "c172p";
        items << "YardStik";
        items << "Malolo1";
        _mavSettingsSubGroup = _mavSettingsSubGroupFixedWing;
    }
    else if (_mav->getSystemType() == MAV_TYPE_QUADROTOR)
    {
        items << "arducopter";
        _mavSettingsSubGroup = _mavSettingsSubGroupQuadRotor;
    }
    else
    {
        // FIXME: Should disable all input, won't work. Show error message in the status label thing.
        items << "<aircraft>";
    }
    _ui.aircraftComboBox->addItems(items);

    QSettings settings;
    settings.beginGroup(_settingsGroup);
    settings.beginGroup(_mavSettingsSubGroup);
    QString aircraft = settings.value(_aircraftKey).toString();
    QString options = settings.value(_optionsKey).toString();
    QString baroOffset = settings.value(_barometerOffsetKey).toString();
    bool sensorHil = settings.value(_sensorHilKey, QVariant(true)).toBool();
    settings.endGroup();
    settings.endGroup();

    if (!aircraft.isEmpty()) {
        int index = _ui.aircraftComboBox->findText(aircraft);
        if (index != -1) {
            _ui.aircraftComboBox->setCurrentIndex(index);
        }
    }
    if (options.isEmpty()) {
        options = _defaultOptions;
    }
    _ui.optionsPlainTextEdit->setPlainText(options);
    _ui.barometerOffsetLineEdit->setText(baroOffset);
    _ui.sensorHilCheckBox->setChecked(sensorHil);

    // Provide an option on the context menu to reset the option back to default
    _ui.optionsPlainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
    bool success = connect(&_resetOptionsAction, SIGNAL(triggered()), this, SLOT(_setDefaultOptions()));
    Q_ASSERT(success);
    success = connect(_ui.optionsPlainTextEdit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(_showContextMenu(const QPoint &)));
    Q_ASSERT(success);
}

QGCHilFlightGearConfiguration::~QGCHilFlightGearConfiguration()
{
    QString aircraft = _ui.aircraftComboBox->currentText();
    QString options = _ui.optionsPlainTextEdit->toPlainText();
    QString baroOffset = _ui.barometerOffsetLineEdit->text();
    bool sensorHil = _ui.sensorHilCheckBox->isChecked();

    QSettings settings;
    settings.beginGroup(_settingsGroup);
    settings.beginGroup(_mavSettingsSubGroup);

    if (aircraft.isEmpty()) {
        settings.remove(_aircraftKey);
    } else {
        settings.setValue(_aircraftKey, aircraft);
    }

    if (options.isEmpty() || options == _defaultOptions) {
        settings.remove(_optionsKey);
    } else {
        settings.setValue(_optionsKey, options);
    }

    // Double QVariant is to convert from string to float. It will change to 0.0 if invalid.
    settings.setValue(_barometerOffsetKey, QVariant(QVariant(baroOffset).toFloat()));

    settings.setValue(_sensorHilKey, QVariant(sensorHil));

    settings.endGroup();
    settings.endGroup();
}

void QGCHilFlightGearConfiguration::on_startButton_clicked()
{
    //XXX check validity of inputs
    QString options = _ui.optionsPlainTextEdit->toPlainText();
    options.append(" --aircraft=" + _ui.aircraftComboBox->currentText());
    _mav->enableHilFlightGear(true, options, _ui.sensorHilCheckBox->isChecked(), this);
}

void QGCHilFlightGearConfiguration::on_stopButton_clicked()
{
    _mav->stopHil();
}

void QGCHilFlightGearConfiguration::on_barometerOffsetLineEdit_textChanged(const QString& baroOffset)
{
    emit barometerOffsetChanged(baroOffset.toFloat());
}

void QGCHilFlightGearConfiguration::_showContextMenu(const QPoint &pt)
{
    QMenu* menu = _ui.optionsPlainTextEdit->createStandardContextMenu();
    menu->addAction(&_resetOptionsAction);
    menu->exec(_ui.optionsPlainTextEdit->mapToGlobal(pt));
    delete menu;
}

void QGCHilFlightGearConfiguration::_setDefaultOptions(void)
{
    _ui.optionsPlainTextEdit->setPlainText(_defaultOptions);
}

<|endoftext|>