<commit_before>#include "XmlReader.h"

#include "Exception.h"
#include "Factory.h"
#include "Data.h"
#include "Stream.h"
#include "Operator.h"

#include "impl/XmlUtilities.h"

#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>

namespace stream
{
    using namespace xercesc;
    using namespace impl;

    Stream*const XmlReader::read(const std::string & filename)
    {
        cleanUp();

        m_currentPath = computePath(filename);

        try
        {
            XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
        }
        catch (const XMLException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.getMessage());

            FileAccessFailed ex(filename, "Failed to initialize xerces-c: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }

        XercesDOMParser* parser = new XercesDOMParser();
        parser->setValidationScheme(XercesDOMParser::Val_Always);
        parser->setDoNamespaces(true);    // optional

        ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
        parser->setErrorHandler(errHandler);

        const char* xmlFile = filename.c_str();

        try
        {
            parser->parse(xmlFile);
        }
        catch (const XMLException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.getMessage());

            FileAccessFailed ex(filename, "XML exception: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }
        catch (const DOMException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.msg);

            FileAccessFailed ex(filename, "DOM exception: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }
        catch (...)
        {
            throw FileAccessFailed(filename, "Unexpected exception.");
        }

        try
        {
            m_stream = new Stream();

            DOMDocument* doc = parser->getDocument();
            DOMElement* stream = doc->getDocumentElement();

            Xml2Str name(stream->getAttribute(Str2Xml("name")));
            m_stream->setName(std::string(name));

            DOMNodeList* operators = stream->getElementsByTagName(Str2Xml("Operator"));
            XMLSize_t numOperators = operators->getLength();

            for(unsigned int i = 0; i < numOperators; ++i)
            {
                DOMElement* op = dynamic_cast<DOMElement*>(operators->item(i));
                readOperator(op);
            }
        }
        catch(xercesc::XMLException&)
        {
            delete m_stream;
            throw FileAccessFailed(filename, "Failed to read XML file.");
        }
        catch(stream::Exception& e)
        {
            delete m_stream;
            throw FileAccessFailed(filename, e.what());
        }
        catch(boost::bad_lexical_cast e)
        {
            delete m_stream;
            throw FileAccessFailed(filename, e.what());
        }

        delete parser;
        delete errHandler;

        try
        {
            XMLPlatformUtils::Terminate();  // Terminate after release of memory
        }
        catch(XMLException&)
        {
        }

        Stream* retValue = m_stream;

        cleanUp();

        return retValue;
    }

    XmlReader::~XmlReader()
    {
        cleanUp();
    }

    void XmlReader::readOperator(DOMElement*const opElement)
    {
        Xml2Str name(opElement->getAttribute(Str2Xml("name")));
        Xml2Str idStr(opElement->getAttribute(Str2Xml("id")));
        Xml2Str type(opElement->getAttribute(Str2Xml("type")));
        Xml2Str package(opElement->getAttribute(Str2Xml("package")));

        unsigned int id = boost::lexical_cast<unsigned int>((const char*)(idStr));

        if(m_id2OperatorMap.count(id))
            throw XmlError("Multiple operators with the same ID.");

        Operator* op = m_factory->newOperator(std::string(package), std::string(type));
        op->setName(std::string(name));

        m_id2OperatorMap[id] = op;

        DOMNodeList* parameters = opElement->getElementsByTagName(Str2Xml("Parameter"));
        XMLSize_t numParameters = parameters->getLength();

        for(unsigned int i = 0; i < numParameters; ++i)
        {
            DOMElement* paramElement = dynamic_cast<DOMElement*>(parameters->item(i));
            readParameter(paramElement);
        }
    }

    void XmlReader::readParameter(DOMElement*const paramElement)
    {
        Xml2Str idStr(paramElement->getAttribute(Str2Xml("id")));

        unsigned int id = boost::lexical_cast<unsigned int>((const char*)(idStr));

        DOMNodeList* dataElements = paramElement->getElementsByTagName(Str2Xml("Data"));
        XMLSize_t numDataElements = dataElements->getLength();

        if(! numDataElements)
            return;

        if(numDataElements != 1)
            throw XmlError("More than one <Data/> elements for parameter.");

        DOMElement* dataElement = dynamic_cast<DOMElement*>(dataElements->item(0));
        Data* data = readData(dataElement);

        if(m_id2DataMap.count(id))
            throw XmlError("Multiple parameters with the same ID.");

        m_id2DataMap[id] = data;
    }

    Data* XmlReader::readData(DOMElement*const dataElement)
    {
        Xml2Str type(dataElement->getAttribute(Str2Xml("type")));
        Xml2Str package(dataElement->getAttribute(Str2Xml("package")));

        DOMNodeList* dataTextElements = dataElement->getChildNodes();
        XMLSize_t numDataTextElements = dataTextElements->getLength();
        std::string dataString;

        if(numDataTextElements > 1)
            throw XmlError("More than one children of <Data/>.");

        if(numDataTextElements)
        {
            DOMNode* node = dataTextElements->item(0);
            if(node->getNodeType() != DOMNode::TEXT_NODE)
                throw XmlError("Child of <Data/> must be a text node.");

            dataString = std::string(Xml2Str(node->getNodeValue()));
        }

        Data* data = m_factory->newData(std::string(package), std::string(type));

        try
        {
            data->deserialize(dataString, m_currentPath);
        }
        catch(Exception& e)
        {
            delete data;
            throw e;
        }

        return data;
    }

    const std::string XmlReader::computePath(const std::string& filename)
    {
        boost::filesystem::path filepath(filename);
        boost::filesystem::path parentpath = filepath.parent_path();
        std::string pathSeparator;

        if(! parentpath.empty())
            pathSeparator = boost::filesystem::path("/").file_string();

        return parentpath.file_string() + pathSeparator;
    }

    void XmlReader::cleanUp()
    {
        m_stream = 0;
        m_currentPath = "";

        for(std::map<unsigned int, Operator*>::iterator iter = m_id2OperatorMap.begin();
            iter != m_id2OperatorMap.end();
            ++iter)
        {
            delete iter->second;
        }

        m_id2OperatorMap.clear();

        for(std::map<unsigned int, Data*>::iterator iter = m_id2DataMap.begin();
            iter != m_id2DataMap.end();
            ++iter)
        {
            delete iter->second;
        }

        m_id2DataMap.clear();

    }
}
<commit_msg>Read parameters to buffer before actually setting them<commit_after>#include "XmlReader.h"

#include "Exception.h"
#include "Factory.h"
#include "Data.h"
#include "Stream.h"
#include "Operator.h"

#include "impl/XmlUtilities.h"

#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>

namespace stream
{
    using namespace xercesc;
    using namespace impl;

    Stream*const XmlReader::read(const std::string & filename)
    {
        cleanUp();

        m_currentPath = computePath(filename);

        try
        {
            XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
        }
        catch (const XMLException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.getMessage());

            FileAccessFailed ex(filename, "Failed to initialize xerces-c: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }

        XercesDOMParser* parser = new XercesDOMParser();
        parser->setValidationScheme(XercesDOMParser::Val_Always);
        parser->setDoNamespaces(true);    // optional

        ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
        parser->setErrorHandler(errHandler);

        const char* xmlFile = filename.c_str();

        try
        {
            parser->parse(xmlFile);
        }
        catch (const XMLException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.getMessage());

            FileAccessFailed ex(filename, "XML exception: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }
        catch (const DOMException& toCatch)
        {
            char* message = XMLString::transcode(toCatch.msg);

            FileAccessFailed ex(filename, "DOM exception: " + std::string(message));
            XMLString::release(&message);
            throw ex;
        }
        catch (...)
        {
            throw FileAccessFailed(filename, "Unexpected exception.");
        }

        try
        {
            m_stream = new Stream();

            DOMDocument* doc = parser->getDocument();
            DOMElement* stream = doc->getDocumentElement();

            Xml2Str name(stream->getAttribute(Str2Xml("name")));
            m_stream->setName(std::string(name));

            DOMNodeList* operators = stream->getElementsByTagName(Str2Xml("Operator"));
            XMLSize_t numOperators = operators->getLength();

            for(unsigned int i = 0; i < numOperators; ++i)
            {
                DOMElement* op = dynamic_cast<DOMElement*>(operators->item(i));
                readOperator(op);
            }
        }
        catch(xercesc::XMLException&)
        {
            delete m_stream;
            throw FileAccessFailed(filename, "Failed to read XML file.");
        }
        catch(stream::Exception& e)
        {
            delete m_stream;
            throw FileAccessFailed(filename, e.what());
        }
        catch(boost::bad_lexical_cast e)
        {
            delete m_stream;
            throw FileAccessFailed(filename, e.what());
        }

        delete parser;
        delete errHandler;

        try
        {
            XMLPlatformUtils::Terminate();  // Terminate after release of memory
        }
        catch(XMLException&)
        {
        }

        Stream* retValue = m_stream;

        cleanUp();

        return retValue;
    }

    XmlReader::~XmlReader()
    {
        cleanUp();
    }

    void XmlReader::readOperator(DOMElement*const opElement)
    {
        Xml2Str name(opElement->getAttribute(Str2Xml("name")));
        Xml2Str idStr(opElement->getAttribute(Str2Xml("id")));
        Xml2Str type(opElement->getAttribute(Str2Xml("type")));
        Xml2Str package(opElement->getAttribute(Str2Xml("package")));

        unsigned int id = boost::lexical_cast<unsigned int>((const char*)(idStr));

        if(m_id2OperatorMap.count(id))
            throw XmlError("Multiple operators with the same ID.");

        Operator* op = m_factory->newOperator(std::string(package), std::string(type));
        op->setName(std::string(name));

        m_id2OperatorMap[id] = op;

        DOMNodeList* parameters = opElement->getElementsByTagName(Str2Xml("Parameter"));
        XMLSize_t numParameters = parameters->getLength();

        for(unsigned int i = 0; i < numParameters; ++i)
        {
            DOMElement* paramElement = dynamic_cast<DOMElement*>(parameters->item(i));
            readParameter(paramElement);
        }
    }

    void XmlReader::readParameter(DOMElement*const paramElement)
    {
        Xml2Str idStr(paramElement->getAttribute(Str2Xml("id")));

        unsigned int id = boost::lexical_cast<unsigned int>((const char*)(idStr));

        DOMNodeList* dataElements = paramElement->getElementsByTagName(Str2Xml("Data"));
        XMLSize_t numDataElements = dataElements->getLength();

        if(! numDataElements)
            return;

        if(numDataElements != 1)
            throw XmlError("More than one <Data/> elements for parameter.");

        DOMElement* dataElement = dynamic_cast<DOMElement*>(dataElements->item(0));
        Data* data = readData(dataElement);

        if(m_id2DataMap.count(id))
            throw XmlError("Multiple parameters with the same ID.");

        m_id2DataMap[id] = data;
    }

    Data* XmlReader::readData(DOMElement*const dataElement)
    {
        Xml2Str type(dataElement->getAttribute(Str2Xml("type")));
        Xml2Str package(dataElement->getAttribute(Str2Xml("package")));

        DOMNodeList* dataTextElements = dataElement->getChildNodes();
        XMLSize_t numDataTextElements = dataTextElements->getLength();
        std::string dataString;

        if(numDataTextElements > 1)
            throw XmlError("More than one children of <Data/>.");

        if(numDataTextElements)
        {
            DOMNode* node = dataTextElements->item(0);
            if(node->getNodeType() != DOMNode::TEXT_NODE)
                throw XmlError("Child of <Data/> must be a text node.");

            dataString = std::string(Xml2Str(node->getNodeValue()));
        }

        Data* data = m_factory->newData(std::string(package), std::string(type));

        try
        {
            data->deserialize(dataString, m_currentPath);
        }
        catch(Exception& e)
        {
            delete data;
            throw e;
        }

        return data;
    }

    const std::string XmlReader::computePath(const std::string& filename)
    {
        boost::filesystem::path filepath(filename);
        boost::filesystem::path parentpath = filepath.parent_path();
        std::string pathSeparator;

        if(! parentpath.empty())
            pathSeparator = boost::filesystem::path("/").file_string();

        return parentpath.file_string() + pathSeparator;
    }

    void XmlReader::cleanUp()
    {
        m_stream = 0;
        m_currentPath = "";

        m_id2OperatorMap.clear();

        for(std::map<unsigned int, Data*>::iterator iter = m_id2DataMap.begin();
            iter != m_id2DataMap.end();
            ++iter)
        {
            delete iter->second;
        }

        m_id2DataMap.clear();

    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: David Guillen Fandos
 */

#include "sim/power/mathexpr_powermodel.hh"

#include "base/statistics.hh"
#include "params/MathExprPowerModel.hh"
#include "sim/mathexpr.hh"
#include "sim/power/thermal_model.hh"
#include "sim/sim_object.hh"

MathExprPowerModel::MathExprPowerModel(const Params *p)
    : PowerModelState(p), dyn_expr(p->dyn), st_expr(p->st), failed(false)
{
    // Calculate the name of the object we belong to
    std::vector<std::string> path;
    tokenize(path, name(), '.', true);
    // It's something like xyz.power_model.pm2
    assert(path.size() > 2);
    for (unsigned i = 0; i < path.size() - 2; i++)
        basename += path[i] + ".";
}

void
MathExprPowerModel::startup()
{
    // Create a map with stats and pointers for quick access
    // Has to be done here, since we need access to the statsList
    for (auto & i: Stats::statsList())
        if (i->name.find(basename) == 0)
            stats_map[i->name.substr(basename.size())] = i;

    tryEval(st_expr);
    const bool st_failed = failed;

    tryEval(dyn_expr);
    const bool dyn_failed = failed;

    if (st_failed || dyn_failed) {
        const auto *p = dynamic_cast<const Params *>(params());
        assert(p);

        fatal("Failed to evaluate power expressions:\n%s%s%s\n",
              st_failed ? p->st : "",
              st_failed && dyn_failed ? "\n" : "",
              dyn_failed ? p->dyn : "");
    }
}

double
MathExprPowerModel::eval(const MathExpr &expr) const
{
    const double value = tryEval(expr);

    // This shouldn't happen unless something went wrong the equations
    // were verified in startup().
    panic_if(failed, "Failed to evaluate power expression '%s'\n",
             expr.toStr());

    return value;
}

double
MathExprPowerModel::tryEval(const MathExpr &expr) const
{
    failed = false;
    const double value = expr.eval(
        std::bind(&MathExprPowerModel::getStatValue,
                  this, std::placeholders::_1)
        );

    return value;
}

double
MathExprPowerModel::getStatValue(const std::string &name) const
{
    using namespace Stats;

    // Automatic variables:
    if (name == "temp")
        return _temp;

    // Try to cast the stat, only these are supported right now
    const auto it = stats_map.find(name);
    if (it == stats_map.cend()) {
        warn("Failed to find stat '%s'\n", name);
        failed = true;
        return 0;
    }

    const Info *info = it->second;

    auto si = dynamic_cast<const ScalarInfo *>(info);
    if (si)
        return si->value();
    auto fi = dynamic_cast<const FormulaInfo *>(info);
    if (fi)
        return fi->total();

    panic("Unknown stat type!\n");
}

void
MathExprPowerModel::regStats()
{
    PowerModelState::regStats();
}

MathExprPowerModel*
MathExprPowerModelParams::create()
{
    return new MathExprPowerModel(this);
}
<commit_msg>power: Add a voltage variable to power expressions<commit_after>/*
 * Copyright (c) 2016-2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: David Guillen Fandos
 */

#include "sim/power/mathexpr_powermodel.hh"

#include "base/statistics.hh"
#include "params/MathExprPowerModel.hh"
#include "sim/mathexpr.hh"
#include "sim/power/thermal_model.hh"
#include "sim/sim_object.hh"

MathExprPowerModel::MathExprPowerModel(const Params *p)
    : PowerModelState(p), dyn_expr(p->dyn), st_expr(p->st), failed(false)
{
    // Calculate the name of the object we belong to
    std::vector<std::string> path;
    tokenize(path, name(), '.', true);
    // It's something like xyz.power_model.pm2
    assert(path.size() > 2);
    for (unsigned i = 0; i < path.size() - 2; i++)
        basename += path[i] + ".";
}

void
MathExprPowerModel::startup()
{
    // Create a map with stats and pointers for quick access
    // Has to be done here, since we need access to the statsList
    for (auto & i: Stats::statsList())
        if (i->name.find(basename) == 0)
            stats_map[i->name.substr(basename.size())] = i;

    tryEval(st_expr);
    const bool st_failed = failed;

    tryEval(dyn_expr);
    const bool dyn_failed = failed;

    if (st_failed || dyn_failed) {
        const auto *p = dynamic_cast<const Params *>(params());
        assert(p);

        fatal("Failed to evaluate power expressions:\n%s%s%s\n",
              st_failed ? p->st : "",
              st_failed && dyn_failed ? "\n" : "",
              dyn_failed ? p->dyn : "");
    }
}

double
MathExprPowerModel::eval(const MathExpr &expr) const
{
    const double value = tryEval(expr);

    // This shouldn't happen unless something went wrong the equations
    // were verified in startup().
    panic_if(failed, "Failed to evaluate power expression '%s'\n",
             expr.toStr());

    return value;
}

double
MathExprPowerModel::tryEval(const MathExpr &expr) const
{
    failed = false;
    const double value = expr.eval(
        std::bind(&MathExprPowerModel::getStatValue,
                  this, std::placeholders::_1)
        );

    return value;
}

double
MathExprPowerModel::getStatValue(const std::string &name) const
{
    using namespace Stats;

    // Automatic variables:
    if (name == "temp") {
        return _temp;
    } else if (name == "voltage") {
        return clocked_object->voltage();
    }

    // Try to cast the stat, only these are supported right now
    const auto it = stats_map.find(name);
    if (it == stats_map.cend()) {
        warn("Failed to find stat '%s'\n", name);
        failed = true;
        return 0;
    }

    const Info *info = it->second;

    auto si = dynamic_cast<const ScalarInfo *>(info);
    if (si)
        return si->value();
    auto fi = dynamic_cast<const FormulaInfo *>(info);
    if (fi)
        return fi->total();

    panic("Unknown stat type!\n");
}

void
MathExprPowerModel::regStats()
{
    PowerModelState::regStats();
}

MathExprPowerModel*
MathExprPowerModelParams::create()
{
    return new MathExprPowerModel(this);
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "content/browser/renderer_host/accelerated_surface_container_linux.h"

#include "base/memory/scoped_ptr.h"
#include "content/browser/renderer_host/image_transport_client.h"
#include "ui/gfx/compositor/compositor_cc.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"

namespace {

class AcceleratedSurfaceContainerLinuxCC
    : public AcceleratedSurfaceContainerLinux, public ui::TextureCC {
 public:
  explicit AcceleratedSurfaceContainerLinuxCC(const gfx::Size& size)
      : size_(size),
        acquired_(false) {
  }

  virtual ~AcceleratedSurfaceContainerLinuxCC() {
    if (image_transport_client_.get())
      image_transport_client_->Release();
  }

  virtual void AddRef() { ui::TextureCC::AddRef(); }
  virtual void Release() { ui::TextureCC::Release(); }

  virtual bool Initialize(uint64* surface_id) OVERRIDE {
    ui::SharedResourcesCC* instance = ui::SharedResourcesCC::GetInstance();
    DCHECK(instance);
    image_transport_client_.reset(
        ImageTransportClient::Create(instance, size_));
    if (!image_transport_client_.get())
      return false;

    texture_id_ = image_transport_client_->Initialize(surface_id);
    if (!texture_id_) {
      image_transport_client_.reset();
      return false;
    }
    flipped_ = image_transport_client_->Flipped();
    return true;
  }

  // TextureCC implementation
  virtual void Update() OVERRIDE {
    ui::SharedResourcesCC* instance = ui::SharedResourcesCC::GetInstance();
    DCHECK(instance);
    instance->MakeSharedContextCurrent();
    if (acquired_)
      image_transport_client_->Release();
    else
      acquired_ = true;
    image_transport_client_->Acquire();
  }

  virtual TransportDIB::Handle Handle() const {
    return image_transport_client_->Handle();
  }

  virtual ui::Texture* GetTexture() { return this; }

 private:
  scoped_ptr<ImageTransportClient> image_transport_client_;
  gfx::Size size_;
  bool acquired_;
  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxCC);
};

}  // namespace

// static
AcceleratedSurfaceContainerLinux*
AcceleratedSurfaceContainerLinux::Create(const gfx::Size& size) {
  return new AcceleratedSurfaceContainerLinuxCC(size);
}
<commit_msg>aura/cc: Fix GPU leak on resize.<commit_after>// Copyright (c) 2011 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 "content/browser/renderer_host/accelerated_surface_container_linux.h"

#include "base/memory/scoped_ptr.h"
#include "content/browser/renderer_host/image_transport_client.h"
#include "ui/gfx/compositor/compositor_cc.h"
#include "ui/gfx/gl/gl_bindings.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"

namespace {

class AcceleratedSurfaceContainerLinuxCC
    : public AcceleratedSurfaceContainerLinux, public ui::TextureCC {
 public:
  explicit AcceleratedSurfaceContainerLinuxCC(const gfx::Size& size)
      : size_(size),
        acquired_(false) {
  }

  virtual ~AcceleratedSurfaceContainerLinuxCC() {
    if (texture_id_) {
      ui::SharedResourcesCC* instance = ui::SharedResourcesCC::GetInstance();
      DCHECK(instance);
      instance->MakeSharedContextCurrent();
      glDeleteTextures(1, &texture_id_);
    }

    if (image_transport_client_.get())
      image_transport_client_->Release();
  }

  virtual void AddRef() { ui::TextureCC::AddRef(); }
  virtual void Release() { ui::TextureCC::Release(); }

  virtual bool Initialize(uint64* surface_id) OVERRIDE {
    ui::SharedResourcesCC* instance = ui::SharedResourcesCC::GetInstance();
    DCHECK(instance);
    image_transport_client_.reset(
        ImageTransportClient::Create(instance, size_));
    if (!image_transport_client_.get())
      return false;

    texture_id_ = image_transport_client_->Initialize(surface_id);
    if (!texture_id_) {
      image_transport_client_.reset();
      return false;
    }
    flipped_ = image_transport_client_->Flipped();
    return true;
  }

  // TextureCC implementation
  virtual void Update() OVERRIDE {
    ui::SharedResourcesCC* instance = ui::SharedResourcesCC::GetInstance();
    DCHECK(instance);
    instance->MakeSharedContextCurrent();
    if (acquired_)
      image_transport_client_->Release();
    else
      acquired_ = true;
    image_transport_client_->Acquire();
  }

  virtual TransportDIB::Handle Handle() const {
    return image_transport_client_->Handle();
  }

  virtual ui::Texture* GetTexture() { return this; }

 private:
  scoped_ptr<ImageTransportClient> image_transport_client_;
  gfx::Size size_;
  bool acquired_;
  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxCC);
};

}  // namespace

// static
AcceleratedSurfaceContainerLinux*
AcceleratedSurfaceContainerLinux::Create(const gfx::Size& size) {
  return new AcceleratedSurfaceContainerLinuxCC(size);
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2012, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <asp/Core/InterestPointMatching.h>

using namespace vw;

namespace asp {

  Vector3 datum_intersection( cartography::Datum const& datum,
                              camera::CameraModel* model,
                              Vector2 const& pix ) {
    using namespace vw;

    // Intersect the ray back-projected from the camera with the
    // datum, which is a spheroid. To simplify the calculations, scale
    // everything in such a way that the spheroid becomes a
    // sphere. Scale back at the end of computation.

    double z_scale = datum.semi_major_axis() / datum.semi_minor_axis();

    Vector3 ccenter = model->camera_center( pix );
    Vector3 cvec  = model->pixel_to_vector( pix );
    ccenter.z() *= z_scale;
    cvec.z() *= z_scale;
    cvec = normalize(cvec);
    double radius_2 = datum.semi_major_axis() *
      datum.semi_major_axis();
    double alpha = -dot_prod(ccenter, cvec );
    Vector3 projection = ccenter + alpha*cvec;
    if ( norm_2_sqr(projection) > radius_2 ) {
      // did not intersect
      return Vector3();
    }

    alpha -= sqrt( radius_2 -
                   norm_2_sqr(projection) );
    return elem_prod(ccenter + alpha * cvec, Vector3(1,1,1.0/z_scale));
  }

  // Find a rough homography that maps right to left using the camera
  // and datum information.
  Matrix<double>
  rough_homography_fit( camera::CameraModel* cam1,
                        camera::CameraModel* cam2,
                        BBox2i const& box1, BBox2i const& box2,
                        cartography::Datum const& datum ) {

    // Bounce several points off the datum and fit an affine.
    std::vector<Vector3> left_points, right_points;
    left_points.reserve(20000);
    right_points.reserve(20000);
    for ( size_t i = 0; i < 100; i++ ) {
      for ( size_t j = 0; j < 100; j++ ) {
        try {
          Vector2 l( double(box1.width() - 1) * i / 99.0,
                     double(box1.height() - 1) * j / 99.0 );

          Vector3 intersection =
            datum_intersection( datum, cam1, l );
          if ( intersection == Vector3() )
            continue;

          Vector2 r = cam2->point_to_pixel( intersection );

          if ( box2.contains( r ) ) {
            left_points.push_back( Vector3(l[0],l[1],1) );
            right_points.push_back( Vector3(r[0],r[1],1) );
          }
        } catch (camera::PixelToRayErr const& e ) {}
        try {
          Vector2 r( double(box2.width() - 1) * i / 99.0,
                     double(box2.height() - 1) * j / 99.0 );

          Vector3 intersection =
            datum_intersection( datum, cam2, r );
          if ( intersection == Vector3() )
            continue;

          Vector2 l = cam1->point_to_pixel( intersection );

          if ( box1.contains( l ) ) {
            left_points.push_back( Vector3(l[0],l[1],1) );
            right_points.push_back( Vector3(r[0],r[1],1) );
          }
        } catch (camera::PixelToRayErr const& e ) {}
      }
    }

    VW_OUT( DebugMessage, "asp" ) << "Projected " << left_points.size()
                                  << " rays for rough homography.\n";

    typedef math::HomographyFittingFunctor hfit_func;
    math::RandomSampleConsensus<hfit_func, math::InterestPointErrorMetric> ransac( hfit_func(), math::InterestPointErrorMetric(), norm_2(Vector2(box1.height(),box1.width())) / 10 );
    Matrix<double> H = ransac( right_points, left_points );
    std::vector<size_t> indices = ransac.inlier_indices(H, right_points, left_points);

    if ( indices.size() < std::min( right_points.size(), left_points.size() )/3 ){
      vw_throw( ArgumentErr() << "InterestPointMatching: The number of inliers is less than 1/3 of the number of points. The homography fit is inaccurate.\n" );
    }

    double det = H(0, 0)*H(1, 1) - H(0, 1)*H(1, 0);
    if (det <= 0.0 || det > 2.0){
      vw_throw( ArgumentErr() << "InterestPointMatching: The determinant of homography matrix is negative or too large. The homography fit is inaccurate.\n" );
    }

    return H;
  }

  vw::Matrix<double>
  homography_fit( std::vector<vw::ip::InterestPoint> const& ip1,
                  std::vector<vw::ip::InterestPoint> const& ip2,
                  vw::BBox2i const& image_size ) {
    using namespace vw;

    typedef math::HomographyFittingFunctor hfit_func;
    math::RandomSampleConsensus<hfit_func, math::InterestPointErrorMetric> ransac( hfit_func(), math::InterestPointErrorMetric(), norm_2(Vector2(image_size.width(),image_size.height())) / 10 );
    std::vector<Vector3>  copy1, copy2;
    copy1.reserve( ip1.size() );
    copy2.reserve( ip1.size() );
    for ( size_t i = 0; i < ip1.size(); i++ ) {
      copy1.push_back( Vector3(ip1[i].x, ip1[i].y, 1) );
      copy2.push_back( Vector3(ip2[i].x, ip2[i].y, 1) );
    }
    Matrix<double> ransac_result = ransac(copy1,copy2);
    return hfit_func()(copy1,copy2,ransac_result);
  }

}
<commit_msg>InterestPointMatching: Add comments.<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2012, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <asp/Core/InterestPointMatching.h>

using namespace vw;

namespace asp {

  Vector3 datum_intersection( cartography::Datum const& datum,
                              camera::CameraModel* model,
                              Vector2 const& pix ) {
    using namespace vw;

    // Intersect the ray back-projected from the camera with the
    // datum, which is a spheroid. To simplify the calculations, scale
    // everything in such a way that the spheroid becomes a
    // sphere. Scale back at the end of computation.

    double z_scale = datum.semi_major_axis() / datum.semi_minor_axis();

    Vector3 ccenter = model->camera_center( pix );
    Vector3 cvec  = model->pixel_to_vector( pix );
    ccenter.z() *= z_scale;
    cvec.z() *= z_scale;
    cvec = normalize(cvec);
    double radius_2 = datum.semi_major_axis() *
      datum.semi_major_axis();
    double alpha = -dot_prod(ccenter, cvec );
    Vector3 projection = ccenter + alpha*cvec;
    if ( norm_2_sqr(projection) > radius_2 ) {
      // did not intersect
      return Vector3();
    }

    alpha -= sqrt( radius_2 -
                   norm_2_sqr(projection) );
    return elem_prod(ccenter + alpha * cvec, Vector3(1,1,1.0/z_scale));
  }

  // Find a rough homography that maps right to left using the camera
  // and datum information.
  Matrix<double>
  rough_homography_fit( camera::CameraModel* cam1,
                        camera::CameraModel* cam2,
                        BBox2i const& box1, BBox2i const& box2,
                        cartography::Datum const& datum ) {

    // Bounce several points off the datum and fit an affine.
    std::vector<Vector3> left_points, right_points;
    left_points.reserve(20000);
    right_points.reserve(20000);
    for ( size_t i = 0; i < 100; i++ ) {
      for ( size_t j = 0; j < 100; j++ ) {
        try {
          Vector2 l( double(box1.width() - 1) * i / 99.0,
                     double(box1.height() - 1) * j / 99.0 );

          Vector3 intersection =
            datum_intersection( datum, cam1, l );
          if ( intersection == Vector3() )
            continue;

          Vector2 r = cam2->point_to_pixel( intersection );

          if ( box2.contains( r ) ) {
            left_points.push_back( Vector3(l[0],l[1],1) );
            right_points.push_back( Vector3(r[0],r[1],1) );
          }
        } catch (camera::PixelToRayErr const& e ) {}
        try {
          Vector2 r( double(box2.width() - 1) * i / 99.0,
                     double(box2.height() - 1) * j / 99.0 );

          Vector3 intersection =
            datum_intersection( datum, cam2, r );
          if ( intersection == Vector3() )
            continue;

          Vector2 l = cam1->point_to_pixel( intersection );

          if ( box1.contains( l ) ) {
            left_points.push_back( Vector3(l[0],l[1],1) );
            right_points.push_back( Vector3(r[0],r[1],1) );
          }
        } catch (camera::PixelToRayErr const& e ) {}
      }
    }

    VW_OUT( DebugMessage, "asp" ) << "Projected " << left_points.size()
                                  << " rays for rough homography.\n";

    typedef math::HomographyFittingFunctor hfit_func;
    math::RandomSampleConsensus<hfit_func, math::InterestPointErrorMetric> ransac( hfit_func(), math::InterestPointErrorMetric(), norm_2(Vector2(box1.height(),box1.width())) / 10 );
    Matrix<double> H = ransac( right_points, left_points );
    std::vector<size_t> indices = ransac.inlier_indices(H, right_points, left_points);

    // Sanity checks. If these fail, most likely the two images are too different
    // for stereo to succeed.
    if ( indices.size() < std::min( right_points.size(), left_points.size() )/3 ){
      vw_throw( ArgumentErr() << "InterestPointMatching: The number of inliers is less than 1/3 of the number of points. The homography fit is inaccurate.\n" );
    }

    double det = H(0, 0)*H(1, 1) - H(0, 1)*H(1, 0);
    if (det <= 0.0 || det > 2.0){
      vw_throw( ArgumentErr() << "InterestPointMatching: The determinant of homography matrix is negative or too large. The homography fit is inaccurate.\n" );
    }

    return H;
  }

  vw::Matrix<double>
  homography_fit( std::vector<vw::ip::InterestPoint> const& ip1,
                  std::vector<vw::ip::InterestPoint> const& ip2,
                  vw::BBox2i const& image_size ) {
    using namespace vw;

    typedef math::HomographyFittingFunctor hfit_func;
    math::RandomSampleConsensus<hfit_func, math::InterestPointErrorMetric> ransac( hfit_func(), math::InterestPointErrorMetric(), norm_2(Vector2(image_size.width(),image_size.height())) / 10 );
    std::vector<Vector3>  copy1, copy2;
    copy1.reserve( ip1.size() );
    copy2.reserve( ip1.size() );
    for ( size_t i = 0; i < ip1.size(); i++ ) {
      copy1.push_back( Vector3(ip1[i].x, ip1[i].y, 1) );
      copy2.push_back( Vector3(ip2[i].x, ip2[i].y, 1) );
    }
    Matrix<double> ransac_result = ransac(copy1,copy2);
    return hfit_func()(copy1,copy2,ransac_result);
  }

}
<|endoftext|>


<commit_before>/*
 *
 * RIppleLikeTransactionDatabaseHelper
 *
 * Created by El Khalil Bellakrid on 06/01/2019.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "RippleLikeTransactionDatabaseHelper.h"
#include <database/soci-option.h>
#include <database/soci-date.h>
#include <database/soci-number.h>
#include <crypto/SHA256.hpp>
#include <wallet/common/database/BlockDatabaseHelper.h>

using namespace soci;

namespace ledger {
    namespace core {

        bool RippleLikeTransactionDatabaseHelper::getTransactionByHash(soci::session &sql,
                                                                       const std::string &hash,
                                                                       RippleLikeBlockchainExplorerTransaction &tx) {

            rowset<row> rows = (sql.prepare << "SELECT  tx.hash, tx.value, tx.time, "
                    " tx.sender, tx.receiver, tx.fees, tx.confirmations, "
                    "block.height, block.hash, block.time, block.currency_name, "
                    "memo.data, memo.fmt, memo.ty "
                    "FROM ripple_transactions AS tx "
                    "LEFT JOIN blocks AS block ON tx.block_uid = block.uid "
                    "LEFT JOIN ripple_memos AS memo ON memo.transaction_uid = tx.transaction_uid "
                    "WHERE tx.hash = :hash "
                    "ORDER BY memo.array_index ASC", use(hash));

            for (auto &row : rows) {
                inflateTransaction(sql, row, tx);
                return true;
            }

            return false;
        }

        bool RippleLikeTransactionDatabaseHelper::inflateTransaction(soci::session &sql,
                                                                     const soci::row &row,
                                                                     RippleLikeBlockchainExplorerTransaction &tx) {
            tx.hash = row.get<std::string>(0);
            tx.value = BigInt::fromHex(row.get<std::string>(1));
            tx.receivedAt = row.get<std::chrono::system_clock::time_point>(2);
            tx.sender = row.get<std::string>(3);
            tx.receiver = row.get<std::string>(4);
            tx.fees = BigInt::fromHex(row.get<std::string>(5));
            tx.confirmations = get_number<uint64_t>(row, 6);
            if (row.get_indicator(7) != i_null) {
                RippleLikeBlockchainExplorer::Block block;
                block.height = get_number<uint64_t>(row, 7);
                block.hash = row.get<std::string>(8);
                block.time = row.get<std::chrono::system_clock::time_point>(9);
                block.currencyName = row.get<std::string>(10);
                tx.block = block;
            }

            if (row.get_indicator(11) != i_null &&
                    row.get_indicator(12) != i_null &&
                    row.get_indicator(13) != i_null) {
                tx.memos.push_back(api::RippleLikeMemo(
                        row.get<std::string>(11),
                        row.get<std::string>(12),
                        row.get<std::string>(13)
                ));
            }

            return true;
        }

        bool RippleLikeTransactionDatabaseHelper::transactionExists(soci::session &sql,
                                                                    const std::string &rippleTxUid) {
            int32_t count = 0;
            sql << "SELECT COUNT(*) FROM ripple_transactions WHERE transaction_uid = :rippleTxUid", use(rippleTxUid), into(
                    count);
            return count == 1;
        }

        std::string RippleLikeTransactionDatabaseHelper::createRippleTransactionUid(const std::string &accountUid,
                                                                                const std::string &txHash) {
            auto result = SHA256::stringToHexHash(fmt::format("uid:{}+{}", accountUid, txHash));
            return result;
        }

        std::string RippleLikeTransactionDatabaseHelper::putTransaction(soci::session &sql,
                                                                        const std::string &accountUid,
                                                                        const RippleLikeBlockchainExplorerTransaction &tx) {
            auto blockUid = tx.block.map<std::string>([](const RippleLikeBlockchainExplorer::Block &block) {
                return block.getUid();
            });

            auto rippleTxUid = createRippleTransactionUid(accountUid, tx.hash);

            if (transactionExists(sql, rippleTxUid)) {
                // UPDATE (we only update block information)
                if (tx.block.nonEmpty()) {
                    sql << "UPDATE ripple_transactions SET block_uid = :uid WHERE hash = :tx_hash",
                            use(blockUid), use(tx.hash);
                }
                return rippleTxUid;
            } else {
                // Insert
                if (tx.block.nonEmpty()) {
                    BlockDatabaseHelper::putBlock(sql, tx.block.getValue());
                }
                auto hexValue = tx.value.toHexString();
                auto hexFees = tx.fees.toHexString();
                sql
                        << "INSERT INTO ripple_transactions VALUES(:tx_uid, :hash, :value, :block_uid, :time, :sender, :receiver, :fees, :confirmations)",
                        use(rippleTxUid),
                        use(tx.hash),
                        use(hexValue),
                        use(blockUid),
                        use(tx.receivedAt),
                        use(tx.sender),
                        use(tx.receiver),
                        use(hexFees),
                        use(tx.confirmations);

                int fieldIndex = 0;
                for (auto& memo : tx.memos) {
                    sql << "INSERT INTO ripple_memos VALUES (:tx_uid, :data, :fmt, :ty, :i)",
                           use(rippleTxUid),
                           use(memo.data),
                           use(memo.fmt),
                           use(memo.ty),
                           use(fieldIndex);

                    ++fieldIndex;
                }

                return rippleTxUid;
            }
        }
    }
}
<commit_msg>Get sequence when inflating XRP transaction.<commit_after>/*
 *
 * RIppleLikeTransactionDatabaseHelper
 *
 * Created by El Khalil Bellakrid on 06/01/2019.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "RippleLikeTransactionDatabaseHelper.h"
#include <database/soci-option.h>
#include <database/soci-date.h>
#include <database/soci-number.h>
#include <crypto/SHA256.hpp>
#include <wallet/common/database/BlockDatabaseHelper.h>

using namespace soci;

namespace ledger {
    namespace core {

        bool RippleLikeTransactionDatabaseHelper::getTransactionByHash(soci::session &sql,
                                                                       const std::string &hash,
                                                                       RippleLikeBlockchainExplorerTransaction &tx) {

            rowset<row> rows = (sql.prepare << "SELECT  tx.hash, tx.value, tx.time, "
                    " tx.sender, tx.receiver, tx.fees, tx.confirmations, "
                    "block.height, block.hash, block.time, block.currency_name, "
                    "memo.data, memo.fmt, memo.ty, tx.sequence "
                    "FROM ripple_transactions AS tx "
                    "LEFT JOIN blocks AS block ON tx.block_uid = block.uid "
                    "LEFT JOIN ripple_memos AS memo ON memo.transaction_uid = tx.transaction_uid "
                    "WHERE tx.hash = :hash "
                    "ORDER BY memo.array_index ASC", use(hash));

            for (auto &row : rows) {
                inflateTransaction(sql, row, tx);
                return true;
            }

            return false;
        }

        bool RippleLikeTransactionDatabaseHelper::inflateTransaction(soci::session &sql,
                                                                     const soci::row &row,
                                                                     RippleLikeBlockchainExplorerTransaction &tx) {
            tx.hash = row.get<std::string>(0);
            tx.value = BigInt::fromHex(row.get<std::string>(1));
            tx.receivedAt = row.get<std::chrono::system_clock::time_point>(2);
            tx.sender = row.get<std::string>(3);
            tx.receiver = row.get<std::string>(4);
            tx.fees = BigInt::fromHex(row.get<std::string>(5));
            tx.confirmations = get_number<uint64_t>(row, 6);
            if (row.get_indicator(7) != i_null) {
                RippleLikeBlockchainExplorer::Block block;
                block.height = get_number<uint64_t>(row, 7);
                block.hash = row.get<std::string>(8);
                block.time = row.get<std::chrono::system_clock::time_point>(9);
                block.currencyName = row.get<std::string>(10);
                tx.block = block;
            }

            if (row.get_indicator(11) != i_null &&
                    row.get_indicator(12) != i_null &&
                    row.get_indicator(13) != i_null) {
                tx.memos.push_back(api::RippleLikeMemo(
                        row.get<std::string>(11),
                        row.get<std::string>(12),
                        row.get<std::string>(13)
                ));
            }

            tx.sequence = BigInt(row.get<std::string>(14));

            return true;
        }

        bool RippleLikeTransactionDatabaseHelper::transactionExists(soci::session &sql,
                                                                    const std::string &rippleTxUid) {
            int32_t count = 0;
            sql << "SELECT COUNT(*) FROM ripple_transactions WHERE transaction_uid = :rippleTxUid", use(rippleTxUid), into(
                    count);
            return count == 1;
        }

        std::string RippleLikeTransactionDatabaseHelper::createRippleTransactionUid(const std::string &accountUid,
                                                                                const std::string &txHash) {
            auto result = SHA256::stringToHexHash(fmt::format("uid:{}+{}", accountUid, txHash));
            return result;
        }

        std::string RippleLikeTransactionDatabaseHelper::putTransaction(soci::session &sql,
                                                                        const std::string &accountUid,
                                                                        const RippleLikeBlockchainExplorerTransaction &tx) {
            auto blockUid = tx.block.map<std::string>([](const RippleLikeBlockchainExplorer::Block &block) {
                return block.getUid();
            });

            auto rippleTxUid = createRippleTransactionUid(accountUid, tx.hash);

            if (transactionExists(sql, rippleTxUid)) {
                // UPDATE (we only update block information)
                if (tx.block.nonEmpty()) {
                    sql << "UPDATE ripple_transactions SET block_uid = :uid WHERE hash = :tx_hash",
                            use(blockUid), use(tx.hash);
                }
                return rippleTxUid;
            } else {
                // Insert
                if (tx.block.nonEmpty()) {
                    BlockDatabaseHelper::putBlock(sql, tx.block.getValue());
                }
                auto hexValue = tx.value.toHexString();
                auto hexFees = tx.fees.toHexString();
                sql
                        << "INSERT INTO ripple_transactions VALUES(:tx_uid, :hash, :value, :block_uid, :time, :sender, :receiver, :fees, :confirmations)",
                        use(rippleTxUid),
                        use(tx.hash),
                        use(hexValue),
                        use(blockUid),
                        use(tx.receivedAt),
                        use(tx.sender),
                        use(tx.receiver),
                        use(hexFees),
                        use(tx.confirmations);

                int fieldIndex = 0;
                for (auto& memo : tx.memos) {
                    sql << "INSERT INTO ripple_memos VALUES (:tx_uid, :data, :fmt, :ty, :i)",
                           use(rippleTxUid),
                           use(memo.data),
                           use(memo.fmt),
                           use(memo.ty),
                           use(fieldIndex);

                    ++fieldIndex;
                }

                return rippleTxUid;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2022                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "modules/server/include/topics/skybrowsertopic.h"

#include <modules/server/include/connection.h>
#include <modules/server/servermodule.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>

namespace {
    constexpr const char* EventKey = "event";
    constexpr const char* SubscribeEvent = "start_subscription";
    constexpr const char* UnsubscribeEvent = "stop_subscription";
} // namespace

using nlohmann::json;

namespace openspace {

SkyBrowserTopic::SkyBrowserTopic()
    : _lastUpdateTime(std::chrono::system_clock::now())
{
    ServerModule* module = global::moduleEngine->module<ServerModule>();
    if (module) {
        _skyBrowserUpdateTime = std::chrono::milliseconds(module->skyBrowserUpdateTime());
    }
}

SkyBrowserTopic::~SkyBrowserTopic() {
    if (_targetDataCallbackHandle != UnsetOnChangeHandle) {
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        module->removePreSyncCallback(_targetDataCallbackHandle);
    }
}

bool SkyBrowserTopic::isDone() const {
    return _isDone;
}

void SkyBrowserTopic::handleJson(const nlohmann::json& json) {
    std::string event = json.at(EventKey).get<std::string>();
    if (event == UnsubscribeEvent) {
        _isDone = true;
        return;
    }

    if (event != SubscribeEvent) {
        _isDone = true;
        return;
    }

    SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
    _targetDataCallbackHandle = module->addPreSyncCallback([this]() {
        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
        if (now - _lastUpdateTime > _skyBrowserUpdateTime) {
            sendBrowserData();
            _lastUpdateTime = std::chrono::system_clock::now();
        }
    });
}

void SkyBrowserTopic::sendBrowserData() {
    using namespace openspace;

    SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
    ghoul::Dictionary data;

    // The current viewport data for OpenSpace
    ghoul::Dictionary openSpace;

    // Set general data
    data.setValue("selectedBrowserId", module->selectedBrowserId());
    data.setValue("cameraInSolarSystem", module->isCameraInSolarSystem());

    // Pass data for all the browsers and the corresponding targets
    if (module->isCameraInSolarSystem()) {
        const std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
        ghoul::Dictionary targets;
        for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
            std::string id = pair->browserId();
            // Convert deque to vector so ghoul can read it
            std::vector<int> selectedImagesVector;
            const std::deque<int> selectedImages = pair->selectedImages();
            std::for_each(
                selectedImages.begin(),
                selectedImages.end(),
                [&](int i) {
                    selectedImagesVector.push_back(i);
                }
            );

            glm::dvec2 spherical = pair->targetDirectionEquatorial();
            glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);

            ghoul::Dictionary target;
            // Set ("Key", value)
            target.setValue("id", id);
            target.setValue("name", pair->browserGuiName());
            target.setValue("fov", static_cast<double>(pair->verticalFov()));
            target.setValue("ra", spherical.x);
            target.setValue("dec", spherical.y);
            target.setValue("roll", pair->targetRoll());
            target.setValue("color", pair->borderColor());
            target.setValue("cartesianDirection", cartesian);
            target.setValue("ratio", static_cast<double>(pair->browserRatio()));
            target.setValue("isFacingCamera", pair->isFacingCamera());
            target.setValue("isUsingRae", pair->isUsingRadiusAzimuthElevation());
            target.setValue("selectedImages", selectedImagesVector);

            std::vector<std::pair<std::string, glm::dvec3>> copies = pair->renderCopies();
            ghoul::Dictionary copiesData;
            for (size_t i = 0; i < copies.size(); i++) {
                copiesData.setValue(copies[i].first, copies[i].second);
            }
            // Set table for the current target
            target.setValue("renderCopies", copiesData);
            targets.setValue(id, target);
        }
        data.setValue("browsers", targets);
    }
    std::string jsonString = ghoul::formatJson(data);
    json jsonData = json::parse(jsonString.begin(), jsonString.end());
    _connection->sendJson(wrappedPayload(jsonData));
}

} // namespace openspace
<commit_msg>Don't try to access module if it no longer exists<commit_after>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2022                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "modules/server/include/topics/skybrowsertopic.h"

#include <modules/server/include/connection.h>
#include <modules/server/servermodule.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>

namespace {
    constexpr const char* EventKey = "event";
    constexpr const char* SubscribeEvent = "start_subscription";
    constexpr const char* UnsubscribeEvent = "stop_subscription";
} // namespace

using nlohmann::json;

namespace openspace {

SkyBrowserTopic::SkyBrowserTopic()
    : _lastUpdateTime(std::chrono::system_clock::now())
{
    ServerModule* module = global::moduleEngine->module<ServerModule>();
    if (module) {
        _skyBrowserUpdateTime = std::chrono::milliseconds(module->skyBrowserUpdateTime());
    }
}

SkyBrowserTopic::~SkyBrowserTopic() {
    if (_targetDataCallbackHandle != UnsetOnChangeHandle) {
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        if (module) {
            module->removePreSyncCallback(_targetDataCallbackHandle);
        }
    }
}

bool SkyBrowserTopic::isDone() const {
    return _isDone;
}

void SkyBrowserTopic::handleJson(const nlohmann::json& json) {
    std::string event = json.at(EventKey).get<std::string>();
    if (event == UnsubscribeEvent) {
        _isDone = true;
        return;
    }

    if (event != SubscribeEvent) {
        _isDone = true;
        return;
    }

    SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
    _targetDataCallbackHandle = module->addPreSyncCallback([this]() {
        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
        if (now - _lastUpdateTime > _skyBrowserUpdateTime) {
            sendBrowserData();
            _lastUpdateTime = std::chrono::system_clock::now();
        }
    });
}

void SkyBrowserTopic::sendBrowserData() {
    using namespace openspace;

    SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
    ghoul::Dictionary data;

    // The current viewport data for OpenSpace
    ghoul::Dictionary openSpace;

    // Set general data
    data.setValue("selectedBrowserId", module->selectedBrowserId());
    data.setValue("cameraInSolarSystem", module->isCameraInSolarSystem());

    // Pass data for all the browsers and the corresponding targets
    if (module->isCameraInSolarSystem()) {
        const std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
        ghoul::Dictionary targets;
        for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
            std::string id = pair->browserId();
            // Convert deque to vector so ghoul can read it
            std::vector<int> selectedImagesVector;
            const std::deque<int> selectedImages = pair->selectedImages();
            std::for_each(
                selectedImages.begin(),
                selectedImages.end(),
                [&](int i) {
                    selectedImagesVector.push_back(i);
                }
            );

            glm::dvec2 spherical = pair->targetDirectionEquatorial();
            glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);

            ghoul::Dictionary target;
            // Set ("Key", value)
            target.setValue("id", id);
            target.setValue("name", pair->browserGuiName());
            target.setValue("fov", static_cast<double>(pair->verticalFov()));
            target.setValue("ra", spherical.x);
            target.setValue("dec", spherical.y);
            target.setValue("roll", pair->targetRoll());
            target.setValue("color", pair->borderColor());
            target.setValue("cartesianDirection", cartesian);
            target.setValue("ratio", static_cast<double>(pair->browserRatio()));
            target.setValue("isFacingCamera", pair->isFacingCamera());
            target.setValue("isUsingRae", pair->isUsingRadiusAzimuthElevation());
            target.setValue("selectedImages", selectedImagesVector);

            std::vector<std::pair<std::string, glm::dvec3>> copies = pair->renderCopies();
            ghoul::Dictionary copiesData;
            for (size_t i = 0; i < copies.size(); i++) {
                copiesData.setValue(copies[i].first, copies[i].second);
            }
            // Set table for the current target
            target.setValue("renderCopies", copiesData);
            targets.setValue(id, target);
        }
        data.setValue("browsers", targets);
    }
    std::string jsonString = ghoul::formatJson(data);
    json jsonData = json::parse(jsonString.begin(), jsonString.end());
    _connection->sendJson(wrappedPayload(jsonData));
}

} // namespace openspace
<|endoftext|>


<commit_before>#ifndef slic3r_Mouse3DController_hpp_
#define slic3r_Mouse3DController_hpp_

// Enabled debug output to console and extended imgui dialog
#define ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT 0

#include "libslic3r/Point.hpp"

#include "hidapi.h"

#include <queue>
#include <thread>
#include <vector>
#include <chrono>

#include <tbb/mutex.h>

namespace Slic3r {

class AppConfig;

namespace GUI {

struct Camera;
class GLCanvas3D;

class Mouse3DController
{
	// Parameters, which are configured by the ImGUI dialog when pressing Ctrl+M.
	// The UI thread modifies a copy of the parameters and indicates to the background thread that there was a change
	// to copy the parameters.
	struct Params
	{
		static constexpr double DefaultTranslationScale = 2.5;
		static constexpr double MaxTranslationDeadzone = 0.2;
		static constexpr double DefaultTranslationDeadzone = 0.5 * MaxTranslationDeadzone;
		static constexpr float  DefaultRotationScale = 1.0f;
		static constexpr float  MaxRotationDeadzone = 0.2f;
		static constexpr float  DefaultRotationDeadzone = 0.5f * MaxRotationDeadzone;
		static constexpr double DefaultZoomScale = 0.1;

        template <typename Number>
        struct CustomParameters
        {
            Number scale;
            Number deadzone;
        };

        CustomParameters<double> translation { DefaultTranslationScale, DefaultTranslationDeadzone };
        CustomParameters<float>  rotation { DefaultRotationScale, DefaultRotationDeadzone };
        CustomParameters<double> zoom { DefaultZoomScale, 0.0 };
        // Do not process button presses from 3DConnexion device, let the user map the 3DConnexion keys in 3DConnexion driver.
        bool 					 buttons_enabled { false };
        // The default value of 15 for max_size seems to work fine on all platforms
        // The effects of changing this value can be tested by setting ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT to 1
        // and playing with the imgui dialog which shows by pressing CTRL+M
        size_t 					 input_queue_max_size { 15 };
	};

	// Queue of the 3DConnexion input events (translations, rotations, button presses).
    class State
    {
    public:
        struct QueueItem {
            static QueueItem translation(const Vec3d &translation) { QueueItem out; out.vector = translation; out.type_or_buttons = TranslationType; return out; }
            static QueueItem rotation(const Vec3d &rotation) { QueueItem out; out.vector = rotation; out.type_or_buttons = RotationType; return out; }
            static QueueItem buttons(unsigned int buttons) { QueueItem out; out.type_or_buttons = buttons; return out; }

            bool 			 is_translation() const { return this->type_or_buttons == TranslationType; }
            bool 			 is_rotation() const { return this->type_or_buttons == RotationType; }
            bool 			 is_buttons() const { return ! this->is_translation() && ! this->is_rotation(); }

            Vec3d        	 vector;
            unsigned int 	 type_or_buttons;

            static constexpr unsigned int TranslationType = std::numeric_limits<unsigned int>::max();
            static constexpr unsigned int RotationType    = TranslationType - 1;
        };

    private:
    	// m_input_queue is accessed by the background thread and by the UI thread. Access to m_input_queue
    	// is guarded with m_input_queue_mutex.
        std::deque<QueueItem> m_input_queue;
        mutable tbb::mutex	  m_input_queue_mutex;

#ifdef WIN32
        // When the 3Dconnexion driver is running the system gets, by default, mouse wheel events when rotations around the X axis are detected.
        // We want to filter these out because we are getting the data directly from the device, bypassing the driver, and those mouse wheel events interfere
        // by triggering unwanted zoom in/out of the scene
        // The following variable is used to count the potential mouse wheel events triggered and is updated by:
        // Mouse3DController::collect_input() through the call to the append_rotation() method
        // GLCanvas3D::on_mouse_wheel() through the call to the process_mouse_wheel() method
        // GLCanvas3D::on_idle() through the call to the apply() method
        unsigned int 		  m_mouse_wheel_counter { 0 };
#endif /* WIN32 */

    public:
        // Called by the background thread or by by Mouse3DHandlerMac.mm when a new event is received from 3DConnexion device.
        void append_translation(const Vec3d& translation, size_t input_queue_max_size);
        void append_rotation(const Vec3f& rotation, size_t input_queue_max_size);
        void append_button(unsigned int id, size_t input_queue_max_size);

#ifdef WIN32
        // Called by GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
        // to filter out spurious mouse scroll events produced by the 3DConnexion driver on Windows.
        bool process_mouse_wheel();
#endif /* WIN32 */

#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
        Vec3d               get_first_vector_of_type(unsigned int type) const {
            tbb::mutex::scoped_lock lock(m_input_queue_mutex);
            auto it = std::find_if(m_input_queue.begin(), m_input_queue.end(), [type](const QueueItem& item) { return item.type_or_buttons == type; });
            return (it == m_input_queue.end()) ? Vec3d::Zero() : it->vector;
        }
        size_t              input_queue_size_current() const {
        	tbb::mutex::scoped_lock lock(m_input_queue_mutex);
        	return m_input_queue.size();
        }
        std::atomic<size_t> input_queue_max_size_achieved;
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT

        // Apply the 3DConnexion events stored in the input queue, reset the input queue.
        // Returns true if any change to the camera took place.
        bool apply(const Params &params, Camera& camera);
    };

    // Background thread works with this copy.
    Params 				m_params;
    // UI thread will read / write this copy.
    Params 				m_params_ui;
    bool 	            m_params_ui_changed { false };
    mutable tbb::mutex	m_params_ui_mutex;

    // This is a database of parametes of all 3DConnexion devices ever connected.
    // This database is loaded from AppConfig on application start and it is stored to AppConfig on application exit.
    // We need to do that as the AppConfig is not thread safe and we need read the parameters on device connect / disconnect,
    // which is now done by a background thread.
    std::map<std::string, Params> m_params_by_device;

    mutable State 		m_state;
    std::atomic<bool> 	m_connected;
    std::string 		m_device_str;

#if ! __APPLE__
    // Worker thread for enumerating devices, connecting, reading data from the device and closing the device.
    std::thread 		m_thread;
    hid_device* 		m_device { nullptr };
    // Using m_stop_condition_mutex to synchronize m_stop.
    bool				m_stop { false };
    // Mutex and condition variable for sleeping during the detection of 3DConnexion devices by polling while allowing
    // cancellation before the end of the polling interval.
	std::mutex 			m_stop_condition_mutex;
   	std::condition_variable m_stop_condition;
#endif

   	// Is the ImGUI dialog shown? Accessed from UI thread only.
    mutable bool 		m_show_settings_dialog { false };
    // Set to true when ther user closes the dialog by clicking on [X] or [Close] buttons. Accessed from UI thread only.
    mutable bool 		m_settings_dialog_closed_by_user { false };

public:
	// Load the device parameter database from appconfig. To be called on application startup.
	void load_config(const AppConfig &appconfig);
	// Store the device parameter database back to appconfig. To be called on application closeup.
	void save_config(AppConfig &appconfig) const;
	// Start the background thread to detect and connect to a HID device (Windows and Linux).
	// Connect to a 3DConnextion driver (OSX).
	// Call load_config() before init().
    void init();
	// Stop the background thread (Windows and Linux).
	// Disconnect from a 3DConnextion driver (OSX).
	// Call save_config() after shutdown().
    void shutdown();

    bool connected() const { return m_connected; }

#if __APPLE__
    // Interfacing with the Objective C code (MouseHandlerMac.mm)
    void connected(std::string device_name);
    void disconnected();
    typedef std::array<double, 6> DataPacketAxis;
	// Unpack a 3DConnexion packet provided by the 3DConnexion driver into m_state. Called by Mouse3DHandlerMac.mm
    bool handle_input(const DataPacketAxis& packet);
#endif // __APPLE__

#ifdef WIN32
    // On Windows, the 3DConnexion driver sends out mouse wheel rotation events to an active application
    // if the application does not register at the driver. This is a workaround to ignore these superfluous
    // mouse wheel events.
    bool process_mouse_wheel() { return m_state.process_mouse_wheel(); }
#endif // WIN32

    // Apply the received 3DConnexion mouse events to the camera. Called from the UI rendering thread.
    bool apply(Camera& camera);

    bool is_settings_dialog_shown() const { return m_show_settings_dialog; }
    void show_settings_dialog(bool show) { m_show_settings_dialog = show && this->connected(); }
    void render_settings_dialog(GLCanvas3D& canvas) const;

#if ! __APPLE__
private:
    bool connect_device();
    void disconnect_device();

    // secondary thread methods
    void run();
    void collect_input();

    typedef std::array<unsigned char, 13> DataPacketRaw;

	// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
    static bool handle_input(const DataPacketRaw& packet, const int packet_lenght, const Params &params, State &state_in_out);
    // The following is called by handle_input() from the worker thread.
    static bool handle_packet(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_wireless_packet(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_packet_translation(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_packet_rotation(const DataPacketRaw& packet, unsigned int first_byte, const Params &params, State &state_in_out);
    static bool handle_packet_button(const DataPacketRaw& packet, unsigned int packet_size, const Params &params, State &state_in_out);
#endif /* __APPLE__ */
};

} // namespace GUI
} // namespace Slic3r

#endif // slic3r_Mouse3DController_hpp_
<commit_msg>Added a missing include<commit_after>#ifndef slic3r_Mouse3DController_hpp_
#define slic3r_Mouse3DController_hpp_

// Enabled debug output to console and extended imgui dialog
#define ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT 0

#include "libslic3r/Point.hpp"

#include "hidapi.h"

#include <queue>
#include <thread>
#include <vector>
#include <chrono>
#include <condition_variable>

#include <tbb/mutex.h>

namespace Slic3r {

class AppConfig;

namespace GUI {

struct Camera;
class GLCanvas3D;

class Mouse3DController
{
	// Parameters, which are configured by the ImGUI dialog when pressing Ctrl+M.
	// The UI thread modifies a copy of the parameters and indicates to the background thread that there was a change
	// to copy the parameters.
	struct Params
	{
		static constexpr double DefaultTranslationScale = 2.5;
		static constexpr double MaxTranslationDeadzone = 0.2;
		static constexpr double DefaultTranslationDeadzone = 0.5 * MaxTranslationDeadzone;
		static constexpr float  DefaultRotationScale = 1.0f;
		static constexpr float  MaxRotationDeadzone = 0.2f;
		static constexpr float  DefaultRotationDeadzone = 0.5f * MaxRotationDeadzone;
		static constexpr double DefaultZoomScale = 0.1;

        template <typename Number>
        struct CustomParameters
        {
            Number scale;
            Number deadzone;
        };

        CustomParameters<double> translation { DefaultTranslationScale, DefaultTranslationDeadzone };
        CustomParameters<float>  rotation { DefaultRotationScale, DefaultRotationDeadzone };
        CustomParameters<double> zoom { DefaultZoomScale, 0.0 };
        // Do not process button presses from 3DConnexion device, let the user map the 3DConnexion keys in 3DConnexion driver.
        bool 					 buttons_enabled { false };
        // The default value of 15 for max_size seems to work fine on all platforms
        // The effects of changing this value can be tested by setting ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT to 1
        // and playing with the imgui dialog which shows by pressing CTRL+M
        size_t 					 input_queue_max_size { 15 };
	};

	// Queue of the 3DConnexion input events (translations, rotations, button presses).
    class State
    {
    public:
        struct QueueItem {
            static QueueItem translation(const Vec3d &translation) { QueueItem out; out.vector = translation; out.type_or_buttons = TranslationType; return out; }
            static QueueItem rotation(const Vec3d &rotation) { QueueItem out; out.vector = rotation; out.type_or_buttons = RotationType; return out; }
            static QueueItem buttons(unsigned int buttons) { QueueItem out; out.type_or_buttons = buttons; return out; }

            bool 			 is_translation() const { return this->type_or_buttons == TranslationType; }
            bool 			 is_rotation() const { return this->type_or_buttons == RotationType; }
            bool 			 is_buttons() const { return ! this->is_translation() && ! this->is_rotation(); }

            Vec3d        	 vector;
            unsigned int 	 type_or_buttons;

            static constexpr unsigned int TranslationType = std::numeric_limits<unsigned int>::max();
            static constexpr unsigned int RotationType    = TranslationType - 1;
        };

    private:
    	// m_input_queue is accessed by the background thread and by the UI thread. Access to m_input_queue
    	// is guarded with m_input_queue_mutex.
        std::deque<QueueItem> m_input_queue;
        mutable tbb::mutex	  m_input_queue_mutex;

#ifdef WIN32
        // When the 3Dconnexion driver is running the system gets, by default, mouse wheel events when rotations around the X axis are detected.
        // We want to filter these out because we are getting the data directly from the device, bypassing the driver, and those mouse wheel events interfere
        // by triggering unwanted zoom in/out of the scene
        // The following variable is used to count the potential mouse wheel events triggered and is updated by:
        // Mouse3DController::collect_input() through the call to the append_rotation() method
        // GLCanvas3D::on_mouse_wheel() through the call to the process_mouse_wheel() method
        // GLCanvas3D::on_idle() through the call to the apply() method
        unsigned int 		  m_mouse_wheel_counter { 0 };
#endif /* WIN32 */

    public:
        // Called by the background thread or by by Mouse3DHandlerMac.mm when a new event is received from 3DConnexion device.
        void append_translation(const Vec3d& translation, size_t input_queue_max_size);
        void append_rotation(const Vec3f& rotation, size_t input_queue_max_size);
        void append_button(unsigned int id, size_t input_queue_max_size);

#ifdef WIN32
        // Called by GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
        // to filter out spurious mouse scroll events produced by the 3DConnexion driver on Windows.
        bool process_mouse_wheel();
#endif /* WIN32 */

#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
        Vec3d               get_first_vector_of_type(unsigned int type) const {
            tbb::mutex::scoped_lock lock(m_input_queue_mutex);
            auto it = std::find_if(m_input_queue.begin(), m_input_queue.end(), [type](const QueueItem& item) { return item.type_or_buttons == type; });
            return (it == m_input_queue.end()) ? Vec3d::Zero() : it->vector;
        }
        size_t              input_queue_size_current() const {
        	tbb::mutex::scoped_lock lock(m_input_queue_mutex);
        	return m_input_queue.size();
        }
        std::atomic<size_t> input_queue_max_size_achieved;
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT

        // Apply the 3DConnexion events stored in the input queue, reset the input queue.
        // Returns true if any change to the camera took place.
        bool apply(const Params &params, Camera& camera);
    };

    // Background thread works with this copy.
    Params 				m_params;
    // UI thread will read / write this copy.
    Params 				m_params_ui;
    bool 	            m_params_ui_changed { false };
    mutable tbb::mutex	m_params_ui_mutex;

    // This is a database of parametes of all 3DConnexion devices ever connected.
    // This database is loaded from AppConfig on application start and it is stored to AppConfig on application exit.
    // We need to do that as the AppConfig is not thread safe and we need read the parameters on device connect / disconnect,
    // which is now done by a background thread.
    std::map<std::string, Params> m_params_by_device;

    mutable State 		m_state;
    std::atomic<bool> 	m_connected;
    std::string 		m_device_str;

#if ! __APPLE__
    // Worker thread for enumerating devices, connecting, reading data from the device and closing the device.
    std::thread 		m_thread;
    hid_device* 		m_device { nullptr };
    // Using m_stop_condition_mutex to synchronize m_stop.
    bool				m_stop { false };
    // Mutex and condition variable for sleeping during the detection of 3DConnexion devices by polling while allowing
    // cancellation before the end of the polling interval.
	std::mutex 			m_stop_condition_mutex;
   	std::condition_variable m_stop_condition;
#endif

   	// Is the ImGUI dialog shown? Accessed from UI thread only.
    mutable bool 		m_show_settings_dialog { false };
    // Set to true when ther user closes the dialog by clicking on [X] or [Close] buttons. Accessed from UI thread only.
    mutable bool 		m_settings_dialog_closed_by_user { false };

public:
	// Load the device parameter database from appconfig. To be called on application startup.
	void load_config(const AppConfig &appconfig);
	// Store the device parameter database back to appconfig. To be called on application closeup.
	void save_config(AppConfig &appconfig) const;
	// Start the background thread to detect and connect to a HID device (Windows and Linux).
	// Connect to a 3DConnextion driver (OSX).
	// Call load_config() before init().
    void init();
	// Stop the background thread (Windows and Linux).
	// Disconnect from a 3DConnextion driver (OSX).
	// Call save_config() after shutdown().
    void shutdown();

    bool connected() const { return m_connected; }

#if __APPLE__
    // Interfacing with the Objective C code (MouseHandlerMac.mm)
    void connected(std::string device_name);
    void disconnected();
    typedef std::array<double, 6> DataPacketAxis;
	// Unpack a 3DConnexion packet provided by the 3DConnexion driver into m_state. Called by Mouse3DHandlerMac.mm
    bool handle_input(const DataPacketAxis& packet);
#endif // __APPLE__

#ifdef WIN32
    // On Windows, the 3DConnexion driver sends out mouse wheel rotation events to an active application
    // if the application does not register at the driver. This is a workaround to ignore these superfluous
    // mouse wheel events.
    bool process_mouse_wheel() { return m_state.process_mouse_wheel(); }
#endif // WIN32

    // Apply the received 3DConnexion mouse events to the camera. Called from the UI rendering thread.
    bool apply(Camera& camera);

    bool is_settings_dialog_shown() const { return m_show_settings_dialog; }
    void show_settings_dialog(bool show) { m_show_settings_dialog = show && this->connected(); }
    void render_settings_dialog(GLCanvas3D& canvas) const;

#if ! __APPLE__
private:
    bool connect_device();
    void disconnect_device();

    // secondary thread methods
    void run();
    void collect_input();

    typedef std::array<unsigned char, 13> DataPacketRaw;

	// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
    static bool handle_input(const DataPacketRaw& packet, const int packet_lenght, const Params &params, State &state_in_out);
    // The following is called by handle_input() from the worker thread.
    static bool handle_packet(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_wireless_packet(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_packet_translation(const DataPacketRaw& packet, const Params &params, State &state_in_out);
    static bool handle_packet_rotation(const DataPacketRaw& packet, unsigned int first_byte, const Params &params, State &state_in_out);
    static bool handle_packet_button(const DataPacketRaw& packet, unsigned int packet_size, const Params &params, State &state_in_out);
#endif /* __APPLE__ */
};

} // namespace GUI
} // namespace Slic3r

#endif // slic3r_Mouse3DController_hpp_
<|endoftext|>


<commit_before><commit_msg>Potential build problem fix.<commit_after><|endoftext|>