<commit_before>/**
   @file abstractsensor_i.cpp
   @brief Base class for sensor interface

   Copyright (C) 2009-2010 Nokia Corporation

   @author Joep van Gassel <joep.van.gassel@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord 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.

   Sensord 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 Sensord.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "sensormanagerinterface.h"
#include "abstractsensor_i.h"

struct AbstractSensorChannelInterface::AbstractSensorChannelInterfaceImpl
{
    AbstractSensorChannelInterfaceImpl(QObject* parent, int sessionId);

    SensorError errorCode_;
    QString errorString_;
    int sessionId_;
    int interval_;
    unsigned int bufferInterval_;
    unsigned int bufferSize_;
    SocketReader socketReader_;
    bool running_;
    bool standbyOverride_;
};

AbstractSensorChannelInterface::AbstractSensorChannelInterfaceImpl::AbstractSensorChannelInterfaceImpl(QObject* parent, int sessionId) :
    sessionId_(sessionId),
    interval_(0),
    bufferInterval_(0),
    bufferSize_(1),
    socketReader_(parent),
    running_(false),
    standbyOverride_(false)
{
}

AbstractSensorChannelInterface::AbstractSensorChannelInterface(const QString& path, const char* interfaceName, int sessionId) :
    QDBusAbstractInterface(SERVICE_NAME, path, interfaceName, QDBusConnection::systemBus(), 0),
    pimpl_(new AbstractSensorChannelInterfaceImpl(this, sessionId))
{
    if (!pimpl_->socketReader_.initiateConnection(sessionId)) {
        setError(SClientSocketError, "Socket connection failed.");
        // TODO: Invalidate!
    }

    qDBusRegisterMetaType<DataRange>();

    Q_ASSERT ( isValid() );
}

AbstractSensorChannelInterface::~AbstractSensorChannelInterface()
{
    if ( isValid() )
        release();
    if (!pimpl_->socketReader_.dropConnection())
        setError(SClientSocketError, "Socket disconnect failed.");
    delete pimpl_;
}

SocketReader& AbstractSensorChannelInterface::getSocketReader() const
{
    return pimpl_->socketReader_;
}

bool AbstractSensorChannelInterface::release()
{
    // ToDo: note that after release this interace becomes invalid (this should be handled correctly)
    return SensorManagerInterface::instance().releaseInterface(id(), pimpl_->sessionId_);
}

void AbstractSensorChannelInterface::setError(SensorError errorCode, const QString& errorString)
{
    pimpl_->errorCode_   = errorCode;
    pimpl_->errorString_ = errorString;

    //emit errorSignal(errorCode);
}

QDBusReply<void> AbstractSensorChannelInterface::start()
{
    return start(pimpl_->sessionId_);
}

QDBusReply<void> AbstractSensorChannelInterface::stop()
{
    return stop(pimpl_->sessionId_);
}

QDBusReply<void> AbstractSensorChannelInterface::start(int sessionId)
{
    clearError();

    if (pimpl_->running_) {
        return QDBusReply<void>();
    }
    pimpl_->running_ = true;

    connect(pimpl_->socketReader_.socket(), SIGNAL(readyRead()), this, SLOT(dataReceived()));

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId);
    QDBusReply<void> returnValue = callWithArgumentList(QDBus::Block, QLatin1String("start"), argumentList);

    if (pimpl_->standbyOverride_)
    {
        setStandbyOverride(sessionId, true);
    }
    /// Send interval request when started.
    setInterval(sessionId, pimpl_->interval_);

    return returnValue;
}

QDBusReply<void> AbstractSensorChannelInterface::stop(int sessionId)
{
    clearError();

    if (!pimpl_->running_) {
        return QDBusReply<void>();
    }
    pimpl_->running_ = false ;

    disconnect(pimpl_->socketReader_.socket(), SIGNAL(readyRead()), this, SLOT(dataReceived()));
    setStandbyOverride(sessionId, false);
    /// Drop interval requests when stopped
    setInterval(sessionId, 0);

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId);
    return callWithArgumentList(QDBus::Block, QLatin1String("stop"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setInterval(int sessionId, int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setInterval"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setBufferInterval(int sessionId, unsigned int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setBufferInterval"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setBufferSize(int sessionId, unsigned int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setBufferSize"), argumentList);
}

QDBusReply<bool> AbstractSensorChannelInterface::setStandbyOverride(int sessionId, bool value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setStandbyOverride"), argumentList);
}

DataRangeList AbstractSensorChannelInterface::getAvailableDataRanges()
{
    QDBusReply<DataRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableDataRanges"));
    return ret.value();
}

DataRange AbstractSensorChannelInterface::getCurrentDataRange()
{
    clearError();
    QDBusReply<DataRange> retVal = call(QDBus::Block, QLatin1String("getCurrentDataRange"));
    return retVal.value();
}

void AbstractSensorChannelInterface::requestDataRange(DataRange range)
{
    clearError();
    call(QDBus::Block, QLatin1String("requestDataRange"), qVariantFromValue(pimpl_->sessionId_), qVariantFromValue(range));
}

void AbstractSensorChannelInterface::removeDataRangeRequest()
{
    clearError();
    call(QDBus::Block, QLatin1String("removeDataRangeRequest"), qVariantFromValue(pimpl_->sessionId_));
}

DataRangeList AbstractSensorChannelInterface::getAvailableIntervals()
{
    QDBusReply<DataRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableIntervals"));
    return ret.value();
}

IntegerRangeList AbstractSensorChannelInterface::getAvailableBufferIntervals()
{
    QDBusReply<IntegerRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableBufferIntervals"));
    return ret.value();
}

IntegerRangeList AbstractSensorChannelInterface::getAvailableBufferSizes()
{
    QDBusReply<IntegerRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableBufferSizes"));
    return ret.value();
}

int AbstractSensorChannelInterface::sessionId() const
{
    return pimpl_->sessionId_;
}

SensorError AbstractSensorChannelInterface::errorCode() const
{
    // TODO: This solution may introduce problems, if errors are
    //       not cleared before another happens.
    if (pimpl_->errorCode_ != SNoError) {
        return pimpl_->errorCode_;
    }
    return static_cast<SensorError>(errorCodeInt());
}

QString AbstractSensorChannelInterface::errorString() const
{
    if (pimpl_->errorCode_ != SNoError) {
        return pimpl_->errorString_;
    }
    return qvariant_cast<QString>(internalPropGet("errorString"));
}

QString AbstractSensorChannelInterface::description() const
{
    return qvariant_cast<QString>(internalPropGet("description"));
}

QString AbstractSensorChannelInterface::id() const
{
    return qvariant_cast<QString>(internalPropGet("id"));
}

int AbstractSensorChannelInterface::interval() const
{
    return qvariant_cast<int>(internalPropGet("interval"));
}

void AbstractSensorChannelInterface::setInterval(int value)
{
    pimpl_->interval_ = value;
    if (pimpl_->running_)
        setInterval(pimpl_->sessionId_, value);
}

unsigned int AbstractSensorChannelInterface::bufferInterval() const
{
    return qvariant_cast<unsigned int>(internalPropGet("bufferInterval"));
}

void AbstractSensorChannelInterface::setBufferInterval(unsigned int value)
{
    pimpl_->bufferInterval_ = value;
    if (!pimpl_->running_)
        setBufferInterval(pimpl_->sessionId_, value);
}

unsigned int AbstractSensorChannelInterface::bufferSize() const
{
    return qvariant_cast<unsigned int>(internalPropGet("bufferSize"));
}

void AbstractSensorChannelInterface::setBufferSize(unsigned int value)
{
    pimpl_->bufferSize_ = value;
    if (!pimpl_->running_)
        setBufferSize(pimpl_->sessionId_, value);
}

bool AbstractSensorChannelInterface::standbyOverride() const
{
    return pimpl_->standbyOverride_ || qvariant_cast<bool>(internalPropGet("standbyOverride"));
}

bool AbstractSensorChannelInterface::setStandbyOverride(bool override)
{
    pimpl_->standbyOverride_ = override;
    return setStandbyOverride(pimpl_->sessionId_, override);
}

QString AbstractSensorChannelInterface::type() const
{
    return qvariant_cast<QString>(internalPropGet("type"));
}

int AbstractSensorChannelInterface::errorCodeInt() const
{
    return static_cast<SensorManagerError>(qvariant_cast<int>(internalPropGet("errorCodeInt")));
}

void AbstractSensorChannelInterface::clearError()
{
    pimpl_->errorCode_ = SNoError;
    pimpl_->errorString_.clear();
}

void AbstractSensorChannelInterface::dataReceived()
{
}

bool AbstractSensorChannelInterface::read(void* buffer, int size)
{
    return pimpl_->socketReader_.read(buffer, size);
}
<commit_msg>buffersize and bufferinterval are now set after sensor has been started.<commit_after>/**
   @file abstractsensor_i.cpp
   @brief Base class for sensor interface

   Copyright (C) 2009-2010 Nokia Corporation

   @author Joep van Gassel <joep.van.gassel@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord 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.

   Sensord 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 Sensord.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "sensormanagerinterface.h"
#include "abstractsensor_i.h"

struct AbstractSensorChannelInterface::AbstractSensorChannelInterfaceImpl
{
    AbstractSensorChannelInterfaceImpl(QObject* parent, int sessionId);

    SensorError errorCode_;
    QString errorString_;
    int sessionId_;
    int interval_;
    unsigned int bufferInterval_;
    unsigned int bufferSize_;
    SocketReader socketReader_;
    bool running_;
    bool standbyOverride_;
};

AbstractSensorChannelInterface::AbstractSensorChannelInterfaceImpl::AbstractSensorChannelInterfaceImpl(QObject* parent, int sessionId) :
    sessionId_(sessionId),
    interval_(0),
    bufferInterval_(0),
    bufferSize_(1),
    socketReader_(parent),
    running_(false),
    standbyOverride_(false)
{
}

AbstractSensorChannelInterface::AbstractSensorChannelInterface(const QString& path, const char* interfaceName, int sessionId) :
    QDBusAbstractInterface(SERVICE_NAME, path, interfaceName, QDBusConnection::systemBus(), 0),
    pimpl_(new AbstractSensorChannelInterfaceImpl(this, sessionId))
{
    if (!pimpl_->socketReader_.initiateConnection(sessionId)) {
        setError(SClientSocketError, "Socket connection failed.");
        // TODO: Invalidate!
    }

    qDBusRegisterMetaType<DataRange>();

    Q_ASSERT ( isValid() );
}

AbstractSensorChannelInterface::~AbstractSensorChannelInterface()
{
    if ( isValid() )
        release();
    if (!pimpl_->socketReader_.dropConnection())
        setError(SClientSocketError, "Socket disconnect failed.");
    delete pimpl_;
}

SocketReader& AbstractSensorChannelInterface::getSocketReader() const
{
    return pimpl_->socketReader_;
}

bool AbstractSensorChannelInterface::release()
{
    // ToDo: note that after release this interace becomes invalid (this should be handled correctly)
    return SensorManagerInterface::instance().releaseInterface(id(), pimpl_->sessionId_);
}

void AbstractSensorChannelInterface::setError(SensorError errorCode, const QString& errorString)
{
    pimpl_->errorCode_   = errorCode;
    pimpl_->errorString_ = errorString;

    //emit errorSignal(errorCode);
}

QDBusReply<void> AbstractSensorChannelInterface::start()
{
    return start(pimpl_->sessionId_);
}

QDBusReply<void> AbstractSensorChannelInterface::stop()
{
    return stop(pimpl_->sessionId_);
}

QDBusReply<void> AbstractSensorChannelInterface::start(int sessionId)
{
    clearError();

    if (pimpl_->running_) {
        return QDBusReply<void>();
    }
    pimpl_->running_ = true;

    connect(pimpl_->socketReader_.socket(), SIGNAL(readyRead()), this, SLOT(dataReceived()));

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId);
    QDBusReply<void> returnValue = callWithArgumentList(QDBus::Block, QLatin1String("start"), argumentList);

    if (pimpl_->standbyOverride_)
    {
        setStandbyOverride(sessionId, true);
    }
    /// Send interval request when started.
    setInterval(sessionId, pimpl_->interval_);
    setBufferInterval(sessionId, pimpl_->bufferInterval_);
    setBufferSize(sessionId, pimpl_->bufferSize_);

    return returnValue;
}

QDBusReply<void> AbstractSensorChannelInterface::stop(int sessionId)
{
    clearError();

    if (!pimpl_->running_) {
        return QDBusReply<void>();
    }
    pimpl_->running_ = false ;

    disconnect(pimpl_->socketReader_.socket(), SIGNAL(readyRead()), this, SLOT(dataReceived()));
    setStandbyOverride(sessionId, false);
    /// Drop interval requests when stopped
    setInterval(sessionId, 0);

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId);
    return callWithArgumentList(QDBus::Block, QLatin1String("stop"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setInterval(int sessionId, int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setInterval"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setBufferInterval(int sessionId, unsigned int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setBufferInterval"), argumentList);
}

QDBusReply<void> AbstractSensorChannelInterface::setBufferSize(int sessionId, unsigned int value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setBufferSize"), argumentList);
}

QDBusReply<bool> AbstractSensorChannelInterface::setStandbyOverride(int sessionId, bool value)
{
    clearError();

    QList<QVariant> argumentList;
    argumentList << qVariantFromValue(sessionId) << qVariantFromValue(value);
    return callWithArgumentList(QDBus::Block, QLatin1String("setStandbyOverride"), argumentList);
}

DataRangeList AbstractSensorChannelInterface::getAvailableDataRanges()
{
    QDBusReply<DataRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableDataRanges"));
    return ret.value();
}

DataRange AbstractSensorChannelInterface::getCurrentDataRange()
{
    clearError();
    QDBusReply<DataRange> retVal = call(QDBus::Block, QLatin1String("getCurrentDataRange"));
    return retVal.value();
}

void AbstractSensorChannelInterface::requestDataRange(DataRange range)
{
    clearError();
    call(QDBus::Block, QLatin1String("requestDataRange"), qVariantFromValue(pimpl_->sessionId_), qVariantFromValue(range));
}

void AbstractSensorChannelInterface::removeDataRangeRequest()
{
    clearError();
    call(QDBus::Block, QLatin1String("removeDataRangeRequest"), qVariantFromValue(pimpl_->sessionId_));
}

DataRangeList AbstractSensorChannelInterface::getAvailableIntervals()
{
    QDBusReply<DataRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableIntervals"));
    return ret.value();
}

IntegerRangeList AbstractSensorChannelInterface::getAvailableBufferIntervals()
{
    QDBusReply<IntegerRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableBufferIntervals"));
    return ret.value();
}

IntegerRangeList AbstractSensorChannelInterface::getAvailableBufferSizes()
{
    QDBusReply<IntegerRangeList> ret = call(QDBus::Block, QLatin1String("getAvailableBufferSizes"));
    return ret.value();
}

int AbstractSensorChannelInterface::sessionId() const
{
    return pimpl_->sessionId_;
}

SensorError AbstractSensorChannelInterface::errorCode() const
{
    // TODO: This solution may introduce problems, if errors are
    //       not cleared before another happens.
    if (pimpl_->errorCode_ != SNoError) {
        return pimpl_->errorCode_;
    }
    return static_cast<SensorError>(errorCodeInt());
}

QString AbstractSensorChannelInterface::errorString() const
{
    if (pimpl_->errorCode_ != SNoError) {
        return pimpl_->errorString_;
    }
    return qvariant_cast<QString>(internalPropGet("errorString"));
}

QString AbstractSensorChannelInterface::description() const
{
    return qvariant_cast<QString>(internalPropGet("description"));
}

QString AbstractSensorChannelInterface::id() const
{
    return qvariant_cast<QString>(internalPropGet("id"));
}

int AbstractSensorChannelInterface::interval() const
{
    return qvariant_cast<int>(internalPropGet("interval"));
}

void AbstractSensorChannelInterface::setInterval(int value)
{
    pimpl_->interval_ = value;
    if (pimpl_->running_)
        setInterval(pimpl_->sessionId_, value);
}

unsigned int AbstractSensorChannelInterface::bufferInterval() const
{
    return qvariant_cast<unsigned int>(internalPropGet("bufferInterval"));
}

void AbstractSensorChannelInterface::setBufferInterval(unsigned int value)
{
    pimpl_->bufferInterval_ = value;
    if (!pimpl_->running_)
        setBufferInterval(pimpl_->sessionId_, value);
}

unsigned int AbstractSensorChannelInterface::bufferSize() const
{
    return qvariant_cast<unsigned int>(internalPropGet("bufferSize"));
}

void AbstractSensorChannelInterface::setBufferSize(unsigned int value)
{
    pimpl_->bufferSize_ = value;
    if (!pimpl_->running_)
        setBufferSize(pimpl_->sessionId_, value);
}

bool AbstractSensorChannelInterface::standbyOverride() const
{
    return pimpl_->standbyOverride_ || qvariant_cast<bool>(internalPropGet("standbyOverride"));
}

bool AbstractSensorChannelInterface::setStandbyOverride(bool override)
{
    pimpl_->standbyOverride_ = override;
    return setStandbyOverride(pimpl_->sessionId_, override);
}

QString AbstractSensorChannelInterface::type() const
{
    return qvariant_cast<QString>(internalPropGet("type"));
}

int AbstractSensorChannelInterface::errorCodeInt() const
{
    return static_cast<SensorManagerError>(qvariant_cast<int>(internalPropGet("errorCodeInt")));
}

void AbstractSensorChannelInterface::clearError()
{
    pimpl_->errorCode_ = SNoError;
    pimpl_->errorString_.clear();
}

void AbstractSensorChannelInterface::dataReceived()
{
}

bool AbstractSensorChannelInterface::read(void* buffer, int size)
{
    return pimpl_->socketReader_.read(buffer, size);
}
<|endoftext|>


<commit_before>/*
	This file is part of the E_Geometry library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Matrix4x4.h"
#include "E_SRT.h"
#include "E_Vec3.h"
#include "E_Vec4.h"
#include <EScript/Basics.h>
#include <EScript/StdObjects.h>
#include <Geometry/Matrix4x4.h>
#include <sstream>

namespace E_Geometry {

//! (static)
EScript::Type * E_Matrix4x4::getTypeObject(){
	static EScript::Type * typeObject = new EScript::Type(EScript::Object::getTypeObject()); // ---|> Object
	return typeObject;
}

//!	(static) init members
void E_Matrix4x4::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = E_Matrix4x4::getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);

	using namespace Geometry;

	//! [ESMF] new Geometry.Matrix4x4([Matrix4x4 | Array | SRT])
	ES_CONSTRUCTOR(typeObject,0,1,{
		if(parameter.count()==0){
			return new E_Matrix4x4;
		}else{
			E_Matrix4x4 * em=parameter[0].toType<E_Matrix4x4>();
			if(em)
				return new E_Matrix4x4(**em);

			E_SRT * srt = parameter[0].toType<E_SRT>();
			if(srt)
				return new E_Matrix4x4(**srt);

			EScript::Array * a=parameter[0].toType<EScript::Array>();
			if(!a){
				rt.setException("Matrix4x4: Wrong argument for constructor.");
				return nullptr;
			}
			float f[16];
			for(unsigned int i=0;i<16;i++){
				Object * num=a->get(i);
				if(num){
					f[i]=static_cast<float>(num->toDouble());
				}else{
					f[i]=0;
				}
			}
			return new E_Matrix4x4(f);
		}
	})

	//! [ESMF] Vec3|Matrix|SRT Matrix4x4.*(Vec3|Vec4|Matrix|SRT|Number)
	ES_MFUNCTION(typeObject,Matrix4x4,"*",1,1,{
		if(E_Vec3 * evt=parameter[0].toType<E_Vec3>()){
			rt.warn("Matrix4x4.*(Vec3) is deprecated. Use Matrix4x4.transformPosition(...) instead");
			return EScript::create(std::move(thisObj->transformPosition(**evt)));
		}else if(E_Vec4 * evf=parameter[0].toType<E_Vec4>()){
			return EScript::create(std::move(*thisObj * (**evf)));
		}else if(E_Matrix4x4 * em=parameter[0].toType<E_Matrix4x4>()){
			return EScript::create(std::move(*thisObj * (**em)));
		}else if(E_SRT * es=parameter[0].toType<E_SRT>()){
			return EScript::create(std::move(*thisObj * (**es)));
		}else return EScript::create(std::move(*thisObj * parameter[0].to<float>(rt)));
	})

	//! [ESMF] Matrix4x4 Matrix4x4.inverse()
	ES_MFUN(typeObject,Matrix4x4,"inverse",0,0,std::move(thisObj->inverse()))

	//! [ESMF] self Matrix4x4.lookAt(E_Vec3 pos,E_Vec3 target,E_Vec3 up)
	ES_MFUN(typeObject,Matrix4x4,"lookAt",3,3,( thisObj->lookAt(
		 parameter[0].to<Vec3>(rt),
		 parameter[1].to<Vec3>(rt),
		 parameter[2].to<Vec3>(rt)),thisEObj))

	//! [ESMF] self Matrix4x4.rotate(deg,x,y,z)
	ES_MFUN(typeObject,Matrix4x4,"rotate",4,4,(thisObj->
			rotate_deg(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt)),thisEObj))

	//! [ESMF] self Matrix4x4.rotate_deg(deg,x,y,z)
	ES_MFUN(typeObject,Matrix4x4,"rotate_deg",4,4,(thisObj->
			rotate_deg(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt)),thisEObj))

	//! [ESMF] self Matrix4x4.rotate_rad(angle,x,y,z)
	ES_MFUN(typeObject,Matrix4x4,"rotate_rad",4,4,(thisObj->
			rotate_rad(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt)),thisEObj))

	//! [ESMF] Matrix4x4 Matrix4x4.scale(x,y,z)
	ES_MFUNCTION(typeObject,Matrix4x4,"scale",3,3,{
		thisObj->scale(
			parameter[0].to<double>(rt),parameter[1].to<double>(rt),parameter[2].to<double>(rt));
		return thisEObj;
	})

	//! [ESF] Matrix4x4 Matrix4x4.setIdentity()
	ES_MFUNCTION(typeObject,Matrix4x4,"setIdentity",0,0,{
		thisObj->setIdentity();
		return thisEObj;
	})

	//! [ESMF] Vec3 Matrix4x4.transformDirection(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,const Matrix4x4,"transformDirection",1,3,{
		if(parameter.count() == 3){
			return EScript::create(thisObj->transformDirection(parameter[0].to<double>(rt),
										parameter[1].to<double>(rt),parameter[2].to<double>(rt)));
		}
		return EScript::create(thisObj->transformDirection(parameter[0].to<Vec3>(rt)));
	})

	//! [ESMF] Vec3 Matrix4x4.transformPosition(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,const Matrix4x4,"transformPosition",1,3,{
		if(parameter.count() == 3){
			return EScript::create(thisObj->transformPosition(parameter[0].to<double>(rt),
										parameter[1].to<double>(rt),parameter[2].to<double>(rt)));
		}
		return EScript::create(thisObj->transformPosition(parameter[0].to<Vec3>(rt)));
	})

	//! [ESMF] Array Matrix4x4.toArray()
	ES_MFUNCTION(typeObject,Matrix4x4,"toArray",0,0,{
		EScript::Array * a = EScript::Array::create();
		for(unsigned int i=0;i<16;i++)
			a->pushBack(EScript::create((*thisObj)[i]));
		return a;
	})

	//! [ESMF] Bool Matrix4x4.convertsSafelyToSRT()
	ES_MFUN(typeObject,Matrix4x4, "convertsSafelyToSRT", 0, 0, thisObj->convertsSafelyToSRT())

	//! [ESMF] SRT Matrix4x4.toSRT()
	ES_MFUN(typeObject,Matrix4x4,"toSRT",0,0,std::move(thisObj->_toSRT()))

	//! [ESMF] Matrix4x4 Matrix4x4.translate(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,Matrix4x4,"translate",1,3,{
		if(parameter.count() == 3){
			thisObj->translate(
			parameter[0].to<double>(rt),parameter[1].to<double>(rt),parameter[2].to<double>(rt));
		}
		else{
			thisObj->translate(parameter[0].to<Vec3>(rt));
		}
		return thisEObj;
	})

}

std::string E_Matrix4x4::toString() const {
	std::ostringstream stream;
	stream << getClassName() << '(' << (**this) << ')';
	return stream.str();
}

}
<commit_msg>E_Matrix4x4: Allow Vec3 parameter for rotate_deg and rotate_rad.<commit_after>/*
	This file is part of the E_Geometry library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Matrix4x4.h"
#include "E_SRT.h"
#include "E_Vec3.h"
#include "E_Vec4.h"
#include <EScript/Basics.h>
#include <EScript/StdObjects.h>
#include <Geometry/Matrix4x4.h>
#include <sstream>

namespace E_Geometry {

//! (static)
EScript::Type * E_Matrix4x4::getTypeObject(){
	static EScript::Type * typeObject = new EScript::Type(EScript::Object::getTypeObject()); // ---|> Object
	return typeObject;
}

//!	(static) init members
void E_Matrix4x4::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = E_Matrix4x4::getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);

	using namespace Geometry;

	//! [ESMF] new Geometry.Matrix4x4([Matrix4x4 | Array | SRT])
	ES_CONSTRUCTOR(typeObject,0,1,{
		if(parameter.count()==0){
			return new E_Matrix4x4;
		}else{
			E_Matrix4x4 * em=parameter[0].toType<E_Matrix4x4>();
			if(em)
				return new E_Matrix4x4(**em);

			E_SRT * srt = parameter[0].toType<E_SRT>();
			if(srt)
				return new E_Matrix4x4(**srt);

			EScript::Array * a=parameter[0].toType<EScript::Array>();
			if(!a){
				rt.setException("Matrix4x4: Wrong argument for constructor.");
				return nullptr;
			}
			float f[16];
			for(unsigned int i=0;i<16;i++){
				Object * num=a->get(i);
				if(num){
					f[i]=static_cast<float>(num->toDouble());
				}else{
					f[i]=0;
				}
			}
			return new E_Matrix4x4(f);
		}
	})

	//! [ESMF] Vec3|Matrix|SRT Matrix4x4.*(Vec3|Vec4|Matrix|SRT|Number)
	ES_MFUNCTION(typeObject,Matrix4x4,"*",1,1,{
		if(E_Vec3 * evt=parameter[0].toType<E_Vec3>()){
			rt.warn("Matrix4x4.*(Vec3) is deprecated. Use Matrix4x4.transformPosition(...) instead");
			return EScript::create(std::move(thisObj->transformPosition(**evt)));
		}else if(E_Vec4 * evf=parameter[0].toType<E_Vec4>()){
			return EScript::create(std::move(*thisObj * (**evf)));
		}else if(E_Matrix4x4 * em=parameter[0].toType<E_Matrix4x4>()){
			return EScript::create(std::move(*thisObj * (**em)));
		}else if(E_SRT * es=parameter[0].toType<E_SRT>()){
			return EScript::create(std::move(*thisObj * (**es)));
		}else return EScript::create(std::move(*thisObj * parameter[0].to<float>(rt)));
	})

	//! [ESMF] Matrix4x4 Matrix4x4.inverse()
	ES_MFUN(typeObject,Matrix4x4,"inverse",0,0,std::move(thisObj->inverse()))

	//! [ESMF] self Matrix4x4.lookAt(E_Vec3 pos,E_Vec3 target,E_Vec3 up)
	ES_MFUN(typeObject,Matrix4x4,"lookAt",3,3,( thisObj->lookAt(
		 parameter[0].to<Vec3>(rt),
		 parameter[1].to<Vec3>(rt),
		 parameter[2].to<Vec3>(rt)),thisEObj))

	//! [ESMF] self Matrix4x4.rotate(deg,x,y,z)
	ES_MFUN(typeObject,Matrix4x4,"rotate",4,4,(thisObj->
			rotate_deg(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt)),thisEObj))

	//! [ESMF] self Matrix4x4.rotate_deg(deg,  (x,y,z)| Vec3 )
	ES_MFUNCTION(typeObject,Matrix4x4,"rotate_deg",2,4,{
		if(parameter.count()==2){
			thisObj->rotate_deg(parameter[0].to<double>(rt),parameter[1].to<Geometry::Vec3>(rt));
		}else{
			assertParamCount(rt,parameter.count(),4,4);
			thisObj->rotate_deg(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt));
		}
		return thisEObj;
	})

	//! [ESMF] self Matrix4x4.rotate_rad(deg,  (x,y,z)| Vec3 )
	ES_MFUNCTION(typeObject,Matrix4x4,"rotate_rad",2,4,{
		if(parameter.count()==2){
			thisObj->rotate_rad(parameter[0].to<double>(rt),parameter[1].to<Geometry::Vec3>(rt));
		}else{
			assertParamCount(rt,parameter.count(),4,4);
			thisObj->rotate_rad(parameter[0].to<double>(rt),parameter[1].to<double>(rt),
					   parameter[2].to<double>(rt),parameter[3].to<double>(rt));
		}
		return thisEObj;
	})

	//! [ESMF] Matrix4x4 Matrix4x4.scale(x,y,z)
	ES_MFUNCTION(typeObject,Matrix4x4,"scale",3,3,{
		thisObj->scale(
			parameter[0].to<double>(rt),parameter[1].to<double>(rt),parameter[2].to<double>(rt));
		return thisEObj;
	})

	//! [ESF] Matrix4x4 Matrix4x4.setIdentity()
	ES_MFUNCTION(typeObject,Matrix4x4,"setIdentity",0,0,{
		thisObj->setIdentity();
		return thisEObj;
	})

	//! [ESMF] Vec3 Matrix4x4.transformDirection(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,const Matrix4x4,"transformDirection",1,3,{
		if(parameter.count() == 3){
			return EScript::create(thisObj->transformDirection(parameter[0].to<double>(rt),
										parameter[1].to<double>(rt),parameter[2].to<double>(rt)));
		}
		return EScript::create(thisObj->transformDirection(parameter[0].to<Vec3>(rt)));
	})

	//! [ESMF] Vec3 Matrix4x4.transformPosition(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,const Matrix4x4,"transformPosition",1,3,{
		if(parameter.count() == 3){
			return EScript::create(thisObj->transformPosition(parameter[0].to<double>(rt),
										parameter[1].to<double>(rt),parameter[2].to<double>(rt)));
		}
		return EScript::create(thisObj->transformPosition(parameter[0].to<Vec3>(rt)));
	})

	//! [ESMF] Array Matrix4x4.toArray()
	ES_MFUNCTION(typeObject,Matrix4x4,"toArray",0,0,{
		EScript::Array * a = EScript::Array::create();
		for(unsigned int i=0;i<16;i++)
			a->pushBack(EScript::create((*thisObj)[i]));
		return a;
	})

	//! [ESMF] Bool Matrix4x4.convertsSafelyToSRT()
	ES_MFUN(typeObject,Matrix4x4, "convertsSafelyToSRT", 0, 0, thisObj->convertsSafelyToSRT())

	//! [ESMF] SRT Matrix4x4.toSRT()
	ES_MFUN(typeObject,Matrix4x4,"toSRT",0,0,std::move(thisObj->_toSRT()))

	//! [ESMF] Matrix4x4 Matrix4x4.translate(E_Vec3|x,y,z)
	ES_MFUNCTION(typeObject,Matrix4x4,"translate",1,3,{
		if(parameter.count() == 3){
			thisObj->translate(
			parameter[0].to<double>(rt),parameter[1].to<double>(rt),parameter[2].to<double>(rt));
		}
		else{
			thisObj->translate(parameter[0].to<Vec3>(rt));
		}
		return thisEObj;
	})

}

std::string E_Matrix4x4::toString() const {
	std::ostringstream stream;
	stream << getClassName() << '(' << (**this) << ')';
	return stream.str();
}

}
<|endoftext|>


<commit_before>#include <iostream>

#include "WakeDefines.h"

#include "Logging/LogMacros.h"

#include "Engine/InputManager.h"
#include "Engine/GEngine.h"
#include "Engine/Bootstrap.h"
#include "Engine/Shader.h"

#include "World/World.h"
#include "World/StaticMeshComponent.h"
#include "World/CameraComponent.h"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>

int xAxis = 0;
int yAxis = 0;

class CameraActor : public Actor
{
public:
	CameraActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		Camera = CreateComponent<CameraComponent>(true);
	}

private:
	CameraComponent* Camera;
};

class TestActor : public Actor
{
public:
	TestActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		ShaderProgram* Shader = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
		GLint posAttrib = glGetAttribLocation(Shader->GetProgram(), "position");

		float vertices[] = {
			0.f, 0.5f, 0.f,
			0.5f, -0.5f, 0.f,
			-0.5f, -0.5f, 0.f
		};

		GLuint vbo;
		GLuint vao;

		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);

		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(posAttrib);

		MeshComponent = CreateComponent<StaticMeshComponent>(true, new StaticMesh(vbo, vao, 3), Shader);
	}

	virtual void Destroy() override
	{
	}

	virtual void Tick() override
	{
	}

private:
	StaticMeshComponent* MeshComponent;
};

void Left(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void Right(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Up(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Down(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void OnInput_Exit(const Input& Input)
{
	W_ENGINE.Stop();
}

CameraActor* Cam = nullptr;

void Tick()
{
	auto fwd = Cam->GetForward();
	auto right = Cam->GetRight();
	Cam->SetPosition(Cam->GetPosition() + (Cam->GetForward() * (float)yAxis + Cam->GetRight() * (float)xAxis) * W_ENGINE.GetDeltaTime());

	auto MousePos = sf::Mouse::getPosition(*W_ENGINE.GetGameWindow().GetRenderWindow());
	auto Center = sf::Vector2i(W_ENGINE.GetGameWindow().GetWidth() / 2, W_ENGINE.GetGameWindow().GetHeight() / 2);
	float xChange = Center.x - MousePos.x;
	float yChange = Center.y - MousePos.y;
	auto rot = glm::vec3(yChange, xChange, 0) * W_ENGINE.GetDeltaTime();
	Cam->SetRotation(Cam->GetRotation() * glm::quat(rot));
	sf::Mouse::setPosition(Center, *W_ENGINE.GetGameWindow().GetRenderWindow());
}

void Setup()
{
	Actor* Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(-1, 0, -1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(-1, 0, 1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(1, 0, -1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(1, 0, 1));
	Test->SetRotation(glm::quat(glm::vec3(0, glm::pi<float>() / 2.f, 0)));

	Cam = W_WORLD.SpawnActor<CameraActor>(true);
	Cam->SetPosition(glm::vec3(0, 0, 3));

	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Pressed, Escape));
	W_INPUT.Event("Exit").Bind(&OnInput_Exit);

	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Pressed, A));
	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Released, A));

	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Pressed, D));
	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Released, D));

	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Pressed, W));
	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Released, W));

	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Pressed, S));
	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Released, S));

	W_INPUT.Event("Left").Bind(&Left);
	W_INPUT.Event("Right").Bind(&Right);
	W_INPUT.Event("Up").Bind(&Up);
	W_INPUT.Event("Down").Bind(&Down);

	W_ENGINE.Tick.Bind(&Tick);

	sf::Mouse::setPosition(sf::Vector2i(W_ENGINE.GetGameWindow().GetWidth() / 2, W_ENGINE.GetGameWindow().GetHeight() / 2), *W_ENGINE.GetGameWindow().GetRenderWindow());
}

void RunEngine(int ArgC, char** ArgV)
{
	BootstrapOptions Options;
	Options.DefaultLogSinks = true;
	Options.DontRunEngine = false;

	Bootstrap Engine(ArgC, ArgV, Options);
	if (!Engine.Startup())
	{
		return;
	}

	Setup();

	Engine.Run();
}

int main(int argc, char** argv)
{
	RunEngine(argc, argv);

#ifdef WAKE_EXIT_PAUSE
	std::cout << "Press return to exit..." << std::endl;
	getchar();
#endif
	return 0;
}<commit_msg>spinning triangles<commit_after>#include <iostream>

#include "WakeDefines.h"

#include "Logging/LogMacros.h"

#include "Engine/InputManager.h"
#include "Engine/GEngine.h"
#include "Engine/Bootstrap.h"
#include "Engine/Shader.h"

#include "World/World.h"
#include "World/StaticMeshComponent.h"
#include "World/CameraComponent.h"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>

int xAxis = 0;
int yAxis = 0;

class CameraActor : public Actor
{
public:
	CameraActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		Camera = CreateComponent<CameraComponent>(true);
	}

private:
	CameraComponent* Camera;
};

class TestActor : public Actor
{
public:
	TestActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		ShaderProgram* Shader = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
		GLint posAttrib = glGetAttribLocation(Shader->GetProgram(), "position");

		float vertices[] = {
			0.f, 0.5f, 0.f,
			0.5f, -0.5f, 0.f,
			-0.5f, -0.5f, 0.f
		};

		GLuint vbo;
		GLuint vao;

		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);

		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(posAttrib);

		MeshComponent = CreateComponent<StaticMeshComponent>(true, new StaticMesh(vbo, vao, 3), Shader);
	}

	virtual void Tick() override
	{
		Actor::Tick();

		SetRotation(GetRotation() * glm::quat(glm::vec3(0, glm::pi<float>() / 2.f, 0) * W_ENGINE.GetDeltaTime()));
	}

private:
	StaticMeshComponent* MeshComponent;
};

void Left(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void Right(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Up(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Down(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void OnInput_Exit(const Input& Input)
{
	W_ENGINE.Stop();
}

CameraActor* Cam = nullptr;

void Tick()
{
	auto fwd = Cam->GetForward();
	auto right = Cam->GetRight();
	Cam->SetPosition(Cam->GetPosition() + (Cam->GetForward() * (float)yAxis + Cam->GetRight() * (float)xAxis) * W_ENGINE.GetDeltaTime());

	auto MousePos = sf::Mouse::getPosition(*W_ENGINE.GetGameWindow().GetRenderWindow());
	auto Center = sf::Vector2i(W_ENGINE.GetGameWindow().GetWidth() / 2, W_ENGINE.GetGameWindow().GetHeight() / 2);
	float xChange = Center.x - MousePos.x;
	float yChange = Center.y - MousePos.y;
	auto rot = glm::vec3(yChange, xChange, 0) * W_ENGINE.GetDeltaTime();
	Cam->SetRotation(Cam->GetRotation() * glm::quat(rot));
	sf::Mouse::setPosition(Center, *W_ENGINE.GetGameWindow().GetRenderWindow());
}

void Setup()
{
	Actor* Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(-1, 0, -1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(-1, 0, 1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(1, 0, -1));
	Test = W_WORLD.SpawnActor<TestActor>();
	Test->SetPosition(glm::vec3(1, 0, 1));
	Test->SetRotation(glm::quat(glm::vec3(0, glm::pi<float>() / 2.f, 0)));

	Cam = W_WORLD.SpawnActor<CameraActor>(true);
	Cam->SetPosition(glm::vec3(0, 0, 3));

	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Pressed, Escape));
	W_INPUT.Event("Exit").Bind(&OnInput_Exit);

	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Pressed, A));
	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Released, A));

	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Pressed, D));
	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Released, D));

	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Pressed, W));
	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Released, W));

	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Pressed, S));
	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Released, S));

	W_INPUT.Event("Left").Bind(&Left);
	W_INPUT.Event("Right").Bind(&Right);
	W_INPUT.Event("Up").Bind(&Up);
	W_INPUT.Event("Down").Bind(&Down);

	W_ENGINE.Tick.Bind(&Tick);

	sf::Mouse::setPosition(sf::Vector2i(W_ENGINE.GetGameWindow().GetWidth() / 2, W_ENGINE.GetGameWindow().GetHeight() / 2), *W_ENGINE.GetGameWindow().GetRenderWindow());
}

void RunEngine(int ArgC, char** ArgV)
{
	BootstrapOptions Options;
	Options.DefaultLogSinks = true;
	Options.DontRunEngine = false;

	Bootstrap Engine(ArgC, ArgV, Options);
	if (!Engine.Startup())
	{
		return;
	}

	Setup();

	Engine.Run();
}

int main(int argc, char** argv)
{
	RunEngine(argc, argv);

#ifdef WAKE_EXIT_PAUSE
	std::cout << "Press return to exit..." << std::endl;
	getchar();
#endif
	return 0;
}<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// Read in a Mesh file and write out partitionings of it that are suitable
// for reading into a DistributedMesh
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/checkpoint_io.h"
#include "libmesh/metis_partitioner.h"
#include "libmesh/getpot.h"

using namespace libMesh;

int main (int argc, char ** argv)
{
  LibMeshInit init (argc, argv);

  if (libMesh::on_command_line("--help"))
    {
      libMesh::out << "Example: ./splitter-opt --mesh=filename.e --n-procs='4 8 16' --dry-run\n\n"
                   << "--mesh             Full name of the mesh file to read in. \n"
                   << "--n-procs          Vector of number of processors.\n"
                   << "--dry-run          Only test the partitioning, don't write any files.\n"
                   << std::endl;

      return 0;
    }

  std::string filename = libMesh::command_line_value("--mesh", std::string());

  std::vector<int> all_n_procs;
  libMesh::command_line_vector("--n-procs", all_n_procs);

  Parallel::Communicator & comm = init.comm();

  Mesh mesh(init.comm());

  libMesh::out << "Reading " << filename << std::endl;

  mesh.read(filename);

  MetisPartitioner partitioner;

  for (unsigned int i = 0; i < all_n_procs.size(); i++)
    {
      processor_id_type n_procs = all_n_procs[i];

      libMesh::out << "\nWriting out files for " << n_procs << " processors...\n\n" << std::endl;

      // Reset the partitioning each time after the first one
      if (i > 0)
        {
          libMesh::out << "Resetting Partitioning" << std::endl;
          partitioner.partition(mesh, 1);
        }

      libMesh::out << "Partitioning" << std::endl;

      // Partition it to how we want it
      partitioner.partition(mesh, n_procs);

      mesh.print_info();

      // When running in parallel each processor will write out a portion of the mesh files

      processor_id_type num_chunks = n_procs / comm.size();
      processor_id_type remaining_chunks = n_procs % comm.size();

      processor_id_type my_num_chunks = num_chunks;

      processor_id_type my_first_chunk = 0;

      processor_id_type rank = comm.rank();
      processor_id_type comm_size = comm.size();

      if (n_procs >= comm_size) // More partitions than processors
        {
          if (remaining_chunks) // Means that it doesn't split up evenly
            {
              // Spread the remainder over the first few processors
              // There will be "remaining_chunks" number of processors that will each
              // get one extra chunk
              if (rank < remaining_chunks)
                {
                  my_num_chunks += 1;
                  my_first_chunk = my_num_chunks * rank;
                }
              else // The processors beyond the "first" set that don't get an extra chunk
                {
                  // The number of chunks dealt with by the first processors
                  // num chunks         // num procs
                  processor_id_type num_chunks_in_first_procs = (my_num_chunks + 1) * remaining_chunks;
                  processor_id_type distance_to_first_procs = rank - remaining_chunks;

                  my_first_chunk = num_chunks_in_first_procs + (my_num_chunks * distance_to_first_procs);
                }
            }
          else // Splits evenly
            my_first_chunk = my_num_chunks * rank;
        }
      else // More processors than partitions
        {
          if (rank < n_procs)
            {
              my_num_chunks = 1;
              my_first_chunk = rank;
            }
          else
            {
              my_num_chunks = 0;
              my_first_chunk = std::numeric_limits<processor_id_type>::max();
            }
        }

      if (!libMesh::on_command_line("--dry-run"))
        {
          libMesh::out << "Writing " << my_num_chunks << " Files" << std::endl;

          for (unsigned int i = my_first_chunk; i < my_first_chunk + my_num_chunks; i++)
            {
              libMesh::err << comm.rank() << ": " << i << std::endl;

              CheckpointIO cpr(mesh);
              cpr.current_processor_id() = i;
              cpr.current_n_processors() = n_procs;
              cpr.binary() = true;
              cpr.parallel() = true;
              cpr.write(filename + ".cpr");
            }
        }
    }

  return 0;
}
<commit_msg>Small changes to splitter to change the way the filenames are output<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// Read in a Mesh file and write out partitionings of it that are suitable
// for reading into a DistributedMesh
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/checkpoint_io.h"
#include "libmesh/metis_partitioner.h"
#include "libmesh/getpot.h"

using namespace libMesh;

// From: http://stackoverflow.com/a/6417908/2042320
std::string remove_extension (const std::string & filename)
{
  size_t lastdot = filename.find_last_of(".");

  if (lastdot == std::string::npos)
    return filename;

  return filename.substr(0, lastdot);
}

int main (int argc, char ** argv)
{
  LibMeshInit init (argc, argv);

  if (libMesh::on_command_line("--help") || argc < 3)
    {
      libMesh::out << "Example: ./splitter-opt --mesh=filename.e --n-procs='4 8 16' --dry-run\n\n"
                   << "--mesh             Full name of the mesh file to read in. \n"
                   << "--n-procs          Vector of number of processors.\n"
                   << "--dry-run          Only test the partitioning, don't write any files.\n"
                   << std::endl;

      return 0;
    }

  std::string filename = libMesh::command_line_value("--mesh", std::string());

  std::vector<int> all_n_procs;
  libMesh::command_line_vector("--n-procs", all_n_procs);

  Parallel::Communicator & comm = init.comm();

  Mesh mesh(init.comm());

  libMesh::out << "Reading " << filename << std::endl;

  mesh.read(filename);

  MetisPartitioner partitioner;

  for (unsigned int i = 0; i < all_n_procs.size(); i++)
    {
      processor_id_type n_procs = all_n_procs[i];

      libMesh::out << "\nWriting out files for " << n_procs << " processors...\n\n" << std::endl;

      // Reset the partitioning each time after the first one
      if (i > 0)
        {
          libMesh::out << "Resetting Partitioning" << std::endl;
          partitioner.partition(mesh, 1);
        }

      libMesh::out << "Partitioning" << std::endl;

      // Partition it to how we want it
      partitioner.partition(mesh, n_procs);

      mesh.print_info();

      // When running in parallel each processor will write out a portion of the mesh files

      processor_id_type num_chunks = n_procs / comm.size();
      processor_id_type remaining_chunks = n_procs % comm.size();

      processor_id_type my_num_chunks = num_chunks;

      processor_id_type my_first_chunk = 0;

      processor_id_type rank = comm.rank();
      processor_id_type comm_size = comm.size();

      if (n_procs >= comm_size) // More partitions than processors
        {
          if (remaining_chunks) // Means that it doesn't split up evenly
            {
              // Spread the remainder over the first few processors
              // There will be "remaining_chunks" number of processors that will each
              // get one extra chunk
              if (rank < remaining_chunks)
                {
                  my_num_chunks += 1;
                  my_first_chunk = my_num_chunks * rank;
                }
              else // The processors beyond the "first" set that don't get an extra chunk
                {
                  // The number of chunks dealt with by the first processors
                  // num chunks         // num procs
                  processor_id_type num_chunks_in_first_procs = (my_num_chunks + 1) * remaining_chunks;
                  processor_id_type distance_to_first_procs = rank - remaining_chunks;

                  my_first_chunk = num_chunks_in_first_procs + (my_num_chunks * distance_to_first_procs);
                }
            }
          else // Splits evenly
            my_first_chunk = my_num_chunks * rank;
        }
      else // More processors than partitions
        {
          if (rank < n_procs)
            {
              my_num_chunks = 1;
              my_first_chunk = rank;
            }
          else
            {
              my_num_chunks = 0;
              my_first_chunk = std::numeric_limits<processor_id_type>::max();
            }
        }

      if (!libMesh::on_command_line("--dry-run"))
        {
          libMesh::out << "Writing " << my_num_chunks << " Files" << std::endl;

          for (unsigned int i = my_first_chunk; i < my_first_chunk + my_num_chunks; i++)
            {
              libMesh::err << comm.rank() << ": " << i << std::endl;

              CheckpointIO cpr(mesh);
              cpr.current_processor_id() = i;
              cpr.current_n_processors() = n_procs;
              cpr.binary() = true;
              cpr.parallel() = true;
              cpr.write(remove_extension(filename) + ".cpr");
            }
        }
    }

  return 0;
}
<|endoftext|>


<commit_before>#include <cstdint>
#include <utility>

#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;

#include "Buddha.h"

Buddha::Buddha(const Params & p, const std::size_t thread_vector_size)
  : thread_vector_size_(thread_vector_size) {
    x_size_ = p.width;
    y_size_ = p.width;
    radius_ = p.radius;
    num_threads_ = p.num_threads;
    max_iterations_ = p.max_iterations;

    if (max_iterations_ > thread_vector_size)
        throw MaxIterationsTooBigException();

    data_ = std::vector<uint64_t>(x_size_ * y_size_);
}

Buddha::Params Buddha::get_empty_params() {
    Params p;
    p.num_threads = -1;
    return p;
}

void Buddha::run() {
    uint64_t part_size = x_size_ * y_size_ / num_threads_;

    for (std::size_t i = 0; i < num_threads_; ++i)
        threads_.emplace_back(&Buddha::worker, this, i * part_size, (i+1) * part_size);

    for (auto & t : threads_)
        t.join();

    render();
}

std::pair<uint64_t, uint64_t> Buddha::lin2car(uint64_t pos) const {
    return std::make_pair(pos % x_size_, pos / x_size_);
}

uint64_t Buddha::car2lin(uint64_t x, uint64_t y) const {
    return y * x_size_ + x;
}

Buddha::complex_type Buddha::car2complex(uint64_t x, uint64_t y) const {
    floating_type re = radius_ * ( 2. / x_size_ * x - 1);
    floating_type im = radius_ * ( 2. / y_size_ * x - 1);
    return complex_type(re, im);
}

std::pair<uint64_t, uint64_t> Buddha::complex2car(
    Buddha::complex_type c) const {
    uint64_t x = (uint64_t)(x_size_ * (c.real() / radius_ + 1) / 2.);
    uint64_t y = (uint64_t)(y_size_ * (c.imag() / radius_ + 1) / 2.);
    return std::make_pair(x, y);
}

Buddha::complex_type Buddha::lin2complex(uint64_t pos) const {
   auto pair = lin2car(pos);
   return car2complex(pair.first, pair.second);
}

uint64_t Buddha::complex2lin(Buddha::complex_type c) const {
    auto pair = complex2car(c);
    return car2lin(pair.first, pair.second);
}

CImg<uint64_t> Buddha::render() {
    std::lock_guard<std::mutex> _(data_lock_);
    CImg<uint64_t> img(x_size_, y_size_, 1, 1, 0);

    for (uint64_t i = 0; i < data_.size(); ++i) {
        auto car = lin2car(i);
        img.draw_point(car.first, car.second, &(data_[i]));
    }

    img.save("buddhabrot.png");

    return img;
}
<commit_msg>bugfix: creating a lot of threads<commit_after>#include <cstdint>
#include <utility>

#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;

#include "Buddha.h"

Buddha::Buddha(const Params & p, const std::size_t thread_vector_size)
  : thread_vector_size_(thread_vector_size) {
    x_size_ = p.width;
    y_size_ = p.width;
    radius_ = p.radius;
    max_iterations_ = p.max_iterations;
    num_threads_ = p.num_threads > 0
        ? p.num_threads
        : std::thread::hardware_concurrency();

    if (max_iterations_ > thread_vector_size)
        throw MaxIterationsTooBigException();

    data_ = std::vector<uint64_t>(x_size_ * y_size_);
}

Buddha::Params Buddha::get_empty_params() {
    Params p;
    p.num_threads = -1;
    return p;
}

void Buddha::run() {
    uint64_t part_size = x_size_ * y_size_ / num_threads_;

    for (std::size_t i = 0; i < num_threads_; ++i)
        threads_.emplace_back(&Buddha::worker, this, i * part_size, (i+1) * part_size);

    for (auto & t : threads_)
        t.join();

    render();
}

std::pair<uint64_t, uint64_t> Buddha::lin2car(uint64_t pos) const {
    return std::make_pair(pos % x_size_, pos / x_size_);
}

uint64_t Buddha::car2lin(uint64_t x, uint64_t y) const {
    return y * x_size_ + x;
}

Buddha::complex_type Buddha::car2complex(uint64_t x, uint64_t y) const {
    floating_type re = radius_ * ( 2. / x_size_ * x - 1);
    floating_type im = radius_ * ( 2. / y_size_ * x - 1);
    return complex_type(re, im);
}

std::pair<uint64_t, uint64_t> Buddha::complex2car(
    Buddha::complex_type c) const {
    uint64_t x = (uint64_t)(x_size_ * (c.real() / radius_ + 1) / 2.);
    uint64_t y = (uint64_t)(y_size_ * (c.imag() / radius_ + 1) / 2.);
    return std::make_pair(x, y);
}

Buddha::complex_type Buddha::lin2complex(uint64_t pos) const {
   auto pair = lin2car(pos);
   return car2complex(pair.first, pair.second);
}

uint64_t Buddha::complex2lin(Buddha::complex_type c) const {
    auto pair = complex2car(c);
    return car2lin(pair.first, pair.second);
}

CImg<uint64_t> Buddha::render() {
    std::lock_guard<std::mutex> _(data_lock_);
    CImg<uint64_t> img(x_size_, y_size_, 1, 1, 0);

    for (uint64_t i = 0; i < data_.size(); ++i) {
        auto car = lin2car(i);
        img.draw_point(car.first, car.second, &(data_[i]));
    }

    img.save("buddhabrot.png");

    return img;
}
<|endoftext|>


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

	Author: Tiago Britto Lobão
	tiago.blobao@gmail.com
*/

/*
	Purpose: Control an integrated circuit
	Cirrus Logic - CS5490

	Used to measure electrical quantities

	MIT License

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

#include "CS5490.h"

/******* Init CS5490 *******/

//For Arduino & ESP8622
#if !(defined ARDUINO_NodeMCU_32S ) && !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(ARDUINO_Node32s)
	CS5490::CS5490(float mclk, int rx, int tx){
		this->selectedPage = -1;
		this->MCLK = mclk;
		this->cSerial = new SoftwareSerial(rx,tx);
	}
//For ESP32 AND MEGA
#else
	CS5490::CS5490(float mclk){
		this->selectedPage = -1;
		this->MCLK = mclk;
		this->cSerial = &Serial2;
	}
#endif

void CS5490::begin(int baudRate){
	cSerial->begin(baudRate);
	delay(10); //Avoid Bugs on Arduino UNO
}

/**************************************************************/
/*                     PRIVATE METHODS                        */
/**************************************************************/

/******* Write a register by the serial communication *******/
/* data bytes pass by data variable from this class */

void CS5490::write(int page, int address, long value){

	uint8_t checksum = 0;
	for(int i=0; i<3; i++)
		checksum += 0xFF - checksum;

	uint8_t buffer;
	//Select page and address
	if(this->selectedPage != page){
		buffer = (pageByte | (uint8_t)page);
		cSerial->write(buffer);
		this->selectedPage = page;
	}
	buffer = (writeByte | (uint8_t)address);
	cSerial->write(buffer);

	//Send information
	for(int i=0; i<3 ; i++){
		data[i] = value & 0x000000FF;
		cSerial->write(this->data[i]);
		value >>= 8;
	}
	//Calculate and send checksum
	buffer = 0xFF - data[0] - data[1] - data[2];
	cSerial->write(buffer);
}

/******* Read a register by the serial communication *******/
/* data bytes pass by data variable from this class */

void CS5490::read(int page, int address){

	this->clearSerialBuffer();

	uint8_t buffer;
	//Select page and address
	if(this->selectedPage != page){
		buffer = (pageByte | (uint8_t)page);
		cSerial->write(buffer);
		this->selectedPage = page;
	}
	buffer = (readByte | (uint8_t)address);
	cSerial->write(buffer);

	//Wait for 3 bytes to arrive
	while(cSerial->available() < 3);
	for(int i=0; i<3; i++){
		data[i] = cSerial->read();
	}
}

/******* Give an instruction by the serial communication *******/

void CS5490::instruct(int value){
	uint8_t buffer = (instructionByte | (uint8_t)value);
	cSerial->write(buffer);
}

/******* Clears cSerial Buffer *******/
void CS5490::clearSerialBuffer(){
	while (cSerial->available()) cSerial->read();
}

/*
  Function: toDouble
  Transforms a 24 bit number to a double number for easy processing data

  Param:
  data[] => Array with size 3. Each uint8_t is an 8 byte number received from CS5490
  LSBpow => Exponent specified from datasheet of the less significant bit
  MSBoption => Information of most significant bit case. It can be only three values:
    MSBnull (1)  The MSB is a Don't Care bit
    MSBsigned (2) the MSB is a negative value, requiring a 2 complement conversion
    MSBunsigned (3) The MSB is a positive value, the default case.

	https://repl.it/@tiagolobao/toDouble-CS5490
*/
double CS5490::toDouble(int LSBpow, int MSBoption){

	uint32_t buffer = 0;
	double output = 0.0;
	bool MSB;

	//Concat bytes in a 32 bit word
	buffer += this->data[0];
	buffer += this->data[1] << 8;
	buffer += this->data[2] << 16;

  switch(MSBoption){

    case MSBnull:
      this->data[2] &= ~(1 << 7); //Clear MSB
      buffer += this->data[2] << 16;
      output = (double)buffer;
      output /= pow(2,LSBpow);
    break;

    case MSBsigned:
      MSB = data[2] & 0x80;
  		if(MSB){  //- (2 complement conversion)
  			buffer = ~buffer;
  			buffer = buffer & 0x00FFFFFF; //Clearing the first 8 bits
  			output = (double)buffer + 1.0;
  			output /= -pow(2,LSBpow);
  		}
  		else{     //+
  		  output = (double)buffer;
  			output /= (pow(2,LSBpow)-1.0);
  		}
    break;

    default:
    case MSBunsigned:
      output = (double)buffer;
  		output /= pow(2,LSBpow);
    break;

  }

	return output;
}

/**************************************************************/
/*              PUBLIC METHODS - Instructions                 */
/**************************************************************/
void CS5490::reset(){
	this->instruct(1);
}

void CS5490::standby(){
	this->instruct(2);
}

void CS5490::wakeUp(){
	this->instruct(3);
}

void CS5490::singConv(){
	this->instruct(20);
}

void CS5490::contConv(){
	this->instruct(21);
}

void CS5490::haltConv(){
	this->instruct(24);
}

/**************************************************************/
/*       PUBLIC METHODS - Calibration and Configuration       */
/**************************************************************/

/* SET */
void CS5490::setBaudRate(long value){

	//Calculate the correct binary value
	uint32_t hexBR = ceil(value*0.5242880/MCLK);
	if (hexBR > 65535) hexBR = 65535;
	hexBR += 0x020000;

	this->write(0x80,0x07,hexBR);
	delay(100); //To avoid bugs from ESP32

	//Reset Serial communication from controller
	cSerial->end();
	cSerial->begin(value);
	delay(50); //Avoid bugs from Arduino MEGA
	return;
}

/* GET */
int CS5490::getGainI(){
	//Page 16, Address 33
	this->read(16,33);
	return this->toDouble(22,MSBunsigned);
}

long CS5490::getBaudRate(){
	this->read(0,7);
	uint32_t buffer = this->data[0];
	buffer += this->data[1] << 8;
	buffer += this->data[2] << 16;
	buffer -= 0x020000;
	return ( (buffer/0.5242880)*MCLK );
}

/**************************************************************/
/*              PUBLIC METHODS - Measurements                 */
/**************************************************************/

double CS5490::getPeakV(){
	//Page 0, Address 36
	this->read(0,36);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getPeakI(){
	//Page 0, Address 37
	this->read(0,37);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstI(){
	//Page 16, Address 2
	this->read(16,2);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstV(){
	//Page 16, Address 3
	this->read(16,3);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstP(){
	//Page 16, Address 4
	this->read(16,4);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getRmsI(){
	//Page 16, Address 6
	this->read(16,6);
	return this->toDouble(24, MSBunsigned);
}

double CS5490::getRmsV(){
	//Page 16, Address 7
	this->read(16,7);
	return this->toDouble(24, MSBunsigned);
}

double CS5490::getAvgP(){
	//Page 16, Address 5
	this->read(16,5);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getAvgQ(){
	//Page 16, Address 14
	this->read(16,14);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getAvgS(){
	//Page 16, Address 20
	this->read(16,20);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstQ(){
	//Page 16, Address 15
	this->read(16,15);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getPF(){
	//Page 16, Address 21
	this->read(16,21);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalP(){
	//Page 16, Address 29
	this->read(16,29);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalS(){
	//Page 16, Address 30
	this->read(16,30);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalQ(){
	//Page 16, Address 31
	this->read(16,31);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getFreq(){
	//Page 16, Address 49
	this->read(16,49);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTime(){
	//Page 16, Address 61
	this->read(16,61);
	return this->toDouble(0, MSBunsigned);
}

/**************************************************************/
/*              PUBLIC METHODS - Read Register                */
/**************************************************************/

long CS5490::readReg(int page, int address){
	uint32_t value = 0;
	this->read(page, address);
	value = value + data[2] << 8;
	value = value + data[1] << 8;
	value = value + data[0];
	return value;
}
<commit_msg>Fixing toDouble when MSBnull<commit_after>/******************************************

	Author: Tiago Britto Lobão
	tiago.blobao@gmail.com
*/

/*
	Purpose: Control an integrated circuit
	Cirrus Logic - CS5490

	Used to measure electrical quantities

	MIT License

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

#include "CS5490.h"

/******* Init CS5490 *******/

//For Arduino & ESP8622
#if !(defined ARDUINO_NodeMCU_32S ) && !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(ARDUINO_Node32s)
	CS5490::CS5490(float mclk, int rx, int tx){
		this->selectedPage = -1;
		this->MCLK = mclk;
		this->cSerial = new SoftwareSerial(rx,tx);
	}
//For ESP32 AND MEGA
#else
	CS5490::CS5490(float mclk){
		this->selectedPage = -1;
		this->MCLK = mclk;
		this->cSerial = &Serial2;
	}
#endif

void CS5490::begin(int baudRate){
	cSerial->begin(baudRate);
	delay(10); //Avoid Bugs on Arduino UNO
}

/**************************************************************/
/*                     PRIVATE METHODS                        */
/**************************************************************/

/******* Write a register by the serial communication *******/
/* data bytes pass by data variable from this class */

void CS5490::write(int page, int address, long value){

	uint8_t checksum = 0;
	for(int i=0; i<3; i++)
		checksum += 0xFF - checksum;

	uint8_t buffer;
	//Select page and address
	if(this->selectedPage != page){
		buffer = (pageByte | (uint8_t)page);
		cSerial->write(buffer);
		this->selectedPage = page;
	}
	buffer = (writeByte | (uint8_t)address);
	cSerial->write(buffer);

	//Send information
	for(int i=0; i<3 ; i++){
		data[i] = value & 0x000000FF;
		cSerial->write(this->data[i]);
		value >>= 8;
	}
	//Calculate and send checksum
	buffer = 0xFF - data[0] - data[1] - data[2];
	cSerial->write(buffer);
}

/******* Read a register by the serial communication *******/
/* data bytes pass by data variable from this class */

void CS5490::read(int page, int address){

	this->clearSerialBuffer();

	uint8_t buffer;
	//Select page and address
	if(this->selectedPage != page){
		buffer = (pageByte | (uint8_t)page);
		cSerial->write(buffer);
		this->selectedPage = page;
	}
	buffer = (readByte | (uint8_t)address);
	cSerial->write(buffer);

	//Wait for 3 bytes to arrive
	while(cSerial->available() < 3);
	for(int i=0; i<3; i++){
		data[i] = cSerial->read();
	}
}

/******* Give an instruction by the serial communication *******/

void CS5490::instruct(int value){
	uint8_t buffer = (instructionByte | (uint8_t)value);
	cSerial->write(buffer);
}

/******* Clears cSerial Buffer *******/
void CS5490::clearSerialBuffer(){
	while (cSerial->available()) cSerial->read();
}

/*
  Function: toDouble
  Transforms a 24 bit number to a double number for easy processing data

  Param:
  data[] => Array with size 3. Each uint8_t is an 8 byte number received from CS5490
  LSBpow => Exponent specified from datasheet of the less significant bit
  MSBoption => Information of most significant bit case. It can be only three values:
    MSBnull (1)  The MSB is a Don't Care bit
    MSBsigned (2) the MSB is a negative value, requiring a 2 complement conversion
    MSBunsigned (3) The MSB is a positive value, the default case.

	https://repl.it/@tiagolobao/toDouble-CS5490
*/
double CS5490::toDouble(int LSBpow, int MSBoption){

	uint32_t buffer = 0;
	double output = 0.0;
	bool MSB;

	//Concat bytes in a 32 bit word
	buffer += this->data[0];
	buffer += this->data[1] << 8;
	buffer += this->data[2] << 16;

  switch(MSBoption){

    case MSBnull:
			buffer &= 0x7FFFFF; //Clear MSB
      output = (double)buffer;
      output /= pow(2,LSBpow);
    break;

    case MSBsigned:
      MSB = data[2] & 0x80;
  		if(MSB){  //- (2 complement conversion)
  			buffer = ~buffer;
  			buffer = buffer & 0x00FFFFFF; //Clearing the first 8 bits
  			output = (double)buffer + 1.0;
  			output /= -pow(2,LSBpow);
  		}
  		else{     //+
  		  output = (double)buffer;
  			output /= (pow(2,LSBpow)-1.0);
  		}
    break;

    default:
    case MSBunsigned:
      output = (double)buffer;
  		output /= pow(2,LSBpow);
    break;

  }

	return output;
}

/**************************************************************/
/*              PUBLIC METHODS - Instructions                 */
/**************************************************************/
void CS5490::reset(){
	this->instruct(1);
}

void CS5490::standby(){
	this->instruct(2);
}

void CS5490::wakeUp(){
	this->instruct(3);
}

void CS5490::singConv(){
	this->instruct(20);
}

void CS5490::contConv(){
	this->instruct(21);
}

void CS5490::haltConv(){
	this->instruct(24);
}

/**************************************************************/
/*       PUBLIC METHODS - Calibration and Configuration       */
/**************************************************************/

/* SET */
void CS5490::setBaudRate(long value){

	//Calculate the correct binary value
	uint32_t hexBR = ceil(value*0.5242880/MCLK);
	if (hexBR > 65535) hexBR = 65535;
	hexBR += 0x020000;

	this->write(0x80,0x07,hexBR);
	delay(100); //To avoid bugs from ESP32

	//Reset Serial communication from controller
	cSerial->end();
	cSerial->begin(value);
	delay(50); //Avoid bugs from Arduino MEGA
	return;
}

/* GET */
int CS5490::getGainI(){
	//Page 16, Address 33
	this->read(16,33);
	return this->toDouble(22,MSBunsigned);
}

long CS5490::getBaudRate(){
	this->read(0,7);
	uint32_t buffer = this->data[0];
	buffer += this->data[1] << 8;
	buffer += this->data[2] << 16;
	buffer -= 0x020000;
	return ( (buffer/0.5242880)*MCLK );
}

/**************************************************************/
/*              PUBLIC METHODS - Measurements                 */
/**************************************************************/

double CS5490::getPeakV(){
	//Page 0, Address 36
	this->read(0,36);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getPeakI(){
	//Page 0, Address 37
	this->read(0,37);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstI(){
	//Page 16, Address 2
	this->read(16,2);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstV(){
	//Page 16, Address 3
	this->read(16,3);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstP(){
	//Page 16, Address 4
	this->read(16,4);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getRmsI(){
	//Page 16, Address 6
	this->read(16,6);
	return this->toDouble(24, MSBunsigned);
}

double CS5490::getRmsV(){
	//Page 16, Address 7
	this->read(16,7);
	return this->toDouble(24, MSBunsigned);
}

double CS5490::getAvgP(){
	//Page 16, Address 5
	this->read(16,5);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getAvgQ(){
	//Page 16, Address 14
	this->read(16,14);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getAvgS(){
	//Page 16, Address 20
	this->read(16,20);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getInstQ(){
	//Page 16, Address 15
	this->read(16,15);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getPF(){
	//Page 16, Address 21
	this->read(16,21);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalP(){
	//Page 16, Address 29
	this->read(16,29);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalS(){
	//Page 16, Address 30
	this->read(16,30);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTotalQ(){
	//Page 16, Address 31
	this->read(16,31);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getFreq(){
	//Page 16, Address 49
	this->read(16,49);
	return this->toDouble(23, MSBsigned);
}

double CS5490::getTime(){
	//Page 16, Address 61
	this->read(16,61);
	return this->toDouble(0, MSBunsigned);
}

/**************************************************************/
/*              PUBLIC METHODS - Read Register                */
/**************************************************************/

long CS5490::readReg(int page, int address){
	uint32_t value = 0;
	this->read(page, address);
	value = value + data[2] << 8;
	value = value + data[1] << 8;
	value = value + data[0];
	return value;
}
<|endoftext|>


<commit_before>/*
 * Canvas.hpp
 *
 *  Created on: Oct 14, 2014
 *      Author: Carsten Uphoff (uphoff@mytum.de)
 */
#ifndef HPLOTLIB_CANVAS_HPP
#define HPLOTLIB_CANVAS_HPP

#include <vector>
#include <string>
#include <queue>

#include "AbstractPlotter.hpp"
#include "Geometry.hpp"
#include "Layout.hpp"
#include "PostscriptPrinter.hpp"
#include "Registry.hpp"

namespace hpl
{
class Canvas {
public:
    Canvas();
	~Canvas();

	void addCoordinateSystemToLayout(CoordinateSystem::ID cs, Layout::ID to) { addSlotToLayout(Slot(cs), to); }
	void addLayoutToLayout(Layout::ID layout, Layout::ID to) { addSlotToLayout(Slot(layout), to); }

	template<typename T>
	T& addLayout() {
		T* layout = new T;
		Layout::ID id = layouts.add(layout);
		layout->changed.template bind<Canvas, &Canvas::recalculateLayout>(this);
		return *layout;
	}

	template<typename T>
    T& addCoordinateSystem();

    inline void connectToPlotter(AbstractPlotter* plotter) {
        plotter->setPlots(&rawData, &dataRevisions);
        connectedPlotters.push_back(plotter);
    }

private:
	struct Slot {
        Slot(Layout::ID l) : layout(l) {}
		Slot(CoordinateSystem::ID c) : cs(c) {}
		bool operator==(Slot const& other) {
			return layout == other.layout && cs == other.cs;
		}
		void invalidate() {
			layout.invalidate();
			cs.invalidate();
		}
		Layout::ID layout;
		CoordinateSystem::ID cs;
	};
	struct Rack {
		std::vector<Slot> slots;
		std::vector<Geometry> geometries;
	};

	Slot* findSlot(Slot const& slot);
	void addSlotToLayout(Slot const& slot, Layout::ID to);
	void recalculateLayout(Layout::ID layout);

    void processUpdate(Drawable::ID = 0);

	Registry<Layout> layouts;
	Registry<CoordinateSystem> csystems;
	std::queue<CoordinateSystem::ID> csInit;

    Registry<Drawable> rawData;
    std::map<Drawable::ID, unsigned int> dataRevisions;

    std::unordered_map<Layout::ID, Rack, std::hash<Layout::ID::Type>> racks;

    std::vector<AbstractPlotter*> connectedPlotters;
};

template<typename T>
T& Canvas::addCoordinateSystem()
{
    T* cs = new T(rawData, dataRevisions);
    cs->changed.template bind<Canvas, &Canvas::processUpdate>(this);

    //pthread_mutex_lock(&mutex);
    CoordinateSystem::ID id = csystems.add(cs);
    csInit.push(id);
    //pthread_mutex_unlock(&mutex);

    //update();

    return *cs;
}
}

#endif

<commit_msg>Little fix<commit_after>/*
 * Canvas.hpp
 *
 *  Created on: Oct 14, 2014
 *      Author: Carsten Uphoff (uphoff@mytum.de)
 */
#ifndef HPLOTLIB_CANVAS_HPP
#define HPLOTLIB_CANVAS_HPP

#include <vector>
#include <string>
#include <queue>

#include "AbstractPlotter.hpp"
#include "Geometry.hpp"
#include "Layout.hpp"
#include "PostscriptPrinter.hpp"
#include "Registry.hpp"

namespace hpl
{
class Canvas {
public:
    Canvas();
	~Canvas();

	void addCoordinateSystemToLayout(CoordinateSystem::ID cs, Layout::ID to) { addSlotToLayout(Slot(cs), to); }
	void addLayoutToLayout(Layout::ID layout, Layout::ID to) { addSlotToLayout(Slot(layout), to); }

	template<typename T>
	T& addLayout() {
		T* layout = new T;
		Layout::ID id = layouts.add(layout);
		layout->changed.template bind<Canvas, &Canvas::recalculateLayout>(this);
		return *layout;
	}

	template<typename T>
    T& addCoordinateSystem();

    inline void connectToPlotter(AbstractPlotter* plotter) {
        plotter->setPlots(&rawData, &dataRevisions);
        connectedPlotters.push_back(plotter);
    }

private:
	struct Slot {
        Slot(Layout::ID l) : layout(l) {}
		Slot(CoordinateSystem::ID c) : cs(c) {}
		bool operator==(Slot const& other) {
			return layout == other.layout && cs == other.cs;
		}
		void invalidate() {
			layout.invalidate();
			cs.invalidate();
		}
		Layout::ID layout;
		CoordinateSystem::ID cs;
	};
	struct Rack {
		std::vector<Slot> slots;
		std::vector<Geometry> geometries;
	};

	Slot* findSlot(Slot const& slot);
	void addSlotToLayout(Slot const& slot, Layout::ID to);
	void recalculateLayout(Layout::ID layout);

    void processUpdate(Drawable::ID = Drawable::ID());

	Registry<Layout> layouts;
	Registry<CoordinateSystem> csystems;
	std::queue<CoordinateSystem::ID> csInit;

    Registry<Drawable> rawData;
    std::map<Drawable::ID, unsigned int> dataRevisions;

    std::unordered_map<Layout::ID, Rack, std::hash<Layout::ID::Type>> racks;

    std::vector<AbstractPlotter*> connectedPlotters;
};

template<typename T>
T& Canvas::addCoordinateSystem()
{
    T* cs = new T(rawData, dataRevisions);
    cs->changed.template bind<Canvas, &Canvas::processUpdate>(this);

    //pthread_mutex_lock(&mutex);
    CoordinateSystem::ID id = csystems.add(cs);
    csInit.push(id);
    //pthread_mutex_unlock(&mutex);

    //update();

    return *cs;
}
}

#endif

<|endoftext|>


<commit_before>/* Copyright 2016 Streampunk Media Ltd

  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.
*/

/* -LICENSE-START-
 ** Copyright (c) 2010 Blackmagic Design
 **
 ** Permission is hereby granted, free of charge, to any person or organization
 ** obtaining a copy of the software and accompanying documentation covered by
 ** this license (the "Software") to use, reproduce, display, distribute,
 ** execute, and transmit the Software, and to prepare derivative works of the
 ** Software, and to permit third-parties to whom the Software is furnished to
 ** do so, all subject to the following:
 **
 ** The copyright notices in the Software and this entire statement, including
 ** the above license grant, this restriction and the following disclaimer,
 ** must be included in all copies of the Software, in whole or in part, and
 ** all derivative works of the Software, unless such copies or derivative
 ** works are solely in the form of machine-executable object code generated by
 ** a source language processor.
 **
 ** 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ** DEALINGS IN THE SOFTWARE.
 ** -LICENSE-END-
 */

#include "Capture.h"

namespace streampunk {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;
using v8::EscapableHandleScope;
using v8::HandleScope;
using v8::Exception;

Persistent<Function> Capture::constructor;

Capture::Capture(uint32_t deviceIndex, uint32_t displayMode,
    uint32_t pixelFormat) : deviceIndex_(deviceIndex),
    displayMode_(displayMode), pixelFormat_(pixelFormat), latestFrame_(NULL) {
  async = new uv_async_t;
  uv_async_init(uv_default_loop(), async, FrameCallback);
  async->data = this;
}

Capture::~Capture() {
  if (!captureCB_.IsEmpty())
    captureCB_.Reset();
}

void Capture::Init(Local<Object> exports) {
  Isolate* isolate = exports->GetIsolate();

  #ifdef WIN32
  HRESULT result;
  result = CoInitialize(NULL);
	if (FAILED(result))
	{
		fprintf(stderr, "Initialization of COM failed - result = %08x.\n", result);
	}
  #endif

  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  tpl->SetClassName(String::NewFromUtf8(isolate, "Capture"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "init", BMInit);
  NODE_SET_PROTOTYPE_METHOD(tpl, "doCapture", DoCapture);
  NODE_SET_PROTOTYPE_METHOD(tpl, "stop", StopCapture);

  constructor.Reset(isolate, tpl->GetFunction());
  exports->Set(String::NewFromUtf8(isolate, "Capture"),
               tpl->GetFunction());
}

void Capture::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new Capture(...)`
    double deviceIndex = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
    double displayMode = args[1]->IsUndefined() ? 0 : args[1]->NumberValue();
    double pixelFormat = args[2]->IsUndefined() ? 0 : args[2]->NumberValue();
    Capture* obj = new Capture(deviceIndex, displayMode, pixelFormat);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `Capture(...)`, turn into construct call.
    const int argc = 3;
    Local<Value> argv[argc] = { args[0], args[1], args[2] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

void Capture::BMInit(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  IDeckLinkIterator* deckLinkIterator;
  HRESULT	result;
  IDeckLinkAPIInformation *deckLinkAPIInformation;
  IDeckLink* deckLink;
  #ifdef WIN32
  CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&deckLinkIterator);
  #else
  deckLinkIterator = CreateDeckLinkIteratorInstance();
  #endif
  result = deckLinkIterator->QueryInterface(IID_IDeckLinkAPIInformation, (void**)&deckLinkAPIInformation);
  if (result != S_OK) {
    isolate->ThrowException(Exception::Error(
      String::NewFromUtf8(isolate, "Error connecting to DeckLinkAPI.")));
  }
  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());

  for ( uint32_t x = 0 ; x <= obj->deviceIndex_ ; x++ ) {
    if (deckLinkIterator->Next(&deckLink) != S_OK) {
      args.GetReturnValue().Set(Undefined(isolate));
      return;
    }
  }

  obj->m_deckLink = deckLink;

  IDeckLinkInput *deckLinkInput;
  if (deckLink->QueryInterface(IID_IDeckLinkInput, (void **)&deckLinkInput) != S_OK)
	{
    isolate->ThrowException(Exception::Error(
      String::NewFromUtf8(isolate, "Could not obtain the DeckLink Input interface.")));
	}
  obj->m_deckLinkInput = deckLinkInput;
  if (deckLinkInput)
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "made it!"));
  else
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "sad :-("));
}

void Capture::DoCapture(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  Local<Function> cb = Local<Function>::Cast(args[0]);
  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());
  obj->captureCB_.Reset(isolate, cb);

  obj->setupDeckLinkInput();

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Capture started."));
}

void Capture::StopCapture(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();

  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());

  obj->cleanupDeckLinkInput();

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Capture stopped."));
}

// Stop video input
void Capture::cleanupDeckLinkInput()
{
	m_deckLinkInput->StopStreams();
	m_deckLinkInput->DisableVideoInput();
	m_deckLinkInput->SetCallback(NULL);
}

bool Capture::setupDeckLinkInput() {
  // bool result = false;
  IDeckLinkDisplayModeIterator*	displayModeIterator = NULL;
  IDeckLinkDisplayMode*			deckLinkDisplayMode = NULL;

  m_width = -1;

  // get frame scale and duration for the video mode
  if (m_deckLinkInput->GetDisplayModeIterator(&displayModeIterator) != S_OK)
    return false;

  while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK)
  {
    if (deckLinkDisplayMode->GetDisplayMode() == displayMode_)
    {
      m_width = deckLinkDisplayMode->GetWidth();
      m_height = deckLinkDisplayMode->GetHeight();
      deckLinkDisplayMode->GetFrameRate(&m_frameDuration, &m_timeScale);
      deckLinkDisplayMode->Release();

      break;
    }

    deckLinkDisplayMode->Release();
  }

  printf("Width %li Height %li\n", m_width, m_height);

  displayModeIterator->Release();

  if (m_width == -1)
    return false;

  m_deckLinkInput->SetCallback(this);

  if (m_deckLinkInput->EnableVideoInput((BMDDisplayMode) displayMode_, (BMDPixelFormat) pixelFormat_, bmdVideoInputFlagDefault) != S_OK)
	  return false;

  if (m_deckLinkInput->StartStreams() != S_OK)
    return false;

  return true;
}

HRESULT	Capture::VideoInputFrameArrived (IDeckLinkVideoInputFrame* arrivedFrame, IDeckLinkAudioInputPacket*)
{
  arrivedFrame->AddRef();
  latestFrame_ = arrivedFrame;
  uv_async_send(async);
  return S_OK;
}

HRESULT	Capture::VideoInputFormatChanged (BMDVideoInputFormatChangedEvents notificationEvents, IDeckLinkDisplayMode* newDisplayMode, BMDDetectedVideoInputFormatFlags detectedSignalFlags) {
  return S_OK;
};

void Capture::TestUV() {
  uv_async_send(async);
}

// void FreeCallback(char* data, void* hint) {
//   Isolate* isolate = v8::Isolate::GetCurrent();
//   IDeckLinkVideoInputFrame* frame = static_cast<IDeckLinkVideoInputFrame*>(hint);
//   isolate->AdjustAmountOfExternalAllocatedMemory(-(frame->GetRowBytes() * frame->GetHeight()));
//   frame->Release();
// }

void Capture::FrameCallback(uv_async_t *handle) {
  Isolate* isolate = v8::Isolate::GetCurrent();
  HandleScope scope(isolate);
  Capture *capture = static_cast<Capture*>(handle->data);
  Local<Function> cb = Local<Function>::New(isolate, capture->captureCB_);
  char* new_data;
  capture->latestFrame_->GetBytes((void**) &new_data);
  long new_data_size = capture->latestFrame_->GetRowBytes() * capture->latestFrame_->GetHeight();
  // Local<Object> b = node::Buffer::New(isolate, new_data, new_data_size,
  //   FreeCallback, capture->latestFrame_).ToLocalChecked();
  Local<Object> b = node::Buffer::Copy(isolate, new_data, new_data_size).ToLocalChecked();
  capture->latestFrame_->Release();
  // long extSize = isolate->AdjustAmountOfExternalAllocatedMemory(new_data_size);
  // if (extSize > 100000000) {
  //   isolate->LowMemoryNotification();
  //   printf("Requesting bin collection.\n");
  // }
  Local<Value> argv[1] = { b };
  cb->Call(Null(isolate), 1, argv);
}

}
<commit_msg>Comment at the line where the seg fault happens.<commit_after>/* Copyright 2016 Streampunk Media Ltd

  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.
*/

/* -LICENSE-START-
 ** Copyright (c) 2010 Blackmagic Design
 **
 ** Permission is hereby granted, free of charge, to any person or organization
 ** obtaining a copy of the software and accompanying documentation covered by
 ** this license (the "Software") to use, reproduce, display, distribute,
 ** execute, and transmit the Software, and to prepare derivative works of the
 ** Software, and to permit third-parties to whom the Software is furnished to
 ** do so, all subject to the following:
 **
 ** The copyright notices in the Software and this entire statement, including
 ** the above license grant, this restriction and the following disclaimer,
 ** must be included in all copies of the Software, in whole or in part, and
 ** all derivative works of the Software, unless such copies or derivative
 ** works are solely in the form of machine-executable object code generated by
 ** a source language processor.
 **
 ** 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ** DEALINGS IN THE SOFTWARE.
 ** -LICENSE-END-
 */

#include "Capture.h"

namespace streampunk {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;
using v8::EscapableHandleScope;
using v8::HandleScope;
using v8::Exception;

Persistent<Function> Capture::constructor;

Capture::Capture(uint32_t deviceIndex, uint32_t displayMode,
    uint32_t pixelFormat) : deviceIndex_(deviceIndex),
    displayMode_(displayMode), pixelFormat_(pixelFormat), latestFrame_(NULL) {
  async = new uv_async_t;
  uv_async_init(uv_default_loop(), async, FrameCallback);
  async->data = this;
}

Capture::~Capture() {
  if (!captureCB_.IsEmpty())
    captureCB_.Reset();
}

void Capture::Init(Local<Object> exports) {
  Isolate* isolate = exports->GetIsolate();

  #ifdef WIN32
  HRESULT result;
  result = CoInitialize(NULL);
	if (FAILED(result))
	{
		fprintf(stderr, "Initialization of COM failed - result = %08x.\n", result);
	}
  #endif

  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  tpl->SetClassName(String::NewFromUtf8(isolate, "Capture"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "init", BMInit);
  NODE_SET_PROTOTYPE_METHOD(tpl, "doCapture", DoCapture);
  NODE_SET_PROTOTYPE_METHOD(tpl, "stop", StopCapture);

  constructor.Reset(isolate, tpl->GetFunction());
  exports->Set(String::NewFromUtf8(isolate, "Capture"),
               tpl->GetFunction());
}

void Capture::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new Capture(...)`
    double deviceIndex = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
    double displayMode = args[1]->IsUndefined() ? 0 : args[1]->NumberValue();
    double pixelFormat = args[2]->IsUndefined() ? 0 : args[2]->NumberValue();
    Capture* obj = new Capture(deviceIndex, displayMode, pixelFormat);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `Capture(...)`, turn into construct call.
    const int argc = 3;
    Local<Value> argv[argc] = { args[0], args[1], args[2] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

void Capture::BMInit(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  IDeckLinkIterator* deckLinkIterator;
  HRESULT	result;
  IDeckLinkAPIInformation *deckLinkAPIInformation;
  IDeckLink* deckLink;
  #ifdef WIN32
  CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&deckLinkIterator);
  #else
  deckLinkIterator = CreateDeckLinkIteratorInstance();
  #endif
  result = deckLinkIterator->QueryInterface(IID_IDeckLinkAPIInformation, (void**)&deckLinkAPIInformation);
  if (result != S_OK) {
    isolate->ThrowException(Exception::Error(
      String::NewFromUtf8(isolate, "Error connecting to DeckLinkAPI.")));
  }
  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());

  for ( uint32_t x = 0 ; x <= obj->deviceIndex_ ; x++ ) {
    if (deckLinkIterator->Next(&deckLink) != S_OK) {
      args.GetReturnValue().Set(Undefined(isolate));
      return;
    }
  }

  obj->m_deckLink = deckLink;

  IDeckLinkInput *deckLinkInput;
  if (deckLink->QueryInterface(IID_IDeckLinkInput, (void **)&deckLinkInput) != S_OK)
	{
    isolate->ThrowException(Exception::Error(
      String::NewFromUtf8(isolate, "Could not obtain the DeckLink Input interface.")));
	}
  obj->m_deckLinkInput = deckLinkInput;
  if (deckLinkInput)
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "made it!"));
  else
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, "sad :-("));
}

void Capture::DoCapture(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  Local<Function> cb = Local<Function>::Cast(args[0]);
  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());
  obj->captureCB_.Reset(isolate, cb);

  obj->setupDeckLinkInput();

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Capture started."));
}

void Capture::StopCapture(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();

  Capture* obj = ObjectWrap::Unwrap<Capture>(args.Holder());

  obj->cleanupDeckLinkInput();

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Capture stopped."));
}

// Stop video input
void Capture::cleanupDeckLinkInput()
{
	m_deckLinkInput->StopStreams();
	m_deckLinkInput->DisableVideoInput();
	m_deckLinkInput->SetCallback(NULL);
}

bool Capture::setupDeckLinkInput() {
  // bool result = false;
  IDeckLinkDisplayModeIterator*	displayModeIterator = NULL;
  IDeckLinkDisplayMode*			deckLinkDisplayMode = NULL;

  m_width = -1;

  // get frame scale and duration for the video mode
  if (m_deckLinkInput->GetDisplayModeIterator(&displayModeIterator) != S_OK)
    return false;

  while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK)
  {
    if (deckLinkDisplayMode->GetDisplayMode() == displayMode_)
    {
      m_width = deckLinkDisplayMode->GetWidth();
      m_height = deckLinkDisplayMode->GetHeight();
      deckLinkDisplayMode->GetFrameRate(&m_frameDuration, &m_timeScale);
      deckLinkDisplayMode->Release();

      break;
    }

    deckLinkDisplayMode->Release();
  }

  printf("Width %li Height %li\n", m_width, m_height);

  displayModeIterator->Release();

  if (m_width == -1)
    return false;

  m_deckLinkInput->SetCallback(this);

  if (m_deckLinkInput->EnableVideoInput((BMDDisplayMode) displayMode_, (BMDPixelFormat) pixelFormat_, bmdVideoInputFlagDefault) != S_OK)
	  return false;

  if (m_deckLinkInput->StartStreams() != S_OK)
    return false;

  return true;
}

HRESULT	Capture::VideoInputFrameArrived (IDeckLinkVideoInputFrame* arrivedFrame, IDeckLinkAudioInputPacket*)
{
  arrivedFrame->AddRef();
  latestFrame_ = arrivedFrame;
  uv_async_send(async);
  return S_OK;
}

HRESULT	Capture::VideoInputFormatChanged (BMDVideoInputFormatChangedEvents notificationEvents, IDeckLinkDisplayMode* newDisplayMode, BMDDetectedVideoInputFormatFlags detectedSignalFlags) {
  return S_OK;
};

void Capture::TestUV() {
  uv_async_send(async);
}

// void FreeCallback(char* data, void* hint) {
//   Isolate* isolate = v8::Isolate::GetCurrent();
//   IDeckLinkVideoInputFrame* frame = static_cast<IDeckLinkVideoInputFrame*>(hint);
//   isolate->AdjustAmountOfExternalAllocatedMemory(-(frame->GetRowBytes() * frame->GetHeight()));
//   frame->Release();
// }

void Capture::FrameCallback(uv_async_t *handle) {
  Isolate* isolate = v8::Isolate::GetCurrent();
  HandleScope scope(isolate);
  Capture *capture = static_cast<Capture*>(handle->data);
  Local<Function> cb = Local<Function>::New(isolate, capture->captureCB_);
  char* new_data;
  // TODO why does this seg fault
  capture->latestFrame_->GetBytes((void**) &new_data);
  long new_data_size = capture->latestFrame_->GetRowBytes() * capture->latestFrame_->GetHeight();
  // Local<Object> b = node::Buffer::New(isolate, new_data, new_data_size,
  //   FreeCallback, capture->latestFrame_).ToLocalChecked();
  Local<Object> b = node::Buffer::Copy(isolate, new_data, new_data_size).ToLocalChecked();
  capture->latestFrame_->Release();
  // long extSize = isolate->AdjustAmountOfExternalAllocatedMemory(new_data_size);
  // if (extSize > 100000000) {
  //   isolate->LowMemoryNotification();
  //   printf("Requesting bin collection.\n");
  // }
  Local<Value> argv[1] = { b };
  cb->Call(Null(isolate), 1, argv);
}

}
<|endoftext|>