<commit_before>#include "depthai/pipeline/node/StereoDepth.hpp"

// standard
#include <fstream>

#include "spdlog/spdlog.h"

namespace dai {
namespace node {

StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId) : StereoDepth(par, nodeId, std::make_unique<StereoDepth::Properties>()) {}
StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId, std::unique_ptr<Properties> props)
    : NodeCRTP<Node, StereoDepth, StereoDepthProperties>(par, nodeId, std::move(props)),
      rawConfig(std::make_shared<RawStereoDepthConfig>()),
      initialConfig(rawConfig) {
    // 'properties' defaults already set
    setInputRefs({&inputConfig, &left, &right});
    setOutputRefs({&depth,
                   &disparity,
                   &syncedLeft,
                   &syncedRight,
                   &rectifiedLeft,
                   &rectifiedRight,
                   &outConfig,
                   &debugDispLrCheckIt1,
                   &debugDispLrCheckIt2,
                   &debugExtDispLrCheckIt1,
                   &debugExtDispLrCheckIt2,
                   &debugDispCostDump,
                   &confidenceMap});

    setDefaultProfilePreset(presetMode);
}

StereoDepth::Properties& StereoDepth::getProperties() {
    properties.initialConfig = *rawConfig;
    return properties;
}

void StereoDepth::loadCalibrationData(const std::vector<std::uint8_t>& data) {
    (void)data;
    spdlog::warn("{} is deprecated. This function call is replaced by Pipeline::setCalibrationData under pipeline. ", __func__);
}

void StereoDepth::loadCalibrationFile(const std::string& path) {
    (void)path;
    spdlog::warn("{} is deprecated. This function call is replaced by Pipeline::setCalibrationData under pipeline. ", __func__);
}

void StereoDepth::setEmptyCalibration(void) {
    setRectification(false);
    spdlog::warn("{} is deprecated. This function call can be replaced by Stereo::setRectification(false). ", __func__);
}

void StereoDepth::loadMeshData(const std::vector<std::uint8_t>& dataLeft, const std::vector<std::uint8_t>& dataRight) {
    if(dataLeft.size() != dataRight.size()) {
        throw std::runtime_error("StereoDepth | left and right mesh sizes must match");
    }

    Asset meshAsset;
    std::string assetKey;
    meshAsset.alignment = 64;

    meshAsset.data = dataLeft;
    assetKey = "meshLeft";
    properties.mesh.meshLeftUri = assetManager.set(assetKey, meshAsset)->getRelativeUri();

    meshAsset.data = dataRight;
    assetKey = "meshRight";
    properties.mesh.meshRightUri = assetManager.set(assetKey, meshAsset)->getRelativeUri();

    properties.mesh.meshSize = static_cast<uint32_t>(meshAsset.data.size());
}

void StereoDepth::loadMeshFiles(const std::string& pathLeft, const std::string& pathRight) {
    std::ifstream streamLeft(pathLeft, std::ios::binary);
    if(!streamLeft.is_open()) {
        throw std::runtime_error("StereoDepth | Cannot open mesh at path: " + pathLeft);
    }
    std::vector<std::uint8_t> dataLeft = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(streamLeft), {});

    std::ifstream streamRight(pathRight, std::ios::binary);
    if(!streamRight.is_open()) {
        throw std::runtime_error("StereoDepth | Cannot open mesh at path: " + pathRight);
    }
    std::vector<std::uint8_t> dataRight = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(streamRight), {});

    loadMeshData(dataLeft, dataRight);
}

void StereoDepth::setMeshStep(int width, int height) {
    properties.mesh.stepWidth = width;
    properties.mesh.stepHeight = height;
}

void StereoDepth::setInputResolution(int width, int height) {
    properties.width = width;
    properties.height = height;
}
void StereoDepth::setInputResolution(std::tuple<int, int> resolution) {
    setInputResolution(std::get<0>(resolution), std::get<1>(resolution));
}
void StereoDepth::setOutputSize(int width, int height) {
    properties.outWidth = width;
    properties.outHeight = height;
}
void StereoDepth::setOutputKeepAspectRatio(bool keep) {
    properties.outKeepAspectRatio = keep;
}
void StereoDepth::setMedianFilter(dai::MedianFilter median) {
    initialConfig.setMedianFilter(median);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setDepthAlign(Properties::DepthAlign align) {
    initialConfig.setDepthAlign(align);
    // Unset 'depthAlignCamera', that would take precedence otherwise
    properties.depthAlignCamera = CameraBoardSocket::AUTO;
}
void StereoDepth::setDepthAlign(CameraBoardSocket camera) {
    properties.depthAlignCamera = camera;
}
void StereoDepth::setConfidenceThreshold(int confThr) {
    initialConfig.setConfidenceThreshold(confThr);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setRectification(bool enable) {
    properties.enableRectification = enable;
}
void StereoDepth::setLeftRightCheck(bool enable) {
    initialConfig.setLeftRightCheck(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setSubpixel(bool enable) {
    initialConfig.setSubpixel(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setExtendedDisparity(bool enable) {
    initialConfig.setExtendedDisparity(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setRectifyEdgeFillColor(int color) {
    properties.rectifyEdgeFillColor = color;
}
void StereoDepth::setRectifyMirrorFrame(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated.", __func__);
}
void StereoDepth::setOutputRectified(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}
void StereoDepth::setOutputDepth(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}

void StereoDepth::setRuntimeModeSwitch(bool enable) {
    properties.enableRuntimeStereoModeSwitch = enable;
}

void StereoDepth::setNumFramesPool(int numFramesPool) {
    properties.numFramesPool = numFramesPool;
}

float StereoDepth::getMaxDisparity() const {
    return initialConfig.getMaxDisparity();
}

void StereoDepth::setPostProcessingHardwareResources(int numShaves, int numMemorySlices) {
    properties.numPostProcessingShaves = numShaves;
    properties.numPostProcessingMemorySlices = numMemorySlices;
}

void StereoDepth::setDefaultProfilePreset(PresetMode mode) {
    presetMode = mode;
    switch(presetMode) {
        case PresetMode::HIGH_ACCURACY: {
            initialConfig.setConfidenceThreshold(200);
            initialConfig.setLeftRightCheck(5);
        } break;
        case PresetMode::HIGH_DENSITY: {
            initialConfig.setConfidenceThreshold(245);
            initialConfig.setLeftRightCheck(10);
        } break;
    }
}

}  // namespace node
}  // namespace dai
<commit_msg>Fix StereoDepth::setDefaultProfilePreset<commit_after>#include "depthai/pipeline/node/StereoDepth.hpp"

// standard
#include <fstream>

#include "spdlog/spdlog.h"

namespace dai {
namespace node {

StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId) : StereoDepth(par, nodeId, std::make_unique<StereoDepth::Properties>()) {}
StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId, std::unique_ptr<Properties> props)
    : NodeCRTP<Node, StereoDepth, StereoDepthProperties>(par, nodeId, std::move(props)),
      rawConfig(std::make_shared<RawStereoDepthConfig>()),
      initialConfig(rawConfig) {
    // 'properties' defaults already set
    setInputRefs({&inputConfig, &left, &right});
    setOutputRefs({&depth,
                   &disparity,
                   &syncedLeft,
                   &syncedRight,
                   &rectifiedLeft,
                   &rectifiedRight,
                   &outConfig,
                   &debugDispLrCheckIt1,
                   &debugDispLrCheckIt2,
                   &debugExtDispLrCheckIt1,
                   &debugExtDispLrCheckIt2,
                   &debugDispCostDump,
                   &confidenceMap});

    setDefaultProfilePreset(presetMode);
}

StereoDepth::Properties& StereoDepth::getProperties() {
    properties.initialConfig = *rawConfig;
    return properties;
}

void StereoDepth::loadCalibrationData(const std::vector<std::uint8_t>& data) {
    (void)data;
    spdlog::warn("{} is deprecated. This function call is replaced by Pipeline::setCalibrationData under pipeline. ", __func__);
}

void StereoDepth::loadCalibrationFile(const std::string& path) {
    (void)path;
    spdlog::warn("{} is deprecated. This function call is replaced by Pipeline::setCalibrationData under pipeline. ", __func__);
}

void StereoDepth::setEmptyCalibration(void) {
    setRectification(false);
    spdlog::warn("{} is deprecated. This function call can be replaced by Stereo::setRectification(false). ", __func__);
}

void StereoDepth::loadMeshData(const std::vector<std::uint8_t>& dataLeft, const std::vector<std::uint8_t>& dataRight) {
    if(dataLeft.size() != dataRight.size()) {
        throw std::runtime_error("StereoDepth | left and right mesh sizes must match");
    }

    Asset meshAsset;
    std::string assetKey;
    meshAsset.alignment = 64;

    meshAsset.data = dataLeft;
    assetKey = "meshLeft";
    properties.mesh.meshLeftUri = assetManager.set(assetKey, meshAsset)->getRelativeUri();

    meshAsset.data = dataRight;
    assetKey = "meshRight";
    properties.mesh.meshRightUri = assetManager.set(assetKey, meshAsset)->getRelativeUri();

    properties.mesh.meshSize = static_cast<uint32_t>(meshAsset.data.size());
}

void StereoDepth::loadMeshFiles(const std::string& pathLeft, const std::string& pathRight) {
    std::ifstream streamLeft(pathLeft, std::ios::binary);
    if(!streamLeft.is_open()) {
        throw std::runtime_error("StereoDepth | Cannot open mesh at path: " + pathLeft);
    }
    std::vector<std::uint8_t> dataLeft = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(streamLeft), {});

    std::ifstream streamRight(pathRight, std::ios::binary);
    if(!streamRight.is_open()) {
        throw std::runtime_error("StereoDepth | Cannot open mesh at path: " + pathRight);
    }
    std::vector<std::uint8_t> dataRight = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(streamRight), {});

    loadMeshData(dataLeft, dataRight);
}

void StereoDepth::setMeshStep(int width, int height) {
    properties.mesh.stepWidth = width;
    properties.mesh.stepHeight = height;
}

void StereoDepth::setInputResolution(int width, int height) {
    properties.width = width;
    properties.height = height;
}
void StereoDepth::setInputResolution(std::tuple<int, int> resolution) {
    setInputResolution(std::get<0>(resolution), std::get<1>(resolution));
}
void StereoDepth::setOutputSize(int width, int height) {
    properties.outWidth = width;
    properties.outHeight = height;
}
void StereoDepth::setOutputKeepAspectRatio(bool keep) {
    properties.outKeepAspectRatio = keep;
}
void StereoDepth::setMedianFilter(dai::MedianFilter median) {
    initialConfig.setMedianFilter(median);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setDepthAlign(Properties::DepthAlign align) {
    initialConfig.setDepthAlign(align);
    // Unset 'depthAlignCamera', that would take precedence otherwise
    properties.depthAlignCamera = CameraBoardSocket::AUTO;
}
void StereoDepth::setDepthAlign(CameraBoardSocket camera) {
    properties.depthAlignCamera = camera;
}
void StereoDepth::setConfidenceThreshold(int confThr) {
    initialConfig.setConfidenceThreshold(confThr);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setRectification(bool enable) {
    properties.enableRectification = enable;
}
void StereoDepth::setLeftRightCheck(bool enable) {
    initialConfig.setLeftRightCheck(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setSubpixel(bool enable) {
    initialConfig.setSubpixel(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setExtendedDisparity(bool enable) {
    initialConfig.setExtendedDisparity(enable);
    properties.initialConfig = *rawConfig;
}
void StereoDepth::setRectifyEdgeFillColor(int color) {
    properties.rectifyEdgeFillColor = color;
}
void StereoDepth::setRectifyMirrorFrame(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated.", __func__);
}
void StereoDepth::setOutputRectified(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}
void StereoDepth::setOutputDepth(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}

void StereoDepth::setRuntimeModeSwitch(bool enable) {
    properties.enableRuntimeStereoModeSwitch = enable;
}

void StereoDepth::setNumFramesPool(int numFramesPool) {
    properties.numFramesPool = numFramesPool;
}

float StereoDepth::getMaxDisparity() const {
    return initialConfig.getMaxDisparity();
}

void StereoDepth::setPostProcessingHardwareResources(int numShaves, int numMemorySlices) {
    properties.numPostProcessingShaves = numShaves;
    properties.numPostProcessingMemorySlices = numMemorySlices;
}

void StereoDepth::setDefaultProfilePreset(PresetMode mode) {
    presetMode = mode;
    switch(presetMode) {
        case PresetMode::HIGH_ACCURACY: {
            initialConfig.setConfidenceThreshold(200);
            initialConfig.setLeftRightCheck(true);
            initialConfig.setLeftRightCheckThreshold(5);
        } break;
        case PresetMode::HIGH_DENSITY: {
            initialConfig.setConfidenceThreshold(245);
            initialConfig.setLeftRightCheck(true);
            initialConfig.setLeftRightCheckThreshold(10);
        } break;
    }
}

}  // namespace node
}  // namespace dai
<|endoftext|>


<commit_before>#include <assert.h>
#include <iostream>
#include <map>
#include <memory>
#include <vector>

#include "common/simhubdeviceplugin.h"
#include "main.h"

// -- public C FFI

extern "C" {

int simplug_init(SPHANDLE *plugin_instance, LoggingFunctionCB logger)
{
    *plugin_instance = new PokeyDevicePluginStateManager(logger);
    return 0;
}

 int simplug_config_passthrough(SPHANDLE plugin_instance, void *libconfig_instance)
 {
    return static_cast<PluginStateManager *>(plugin_instance)->configPassthrough(static_cast<libconfig::Config *>(libconfig_instance));
 }

int simplug_preflight_complete(SPHANDLE plugin_instance)
{
    return static_cast<PluginStateManager *>(plugin_instance)->preflightComplete();
}

void simplug_commence_eventing(SPHANDLE plugin_instance, EnqueueEventHandler enqueue_callback, void *arg)
{
    static_cast<PluginStateManager *>(plugin_instance)->commenceEventing(enqueue_callback, arg);
}

int simplug_deliver_value(SPHANDLE plugin_instance, genericTLV *value)
{
    return static_cast<PluginStateManager *>(plugin_instance)->deliverValue(value);
}

void simplug_cease_eventing(SPHANDLE plugin_instance)
{
    static_cast<PluginStateManager *>(plugin_instance)->ceaseEventing();
}

void simplug_release(SPHANDLE plugin_instance)
{
    assert(plugin_instance);
    delete static_cast<PluginStateManager *>(plugin_instance);
}
}

PokeyDevicePluginStateManager *PokeyDevicePluginStateManager::_StateManagerInstance = NULL;

// -- private C++ pokey plugin implementation

PokeyDevicePluginStateManager::PokeyDevicePluginStateManager(LoggingFunctionCB logger)
    : PluginStateManager(logger)
{
    _numberOfDevices = 0; ///< 0 devices discovered
    _devices = (sPoKeysNetworkDeviceSummary *)calloc(sizeof(sPoKeysNetworkDeviceSummary), 16); ///<0 initialise the network device summary
}

//! static getter for singleton instance of our class
PokeyDevicePluginStateManager *PokeyDevicePluginStateManager::StateManagerInstance(void)
{
    return _StateManagerInstance;
}

PokeyDevicePluginStateManager::~PokeyDevicePluginStateManager(void)
{
    // TODO: enable once shtudown implemented
    if (_pluginThread != NULL) {
        if (_pluginThread->joinable()) {
            ceaseEventing();
            _pluginThread->join();
        }
        _deviceList.clear();
        delete _pluginThread;
    }
}

int PokeyDevicePluginStateManager::deliverValue(genericTLV *value)
{
    assert(value);
    _logger(LOG_INFO, "Pokey plugin to deliver: %s", value->name);
    return 0;
}

void PokeyDevicePluginStateManager::enumerateDevices(void)
{
    _numberOfDevices = PK_EnumerateNetworkDevices(_devices,800);
    assert(_numberOfDevices > 0);

    for (int i = 0; i < _numberOfDevices; i++) {
        pokeyDeviceSharedPointer device = std::make_shared<PokeyDevice>(_devices[i], i);

        _logger(LOG_INFO, "    - #%s %s %s (v%d.%d.%d) - %u.%u.%u.%u ",
                device->serialNumber().c_str(),
                device->hardwareTypeString().c_str(),
                device->deviceData().DeviceName,
                device->firmwareMajorMajorVersion(),
                device->firmwareMajorVersion(),
                device->firmwareMinorVersion(),
                device->ipAddress()[0],
                device->ipAddress()[1],
                device->ipAddress()[2],
                device->ipAddress()[3]);

        _deviceList.emplace(device->serialNumber(), device);

    }
}

pokeyDeviceSharedPointer PokeyDevicePluginStateManager::device(std::string serialNumber)
{
    if (_deviceList.count(serialNumber)){
        return _deviceList.find(serialNumber)->second;
    } else{
        return NULL;
    }
}

bool PokeyDevicePluginStateManager::validateConfig(libconfig::SettingIterator iter)
{
    bool retValue = true;
     try {
         iter->lookup("pins");
    } catch(const libconfig::SettingNotFoundException &nfex){
        _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
        retValue = false;
    }
    return retValue;

}

int PokeyDevicePluginStateManager::preflightComplete(void)
{
    int retVal = PREFLIGHT_OK;

    enumerateDevices();

    libconfig::Setting *devicesSetting;

    try {
        devicesSetting = &_config->lookup("configuration");
    } catch(const libconfig::SettingNotFoundException &nfex){
        _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
    }

    for (libconfig::SettingIterator iter = devicesSetting->begin(); iter != devicesSetting->end(); iter++) {
        std::string serialNumber;
        std::string name;

        // check that the configuration has the required config sections
        if (!validateConfig(iter)){
            continue;
        }

        try {
             iter->lookupValue("serialNumber",serialNumber);
             pokeyDeviceSharedPointer pokeyDevice = device(serialNumber);

             if (pokeyDevice == NULL){
                _logger(LOG_ERROR, "    - #%s. No physical device. Skipping....", serialNumber.c_str());
                 continue;
             }

            iter->lookupValue("name",name);
            _logger(LOG_INFO,"^^^^ %s",pokeyDevice->name().c_str());

        }
        catch (const libconfig::SettingNotFoundException &nfex) {
            _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
            continue;
        }

    }

    if (_numberOfDevices > 0) {
        _logger(LOG_INFO, "  - Discovered %d pokey devices", _numberOfDevices);
        retVal = PREFLIGHT_OK;
    }
    else {
        _logger(LOG_INFO, "   - No Pokey devices discovered");
    }

    return retVal;
}
<commit_msg>checking if the name in the configuration is different to the name returned from the device<commit_after>#include <assert.h>
#include <iostream>
#include <map>
#include <memory>
#include <vector>

#include "common/simhubdeviceplugin.h"
#include "main.h"

// -- public C FFI

extern "C" {

int simplug_init(SPHANDLE *plugin_instance, LoggingFunctionCB logger)
{
    *plugin_instance = new PokeyDevicePluginStateManager(logger);
    return 0;
}

int simplug_config_passthrough(SPHANDLE plugin_instance, void *libconfig_instance)
{
    return static_cast<PluginStateManager *>(plugin_instance)->configPassthrough(static_cast<libconfig::Config *>(libconfig_instance));
}

int simplug_preflight_complete(SPHANDLE plugin_instance)
{
    return static_cast<PluginStateManager *>(plugin_instance)->preflightComplete();
}

void simplug_commence_eventing(SPHANDLE plugin_instance, EnqueueEventHandler enqueue_callback, void *arg)
{
    static_cast<PluginStateManager *>(plugin_instance)->commenceEventing(enqueue_callback, arg);
}

int simplug_deliver_value(SPHANDLE plugin_instance, genericTLV *value)
{
    return static_cast<PluginStateManager *>(plugin_instance)->deliverValue(value);
}

void simplug_cease_eventing(SPHANDLE plugin_instance)
{
    static_cast<PluginStateManager *>(plugin_instance)->ceaseEventing();
}

void simplug_release(SPHANDLE plugin_instance)
{
    assert(plugin_instance);
    delete static_cast<PluginStateManager *>(plugin_instance);
}
}

PokeyDevicePluginStateManager *PokeyDevicePluginStateManager::_StateManagerInstance = NULL;

// -- private C++ pokey plugin implementation

PokeyDevicePluginStateManager::PokeyDevicePluginStateManager(LoggingFunctionCB logger)
    : PluginStateManager(logger)
{
    _numberOfDevices = 0; ///< 0 devices discovered
    _devices = (sPoKeysNetworkDeviceSummary *)calloc(sizeof(sPoKeysNetworkDeviceSummary),
        16); ///< 0 initialise the network device summary
}

//! static getter for singleton instance of our class
PokeyDevicePluginStateManager *PokeyDevicePluginStateManager::StateManagerInstance(void)
{
    return _StateManagerInstance;
}

PokeyDevicePluginStateManager::~PokeyDevicePluginStateManager(void)
{
    // TODO: enable once shtudown implemented
    if (_pluginThread != NULL) {
        if (_pluginThread->joinable()) {
            ceaseEventing();
            _pluginThread->join();
        }
        _deviceList.clear();
        delete _pluginThread;
    }
}

int PokeyDevicePluginStateManager::deliverValue(genericTLV *value)
{
    assert(value);
    _logger(LOG_INFO, "Pokey plugin to deliver: %s", value->name);
    return 0;
}

void PokeyDevicePluginStateManager::enumerateDevices(void)
{
    _numberOfDevices = PK_EnumerateNetworkDevices(_devices, 800);
    assert(_numberOfDevices > 0);

    for (int i = 0; i < _numberOfDevices; i++) {
        pokeyDeviceSharedPointer device = std::make_shared<PokeyDevice>(_devices[i], i);

        _logger(LOG_INFO, "    - #%s %s %s (v%d.%d.%d) - %u.%u.%u.%u ", device->serialNumber().c_str(), device->hardwareTypeString().c_str(), device->deviceData().DeviceName,
            device->firmwareMajorMajorVersion(), device->firmwareMajorVersion(), device->firmwareMinorVersion(), device->ipAddress()[0], device->ipAddress()[1],
            device->ipAddress()[2], device->ipAddress()[3]);

        _deviceList.emplace(device->serialNumber(), device);
    }
}

pokeyDeviceSharedPointer PokeyDevicePluginStateManager::device(std::string serialNumber)
{
    if (_deviceList.count(serialNumber)) {
        return _deviceList.find(serialNumber)->second;
    }
    else {
        return NULL;
    }
}

bool PokeyDevicePluginStateManager::validateConfig(libconfig::SettingIterator iter)
{
    bool retValue = true;
    try {
        iter->lookup("pins");
    }
    catch (const libconfig::SettingNotFoundException &nfex) {
        _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
        retValue = false;
    }
    return retValue;
}

int PokeyDevicePluginStateManager::preflightComplete(void)
{
    int retVal = PREFLIGHT_OK;

    enumerateDevices();

    libconfig::Setting *devicesSetting;

    try {
        devicesSetting = &_config->lookup("configuration");
    }
    catch (const libconfig::SettingNotFoundException &nfex) {
        _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
    }

    for (libconfig::SettingIterator iter = devicesSetting->begin(); iter != devicesSetting->end(); iter++) {
        std::string serialNumber;
        std::string name;

        // check that the configuration has the required config sections
        if (!validateConfig(iter)) {
            continue;
        }

        try {
            iter->lookupValue("serialNumber", serialNumber);
            pokeyDeviceSharedPointer pokeyDevice = device(serialNumber);

            if (pokeyDevice == NULL) {
                _logger(LOG_ERROR, "    - #%s. No physical device. Skipping....", serialNumber.c_str());
                continue;
            }

            iter->lookupValue("name", name);

            if (name != pokeyDevice->name().c_str()) {
                _logger(LOG_INFO, "      - Name mismatch. %s <-> %s", name.c_str(), pokeyDevice->name().c_str());
            }
        }
        catch (const libconfig::SettingNotFoundException &nfex) {
            _logger(LOG_ERROR, "Config file parse error at %s. Skipping....", nfex.getPath());
            continue;
        }
    }

    if (_numberOfDevices > 0) {
        _logger(LOG_INFO, "  - Discovered %d pokey devices", _numberOfDevices);
        retVal = PREFLIGHT_OK;
    }
    else {
        _logger(LOG_INFO, "   - No Pokey devices discovered");
    }

    return retVal;
}
<|endoftext|>


<commit_before>//(c) 2016 by Authors
//This file is a part of ABruijn program.
//Released under the BSD license (see LICENSE file)

#include "read_aligner.h"
#include "../common/parallel.h"
#include <cmath>
#include <iomanip>

namespace
{
	struct Chain
	{
		Chain(): score(0) {}
		std::vector<const EdgeAlignment*> aln;
		int32_t score;
	};
}

//Give alignments to separate edges for a single read, merges them
//into non-overlapping chains (could be more than one chain per read
//in case of chimera) with maximum score
std::vector<GraphAlignment>
	ReadAligner::chainReadAlignments(const std::vector<EdgeAlignment>& ovlps) const
{
	static const int32_t MAX_JUMP = Config::get("maximum_jump");
	//static const int32_t MAX_SEP = Config::get("max_separation");
	static const int32_t MAX_READ_OVLP = 50;
	//static const int32_t KMER_SIZE = Parameters::get().kmerSize;

	std::list<Chain> activeChains;
	for (auto& edgeAlignment : ovlps)
	{
		std::list<Chain> newChains;
		int32_t maxScore = 0;
		Chain* maxChain = nullptr;
		for (auto& chain : activeChains)
		{
			const OverlapRange& nextOvlp = edgeAlignment.overlap;
			const OverlapRange& prevOvlp = chain.aln.back()->overlap;

			int32_t readDiff = nextOvlp.curBegin - prevOvlp.curEnd;
			int32_t graphLeftDiff = nextOvlp.extBegin;
			int32_t graphRightDiff = prevOvlp.extLen - prevOvlp.extEnd;

			if (chain.aln.back()->edge->nodeRight == edgeAlignment.edge->nodeLeft &&
				MAX_JUMP > readDiff && readDiff > -MAX_READ_OVLP &&
				graphLeftDiff + graphRightDiff < MAX_JUMP)
			{
				//int32_t jumpDiv = abs(readDiff -
				//					  (graphLeftDiff + graphRightDiff));
				//int32_t gapCost = (jumpDiv > 100) ? 2 * jumpDiv : 0;
				int32_t gapCost = std::max(-readDiff, 0);
				int32_t score = chain.score + nextOvlp.score - gapCost;
				if (score > maxScore)
				{
					maxScore = score;
					maxChain = &chain;
				}
			}
		}

		if (maxChain)
		{
			newChains.push_back(*maxChain);
			maxChain->aln.push_back(&edgeAlignment);
			maxChain->score = maxScore;
		}

		activeChains.splice(activeChains.end(), newChains);
		activeChains.push_back(Chain());
		activeChains.back().aln.push_back(&edgeAlignment);
		activeChains.back().score = edgeAlignment.overlap.score;
	}

	//greedily choose non-intersecting set of alignments
	std::vector<GraphAlignment> acceptedAlignments;
	std::vector<Chain> sortedChains(activeChains.begin(), activeChains.end());
	std::sort(sortedChains.begin(), sortedChains.end(),
			  [](const Chain& c1, const Chain& c2)
			  {return c1.score > c2.score;});
	for (auto& chain : sortedChains)
	{
		int32_t alnLen = chain.aln.back()->overlap.curEnd -
					 	 chain.aln.front()->overlap.curBegin;
		if (alnLen < Parameters::get().minimumOverlap) continue;

		//check if it overlaps with other accepted chains
		bool overlaps = false;
		for (auto& existAln : acceptedAlignments)
		{
			int32_t existStart = existAln.front().overlap.curBegin;
			int32_t existEnd = existAln.back().overlap.curEnd;
			int32_t curStart = chain.aln.front()->overlap.curBegin;
			int32_t curEnd = chain.aln.back()->overlap.curEnd;

			int32_t overlapRate = std::min(curEnd, existEnd) -
									std::max(curStart, existStart);
			if (overlapRate > (int)Config::get("max_separation")) overlaps = true;
		}
		if (!overlaps)
		{
			acceptedAlignments.emplace_back();
			for (auto& aln : chain.aln) acceptedAlignments.back().push_back(*aln);
		}
	}

	return acceptedAlignments;
}

void ReadAligner::alignReads()
{
	static const int MIN_EDGE_OVLP = (int)Config::get("max_separation");
	static const int EDGE_FLANK = 100;

	//create database
	std::unordered_map<FastaRecord::Id,
					   std::pair<GraphEdge*, EdgeSequence>> idToSegment;
	for (auto& edge : _graph.iterEdges())
	{
		for (auto& segment : edge->seqSegments)
		{
			idToSegment[segment.edgeSeqId] = {edge, segment};
			idToSegment[segment.edgeSeqId.rc()] = {_graph.complementEdge(edge),
										   		   segment.complement()};
		}
	}

	//index it and align reads
	VertexIndex pathsIndex(_graph.edgeSequences(),
						   (int)Config::get("read_align_kmer_sample"));
	pathsIndex.countKmers(/*min freq*/ 1, /* genome size*/ 0);
	pathsIndex.setRepeatCutoff(/*min freq*/ 1);
	pathsIndex.buildIndex(/*min freq*/ 1);
	OverlapDetector readsOverlapper(_graph.edgeSequences(), pathsIndex,
									(int)Config::get("maximum_jump"),
									MIN_EDGE_OVLP - EDGE_FLANK,
									/*no overhang*/ 0, /*no max ovlp count*/ 0,
									/*keep alignment*/ false, /*only max*/ false,
									(float)Config::get("read_align_ovlp_divergence"),
									/*bad end adjust*/ 0.0f,
									/*nucl alignment*/ false);
	OverlapContainer readsOverlaps(readsOverlapper, _readSeqs);

	std::vector<FastaRecord::Id> allQueries;
	int64_t totalLength = 0;
	for (auto& read : _readSeqs.iterSeqs())
	{
		if (!read.id.strand()) continue;
		if (read.sequence.length() > (size_t)Parameters::get().minimumOverlap)
		{
			totalLength += read.sequence.length();
			allQueries.push_back(read.id);
		}
	}
	std::mutex indexMutex;
	int numAligned = 0;
	int alignedInFull = 0;
	int64_t alignedLength = 0;

	std::function<void(const FastaRecord::Id&)> alignRead =
	[this, &indexMutex, &numAligned, &readsOverlaps,
		&idToSegment, &alignedLength, &alignedInFull]
	(const FastaRecord::Id& seqId)
	{
		auto overlaps = readsOverlaps.quickSeqOverlaps(seqId);
		std::vector<EdgeAlignment> alignments;
		for (auto& ovlp : overlaps)
		{
			//because edges might be as short as max_separation,
			//we set minimum alignment threshold to a bit shorter value.
			//However, apply the actual threshold for longer edges now.
			if (ovlp.extLen < MIN_EDGE_OVLP + EDGE_FLANK ||
				std::min(ovlp.curRange(), ovlp.extRange()) > MIN_EDGE_OVLP)
			{
				//alignments.push_back({ovlp, idToSegment[ovlp.extId].first,
				//					  idToSegment[ovlp.extId].second});
				alignments.push_back({ovlp, idToSegment[ovlp.extId].first});
			}

		}
		std::sort(alignments.begin(), alignments.end(),
		  [](const EdgeAlignment& e1, const EdgeAlignment& e2)
			{return e1.overlap.curBegin < e2.overlap.curBegin;});
		auto readChains = this->chainReadAlignments(alignments);

		std::vector<GraphAlignment> complChains(readChains);
		for (auto& chain : complChains)
		{
			for (auto& aln : chain)
			{
				aln.edge = _graph.complementEdge(aln.edge);
				//aln.segment = aln.segment.complement();
				aln.overlap = aln.overlap.complement();
			}
			std::reverse(chain.begin(), chain.end());
		}

		if (readChains.empty()) return;

		/////synchronized part
		indexMutex.lock();
		++numAligned;
		if (readChains.size() == 1) ++alignedInFull;
		for (auto& chain : readChains)
		{
			_readAlignments.push_back(chain);
			alignedLength += chain.back().overlap.curEnd -
							 chain.front().overlap.curBegin;
		}
		for (auto& chain : complChains)
		{
			_readAlignments.push_back(chain);
		}
		indexMutex.unlock();
		/////
	};

	processInParallel(allQueries, alignRead,
					  Parameters::get().numThreads, true);

	/*for (auto& aln : _readAlignments)
	{
		if (aln.size() > 1)
		{
			std::string alnStr;
			int switches = 0;
			for (size_t i = 0; i < aln.size() - 1; ++i)
			{
				if (aln[i].segment.end != aln[i + 1].segment.start) ++switches;
			}

			int totalScore = 0;
			int32_t prevGap = 0;
			int32_t prevReadPos = 0;
			for (auto& edge : aln)
			{
				totalScore += edge.overlap.score;
				int32_t nextGap = edge.overlap.extBegin;
				int32_t readGap = edge.overlap.curBegin - prevReadPos;
				if (prevGap > 0)
				{
					int32_t gapCost = (nextGap + prevGap) / 10;
					totalScore -= gapCost;
				}

				alnStr += std::to_string(edge.edge->edgeId.signedId()) + " ("
					+ std::to_string(edge.overlap.curRange()) + ", "
					+ std::to_string(edge.overlap.seqDivergence) + ", "
					+ std::to_string(nextGap + prevGap) + ", "
					+ std::to_string(readGap) + ") -> ";

				prevGap = edge.overlap.extLen - edge.overlap.extEnd;
				prevReadPos = edge.overlap.curEnd;
			}
			alnStr.erase(alnStr.size() - 4);
			alnStr += " readLen:" + std::to_string(aln.front().overlap.curLen);
			alnStr += " alnLen:" + std::to_string(aln.back().overlap.curEnd -
												   aln.front().overlap.curBegin);
			alnStr += " score:" + std::to_string(totalScore);
			FastaRecord::Id readId = aln.front().overlap.curId;
			Logger::get().debug() << "Aln " << _readSeqs.seqName(readId);
			Logger::get().debug() << "\t" << alnStr;
		}
	}*/

	Logger::get().debug() << "Total reads : " << allQueries.size();
	Logger::get().debug() << "Read with aligned parts : " << numAligned;
	Logger::get().debug() << "Aligned in one piece : " << alignedInFull;
	Logger::get().info() << "Aligned read sequence: " << alignedLength << " / "
		<< totalLength << " (" << (float)alignedLength / totalLength << ")";
	readsOverlaps.overlapDivergenceStats();
}

//updates alignments with respect to the new graph
void ReadAligner::updateAlignments()
{
	std::vector<GraphAlignment> newAlignments;
	for (auto& aln : _readAlignments)
	{
		GraphAlignment curAlignment;
		for (size_t i = 0; i < aln.size() - 1; ++i)
		{
			if (!_graph.hasEdge(aln[i].edge)) continue;

			curAlignment.push_back(aln[i]);
			if (!_graph.hasEdge(aln[i + 1].edge) ||
				aln[i].edge->nodeRight != aln[i + 1].edge->nodeLeft)
			{
				newAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}

		if (_graph.hasEdge(aln.back().edge)) curAlignment.push_back(aln.back());
		if (!curAlignment.empty()) newAlignments.push_back(curAlignment);
	}

	_readAlignments = newAlignments;
}

void ReadAligner::storeAlignments(const std::string& filename)
{
	std::ofstream fout(filename);
	if (!fout)
	{
		throw std::runtime_error("Can't open "  + filename);
	}

	for (auto& chain : _readAlignments)
	{
		fout << "Chain\n";
		for (auto& aln : chain)
		{
			fout << "\tAln\t" << aln.edge->edgeId << "\t";
			aln.overlap.dump(fout, _readSeqs, _graph.edgeSequences());
			fout << "\n";
		}
	}
}

void ReadAligner::loadAlignments(const std::string& filename)
{
	std::ifstream fin(filename);
	if (!fin)
	{
		throw std::runtime_error("Can't open "  + filename);
	}

	GraphAlignment curAlignment;
	while(!fin.eof())
	{
		std::string buffer;
		fin >> buffer;
		if (buffer.empty()) continue;

		if (buffer == "Chain")
		{
			if (!curAlignment.empty())
			{
				_readAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}
		else if (buffer == "Aln")
		{
			OverlapRange ovlp;
			size_t edgeId = 0;
			fin >> edgeId;
			ovlp.load(fin, _readSeqs, _graph.edgeSequences());
			GraphEdge* edge = _graph.getEdge(FastaRecord::Id(edgeId));
			curAlignment.push_back({ovlp, edge});
		}
		else throw std::runtime_error("Error parsing: " + filename);
	}
	if (!curAlignment.empty())
	{
		_readAlignments.push_back(curAlignment);
		curAlignment.clear();
	}

	this->updateAlignments();
}
<commit_msg>some revisions in read alignment<commit_after>//(c) 2016 by Authors
//This file is a part of ABruijn program.
//Released under the BSD license (see LICENSE file)

#include "read_aligner.h"
#include "../common/parallel.h"
#include <cmath>
#include <iomanip>

namespace
{
	struct Chain
	{
		Chain(): score(0) {}
		std::vector<const EdgeAlignment*> aln;
		int32_t score;
	};
}

//Give alignments to separate edges for a single read, merges them
//into non-overlapping chains (could be more than one chain per read
//in case of chimera) with maximum score
std::vector<GraphAlignment>
	ReadAligner::chainReadAlignments(const std::vector<EdgeAlignment>& ovlps) const
{
	static const int32_t MAX_JUMP = Config::get("maximum_jump");
	//static const int32_t MAX_SEP = Config::get("max_separation");
	static const int32_t MAX_READ_OVLP = 50;
	//static const int32_t KMER_SIZE = Parameters::get().kmerSize;

	std::list<Chain> activeChains;
	for (auto& edgeAlignment : ovlps)
	{
		std::list<Chain> newChains;
		int32_t maxScore = 0;
		Chain* maxChain = nullptr;
		for (auto& chain : activeChains)
		{
			const OverlapRange& nextOvlp = edgeAlignment.overlap;
			const OverlapRange& prevOvlp = chain.aln.back()->overlap;

			int32_t readDiff = nextOvlp.curBegin - prevOvlp.curEnd;
			int32_t graphLeftDiff = nextOvlp.extBegin;
			int32_t graphRightDiff = prevOvlp.extLen - prevOvlp.extEnd;

			if (chain.aln.back()->edge->nodeRight == edgeAlignment.edge->nodeLeft &&
				MAX_JUMP > readDiff && readDiff > -MAX_READ_OVLP &&
				graphLeftDiff + graphRightDiff < MAX_JUMP)
			{
				//int32_t gapCost = std::max(-readDiff, 0);
				int32_t jumpDiv = abs(readDiff - (graphLeftDiff + graphRightDiff));
				int32_t gapCost = (jumpDiv > 100) ? jumpDiv / 50 : 0;
				int32_t score = chain.score + nextOvlp.score - gapCost;
				if (score > maxScore)
				{
					maxScore = score;
					maxChain = &chain;
				}
			}
		}

		if (maxChain)
		{
			newChains.push_back(*maxChain);
			maxChain->aln.push_back(&edgeAlignment);
			maxChain->score = maxScore;
		}

		activeChains.splice(activeChains.end(), newChains);
		activeChains.push_back(Chain());
		activeChains.back().aln.push_back(&edgeAlignment);
		activeChains.back().score = edgeAlignment.overlap.score;
	}

	//greedily choose non-intersecting set of alignments
	std::vector<GraphAlignment> acceptedAlignments;
	std::vector<Chain> sortedChains(activeChains.begin(), activeChains.end());
	std::sort(sortedChains.begin(), sortedChains.end(),
			  [](const Chain& c1, const Chain& c2)
			  {return c1.score > c2.score;});
	for (auto& chain : sortedChains)
	{
		int32_t alnLen = chain.aln.back()->overlap.curEnd -
					 	 chain.aln.front()->overlap.curBegin;
		if (alnLen < Parameters::get().minimumOverlap) continue;

		//check if it overlaps with other accepted chains
		bool overlaps = false;
		for (auto& existAln : acceptedAlignments)
		{
			int32_t existStart = existAln.front().overlap.curBegin;
			int32_t existEnd = existAln.back().overlap.curEnd;
			int32_t curStart = chain.aln.front()->overlap.curBegin;
			int32_t curEnd = chain.aln.back()->overlap.curEnd;

			int32_t overlapRate = std::min(curEnd, existEnd) -
									std::max(curStart, existStart);
			if (overlapRate > (int)Config::get("max_separation")) overlaps = true;
		}
		if (!overlaps)
		{
			acceptedAlignments.emplace_back();
			for (auto& aln : chain.aln) acceptedAlignments.back().push_back(*aln);
		}
	}

	return acceptedAlignments;
}

void ReadAligner::alignReads()
{
	static const int MIN_EDGE_OVLP = (int)Config::get("max_separation");
	static const int EDGE_FLANK = 100;

	//create database
	std::unordered_map<FastaRecord::Id,
					   std::pair<GraphEdge*, EdgeSequence>> idToSegment;
	for (auto& edge : _graph.iterEdges())
	{
		for (auto& segment : edge->seqSegments)
		{
			idToSegment[segment.edgeSeqId] = {edge, segment};
			idToSegment[segment.edgeSeqId.rc()] = {_graph.complementEdge(edge),
										   		   segment.complement()};
		}
	}

	//index it and align reads
	VertexIndex pathsIndex(_graph.edgeSequences(),
						   (int)Config::get("read_align_kmer_sample"));
	pathsIndex.countKmers(/*min freq*/ 1, /* genome size*/ 0);
	pathsIndex.setRepeatCutoff(/*min freq*/ 1);
	pathsIndex.buildIndex(/*min freq*/ 1);
	OverlapDetector readsOverlapper(_graph.edgeSequences(), pathsIndex,
									(int)Config::get("maximum_jump"),
									MIN_EDGE_OVLP - EDGE_FLANK,
									/*no overhang*/ 0, /*no max ovlp count*/ 0,
									/*keep alignment*/ false, /*only max*/ false,
									/*no max divergence*/ 1.0f,
									/*bad end adjust*/ 0.0f,
									/*nucl alignment*/ false);
	OverlapContainer readsOverlaps(readsOverlapper, _readSeqs);

	std::vector<FastaRecord::Id> allQueries;
	int64_t totalLength = 0;
	for (auto& read : _readSeqs.iterSeqs())
	{
		if (!read.id.strand()) continue;
		if (read.sequence.length() > (size_t)Parameters::get().minimumOverlap)
		{
			totalLength += read.sequence.length();
			allQueries.push_back(read.id);
		}
	}
	std::mutex indexMutex;
	int numAligned = 0;
	int alignedInFull = 0;
	int64_t alignedLength = 0;

	std::function<void(const FastaRecord::Id&)> alignRead =
	[this, &indexMutex, &numAligned, &readsOverlaps,
		&idToSegment, &alignedLength, &alignedInFull]
	(const FastaRecord::Id& seqId)
	{
		auto overlaps = readsOverlaps.quickSeqOverlaps(seqId);
		std::vector<EdgeAlignment> alignments;
		for (auto& ovlp : overlaps)
		{
			//because edges might be as short as max_separation,
			//we set minimum alignment threshold to a bit shorter value.
			//However, apply the actual threshold for longer edges now.
			if (ovlp.extLen < MIN_EDGE_OVLP + EDGE_FLANK ||
				std::min(ovlp.curRange(), ovlp.extRange()) > MIN_EDGE_OVLP)
			{
				//alignments.push_back({ovlp, idToSegment[ovlp.extId].first,
				//					  idToSegment[ovlp.extId].second});
				alignments.push_back({ovlp, idToSegment[ovlp.extId].first});
			}

		}
		std::sort(alignments.begin(), alignments.end(),
		  [](const EdgeAlignment& e1, const EdgeAlignment& e2)
			{return e1.overlap.curBegin < e2.overlap.curBegin;});
		auto readChains = this->chainReadAlignments(alignments);

		std::vector<GraphAlignment> complChains(readChains);
		for (auto& chain : complChains)
		{
			for (auto& aln : chain)
			{
				aln.edge = _graph.complementEdge(aln.edge);
				//aln.segment = aln.segment.complement();
				aln.overlap = aln.overlap.complement();
			}
			std::reverse(chain.begin(), chain.end());
		}

		if (readChains.empty()) return;

		/////synchronized part
		indexMutex.lock();
		++numAligned;
		if (readChains.size() == 1) ++alignedInFull;
		for (auto& chain : readChains)
		{
			_readAlignments.push_back(chain);
			alignedLength += chain.back().overlap.curEnd -
							 chain.front().overlap.curBegin;
		}
		for (auto& chain : complChains)
		{
			_readAlignments.push_back(chain);
		}
		indexMutex.unlock();
		/////
	};

	processInParallel(allQueries, alignRead,
					  Parameters::get().numThreads, true);

	/*for (auto& aln : _readAlignments)
	{
		if (aln.size() > 1)
		{
			std::string alnStr;
			int switches = 0;
			for (size_t i = 0; i < aln.size() - 1; ++i)
			{
				if (aln[i].segment.end != aln[i + 1].segment.start) ++switches;
			}

			int totalScore = 0;
			int32_t prevGap = 0;
			int32_t prevReadPos = 0;
			for (auto& edge : aln)
			{
				totalScore += edge.overlap.score;
				int32_t nextGap = edge.overlap.extBegin;
				int32_t readGap = edge.overlap.curBegin - prevReadPos;
				if (prevGap > 0)
				{
					int32_t gapCost = (nextGap + prevGap) / 10;
					totalScore -= gapCost;
				}

				alnStr += std::to_string(edge.edge->edgeId.signedId()) + " ("
					+ std::to_string(edge.overlap.curRange()) + ", "
					+ std::to_string(edge.overlap.seqDivergence) + ", "
					+ std::to_string(nextGap + prevGap) + ", "
					+ std::to_string(readGap) + ") -> ";

				prevGap = edge.overlap.extLen - edge.overlap.extEnd;
				prevReadPos = edge.overlap.curEnd;
			}
			alnStr.erase(alnStr.size() - 4);
			alnStr += " readLen:" + std::to_string(aln.front().overlap.curLen);
			alnStr += " alnLen:" + std::to_string(aln.back().overlap.curEnd -
												   aln.front().overlap.curBegin);
			alnStr += " score:" + std::to_string(totalScore);
			FastaRecord::Id readId = aln.front().overlap.curId;
			Logger::get().debug() << "Aln " << _readSeqs.seqName(readId);
			Logger::get().debug() << "\t" << alnStr;
		}
	}*/

	Logger::get().debug() << "Total reads : " << allQueries.size();
	Logger::get().debug() << "Read with aligned parts : " << numAligned;
	Logger::get().debug() << "Aligned in one piece : " << alignedInFull;
	Logger::get().info() << "Aligned read sequence: " << alignedLength << " / "
		<< totalLength << " (" << (float)alignedLength / totalLength << ")";
	readsOverlaps.overlapDivergenceStats();
}

//updates alignments with respect to the new graph
void ReadAligner::updateAlignments()
{
	std::vector<GraphAlignment> newAlignments;
	for (auto& aln : _readAlignments)
	{
		GraphAlignment curAlignment;
		for (size_t i = 0; i < aln.size() - 1; ++i)
		{
			if (!_graph.hasEdge(aln[i].edge)) continue;

			curAlignment.push_back(aln[i]);
			if (!_graph.hasEdge(aln[i + 1].edge) ||
				aln[i].edge->nodeRight != aln[i + 1].edge->nodeLeft)
			{
				newAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}

		if (_graph.hasEdge(aln.back().edge)) curAlignment.push_back(aln.back());
		if (!curAlignment.empty()) newAlignments.push_back(curAlignment);
	}

	_readAlignments = newAlignments;
}

void ReadAligner::storeAlignments(const std::string& filename)
{
	std::ofstream fout(filename);
	if (!fout)
	{
		throw std::runtime_error("Can't open "  + filename);
	}

	for (auto& chain : _readAlignments)
	{
		fout << "Chain\n";
		for (auto& aln : chain)
		{
			fout << "\tAln\t" << aln.edge->edgeId << "\t";
			aln.overlap.dump(fout, _readSeqs, _graph.edgeSequences());
			fout << "\n";
		}
	}
}

void ReadAligner::loadAlignments(const std::string& filename)
{
	std::ifstream fin(filename);
	if (!fin)
	{
		throw std::runtime_error("Can't open "  + filename);
	}

	GraphAlignment curAlignment;
	while(!fin.eof())
	{
		std::string buffer;
		fin >> buffer;
		if (buffer.empty()) continue;

		if (buffer == "Chain")
		{
			if (!curAlignment.empty())
			{
				_readAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}
		else if (buffer == "Aln")
		{
			OverlapRange ovlp;
			size_t edgeId = 0;
			fin >> edgeId;
			ovlp.load(fin, _readSeqs, _graph.edgeSequences());
			GraphEdge* edge = _graph.getEdge(FastaRecord::Id(edgeId));
			curAlignment.push_back({ovlp, edge});
		}
		else throw std::runtime_error("Error parsing: " + filename);
	}
	if (!curAlignment.empty())
	{
		_readAlignments.push_back(curAlignment);
		curAlignment.clear();
	}

	this->updateAlignments();
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <sys/time.h>

#include <iostream>

#include <xen/io/pciif.h>
#include <xen/io/xenbus.h>

#include <llamaos/memory/memory.h>
#include <llamaos/xen/Hypercall.h>
#include <llamaos/xen/Hypervisor.h>
#include <llamaos/config.h>
#include <llamaos/trace.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::memory;
using namespace llamaos::xen;

int main (int /* argc */, char ** /* argv [] */)
{
   cout << "running e1000e llamaNET domain...\n" << endl;

   cout << "waiting for 60 secs..." << endl;
   timeval tv, tv1, tv2;
   gettimeofday (&tv1, nullptr);
   tv = tv1;

   for (;;)
   {
      gettimeofday (&tv2, nullptr);

      if ((tv2.tv_sec - tv1.tv_sec) > 60)
      {
         break;
      }
   }

   cout << "setup pci device xenbus..." << endl;

   domid_t backend_id = Hypervisor::get_instance ()->xenstore.read<domid_t>("device/pci/0/backend-id");
   cout << "backend-id: " << backend_id << endl;

   char *buffer = new char [sizeof(struct xen_pci_sharedinfo) + PAGE_SIZE];

   struct xen_pci_sharedinfo *pci_sharedinfo = address_to_pointer<struct xen_pci_sharedinfo> (pointer_to_address (buffer + PAGE_SIZE) & ~(PAGE_SIZE-1));
   grant_ref_t ref = Hypervisor::get_instance ()->grant_table.grant_access (backend_id, pci_sharedinfo);

   evtchn_port_t port = 0;
   Hypercall::event_channel_alloc_unbound (0, port);

   Hypervisor::get_instance ()->xenstore.start_transaction (1);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/pci-op-ref", ref);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/event-channel", port);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/magic", XEN_PCI_MAGIC);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/state", XenbusStateInitialised);
   Hypervisor::get_instance ()->xenstore.end_transaction (1);

   return 0;
}
<commit_msg>changing e1000e status to Connected and looking for backend<commit_after>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ''AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <sys/time.h>

#include <iostream>

#include <xen/io/pciif.h>
#include <xen/io/xenbus.h>

#include <llamaos/memory/memory.h>
#include <llamaos/xen/Hypercall.h>
#include <llamaos/xen/Hypervisor.h>
#include <llamaos/config.h>
#include <llamaos/trace.h>

using namespace std;
using namespace llamaos;
using namespace llamaos::memory;
using namespace llamaos::xen;

int main (int /* argc */, char ** /* argv [] */)
{
   cout << "running e1000e llamaNET domain...\n" << endl;

   cout << "waiting for 60 secs..." << endl;
   timeval tv, tv1, tv2;
   gettimeofday (&tv1, nullptr);
   tv = tv1;

   for (;;)
   {
      gettimeofday (&tv2, nullptr);

      if ((tv2.tv_sec - tv1.tv_sec) > 10)
      {
         break;
      }
   }

   cout << "setup pci device xenbus..." << endl;

   domid_t backend_id = Hypervisor::get_instance ()->xenstore.read<domid_t>("device/pci/0/backend-id");
   cout << "backend-id: " << backend_id << endl;

   char *buffer = new char [sizeof(struct xen_pci_sharedinfo) + PAGE_SIZE];

   struct xen_pci_sharedinfo *pci_sharedinfo = address_to_pointer<struct xen_pci_sharedinfo> (pointer_to_address (buffer + PAGE_SIZE) & ~(PAGE_SIZE-1));
   grant_ref_t ref = Hypervisor::get_instance ()->grant_table.grant_access (backend_id, pci_sharedinfo);

   evtchn_port_t port = 0;
   Hypercall::event_channel_alloc_unbound (0, port);

   Hypervisor::get_instance ()->xenstore.start_transaction (1);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/pci-op-ref", ref);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/event-channel", port);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/magic", XEN_PCI_MAGIC);
   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/state", XenbusStateInitialised);
   Hypervisor::get_instance ()->xenstore.end_transaction (1);

   gettimeofday (&tv1, nullptr);

   for (;;)
   {
      gettimeofday (&tv2, nullptr);

      if ((tv2.tv_sec - tv1.tv_sec) > 10)
      {
         break;
      }
   }

   Hypervisor::get_instance ()->xenstore.write ("device/pci/0/state", XenbusStateConnected);

   string backend = Hypervisor::get_instance ()->xenstore.read("device/pci/0/backend");

   cout << "backend: " << backend << endl;

   cout << "num-devs: " << Hypervisor::get_instance ()->xenstore.read(backend+"/num-devs");

   return 0;
}
<|endoftext|>


<commit_before><commit_msg>Minor corrections<commit_after><|endoftext|>


<commit_before><commit_msg>Modified tempNuptake to be consistent with tem-dvm<commit_after><|endoftext|>


<commit_before>#ifdef _WIN32

#include "net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions.h"
#include "generic.h"
#include "win.h"
#include <process.h>
#include <list>
#include <vector>
#include <string>

using namespace std;

// TODO Find the right size for this
#define EVENT_BUFFER_SIZE (16*1024)

#define CREATE_SHARE (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
#define CREATE_FLAGS (FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED)
#define EVENT_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | \
                    FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE)

class Server;
class WatchPoint;

class WatchPoint {
public:
    WatchPoint(Server *server, wstring path) {
        this->server = server;
        this->path = path;
        this->buffer.resize(EVENT_BUFFER_SIZE);
        ZeroMemory(&this->overlapped, sizeof(OVERLAPPED));
        this->overlapped.hEvent = this;
        this->directoryHandle = CreateFileW(
            path.c_str(),                       // pointer to the file name
            FILE_LIST_DIRECTORY,                // access (read/write) mode
            CREATE_SHARE,                       // share mode
            NULL,                               // security descriptor
            OPEN_EXISTING,                      // how to create
            CREATE_FLAGS,                       // file attributes
            NULL                                // file with attributes to copy
        );

        // TODO Error handling
    }

    void close();
    void listen();

private:
    Server *server;
    friend static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg);
    wstring path;
    HANDLE directoryHandle;
    OVERLAPPED overlapped;
    vector<BYTE> buffer;

    void handleEvent(DWORD errorCode, DWORD bytesTransfered);
    void handlePathChanged(FILE_NOTIFY_INFORMATION *info);
    friend static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransfered, LPOVERLAPPED overlapped);
};

class Server {
public:
    Server(
        JavaVM *jvm,
        JNIEnv *env,
        jobject watcherCallback
    ) {
        this->jvm = jvm;
        this->watcherCallback = env->NewGlobalRef(watcherCallback);
        this->threadHandle = (HANDLE)_beginthreadex(
            NULL,                   // default security attributes
            0,                      // use default stack size
            EventProcessingThread,  // thread function name
            this,                   // argument to thread function
            0,                      // use default creation flags
            NULL                    // the thread identifier
        );
        // TODO Error handling
        SetThreadPriority(this->threadHandle, THREAD_PRIORITY_ABOVE_NORMAL);
    }

    void startWatching(wchar_t *path);
    void reportEvent(jint type, const wstring changedPath);
    void reportFinished(WatchPoint* watchPoint);

    void close(JNIEnv *env);

private:
    struct StartWatchRequest {
        Server *server;
        wstring path;
    };
    friend static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg);

    JavaVM *jvm;
    list<WatchPoint*> watchPoints;
    jobject watcherCallback;

    HANDLE threadHandle;
    bool terminate = false;

    friend static void CALLBACK requestTerminationCallback(_In_ ULONG_PTR arg);
    void requestTermination();

    friend static unsigned CALLBACK EventProcessingThread(void* data);
    void run();
};

void WatchPoint::close() {
    CancelIo(directoryHandle);
    CloseHandle(directoryHandle);
}

void WatchPoint::listen() {
    BOOL success = ReadDirectoryChangesW(
        directoryHandle,                    // handle to directory
        &buffer[0],                         // read results buffer
        buffer.size(),                      // length of buffer
        TRUE,                               // include children
        EVENT_MASK,                         // filter conditions
        NULL,                               // bytes returned
        &overlapped,                        // overlapped buffer
        &handleEventCallback                // completion routine
    );
    // TODO Error handling
}

static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransfered, LPOVERLAPPED overlapped) {
    WatchPoint* watchPoint = (WatchPoint*)overlapped->hEvent;
    watchPoint->handleEvent(errorCode, bytesTransfered);
}

void WatchPoint::handleEvent(DWORD errorCode, DWORD bytesTransfered) {
    if (errorCode == ERROR_OPERATION_ABORTED){
        server->reportFinished(this);
        delete this;
        return;
    }

    if (bytesTransfered == 0) {
        // don't send dirty too much, everything is changed anyway
        // TODO Understand what this does
        // if (WaitForSingleObject(stopEventHandle, 500) == WAIT_OBJECT_0)
        //    break;

        // Got a buffer overflow => current changes lost => send INVALIDATE on root
        server->reportEvent(FILE_EVENT_INVALIDATE, path);
    } else {
        FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)buffer.data();
        do {
            handlePathChanged(info);
            info = (FILE_NOTIFY_INFORMATION *)((char *)info + info->NextEntryOffset);
        } while (info->NextEntryOffset != 0);
    }

    // Get the new read issued as fast as possible. The documentation
    // says that the original OVERLAPPED structure will not be used
    // again once the completion routine is called.
    listen();
}

void WatchPoint::handlePathChanged(FILE_NOTIFY_INFORMATION *info) {
    wstring changedPath = wstring(info->FileName, 0, info->FileNameLength / sizeof(wchar_t));
    if (!changedPath.empty()) {
        changedPath.insert(0, 1, L'\\');
        changedPath.insert(0, path);
    }

    // log_info(details->env, L"~~~~ Changed: 0x%x %ls\n", info->Action, changedPath);

    jint type;
    if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_NEW_NAME) {
        type = FILE_EVENT_CREATED;
    } else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
        type = FILE_EVENT_REMOVED;
    } else if (info->Action == FILE_ACTION_MODIFIED) {
        type = FILE_EVENT_MODIFIED;
    } else {
        wprintf(L"~~~~ Unknown event 0x%x for %ls\n", info->Action, changedPath.c_str());
        type = FILE_EVENT_UNKNOWN;
    }

    server->reportEvent(type, changedPath);
}

void Server::startWatching(wchar_t *path) {
    WatchPoint* watchPoint = new WatchPoint(this, wstring(path));
    QueueUserAPC(&startWatchCallback, threadHandle, (ULONG_PTR) watchPoint);
}

// Called by QueueUserAPC to add another directory.
static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg) {
    WatchPoint* watchPoint = (WatchPoint*)arg;
    watchPoint->server->watchPoints.push_back(watchPoint);
    watchPoint->listen();
}

void Server::reportFinished(WatchPoint* watchPoint) {
    watchPoints.remove(watchPoint);
}

static JNIEnv* getThreadEnv(JavaVM *jvm) {
    JNIEnv* env;
    // TODO Verify that JNI 1.6 is the right version
    jint ret = jvm->GetEnv((void **) &(env), JNI_VERSION_1_6);
    if (ret != JNI_OK) {
        printf("Failed to attach JNI to current thread: %d\n", ret);
        return NULL;
    }
    return env;
}

void Server::reportEvent(jint type, const wstring changedPath) {
    JNIEnv* env = getThreadEnv(jvm);
    jstring changedPathJava = wchar_to_java_path(env, changedPath.c_str());
    jclass callback_class = env->GetObjectClass(watcherCallback);
    jmethodID methodCallback = env->GetMethodID(callback_class, "pathChanged", "(ILjava/lang/String;)V");
    env->CallVoidMethod(watcherCallback, methodCallback, type, changedPathJava);
}

static unsigned CALLBACK EventProcessingThread(void* data) {
    Server *server = (Server*) data;
    server->run();
    return 0;
}

void Server::run() {
    printf("~~~~ Thread %d running\n", GetCurrentThreadId());

    // TODO Extract this logic to some shared function
    JNIEnv* env;
    jint statAttach = jvm->AttachCurrentThreadAsDaemon((void **) &(env), NULL);
    if (statAttach != JNI_OK) {
        printf("Failed to attach JNI to current thread: %d\n", statAttach);
        return;
    }

    while (!terminate || watchPoints.size() > 0) {
        SleepEx(INFINITE, true);
    }

    printf("~~~~ Stopping thread\n");

    // TODO Extract this logic to some shared function
    jint statDetach = jvm->DetachCurrentThread();
    if (statDetach != JNI_OK) {
        printf("Failed to detach JNI from current thread: %d\n", statAttach);
        return;
    }
}

static void CALLBACK requestTerminationCallback(_In_ ULONG_PTR arg) {
    Server* server = (Server*)arg;
    server->requestTermination();
}

void Server::requestTermination() {
    terminate = true;
    // Make copy so terminated entries can be removed
    list<WatchPoint*> copyWatchPoints(watchPoints);
    for (auto &watchPoint : copyWatchPoints) {
        watchPoint->close();
    }
}

void Server::close(JNIEnv *env) {
    QueueUserAPC(requestTerminationCallback, this->threadHandle, (ULONG_PTR)this);
    WaitForSingleObject(this->threadHandle, INFINITE);
    CloseHandle(this->threadHandle);
    env->DeleteGlobalRef(this->watcherCallback);
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_startWatching(JNIEnv *env, jclass target, jobjectArray paths, jobject javaCallback, jobject result) {

    printf("\n~~~~ Configuring...\n");

    JavaVM* jvm;
    int jvmStatus = env->GetJavaVM(&jvm);
    if (jvmStatus != JNI_OK) {
        mark_failed_with_errno(env, "Could not store jvm instance.", result);
        return NULL;
    }

    int watchPointCount = env->GetArrayLength(paths);
    if (watchPointCount == 0) {
        mark_failed_with_errno(env, "No paths given to watch.", result);
        return NULL;
    }

    Server* server = new Server(jvm, env, javaCallback);

    for (int i = 0; i < watchPointCount; i++) {
        jstring path = (jstring) env->GetObjectArrayElement(paths, i);
        wchar_t* watchPoint = java_to_wchar_path(env, path);
        int watchPointLen = wcslen(watchPoint);
        wprintf(L"~~~~ Watching %ls\n", watchPoint);
        server->startWatching(watchPoint);
        free(watchPoint);
    }

    jclass clsWatch = env->FindClass("net/rubygrapefruit/platform/internal/jni/WindowsFileEventFunctions$WatcherImpl");
    jmethodID constructor = env->GetMethodID(clsWatch, "<init>", "(Ljava/lang/Object;)V");
    return env->NewObject(clsWatch, constructor, env->NewDirectByteBuffer(server, sizeof(server)));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_stopWatching(JNIEnv *env, jclass target, jobject detailsObj, jobject result) {
    Server* server = (Server*)env->GetDirectBufferAddress(detailsObj);
    server->close(env);
    delete server;
}

#endif
<commit_msg>Log problems better<commit_after>#ifdef _WIN32

#include "net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions.h"
#include "generic.h"
#include "win.h"
#include <process.h>
#include <list>
#include <vector>
#include <string>

using namespace std;

// TODO Find the right size for this
#define EVENT_BUFFER_SIZE (16*1024)

#define CREATE_SHARE (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
#define CREATE_FLAGS (FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED)
#define EVENT_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | \
                    FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE)

class Server;
class WatchPoint;

class WatchPoint {
public:
    WatchPoint(Server *server, wstring path);
    void close();
    void listen();

private:
    Server *server;
    friend static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg);
    wstring path;
    HANDLE directoryHandle;
    OVERLAPPED overlapped;
    vector<BYTE> buffer;

    void handleEvent(DWORD errorCode, DWORD bytesTransfered);
    void handlePathChanged(FILE_NOTIFY_INFORMATION *info);
    friend static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransfered, LPOVERLAPPED overlapped);
};

class Server {
public:
    Server(
        JavaVM *jvm,
        JNIEnv *env,
        jobject watcherCallback
    ) {
        this->jvm = jvm;
        this->watcherCallback = env->NewGlobalRef(watcherCallback);
        this->threadHandle = (HANDLE)_beginthreadex(
            NULL,                   // default security attributes
            0,                      // use default stack size
            EventProcessingThread,  // thread function name
            this,                   // argument to thread function
            0,                      // use default creation flags
            NULL                    // the thread identifier
        );
        // TODO Error handling
        SetThreadPriority(this->threadHandle, THREAD_PRIORITY_ABOVE_NORMAL);
    }

    void startWatching(wchar_t *path);
    void reportEvent(jint type, const wstring changedPath);
    void reportFinished(WatchPoint* watchPoint);

    void close(JNIEnv *env);

    // TOOD: Move this to somewhere else
    JNIEnv* getThreadEnv();

private:
    struct StartWatchRequest {
        Server *server;
        wstring path;
    };
    friend static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg);

    JavaVM *jvm;
    list<WatchPoint*> watchPoints;
    jobject watcherCallback;

    HANDLE threadHandle;
    bool terminate = false;

    friend static void CALLBACK requestTerminationCallback(_In_ ULONG_PTR arg);
    void requestTermination();

    friend static unsigned CALLBACK EventProcessingThread(void* data);
    void run();
};

void WatchPoint::close() {
    BOOL ret = CancelIo(directoryHandle);
    if (!ret) {
        log_severe(server->getThreadEnv(), L"Couldn't cancel I/O %p for '%ls': %d\n", directoryHandle, path.c_str(), GetLastError());
    }
    ret = CloseHandle(directoryHandle);
    if (!ret) {
        log_severe(server->getThreadEnv(), L"Couldn't close handle %p for '%ls': %d\n", directoryHandle, path.c_str(), GetLastError());
    }
}

WatchPoint::WatchPoint(Server *server, wstring path) {
    this->server = server;
    this->path = path;
    this->buffer.resize(EVENT_BUFFER_SIZE);
    ZeroMemory(&this->overlapped, sizeof(OVERLAPPED));
    this->overlapped.hEvent = this;
    HANDLE directoryHandle = CreateFileW(
        path.c_str(),                       // pointer to the file name
        FILE_LIST_DIRECTORY,                // access (read/write) mode
        CREATE_SHARE,                       // share mode
        NULL,                               // security descriptor
        OPEN_EXISTING,                      // how to create
        CREATE_FLAGS,                       // file attributes
        NULL                                // file with attributes to copy
    );

    if (directoryHandle == INVALID_HANDLE_VALUE) {
        log_severe(server->getThreadEnv(), L"Couldn't get handle for '%ls': %d\n", path.c_str(), GetLastError());
    }

    log_info(server->getThreadEnv(), L"Started watching %p for '%ls'\n", directoryHandle, path.c_str());
    this->directoryHandle = directoryHandle;
}

void WatchPoint::listen() {
    log_fine(server->getThreadEnv(), L"Listening to %p for '%ls'\n", directoryHandle, path.c_str());
    BOOL success = ReadDirectoryChangesW(
        directoryHandle,                    // handle to directory
        &buffer[0],                         // read results buffer
        buffer.size(),                      // length of buffer
        TRUE,                               // include children
        EVENT_MASK,                         // filter conditions
        NULL,                               // bytes returned
        &overlapped,                        // overlapped buffer
        &handleEventCallback                // completion routine
    );
    if (!success) {
        log_severe(server->getThreadEnv(), L"Couldn't start watching %p for '%ls': %d\n", directoryHandle, path.c_str(), GetLastError());
    }
    // TODO Error handling
}

static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransfered, LPOVERLAPPED overlapped) {
    WatchPoint* watchPoint = (WatchPoint*)overlapped->hEvent;
    watchPoint->handleEvent(errorCode, bytesTransfered);
}

void WatchPoint::handleEvent(DWORD errorCode, DWORD bytesTransfered) {
    if (errorCode == ERROR_OPERATION_ABORTED){
        log_fine(server->getThreadEnv(), L"Finished watching %p for '%ls'\n", directoryHandle, path.c_str());
        server->reportFinished(this);
        delete this;
        return;
    }

    if (bytesTransfered == 0) {
        // don't send dirty too much, everything is changed anyway
        // TODO Understand what this does
        // if (WaitForSingleObject(stopEventHandle, 500) == WAIT_OBJECT_0)
        //    break;

        // Got a buffer overflow => current changes lost => send INVALIDATE on root
        server->reportEvent(FILE_EVENT_INVALIDATE, path);
    } else {
        FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)buffer.data();
        do {
            handlePathChanged(info);
            info = (FILE_NOTIFY_INFORMATION *)((char *)info + info->NextEntryOffset);
        } while (info->NextEntryOffset != 0);
    }

    // Get the new read issued as fast as possible. The documentation
    // says that the original OVERLAPPED structure will not be used
    // again once the completion routine is called.
    listen();
}

void WatchPoint::handlePathChanged(FILE_NOTIFY_INFORMATION *info) {
    wstring changedPath = wstring(info->FileName, 0, info->FileNameLength / sizeof(wchar_t));
    if (!changedPath.empty()) {
        changedPath.insert(0, 1, L'\\');
        changedPath.insert(0, path);
    }

    log_info(server->getThreadEnv(), L"Changed: 0x%x %ls\n", info->Action, changedPath.c_str());

    jint type;
    if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_NEW_NAME) {
        type = FILE_EVENT_CREATED;
    } else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
        type = FILE_EVENT_REMOVED;
    } else if (info->Action == FILE_ACTION_MODIFIED) {
        type = FILE_EVENT_MODIFIED;
    } else {
        log_warning(server->getThreadEnv(), L"Unknown event 0x%x for %ls\n", info->Action, changedPath.c_str());
        type = FILE_EVENT_UNKNOWN;
    }

    server->reportEvent(type, changedPath);
}

void Server::startWatching(wchar_t *path) {
    WatchPoint* watchPoint = new WatchPoint(this, wstring(path));
    QueueUserAPC(&startWatchCallback, threadHandle, (ULONG_PTR) watchPoint);
}

// Called by QueueUserAPC to add another directory.
static void CALLBACK startWatchCallback(_In_ ULONG_PTR arg) {
    WatchPoint* watchPoint = (WatchPoint*)arg;
    watchPoint->server->watchPoints.push_back(watchPoint);
    watchPoint->listen();
}

void Server::reportFinished(WatchPoint* watchPoint) {
    watchPoints.remove(watchPoint);
}

static JNIEnv* lookupThreadEnv(JavaVM *jvm) {
    JNIEnv* env;
    // TODO Verify that JNI 1.6 is the right version
    jint ret = jvm->GetEnv((void **) &(env), JNI_VERSION_1_6);
    if (ret != JNI_OK) {
        fwprintf(stderr, L"Failed to get JNI env for current thread: %d\n", ret);
        return NULL;
    }
    return env;
}

JNIEnv* Server::getThreadEnv() {
    return lookupThreadEnv(jvm);
}

void Server::reportEvent(jint type, const wstring changedPath) {
    JNIEnv* env = getThreadEnv();
    jstring changedPathJava = wchar_to_java_path(env, changedPath.c_str());
    jclass callback_class = env->GetObjectClass(watcherCallback);
    jmethodID methodCallback = env->GetMethodID(callback_class, "pathChanged", "(ILjava/lang/String;)V");
    env->CallVoidMethod(watcherCallback, methodCallback, type, changedPathJava);
}

static unsigned CALLBACK EventProcessingThread(void* data) {
    Server *server = (Server*) data;
    server->run();
    return 0;
}

void Server::run() {
    // TODO Extract this logic to some shared function
    JNIEnv* env;
    jint statAttach = jvm->AttachCurrentThreadAsDaemon((void **) &(env), NULL);
    if (statAttach != JNI_OK) {
        fwprintf(stderr, L"Failed to attach JNI to current thread: %d\n", statAttach);
        return;
    }

    log_info(env, L"Thread %d running\n", GetCurrentThreadId());

    while (!terminate || watchPoints.size() > 0) {
        SleepEx(INFINITE, true);
    }

    log_info(env, L"Stopping thread %d\n", GetCurrentThreadId());

    // TODO Extract this logic to some shared function
    jint statDetach = jvm->DetachCurrentThread();
    if (statDetach != JNI_OK) {
        fwprintf(stderr, L"Failed to detach JNI from current thread: %d\n", statAttach);
        return;
    }
}

static void CALLBACK requestTerminationCallback(_In_ ULONG_PTR arg) {
    Server* server = (Server*)arg;
    server->requestTermination();
}

void Server::requestTermination() {
    terminate = true;
    // Make copy so terminated entries can be removed
    list<WatchPoint*> copyWatchPoints(watchPoints);
    for (auto &watchPoint : copyWatchPoints) {
        watchPoint->close();
    }
}

void Server::close(JNIEnv *env) {
    QueueUserAPC(requestTerminationCallback, this->threadHandle, (ULONG_PTR)this);
    WaitForSingleObject(this->threadHandle, INFINITE);
    CloseHandle(this->threadHandle);
    env->DeleteGlobalRef(this->watcherCallback);
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_startWatching(JNIEnv *env, jclass target, jobjectArray paths, jobject javaCallback, jobject result) {

    log_info(env, L"Configuring...\n", nullptr);

    JavaVM* jvm;
    int jvmStatus = env->GetJavaVM(&jvm);
    if (jvmStatus != JNI_OK) {
        mark_failed_with_errno(env, "Could not store jvm instance.", result);
        return NULL;
    }

    int watchPointCount = env->GetArrayLength(paths);
    if (watchPointCount == 0) {
        mark_failed_with_errno(env, "No paths given to watch.", result);
        return NULL;
    }

    Server* server = new Server(jvm, env, javaCallback);

    for (int i = 0; i < watchPointCount; i++) {
        jstring path = (jstring) env->GetObjectArrayElement(paths, i);
        wchar_t* watchPoint = java_to_wchar_path(env, path);
        int watchPointLen = wcslen(watchPoint);
        server->startWatching(watchPoint);
        free(watchPoint);
    }

    jclass clsWatch = env->FindClass("net/rubygrapefruit/platform/internal/jni/WindowsFileEventFunctions$WatcherImpl");
    jmethodID constructor = env->GetMethodID(clsWatch, "<init>", "(Ljava/lang/Object;)V");
    return env->NewObject(clsWatch, constructor, env->NewDirectByteBuffer(server, sizeof(server)));
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_stopWatching(JNIEnv *env, jclass target, jobject detailsObj, jobject result) {
    Server* server = (Server*)env->GetDirectBufferAddress(detailsObj);
    server->close(env);
    delete server;
}

#endif
<|endoftext|>


<commit_before>// -*- C++ -*-
/*
 * Copyright Procedural Insight 2006
 * Author Nicholas Yue
 */

#include <stdexcept>

template <typename T> TParameterList<T>::TParameterList(DeclarationManager& dm)
  :_dm(dm)
   // ,_tokens(0)
   // ,_parms(0)
  ,_size(0)
  , _paramIndex(0)
  , _numPointers(0) /// experimental
{
  _rawCharPtrArray = new char* [1024];
}

template <typename T> TParameterList<T>::~TParameterList()
{
  cleanUpRawPointerArray();
}

template <typename T> void TParameterList<T>::Init(size_t numTVPairs)
{
  // std::cout << "TParameterList::Init() size is " << numTVPairs << std::endl;
  if (numTVPairs == 0)
    throw std::runtime_error("Init with zero size");
  _tokenStorage.resize(numTVPairs);
  parms.resize(numTVPairs);
  parameterType.resize(numTVPairs);
  _tokens.resize(numTVPairs);
  _parms.resize(numTVPairs);
  _size = numTVPairs;
  _paramIndex = 0;
  _numPointers = 0;
}

template <typename T> void TParameterList<T>::cleanUpRawPointerArray()
{
  std::cout << "cleanUpRawPointerArray [START]" << std::endl;
  if ( _rawCharPtrArray != 0 )
  {
    for (size_t i = 0 ; i < _numPointers; i++)
    {
      if ( _rawCharPtrArray[i] != 0 )
        delete [] _rawCharPtrArray[i];
    }
    delete [] _rawCharPtrArray;
  }

  std::cout << "cleanUpRawPointerArray [END]" << std::endl;
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     RtFloatVector& floatParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     RtIntVector& intParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     StringVec& stringParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Reinitialize()
{
  _tokenStorage.clear();
  parms.clear();
  parameterType.clear();
  _tokens.clear();
  _parms.clear();
  _size = 0;
  _paramIndex = 0;
}

template <typename T> void TParameterList<T>::CleanUpArgStorage()
{
  __STLstringArrayStorage.clear();
  _RtIntArrayStorage.clear();
  _RtFloatArrayStorage.clear();
  _RtStringArrayStorage.clear();
};

template <typename T> RtInt*
TParameterList<T>::AddRtIntArrayArg(RtIntVector input)
{
  _RtIntArrayStorage.push_back(input);
  return &(_RtIntArrayStorage.back()[0]);
}

template <typename T> RtFloat*
TParameterList<T>::AddRtFloatArrayArg(RtFloatVector input)
{
  _RtFloatArrayStorage.push_back(input);
  return &(_RtFloatArrayStorage.back()[0]);
}

template <typename T> RtString*
TParameterList<T>::AddRtStringArrayArg(StringVec input)
{
  __STLstringArrayStorage.push_back(input);
  RtStringVector rtv;
  _RtStringArrayStorage.push_back(rtv);
  size_t numElements = input.size();
  _RtStringArrayStorage.back().resize(numElements);
  for (size_t i=0;i<numElements;i++)
  {
    _RtStringArrayStorage.back()[i] = &(__STLstringArrayStorage.back()[i][0]);
  }
  return &(_RtStringArrayStorage.back()[0]);
}

template <typename T> RtToken*
TParameterList<T>::AddRtTokenArrayArg(StringVec input)
{
  __STLstringArrayStorage.push_back(input);
  RtTokenVector rtv;
  _RtTokenArrayStorage.push_back(rtv);
  size_t numElements = input.size();
  _RtTokenArrayStorage.back().resize(numElements);
  for (size_t i=0;i<numElements;i++)
  {
    _RtTokenArrayStorage.back()[i] = &(__STLstringArrayStorage.back()[i][0]);
  }
  return &(_RtTokenArrayStorage.back()[0]);
}

// == Emacs ================
// -------------------------
// Local variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// end:
//
// == vi ===================
// -------------------------
// Format block
// ex:ts=2:sw=2:expandtab
// -------------------------
<commit_msg>Comment out debugging comments<commit_after>// -*- C++ -*-
/*
 * Copyright Procedural Insight 2006
 * Author Nicholas Yue
 */

#include <stdexcept>

template <typename T> TParameterList<T>::TParameterList(DeclarationManager& dm)
  :_dm(dm)
   // ,_tokens(0)
   // ,_parms(0)
  ,_size(0)
  , _paramIndex(0)
  , _numPointers(0) /// experimental
{
  _rawCharPtrArray = new char* [1024];
}

template <typename T> TParameterList<T>::~TParameterList()
{
  cleanUpRawPointerArray();
}

template <typename T> void TParameterList<T>::Init(size_t numTVPairs)
{
  // std::cout << "TParameterList::Init() size is " << numTVPairs << std::endl;
  if (numTVPairs == 0)
    throw std::runtime_error("Init with zero size");
  _tokenStorage.resize(numTVPairs);
  parms.resize(numTVPairs);
  parameterType.resize(numTVPairs);
  _tokens.resize(numTVPairs);
  _parms.resize(numTVPairs);
  _size = numTVPairs;
  _paramIndex = 0;
  _numPointers = 0;
}

template <typename T> void TParameterList<T>::cleanUpRawPointerArray()
{
  // std::cout << "cleanUpRawPointerArray [START]" << std::endl;
  if ( _rawCharPtrArray != 0 )
  {
    for (size_t i = 0 ; i < _numPointers; i++)
    {
      if ( _rawCharPtrArray[i] != 0 )
        delete [] _rawCharPtrArray[i];
    }
    delete [] _rawCharPtrArray;
  }

  // std::cout << "cleanUpRawPointerArray [END]" << std::endl;
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     RtFloatVector& floatParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     RtIntVector& intParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Update(size_t index,
                                                     std::string& tokenName,
                                                     StringVec& stringParam)
{
  // Is this depreacted?
}

template <typename T> void TParameterList<T>::Reinitialize()
{
  _tokenStorage.clear();
  parms.clear();
  parameterType.clear();
  _tokens.clear();
  _parms.clear();
  _size = 0;
  _paramIndex = 0;
}

template <typename T> void TParameterList<T>::CleanUpArgStorage()
{
  __STLstringArrayStorage.clear();
  _RtIntArrayStorage.clear();
  _RtFloatArrayStorage.clear();
  _RtStringArrayStorage.clear();
};

template <typename T> RtInt*
TParameterList<T>::AddRtIntArrayArg(RtIntVector input)
{
  _RtIntArrayStorage.push_back(input);
  return &(_RtIntArrayStorage.back()[0]);
}

template <typename T> RtFloat*
TParameterList<T>::AddRtFloatArrayArg(RtFloatVector input)
{
  _RtFloatArrayStorage.push_back(input);
  return &(_RtFloatArrayStorage.back()[0]);
}

template <typename T> RtString*
TParameterList<T>::AddRtStringArrayArg(StringVec input)
{
  __STLstringArrayStorage.push_back(input);
  RtStringVector rtv;
  _RtStringArrayStorage.push_back(rtv);
  size_t numElements = input.size();
  _RtStringArrayStorage.back().resize(numElements);
  for (size_t i=0;i<numElements;i++)
  {
    _RtStringArrayStorage.back()[i] = &(__STLstringArrayStorage.back()[i][0]);
  }
  return &(_RtStringArrayStorage.back()[0]);
}

template <typename T> RtToken*
TParameterList<T>::AddRtTokenArrayArg(StringVec input)
{
  __STLstringArrayStorage.push_back(input);
  RtTokenVector rtv;
  _RtTokenArrayStorage.push_back(rtv);
  size_t numElements = input.size();
  _RtTokenArrayStorage.back().resize(numElements);
  for (size_t i=0;i<numElements;i++)
  {
    _RtTokenArrayStorage.back()[i] = &(__STLstringArrayStorage.back()[i][0]);
  }
  return &(_RtTokenArrayStorage.back()[0]);
}

// == Emacs ================
// -------------------------
// Local variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// end:
//
// == vi ===================
// -------------------------
// Format block
// ex:ts=2:sw=2:expandtab
// -------------------------
<|endoftext|>


<commit_before>#ifndef EBITEN_GRAPHICS_DRAWING_REGION_HPP
#define EBITEN_GRAPHICS_DRAWING_REGION_HPP

#include "ebiten/util/noncopyable.hpp"
#include <algorithm>

namespace ebiten {
namespace graphics {

class drawing_region : private ebiten::util::noncopyable {

private:
  // TODO: implements by std::unique_ptr<std::array<double, 6> >?
  double src_x_, src_y_, dst_x_, dst_y_, width_, height_;
public:
  drawing_region()
    : src_x_(0), src_y_(0), dst_x_(0), dst_y_(0),
      width_(0), height_(0) {
  }
  drawing_region(double src_x,
                 double src_y,
                 double dst_x,
                 double dst_y,
                 double width,
                 double height)
    : src_x_(src_x), src_y_(src_y), dst_x_(dst_x), dst_y_(dst_y),
      width_(width), height_(height) {
  }
  double src_x() const {
    return this->src_x_;
  }
  double src_y() const {
    return this->src_y_;
  }
  double dst_x() const {
    return this->dst_x_;
  }
  double dst_y() const {
    return this->dst_y_;
  }
  double width() const {
    return this->width_;
  }
  double height() const {
    return this->height_;
  }
  void set_src_x(double value) {
    this->src_x_ = value;
  }
  void set_src_y(double value) {
    this->src_y_ = value;
  }
  void set_dst_x(double value) {
    this->dst_x_ = value;
  }
  void set_dst_y(double value) {
    this->dst_y_ = value;
  }
  void set_width(double value) {
    this->width_ = value;
  }
  void set_height(double value) {
    this->height_ = value;
  }
};

}
}

#endif
<commit_msg>Removed an extra macro<commit_after>#ifndef EBITEN_GRAPHICS_DRAWING_REGION_HPP
#define EBITEN_GRAPHICS_DRAWING_REGION_HPP

#include "ebiten/util/noncopyable.hpp"

namespace ebiten {
namespace graphics {

class drawing_region : private ebiten::util::noncopyable {

private:
  // TODO: implements by std::unique_ptr<std::array<double, 6> >?
  double src_x_, src_y_, dst_x_, dst_y_, width_, height_;
public:
  drawing_region()
    : src_x_(0), src_y_(0), dst_x_(0), dst_y_(0),
      width_(0), height_(0) {
  }
  drawing_region(double src_x,
                 double src_y,
                 double dst_x,
                 double dst_y,
                 double width,
                 double height)
    : src_x_(src_x), src_y_(src_y), dst_x_(dst_x), dst_y_(dst_y),
      width_(width), height_(height) {
  }
  double src_x() const {
    return this->src_x_;
  }
  double src_y() const {
    return this->src_y_;
  }
  double dst_x() const {
    return this->dst_x_;
  }
  double dst_y() const {
    return this->dst_y_;
  }
  double width() const {
    return this->width_;
  }
  double height() const {
    return this->height_;
  }
  void set_src_x(double value) {
    this->src_x_ = value;
  }
  void set_src_y(double value) {
    this->src_y_ = value;
  }
  void set_dst_x(double value) {
    this->dst_x_ = value;
  }
  void set_dst_y(double value) {
    this->dst_y_ = value;
  }
  void set_width(double value) {
    this->width_ = value;
  }
  void set_height(double value) {
    this->height_ = value;
  }
};

}
}

#endif
<|endoftext|>


<commit_before>// Copyright 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/wayland/inputs/cursor.h"
#include "ozone/wayland/surface.h"

namespace ozonewayland {

class WaylandCursorData {
public:
  static WaylandCursorData* Initialize(wl_shm* shm = 0)
  {
    static WaylandCursorData data(shm);
    return &data;
  }

  static WaylandCursorData* GetInstance()
  {
    return Initialize();
  }

  struct wl_cursor_image* GetCursorImage(int index);
  void Clear();
  virtual ~WaylandCursorData();

private:
  WaylandCursorData(wl_shm* shm);
  wl_cursor_theme *cursor_theme_;
  wl_cursor **cursors_;
};

WaylandCursorData::WaylandCursorData(wl_shm* shm)
{
    const char *cursor_names[] = {
      "bottom_left_corner",
      "bottom_right_corner",
      "bottom_side",
      "grabbing",
      "left_ptr",
      "left_side",
      "right_side",
      "top_left_corner",
      "top_right_corner",
      "top_side",
      "xterm",
      "hand1",
    };

    // (kalyan) We should be able to configure the size of cursor and theme name.
    unsigned int i, array_size = (sizeof(cursor_names) / sizeof(cursor_names[0])) -1;
    cursor_theme_ = wl_cursor_theme_load(NULL, 24, shm);
    cursors_ = new wl_cursor*[array_size];
    memset(cursors_, 0, sizeof(wl_cursor*) * array_size);

    for(i = 0; i < array_size; i++)
      cursors_[i] = wl_cursor_theme_get_cursor(cursor_theme_, cursor_names[i]);
}

struct wl_cursor_image* WaylandCursorData::GetCursorImage(int index)
{
    struct wl_cursor *cursor = cursors_[index];
    if (!cursor)
      return 0;

    return cursor->images[0];
}

WaylandCursorData::~WaylandCursorData()
{
}

void WaylandCursorData::Clear()
{
 if(cursor_theme_)
 {
   wl_cursor_theme_destroy(cursor_theme_);
   cursor_theme_ = NULL;
 }

 if(cursors_)
 {
   delete[] cursors_;
   cursors_ = NULL;
 }
}

WaylandCursor::WaylandCursor(wl_shm* shm) : input_pointer_(NULL),
    buffer_(NULL),
    width_(0),
    height_(0),
    type_(CURSOR_UNSET)
{
  pointer_surface_ = new WaylandSurface();
  WaylandCursorData::Initialize(shm);
}

WaylandCursor::~WaylandCursor()
{
  if (pointer_surface_) {
    delete pointer_surface_;
    pointer_surface_ = NULL;
  }
}

void WaylandCursor::Update(CursorType type, uint32_t serial)
{
  if (!input_pointer_)
    return;

  ValidateBuffer(type, serial);
  struct wl_surface* surface = pointer_surface_->wlSurface();
  wl_surface_attach(surface, buffer_, 0, 0);
  wl_surface_damage(surface, 0, 0, width_, height_);
  wl_surface_commit(surface);
}

void WaylandCursor::SetInputPointer(wl_pointer* pointer)
{
  input_pointer_ = pointer;
}

void WaylandCursor::ValidateBuffer(CursorType type, uint32_t serial)
{
  if (type_ == type)
    return;

  struct wl_cursor_image* image = WaylandCursorData::GetInstance()->
      GetCursorImage(type - 1);
  buffer_ = wl_cursor_image_get_buffer(image);
  width_ = image->width;
  height_ = image->height;
  wl_pointer_set_cursor(input_pointer_,
                        serial,
                        pointer_surface_->wlSurface(),
                        image->hotspot_x,
                        image->hotspot_y);
}

void WaylandCursor::Clear()
{
  WaylandCursorData::GetInstance()->Clear();
}

}  // namespace ozonewayland

<commit_msg>wayland/inputs: Change WaylandCursorData constructor and destructor<commit_after>// Copyright 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/wayland/inputs/cursor.h"
#include "ozone/wayland/surface.h"

namespace ozonewayland {

class WaylandCursorData {
 public:
  WaylandCursorData(wl_shm* shm);
  virtual ~WaylandCursorData();

  static WaylandCursorData* GetInstance() {
    return impl_;
  }

  static void InitializeCursorData(wl_shm* shm) {
    if (!impl_)
      impl_ = new WaylandCursorData(shm);
  }

  static void DestroyCursorData() {
    if (impl_) {
      delete impl_;
      impl_ = NULL;
    }
  }

  struct wl_cursor_image* GetCursorImage(int index);

 private:
  wl_cursor_theme *cursor_theme_;
  wl_cursor **cursors_;
  static WaylandCursorData* impl_;
};

WaylandCursorData* WaylandCursorData::impl_ = NULL;

WaylandCursorData::WaylandCursorData(wl_shm* shm)
{
    const char *cursor_names[] = {
      "bottom_left_corner",
      "bottom_right_corner",
      "bottom_side",
      "grabbing",
      "left_ptr",
      "left_side",
      "right_side",
      "top_left_corner",
      "top_right_corner",
      "top_side",
      "xterm",
      "hand1",
    };

    // (kalyan) We should be able to configure the size of cursor and theme name.
    unsigned int i, array_size = (sizeof(cursor_names) / sizeof(cursor_names[0])) -1;
    cursor_theme_ = wl_cursor_theme_load(NULL, 24, shm);
    cursors_ = new wl_cursor*[array_size];
    memset(cursors_, 0, sizeof(wl_cursor*) * array_size);

    for(i = 0; i < array_size; i++)
      cursors_[i] = wl_cursor_theme_get_cursor(cursor_theme_, cursor_names[i]);
}

struct wl_cursor_image* WaylandCursorData::GetCursorImage(int index)
{
    struct wl_cursor *cursor = cursors_[index];
    if (!cursor)
      return 0;

    return cursor->images[0];
}

WaylandCursorData::~WaylandCursorData()
{
 if(cursor_theme_)
 {
   wl_cursor_theme_destroy(cursor_theme_);
   cursor_theme_ = NULL;
 }

 if(cursors_)
 {
   delete[] cursors_;
   cursors_ = NULL;
 }
}

WaylandCursor::WaylandCursor(wl_shm* shm) : input_pointer_(NULL),
    buffer_(NULL),
    width_(0),
    height_(0),
    type_(CURSOR_UNSET)
{
  pointer_surface_ = new WaylandSurface();
  WaylandCursorData::InitializeCursorData(shm);
}

WaylandCursor::~WaylandCursor()
{
  if (pointer_surface_) {
    delete pointer_surface_;
    pointer_surface_ = NULL;
  }
}

void WaylandCursor::Update(CursorType type, uint32_t serial)
{
  if (!input_pointer_)
    return;

  ValidateBuffer(type, serial);
  struct wl_surface* surface = pointer_surface_->wlSurface();
  wl_surface_attach(surface, buffer_, 0, 0);
  wl_surface_damage(surface, 0, 0, width_, height_);
  wl_surface_commit(surface);
}

void WaylandCursor::SetInputPointer(wl_pointer* pointer)
{
  input_pointer_ = pointer;
}

void WaylandCursor::ValidateBuffer(CursorType type, uint32_t serial)
{
  if (type_ == type)
    return;

  struct wl_cursor_image* image = WaylandCursorData::GetInstance()->
      GetCursorImage(type - 1);
  buffer_ = wl_cursor_image_get_buffer(image);
  width_ = image->width;
  height_ = image->height;
  wl_pointer_set_cursor(input_pointer_,
                        serial,
                        pointer_surface_->wlSurface(),
                        image->hotspot_x,
                        image->hotspot_y);
}

void WaylandCursor::Clear()
{
  WaylandCursorData::DestroyCursorData();
}

}  // namespace ozonewayland
<|endoftext|>