<commit_before>/***************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Aaron Kennedy <aaron.kennedy@jollamobile.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QWaylandInputDevice>
#include "homeapplication.h"
#include "windowmodel.h"
#include "lipstickcompositorprocwindow.h"
#include "lipstickcompositor.h"

LipstickCompositor *LipstickCompositor::m_instance = 0;

LipstickCompositor::LipstickCompositor()
: QWaylandCompositor(this), m_totalWindowCount(0), m_nextWindowId(1), m_homeActive(true), m_shaderEffect(0),
  m_fullscreenSurface(0), m_directRenderingActive(false), m_topmostWindowId(0), m_screenOrientation(Qt::PrimaryOrientation)
{
    if (m_instance) qFatal("LipstickCompositor: Only one compositor instance per process is supported");
    m_instance = this;

    QObject::connect(this, SIGNAL(frameSwapped()), this, SLOT(windowSwapped()));

    emit HomeApplication::instance()->homeActiveChanged();
}

LipstickCompositor::~LipstickCompositor()
{
    delete m_shaderEffect;
}

LipstickCompositor *LipstickCompositor::instance()
{
    return m_instance;
}

void LipstickCompositor::classBegin()
{
}

void LipstickCompositor::componentComplete()
{
    QWaylandCompositor::setOutputGeometry(QRect(0, 0, width(), height()));
}

void LipstickCompositor::surfaceCreated(QWaylandSurface *surface)
{
    Q_UNUSED(surface)
    connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
    connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
    connect(surface, SIGNAL(sizeChanged()), this, SLOT(surfaceSizeChanged()));
    connect(surface, SIGNAL(titleChanged()), this, SLOT(surfaceTitleChanged()));
    connect(surface, SIGNAL(windowPropertyChanged(QString,QVariant)), this, SLOT(windowPropertyChanged(QString)));
    connect(surface, SIGNAL(raiseRequested()), this, SLOT(surfaceRaised()));
    connect(surface, SIGNAL(lowerRequested()), this, SLOT(surfaceLowered()));
}

int LipstickCompositor::windowCount() const
{
    return m_mappedSurfaces.count();
}

int LipstickCompositor::ghostWindowCount() const
{
    return m_totalWindowCount - windowCount();
}

bool LipstickCompositor::homeActive() const
{
    return m_homeActive;
}

void LipstickCompositor::setHomeActive(bool a)
{
    if (a == m_homeActive)
        return;

    m_homeActive = a;

    emit homeActiveChanged();
    emit HomeApplication::instance()->homeActiveChanged();
}

bool LipstickCompositor::debug() const
{
    static enum { Yes, No, Unknown } status = Unknown;
    if (status == Unknown) {
        QByteArray v = qgetenv("LIPSTICK_COMPOSITOR_DEBUG");
        bool value = !v.isEmpty() && v != "0" && v != "false";
        if (value) status = Yes;
        else status = No;
    }
    return status == Yes;
}

QObject *LipstickCompositor::windowForId(int id) const
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    return window;
}

void LipstickCompositor::closeClientForWindowId(int id)
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    if (window && window->surface())
        destroyClientForSurface(window->surface());
}

QWaylandSurface *LipstickCompositor::surfaceForId(int id) const
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    return window?window->surface():0;
}

int LipstickCompositor::windowIdForLink(QWaylandSurface *s, uint link) const
{
    for (QHash<int, LipstickCompositorWindow *>::ConstIterator iter = m_mappedSurfaces.begin();
         iter != m_mappedSurfaces.end(); ++iter) {

        QWaylandSurface *windowSurface = iter.value()->surface();

        if (windowSurface && windowSurface->processId() == s->processId() &&
            windowSurface->windowProperties().value("WINID", uint(0)).toUInt() == link)
            return iter.value()->windowId();
    }

    return 0;
}

void LipstickCompositor::clearKeyboardFocus()
{
    defaultInputDevice()->setKeyboardFocus(0);
}

void LipstickCompositor::setFullscreenSurface(QWaylandSurface *surface)
{
    if (surface == m_fullscreenSurface)
        return;

    // Prevent flicker when returning to composited mode
    if (!surface && m_fullscreenSurface && m_fullscreenSurface->surfaceItem())
        m_fullscreenSurface->surfaceItem()->update();

    m_fullscreenSurface = surface;

    const bool directRenderingSucceeded = setDirectRenderSurface(m_fullscreenSurface, openglContext());
    if (surface && !directRenderingSucceeded)
        qWarning() << Q_FUNC_INFO << "failed to set direct render surface";
    if ((surface && directRenderingSucceeded) != m_directRenderingActive) {
        m_directRenderingActive = surface && directRenderingSucceeded;
        emit directRenderingActiveChanged();
    }

    emit fullscreenSurfaceChanged();
}

void LipstickCompositor::setTopmostWindowId(int id)
{
    if (id != m_topmostWindowId) {
        m_topmostWindowId = id;
        emit topmostWindowIdChanged();
    }
}

void LipstickCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface)
{
    Q_ASSERT(surface);
    surfaceUnmapped(static_cast<QWaylandSurface *>(surface));
}

void LipstickCompositor::surfaceMapped()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    //Ignore surface if it's not a window surface
    if (!surface->hasShellSurface())
        return;

    QVariantMap properties = surface->windowProperties();
    QString category = properties.value("CATEGORY").toString();

    Q_ASSERT(surface->surfaceItem() == 0);

    int id = m_nextWindowId++;

    LipstickCompositorWindow *item = new LipstickCompositorWindow(id, category, surface, contentItem());
    item->setSize(surface->size());
    QObject::connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed()));
    m_totalWindowCount++;
    m_mappedSurfaces.insert(id, item);

    item->setTouchEventsEnabled(true);

    emit windowCountChanged();
    emit windowAdded(item);

    windowAdded(id);

    emit availableWinIdsChanged();
}

void LipstickCompositor::surfaceUnmapped()
{
    surfaceUnmapped(qobject_cast<QWaylandSurface *>(sender()));
}

void LipstickCompositor::surfaceSizeChanged()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());

    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
    if (window)
        window->setSize(surface->size());
}

void LipstickCompositor::surfaceTitleChanged()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit window->titleChanged();

        int windowId = window->windowId();

        for (int ii = 0; ii < m_windowModels.count(); ++ii)
            m_windowModels.at(ii)->titleChanged(windowId);
    }
}

void LipstickCompositor::surfaceRaised()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit windowRaised(window);
    }
}

void LipstickCompositor::surfaceLowered()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit windowLowered(window);
    }
}

void LipstickCompositor::windowSwapped()
{
    frameFinished(m_fullscreenSurface);
}

void LipstickCompositor::windowDestroyed()
{
    m_totalWindowCount--;
    emit ghostWindowCountChanged();
}

void LipstickCompositor::windowPropertyChanged(const QString &property)
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());

    if (debug())
        qDebug() << "Window properties changed:" << surface << surface->windowProperties();

    if (property == QLatin1String("MOUSE_REGION")) {
        LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
        if (window)
            window->refreshMouseRegion();
    }
}

void LipstickCompositor::surfaceUnmapped(QWaylandSurface *surface)
{
    LipstickCompositorWindow *item = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
    surface->setSurfaceItem(0);

    if (surface == m_fullscreenSurface)
        setFullscreenSurface(0);

    if (item) {
        int id = item->windowId();

        int gc = ghostWindowCount();
        m_mappedSurfaces.remove(item->windowId());

        emit windowCountChanged();
        emit windowRemoved(item);

        item->m_windowClosed = true;
        item->tryRemove();

        if (gc != ghostWindowCount())
            emit ghostWindowCountChanged();

        windowRemoved(id);

        emit availableWinIdsChanged();
    }
}

void LipstickCompositor::surfaceUnmapped(LipstickCompositorProcWindow *item)
{
    int id = item->windowId();

    int gc = ghostWindowCount();
    m_mappedSurfaces.remove(item->windowId());

    emit windowCountChanged();
    emit windowRemoved(item);

    item->m_windowClosed = true;
    item->tryRemove();

    if (gc != ghostWindowCount())
        emit ghostWindowCountChanged();

    windowRemoved(id);

    emit availableWinIdsChanged();
}

void LipstickCompositor::windowAdded(int id)
{
    for (int ii = 0; ii < m_windowModels.count(); ++ii)
        m_windowModels.at(ii)->addItem(id);
}

void LipstickCompositor::windowRemoved(int id)
{
    for (int ii = 0; ii < m_windowModels.count(); ++ii)
        m_windowModels.at(ii)->remItem(id);
}

QQmlComponent *LipstickCompositor::shaderEffectComponent()
{
    const char *qml_source =
        "import QtQuick 2.0\n"
        "ShaderEffect {\n"
            "property QtObject window\n"
            "property ShaderEffectSource source: ShaderEffectSource { sourceItem: window }\n"
        "}";

    if (!m_shaderEffect) {
        m_shaderEffect = new QQmlComponent(qmlEngine(this));
        m_shaderEffect->setData(qml_source, QUrl());
    }
    return m_shaderEffect;
}

void LipstickCompositor::setScreenOrientation(Qt::ScreenOrientation screenOrientation)
{
    if (m_screenOrientation != screenOrientation) {
        QWaylandCompositor::setScreenOrientation(screenOrientation);

        m_screenOrientation = screenOrientation;
        emit screenOrientationChanged();
    }
}
<commit_msg>[lipstick] Change semantics of surface mapped and unmapped<commit_after>/***************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Aaron Kennedy <aaron.kennedy@jollamobile.com>
**
** This file is part of lipstick.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QWaylandInputDevice>
#include "homeapplication.h"
#include "windowmodel.h"
#include "lipstickcompositorprocwindow.h"
#include "lipstickcompositor.h"

LipstickCompositor *LipstickCompositor::m_instance = 0;

LipstickCompositor::LipstickCompositor()
: QWaylandCompositor(this), m_totalWindowCount(0), m_nextWindowId(1), m_homeActive(true), m_shaderEffect(0),
  m_fullscreenSurface(0), m_directRenderingActive(false), m_topmostWindowId(0), m_screenOrientation(Qt::PrimaryOrientation)
{
    if (m_instance) qFatal("LipstickCompositor: Only one compositor instance per process is supported");
    m_instance = this;

    QObject::connect(this, SIGNAL(frameSwapped()), this, SLOT(windowSwapped()));

    emit HomeApplication::instance()->homeActiveChanged();
}

LipstickCompositor::~LipstickCompositor()
{
    delete m_shaderEffect;
}

LipstickCompositor *LipstickCompositor::instance()
{
    return m_instance;
}

void LipstickCompositor::classBegin()
{
}

void LipstickCompositor::componentComplete()
{
    QWaylandCompositor::setOutputGeometry(QRect(0, 0, width(), height()));
}

void LipstickCompositor::surfaceCreated(QWaylandSurface *surface)
{
    Q_UNUSED(surface)
    connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
    connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
    connect(surface, SIGNAL(sizeChanged()), this, SLOT(surfaceSizeChanged()));
    connect(surface, SIGNAL(titleChanged()), this, SLOT(surfaceTitleChanged()));
    connect(surface, SIGNAL(windowPropertyChanged(QString,QVariant)), this, SLOT(windowPropertyChanged(QString)));
    connect(surface, SIGNAL(raiseRequested()), this, SLOT(surfaceRaised()));
    connect(surface, SIGNAL(lowerRequested()), this, SLOT(surfaceLowered()));
}

int LipstickCompositor::windowCount() const
{
    return m_mappedSurfaces.count();
}

int LipstickCompositor::ghostWindowCount() const
{
    return m_totalWindowCount - windowCount();
}

bool LipstickCompositor::homeActive() const
{
    return m_homeActive;
}

void LipstickCompositor::setHomeActive(bool a)
{
    if (a == m_homeActive)
        return;

    m_homeActive = a;

    emit homeActiveChanged();
    emit HomeApplication::instance()->homeActiveChanged();
}

bool LipstickCompositor::debug() const
{
    static enum { Yes, No, Unknown } status = Unknown;
    if (status == Unknown) {
        QByteArray v = qgetenv("LIPSTICK_COMPOSITOR_DEBUG");
        bool value = !v.isEmpty() && v != "0" && v != "false";
        if (value) status = Yes;
        else status = No;
    }
    return status == Yes;
}

QObject *LipstickCompositor::windowForId(int id) const
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    return window;
}

void LipstickCompositor::closeClientForWindowId(int id)
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    if (window && window->surface())
        destroyClientForSurface(window->surface());
}

QWaylandSurface *LipstickCompositor::surfaceForId(int id) const
{
    LipstickCompositorWindow *window = m_mappedSurfaces.value(id, 0);
    return window?window->surface():0;
}

int LipstickCompositor::windowIdForLink(QWaylandSurface *s, uint link) const
{
    for (QHash<int, LipstickCompositorWindow *>::ConstIterator iter = m_mappedSurfaces.begin();
         iter != m_mappedSurfaces.end(); ++iter) {

        QWaylandSurface *windowSurface = iter.value()->surface();

        if (windowSurface && windowSurface->processId() == s->processId() &&
            windowSurface->windowProperties().value("WINID", uint(0)).toUInt() == link)
            return iter.value()->windowId();
    }

    return 0;
}

void LipstickCompositor::clearKeyboardFocus()
{
    defaultInputDevice()->setKeyboardFocus(0);
}

void LipstickCompositor::setFullscreenSurface(QWaylandSurface *surface)
{
    if (surface == m_fullscreenSurface)
        return;

    // Prevent flicker when returning to composited mode
    if (!surface && m_fullscreenSurface && m_fullscreenSurface->surfaceItem())
        m_fullscreenSurface->surfaceItem()->update();

    m_fullscreenSurface = surface;

    const bool directRenderingSucceeded = setDirectRenderSurface(m_fullscreenSurface, openglContext());
    if (surface && !directRenderingSucceeded)
        qWarning() << Q_FUNC_INFO << "failed to set direct render surface";
    if ((surface && directRenderingSucceeded) != m_directRenderingActive) {
        m_directRenderingActive = surface && directRenderingSucceeded;
        emit directRenderingActiveChanged();
    }

    emit fullscreenSurfaceChanged();
}

void LipstickCompositor::setTopmostWindowId(int id)
{
    if (id != m_topmostWindowId) {
        m_topmostWindowId = id;
        emit topmostWindowIdChanged();
    }
}

void LipstickCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface)
{
    Q_ASSERT(surface);
    LipstickCompositorWindow *item = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
    surface->setSurfaceItem(0);

    if (surface == m_fullscreenSurface)
        setFullscreenSurface(0);

    if (item) {
        int id = item->windowId();

        int gc = ghostWindowCount();
        m_mappedSurfaces.remove(item->windowId());

        emit windowCountChanged();
        emit windowRemoved(item);

        item->m_windowClosed = true;
        item->tryRemove();

        if (gc != ghostWindowCount())
            emit ghostWindowCountChanged();

        windowRemoved(id);

        emit availableWinIdsChanged();
    }
}

void LipstickCompositor::surfaceMapped()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    //Ignore surface if it's not a window surface
    if (!surface->hasShellSurface())
        return;

    QVariantMap properties = surface->windowProperties();
    QString category = properties.value("CATEGORY").toString();

    if (surface->surfaceItem())
        return;

    // The surface was mapped for the first time
    int id = m_nextWindowId++;
    LipstickCompositorWindow *item = new LipstickCompositorWindow(id, category, surface, contentItem());
    item->setSize(surface->size());
    QObject::connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed()));
    m_totalWindowCount++;
    m_mappedSurfaces.insert(id, item);

    item->setTouchEventsEnabled(true);

    emit windowCountChanged();
    emit windowAdded(item);

    windowAdded(id);

    emit availableWinIdsChanged();
}

void LipstickCompositor::surfaceUnmapped()
{
    surfaceUnmapped(qobject_cast<QWaylandSurface *>(sender()));
}

void LipstickCompositor::surfaceSizeChanged()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());

    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
    if (window)
        window->setSize(surface->size());
}

void LipstickCompositor::surfaceTitleChanged()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit window->titleChanged();

        int windowId = window->windowId();

        for (int ii = 0; ii < m_windowModels.count(); ++ii)
            m_windowModels.at(ii)->titleChanged(windowId);
    }
}

void LipstickCompositor::surfaceRaised()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit windowRaised(window);
    }
}

void LipstickCompositor::surfaceLowered()
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
    LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());

    if (window) {
        emit windowLowered(window);
    }
}

void LipstickCompositor::windowSwapped()
{
    frameFinished(m_fullscreenSurface);
}

void LipstickCompositor::windowDestroyed()
{
    m_totalWindowCount--;
    emit ghostWindowCountChanged();
}

void LipstickCompositor::windowPropertyChanged(const QString &property)
{
    QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());

    if (debug())
        qDebug() << "Window properties changed:" << surface << surface->windowProperties();

    if (property == QLatin1String("MOUSE_REGION")) {
        LipstickCompositorWindow *window = static_cast<LipstickCompositorWindow *>(surface->surfaceItem());
        if (window)
            window->refreshMouseRegion();
    }
}

void LipstickCompositor::surfaceUnmapped(QWaylandSurface *surface)
{
    if (surface == m_fullscreenSurface)
        setFullscreenSurface(0);
}

void LipstickCompositor::surfaceUnmapped(LipstickCompositorProcWindow *item)
{
    int id = item->windowId();

    int gc = ghostWindowCount();
    m_mappedSurfaces.remove(item->windowId());

    emit windowCountChanged();
    emit windowRemoved(item);

    item->m_windowClosed = true;
    item->tryRemove();

    if (gc != ghostWindowCount())
        emit ghostWindowCountChanged();

    windowRemoved(id);

    emit availableWinIdsChanged();
}

void LipstickCompositor::windowAdded(int id)
{
    for (int ii = 0; ii < m_windowModels.count(); ++ii)
        m_windowModels.at(ii)->addItem(id);
}

void LipstickCompositor::windowRemoved(int id)
{
    for (int ii = 0; ii < m_windowModels.count(); ++ii)
        m_windowModels.at(ii)->remItem(id);
}

QQmlComponent *LipstickCompositor::shaderEffectComponent()
{
    const char *qml_source =
        "import QtQuick 2.0\n"
        "ShaderEffect {\n"
            "property QtObject window\n"
            "property ShaderEffectSource source: ShaderEffectSource { sourceItem: window }\n"
        "}";

    if (!m_shaderEffect) {
        m_shaderEffect = new QQmlComponent(qmlEngine(this));
        m_shaderEffect->setData(qml_source, QUrl());
    }
    return m_shaderEffect;
}

void LipstickCompositor::setScreenOrientation(Qt::ScreenOrientation screenOrientation)
{
    if (m_screenOrientation != screenOrientation) {
        QWaylandCompositor::setScreenOrientation(screenOrientation);

        m_screenOrientation = screenOrientation;
        emit screenOrientationChanged();
    }
}
<|endoftext|>


<commit_before>#include "Makefile.hpp"

#include <configure/BuildGraph.hpp>
#include <configure/Build.hpp>
#include <configure/Command.hpp>
#include <configure/Filesystem.hpp>
#include <configure/Graph.hpp>
#include <configure/quote.hpp>

#include <boost/algorithm/string/join.hpp>
#include <boost/graph/topological_sort.hpp>

#include <fstream>
#include <unordered_set>

namespace configure { namespace generators {

	std::string Makefile::name() const
	{ return "makefile"; }

	void Makefile::generate(Build& build) const
	{
		std::ofstream out((build.directory() / "Makefile").string());
		out << "# Generated makefile" << std::endl;
		BuildGraph const& bg = build.build_graph();
		Graph const& g = bg.graph();

		// Fill the "all" rule
		{
			std::set<Node*> all;
			std::set<Node*> phony;

			// Search leaf nodes in the graph which are not virtual nodes
			for (auto vertex_range = boost::vertices(g);
			     vertex_range.first != vertex_range.second;
			     ++vertex_range.first)
			{
				auto vertex = *vertex_range.first;
				auto& node = bg.node(vertex);
				if (node->is_virtual())
				{
					if (!node->name().empty())
						phony.insert(node.get());
					continue;
				}
				// Check if a node is not a dependency of something else
				// then it should be in the "all" rule.
				auto out_edge_range = boost::out_edges(vertex, g);
				if (out_edge_range.first == out_edge_range.second)
					all.insert(node.get());
			}

			// Add outputs of the all virtual node
			for (auto in_edge_range = boost::in_edges(build.virtual_node("all")->index, g);
			     in_edge_range.first != in_edge_range.second;
			     ++in_edge_range.first)
			{
				all.insert(
					bg.node(boost::source(*in_edge_range.first, g)).get()
				);
			}

			out << ".PHONY:" << std::endl;
			out << ".PHONY: all";
			for (auto node: phony)
				out << ' ' << node->name();
			out << "\n\n";

			if (!all.empty())
			{
				out << "all:";
				for (auto& node: all)
				{
					if (node->is_file())
						out << ' ' << this->node_path(build, *node);
					else if (node->is_virtual() && !node->name().empty())
						out << ' ' << node->name();
				}
				out << "\n\n";
			}
		}

		for (auto vertex_range = boost::vertices(g);
		     vertex_range.first != vertex_range.second;
		     ++vertex_range.first)
		{
			auto vertex = *vertex_range.first;
			auto node = bg.node(vertex).get();

			auto in_edge_range = boost::in_edges(vertex, g);

			if (in_edge_range.first == in_edge_range.second)
				continue;

			if (node->is_virtual())
				out << node->name() << ':';
			else
				out << this->node_path(build, *node) << ':';

			for (GraphTraits::in_edge_iterator i = in_edge_range.first;
			     i != in_edge_range.second; ++i)
			{
				auto node = bg.node(boost::source(*i, g)).get();
				if (node->is_file())
					out << ' ' << this->node_path(build, *node);
				else if (node->is_virtual())
					out << ' ' << node->name();
			}
			out << std::endl;

			std::unordered_set<Command const*> seen_commands;
			for (; in_edge_range.first != in_edge_range.second;
			     ++in_edge_range.first)
			{
				Command const* cmd_ptr = &bg.link(*in_edge_range.first).command();
				if (seen_commands.count(cmd_ptr) != 0)
					continue;
				seen_commands.insert(cmd_ptr);
				for (auto const& shell_command: cmd_ptr->shell_commands())
				{
					out << '\t';
					this->dump_command(out, shell_command.dump());
					out << std::endl;
				}
			}
			out << std::endl;
		}

	}

	std::string Makefile::node_path(Build&, Node& node) const
	{
		return node.path().string();
	}

	void Makefile::dump_command(
		    std::ostream& out,
		    std::vector<std::string> const& cmd) const
	{
		out << quote<CommandParser::make>(cmd);
	}

	bool Makefile::is_available(Build& build) const
	{
		return build.fs().which("make") != boost::none;
	}
	std::vector<std::string>
	Makefile::build_command(Build& build, std::string const& target) const
	{
		return {
			"make", "-C", build.directory().string(),
			target.empty() ? "all" : target
		};
	}
}}

<commit_msg>Use capitalized name for Makefile generator.<commit_after>#include "Makefile.hpp"

#include <configure/BuildGraph.hpp>
#include <configure/Build.hpp>
#include <configure/Command.hpp>
#include <configure/Filesystem.hpp>
#include <configure/Graph.hpp>
#include <configure/quote.hpp>

#include <boost/algorithm/string/join.hpp>
#include <boost/graph/topological_sort.hpp>

#include <fstream>
#include <unordered_set>

namespace configure { namespace generators {

	std::string Makefile::name() const
	{ return "Makefile"; }

	void Makefile::generate(Build& build) const
	{
		std::ofstream out((build.directory() / "Makefile").string());
		out << "# Generated makefile" << std::endl;
		BuildGraph const& bg = build.build_graph();
		Graph const& g = bg.graph();

		// Fill the "all" rule
		{
			std::set<Node*> all;
			std::set<Node*> phony;

			// Search leaf nodes in the graph which are not virtual nodes
			for (auto vertex_range = boost::vertices(g);
			     vertex_range.first != vertex_range.second;
			     ++vertex_range.first)
			{
				auto vertex = *vertex_range.first;
				auto& node = bg.node(vertex);
				if (node->is_virtual())
				{
					if (!node->name().empty())
						phony.insert(node.get());
					continue;
				}
				// Check if a node is not a dependency of something else
				// then it should be in the "all" rule.
				auto out_edge_range = boost::out_edges(vertex, g);
				if (out_edge_range.first == out_edge_range.second)
					all.insert(node.get());
			}

			// Add outputs of the all virtual node
			for (auto in_edge_range = boost::in_edges(build.virtual_node("all")->index, g);
			     in_edge_range.first != in_edge_range.second;
			     ++in_edge_range.first)
			{
				all.insert(
					bg.node(boost::source(*in_edge_range.first, g)).get()
				);
			}

			out << ".PHONY:" << std::endl;
			out << ".PHONY: all";
			for (auto node: phony)
				out << ' ' << node->name();
			out << "\n\n";

			if (!all.empty())
			{
				out << "all:";
				for (auto& node: all)
				{
					if (node->is_file())
						out << ' ' << this->node_path(build, *node);
					else if (node->is_virtual() && !node->name().empty())
						out << ' ' << node->name();
				}
				out << "\n\n";
			}
		}

		for (auto vertex_range = boost::vertices(g);
		     vertex_range.first != vertex_range.second;
		     ++vertex_range.first)
		{
			auto vertex = *vertex_range.first;
			auto node = bg.node(vertex).get();

			auto in_edge_range = boost::in_edges(vertex, g);

			if (in_edge_range.first == in_edge_range.second)
				continue;

			if (node->is_virtual())
				out << node->name() << ':';
			else
				out << this->node_path(build, *node) << ':';

			for (GraphTraits::in_edge_iterator i = in_edge_range.first;
			     i != in_edge_range.second; ++i)
			{
				auto node = bg.node(boost::source(*i, g)).get();
				if (node->is_file())
					out << ' ' << this->node_path(build, *node);
				else if (node->is_virtual())
					out << ' ' << node->name();
			}
			out << std::endl;

			std::unordered_set<Command const*> seen_commands;
			for (; in_edge_range.first != in_edge_range.second;
			     ++in_edge_range.first)
			{
				Command const* cmd_ptr = &bg.link(*in_edge_range.first).command();
				if (seen_commands.count(cmd_ptr) != 0)
					continue;
				seen_commands.insert(cmd_ptr);
				for (auto const& shell_command: cmd_ptr->shell_commands())
				{
					out << '\t';
					this->dump_command(out, shell_command.dump());
					out << std::endl;
				}
			}
			out << std::endl;
		}

	}

	std::string Makefile::node_path(Build&, Node& node) const
	{
		return node.path().string();
	}

	void Makefile::dump_command(
		    std::ostream& out,
		    std::vector<std::string> const& cmd) const
	{
		out << quote<CommandParser::make>(cmd);
	}

	bool Makefile::is_available(Build& build) const
	{
		return build.fs().which("make") != boost::none;
	}
	std::vector<std::string>
	Makefile::build_command(Build& build, std::string const& target) const
	{
		return {
			"make", "-C", build.directory().string(),
			target.empty() ? "all" : target
		};
	}
}}

<|endoftext|>


<commit_before>// Copyright (c) 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 <stdlib.h>
#include <stdbool.h>
#include <stdio.h>

#include <glib.h>
#include <gio/gio.h>
#include <locale.h>

#include "base/at_exit.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"

#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"

#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/installer/package_installer.h"
#include "xwalk/application/tools/linux/dbus_connection.h"
#include "xwalk/runtime/common/xwalk_paths.h"
#if defined(OS_TIZEN)
#include "xwalk/application/common/id_util.h"
#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
#endif

using xwalk::application::ApplicationData;
using xwalk::application::ApplicationStorage;
using xwalk::application::PackageInstaller;

static char* install_path;
static char* uninstall_appid;

static gint debugging_port = -1;

static GOptionEntry entries[] = {
  { "install", 'i', 0, G_OPTION_ARG_STRING, &install_path,
    "Path of the application to be installed/updated", "PATH" },
  { "uninstall", 'u', 0, G_OPTION_ARG_STRING, &uninstall_appid,
    "Uninstall the application with this appid", "APPID" },
  { "debugging_port", 'd', 0, G_OPTION_ARG_INT, &debugging_port,
    "Enable remote debugging, port number 0 means to disable", NULL },
  { NULL }
};

#if defined(SHARED_PROCESS_MODE)
namespace {

const char xwalk_service_name[] = "org.crosswalkproject.Runtime1";
const char xwalk_running_manager_iface[] =
    "org.crosswalkproject.Running.Manager1";
const dbus::ObjectPath kRunningManagerDBusPath("/running1");

}  // namespace

static void TerminateIfRunning(const std::string& app_id) {
  dbus::Bus::Options options;
#if defined(OS_TIZEN_MOBILE)
  options.bus_type = dbus::Bus::CUSTOM_ADDRESS;
  options.address.assign("unix:path=/run/user/app/dbus/user_bus_socket");
#endif
  scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
  dbus::ObjectProxy* app_proxy =
      bus->GetObjectProxy(xwalk_service_name, kRunningManagerDBusPath);
  if (!app_proxy)
    return;

  dbus::MethodCall method_call(
      xwalk_running_manager_iface, "TerminateIfRunning");
  dbus::MessageWriter writer(&method_call);
  writer.AppendString(app_id);

  app_proxy->CallMethodAndBlock(&method_call, 1000);
}

static bool enable_remote_debugging(gint debugging_port) {
  dbus::Bus::Options options;
#if defined(OS_TIZEN_MOBILE)
  options.bus_type = dbus::Bus::CUSTOM_ADDRESS;
  options.address.assign("unix:path=/run/user/app/dbus/user_bus_socket");
#endif
  scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
  dbus::ObjectProxy* app_proxy =
      bus->GetObjectProxy(
          xwalk_service_name,
          kRunningManagerDBusPath);
  if (!app_proxy)
    return false;

  dbus::MethodCall method_call(
      xwalk_running_manager_iface, "EnableRemoteDebugging");
  dbus::MessageWriter writer(&method_call);
  writer.AppendUint32(debugging_port);

  app_proxy->CallMethodAndBlock(&method_call, 1000);

  if (debugging_port > 0) {
    g_print("Remote debugging enabled at port '%d'\n", debugging_port);
  } else {
    g_print("Remote debugging has been disabled\n");
  }
  return true;
}
#endif

bool list_applications(ApplicationStorage* storage) {
  std::vector<std::string> app_ids;
  if (!storage->GetInstalledApplicationIDs(app_ids))
    return false;

  g_print("Application ID                       Application Name\n");
  g_print("-----------------------------------------------------\n");
  for (unsigned i = 0; i < app_ids.size(); ++i) {
    scoped_refptr<ApplicationData> app_data =
        storage->GetApplicationData(app_ids.at(i));
    if (!app_data) {
      g_print("Failed to obtain app data for xwalk id: %s\n",
              app_ids.at(i).c_str());
      continue;
    }
    g_print("%s  %s\n", app_ids.at(i).c_str(), app_data->Name().c_str());
  }
  g_print("-----------------------------------------------------\n");

  return true;
}

int main(int argc, char* argv[]) {
  setlocale(LC_ALL, "");
  GError* error = NULL;
  GOptionContext* context;
  bool success = false;

#if !GLIB_CHECK_VERSION(2, 36, 0)
  // g_type_init() is deprecated on GLib since 2.36, Tizen has 2.32.
  g_type_init();
#endif

#if defined(OS_TIZEN)
  if (xwalk_tizen_check_user_app())
    exit(1);
#endif

  context = g_option_context_new("- Crosswalk Application Management");
  g_option_context_add_main_entries(context, entries, NULL);
  if (!g_option_context_parse(context, &argc, &argv, &error)) {
    g_print("option parsing failed: %s\n", error->message);
    exit(1);
  }

  base::AtExitManager at_exit;
  base::FilePath data_path;
  xwalk::RegisterPathProvider();
  PathService::Get(xwalk::DIR_DATA_PATH, &data_path);
  scoped_ptr<ApplicationStorage> storage(new ApplicationStorage(data_path));
  scoped_ptr<PackageInstaller> installer =
      PackageInstaller::Create(storage.get());

  if (install_path) {
    std::string app_id;
    const base::FilePath& path = base::FilePath(install_path);
    success = installer->Install(path, &app_id);
    if (!success && storage->Contains(app_id)) {
      g_print("trying to update %s\n", app_id.c_str());
      success = installer->Update(app_id, path);
    }
  } else if (uninstall_appid) {
#if defined(SHARED_PROCESS_MODE)
    TerminateIfRunning(uninstall_appid);
#endif
    success = installer->Uninstall(uninstall_appid);
  } else if (debugging_port >= 0) {
#if defined(SHARED_PROCESS_MODE)
    // Deal with the case "xwalkctl -d PORT_NUMBER"
    success = enable_remote_debugging(debugging_port);
#else
    g_print("Couldn't enable remote debugging for no shared process mode!");
#endif
  } else {
    success = list_applications(storage.get());
  }

  return success ? 0 : 1;
}
<commit_msg>[Tizen] Remove Application running check during uninstallation<commit_after>// Copyright (c) 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 <stdlib.h>
#include <stdbool.h>
#include <stdio.h>

#include <glib.h>
#include <gio/gio.h>
#include <locale.h>

#include "base/at_exit.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"

#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"

#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/installer/package_installer.h"
#include "xwalk/application/tools/linux/dbus_connection.h"
#include "xwalk/runtime/common/xwalk_paths.h"
#if defined(OS_TIZEN)
#include "xwalk/application/common/id_util.h"
#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
#endif

using xwalk::application::ApplicationData;
using xwalk::application::ApplicationStorage;
using xwalk::application::PackageInstaller;

static char* install_path;
static char* uninstall_appid;

static gint debugging_port = -1;

static GOptionEntry entries[] = {
  { "install", 'i', 0, G_OPTION_ARG_STRING, &install_path,
    "Path of the application to be installed/updated", "PATH" },
  { "uninstall", 'u', 0, G_OPTION_ARG_STRING, &uninstall_appid,
    "Uninstall the application with this appid", "APPID" },
  { "debugging_port", 'd', 0, G_OPTION_ARG_INT, &debugging_port,
    "Enable remote debugging, port number 0 means to disable", NULL },
  { NULL }
};

#if defined(SHARED_PROCESS_MODE)
namespace {

const char xwalk_service_name[] = "org.crosswalkproject.Runtime1";
const char xwalk_running_manager_iface[] =
    "org.crosswalkproject.Running.Manager1";
const dbus::ObjectPath kRunningManagerDBusPath("/running1");

}  // namespace

static bool enable_remote_debugging(gint debugging_port) {
  dbus::Bus::Options options;
#if defined(OS_TIZEN_MOBILE)
  options.bus_type = dbus::Bus::CUSTOM_ADDRESS;
  options.address.assign("unix:path=/run/user/app/dbus/user_bus_socket");
#endif
  scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
  dbus::ObjectProxy* app_proxy =
      bus->GetObjectProxy(
          xwalk_service_name,
          kRunningManagerDBusPath);
  if (!app_proxy)
    return false;

  dbus::MethodCall method_call(
      xwalk_running_manager_iface, "EnableRemoteDebugging");
  dbus::MessageWriter writer(&method_call);
  writer.AppendUint32(debugging_port);

  app_proxy->CallMethodAndBlock(&method_call, 1000);

  if (debugging_port > 0) {
    g_print("Remote debugging enabled at port '%d'\n", debugging_port);
  } else {
    g_print("Remote debugging has been disabled\n");
  }
  return true;
}
#endif

bool list_applications(ApplicationStorage* storage) {
  std::vector<std::string> app_ids;
  if (!storage->GetInstalledApplicationIDs(app_ids))
    return false;

  g_print("Application ID                       Application Name\n");
  g_print("-----------------------------------------------------\n");
  for (unsigned i = 0; i < app_ids.size(); ++i) {
    scoped_refptr<ApplicationData> app_data =
        storage->GetApplicationData(app_ids.at(i));
    if (!app_data) {
      g_print("Failed to obtain app data for xwalk id: %s\n",
              app_ids.at(i).c_str());
      continue;
    }
    g_print("%s  %s\n", app_ids.at(i).c_str(), app_data->Name().c_str());
  }
  g_print("-----------------------------------------------------\n");

  return true;
}

int main(int argc, char* argv[]) {
  setlocale(LC_ALL, "");
  GError* error = NULL;
  GOptionContext* context;
  bool success = false;

#if !GLIB_CHECK_VERSION(2, 36, 0)
  // g_type_init() is deprecated on GLib since 2.36, Tizen has 2.32.
  g_type_init();
#endif

#if defined(OS_TIZEN)
  if (xwalk_tizen_check_user_app())
    exit(1);
#endif

  context = g_option_context_new("- Crosswalk Application Management");
  g_option_context_add_main_entries(context, entries, NULL);
  if (!g_option_context_parse(context, &argc, &argv, &error)) {
    g_print("option parsing failed: %s\n", error->message);
    exit(1);
  }

  base::AtExitManager at_exit;
  base::FilePath data_path;
  xwalk::RegisterPathProvider();
  PathService::Get(xwalk::DIR_DATA_PATH, &data_path);
  scoped_ptr<ApplicationStorage> storage(new ApplicationStorage(data_path));
  scoped_ptr<PackageInstaller> installer =
      PackageInstaller::Create(storage.get());

  if (install_path) {
    std::string app_id;
    const base::FilePath& path = base::FilePath(install_path);
    success = installer->Install(path, &app_id);
    if (!success && storage->Contains(app_id)) {
      g_print("trying to update %s\n", app_id.c_str());
      success = installer->Update(app_id, path);
    }
  } else if (uninstall_appid) {
    success = installer->Uninstall(uninstall_appid);
  } else if (debugging_port >= 0) {
#if defined(SHARED_PROCESS_MODE)
    // Deal with the case "xwalkctl -d PORT_NUMBER"
    success = enable_remote_debugging(debugging_port);
#else
    g_print("Couldn't enable remote debugging for no shared process mode!");
#endif
  } else {
    success = list_applications(storage.get());
  }

  return success ? 0 : 1;
}
<|endoftext|>


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

/**
 * @file tgWorldBulletPhysicsImpl.cpp
 * @brief Contains the definitions of members of class tgWorldBulletPhysicsImpl
 * @author Lee Brownston
 * $Id$
 */

// This module
#include "tgWorldBulletPhysicsImpl.h"
// This application
#include "tgWorld.h"
#include "tgCast.h"
#include "terrain/tgBulletGround.h"
#include "terrain/tgEmptyGround.h"
// The Bullet Physics library
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" // New broadphase
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "LinearMath/btDefaultMotionState.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btQuickprof.h"

// Ghost objects
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"

#define MCLP_SOLVER

#ifdef MLCP_SOLVER

#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
#include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h"
#include "BulletDynamics/MLCPSolvers/btMLCPSolver.h"

#endif //MLCP_SOLVER

/**
 * Helper class to bundle objects that have the same life cycle, so they can be
 * constructed and destructed together.
 */
class IntermediateBuildProducts
{
    public:
        IntermediateBuildProducts(double worldSize) :
            corner1 (-worldSize,-worldSize, -worldSize),
            corner2 (worldSize, worldSize, worldSize),
            dispatcher(&collisionConfiguration),
            ghostCallback(),
#ifndef   MLCP_SOLVER
	#if (1) // More acc broadphase - remeber the comma (consider doing ifndef)
				broadphase(corner1, corner2, 16384)
	#endif // Broadphase
#else
			broadphase(corner1, corner2, 16384),
			solver(&mlcp)
#endif //MLCP_SOLVER

  {
	  broadphase.getOverlappingPairCache()->setInternalGhostPairCallback(&ghostCallback);
  }
  const btVector3 corner1;
  const btVector3 corner2;
  btSoftBodyRigidBodyCollisionConfiguration collisionConfiguration;
  btCollisionDispatcher dispatcher;
  btGhostPairCallback ghostCallback;
#if (0) // Default broadphase
        btDbvtBroadphase broadphase;
#else
        // More accurate broadphase:
        btAxisSweep3 broadphase;
#endif

#ifdef MLCP_SOLVER
		//btDantzigSolver mlcp;
		btSolveProjectedGaussSeidel mlcp;
		btMLCPSolver solver;
#else
		btSequentialImpulseConstraintSolver solver;
#endif

};

tgWorldBulletPhysicsImpl::tgWorldBulletPhysicsImpl(const tgWorld::Config& config,
        tgBulletGround* ground) :
    tgWorldImpl(config, ground),
    m_pIntermediateBuildProducts(new IntermediateBuildProducts(config.worldSize)),
    m_pDynamicsWorld(createDynamicsWorld())
{

    // Gravitational acceleration is down on the Y axis
    const btVector3 gravityVector(0, -config.gravity, 0);
    m_pDynamicsWorld->setGravity(gravityVector);

	if (!tgCast::cast<tgBulletGround, tgEmptyGround>(ground) && ground != NULL)
	{
		m_pDynamicsWorld->addRigidBody(ground->getGroundRigidBody());
	}

	/*
	 * These are lines from the old BasicLearningApp.cpp that we weren't using.
	 * Prior to 11/20/14
	 * http://bulletphysics.org/mediawiki-1.5.8/index.php/BtContactSolverInfo
	 */

	 m_pDynamicsWorld->getSolverInfo().m_numIterations = 20;
    #if (0)
		// Split impulse does not appear to apply to MLCP solver
        m_pDynamicsWorld->getSolverInfo().m_splitImpulse = true;
        m_pDynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = -0.02;

    #endif

    // Postcondition
    assert(invariant());
}

tgWorldBulletPhysicsImpl::~tgWorldBulletPhysicsImpl()
{
    // Delete all the collision objects. The dynamics world must exist.
    // Delete in reverse order of creation.
    const size_t nco = m_pDynamicsWorld->getNumCollisionObjects();
    btCollisionObjectArray& oa = m_pDynamicsWorld->getCollisionObjectArray();
    for (int i = nco - 1; i >= 0; --i)
    {
        btCollisionObject * const pCollisionObject = oa[i];

        // If the collision object is a rigid body, delete its motion state
        const btRigidBody* const pRigidBody =
            btRigidBody::upcast(pCollisionObject);
        if (pRigidBody)
        {
            delete pRigidBody->getMotionState();
        }

        // Remove the collision object from the dynamics world
        m_pDynamicsWorld->removeCollisionObject(pCollisionObject);
        // Delete the collision object
        delete pCollisionObject;
    }
    // All collision objects have been removed and deleted
    assert(m_pDynamicsWorld->getNumCollisionObjects() == 0);

    // Delete all the collision shapes. This can be done at any time.
    const size_t ncs = m_collisionShapes.size();

    for (size_t i = 0; i < ncs; ++i) { delete m_collisionShapes[i]; }

    delete m_pDynamicsWorld;

    // Delete the intermediate build products, which are now orphaned
    delete m_pIntermediateBuildProducts;
}

/**
 * Create and return a new instance of a btSoftRigidDynamicsWorld.
 * @return a pointer to a new instance of a btSoftRigidDynamicsWorld
 */
btDynamicsWorld* tgWorldBulletPhysicsImpl::createDynamicsWorld() const
{
  btSoftRigidDynamicsWorld* const result =
    new btSoftRigidDynamicsWorld(&m_pIntermediateBuildProducts->dispatcher,
                 &m_pIntermediateBuildProducts->broadphase,
                 &m_pIntermediateBuildProducts->solver,
                 &m_pIntermediateBuildProducts->collisionConfiguration);
#ifdef MLCPSOLVER
		result ->getSolverInfo().m_minimumSolverBatchSize = 1;//for direct solver it is better to have a small A matrix
#endif
  return result;
}

void tgWorldBulletPhysicsImpl::step(double dt)
{
    // Precondition
    assert(dt > 0.0);

    const btScalar timeStep = dt;
    const int maxSubSteps = 1;
    const btScalar fixedTimeStep = dt;
    m_pDynamicsWorld->stepSimulation(timeStep, maxSubSteps, fixedTimeStep);

    // Postcondition
    assert(invariant());
}

void tgWorldBulletPhysicsImpl::addCollisionShape(btCollisionShape* pShape)
{
#ifndef BT_NO_PROFILE
    BT_PROFILE("addCollisionShape");
#endif //BT_NO_PROFILE

    if (pShape)
    {
        m_collisionShapes.push_back(pShape);
    }

      // Postcondition
      assert(invariant());
}

void tgWorldBulletPhysicsImpl::deleteCollisionShape(btCollisionShape* pShape)
{
#ifndef BT_NO_PROFILE
    BT_PROFILE("deleteCollisionShape");
#endif //BT_NO_PROFILE

    if (pShape)
    {
		btCompoundShape* cShape = tgCast::cast<btCollisionShape, btCompoundShape>(pShape);
		if (cShape)
		{
			std::size_t n = cShape->getNumChildShapes();
			for( std::size_t i = 0; i < n; i++)
			{
				deleteCollisionShape(cShape->getChildShape(i));
			}
		}
		m_collisionShapes.remove(pShape);
        delete pShape;
    }

      // Postcondition
      assert(invariant());
}

bool tgWorldBulletPhysicsImpl::invariant() const
{
    return (m_pDynamicsWorld != 0);
}

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

/**
 * @file tgWorldBulletPhysicsImpl.cpp
 * @brief Contains the definitions of members of class tgWorldBulletPhysicsImpl
 * @author Lee Brownston
 * $Id$
 */

// This module
#include "tgWorldBulletPhysicsImpl.h"
// This application
#include "tgWorld.h"
#include "tgCast.h"
#include "terrain/tgBulletGround.h"
#include "terrain/tgEmptyGround.h"
// The Bullet Physics library
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" // New broadphase
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "LinearMath/btDefaultMotionState.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btQuickprof.h"

// Ghost objects
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"

#define MCLP_SOLVER

#ifdef MLCP_SOLVER

#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
#include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h"
#include "BulletDynamics/MLCPSolvers/btMLCPSolver.h"

#endif //MLCP_SOLVER

/**
 * Helper class to bundle objects that have the same life cycle, so they can be
 * constructed and destructed together.
 */
class IntermediateBuildProducts
{
    public:
        IntermediateBuildProducts(double worldSize) :
            corner1 (-worldSize,-worldSize, -worldSize),
            corner2 (worldSize, worldSize, worldSize),
            dispatcher(&collisionConfiguration),
            ghostCallback(),
#ifndef   MLCP_SOLVER
	#if (1) // More acc broadphase - remeber the comma (consider doing ifndef)
				broadphase(corner1, corner2, 16384)
	#endif // Broadphase
#else
			broadphase(corner1, corner2, 16384),
			solver(&mlcp)
#endif //MLCP_SOLVER

  {
	  broadphase.getOverlappingPairCache()->setInternalGhostPairCallback(&ghostCallback);
  }
  const btVector3 corner1;
  const btVector3 corner2;
  btSoftBodyRigidBodyCollisionConfiguration collisionConfiguration;
  btCollisionDispatcher dispatcher;
  btGhostPairCallback ghostCallback;
#if (0) // Default broadphase
        btDbvtBroadphase broadphase;
#else
        // More accurate broadphase:
        btAxisSweep3 broadphase;
#endif

#ifdef MLCP_SOLVER
		//btDantzigSolver mlcp;
		btSolveProjectedGaussSeidel mlcp;
		btMLCPSolver solver;
#else
		btSequentialImpulseConstraintSolver solver;
#endif

};

tgWorldBulletPhysicsImpl::tgWorldBulletPhysicsImpl(const tgWorld::Config& config,
        tgBulletGround* ground) :
    tgWorldImpl(config, ground),
    m_pIntermediateBuildProducts(new IntermediateBuildProducts(config.worldSize)),
    m_pDynamicsWorld(createDynamicsWorld())
{

    // Gravitational acceleration is down on the Y axis
    const btVector3 gravityVector(0, -config.gravity, 0);
    m_pDynamicsWorld->setGravity(gravityVector);

	if (!tgCast::cast<tgBulletGround, tgEmptyGround>(ground) && ground != NULL)
	{
		m_pDynamicsWorld->addRigidBody(ground->getGroundRigidBody());
	}

	/*
	 * These are lines from the old BasicLearningApp.cpp that we aren't using.
	 * http://bulletphysics.org/mediawiki-1.5.8/index.php/BtContactSolverInfo
	 */
    #if (0)
		// Split impulse does not appear to apply to MLCP solver
        m_pDynamicsWorld->getSolverInfo().m_splitImpulse = true;
        m_pDynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = -0.02;

        // Default is 10 - increases runtime but decreases odds of penetration
        // Makes tetraspine sine waves more accurate and static test less accurate
        m_pDynamicsWorld->getSolverInfo().m_numIterations = 20;
    #endif

    // Postcondition
    assert(invariant());
}

tgWorldBulletPhysicsImpl::~tgWorldBulletPhysicsImpl()
{
    // Delete all the collision objects. The dynamics world must exist.
    // Delete in reverse order of creation.
    const size_t nco = m_pDynamicsWorld->getNumCollisionObjects();
    btCollisionObjectArray& oa = m_pDynamicsWorld->getCollisionObjectArray();
    for (int i = nco - 1; i >= 0; --i)
    {
        btCollisionObject * const pCollisionObject = oa[i];

        // If the collision object is a rigid body, delete its motion state
        const btRigidBody* const pRigidBody =
            btRigidBody::upcast(pCollisionObject);
        if (pRigidBody)
        {
            delete pRigidBody->getMotionState();
        }

        // Remove the collision object from the dynamics world
        m_pDynamicsWorld->removeCollisionObject(pCollisionObject);
        // Delete the collision object
        delete pCollisionObject;
    }
    // All collision objects have been removed and deleted
    assert(m_pDynamicsWorld->getNumCollisionObjects() == 0);

    // Delete all the collision shapes. This can be done at any time.
    const size_t ncs = m_collisionShapes.size();

    for (size_t i = 0; i < ncs; ++i) { delete m_collisionShapes[i]; }

    delete m_pDynamicsWorld;

    // Delete the intermediate build products, which are now orphaned
    delete m_pIntermediateBuildProducts;
}

/**
 * Create and return a new instance of a btSoftRigidDynamicsWorld.
 * @return a pointer to a new instance of a btSoftRigidDynamicsWorld
 */
btDynamicsWorld* tgWorldBulletPhysicsImpl::createDynamicsWorld() const
{
  btSoftRigidDynamicsWorld* const result =
    new btSoftRigidDynamicsWorld(&m_pIntermediateBuildProducts->dispatcher,
                 &m_pIntermediateBuildProducts->broadphase,
                 &m_pIntermediateBuildProducts->solver,
                 &m_pIntermediateBuildProducts->collisionConfiguration);
#ifdef MLCPSOLVER
		result ->getSolverInfo().m_minimumSolverBatchSize = 1;//for direct solver it is better to have a small A matrix
#endif
  return result;
}

void tgWorldBulletPhysicsImpl::step(double dt)
{
    // Precondition
    assert(dt > 0.0);

    const btScalar timeStep = dt;
    const int maxSubSteps = 1;
    const btScalar fixedTimeStep = dt;
    m_pDynamicsWorld->stepSimulation(timeStep, maxSubSteps, fixedTimeStep);

    // Postcondition
    assert(invariant());
}

void tgWorldBulletPhysicsImpl::addCollisionShape(btCollisionShape* pShape)
{
#ifndef BT_NO_PROFILE
    BT_PROFILE("addCollisionShape");
#endif //BT_NO_PROFILE

    if (pShape)
    {
        m_collisionShapes.push_back(pShape);
    }

      // Postcondition
      assert(invariant());
}

void tgWorldBulletPhysicsImpl::deleteCollisionShape(btCollisionShape* pShape)
{
#ifndef BT_NO_PROFILE
    BT_PROFILE("deleteCollisionShape");
#endif //BT_NO_PROFILE

    if (pShape)
    {
		btCompoundShape* cShape = tgCast::cast<btCollisionShape, btCompoundShape>(pShape);
		if (cShape)
		{
			std::size_t n = cShape->getNumChildShapes();
			for( std::size_t i = 0; i < n; i++)
			{
				deleteCollisionShape(cShape->getChildShape(i));
			}
		}
		m_collisionShapes.remove(pShape);
        delete pShape;
    }

      // Postcondition
      assert(invariant());
}

bool tgWorldBulletPhysicsImpl::invariant() const
{
    return (m_pDynamicsWorld != 0);
}

<|endoftext|>


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

#include "stdafx.h"

#include <atltime.h>
#include "ext/rho/rhoruby.h"
#include "../MainWindow.h"
#include "Camera.h"
#include "common/RhodesApp.h"

#ifdef _MSC_VER
// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
#pragma warning ( disable : 4800 )
#endif

extern "C" HWND getMainWnd();

//#if defined(_WIN32_WCE)

static bool copy_file(LPTSTR from, LPTSTR to);
static LPTSTR get_file_name(LPTSTR from, LPTSTR to);
static LPTSTR generate_filename(LPTSTR filename, LPCTSTR szExt );
static void create_folder(LPTSTR Path);

IMPLEMENT_LOGCLASS(Camera,"Camera");

Camera::Camera(void) {
}

Camera::~Camera(void) {
}

HRESULT Camera::takePicture(HWND hwndOwner,LPTSTR pszFilename)
{
    HRESULT         hResult = S_OK;
#if defined(_WIN32_WCE) && !defined( OS_PLATFORM_MOTCE )
    SHCAMERACAPTURE shcc;

    StringW root;
    convertToStringW(rho_rhodesapp_getblobsdirpath(), root);
    wsprintf( pszFilename, L"%s", root.c_str() );

	create_folder(pszFilename);

    //LPCTSTR szExt = wcsrchr(pszFilename, '.');
    TCHAR filename[256];
	generate_filename(filename,L".jpg");

    // Set the SHCAMERACAPTURE structure.
    ZeroMemory(&shcc, sizeof(shcc));
    shcc.cbSize             = sizeof(shcc);
    shcc.hwndOwner          = hwndOwner;
    shcc.pszInitialDir      = pszFilename;
    shcc.pszDefaultFileName = filename;
    shcc.pszTitle           = TEXT("Camera");
    shcc.VideoTypes			= CAMERACAPTURE_VIDEOTYPE_MESSAGING;
    shcc.nResolutionWidth   = 176;
    shcc.nResolutionHeight  = 144;
    shcc.nVideoTimeLimit    = 15;
    shcc.Mode               = CAMERACAPTURE_MODE_STILL;

    // Display the Camera Capture dialog.
    hResult = SHCameraCapture(&shcc);

    // The next statements will execute only after the user takes
    // a picture or video, or closes the Camera Capture dialog.
    if (S_OK == hResult) {
        LPTSTR fname = get_file_name(shcc.szFile,pszFilename);
		if (fname) {
			StringCchCopy(pszFilename, MAX_PATH, fname);
			free(fname);
		} else {
            LOG(ERROR) + "takePicture error get file: " + shcc.szFile;

			hResult = E_INVALIDARG;
		}
    }else
    {
        LOG(ERROR) + "takePicture failed with code: " + LOGFMT("0x%X") + hResult;
    }
#endif //_WIN32_WCE

    return hResult;
}

HRESULT Camera::selectPicture(HWND hwndOwner,LPTSTR pszFilename)
{
	RHO_ASSERT(pszFilename);
#if defined( _WIN32_WCE ) && !defined( OS_PLATFORM_MOTCE )
	OPENFILENAMEEX ofn = {0};
#else
    OPENFILENAME ofn = {0};
#endif

	ofn.lStructSize     = sizeof(ofn);
	ofn.lpstrFilter     = NULL;
	ofn.lpstrFile       = pszFilename;
	ofn.nMaxFile        = MAX_PATH;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle      = _T("Select an image");
#if defined( _WIN32_WCE ) && !defined( OS_PLATFORM_MOTCE )
	ofn.ExFlags         = OFN_EXFLAG_THUMBNAILVIEW|OFN_EXFLAG_NOFILECREATE|OFN_EXFLAG_LOCKDIRECTORY;
    if (GetOpenFileNameEx(&ofn))
#else
    if (GetOpenFileName(&ofn))
#endif

    {
		HRESULT hResult = S_OK;

        /*
		TCHAR rhoroot[MAX_PATH];
		wchar_t* root  = wce_mbtowc(rho_rhodesapp_getblobsdirpath());
		wsprintf(rhoroot,L"%s",root);
		free(root);

		create_folder(rhoroot);*/

        StringW strBlobRoot = convertToStringW( RHODESAPP().getBlobsDirPath() );

        LPCTSTR szExt = wcsrchr(pszFilename, '.');
		TCHAR filename[256];
		generate_filename(filename, szExt);

		int len = strBlobRoot.length() + wcslen(L"\\") + wcslen(filename);
		wchar_t* full_name = (wchar_t*) malloc((len+2)*sizeof(wchar_t));
		wsprintf(full_name,L"%s\\%s",strBlobRoot.c_str(),filename);

		if (copy_file(pszFilename,full_name))
        {
			wcscpy( pszFilename, filename );
		} else {
			hResult = E_INVALIDARG;
		}

		free(full_name);

		return hResult;
	} else if (GetLastError()==ERROR_SUCCESS) {
		return S_FALSE; //user cancel op
	}
	return E_INVALIDARG;
}

bool copy_file(LPTSTR from, LPTSTR to)
{
	RHO_ASSERT(from);
	RHO_ASSERT(to);
/*
	SHFILEOPSTRUCT SHFileOp;
	ATL::CString source(from);
	ATL::CString destination(to);

	// add required string terminators
	source+=_T("\0\0");
	destination+=_T("\0\0");

	// set up File Operation structure
	ZeroMemory(&SHFileOp, sizeof(SHFILEOPSTRUCT));
	SHFileOp.hwnd = NULL;
	SHFileOp.wFunc = FO_COPY;
	SHFileOp.pFrom = source;
	SHFileOp.pTo = destination;
	SHFileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
*/
	//if(SHFileOperation(&SHFileOp) != 0) {
    if ( !CopyFile(from, to, TRUE) )
    {
        DWORD dwErr = GetLastError();
		return false;
	}
	return true;
}

LPTSTR get_file_name(LPTSTR from, LPTSTR to) {
	int len = wcslen(to);
	if (wcsncmp(to,from,len)==0) {
		LPTSTR fname = from+len;
		if ( (wcsncmp(L"\\",fname,1)==0) ||
			 (wcsncmp(L"/",fname,1)==0) ) {
			fname++;
		}
		len = wcslen(fname);
		wchar_t* name = (wchar_t*) malloc(len*sizeof(wchar_t)+1);
		wcscpy(name,fname);
		return name;
	} else {
		return NULL;
	}
}

LPTSTR generate_filename(LPTSTR filename, LPCTSTR szExt) {
	RHO_ASSERT(filename);

	CTime time(CTime::GetCurrentTime());
	tm tl, tg;
	time.GetLocalTm(&tl);
	time.GetGmtTm(&tg);
	int tz = tl.tm_hour-tg.tm_hour; //TBD: fix tz

    wsprintf(filename, L"Image_%02i-%02i-%0004i_%02i.%02i.%02i_%c%03i%s",
		tg.tm_mon, tg.tm_mday, 1900+tg.tm_year, tg.tm_hour, tg.tm_min, tg.tm_sec,
        tz>0?'_':'-',abs(tz),(szExt?szExt:L""));

	return filename;
}

void create_folder(LPTSTR Path)
{
	TCHAR DirName[256];
	LPTSTR p = Path;
	LPTSTR q = DirName;
	while(*p)
	{
		if (('\\' == *p) || ('/' == *p))
		{
			if (':' != *(p-1))
			{
				CreateDirectory(DirName, NULL);
			}
		}
		*q++ = *p++;
		*q = '\0';
	}
	CreateDirectory(DirName, NULL);
}

//#endif //_WIN32_WCE

void choose_picture(char* callback_url) {
//#if defined(_WIN32_WCE)
	HWND main_wnd = getMainWnd();
	::PostMessage(main_wnd,WM_SELECTPICTURE,0,(LPARAM)strdup(callback_url));
//#endif
}

void take_picture(char* callback_url, rho_param * options_hash) {
	HWND main_wnd = getMainWnd();
	::PostMessage(main_wnd,WM_TAKEPICTURE,0,(LPARAM)strdup(callback_url));
}

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

#include "stdafx.h"

#include <atltime.h>
#include "ext/rho/rhoruby.h"
#include "../MainWindow.h"
#include "Camera.h"
#include "common/RhodesApp.h"

#ifdef _MSC_VER
// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
#pragma warning ( disable : 4800 )
#endif

extern "C" HWND getMainWnd();

//#if defined(_WIN32_WCE)

static bool copy_file(LPTSTR from, LPTSTR to);
static LPTSTR get_file_name(LPTSTR from, LPTSTR to);
static LPTSTR generate_filename(LPTSTR filename, LPCTSTR szExt );
static void create_folder(LPTSTR Path);

IMPLEMENT_LOGCLASS(Camera,"Camera");

Camera::Camera(void) {
}

Camera::~Camera(void) {
}

HRESULT Camera::takePicture(HWND hwndOwner,LPTSTR pszFilename)
{
    HRESULT         hResult = S_OK;
#if defined(_WIN32_WCE) && !defined( OS_PLATFORM_MOTCE )
    SHCAMERACAPTURE shcc;

    StringW root;
    convertToStringW(rho_rhodesapp_getblobsdirpath(), root);
    wsprintf( pszFilename, L"%s", root.c_str() );

	create_folder(pszFilename);

    //LPCTSTR szExt = wcsrchr(pszFilename, '.');
    TCHAR filename[256];
	generate_filename(filename,L".jpg");

    // Set the SHCAMERACAPTURE structure.
    ZeroMemory(&shcc, sizeof(shcc));
    shcc.cbSize             = sizeof(shcc);
    shcc.hwndOwner          = hwndOwner;
    shcc.pszInitialDir      = pszFilename;
    shcc.pszDefaultFileName = filename;
    shcc.pszTitle           = TEXT("Camera");
    shcc.VideoTypes			= CAMERACAPTURE_VIDEOTYPE_MESSAGING;
    shcc.nResolutionWidth   = 176;
    shcc.nResolutionHeight  = 144;
    shcc.nVideoTimeLimit    = 15;
    shcc.Mode               = CAMERACAPTURE_MODE_STILL;

    // Display the Camera Capture dialog.
    hResult = SHCameraCapture(&shcc);

    // The next statements will execute only after the user takes
    // a picture or video, or closes the Camera Capture dialog.
    if (S_OK == hResult) {
        LPTSTR fname = get_file_name(shcc.szFile,pszFilename);
		if (fname) {
			StringCchCopy(pszFilename, MAX_PATH, fname);
			free(fname);
		} else {
            LOG(ERROR) + "takePicture error get file: " + shcc.szFile;

			hResult = E_INVALIDARG;
		}
    }else
    {
        LOG(ERROR) + "takePicture failed with code: " + LOGFMT("0x%X") + hResult;
    }
#endif //_WIN32_WCE

    return hResult;
}

HRESULT Camera::selectPicture(HWND hwndOwner,LPTSTR pszFilename)
{
	RHO_ASSERT(pszFilename);
#if defined( _WIN32_WCE ) && !defined( OS_PLATFORM_MOTCE )
	OPENFILENAMEEX ofn = {0};
#else
    OPENFILENAME ofn = {0};
#endif
    pszFilename[0] = 0;

	ofn.lStructSize     = sizeof(ofn);
	ofn.lpstrFilter     = NULL;
	ofn.lpstrFile       = pszFilename;
	ofn.nMaxFile        = MAX_PATH;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle      = _T("Select an image");
#if defined( _WIN32_WCE ) && !defined( OS_PLATFORM_MOTCE )
	ofn.ExFlags         = OFN_EXFLAG_THUMBNAILVIEW|OFN_EXFLAG_NOFILECREATE|OFN_EXFLAG_LOCKDIRECTORY;
    if (GetOpenFileNameEx(&ofn))
#else
    if (GetOpenFileName(&ofn))
#endif

    {
		HRESULT hResult = S_OK;

        /*
		TCHAR rhoroot[MAX_PATH];
		wchar_t* root  = wce_mbtowc(rho_rhodesapp_getblobsdirpath());
		wsprintf(rhoroot,L"%s",root);
		free(root);

		create_folder(rhoroot);*/

        StringW strBlobRoot = convertToStringW( RHODESAPP().getBlobsDirPath() );

        LPCTSTR szExt = wcsrchr(pszFilename, '.');
		TCHAR filename[256];
		generate_filename(filename, szExt);

		int len = strBlobRoot.length() + wcslen(L"\\") + wcslen(filename);
		wchar_t* full_name = (wchar_t*) malloc((len+2)*sizeof(wchar_t));
		wsprintf(full_name,L"%s\\%s",strBlobRoot.c_str(),filename);

		if (copy_file(pszFilename,full_name))
        {
			wcscpy( pszFilename, filename );
		} else {
			hResult = E_INVALIDARG;
		}

		free(full_name);

		return hResult;
	} else if (GetLastError()==ERROR_SUCCESS) {
		return S_FALSE; //user cancel op
	}
	return E_INVALIDARG;
}

bool copy_file(LPTSTR from, LPTSTR to)
{
	RHO_ASSERT(from);
	RHO_ASSERT(to);
/*
	SHFILEOPSTRUCT SHFileOp;
	ATL::CString source(from);
	ATL::CString destination(to);

	// add required string terminators
	source+=_T("\0\0");
	destination+=_T("\0\0");

	// set up File Operation structure
	ZeroMemory(&SHFileOp, sizeof(SHFILEOPSTRUCT));
	SHFileOp.hwnd = NULL;
	SHFileOp.wFunc = FO_COPY;
	SHFileOp.pFrom = source;
	SHFileOp.pTo = destination;
	SHFileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
*/
	//if(SHFileOperation(&SHFileOp) != 0) {
    if ( !CopyFile(from, to, TRUE) )
    {
        DWORD dwErr = GetLastError();
		return false;
	}
	return true;
}

LPTSTR get_file_name(LPTSTR from, LPTSTR to) {
	int len = wcslen(to);
	if (wcsncmp(to,from,len)==0) {
		LPTSTR fname = from+len;
		if ( (wcsncmp(L"\\",fname,1)==0) ||
			 (wcsncmp(L"/",fname,1)==0) ) {
			fname++;
		}
		len = wcslen(fname);
		wchar_t* name = (wchar_t*) malloc(len*sizeof(wchar_t)+1);
		wcscpy(name,fname);
		return name;
	} else {
		return NULL;
	}
}

LPTSTR generate_filename(LPTSTR filename, LPCTSTR szExt) {
	RHO_ASSERT(filename);

	CTime time(CTime::GetCurrentTime());
	tm tl, tg;
	time.GetLocalTm(&tl);
	time.GetGmtTm(&tg);
	int tz = tl.tm_hour-tg.tm_hour; //TBD: fix tz

    wsprintf(filename, L"Image_%02i-%02i-%0004i_%02i.%02i.%02i_%c%03i%s",
		tg.tm_mon, tg.tm_mday, 1900+tg.tm_year, tg.tm_hour, tg.tm_min, tg.tm_sec,
        tz>0?'_':'-',abs(tz),(szExt?szExt:L""));

	return filename;
}

void create_folder(LPTSTR Path)
{
	TCHAR DirName[256];
	LPTSTR p = Path;
	LPTSTR q = DirName;
	while(*p)
	{
		if (('\\' == *p) || ('/' == *p))
		{
			if (':' != *(p-1))
			{
				CreateDirectory(DirName, NULL);
			}
		}
		*q++ = *p++;
		*q = '\0';
	}
	CreateDirectory(DirName, NULL);
}

//#endif //_WIN32_WCE

void choose_picture(char* callback_url) {
//#if defined(_WIN32_WCE)
	HWND main_wnd = getMainWnd();
	::PostMessage(main_wnd,WM_SELECTPICTURE,0,(LPARAM)strdup(callback_url));
//#endif
}

void take_picture(char* callback_url, rho_param * options_hash) {
	HWND main_wnd = getMainWnd();
	::PostMessage(main_wnd,WM_TAKEPICTURE,0,(LPARAM)strdup(callback_url));
}

VALUE get_camera_info(const char* camera_type) {
     return rho_ruby_get_NIL();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: x_parse.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 17:03:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include <x_parse.hxx>

// NOT FULLY DECLARED SERVICES

X_Parser::X_Parser( E_Event             i_eEvent,
                    const char *        i_sObject,
                    const String &      i_sCausingFile_FullPath,
                    uintt               i_nCausingLineNr  )
    :   eEvent(i_eEvent),
        sObject(i_sObject),
        sCausingFile_FullPath(i_sCausingFile_FullPath),
        nCausingLineNr(i_nCausingLineNr)
{
}

X_Parser::~X_Parser()
{
}

X_Parser::E_Event
X_Parser::GetEvent() const
{
     return eEvent;
}

void
X_Parser::GetInfo( std::ostream & o_rOutputMedium ) const
{
    o_rOutputMedium << "Error in file "
                    << sCausingFile_FullPath
                    << " in line "
                    << nCausingLineNr
                    << ": ";

    switch (eEvent)
    {
        case x_InvalidChar:
            o_rOutputMedium << "Unknown character '"
                            << sObject
                            << "'";
            break;
        case x_UnexpectedToken:
            o_rOutputMedium << "Unexpected token \""
                            << sObject
                            << "\"";
            break;
        case x_UnexpectedEOF:
            o_rOutputMedium << "Unexpected end of file.";
            break;
        case x_UnspecifiedSyntaxError:
            o_rOutputMedium << "Unspecified syntax problem in file.";
            break;
        case x_Any:
        default:
            o_rOutputMedium << "Unspecified parsing exception.";
    }   // end switch
    o_rOutputMedium << Endl();
}

std::ostream &
operator<<( std::ostream &                  o_rOut,
            const autodoc::X_Parser_Ifc &   i_rException )
{
    i_rException.GetInfo(o_rOut);
     return o_rOut;
}
<commit_msg>INTEGRATION: CWS changefileheader (1.6.22); FILE MERGED 2008/03/28 16:02:38 rt 1.6.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: x_parse.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <precomp.h>
#include <x_parse.hxx>

// NOT FULLY DECLARED SERVICES

X_Parser::X_Parser( E_Event             i_eEvent,
                    const char *        i_sObject,
                    const String &      i_sCausingFile_FullPath,
                    uintt               i_nCausingLineNr  )
    :   eEvent(i_eEvent),
        sObject(i_sObject),
        sCausingFile_FullPath(i_sCausingFile_FullPath),
        nCausingLineNr(i_nCausingLineNr)
{
}

X_Parser::~X_Parser()
{
}

X_Parser::E_Event
X_Parser::GetEvent() const
{
     return eEvent;
}

void
X_Parser::GetInfo( std::ostream & o_rOutputMedium ) const
{
    o_rOutputMedium << "Error in file "
                    << sCausingFile_FullPath
                    << " in line "
                    << nCausingLineNr
                    << ": ";

    switch (eEvent)
    {
        case x_InvalidChar:
            o_rOutputMedium << "Unknown character '"
                            << sObject
                            << "'";
            break;
        case x_UnexpectedToken:
            o_rOutputMedium << "Unexpected token \""
                            << sObject
                            << "\"";
            break;
        case x_UnexpectedEOF:
            o_rOutputMedium << "Unexpected end of file.";
            break;
        case x_UnspecifiedSyntaxError:
            o_rOutputMedium << "Unspecified syntax problem in file.";
            break;
        case x_Any:
        default:
            o_rOutputMedium << "Unspecified parsing exception.";
    }   // end switch
    o_rOutputMedium << Endl();
}

std::ostream &
operator<<( std::ostream &                  o_rOut,
            const autodoc::X_Parser_Ifc &   i_rException )
{
    i_rException.GetInfo(o_rOut);
     return o_rOut;
}
<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * DMPAddressTest.cpp
 * Test fixture for the DMPAddress class
 * Copyright (C) 2005-2009 Simon Newton
 */

#include <arpa/inet.h>
#include <string.h>
#include <cppunit/extensions/HelperMacros.h>

#include "PDUTestCommon.h"
#include "DMPAddress.h"

namespace ola {
namespace e131 {

class DMPAddressTest: public CppUnit::TestFixture {
  CPPUNIT_TEST_SUITE(DMPAddressTest);
  CPPUNIT_TEST(testAddress);
  CPPUNIT_TEST(testRangeAddress);
  CPPUNIT_TEST(testAddressData);
  CPPUNIT_TEST_SUITE_END();

  public:
    void testAddress();
    void testRangeAddress();
    void testAddressData();
  private:
    void DMPAddressTest::checkAddress(
        const BaseDMPAddress *address,
        unsigned int start,
        unsigned int increment,
        unsigned int number,
        unsigned int size,
        dmp_address_size address_size,
        bool is_range);
};

CPPUNIT_TEST_SUITE_REGISTRATION(DMPAddressTest);

/*
 * Check the property match, pack the address, decode it, and check the decoded
 * address matches the first one.
 */
void DMPAddressTest::checkAddress(
    const BaseDMPAddress *address,
    unsigned int start,
    unsigned int increment,
    unsigned int number,
    unsigned int size,
    dmp_address_size address_size,
    bool is_range) {

  CPPUNIT_ASSERT_EQUAL(size, address->Size());
  CPPUNIT_ASSERT_EQUAL(address_size, address->AddressSize());
  CPPUNIT_ASSERT_EQUAL(is_range, address->IsRange());
  CPPUNIT_ASSERT_EQUAL(start, address->Start());
  CPPUNIT_ASSERT_EQUAL(increment, address->Increment());
  CPPUNIT_ASSERT_EQUAL(number, address->Number());

  unsigned int length = address->Size();
  uint8_t *buffer = new uint8_t[length];
  CPPUNIT_ASSERT(address->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(size, length);

  const BaseDMPAddress *addr = DecodeAddress(
      address_size,
      is_range ? RANGE_SINGLE: NON_RANGE,
      buffer, length);
  CPPUNIT_ASSERT_EQUAL(size, length);
  CPPUNIT_ASSERT_EQUAL(start, address->Start());
  CPPUNIT_ASSERT_EQUAL(increment, address->Increment());
  CPPUNIT_ASSERT_EQUAL(number, address->Number());

  delete[] buffer;
  delete addr;
}

/*
 * Test that addresses work.
 */
void DMPAddressTest::testAddress() {
  uint32_t temp = 0;
  unsigned int length = sizeof(temp);

  OneByteDMPAddress addr1(10);
  checkAddress(&addr1, 10, 0, 1, 1, ONE_BYTES, false);
  TwoByteDMPAddress addr2(1024);
  checkAddress(&addr2, 1024, 0, 1, 2, TWO_BYTES, false);
  FourByteDMPAddress addr3(66000);
  checkAddress(&addr3, 66000, 0, 1, 4, FOUR_BYTES, false);

  const BaseDMPAddress *addr4 = NewSingleAddress(10);
  checkAddress(addr4, 10, 0, 1, 1, ONE_BYTES, false);
  delete addr4;

  const BaseDMPAddress *addr5 = NewSingleAddress(1024);
  checkAddress(addr5, 1024, 0, 1, 2, TWO_BYTES, false);
  delete addr5;

  const BaseDMPAddress *addr6 = NewSingleAddress(66000);
  checkAddress(addr6, 66000, 0, 1, 4, FOUR_BYTES, false);
  delete addr6;
}

/*
 * Test that Ranged Addresses work
 */
void DMPAddressTest::testRangeAddress() {
  uint8_t buffer[12];
  uint16_t *p = (uint16_t*) buffer;
  uint32_t *pp = (uint32_t*) buffer;
  unsigned int length = sizeof(buffer);

  OneByteRangeDMPAddress addr1(10, 2, 4);
  checkAddress(&addr1, 10, 2, 4, 3, ONE_BYTES, true);
  CPPUNIT_ASSERT(addr1.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr1.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[0]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 2, buffer[1]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 4, buffer[2]);

  length = sizeof(buffer);
  TwoByteRangeDMPAddress addr2(1024, 2, 99);
  checkAddress(&addr2, 1024, 2, 99, 6, TWO_BYTES, true);
  CPPUNIT_ASSERT(addr2.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr2.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1024, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 2, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 99, ntohs(*p));

  length = sizeof(buffer);
  FourByteRangeDMPAddress addr3(66000, 2, 100);
  checkAddress(&addr3, 66000, 2, 100, 12, FOUR_BYTES, true);
  CPPUNIT_ASSERT(addr3.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr3.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint32_t) 66000, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 2, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 100, ntohl(*pp));

  const BaseDMPAddress *addr4 = NewRangeAddress(10, 1, 10);
  length = sizeof(buffer);
  checkAddress(addr4, 10, 1, 10, 3, ONE_BYTES, true);
  CPPUNIT_ASSERT(addr4->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr4->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[0]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 1, buffer[1]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[2]);

  p = (uint16_t*) buffer;
  const BaseDMPAddress *addr5 = NewRangeAddress(10, 1, 1024);
  length = sizeof(buffer);
  checkAddress(addr5, 10, 1, 1024, 6, TWO_BYTES, true);
  CPPUNIT_ASSERT(addr5->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr5->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint16_t) 10, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1024, ntohs(*p));

  pp = (uint32_t*) buffer;
  const BaseDMPAddress *addr6 = NewRangeAddress(66000, 1, 1024);
  length = sizeof(buffer);
  checkAddress(addr6, 66000, 1, 1024, 12, FOUR_BYTES, true);
  CPPUNIT_ASSERT(addr6->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr6->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint32_t) 66000, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 1, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 1024, ntohl(*pp));
}

/*
 * test that AddressData objects work
 */
void DMPAddressTest::testAddressData() {
  uint8_t buffer[12];
  unsigned int length = sizeof(buffer);
  OneByteDMPAddress addr1(10);
  DMPAddressData<OneByteDMPAddress> chunk(&addr1, NULL, 0);

  CPPUNIT_ASSERT_EQUAL((const OneByteDMPAddress*) &addr1, chunk.Address());
  CPPUNIT_ASSERT_EQUAL((const uint8_t*) NULL, chunk.Data());
  CPPUNIT_ASSERT_EQUAL((unsigned int) 1, chunk.Size());
  CPPUNIT_ASSERT(!chunk.Pack(buffer, length));

  length = sizeof(buffer);
  TwoByteRangeDMPAddress addr2(10, 2, 10);
  DMPAddressData<TwoByteRangeDMPAddress> chunk2(&addr2, NULL, 0);

  CPPUNIT_ASSERT_EQUAL((const TwoByteRangeDMPAddress*) &addr2,
                       chunk2.Address());
  CPPUNIT_ASSERT_EQUAL((const uint8_t*) NULL, chunk2.Data());
  CPPUNIT_ASSERT_EQUAL((unsigned int) 6, chunk2.Size());
  CPPUNIT_ASSERT(!chunk2.Pack(buffer, length));
}

} // e131
} // ola
<commit_msg> * make the tests pass on linux<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * DMPAddressTest.cpp
 * Test fixture for the DMPAddress class
 * Copyright (C) 2005-2009 Simon Newton
 */

#include <arpa/inet.h>
#include <string.h>
#include <cppunit/extensions/HelperMacros.h>

#include "PDUTestCommon.h"
#include "DMPAddress.h"

namespace ola {
namespace e131 {

class DMPAddressTest: public CppUnit::TestFixture {
  CPPUNIT_TEST_SUITE(DMPAddressTest);
  CPPUNIT_TEST(testAddress);
  CPPUNIT_TEST(testRangeAddress);
  CPPUNIT_TEST(testAddressData);
  CPPUNIT_TEST_SUITE_END();

  public:
    void testAddress();
    void testRangeAddress();
    void testAddressData();
  private:
    void checkAddress(
        const BaseDMPAddress *address,
        unsigned int start,
        unsigned int increment,
        unsigned int number,
        unsigned int size,
        dmp_address_size address_size,
        bool is_range);
};

CPPUNIT_TEST_SUITE_REGISTRATION(DMPAddressTest);

/*
 * Check the property match, pack the address, decode it, and check the decoded
 * address matches the first one.
 */
void DMPAddressTest::checkAddress(
    const BaseDMPAddress *address,
    unsigned int start,
    unsigned int increment,
    unsigned int number,
    unsigned int size,
    dmp_address_size address_size,
    bool is_range) {

  CPPUNIT_ASSERT_EQUAL(size, address->Size());
  CPPUNIT_ASSERT_EQUAL(address_size, address->AddressSize());
  CPPUNIT_ASSERT_EQUAL(is_range, address->IsRange());
  CPPUNIT_ASSERT_EQUAL(start, address->Start());
  CPPUNIT_ASSERT_EQUAL(increment, address->Increment());
  CPPUNIT_ASSERT_EQUAL(number, address->Number());

  unsigned int length = address->Size();
  uint8_t *buffer = new uint8_t[length];
  CPPUNIT_ASSERT(address->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(size, length);

  const BaseDMPAddress *addr = DecodeAddress(
      address_size,
      is_range ? RANGE_SINGLE: NON_RANGE,
      buffer, length);
  CPPUNIT_ASSERT_EQUAL(size, length);
  CPPUNIT_ASSERT_EQUAL(start, address->Start());
  CPPUNIT_ASSERT_EQUAL(increment, address->Increment());
  CPPUNIT_ASSERT_EQUAL(number, address->Number());

  delete[] buffer;
  delete addr;
}

/*
 * Test that addresses work.
 */
void DMPAddressTest::testAddress() {
  uint32_t temp = 0;
  unsigned int length = sizeof(temp);

  OneByteDMPAddress addr1(10);
  checkAddress(&addr1, 10, 0, 1, 1, ONE_BYTES, false);
  TwoByteDMPAddress addr2(1024);
  checkAddress(&addr2, 1024, 0, 1, 2, TWO_BYTES, false);
  FourByteDMPAddress addr3(66000);
  checkAddress(&addr3, 66000, 0, 1, 4, FOUR_BYTES, false);

  const BaseDMPAddress *addr4 = NewSingleAddress(10);
  checkAddress(addr4, 10, 0, 1, 1, ONE_BYTES, false);
  delete addr4;

  const BaseDMPAddress *addr5 = NewSingleAddress(1024);
  checkAddress(addr5, 1024, 0, 1, 2, TWO_BYTES, false);
  delete addr5;

  const BaseDMPAddress *addr6 = NewSingleAddress(66000);
  checkAddress(addr6, 66000, 0, 1, 4, FOUR_BYTES, false);
  delete addr6;
}

/*
 * Test that Ranged Addresses work
 */
void DMPAddressTest::testRangeAddress() {
  uint8_t buffer[12];
  uint16_t *p = (uint16_t*) buffer;
  uint32_t *pp = (uint32_t*) buffer;
  unsigned int length = sizeof(buffer);

  OneByteRangeDMPAddress addr1(10, 2, 4);
  checkAddress(&addr1, 10, 2, 4, 3, ONE_BYTES, true);
  CPPUNIT_ASSERT(addr1.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr1.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[0]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 2, buffer[1]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 4, buffer[2]);

  length = sizeof(buffer);
  TwoByteRangeDMPAddress addr2(1024, 2, 99);
  checkAddress(&addr2, 1024, 2, 99, 6, TWO_BYTES, true);
  CPPUNIT_ASSERT(addr2.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr2.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1024, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 2, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 99, ntohs(*p));

  length = sizeof(buffer);
  FourByteRangeDMPAddress addr3(66000, 2, 100);
  checkAddress(&addr3, 66000, 2, 100, 12, FOUR_BYTES, true);
  CPPUNIT_ASSERT(addr3.Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr3.Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint32_t) 66000, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 2, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 100, ntohl(*pp));

  const BaseDMPAddress *addr4 = NewRangeAddress(10, 1, 10);
  length = sizeof(buffer);
  checkAddress(addr4, 10, 1, 10, 3, ONE_BYTES, true);
  CPPUNIT_ASSERT(addr4->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr4->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[0]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 1, buffer[1]);
  CPPUNIT_ASSERT_EQUAL((uint8_t) 10, buffer[2]);

  p = (uint16_t*) buffer;
  const BaseDMPAddress *addr5 = NewRangeAddress(10, 1, 1024);
  length = sizeof(buffer);
  checkAddress(addr5, 10, 1, 1024, 6, TWO_BYTES, true);
  CPPUNIT_ASSERT(addr5->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr5->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint16_t) 10, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1, ntohs(*p++));
  CPPUNIT_ASSERT_EQUAL((uint16_t) 1024, ntohs(*p));

  pp = (uint32_t*) buffer;
  const BaseDMPAddress *addr6 = NewRangeAddress(66000, 1, 1024);
  length = sizeof(buffer);
  checkAddress(addr6, 66000, 1, 1024, 12, FOUR_BYTES, true);
  CPPUNIT_ASSERT(addr6->Pack(buffer, length));
  CPPUNIT_ASSERT_EQUAL(addr6->Size(), length);
  CPPUNIT_ASSERT_EQUAL((uint32_t) 66000, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 1, ntohl(*pp++));
  CPPUNIT_ASSERT_EQUAL((uint32_t) 1024, ntohl(*pp));
}

/*
 * test that AddressData objects work
 */
void DMPAddressTest::testAddressData() {
  uint8_t buffer[12];
  unsigned int length = sizeof(buffer);
  OneByteDMPAddress addr1(10);
  DMPAddressData<OneByteDMPAddress> chunk(&addr1, NULL, 0);

  CPPUNIT_ASSERT_EQUAL((const OneByteDMPAddress*) &addr1, chunk.Address());
  CPPUNIT_ASSERT_EQUAL((const uint8_t*) NULL, chunk.Data());
  CPPUNIT_ASSERT_EQUAL((unsigned int) 1, chunk.Size());
  CPPUNIT_ASSERT(!chunk.Pack(buffer, length));

  length = sizeof(buffer);
  TwoByteRangeDMPAddress addr2(10, 2, 10);
  DMPAddressData<TwoByteRangeDMPAddress> chunk2(&addr2, NULL, 0);

  CPPUNIT_ASSERT_EQUAL((const TwoByteRangeDMPAddress*) &addr2,
                       chunk2.Address());
  CPPUNIT_ASSERT_EQUAL((const uint8_t*) NULL, chunk2.Data());
  CPPUNIT_ASSERT_EQUAL((unsigned int) 6, chunk2.Size());
  CPPUNIT_ASSERT(!chunk2.Pack(buffer, length));
}

} // e131
} // ola
<|endoftext|>