<commit_before>
#ifndef __BUFFER_CACHE_WRITEBACK_HPP__
#define __BUFFER_CACHE_WRITEBACK_HPP__

#include <set>

#include "concurrency/rwi_lock.hpp"

// TODO: What about interval=0 (flush on every transaction)?
// TODO: What about interval=+inf (never flush)?

template <class config_t>
struct writeback_tmpl_t : public lock_available_callback<config_t> {
public:
    typedef typename config_t::transaction_t transaction_t;
    typedef typename config_t::cache_t cache_t;
    typedef typename config_t::buf_t buf_t;

    writeback_tmpl_t(cache_t *cache, bool wait_for_flush, unsigned int interval_ms);
    virtual ~writeback_tmpl_t();

    void start(); // Start the writeback process as part of database startup.
    void shutdown(sync_callback<config_t> *callback);

    void sync(sync_callback<config_t> *callback);

    bool begin_transaction(transaction_t *txn);
    bool commit(transaction_t *transaction,
        transaction_commit_callback<config_t> *callback);
    void aio_complete(buf_t *, bool written);

    class local_buf_t {
    public:
        explicit local_buf_t(writeback_tmpl_t *wb)
            : writeback(wb), dirty(false) {}

        bool is_dirty() const { return dirty; }
        void set_dirty(buf_t *buf);

        void set_clean() {
            assert(dirty);
            dirty = false;
        }

    private:
        writeback_tmpl_t *writeback;
        bool dirty;
    };

private:
    typedef typename config_t::serializer_t serializer_t;
    typedef typename serializer_t::block_id_t block_id_t;
    typedef transaction_commit_callback<config_t> transaction_commit_callback_t;
    typedef sync_callback<config_t> sync_callback_t;
    typedef std::pair<transaction_t *, transaction_commit_callback_t *>
        txn_state_t;

    enum state {
        state_none,
        state_locking,
        state_locked,
        state_write_bufs,
    };

	void start_flush_timer(void);
    static void timer_callback(void *ctx);
    virtual void on_lock_available();
    void writeback(buf_t *buf);

    /* User-controlled settings. */
    bool wait_for_flush;
    uint64_t interval_ms;

    /* Internal variables used at all times. */
    cache_t *cache;
    unsigned int num_txns;
    rwi_lock<config_t> *flush_lock;
    std::set<txn_state_t> txns;
    std::set<block_id_t> dirty_blocks;
    std::vector<sync_callback_t *> sync_callbacks;
    sync_callback_t *shutdown_callback;
    bool final_sync;

    /* Internal variables used only during a flush operation. */
    enum state state;
    transaction_t *transaction;
    std::set<txn_state_t> flush_txns;
    std::set<buf_t *> flush_bufs;
};

#include "buffer_cache/writeback/writeback_impl.hpp"

#endif // __buffer_cache_writeback_hpp__

<commit_msg>Fixed a bug in previous commit.<commit_after>
#ifndef __BUFFER_CACHE_WRITEBACK_HPP__
#define __BUFFER_CACHE_WRITEBACK_HPP__

#include <set>

#include "concurrency/rwi_lock.hpp"

// TODO: What about interval=0 (flush on every transaction)?
// TODO: What about interval=+inf (never flush)?

template <class config_t>
struct writeback_tmpl_t : public lock_available_callback<config_t> {
public:
    typedef typename config_t::transaction_t transaction_t;
    typedef typename config_t::cache_t cache_t;
    typedef typename config_t::buf_t buf_t;

    writeback_tmpl_t(cache_t *cache, bool wait_for_flush, unsigned int interval_ms);
    virtual ~writeback_tmpl_t();

    void start(); // Start the writeback process as part of database startup.
    void shutdown(sync_callback<config_t> *callback);

    void sync(sync_callback<config_t> *callback);

    bool begin_transaction(transaction_t *txn);
    bool commit(transaction_t *transaction,
        transaction_commit_callback<config_t> *callback);
    void aio_complete(buf_t *, bool written);

    class local_buf_t {
    public:
        explicit local_buf_t(writeback_tmpl_t *wb)
            : writeback(wb), dirty(false) {}

        bool is_dirty() const { return dirty; }
        void set_dirty(buf_t *buf);

        void set_clean() {
            assert(dirty);
            dirty = false;
        }

    private:
        writeback_tmpl_t *writeback;
        bool dirty;
    };

private:
    typedef typename config_t::serializer_t serializer_t;
    typedef typename serializer_t::block_id_t block_id_t;
    typedef transaction_commit_callback<config_t> transaction_commit_callback_t;
    typedef sync_callback<config_t> sync_callback_t;
    typedef std::pair<transaction_t *, transaction_commit_callback_t *>
        txn_state_t;

    enum state {
        state_none,
        state_locking,
        state_locked,
        state_write_bufs,
    };

	void start_flush_timer(void);
    static void timer_callback(void *ctx);
    virtual void on_lock_available();
    void writeback(buf_t *buf);

    /* User-controlled settings. */
    bool wait_for_flush;
    int interval_ms;

    /* Internal variables used at all times. */
    cache_t *cache;
    unsigned int num_txns;
    rwi_lock<config_t> *flush_lock;
    std::set<txn_state_t> txns;
    std::set<block_id_t> dirty_blocks;
    std::vector<sync_callback_t *> sync_callbacks;
    sync_callback_t *shutdown_callback;
    bool final_sync;

    /* Internal variables used only during a flush operation. */
    enum state state;
    transaction_t *transaction;
    std::set<txn_state_t> flush_txns;
    std::set<buf_t *> flush_bufs;
};

#include "buffer_cache/writeback/writeback_impl.hpp"

#endif // __buffer_cache_writeback_hpp__

<|endoftext|>


<commit_before>/******************************************************************************
  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "ModuleOutline.h"

#include "DataSource.h"
#include "pqProxiesWidget.h"
#include "Utilities.h"
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkSMParaViewPipelineControllerWithRendering.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMViewProxy.h"
#include "vtkSMProperty.h"

#include <QHBoxLayout>

namespace tomviz
{

ModuleOutline::ModuleOutline(QObject* parentObject) : Superclass(parentObject)
{
}

ModuleOutline::~ModuleOutline()
{
  this->finalize();
}

QIcon ModuleOutline::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqProbeLocation24.png");
}

bool ModuleOutline::initialize(DataSource* data,
                               vtkSMViewProxy* vtkView)
{
  if (!this->Superclass::initialize(data, vtkView))
  {
    return false;
  }

  vtkNew<vtkSMParaViewPipelineControllerWithRendering> controller;

  vtkSMSessionProxyManager* pxm = data->producer()->GetSessionProxyManager();

  // Create the outline filter.
  vtkSmartPointer<vtkSMProxy> proxy;
  proxy.TakeReference(pxm->NewProxy("filters", "OutlineFilter"));

  this->OutlineFilter = vtkSMSourceProxy::SafeDownCast(proxy);
  Q_ASSERT(this->OutlineFilter);
  controller->PreInitializeProxy(this->OutlineFilter);
  vtkSMPropertyHelper(this->OutlineFilter, "Input").Set(data->producer());
  controller->PostInitializeProxy(this->OutlineFilter);
  controller->RegisterPipelineProxy(this->OutlineFilter);

  // Create the representation for it.
  this->OutlineRepresentation = controller->Show(this->OutlineFilter, 0, vtkView);
  vtkSMPropertyHelper(this->OutlineRepresentation, "Position").Set(data->displayPosition(), 3);
  Q_ASSERT(this->OutlineRepresentation);
  //vtkSMPropertyHelper(this->OutlineRepresentation,
  //                    "Representation").Set("Outline");
  this->OutlineRepresentation->UpdateVTKObjects();
  return true;
}

bool ModuleOutline::finalize()
{
  vtkNew<vtkSMParaViewPipelineControllerWithRendering> controller;
  controller->UnRegisterProxy(this->OutlineRepresentation);
  controller->UnRegisterProxy(this->OutlineFilter);

  this->OutlineFilter = nullptr;
  this->OutlineRepresentation = nullptr;
  return true;
}

bool ModuleOutline::serialize(pugi::xml_node& ns) const
{
  // save stuff that the user can change.
  pugi::xml_node reprNode = ns.append_child("OutlineRepresentation");

  QStringList properties;
  properties << "Visibility" << "DiffuseColor";
  if (tomviz::serialize(this->OutlineRepresentation, reprNode, properties) == false)
  {
    qWarning("Failed to serialize ModuleOutline.");
    ns.remove_child(reprNode);
    return false;
  }
  return true;
}

bool ModuleOutline::deserialize(const pugi::xml_node& ns)
{
  return tomviz::deserialize(this->OutlineRepresentation,
                          ns.child("OutlineRepresentation"));
}

bool ModuleOutline::setVisibility(bool val)
{
  Q_ASSERT(this->OutlineRepresentation);
  vtkSMPropertyHelper(this->OutlineRepresentation,
                      "Visibility").Set(val ? 1 : 0);
  this->OutlineRepresentation->UpdateVTKObjects();
  return true;
}

bool ModuleOutline::visibility() const
{
  Q_ASSERT(this->OutlineRepresentation);
  return vtkSMPropertyHelper(this->OutlineRepresentation,
                             "Visibility").GetAsInt() != 0;
}

void ModuleOutline::addToPanel(QWidget* panel)
{
  Q_ASSERT(panel && this->OutlineRepresentation);

  if (panel->layout()) {
    delete panel->layout();
  }

  QHBoxLayout *layout = new QHBoxLayout;
  panel->setLayout(layout);
  pqProxiesWidget *proxiesWidget = new pqProxiesWidget(panel);
  layout->addWidget(proxiesWidget);

  QStringList properties;
  properties << "DiffuseColor";
  proxiesWidget->addProxy(
    this->OutlineRepresentation, "Annotations", properties, true);
  proxiesWidget->updateLayout();
}

void ModuleOutline::dataSourceMoved(double newX, double newY, double newZ)
{
  double pos[3] = {newX, newY, newZ};
  vtkSMPropertyHelper(this->OutlineRepresentation, "Position").Set(pos, 3);
  this->OutlineRepresentation->UpdateVTKObjects();
}

//-----------------------------------------------------------------------------
bool ModuleOutline::isProxyPartOfModule(vtkSMProxy *proxy)
{
  return (proxy == this->OutlineFilter.Get()) || (proxy == this->OutlineRepresentation.Get());
}

std::string ModuleOutline::getStringForProxy(vtkSMProxy *proxy)
{
  if (proxy == this->OutlineFilter.Get())
  {
    return "Outline";
  }
  else if (proxy == this->OutlineRepresentation.Get())
  {
    return "Representation";
  }
  else
  {
    qWarning("Unknown proxy passed to module outline in save animation");
    return "";
  }
}

vtkSMProxy *ModuleOutline::getProxyForString(const std::string& str)
{
  if (str == "Outline")
  {
    return this->OutlineFilter.Get();
  }
  else if (str == "Representation")
  {
    return this->OutlineRepresentation.Get();
  }
  else
  {
    return nullptr;
  }
}

} // end of namespace tomviz
<commit_msg>Change default outline color<commit_after>/******************************************************************************
  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "ModuleOutline.h"

#include "DataSource.h"
#include "pqProxiesWidget.h"
#include "Utilities.h"
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkSMParaViewPipelineControllerWithRendering.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMViewProxy.h"
#include "vtkSMProperty.h"

#include <QHBoxLayout>

namespace tomviz
{

ModuleOutline::ModuleOutline(QObject* parentObject) : Superclass(parentObject)
{
}

ModuleOutline::~ModuleOutline()
{
  this->finalize();
}

QIcon ModuleOutline::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqProbeLocation24.png");
}

bool ModuleOutline::initialize(DataSource* data,
                               vtkSMViewProxy* vtkView)
{
  if (!this->Superclass::initialize(data, vtkView))
  {
    return false;
  }

  vtkNew<vtkSMParaViewPipelineControllerWithRendering> controller;

  vtkSMSessionProxyManager* pxm = data->producer()->GetSessionProxyManager();

  // Create the outline filter.
  vtkSmartPointer<vtkSMProxy> proxy;
  proxy.TakeReference(pxm->NewProxy("filters", "OutlineFilter"));

  this->OutlineFilter = vtkSMSourceProxy::SafeDownCast(proxy);
  Q_ASSERT(this->OutlineFilter);
  controller->PreInitializeProxy(this->OutlineFilter);
  vtkSMPropertyHelper(this->OutlineFilter, "Input").Set(data->producer());
  controller->PostInitializeProxy(this->OutlineFilter);
  controller->RegisterPipelineProxy(this->OutlineFilter);

  // Create the representation for it.
  this->OutlineRepresentation = controller->Show(this->OutlineFilter, 0, vtkView);
  vtkSMPropertyHelper(this->OutlineRepresentation, "Position").Set(data->displayPosition(), 3);
  double offWhite[3] = { 204.0 / 255, 204.0 / 255, 204.0 / 255 };
  vtkSMPropertyHelper(this->OutlineRepresentation, "DiffuseColor").Set(offWhite, 3);
  Q_ASSERT(this->OutlineRepresentation);
  //vtkSMPropertyHelper(this->OutlineRepresentation,
  //                    "Representation").Set("Outline");
  this->OutlineRepresentation->UpdateVTKObjects();
  return true;
}

bool ModuleOutline::finalize()
{
  vtkNew<vtkSMParaViewPipelineControllerWithRendering> controller;
  controller->UnRegisterProxy(this->OutlineRepresentation);
  controller->UnRegisterProxy(this->OutlineFilter);

  this->OutlineFilter = nullptr;
  this->OutlineRepresentation = nullptr;
  return true;
}

bool ModuleOutline::serialize(pugi::xml_node& ns) const
{
  // save stuff that the user can change.
  pugi::xml_node reprNode = ns.append_child("OutlineRepresentation");

  QStringList properties;
  properties << "Visibility" << "DiffuseColor";
  if (tomviz::serialize(this->OutlineRepresentation, reprNode, properties) == false)
  {
    qWarning("Failed to serialize ModuleOutline.");
    ns.remove_child(reprNode);
    return false;
  }
  return true;
}

bool ModuleOutline::deserialize(const pugi::xml_node& ns)
{
  return tomviz::deserialize(this->OutlineRepresentation,
                          ns.child("OutlineRepresentation"));
}

bool ModuleOutline::setVisibility(bool val)
{
  Q_ASSERT(this->OutlineRepresentation);
  vtkSMPropertyHelper(this->OutlineRepresentation,
                      "Visibility").Set(val ? 1 : 0);
  this->OutlineRepresentation->UpdateVTKObjects();
  return true;
}

bool ModuleOutline::visibility() const
{
  Q_ASSERT(this->OutlineRepresentation);
  return vtkSMPropertyHelper(this->OutlineRepresentation,
                             "Visibility").GetAsInt() != 0;
}

void ModuleOutline::addToPanel(QWidget* panel)
{
  Q_ASSERT(panel && this->OutlineRepresentation);

  if (panel->layout()) {
    delete panel->layout();
  }

  QHBoxLayout *layout = new QHBoxLayout;
  panel->setLayout(layout);
  pqProxiesWidget *proxiesWidget = new pqProxiesWidget(panel);
  layout->addWidget(proxiesWidget);

  QStringList properties;
  properties << "DiffuseColor";
  proxiesWidget->addProxy(
    this->OutlineRepresentation, "Annotations", properties, true);
  proxiesWidget->updateLayout();
}

void ModuleOutline::dataSourceMoved(double newX, double newY, double newZ)
{
  double pos[3] = {newX, newY, newZ};
  vtkSMPropertyHelper(this->OutlineRepresentation, "Position").Set(pos, 3);
  this->OutlineRepresentation->UpdateVTKObjects();
}

//-----------------------------------------------------------------------------
bool ModuleOutline::isProxyPartOfModule(vtkSMProxy *proxy)
{
  return (proxy == this->OutlineFilter.Get()) || (proxy == this->OutlineRepresentation.Get());
}

std::string ModuleOutline::getStringForProxy(vtkSMProxy *proxy)
{
  if (proxy == this->OutlineFilter.Get())
  {
    return "Outline";
  }
  else if (proxy == this->OutlineRepresentation.Get())
  {
    return "Representation";
  }
  else
  {
    qWarning("Unknown proxy passed to module outline in save animation");
    return "";
  }
}

vtkSMProxy *ModuleOutline::getProxyForString(const std::string& str)
{
  if (str == "Outline")
  {
    return this->OutlineFilter.Get();
  }
  else if (str == "Representation")
  {
    return this->OutlineRepresentation.Get();
  }
  else
  {
    return nullptr;
  }
}

} // end of namespace tomviz
<|endoftext|>


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "WelcomeDialog.h"
#include "ui_WelcomeDialog.h"

#include "MainWindow.h"

#include <pqApplicationCore.h>
#include <pqSettings.h>

namespace tomviz
{

WelcomeDialog::WelcomeDialog(MainWindow* mw)
  : QDialog(mw),
    ui(new Ui::WelcomeDialog)
{
  ui->setupUi(this);
  this->connect(this->ui->doNotShowAgain, SIGNAL(stateChanged(int)),
                this, SLOT(onDoNotShowAgainStateChanged(int)));
  this->connect(this->ui->noButton, SIGNAL(clicked()),
                this, SLOT(hide()));
  this->connect(this->ui->yesButton, SIGNAL(clicked()),
                this, SLOT(onLoadSampleDataClicked()));
}

WelcomeDialog::~WelcomeDialog()
{
}

void WelcomeDialog::onLoadSampleDataClicked()
{
  MainWindow *mw = qobject_cast<MainWindow*>(this->parent());
  mw->openRecon();
  this->hide();
}

void WelcomeDialog::onDoNotShowAgainStateChanged(int state)
{
  bool showDialog = (state != Qt::Checked);

  QSettings* settings = pqApplicationCore::instance()->settings();
  settings->setValue("GeneralSettings.ShowWelcomeDialog", showDialog ? 1 : 0);
}
}
<commit_msg>Load sample data with volume module instead of orthoslice<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "WelcomeDialog.h"
#include "ui_WelcomeDialog.h"

#include "ActiveObjects.h"
#include "MainWindow.h"
#include "ModuleManager.h"

#include <pqApplicationCore.h>
#include <pqSettings.h>

namespace tomviz
{

WelcomeDialog::WelcomeDialog(MainWindow* mw)
  : QDialog(mw),
    ui(new Ui::WelcomeDialog)
{
  ui->setupUi(this);
  this->connect(this->ui->doNotShowAgain, SIGNAL(stateChanged(int)),
                this, SLOT(onDoNotShowAgainStateChanged(int)));
  this->connect(this->ui->noButton, SIGNAL(clicked()),
                this, SLOT(hide()));
  this->connect(this->ui->yesButton, SIGNAL(clicked()),
                this, SLOT(onLoadSampleDataClicked()));
}

WelcomeDialog::~WelcomeDialog()
{
}

void WelcomeDialog::onLoadSampleDataClicked()
{
  MainWindow *mw = qobject_cast<MainWindow*>(this->parent());
  mw->openRecon();
  ModuleManager &mm = ModuleManager::instance();
  ActiveObjects &ao = ActiveObjects::instance();
  // Remove the orthogonal slice that is automatically created
  mm.removeModule(ao.activeModule());
  // Add a volume module
  if (Module *module = mm.createAndAddModule("Volume", ao.activeDataSource(), ao.activeView()))
  {
    ao.setActiveModule(module);
  }
  this->hide();
}

void WelcomeDialog::onDoNotShowAgainStateChanged(int state)
{
  bool showDialog = (state != Qt::Checked);

  QSettings* settings = pqApplicationCore::instance()->settings();
  settings->setValue("GeneralSettings.ShowWelcomeDialog", showDialog ? 1 : 0);
}
}
<|endoftext|>


<commit_before>#ifndef HELPER_HXX
#define HELPER_HXX

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>

#include <opengm/inference/icm.hxx>
#include <opengm/inference/lazyflipper.hxx>
#include <opengm/learning/gridsearch-learning.hxx>
#include <opengm/inference/messagepassing/messagepassing.hxx>

#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif

#ifdef WITH_QPBO
#include <opengm/inference/external/qpbo.hxx>
#endif

#ifdef WITH_TRWS
#include <opengm/inference/external/trws.hxx>
#endif

namespace opengm{

template<class LEARNER>
class LearnerInferenceSuite: public boost::python::def_visitor<LearnerInferenceSuite<LEARNER> >{
public:
   friend class boost::python::def_visitor_access;

   LearnerInferenceSuite(){

   }

   template<class INF>
   static void pyLearnWithInf(LEARNER & learner, const typename INF::Parameter & param)
   {
       learner. template learn<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename LEARNER::GMType GMType;
       typedef typename LEARNER::Parameter PyLearnerParam;
       typedef typename LEARNER::DatasetType DatasetType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_TRWS
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_learn",&pyLearnWithInf<IcmInf>)
          .def("_learn",&pyLearnWithInf<LazyFlipperInf>)
          .def("_learn",&pyLearnWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_learn",&pyLearnWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_learn",&pyLearnWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_learn",&pyLearnWithInf<TrwsExternal>)
#endif
      ;
   }
};

template<class DS>
class DatasetInferenceSuite: public boost::python::def_visitor<DatasetInferenceSuite<DS> >{
public:
   friend class boost::python::def_visitor_access;

   DatasetInferenceSuite(){

   }

   template<class INF>
   typename DS::ValueType pyGetLossWithInf(DS & ds, const typename INF::Parameter & param, const size_t i)
   {
       return ds. template getLoss<INF>(param, i);
   }

   template<class INF>
   typename DS::ValueType pyGetTotalLossWithInf(DS & ds, const typename INF::Parameter & param)
   {
       return ds. template getTotalLoss<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename DS::GMType GMType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_getLoss",&pyGetLossWithInf<IcmInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<IcmInf>)
          .def("_getLoss",&pyGetLossWithInf<LazyFlipperInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<LazyFlipperInf>)
          .def("_getLoss",&pyGetLossWithInf<BpInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_getLoss",&pyGetLossWithInf<Cplex>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_getLoss",&pyGetLossWithInf<QpboExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_getLoss",&pyGetLossWithInf<TrwsExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<TrwsExternal>)
#endif
      ;
   }
};

} // namespace opengm

#endif // HELPER_HXX

<commit_msg>fix ifdef<commit_after>#ifndef HELPER_HXX
#define HELPER_HXX

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>

#include <opengm/inference/icm.hxx>
#include <opengm/inference/lazyflipper.hxx>
#include <opengm/learning/gridsearch-learning.hxx>
#include <opengm/inference/messagepassing/messagepassing.hxx>

#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif

#ifdef WITH_QPBO
#include <opengm/inference/external/qpbo.hxx>
#endif

#ifdef WITH_TRWS
#include <opengm/inference/external/trws.hxx>
#endif

namespace opengm{

template<class LEARNER>
class LearnerInferenceSuite: public boost::python::def_visitor<LearnerInferenceSuite<LEARNER> >{
public:
   friend class boost::python::def_visitor_access;

   LearnerInferenceSuite(){

   }

   template<class INF>
   static void pyLearnWithInf(LEARNER & learner, const typename INF::Parameter & param)
   {
       learner. template learn<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename LEARNER::GMType GMType;
       typedef typename LEARNER::Parameter PyLearnerParam;
       typedef typename LEARNER::DatasetType DatasetType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_TRWS
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_learn",&pyLearnWithInf<IcmInf>)
          .def("_learn",&pyLearnWithInf<LazyFlipperInf>)
          .def("_learn",&pyLearnWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_learn",&pyLearnWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_learn",&pyLearnWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_learn",&pyLearnWithInf<TrwsExternal>)
#endif
      ;
   }
};

template<class DS>
class DatasetInferenceSuite: public boost::python::def_visitor<DatasetInferenceSuite<DS> >{
public:
   friend class boost::python::def_visitor_access;

   DatasetInferenceSuite(){

   }

   template<class INF>
   typename DS::ValueType pyGetLossWithInf(DS & ds, const typename INF::Parameter & param, const size_t i)
   {
       return ds. template getLoss<INF>(param, i);
   }

   template<class INF>
   typename DS::ValueType pyGetTotalLossWithInf(DS & ds, const typename INF::Parameter & param)
   {
       return ds. template getTotalLoss<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename DS::GMType GMType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_TRWS
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_getLoss",&pyGetLossWithInf<IcmInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<IcmInf>)
          .def("_getLoss",&pyGetLossWithInf<LazyFlipperInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<LazyFlipperInf>)
          .def("_getLoss",&pyGetLossWithInf<BpInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_getLoss",&pyGetLossWithInf<Cplex>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_getLoss",&pyGetLossWithInf<QpboExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_getLoss",&pyGetLossWithInf<TrwsExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<TrwsExternal>)
#endif
      ;
   }
};

} // namespace opengm

#endif // HELPER_HXX

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "uart.h"
#include "Globals.h"
#include "World.h"
#include "Train.h"
#include "Logs.h"

uart_input::uart_input()
{
    conf = Global::uart_conf;

    if (sp_get_port_by_name(conf.port.c_str(), &port) != SP_OK)
        throw std::runtime_error("uart: cannot find specified port");

    if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK)
        throw std::runtime_error("uart: cannot open port");

	sp_port_config *config;

    if (sp_new_config(&config) != SP_OK ||
		sp_set_config_baudrate(config, conf.baud) != SP_OK ||
		sp_set_config_flowcontrol(config, SP_FLOWCONTROL_NONE) != SP_OK ||
		sp_set_config_bits(config, 8) != SP_OK ||
		sp_set_config_stopbits(config, 1) != SP_OK ||
		sp_set_config_parity(config, SP_PARITY_NONE) != SP_OK ||
		sp_set_config(port, config) != SP_OK)
        throw std::runtime_error("uart: cannot set config");

	sp_free_config(config);

    if (sp_flush(port, SP_BUF_BOTH) != SP_OK)
        throw std::runtime_error("uart: cannot flush");

    old_packet.fill(0);
    last_update = std::chrono::high_resolution_clock::now();
}

uart_input::~uart_input()
{
    sp_close(port);
    sp_free_port(port);
}

#define SPLIT_INT16(x) (uint8_t)x, (uint8_t)(x >> 8)

void uart_input::poll()
{
    auto now = std::chrono::high_resolution_clock::now();
    if (std::chrono::duration<float>(now - last_update).count() < conf.updatetime)
        return;
    last_update = now;

    TTrain *t = Global::pWorld->train();
	if (!t)
		return;

    sp_return ret;

    if ((ret = sp_input_waiting(port)) >= 16)
    {
        std::array<uint8_t, 16> buffer;
        ret = sp_blocking_read(port, (void*)buffer.data(), buffer.size(), 0);
		if (ret < 0)
            throw std::runtime_error("uart: failed to read from port");

		if (conf.debug)
		{
			char buf[buffer.size() * 3 + 1];
			size_t pos = 0;
			for (uint8_t b : buffer)
				pos += sprintf(&buf[pos], "%02X ", b);
			WriteLog("uart: rx: " + std::string(buf));
		}

		data_pending = false;

        for (auto entry : input_bits)
        {
            input_type_t type = std::get<2>(entry);

            size_t byte = std::get<0>(entry) / 8;
            size_t bit = std::get<0>(entry) % 8;

            bool state = (bool)(buffer[byte] & (1 << bit));

			bool repeat = (type == impulse_r ||
			               type == impulse_r_off ||
			               type == impulse_r_on);

			bool changed = (state != (bool)(old_packet[byte] & (1 << bit)));

            if (!changed && !(repeat && state))
                continue;

            int action;
            command_data::desired_state_t desired_state;

            if (type == toggle)
            {
                action = GLFW_PRESS;
                desired_state = state ? command_data::ON : command_data::OFF;
            }
            else if (type == impulse_r_on)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::ON;
            }
            else if (type == impulse_r_off)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::OFF;
            }
            else if (type == impulse || type == impulse_r)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::TOGGLE;
            }

            relay.post(std::get<1>(entry), 0, 0, action, 0, desired_state);
        }

		if (conf.mainenable)
	        t->set_mainctrl(buffer[6]);
		if (conf.scndenable)
	        t->set_scndctrl(buffer[7]);
		if (conf.trainenable)
	        t->set_trainbrake((float)(((uint16_t)buffer[8] | ((uint16_t)buffer[9] << 8)) - conf.mainbrakemin) / (conf.mainbrakemax - conf.mainbrakemin));
		if (conf.localenable)
	        t->set_localbrake((float)(((uint16_t)buffer[10] | ((uint16_t)buffer[11] << 8)) - conf.mainbrakemin) / (conf.localbrakemax - conf.localbrakemin));

        old_packet = buffer;
    }

	if (!data_pending && sp_output_waiting(port) == 0)
	{
	    // TODO: ugly! move it into structure like input_bits

	    uint8_t buzzer = (uint8_t)t->get_alarm();
	    uint8_t tacho = (uint8_t)t->get_tacho();
	    uint16_t tank_press = (uint16_t)std::min(conf.tankuart, t->get_tank_pressure() / conf.tankmax * conf.tankuart);
	    uint16_t pipe_press = (uint16_t)std::min(conf.pipeuart, t->get_pipe_pressure() / conf.pipemax * conf.pipeuart);
	    uint16_t brake_press = (uint16_t)std::min(conf.brakeuart, t->get_brake_pressure() / conf.brakemax * conf.brakeuart);
	    uint16_t hv_voltage = (uint16_t)std::min(conf.hvuart, t->get_hv_voltage() / conf.hvmax * conf.hvuart);
	    auto current = t->get_current();
	    uint16_t current1 = (uint16_t)std::min(conf.currentuart, current[0]) / conf.currentmax * conf.currentuart;
	    uint16_t current2 = (uint16_t)std::min(conf.currentuart, current[1]) / conf.currentmax * conf.currentuart;
	    uint16_t current3 = (uint16_t)std::min(conf.currentuart, current[2]) / conf.currentmax * conf.currentuart;

	    std::array<uint8_t, 31> buffer =
	    {
	        0, 0, //byte 0-1
			tacho, //byte 2
	        0, 0, 0, 0, 0, 0, //byte 3-8
	        SPLIT_INT16(brake_press), //byte 9-10
	        SPLIT_INT16(pipe_press), //byte 11-12
	        SPLIT_INT16(tank_press), //byte 13-14
	        SPLIT_INT16(hv_voltage), //byte 15-16
	        SPLIT_INT16(current1), //byte 17-18
	        SPLIT_INT16(current2), //byte 19-20
	        SPLIT_INT16(current3), //byte 21-22
			0, 0, 0, 0, 0, 0, 0, 0 //byte 23-30
	    };

	    buffer[4] |= t->btLampkaOpory.b() << 1;
	    buffer[4] |= t->btLampkaWysRozr.b() << 2;

	    buffer[6] |= t->btLampkaOgrzewanieSkladu.b() << 0;
	    buffer[6] |= t->btLampkaOpory.b() << 1;
	    buffer[6] |= t->btLampkaPoslizg.b() << 2;
	    buffer[6] |= t->btLampkaCzuwaka.b() << 6;
	    buffer[6] |= t->btLampkaSHP.b() << 7;

	    buffer[7] |= t->btLampkaStyczn.b() << 0;
	    buffer[7] |= t->btLampkaNadmPrzetw.b() << 2;
	    buffer[7] |= t->btLampkaNadmSil.b() << 4;
	    buffer[7] |= t->btLampkaWylSzybki.b() << 5;
	    buffer[7] |= t->btLampkaNadmSpr.b() << 6;

	    buffer[8] |= buzzer << 7;

		if (conf.debug)
		{
			char buf[buffer.size() * 3 + 1];
			size_t pos = 0;
			for (uint8_t b : buffer)
				pos += sprintf(&buf[pos], "%02X ", b);
			WriteLog("uart: tx: " + std::string(buf));
		}

	    ret = sp_blocking_write(port, (void*)buffer.data(), buffer.size(), 0);
	    if (ret != buffer.size())
			throw std::runtime_error("uart: failed to write to port");

		data_pending = true;
	}
}
<commit_msg>uart pressure changes<commit_after>#include "stdafx.h"
#include "uart.h"
#include "Globals.h"
#include "World.h"
#include "Train.h"
#include "Logs.h"

uart_input::uart_input()
{
    conf = Global::uart_conf;

    if (sp_get_port_by_name(conf.port.c_str(), &port) != SP_OK)
        throw std::runtime_error("uart: cannot find specified port");

    if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK)
        throw std::runtime_error("uart: cannot open port");

	sp_port_config *config;

    if (sp_new_config(&config) != SP_OK ||
		sp_set_config_baudrate(config, conf.baud) != SP_OK ||
		sp_set_config_flowcontrol(config, SP_FLOWCONTROL_NONE) != SP_OK ||
		sp_set_config_bits(config, 8) != SP_OK ||
		sp_set_config_stopbits(config, 1) != SP_OK ||
		sp_set_config_parity(config, SP_PARITY_NONE) != SP_OK ||
		sp_set_config(port, config) != SP_OK)
        throw std::runtime_error("uart: cannot set config");

	sp_free_config(config);

    if (sp_flush(port, SP_BUF_BOTH) != SP_OK)
        throw std::runtime_error("uart: cannot flush");

    old_packet.fill(0);
    last_update = std::chrono::high_resolution_clock::now();
}

uart_input::~uart_input()
{
    sp_close(port);
    sp_free_port(port);
}

#define SPLIT_INT16(x) (uint8_t)x, (uint8_t)(x >> 8)

void uart_input::poll()
{
    auto now = std::chrono::high_resolution_clock::now();
    if (std::chrono::duration<float>(now - last_update).count() < conf.updatetime)
        return;
    last_update = now;

    TTrain *t = Global::pWorld->train();
	if (!t)
		return;

    sp_return ret;

    if ((ret = sp_input_waiting(port)) >= 16)
    {
        std::array<uint8_t, 16> buffer;
        ret = sp_blocking_read(port, (void*)buffer.data(), buffer.size(), 0);
		if (ret < 0)
            throw std::runtime_error("uart: failed to read from port");

		if (conf.debug)
		{
			char buf[buffer.size() * 3 + 1];
			size_t pos = 0;
			for (uint8_t b : buffer)
				pos += sprintf(&buf[pos], "%02X ", b);
			WriteLog("uart: rx: " + std::string(buf));
		}

		data_pending = false;

        for (auto entry : input_bits)
        {
            input_type_t type = std::get<2>(entry);

            size_t byte = std::get<0>(entry) / 8;
            size_t bit = std::get<0>(entry) % 8;

            bool state = (bool)(buffer[byte] & (1 << bit));

			bool repeat = (type == impulse_r ||
			               type == impulse_r_off ||
			               type == impulse_r_on);

			bool changed = (state != (bool)(old_packet[byte] & (1 << bit)));

            if (!changed && !(repeat && state))
                continue;

            int action;
            command_data::desired_state_t desired_state;

            if (type == toggle)
            {
                action = GLFW_PRESS;
                desired_state = state ? command_data::ON : command_data::OFF;
            }
            else if (type == impulse_r_on)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::ON;
            }
            else if (type == impulse_r_off)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::OFF;
            }
            else if (type == impulse || type == impulse_r)
            {
                action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE;
                desired_state = command_data::TOGGLE;
            }

            relay.post(std::get<1>(entry), 0, 0, action, 0, desired_state);
        }

		if (conf.mainenable)
	        t->set_mainctrl(buffer[6]);
		if (conf.scndenable)
	        t->set_scndctrl(buffer[7]);
		if (conf.trainenable)
	        t->set_trainbrake((float)(((uint16_t)buffer[8] | ((uint16_t)buffer[9] << 8)) - conf.mainbrakemin) / (conf.mainbrakemax - conf.mainbrakemin));
		if (conf.localenable)
	        t->set_localbrake((float)(((uint16_t)buffer[10] | ((uint16_t)buffer[11] << 8)) - conf.mainbrakemin) / (conf.localbrakemax - conf.localbrakemin));

        old_packet = buffer;
    }

	if (!data_pending && sp_output_waiting(port) == 0)
	{
	    // TODO: ugly! move it into structure like input_bits

	    uint8_t buzzer = (uint8_t)t->get_alarm();
	    uint8_t tacho = (uint8_t)t->get_tacho();
	    uint16_t tank_press = (uint16_t)std::min(conf.tankuart, t->get_tank_pressure() * 0.1f / conf.tankmax * conf.tankuart);
	    uint16_t pipe_press = (uint16_t)std::min(conf.pipeuart, t->get_pipe_pressure() * 0.1f / conf.pipemax * conf.pipeuart);
	    uint16_t brake_press = (uint16_t)std::min(conf.brakeuart, t->get_brake_pressure() * 0.1f / conf.brakemax * conf.brakeuart);
	    uint16_t hv_voltage = (uint16_t)std::min(conf.hvuart, t->get_hv_voltage() / conf.hvmax * conf.hvuart);
	    auto current = t->get_current();
	    uint16_t current1 = (uint16_t)std::min(conf.currentuart, current[0]) / conf.currentmax * conf.currentuart;
	    uint16_t current2 = (uint16_t)std::min(conf.currentuart, current[1]) / conf.currentmax * conf.currentuart;
	    uint16_t current3 = (uint16_t)std::min(conf.currentuart, current[2]) / conf.currentmax * conf.currentuart;

	    std::array<uint8_t, 31> buffer =
	    {
	        0, 0, //byte 0-1
			tacho, //byte 2
	        0, 0, 0, 0, 0, 0, //byte 3-8
	        SPLIT_INT16(brake_press), //byte 9-10
	        SPLIT_INT16(pipe_press), //byte 11-12
	        SPLIT_INT16(tank_press), //byte 13-14
	        SPLIT_INT16(hv_voltage), //byte 15-16
	        SPLIT_INT16(current1), //byte 17-18
	        SPLIT_INT16(current2), //byte 19-20
	        SPLIT_INT16(current3), //byte 21-22
			0, 0, 0, 0, 0, 0, 0, 0 //byte 23-30
	    };

	    buffer[4] |= t->btLampkaOpory.b() << 1;
	    buffer[4] |= t->btLampkaWysRozr.b() << 2;

	    buffer[6] |= t->btLampkaOgrzewanieSkladu.b() << 0;
	    buffer[6] |= t->btLampkaOpory.b() << 1;
	    buffer[6] |= t->btLampkaPoslizg.b() << 2;
	    buffer[6] |= t->btLampkaCzuwaka.b() << 6;
	    buffer[6] |= t->btLampkaSHP.b() << 7;

	    buffer[7] |= t->btLampkaStyczn.b() << 0;
	    buffer[7] |= t->btLampkaNadmPrzetw.b() << 2;
	    buffer[7] |= t->btLampkaNadmSil.b() << 4;
	    buffer[7] |= t->btLampkaWylSzybki.b() << 5;
	    buffer[7] |= t->btLampkaNadmSpr.b() << 6;

	    buffer[8] |= buzzer << 7;

		if (conf.debug)
		{
			char buf[buffer.size() * 3 + 1];
			size_t pos = 0;
			for (uint8_t b : buffer)
				pos += sprintf(&buf[pos], "%02X ", b);
			WriteLog("uart: tx: " + std::string(buf));
		}

	    ret = sp_blocking_write(port, (void*)buffer.data(), buffer.size(), 0);
	    if (ret != buffer.size())
			throw std::runtime_error("uart: failed to write to port");

		data_pending = true;
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/accelerators/accelerator_controller.h"

#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_model.h"
#include "ash/screenshot_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/window_util.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/accelerator_manager.h"
#include "ui/gfx/compositor/debug_utils.h"
#include "ui/gfx/compositor/layer_animation_sequence.h"
#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/compositor/screen_rotation.h"

namespace {

enum AcceleratorAction {
  CYCLE_BACKWARD,
  CYCLE_FORWARD,
  TAKE_SCREENSHOT,
#if !defined(NDEBUG)
  ROTATE_SCREEN,
  PRINT_LAYER_HIERARCHY,
  TOGGLE_ROOT_WINDOW_FULL_SCREEN,
#endif
};

// Accelerators handled by AcceleratorController.
struct AcceleratorData {
  ui::KeyboardCode keycode;
  bool shift;
  bool ctrl;
  bool alt;
  AcceleratorAction action;
} kAcceleratorData[] = {
  { ui::VKEY_TAB, true, false, true, CYCLE_BACKWARD },
  { ui::VKEY_TAB, false, false, true, CYCLE_FORWARD },
  { ui::VKEY_F5, false, false, false, CYCLE_FORWARD },
  { ui::VKEY_F5, false, true, false, TAKE_SCREENSHOT },
  { ui::VKEY_PRINT, false, false, false, TAKE_SCREENSHOT },
#if !defined(NDEBUG)
  { ui::VKEY_HOME, false, true, false, ROTATE_SCREEN },
  { ui::VKEY_F11, false, true, false, TOGGLE_ROOT_WINDOW_FULL_SCREEN },
  { ui::VKEY_L, false, false, true, PRINT_LAYER_HIERARCHY },
#endif
};

bool HandleCycleWindow(bool forward) {
  if (ash::Shell::GetInstance()->IsScreenLocked())
    return false;

  // Use the same order of the windows in LauncherModel to cycle windows.
  ash::LauncherModel* model =
      ash::Shell::GetInstance()->launcher()->model();
  aura::Window* active_window = ash::GetActiveWindow();
  if (!active_window) {
    LOG(ERROR) << "No active window";
    return false;
  }
  int active_index = model->ItemIndexByWindow(active_window);
  if (active_index < 0) {
    VLOG(2) << "Active window not found in the launcher model";
    return false;
  }
  int next_index = (active_index + (forward ? 1 : -1) + model->item_count()) %
      model->item_count();
  ash::ActivateWindow(model->items()[next_index].window);
  return true;
}

#if !defined(NDEBUG)
// Rotates the screen.
bool HandleRotateScreen() {
  static int i = 0;
  int delta = 0;
  switch (i) {
    case 0: delta = 90; break;
    case 1: delta = 90; break;
    case 2: delta = 90; break;
    case 3: delta = 90; break;
    case 4: delta = -90; break;
    case 5: delta = -90; break;
    case 6: delta = -90; break;
    case 7: delta = -90; break;
    case 8: delta = -90; break;
    case 9: delta = 180; break;
    case 10: delta = 180; break;
    case 11: delta = 90; break;
    case 12: delta = 180; break;
    case 13: delta = 180; break;
  }
  i = (i + 1) % 14;
  aura::RootWindow::GetInstance()->layer()->GetAnimator()->
      set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
      new ui::LayerAnimationSequence(new ui::ScreenRotation(delta)));
  screen_rotation->AddObserver(aura::RootWindow::GetInstance());
  aura::RootWindow::GetInstance()->layer()->GetAnimator()->StartAnimation(
      screen_rotation.release());
  return true;
}

bool HandleToggleRootWindowFullScreen() {
  aura::RootWindow::GetInstance()->ToggleFullScreen();
  return true;
}

bool HandlePrintLayerHierarchy() {
  aura::RootWindow* root_window = aura::RootWindow::GetInstance();
  ui::PrintLayerHierarchy(root_window->layer(),
                          root_window->last_mouse_location());
  return true;
}
#endif

}  // namespace

namespace ash {

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, public:

AcceleratorController::AcceleratorController()
    : accelerator_manager_(new ui::AcceleratorManager) {
  Init();
}

AcceleratorController::~AcceleratorController() {
}

void AcceleratorController::Init() {
  for (size_t i = 0; i < arraysize(kAcceleratorData); ++i) {
    ui::Accelerator accelerator(kAcceleratorData[i].keycode,
                                kAcceleratorData[i].shift,
                                kAcceleratorData[i].ctrl,
                                kAcceleratorData[i].alt);
    Register(accelerator, this);
    accelerators_.insert(std::make_pair(accelerator,
                                        kAcceleratorData[i].action));
  }
}

void AcceleratorController::Register(
    const ui::Accelerator& accelerator,
    ui::AcceleratorTarget* target) {
  accelerator_manager_->Register(accelerator, target);
}

void AcceleratorController::Unregister(
    const ui::Accelerator& accelerator,
    ui::AcceleratorTarget* target) {
  accelerator_manager_->Unregister(accelerator, target);
}

void AcceleratorController::UnregisterAll(
    ui::AcceleratorTarget* target) {
  accelerator_manager_->UnregisterAll(target);
}

bool AcceleratorController::Process(const ui::Accelerator& accelerator) {
  return accelerator_manager_->Process(accelerator);
}

void AcceleratorController::SetScreenshotDelegate(
    ScreenshotDelegate* screenshot_delegate) {
  screenshot_delegate_.reset(screenshot_delegate);
}

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, ui::AcceleratorTarget implementation:

bool AcceleratorController::AcceleratorPressed(
    const ui::Accelerator& accelerator) {
  std::map<ui::Accelerator, int>::const_iterator it =
      accelerators_.find(accelerator);
  DCHECK(it != accelerators_.end());
  switch (static_cast<AcceleratorAction>(it->second)) {
    case CYCLE_BACKWARD:
      return HandleCycleWindow(false);
    case CYCLE_FORWARD:
      return HandleCycleWindow(true);
    case TAKE_SCREENSHOT:
      if (screenshot_delegate_.get())
        screenshot_delegate_->HandleTakeScreenshot();
      // Return true to prevent propagation of the key event.
      return true;
#if !defined(NDEBUG)
    case ROTATE_SCREEN:
      return HandleRotateScreen();
    case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
      return HandleToggleRootWindowFullScreen();
    case PRINT_LAYER_HIERARCHY:
      return HandlePrintLayerHierarchy();
#endif
    default:
      NOTREACHED() << "Unhandled action " << it->second;;
  }
  return false;
}

bool AcceleratorController::CanHandleAccelerators() const {
  return true;
}

}  // namespace ash
<commit_msg>Aura: Fix crash when user hits alt-tab in compact window mode<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/accelerators/accelerator_controller.h"

#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_model.h"
#include "ash/screenshot_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/window_util.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/accelerator_manager.h"
#include "ui/gfx/compositor/debug_utils.h"
#include "ui/gfx/compositor/layer_animation_sequence.h"
#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/compositor/screen_rotation.h"

namespace {

enum AcceleratorAction {
  CYCLE_BACKWARD,
  CYCLE_FORWARD,
  TAKE_SCREENSHOT,
#if !defined(NDEBUG)
  ROTATE_SCREEN,
  PRINT_LAYER_HIERARCHY,
  TOGGLE_ROOT_WINDOW_FULL_SCREEN,
#endif
};

// Accelerators handled by AcceleratorController.
struct AcceleratorData {
  ui::KeyboardCode keycode;
  bool shift;
  bool ctrl;
  bool alt;
  AcceleratorAction action;
} kAcceleratorData[] = {
  { ui::VKEY_TAB, true, false, true, CYCLE_BACKWARD },
  { ui::VKEY_TAB, false, false, true, CYCLE_FORWARD },
  { ui::VKEY_F5, false, false, false, CYCLE_FORWARD },
  { ui::VKEY_F5, false, true, false, TAKE_SCREENSHOT },
  { ui::VKEY_PRINT, false, false, false, TAKE_SCREENSHOT },
#if !defined(NDEBUG)
  { ui::VKEY_HOME, false, true, false, ROTATE_SCREEN },
  { ui::VKEY_F11, false, true, false, TOGGLE_ROOT_WINDOW_FULL_SCREEN },
  { ui::VKEY_L, false, false, true, PRINT_LAYER_HIERARCHY },
#endif
};

bool HandleCycleWindow(bool forward) {
  if (ash::Shell::GetInstance()->IsScreenLocked())
    return false;

  // We don't have a launcher in Aura compact window mode.
  // TODO(jamescook): Eliminate this check and rework this function to cycle
  // through most-recently-used browser windows. We may need to always
  // instantiate the launcher and hide its widget, or more likely we should
  // provide an interface to access BrowserList. crbug.com/109193
  if (!ash::Shell::GetInstance()->launcher())
    return false;

  // Use the same order of the windows in LauncherModel to cycle windows.
  ash::LauncherModel* model =
      ash::Shell::GetInstance()->launcher()->model();
  aura::Window* active_window = ash::GetActiveWindow();
  if (!active_window) {
    LOG(ERROR) << "No active window";
    return false;
  }
  int active_index = model->ItemIndexByWindow(active_window);
  if (active_index < 0) {
    VLOG(2) << "Active window not found in the launcher model";
    return false;
  }
  int next_index = (active_index + (forward ? 1 : -1) + model->item_count()) %
      model->item_count();
  ash::ActivateWindow(model->items()[next_index].window);
  return true;
}

#if !defined(NDEBUG)
// Rotates the screen.
bool HandleRotateScreen() {
  static int i = 0;
  int delta = 0;
  switch (i) {
    case 0: delta = 90; break;
    case 1: delta = 90; break;
    case 2: delta = 90; break;
    case 3: delta = 90; break;
    case 4: delta = -90; break;
    case 5: delta = -90; break;
    case 6: delta = -90; break;
    case 7: delta = -90; break;
    case 8: delta = -90; break;
    case 9: delta = 180; break;
    case 10: delta = 180; break;
    case 11: delta = 90; break;
    case 12: delta = 180; break;
    case 13: delta = 180; break;
  }
  i = (i + 1) % 14;
  aura::RootWindow::GetInstance()->layer()->GetAnimator()->
      set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
      new ui::LayerAnimationSequence(new ui::ScreenRotation(delta)));
  screen_rotation->AddObserver(aura::RootWindow::GetInstance());
  aura::RootWindow::GetInstance()->layer()->GetAnimator()->StartAnimation(
      screen_rotation.release());
  return true;
}

bool HandleToggleRootWindowFullScreen() {
  aura::RootWindow::GetInstance()->ToggleFullScreen();
  return true;
}

bool HandlePrintLayerHierarchy() {
  aura::RootWindow* root_window = aura::RootWindow::GetInstance();
  ui::PrintLayerHierarchy(root_window->layer(),
                          root_window->last_mouse_location());
  return true;
}
#endif

}  // namespace

namespace ash {

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, public:

AcceleratorController::AcceleratorController()
    : accelerator_manager_(new ui::AcceleratorManager) {
  Init();
}

AcceleratorController::~AcceleratorController() {
}

void AcceleratorController::Init() {
  for (size_t i = 0; i < arraysize(kAcceleratorData); ++i) {
    ui::Accelerator accelerator(kAcceleratorData[i].keycode,
                                kAcceleratorData[i].shift,
                                kAcceleratorData[i].ctrl,
                                kAcceleratorData[i].alt);
    Register(accelerator, this);
    accelerators_.insert(std::make_pair(accelerator,
                                        kAcceleratorData[i].action));
  }
}

void AcceleratorController::Register(
    const ui::Accelerator& accelerator,
    ui::AcceleratorTarget* target) {
  accelerator_manager_->Register(accelerator, target);
}

void AcceleratorController::Unregister(
    const ui::Accelerator& accelerator,
    ui::AcceleratorTarget* target) {
  accelerator_manager_->Unregister(accelerator, target);
}

void AcceleratorController::UnregisterAll(
    ui::AcceleratorTarget* target) {
  accelerator_manager_->UnregisterAll(target);
}

bool AcceleratorController::Process(const ui::Accelerator& accelerator) {
  return accelerator_manager_->Process(accelerator);
}

void AcceleratorController::SetScreenshotDelegate(
    ScreenshotDelegate* screenshot_delegate) {
  screenshot_delegate_.reset(screenshot_delegate);
}

////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, ui::AcceleratorTarget implementation:

bool AcceleratorController::AcceleratorPressed(
    const ui::Accelerator& accelerator) {
  std::map<ui::Accelerator, int>::const_iterator it =
      accelerators_.find(accelerator);
  DCHECK(it != accelerators_.end());
  switch (static_cast<AcceleratorAction>(it->second)) {
    case CYCLE_BACKWARD:
      return HandleCycleWindow(false);
    case CYCLE_FORWARD:
      return HandleCycleWindow(true);
    case TAKE_SCREENSHOT:
      if (screenshot_delegate_.get())
        screenshot_delegate_->HandleTakeScreenshot();
      // Return true to prevent propagation of the key event.
      return true;
#if !defined(NDEBUG)
    case ROTATE_SCREEN:
      return HandleRotateScreen();
    case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
      return HandleToggleRootWindowFullScreen();
    case PRINT_LAYER_HIERARCHY:
      return HandlePrintLayerHierarchy();
#endif
    default:
      NOTREACHED() << "Unhandled action " << it->second;;
  }
  return false;
}

bool AcceleratorController::CanHandleAccelerators() const {
  return true;
}

}  // namespace ash
<|endoftext|>


<commit_before>/** @file
 *
 * Client/server program for the drive test.
 */
#include <cstdio>
#include "Chassis_Control/DriveData.h"

/* Manually disable client mode on ARM machines (e.g. the Raspberry Pi, which
   gives us enough grief anyway... */
#if defined(__arm__) && ! defined(DISABLE_CLIENT)
# define DISABLE_CLIENT 1
#endif

/* ****************************************************************
 * Help text stuff.
 */
#if ! defined(DISABLE_CLIENT)
#  define PRINT_USAGE(stream) fprintf(stream, "Usage: %s [OPTION]... ADDRESS PORT [EVDEV]\n", argv[0])

#  define HELP_TEXT "\
Simple controls-test program.\n\
\n\
Options:\n\
  -h	Show this help.\n\
\n\
Client mode is assumed when EVDEV argument is present; otherwise server mode is\n\
enabled.\n"
#else
#  define PRINT_USAGE(stream) fprintf(stream, "Usage: %s [OPTION]... ADDRESS PORT\n", argv[0])
#  define HELP_TEXT "\
Simple controls-test program: server-only build.\n\
\n\
Options:\n\
  -h	Show this help.\n\
\n"
#endif  /* ! defined(DISABLE_CLIENT) */
/* **************************************************************** */

#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/signal_set.hpp>
#include <crisp/comms/BasicNode.hh>
#include <crisp/comms/NodeServer.hh>

/* Define some aliases for our communication-types for convenience. */
using namespace crisp::comms;
typedef BasicNode<boost::asio::ip::tcp> Node;
typedef typename Node::Protocol Protocol;
typedef typename Protocol::endpoint Endpoint;

#include "gnublin_i2c.hpp"

#define I2C_BUS "/dev/i2c-1"
#define I2C_SLAVE_ADDRESS 4

static int
run_server(boost::asio::io_service& service,
           const Endpoint& target_endpoint)

{
  crisp::comms::NodeServer<Node> server ( service, target_endpoint, 0, 1 );

  gnublin_i2c i2c ( I2C_BUS, I2C_SLAVE_ADDRESS );

  /* I don't trust this "Gnublin" code (it's terribly written and I had to fix
     it to even get it to compile).   We'll be replacing it eventually. */
  i2c.setDevicefile(I2C_BUS);
  i2c.setAddress(I2C_SLAVE_ADDRESS);

  if ( i2c.fail() )             /* Won't happen because the Gnublin stuff opens
                                   the device on-demand.  /Le sigh.../ */
    return 1;

  DriveData data;
  unsigned char* data_pointer = reinterpret_cast<unsigned char*>(&data);
  memset(data_pointer, 0, sizeof(data));

  using namespace crisp::comms::keywords;

  /* Declare our interface configuration. */
  server.configuration.add_module( "drive", 2)
    .add_input<int8_t>({ "left",  { _neutral = 0, _minimum = -127, _maximum = 128 } })
    .add_input<int8_t>({ "right", { _neutral = 0, _minimum = -127, _maximum = 128 } });

  /* Override the handler run when we receive a module-control packet. */
  server.dispatcher.module_control.received.clear();
  server.dispatcher.module_control.received.connect(
    [&](Node& node, const crisp::comms::ModuleControl& mc)
    {
      if ( isatty(STDERR_FILENO) )
        fprintf(stderr, "[0x%0x] \033[1;33mModule-control received\033[0m: ", THREAD_ID);
      else
        fprintf(stderr, "[0x%0x] Module-control received:", THREAD_ID);

      const crisp::comms::DataValue<> *dvl ( nullptr ), *dvr ( nullptr );

      /* Update our input-value array. */
      if ( (dvl = mc.value_for("left")) != nullptr )
        {
          data.left_motor = dvl->get<int8_t>();
          fprintf(stderr, "%d", data.left_motor);
        }
      dvr = mc.value_for("right");

      if ( dvl && dvr )
        fputs(", ", stderr);

      if ( dvr )
        {
          data.right_motor = dvr->get<int8_t>();
          fprintf(stderr, "%d\n", data.right_motor);
        }

      /* This call here is just so EW EW EW EW EW.  There's a reason for it, of
         course, but that reason is irrelevant with the way we're using I2C. */
      i2c.send(data_pointer, sizeof(data));

      if ( i2c.fail() )
        {
          perror("write");
        }
    });

  server.run();
  return 0;
}

/* Disable client functionality on the Raspberry Pi.

   _With_ this code (and using the old controller code based on the
   terribly-bloated Boost.Signals2 library), I had trouble getting the program
   to compile on the Pi without running out of memory.

   We don't need to support client mode on the Pi, so we might as well keep it
   disabled anyway.
 */
#if ! defined(DISABLE_CLIENT)

#include <crisp/input/EvDevController.hh>
#include <float.h>

/** Update a ModuleControl instance to reflect the input coordinates.
 *
 * @param mc ModuleControl to update.
 *
 * @param left Value of left stick y axis.
 *
 * @param right Value of right stick y axis.
 *
 */
void
update_control(crisp::comms::ModuleControl& mc,
               int left, int right)
{
  left = left > SCHAR_MAX ? SCHAR_MAX : left;
  left = left < SCHAR_MIN ? SCHAR_MIN : left;
  right = right > SCHAR_MAX ? SCHAR_MAX : right;
  right = right < SCHAR_MIN ? SCHAR_MIN : right;

  mc.set<int8_t>("left", left);
  mc.set<int8_t>("right", right);
}

/** Run the client code, connecting to the specified endpoint and taking input
 *  from the specified Linux `evdev` input device.
 */
static int
run_client(boost::asio::io_service& service,
           const Endpoint& target_endpoint,
           const char* evdev)
{
  /* Create a socket, and try to connect it to the specified endpoint. */
  boost::system::error_code ec;
  typename Protocol::socket socket ( service );
  typename Protocol::resolver resolver ( service );

  boost::asio::connect(socket, resolver.resolve(target_endpoint), ec);

  if ( ec )
    { fprintf(stderr, "connect: %s\n", strerror(ec.value()));
      return 1; }
  else
    {
      /* We're going to be modifying the ModuleControl instance on-demand
         (whenever the input controller changes state), but sending it at a
         fixed rate.  Since this will be happening in different threads and
         there's no easy way to coordinate the memory access and modification
         otherwise,  we need a mutex to keep everything in sync.

         (If we didn't do this, we could e.g., get halfway through updating the
         module control instance, send a control packet based on that [likely
         invalid] data, and then finish updating.)
      */
      std::mutex mutex;
      ModuleControl mc;
      bool have_config ( false );
      int left = 0, right = 0;

      /* Create the input device. */
      using namespace crisp::input;
      EvDevController controller ( evdev );
      assert(controller.axes.size() >= 4);

      /* Make sure the axes we'll be using are in absolute mode. */
      for ( size_t i ( 0 ); i < 2; ++i )
        {
          /* controller.axes[i].set_coefficients({1, 0, 0, 0}); */
          if ( controller.axes[i].type != Axis::Type::ABSOLUTE )
            {                     /* Set up emulation for the axis. */
              controller.axes[i].mode = Axis::Type::ABSOLUTE;

              /* We need to manually initialize the absolute-axis raw-value
                 configuration when an axis isn't actually absolute... */
              controller.axes[i].raw.minimum =
                - (controller.axes[i].raw.maximum = 256);
              controller.axes[i].raw.neutral = 0;

              /* set cubic mapping: value = 1 * x^3 + 0 * x^2 + 0 * x + 0.  */
            }
        }

      /* Add event handlers for each of the axes we're interested in. */
      controller.axes[1].hook([&](const Axis& axis, Axis::State state)
                              {
                                if ( have_config )
                                  {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    left = -state.raw_value + 127;
                                    if ( mc.module )
                                      update_control(mc, left, right);
                                  }
                              });
      controller.axes[3].hook([&](const Axis& axis, Axis::State state)
                              {
                                if ( have_config )
                                  {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    right = -state.raw_value + 127;
                                    if ( mc.module )
                                      update_control(mc, left, right);
                                  }
                              });

      /* Instantiate the network node. */
      Node node ( std::move(socket), NodeRole::MASTER );
      node.on_disconnect(std::bind(exit, 1));

      /* Override the default configuration-response-recieved handler with
         this:

         - First, make sure that the received configuration is at least similar to what
           we expect; shut down the node if it isn't.

         - Store the received configuration.

         - Set up the module-control object to
      */
      node.dispatcher.configuration_response.received.connect(
        [&](Node& _node, const Configuration& configuration)
        {
          have_config = true;
          node.configuration = configuration;
          mc.reset(&(node.configuration.modules[0]));
          update_control(mc, left, right);

          using namespace crisp::util::literals;

          /* Set up the control packet to be sent at 25 Hz. */
          fprintf(stderr, "Setting up send action... ");
          node.scheduler.schedule(25_Hz,
                                  [&](crisp::util::PeriodicAction&) {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    node.send(mc);
                                    return;
                                  });
          fprintf(stderr, "done.");
        });

      /* clear the module-control-sent handler -- it's just a lot of spam. */
      node.dispatcher.module_control.sent.clear();

      /* On user interrupt (Ctrl+C), shut down the node and stop the
         controller's main loop.
      */
      boost::asio::signal_set ss ( service, SIGINT );
      ss.async_wait([&](const boost::system::error_code& error, int sig)
                    {
                      if ( ! error )
                        {
                          fprintf(stderr, "Caught SIGINT: shutting down.");
                          node.halt();
                          controller.stop();
                          fprintf(stderr, "Shutdown complete.");
                        }
                    });

      /* Queue a configuration-query message send. */
      node.send(MessageType::CONFIGURATION_QUERY);

      /* Start the controller and the network node. */
      node.launch();
      controller.run();
    }

  return 0;
}
#endif  /* ! defined(DISABLE_CLIENT) */

int
main(int argc, char* argv[])
{
  /* Parse user options. */
  int c;
  while ( (c = getopt(argc, argv, "h")) != -1 )
    switch ( c )
      {
      case 'h':
	PRINT_USAGE(stdout);
	fprintf(stdout, HELP_TEXT);
	return 0;

      default:
	abort();
      }

  if ( argc - optind < 2 )
    {
      PRINT_USAGE(stderr);
      return 1;
    }

  /* Parse the address and port passed via the command line, and inform the user
     if they're doin' it wrong. */
  char* tail;
  boost::system::error_code pec;

  namespace ip = boost::asio::ip;

  ip::address address ( ip::address::from_string(argv[optind], pec) );

  int port ( strtoul(argv[optind + 1], &tail, 0) );

  if ( pec )
    { fprintf(stderr, "%s: %s (failed to parse IP address).\n", argv[optind], pec.message().c_str());
      return 1; }

  if ( *tail != '\0' )
    { fprintf(stderr, "%s: Need integer port number.\n", argv[optind + 1]);
      return 1; }

  /* Construct the target endpoint (IP address + port number) object. */
  using Protocol = Node::Protocol;
  typename Protocol::endpoint target_endpoint(address, port);

  /* Asio's io_service manages all the low-level details of parceling out work
     to IO worker threads in a thread-safe manner.  It's required for pretty
     much any network-related function, so we'll create one here.  */
  boost::asio::io_service service;

#if ! defined(DISABLE_CLIENT)
  return ( argc - optind < 3 )
    ? run_server(service, target_endpoint)
    : run_client(service, target_endpoint, argv[optind+2]);
#else
  return run_server(service, target_endpoint);
#endif
}

<commit_msg>(drive-test) server exits after 5s if no connections are made<commit_after>/** @file
 *
 * Client/server program for the drive test.
 */
#include <cstdio>
#include "Chassis_Control/DriveData.h"

/* Manually disable client mode on ARM machines (e.g. the Raspberry Pi, which
   gives us enough grief anyway... */
#if defined(__arm__) && ! defined(DISABLE_CLIENT)
# define DISABLE_CLIENT 1
#endif

/* ****************************************************************
 * Help text stuff.
 */
#if ! defined(DISABLE_CLIENT)
#  define PRINT_USAGE(stream) fprintf(stream, "Usage: %s [OPTION]... ADDRESS PORT [EVDEV]\n", argv[0])

#  define HELP_TEXT "\
Simple controls-test program.\n\
\n\
Options:\n\
  -h	Show this help.\n\
\n\
Client mode is assumed when EVDEV argument is present; otherwise server mode is\n\
enabled.\n"
#else
#  define PRINT_USAGE(stream) fprintf(stream, "Usage: %s [OPTION]... ADDRESS PORT\n", argv[0])
#  define HELP_TEXT "\
Simple controls-test program: server-only build.\n\
\n\
Options:\n\
  -h	Show this help.\n\
\n"
#endif  /* ! defined(DISABLE_CLIENT) */
/* **************************************************************** */

#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/signal_set.hpp>
#include <crisp/comms/BasicNode.hh>
#include <crisp/comms/NodeServer.hh>

/* Define some aliases for our communication-types for convenience. */
using namespace crisp::comms;
typedef BasicNode<boost::asio::ip::tcp> Node;
typedef typename Node::Protocol Protocol;
typedef typename Protocol::endpoint Endpoint;

#include "gnublin_i2c.hpp"

#define I2C_BUS "/dev/i2c-1"
#define I2C_SLAVE_ADDRESS 4

/** How many seconds to wait for a client to connect before we give up and quit. */
#define SERVER_TIMEOUT 5

static int
run_server(boost::asio::io_service& service,
           const Endpoint& target_endpoint)

{
  crisp::comms::NodeServer<Node> server ( service, target_endpoint, 0, 1 );

  gnublin_i2c i2c ( I2C_BUS, I2C_SLAVE_ADDRESS );

  /* I don't trust this "Gnublin" code (it's terribly written and I had to fix
     it to even get it to compile).   We'll be replacing it eventually. */
  i2c.setDevicefile(I2C_BUS);
  i2c.setAddress(I2C_SLAVE_ADDRESS);

  if ( i2c.fail() )             /* Won't happen because the Gnublin stuff opens
                                   the device on-demand.  /Le sigh.../ */
    return 1;

  DriveData data;
  unsigned char* data_pointer = reinterpret_cast<unsigned char*>(&data);
  memset(data_pointer, 0, sizeof(data));

  using namespace crisp::comms::keywords;

  /* Declare our interface configuration. */
  server.configuration.add_module( "drive", 2)
    .add_input<int8_t>({ "left",  { _neutral = 0, _minimum = -127, _maximum = 128 } })
    .add_input<int8_t>({ "right", { _neutral = 0, _minimum = -127, _maximum = 128 } });

  /* Override the handler run when we receive a module-control packet. */
  server.dispatcher.module_control.received.clear();
  server.dispatcher.module_control.received.connect(
    [&](Node& node, const crisp::comms::ModuleControl& mc)
    {
      if ( isatty(STDERR_FILENO) )
        fprintf(stderr, "[0x%0x] \033[1;33mModule-control received\033[0m: ", THREAD_ID);
      else
        fprintf(stderr, "[0x%0x] Module-control received:", THREAD_ID);

      const crisp::comms::DataValue<> *dvl ( nullptr ), *dvr ( nullptr );

      /* Update our input-value array. */
      if ( (dvl = mc.value_for("left")) != nullptr )
        {
          data.left_motor = dvl->get<int8_t>();
          fprintf(stderr, "%d", data.left_motor);
        }
      dvr = mc.value_for("right");

      if ( dvl && dvr )
        fputs(", ", stderr);

      if ( dvr )
        {
          data.right_motor = dvr->get<int8_t>();
          fprintf(stderr, "%d\n", data.right_motor);
        }

      /* This call here is just so EW EW EW EW EW.  There's a reason for it, of
         course, but that reason is irrelevant with the way we're using I2C. */
      i2c.send(data_pointer, sizeof(data));

      if ( i2c.fail() )
        {
          perror("write");
        }
    });

  crisp::util::Scheduler scheduler ( service );
  crisp::util::WorkerObject worker ( service, 1 );
  /* Wait for a connection for the configured amount of time, then exit if no one has connected.
     This safeguards against CRISP bootstrap instances being unresponsive (because they're busy
     waiting for the server to exit) after a client has trouble connecting or initializing.  */
  std::weak_ptr<crisp::util::ScheduledAction>
    halt_action ( scheduler.set_timer(std::chrono::seconds(SERVER_TIMEOUT),
                                      [&](crisp::util::ScheduledAction&)
                                      { fputs("Timeout waiting for client connection; quitting.\n", stderr);
                                        fflush_unlocked(stderr);
                                        server.halt(); }) );
  server.on_connect([&](crisp::comms::NodeServer<Node>&, Node&)
                    { fputs("Got a connection --- cancelling timeout.\n", stderr);

                      if ( ! halt_action.expired() )
                        halt_action.lock()->cancel(); });
  worker.launch();
  server.run();
  worker.halt();

  return 0;
}

/* Disable client functionality on the Raspberry Pi.

   _With_ this code (and using the old controller code based on the
   terribly-bloated Boost.Signals2 library), I had trouble getting the program
   to compile on the Pi without running out of memory.

   We don't need to support client mode on the Pi, so we might as well keep it
   disabled anyway.
 */
#if ! defined(DISABLE_CLIENT)

#include <crisp/input/EvDevController.hh>
#include <float.h>

/** Update a ModuleControl instance to reflect the input coordinates.
 *
 * @param mc ModuleControl to update.
 *
 * @param left Value of left stick y axis.
 *
 * @param right Value of right stick y axis.
 *
 */
void
update_control(crisp::comms::ModuleControl& mc,
               int left, int right)
{
  left = left > SCHAR_MAX ? SCHAR_MAX : left;
  left = left < SCHAR_MIN ? SCHAR_MIN : left;
  right = right > SCHAR_MAX ? SCHAR_MAX : right;
  right = right < SCHAR_MIN ? SCHAR_MIN : right;

  mc.set<int8_t>("left", left);
  mc.set<int8_t>("right", right);
}

/** Run the client code, connecting to the specified endpoint and taking input
 *  from the specified Linux `evdev` input device.
 */
static int
run_client(boost::asio::io_service& service,
           const Endpoint& target_endpoint,
           const char* evdev)
{
  /* Create a socket, and try to connect it to the specified endpoint. */
  boost::system::error_code ec;
  typename Protocol::socket socket ( service );
  typename Protocol::resolver resolver ( service );

  boost::asio::connect(socket, resolver.resolve(target_endpoint), ec);

  if ( ec )
    { fprintf(stderr, "connect: %s\n", strerror(ec.value()));
      return 1; }
  else
    {
      /* We're going to be modifying the ModuleControl instance on-demand
         (whenever the input controller changes state), but sending it at a
         fixed rate.  Since this will be happening in different threads and
         there's no easy way to coordinate the memory access and modification
         otherwise,  we need a mutex to keep everything in sync.

         (If we didn't do this, we could e.g., get halfway through updating the
         module control instance, send a control packet based on that [likely
         invalid] data, and then finish updating.)
      */
      std::mutex mutex;
      ModuleControl mc;
      bool have_config ( false );
      int left = 0, right = 0;

      /* Create the input device. */
      using namespace crisp::input;
      EvDevController controller ( evdev );
      assert(controller.axes.size() >= 4);

      /* Make sure the axes we'll be using are in absolute mode. */
      for ( size_t i ( 0 ); i < 2; ++i )
        {
          /* controller.axes[i].set_coefficients({1, 0, 0, 0}); */
          if ( controller.axes[i].type != Axis::Type::ABSOLUTE )
            {                     /* Set up emulation for the axis. */
              controller.axes[i].mode = Axis::Type::ABSOLUTE;

              /* We need to manually initialize the absolute-axis raw-value
                 configuration when an axis isn't actually absolute... */
              controller.axes[i].raw.minimum =
                - (controller.axes[i].raw.maximum = 256);
              controller.axes[i].raw.neutral = 0;

              /* set cubic mapping: value = 1 * x^3 + 0 * x^2 + 0 * x + 0.  */
            }
        }

      /* Add event handlers for each of the axes we're interested in. */
      controller.axes[1].hook([&](const Axis& axis, Axis::State state)
                              {
                                if ( have_config )
                                  {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    left = -state.raw_value + 127;
                                    if ( mc.module )
                                      update_control(mc, left, right);
                                  }
                              });
      controller.axes[3].hook([&](const Axis& axis, Axis::State state)
                              {
                                if ( have_config )
                                  {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    right = -state.raw_value + 127;
                                    if ( mc.module )
                                      update_control(mc, left, right);
                                  }
                              });

      /* Instantiate the network node. */
      Node node ( std::move(socket), NodeRole::MASTER );
      node.on_disconnect(std::bind(exit, 1));

      /* Override the default configuration-response-recieved handler with
         this:

         - First, make sure that the received configuration is at least similar to what
           we expect; shut down the node if it isn't.

         - Store the received configuration.

         - Set up the module-control object to
      */
      node.dispatcher.configuration_response.received.connect(
        [&](Node& _node, const Configuration& configuration)
        {
          have_config = true;
          node.configuration = configuration;
          mc.reset(&(node.configuration.modules[0]));
          update_control(mc, left, right);

          using namespace crisp::util::literals;

          /* Set up the control packet to be sent at 25 Hz. */
          fprintf(stderr, "Setting up send action... ");
          node.scheduler.schedule(25_Hz,
                                  [&](crisp::util::PeriodicAction&) {
                                    std::unique_lock<std::mutex> lock ( mutex );
                                    node.send(mc);
                                    return;
                                  });
          fprintf(stderr, "done.");
        });

      /* clear the module-control-sent handler -- it's just a lot of spam. */
      node.dispatcher.module_control.sent.clear();

      /* On user interrupt (Ctrl+C), shut down the node and stop the
         controller's main loop.
      */
      boost::asio::signal_set ss ( service, SIGINT );
      ss.async_wait([&](const boost::system::error_code& error, int sig)
                    {
                      if ( ! error )
                        {
                          fprintf(stderr, "Caught SIGINT: shutting down.");
                          node.halt();
                          controller.stop();
                          fprintf(stderr, "Shutdown complete.");
                        }
                    });

      /* Queue a configuration-query message send. */
      node.send(MessageType::CONFIGURATION_QUERY);

      /* Start the controller and the network node. */
      node.launch();
      controller.run();
    }

  return 0;
}
#endif  /* ! defined(DISABLE_CLIENT) */

int
main(int argc, char* argv[])
{
  /* Parse user options. */
  int c;
  while ( (c = getopt(argc, argv, "h")) != -1 )
    switch ( c )
      {
      case 'h':
	PRINT_USAGE(stdout);
	fprintf(stdout, HELP_TEXT);
	return 0;

      default:
	abort();
      }

  if ( argc - optind < 2 )
    {
      PRINT_USAGE(stderr);
      return 1;
    }

  /* Parse the address and port passed via the command line, and inform the user
     if they're doin' it wrong. */
  char* tail;
  boost::system::error_code pec;

  namespace ip = boost::asio::ip;

  ip::address address ( ip::address::from_string(argv[optind], pec) );

  int port ( strtoul(argv[optind + 1], &tail, 0) );

  if ( pec )
    { fprintf(stderr, "%s: %s (failed to parse IP address).\n", argv[optind], pec.message().c_str());
      return 1; }

  if ( *tail != '\0' )
    { fprintf(stderr, "%s: Need integer port number.\n", argv[optind + 1]);
      return 1; }

  /* Construct the target endpoint (IP address + port number) object. */
  using Protocol = Node::Protocol;
  typename Protocol::endpoint target_endpoint(address, port);

  /* Asio's io_service manages all the low-level details of parceling out work
     to IO worker threads in a thread-safe manner.  It's required for pretty
     much any network-related function, so we'll create one here.  */
  boost::asio::io_service service;

#if ! defined(DISABLE_CLIENT)
  return ( argc - optind < 3 )
    ? run_server(service, target_endpoint)
    : run_client(service, target_endpoint, argv[optind+2]);
#else
  return run_server(service, target_endpoint);
#endif
}

<|endoftext|>


<commit_before>#include"variables.hpp"
#include"processes.hpp"
#include"types.hpp"
#include"atoms.hpp"
#include"bytecodes.hpp"

#include<iostream>

void construct_test(Process&);

int main(int argc, const char* argv[]){
	variables_init();
	Process proc;
	execute(proc, 0, 1); /*initialize*/

	ProcessStack& stack = proc.stack;

	/*compile the bytecode*/
	stack.push(proc.get(globals->lookup("<snap>compile</snap>")));
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	construct_test(proc);
	/*execute it*/
	std::cout << "compiling to bytecode" << std::endl;
	while(execute(proc, 64) != process_dead){
	}
	/*transform bytecode object to global function object*/
	stack.push(proc.get(globals->lookup("<snap>to-free-fun</snap>")));
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	stack.push(stack[0]);
	stack.restack(3);
	/*execute it*/
	std::cout << "converting to free function" << std::endl;
	while(execute(proc, 64) != process_dead){
	}

	/*finally, execute the process*/
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	stack.restack(2);
	std::cout << "executing free function" << std::endl;
	while(execute(proc, 64) != process_dead){
	}
	std::cout << "done" << std::endl;
}

void construct_test(Process& proc){
/*
((check-vars 2)
 (global (quote $))
 (closure 0
          (check-vars 2)
          (local 1)
          continue)
 (sym (quote halt))
 (apply 3))
*/
	ProcessStack& stack = proc.stack;
	bytecode_sym(proc,stack,
		globals->lookup("check-vars"));
	bytecode_int(proc,stack,2);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("global"));
	bytecode_sym(proc,stack,
		globals->lookup("quote"));
	bytecode_sym(proc,stack,
		globals->lookup("$"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("closure"));
	bytecode_int(proc,stack,0);
	bytecode_sym(proc,stack,
		globals->lookup("check-vars"));
	bytecode_int(proc,stack,2);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("local"));
	bytecode_int(proc,stack,1);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("continue"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("sym"));
	bytecode_sym(proc,stack,
		globals->lookup("quote"));
	bytecode_sym(proc,stack,
		globals->lookup("halt"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("apply"));
	bytecode_int(proc,stack,3);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
}

<commit_msg>Added probe output<commit_after>#include"variables.hpp"
#include"processes.hpp"
#include"types.hpp"
#include"atoms.hpp"
#include"bytecodes.hpp"

#include<iostream>

void construct_test(Process&);

int main(int argc, const char* argv[]){
	variables_init();
	Process proc;
	execute(proc, 0, 1); /*initialize*/

	ProcessStack& stack = proc.stack;

	/*compile the bytecode*/
	stack.push(proc.get(globals->lookup("<snap>compile</snap>")));
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	construct_test(proc);
	/*execute it*/
	std::cout << "compiling to bytecode" << std::endl;
	while(execute(proc, 64) != process_dead){
	}
	/*transform bytecode object to global function object*/
	stack.push(proc.get(globals->lookup("<snap>to-free-fun</snap>")));
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	stack.push(stack[0]);
	stack.restack(3);
	/*execute it*/
	std::cout << "converting to free function" << std::endl;
	while(execute(proc, 64) != process_dead){
	}

	/*finally, execute the process*/
	stack.push(proc.get(globals->lookup("<snap>halt</snap>")));
	stack.restack(2);
	std::cout << "executing free function" << std::endl;
	while(execute(proc, 64) != process_dead){
	}
	stack.top()->probe(0);
	std::cout << "done" << std::endl;
}

void construct_test(Process& proc){
/*
((check-vars 2)
 (global (quote $))
 (closure 0
          (check-vars 2)
          (local 1)
          continue)
 (sym (quote halt))
 (apply 3))
*/
	ProcessStack& stack = proc.stack;
	bytecode_sym(proc,stack,
		globals->lookup("check-vars"));
	bytecode_int(proc,stack,2);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("global"));
	bytecode_sym(proc,stack,
		globals->lookup("quote"));
	bytecode_sym(proc,stack,
		globals->lookup("$"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("closure"));
	bytecode_int(proc,stack,0);
	bytecode_sym(proc,stack,
		globals->lookup("check-vars"));
	bytecode_int(proc,stack,2);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("local"));
	bytecode_int(proc,stack,1);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("continue"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("sym"));
	bytecode_sym(proc,stack,
		globals->lookup("quote"));
	bytecode_sym(proc,stack,
		globals->lookup("halt"));
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,
		globals->lookup("apply"));
	bytecode_int(proc,stack,3);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_sym(proc,stack,NILATOM);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
	bytecode_cons(proc,stack);
}

<|endoftext|>