<commit_before>#include "Subsystems/Chassis.h"
#include "Commands/DefaultDrive.h"

Chassis* Chassis::m_pInstance = NULL;

Chassis* Chassis::GetInstance()
{
	if(!m_pInstance) m_pInstance = new Chassis;
	return m_pInstance;
}

Chassis::Chassis() : PIDSubsystem("Chassis", 0.05, 0.01, 0.15)
{
	m_leftMotorFront = new CANTalon(CAN_LEFTMOTORFRONT);
	m_leftMotorRear = new CANTalon(CAN_LEFTMOTORREAR);
	m_rightMotorFront = new CANTalon(CAN_RIGHTMOTORFRONT);
	m_rightMotorRear = new CANTalon(CAN_RIGHTMOTORREAR);
	m_leftMotorFront->SetSensorDirection(false);
	m_rightMotorFront->SetSensorDirection(true);
	m_leftMotorFront->ConfigEncoderCodesPerRev(RATIO_DRIVECODESPERREV);
	m_rightMotorFront->ConfigEncoderCodesPerRev(RATIO_DRIVECODESPERREV);

	m_drive = new RobotDrive(m_leftMotorFront, m_leftMotorRear, m_rightMotorFront, m_rightMotorRear);
	m_drive->SetSafetyEnabled(false);
	m_shifter = new Solenoid(CAN_PNMMODULE, PNM_GEARSHIFTER);
	m_bShiftedLow = false;

	try{
		//Connect to navX Gyro on MXP port.
		m_navX = new AHRS(SPI::Port::kMXP);
		m_bNavXPresent = true;
	} catch (std::exception ex){
		//If connection fails log the error and fall back to encoder based angle handling.
		std::string str_error = "Error instantiating navX from MXP: ";
		str_error += ex.what();
		DriverStation::ReportError(str_error.c_str());
		m_bNavXPresent = false;
	}

	LiveWindow::GetInstance()->AddActuator("Chassis", "Left Front TalonSRX", m_leftMotorFront);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Left Rear TalonSRX", m_leftMotorRear);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Right Front TalonSRX", m_rightMotorFront);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Right Rear TalonSRX", m_rightMotorRear);

	LiveWindow::GetInstance()->AddSensor("Chassis", "NavX", m_navX);

	m_onPID = false;
	m_onGyro = false;
	moveSpeed = 0;
	prevAbsBias = 0;
}

void Chassis::InitDefaultCommand()
{
	// Set the default command for a subsystem here.
	SetDefaultCommand(new DefaultDrive());
}

//Arcade Drives with the values of move as the forward value, and turn as the turning value
void Chassis::Drive(double moveL, double moveR, bool quad)
{
	m_drive->TankDrive(moveL, moveR, quad);
}

void Chassis::DriveArcade(double move, double turn, bool squaredInputs)
{

	m_drive->ArcadeDrive(move, turn, squaredInputs);
}

void Chassis::Shift(bool shiftDown)
{
	m_shifter->Set(shiftDown);
	m_bShiftedLow = shiftDown;
}

double Chassis::GetSpeedL()
{
	return m_leftMotorFront->GetSpeed() * InchesPerRev / 50.0;
}

double Chassis::GetSpeedR()
{
	return m_rightMotorFront->GetSpeed() * InchesPerRev / 50.0;
}

double Chassis::GetSpeed()
{
	return ( GetSpeedL() + GetSpeedR() ) / 2.0;
}

double Chassis::GetDistanceL()
{
	return m_leftMotorFront->GetPosition() * InchesPerRev;
}

double Chassis::GetDistanceR()
{
	return m_rightMotorFront->GetPosition() * InchesPerRev;
}

double Chassis::GetDistance()
{
	return ( GetDistanceL() + GetDistanceR() ) / 2.0;
}

double Chassis::GetAngle(bool forceGyro)
{
	if((m_onGyro || forceGyro) && m_bNavXPresent)
	//if(m_bNavXPresent)									//Always gyro unless not present
	{
		//Angle use wants a faster, more accurate, but drifting angle, for quick use.
		return -m_navX->GetAngle();
	}
	else {
		//Means that angle use wants a driftless angle measure that lasts.
		return ( GetDistanceR() - GetDistanceL() ) * 180 / (Preferences::GetInstance()->GetDouble("ChassisWidth",28.55) * M_PI);
		/*
		 *  Angle is 180 degrees times encoder difference over Pi * the distance between the wheels
		 *	Made from geometry and relation between angle fraction and arc fraction with semicircles.
		 */
	}
}

double Chassis::ReturnPIDInput()
{
	return GetAngle();
}

void Chassis::UsePIDOutput(double bias)
{
	// Chassis ramp rate is the limit on the voltage change per cycle to prevent skidding.
	const double speedLimit = prevAbsBias + Preferences::GetInstance()->GetDouble("ChassisRampRate", 0.25);
	if(bias >  speedLimit) bias = speedLimit;
	if(bias < -speedLimit) bias = -speedLimit;
	double speed_L = moveSpeed-bias;
	double speed_R = moveSpeed+bias;
	m_drive->TankDrive(speed_L, speed_R, false);
	prevAbsBias = fabs(bias);
}

void Chassis::ReleaseAngle()
{
	GetPIDController()->Disable();
	m_onPID=false;
	m_onGyro=false;		//Gyro needs to be explicitly enabled for each PID turn
	prevAbsBias=0;
}

void Chassis::ResetEncoders()
{
	m_leftMotorFront->SetPosition(0);
	m_rightMotorFront->SetPosition(0);
}

void Chassis::HoldAngle(double angle, bool gyro)
{
	if(!m_onPID) m_onGyro = gyro;		//Prevent changing angle mode when already in a turn
	SetPIDValues();
	GetPIDController()->SetSetpoint(GetAngle() + angle);
	GetPIDController()->Enable();
	m_onPID = true;
}

void Chassis::SetPIDValues()
{
	if(m_bShiftedLow){
		GetPIDController()->SetPID(
				Preferences::GetInstance()->GetDouble("ChassisHighP",0.075),
				Preferences::GetInstance()->GetDouble("ChassisHighI",0.01),
				Preferences::GetInstance()->GetDouble("ChassisHighD",0.09)
		);
	}else{
		GetPIDController()->SetPID(
				Preferences::GetInstance()->GetDouble("ChassisLowP", 0.085),
				Preferences::GetInstance()->GetDouble("ChassisLowI", 0.02),
				Preferences::GetInstance()->GetDouble("ChassisLowD", 0.125)
		);
	}
}
<commit_msg>Made Gyro always be used for angles unless it fails to initialize.<commit_after>#include "Subsystems/Chassis.h"
#include "Commands/DefaultDrive.h"

Chassis* Chassis::m_pInstance = NULL;

Chassis* Chassis::GetInstance()
{
	if(!m_pInstance) m_pInstance = new Chassis;
	return m_pInstance;
}

Chassis::Chassis() : PIDSubsystem("Chassis", 0.05, 0.01, 0.15)
{
	m_leftMotorFront = new CANTalon(CAN_LEFTMOTORFRONT);
	m_leftMotorRear = new CANTalon(CAN_LEFTMOTORREAR);
	m_rightMotorFront = new CANTalon(CAN_RIGHTMOTORFRONT);
	m_rightMotorRear = new CANTalon(CAN_RIGHTMOTORREAR);
	m_leftMotorFront->SetSensorDirection(false);
	m_rightMotorFront->SetSensorDirection(true);
	m_leftMotorFront->ConfigEncoderCodesPerRev(RATIO_DRIVECODESPERREV);
	m_rightMotorFront->ConfigEncoderCodesPerRev(RATIO_DRIVECODESPERREV);

	m_drive = new RobotDrive(m_leftMotorFront, m_leftMotorRear, m_rightMotorFront, m_rightMotorRear);
	m_drive->SetSafetyEnabled(false);
	m_shifter = new Solenoid(CAN_PNMMODULE, PNM_GEARSHIFTER);
	m_bShiftedLow = false;

	try{
		//Connect to navX Gyro on MXP port.
		m_navX = new AHRS(SPI::Port::kMXP);
		m_bNavXPresent = true;
	} catch (std::exception ex){
		//If connection fails log the error and fall back to encoder based angle handling.
		std::string str_error = "Error instantiating navX from MXP: ";
		str_error += ex.what();
		DriverStation::ReportError(str_error.c_str());
		m_bNavXPresent = false;
	}

	LiveWindow::GetInstance()->AddActuator("Chassis", "Left Front TalonSRX", m_leftMotorFront);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Left Rear TalonSRX", m_leftMotorRear);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Right Front TalonSRX", m_rightMotorFront);
	LiveWindow::GetInstance()->AddActuator("Chassis", "Right Rear TalonSRX", m_rightMotorRear);

	LiveWindow::GetInstance()->AddSensor("Chassis", "NavX", m_navX);

	m_onPID = false;
	m_onGyro = false;
	moveSpeed = 0;
	prevAbsBias = 0;
}

void Chassis::InitDefaultCommand()
{
	// Set the default command for a subsystem here.
	SetDefaultCommand(new DefaultDrive());
}

//Arcade Drives with the values of move as the forward value, and turn as the turning value
void Chassis::Drive(double moveL, double moveR, bool quad)
{
	m_drive->TankDrive(moveL, moveR, quad);
}

void Chassis::DriveArcade(double move, double turn, bool squaredInputs)
{

	m_drive->ArcadeDrive(move, turn, squaredInputs);
}

void Chassis::Shift(bool shiftDown)
{
	m_shifter->Set(shiftDown);
	m_bShiftedLow = shiftDown;
}

double Chassis::GetSpeedL()
{
	return m_leftMotorFront->GetSpeed() * InchesPerRev / 50.0;
}

double Chassis::GetSpeedR()
{
	return m_rightMotorFront->GetSpeed() * InchesPerRev / 50.0;
}

double Chassis::GetSpeed()
{
	return ( GetSpeedL() + GetSpeedR() ) / 2.0;
}

double Chassis::GetDistanceL()
{
	return m_leftMotorFront->GetPosition() * InchesPerRev;
}

double Chassis::GetDistanceR()
{
	return m_rightMotorFront->GetPosition() * InchesPerRev;
}

double Chassis::GetDistance()
{
	return ( GetDistanceL() + GetDistanceR() ) / 2.0;
}

double Chassis::GetAngle(bool forceGyro)
{
	//if((m_onGyro || forceGyro) && m_bNavXPresent)
	if(m_bNavXPresent)									//Always gyro unless not present
	{
		//Angle use wants a faster, more accurate, but drifting angle, for quick use.
		return -m_navX->GetAngle();
	}
	else {
		//Means that angle use wants a driftless angle measure that lasts.
		return ( GetDistanceR() - GetDistanceL() ) * 180 / (Preferences::GetInstance()->GetDouble("ChassisWidth",28.55) * M_PI);
		/*
		 *  Angle is 180 degrees times encoder difference over Pi * the distance between the wheels
		 *	Made from geometry and relation between angle fraction and arc fraction with semicircles.
		 */
	}
}

double Chassis::ReturnPIDInput()
{
	return GetAngle();
}

void Chassis::UsePIDOutput(double bias)
{
	// Chassis ramp rate is the limit on the voltage change per cycle to prevent skidding.
	const double speedLimit = prevAbsBias + Preferences::GetInstance()->GetDouble("ChassisRampRate", 0.25);
	if(bias >  speedLimit) bias = speedLimit;
	if(bias < -speedLimit) bias = -speedLimit;
	double speed_L = moveSpeed-bias;
	double speed_R = moveSpeed+bias;
	m_drive->TankDrive(speed_L, speed_R, false);
	prevAbsBias = fabs(bias);
}

void Chassis::ReleaseAngle()
{
	GetPIDController()->Disable();
	m_onPID=false;
	m_onGyro=false;		//Gyro needs to be explicitly enabled for each PID turn
	prevAbsBias=0;
}

void Chassis::ResetEncoders()
{
	m_leftMotorFront->SetPosition(0);
	m_rightMotorFront->SetPosition(0);
}

void Chassis::HoldAngle(double angle, bool gyro)
{
	if(!m_onPID) m_onGyro = gyro;		//Prevent changing angle mode when already in a turn
	SetPIDValues();
	GetPIDController()->SetSetpoint(GetAngle() + angle);
	GetPIDController()->Enable();
	m_onPID = true;
}

void Chassis::SetPIDValues()
{
	if(m_bShiftedLow){
		GetPIDController()->SetPID(
				Preferences::GetInstance()->GetDouble("ChassisHighP",0.075),
				Preferences::GetInstance()->GetDouble("ChassisHighI",0.01),
				Preferences::GetInstance()->GetDouble("ChassisHighD",0.09)
		);
	}else{
		GetPIDController()->SetPID(
				Preferences::GetInstance()->GetDouble("ChassisLowP", 0.085),
				Preferences::GetInstance()->GetDouble("ChassisLowI", 0.02),
				Preferences::GetInstance()->GetDouble("ChassisLowD", 0.125)
		);
	}
}
<|endoftext|>


<commit_before>/*
 * AliEmcalAnalysisFactory.cxx
 *
 *  Created on: Feb 23, 2016
 *      Author: markus
 */

#include "AliAODTrack.h"
#include "AliESDtrackCuts.h"
#include "AliEmcalTrackSelection.h"
#include "AliEmcalTrackSelectionESD.h"
#include "AliEmcalTrackSelectionAOD.h"
#include "AliEmcalTriggerOfflineSelection.h"
#include "AliEMCalTriggerExtraCuts.h"

#include "AliEmcalAnalysisFactory.h"

ClassImp(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory)

namespace EMCalTriggerPtAnalysis {

AliEmcalTrackSelection *AliEmcalAnalysisFactory::TrackCutsFactory(TString cut, Bool_t aod){
  AliEmcalTrackSelection *result = NULL;
  if(!aod){
    AliESDtrackCuts *esdcuts = NULL;
    if(cut == "standard"){
      AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(true, 1);
      esdcuts->DefineHistograms(kRed);
      esdcuts->SetName("Standard Track cuts");
      esdcuts->SetMinNCrossedRowsTPC(120);
      esdcuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    } else if(cut == "hybrid"){
      esdcuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kFALSE);
      esdcuts->SetName("Global Hybrid tracks, loose DCA");
      esdcuts->SetMaxDCAToVertexXY(2.4);
      esdcuts->SetMaxDCAToVertexZ(3.2);
      esdcuts->SetDCAToVertex2D(kTRUE);
      esdcuts->SetMaxChi2TPCConstrainedGlobal(36);
      esdcuts->SetMaxFractionSharedTPCClusters(0.4);
    }
    result = new AliEmcalTrackSelectionESD;
    result->AddTrackCuts(esdcuts);
  } else {
    AliEmcalTrackSelectionAOD *aodsel = new AliEmcalTrackSelectionAOD;
    result = aodsel;
    if(cut == "standard"){
      aodsel->AddFilterBit(AliAODTrack::kTrkGlobal);
      AliEMCalTriggerExtraCuts *extracuts = new AliEMCalTriggerExtraCuts;
      extracuts->SetMinTPCCrossedRows(120);
      aodsel->AddTrackCuts(extracuts);
    } else if(cut == "hybrid"){
      aodsel->AddFilterBit(256);
      aodsel->AddFilterBit(512);
    }
  }

  return result;
}

AliEmcalTriggerOfflineSelection *AliEmcalAnalysisFactory::TriggerSelectionFactory(Double_t el0, Double_t eg1, Double_t eg2, Double_t ej1, Double_t ej2){
  AliEmcalTriggerOfflineSelection *result = new AliEmcalTriggerOfflineSelection;
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEL0, el0);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEG1, eg1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEG2, eg1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEJ1, ej1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEJ2, ej2);
  return result;
}

} /* namespace EMCalTriggerPtAnalysis */
<commit_msg>Fix missing assignment in the track selection factory<commit_after>/*
 * AliEmcalAnalysisFactory.cxx
 *
 *  Created on: Feb 23, 2016
 *      Author: markus
 */

#include "AliAODTrack.h"
#include "AliESDtrackCuts.h"
#include "AliEmcalTrackSelection.h"
#include "AliEmcalTrackSelectionESD.h"
#include "AliEmcalTrackSelectionAOD.h"
#include "AliEmcalTriggerOfflineSelection.h"
#include "AliEMCalTriggerExtraCuts.h"

#include "AliEmcalAnalysisFactory.h"

ClassImp(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory)

namespace EMCalTriggerPtAnalysis {

AliEmcalTrackSelection *AliEmcalAnalysisFactory::TrackCutsFactory(TString cut, Bool_t aod){
  AliEmcalTrackSelection *result = NULL;
  if(!aod){
    AliESDtrackCuts *esdcuts = NULL;
    if(cut == "standard"){
      esdcuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(true, 1);
      esdcuts->DefineHistograms(kRed);
      esdcuts->SetName("Standard Track cuts");
      esdcuts->SetMinNCrossedRowsTPC(120);
      esdcuts->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
    } else if(cut == "hybrid"){
      esdcuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kFALSE);
      esdcuts->SetName("Global Hybrid tracks, loose DCA");
      esdcuts->SetMaxDCAToVertexXY(2.4);
      esdcuts->SetMaxDCAToVertexZ(3.2);
      esdcuts->SetDCAToVertex2D(kTRUE);
      esdcuts->SetMaxChi2TPCConstrainedGlobal(36);
      esdcuts->SetMaxFractionSharedTPCClusters(0.4);
    }
    result = new AliEmcalTrackSelectionESD;
    result->AddTrackCuts(esdcuts);
  } else {
    AliEmcalTrackSelectionAOD *aodsel = new AliEmcalTrackSelectionAOD;
    result = aodsel;
    if(cut == "standard"){
      aodsel->AddFilterBit(AliAODTrack::kTrkGlobal);
      AliEMCalTriggerExtraCuts *extracuts = new AliEMCalTriggerExtraCuts;
      extracuts->SetMinTPCCrossedRows(120);
      aodsel->AddTrackCuts(extracuts);
    } else if(cut == "hybrid"){
      aodsel->AddFilterBit(256);
      aodsel->AddFilterBit(512);
    }
  }

  return result;
}

AliEmcalTriggerOfflineSelection *AliEmcalAnalysisFactory::TriggerSelectionFactory(Double_t el0, Double_t eg1, Double_t eg2, Double_t ej1, Double_t ej2){
  AliEmcalTriggerOfflineSelection *result = new AliEmcalTriggerOfflineSelection;
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEL0, el0);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEG1, eg1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEG2, eg1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEJ1, ej1);
  result->SetOfflineEnergyThreshold(AliEmcalTriggerOfflineSelection::kTrgEJ2, ej2);
  return result;
}

} /* namespace EMCalTriggerPtAnalysis */
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThreadList class header
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_

#include "distortos/internal/scheduler/ThreadListNode.hpp"

#include "estd/SortedIntrusiveList.hpp"

namespace distortos
{

namespace internal
{

class ThreadControlBlock;

/// functor which gives descending effective priority order of elements on the list
struct ThreadDescendingEffectivePriority
{
	/**
	 * \brief ThreadDescendingEffectivePriority's constructor
	 */

	constexpr ThreadDescendingEffectivePriority()
	{

	}

	/**
	 * \brief ThreadDescendingEffectivePriority's function call operator
	 *
	 * \param [in] left is the object on the left-hand side of comparison
	 * \param [in] right is the object on the right-hand side of comparison
	 *
	 * \return true if left's effective priority is less than right's effective priority
	 */

	bool operator()(const ThreadListNode& left, const ThreadListNode& right) const
	{
		return left.getEffectivePriority() < right.getEffectivePriority();
	}
};

/// sorted intrusive list of threads (thread control blocks)
class ThreadList : public estd::SortedIntrusiveList<ThreadDescendingEffectivePriority, ThreadListNode,
		&ThreadListNode::threadListNode, ThreadControlBlock>
{

};

}	// namespace internal

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
<commit_msg>Add constructor to ThreadList<commit_after>/**
 * \file
 * \brief ThreadList class header
 *
 * \author Copyright (C) 2014-2018 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_

#include "distortos/internal/scheduler/ThreadListNode.hpp"

#include "estd/SortedIntrusiveList.hpp"

namespace distortos
{

namespace internal
{

class ThreadControlBlock;

/// functor which gives descending effective priority order of elements on the list
struct ThreadDescendingEffectivePriority
{
	/**
	 * \brief ThreadDescendingEffectivePriority's constructor
	 */

	constexpr ThreadDescendingEffectivePriority()
	{

	}

	/**
	 * \brief ThreadDescendingEffectivePriority's function call operator
	 *
	 * \param [in] left is the object on the left-hand side of comparison
	 * \param [in] right is the object on the right-hand side of comparison
	 *
	 * \return true if left's effective priority is less than right's effective priority
	 */

	bool operator()(const ThreadListNode& left, const ThreadListNode& right) const
	{
		return left.getEffectivePriority() < right.getEffectivePriority();
	}
};

/// sorted intrusive list of threads (thread control blocks)
class ThreadList : public estd::SortedIntrusiveList<ThreadDescendingEffectivePriority, ThreadListNode,
		&ThreadListNode::threadListNode, ThreadControlBlock>
{
public:

	/**
	 * \brief ThreadList's constructor
	 */

	constexpr ThreadList() :
			SortedIntrusiveList{}
	{

	}
};

}	// namespace internal

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADLIST_HPP_
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Magnus Jonsson
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED

#include <map>
#include <utility>

#include <boost/shared_ptr.hpp>

#include "libtorrent/resource_request.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp"

namespace libtorrent
{

	int saturated_add(int a, int b);

	namespace aux
	{
		// give num_resources to r,
		// return how how many were actually accepted.
		inline int give(resource_request& r, int num_resources)
		{
			assert(num_resources >= 0);
			assert(r.given <= r.max);

			int accepted = std::min(num_resources, r.max - r.given);
			assert(accepted >= 0);

			r.given += accepted;
			assert(r.given <= r.max);

			return accepted;
		}

#ifndef NDEBUG

		template<class It, class T>
		class allocate_resources_contract_check
		{
			int m_resources;
			It m_start;
			It m_end;
			resource_request T::* m_res;

		public:
			allocate_resources_contract_check(
				int resources
				, It start
				, It end
				, resource_request T::* res)
				: m_resources(resources)
				, m_start(start)
				, m_end(end)
				, m_res(res)
			{
				assert(m_resources >= 0);
				for (It i = m_start, end(m_end); i != end; ++i)
				{
					assert(((*i).*m_res).max >= 0);
					assert(((*i).*m_res).given >= 0);
				}
			}

			~allocate_resources_contract_check()
			{
				int sum_given = 0;
				int sum_max = 0;
				int sum_min = 0;
				for (It i = m_start, end(m_end); i != end; ++i)
				{
					assert(((*i).*m_res).max >= 0);
					assert(((*i).*m_res).min >= 0);
					assert(((*i).*m_res).max >= ((*i).*m_res).min);
					assert(((*i).*m_res).given >= 0);
					assert(((*i).*m_res).given <= ((*i).*m_res).max);

					sum_given = saturated_add(sum_given, ((*i).*m_res).given);
					sum_max = saturated_add(sum_max, ((*i).*m_res).max);
					sum_min = saturated_add(sum_min, ((*i).*m_res).min);
				}
				assert(sum_given == std::min(std::max(m_resources, sum_min), sum_max));
			}
		};

#endif

		template<class It, class T>
		void allocate_resources_impl(
			int resources
			, It start
			, It end
			, resource_request T::* res)
		{
			assert(resources >= 0);
	#ifndef NDEBUG
			allocate_resources_contract_check<It, T> contract_check(
				resources
				, start
				, end
				, res);
	#endif

			if (resources == resource_request::inf)
			{
				// No competition for resources.
				// Just give everyone what they want.
				for (It i = start; i != end; ++i)
				{
					((*i).*res).given = ((*i).*res).max;
				}
				return;
			}

			// Resources are scarce

			int sum_max = 0;
			int sum_min = 0;
			for (It i = start; i != end; ++i)
			{
				sum_max = saturated_add(sum_max, ((*i).*res).max);
				assert(((*i).*res).min < resource_request::inf);
				assert(((*i).*res).min >= 0);
				assert(((*i).*res).min <= ((*i).*res).max);
				sum_min += ((*i).*res).min;
				((*i).*res).given = ((*i).*res).min;
			}

			if (resources == 0 || sum_max == 0)
				return;

			resources = std::max(resources, sum_min);
			int resources_to_distribute = std::min(resources, sum_max) - sum_min;
			assert(resources_to_distribute >= 0);
#ifndef NDEBUG
			int prev_resources_to_distribute = resources_to_distribute;
#endif
			while (resources_to_distribute > 0)
			{
				size_type total_used = 0;
				size_type max_used = 0;
				for (It i = start; i != end; ++i)
				{
					resource_request& r = (*i).*res;
					if(r.given == r.max) continue;

					assert(r.given < r.max);

					max_used = std::max(max_used, (size_type)r.used + 1);
					total_used += (size_type)r.used + 1;
				}

				size_type kNumer = resources_to_distribute;
				size_type kDenom = total_used;
				assert(kNumer >= 0);
				assert(kDenom >= 0);
				assert(kNumer <= std::numeric_limits<int>::max());
				assert(total_used < std::numeric_limits<int>::max());

				if (kNumer * max_used <= kDenom)
				{
					kNumer = 1;
					kDenom = max_used;
					assert(kDenom >= 0);
					assert(kDenom <= std::numeric_limits<int>::max());
				}

				for (It i = start; i != end && resources_to_distribute > 0; ++i)
				{
					resource_request& r = (*i).*res;
					if (r.given == r.max) continue;

					assert(r.given < r.max);

					size_type used = (size_type)r.used + 1;
					if (used < 1) used = 1;
					size_type to_give = used * kNumer / kDenom;
					if (to_give > resources_to_distribute)
						to_give = resources_to_distribute;
					assert(to_give >= 0);
					assert(to_give <= resources_to_distribute);
					resources_to_distribute -= give(r, (int)to_give);
					assert(resources_to_distribute >= 0);
				}

				assert(resources_to_distribute >= 0);
				assert(resources_to_distribute < prev_resources_to_distribute);
#ifndef NDEBUG
				prev_resources_to_distribute = resources_to_distribute;
#endif
			}
		}

	} // namespace libtorrent::aux
}

#endif
<commit_msg>added msvc workarounds<commit_after>/*

Copyright (c) 2003, Magnus Jonsson
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED

#include <map>
#include <utility>

#include <boost/shared_ptr.hpp>

#include "libtorrent/resource_request.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp"

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

namespace libtorrent
{

	int saturated_add(int a, int b);

	namespace aux
	{
		// give num_resources to r,
		// return how how many were actually accepted.
		inline int give(resource_request& r, int num_resources)
		{
			assert(num_resources >= 0);
			assert(r.given <= r.max);

			int accepted = (std::min)(num_resources, r.max - r.given);
			assert(accepted >= 0);

			r.given += accepted;
			assert(r.given <= r.max);

			return accepted;
		}

#ifndef NDEBUG

		template<class It, class T>
		class allocate_resources_contract_check
		{
			int m_resources;
			It m_start;
			It m_end;
			resource_request T::* m_res;

		public:
			allocate_resources_contract_check(
				int resources
				, It start
				, It end
				, resource_request T::* res)
				: m_resources(resources)
				, m_start(start)
				, m_end(end)
				, m_res(res)
			{
				assert(m_resources >= 0);
				for (It i = m_start, end(m_end); i != end; ++i)
				{
					assert(((*i).*m_res).max >= 0);
					assert(((*i).*m_res).given >= 0);
				}
			}

			~allocate_resources_contract_check()
			{
				int sum_given = 0;
				int sum_max = 0;
				int sum_min = 0;
				for (It i = m_start, end(m_end); i != end; ++i)
				{
					assert(((*i).*m_res).max >= 0);
					assert(((*i).*m_res).min >= 0);
					assert(((*i).*m_res).max >= ((*i).*m_res).min);
					assert(((*i).*m_res).given >= 0);
					assert(((*i).*m_res).given <= ((*i).*m_res).max);

					sum_given = saturated_add(sum_given, ((*i).*m_res).given);
					sum_max = saturated_add(sum_max, ((*i).*m_res).max);
					sum_min = saturated_add(sum_min, ((*i).*m_res).min);
				}
				assert(sum_given == (std::min)(std::max(m_resources, sum_min), sum_max));
			}
		};

#endif

		template<class It, class T>
		void allocate_resources_impl(
			int resources
			, It start
			, It end
			, resource_request T::* res)
		{
			assert(resources >= 0);
	#ifndef NDEBUG
			allocate_resources_contract_check<It, T> contract_check(
				resources
				, start
				, end
				, res);
	#endif

			if (resources == resource_request::inf)
			{
				// No competition for resources.
				// Just give everyone what they want.
				for (It i = start; i != end; ++i)
				{
					((*i).*res).given = ((*i).*res).max;
				}
				return;
			}

			// Resources are scarce

			int sum_max = 0;
			int sum_min = 0;
			for (It i = start; i != end; ++i)
			{
				sum_max = saturated_add(sum_max, ((*i).*res).max);
				assert(((*i).*res).min < resource_request::inf);
				assert(((*i).*res).min >= 0);
				assert(((*i).*res).min <= ((*i).*res).max);
				sum_min += ((*i).*res).min;
				((*i).*res).given = ((*i).*res).min;
			}

			if (resources == 0 || sum_max == 0)
				return;

			resources = (std::max)(resources, sum_min);
			int resources_to_distribute = (std::min)(resources, sum_max) - sum_min;
			assert(resources_to_distribute >= 0);
#ifndef NDEBUG
			int prev_resources_to_distribute = resources_to_distribute;
#endif
			while (resources_to_distribute > 0)
			{
				size_type total_used = 0;
				size_type max_used = 0;
				for (It i = start; i != end; ++i)
				{
					resource_request& r = (*i).*res;
					if(r.given == r.max) continue;

					assert(r.given < r.max);

					max_used = (std::max)(max_used, (size_type)r.used + 1);
					total_used += (size_type)r.used + 1;
				}

				size_type kNumer = resources_to_distribute;
				size_type kDenom = total_used;
				assert(kNumer >= 0);
				assert(kDenom >= 0);
				assert(kNumer <= (std::numeric_limits<int>::max)());
				assert(total_used < (std::numeric_limits<int>::max)());

				if (kNumer * max_used <= kDenom)
				{
					kNumer = 1;
					kDenom = max_used;
					assert(kDenom >= 0);
					assert(kDenom <= (std::numeric_limits<int>::max)());
				}

				for (It i = start; i != end && resources_to_distribute > 0; ++i)
				{
					resource_request& r = (*i).*res;
					if (r.given == r.max) continue;

					assert(r.given < r.max);

					size_type used = (size_type)r.used + 1;
					if (used < 1) used = 1;
					size_type to_give = used * kNumer / kDenom;
					if (to_give > resources_to_distribute)
						to_give = resources_to_distribute;
					assert(to_give >= 0);
					assert(to_give <= resources_to_distribute);
					resources_to_distribute -= give(r, (int)to_give);
					assert(resources_to_distribute >= 0);
				}

				assert(resources_to_distribute >= 0);
				assert(resources_to_distribute < prev_resources_to_distribute);
#ifndef NDEBUG
				prev_resources_to_distribute = resources_to_distribute;
#endif
			}
		}

	} // namespace libtorrent::aux
}

#endif
<|endoftext|>


<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "Atlas.h"

#include "Math/Geometry/Rectangle.h"

namespace Magnum { namespace TextureTools {

std::vector<Rectanglei> atlas(const Vector2i& atlasSize, const std::vector<Vector2i>& sizes) {
    if(sizes.empty()) return {};

    /* Size of largest texture */
    Vector2i maxSize;
    for(const Vector2i& size: sizes) {
        /** @todo max() for vector types */
        if(size.x() > maxSize.x()) maxSize.x() = size.x();
        if(size.y() > maxSize.y()) maxSize.y() = size.y();
    }

    std::vector<Rectanglei> atlas;

    /* Columns and rows */
    Vector2i gridSize = atlasSize/maxSize;
    if(std::size_t(gridSize.product()) < sizes.size()) {
        Error() << "TextureTools::Atlas::create(): requested atlas size"
                << atlasSize << "is too small to fit" << sizes.size()
                << maxSize << "textures. Generated atlas will be empty.";
        return atlas;
    }

    /** @todo actual magic implementation, not this joke */

    atlas.reserve(sizes.size());
    for(std::size_t i = 0; i != sizes.size(); ++i)
        atlas.push_back(Rectanglei::fromSize(Vector2i(i%gridSize.x(), i/gridSize.x())*maxSize, sizes[i]));

    return atlas;
}

}}
<commit_msg>TextureTools: use Math::max() instead of doing it by hand.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "Atlas.h"

#include "Math/Functions.h"
#include "Math/Geometry/Rectangle.h"

namespace Magnum { namespace TextureTools {

std::vector<Rectanglei> atlas(const Vector2i& atlasSize, const std::vector<Vector2i>& sizes) {
    if(sizes.empty()) return {};

    /* Size of largest texture */
    Vector2i maxSize;
    for(const Vector2i& size: sizes)
        maxSize = Math::max(maxSize, size);

    std::vector<Rectanglei> atlas;

    /* Columns and rows */
    Vector2i gridSize = atlasSize/maxSize;
    if(std::size_t(gridSize.product()) < sizes.size()) {
        Error() << "TextureTools::Atlas::create(): requested atlas size"
                << atlasSize << "is too small to fit" << sizes.size()
                << maxSize << "textures. Generated atlas will be empty.";
        return atlas;
    }

    /** @todo actual magic implementation, not this joke */

    atlas.reserve(sizes.size());
    for(std::size_t i = 0; i != sizes.size(); ++i)
        atlas.push_back(Rectanglei::fromSize(Vector2i(i%gridSize.x(), i/gridSize.x())*maxSize, sizes[i]));

    return atlas;
}

}}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>
    Copyright (C) 2014  David Edmundson <davidedmundson@kde.org>

    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "im-persons-data-source.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Presence>

#include "KTp/contact-factory.h"
#include "KTp/global-contact-manager.h"
#include "KTp/types.h"

#include <KPeople/AllContactsMonitor>
#include <KDE/KABC/Addressee>

#include <KDebug>
#include <KGlobal>
#include <KStandardDirs>
#include <KPluginFactory>
#include <KPluginLoader>

#include <QSqlDatabase>
#include <QSqlQuery>

using namespace KPeople;

class KTpAllContacts : public AllContactsMonitor
{
    Q_OBJECT
public:
    KTpAllContacts();
    ~KTpAllContacts();
    virtual KABC::Addressee::Map contacts();

private Q_SLOTS:
    void loadCache();
    void onAccountManagerReady(Tp::PendingOperation *op);
    void onContactChanged();
    void onContactInvalidated();
    void onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved);

private:
    QString createUri(const KTp::ContactPtr &contact) const;
    KABC::Addressee contactToAddressee(const Tp::ContactPtr &contact) const;
    QHash<QString, KTp::ContactPtr> m_contacts;
    KABC::Addressee::Map m_contactVCards;
};

KTpAllContacts::KTpAllContacts()
{
    Tp::registerTypes();

    QTimer::singleShot(0, this, SLOT(loadCache()));
}

KTpAllContacts::~KTpAllContacts()
{
}

void KTpAllContacts::loadCache()
{
    QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("ktpCache"));
    db.setDatabaseName(KGlobal::dirs()->locateLocal("data", QLatin1String("ktp/cache.db")));
    db.open();

    QSqlQuery query(QLatin1String("SELECT accountId, contactId, alias, avatarFileName FROM contacts"), db);

    query.exec();

    while (query.next()) {
        KABC::Addressee addressee;

        const QString accountId =  query.value(0).toString();
        const QString contactId =  query.value(1).toString();
        addressee.setFormattedName(query.value(2).toString());
        addressee.setPhoto(KABC::Picture(query.value(3).toString()));

        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("contactId"), contactId);
        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("accountPath"), accountId);
        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), QLatin1String("offline"));

        const QString uri = QLatin1String("ktp://") + accountId + QLatin1Char('?') + contactId;

        m_contactVCards[uri] = addressee;
        Q_EMIT contactAdded(uri, addressee);
    }

    //now start fetching the up-to-date information
    connect(KTp::accountManager()->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
        this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));

    emitInitialFetchComplete();
}

QString KTpAllContacts::createUri(const KTp::ContactPtr &contact) const
{
    // so real ID will look like
    // ktp://gabble/jabber/blah/asdfjwer?foo@bar.com
    // ? is used as it is not a valid character in the dbus path that makes up the account UID
    return QLatin1String("ktp://") + contact->accountUniqueIdentifier() + QLatin1Char('?') + contact->id();
}

void KTpAllContacts::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Failed to initialize AccountManager:" << op->errorName();
        kWarning() << op->errorMessage();

        return;
    }

    kDebug() << "Account manager ready";

    connect(KTp::contactManager(), SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(KTp::contactManager()->allKnownContacts(), Tp::Contacts());
}

void KTpAllContacts::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &c, contactsRemoved) {
            const KTp::ContactPtr &contact = KTp::ContactPtr::qObjectCast(c);
            const QString uri = createUri(contact);
            m_contacts.remove(uri);
            m_contactVCards.remove(uri);
            Q_EMIT contactRemoved(uri);
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        KTp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        const QString uri = createUri(ktpContact);

        const KABC::Addressee vcard = contactToAddressee(contact);

        m_contacts.insert(uri, ktpContact);

        //TODO OPTIMISATION if we already exist we shouldn't create a whole new KABC object, just update the existing one
        //onContactChanged should be split into the relevant onAliasChanged etc.
        if (m_contactVCards.contains(uri)) {
            m_contactVCards[uri] = vcard;
            Q_EMIT contactChanged(uri, vcard);
        } else {
            m_contactVCards.insert(uri, vcard);
            Q_EMIT contactAdded(uri, vcard);
        }

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactInvalidated()));

        connect(ktpContact.data(), SIGNAL(avatarDataChanged(Tp::AvatarData)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(addedToGroup(QString)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(removedFromGroup(QString)),
                this, SLOT(onContactChanged()));
    }
}

void KTpAllContacts::onContactChanged()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    m_contactVCards.insert(createUri(contact), contactToAddressee(contact));
    Q_EMIT contactChanged(createUri(contact), contactToAddressee(contact));
}

void KTpAllContacts::onContactInvalidated()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);

    m_contacts.remove(uri);

    //set to offline and emit changed
    KABC::Addressee &vcard = m_contactVCards[uri];
    vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), QLatin1String("offline"));
    Q_EMIT contactChanged(uri, vcard);
}

KABC::Addressee::Map KTpAllContacts::contacts()
{
    return m_contactVCards;
}

KABC::Addressee KTpAllContacts::contactToAddressee(const Tp::ContactPtr &contact) const
{
    KABC::Addressee vcard;
    Tp::AccountPtr account = KTp::contactManager()->accountForContact(contact);
    if (contact && account) {
        vcard.setFormattedName(contact->alias());
        vcard.setCategories(contact->groups());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("contactId"), contact->id());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("accountPath"), account->objectPath());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), contact->presence().status());
        if (!contact->avatarData().fileName.isEmpty()) {
            vcard.setPhoto(KABC::Picture(contact->avatarData().fileName));
        }
    }
    return vcard;
}

IMPersonsDataSource::IMPersonsDataSource(QObject *parent, const QVariantList &args)
    : BasePersonsDataSource(parent)
{
    Q_UNUSED(args);
}

IMPersonsDataSource::~IMPersonsDataSource()
{
}

QString IMPersonsDataSource::sourcePluginId() const
{
    return QLatin1String("ktp");
}

AllContactsMonitor* IMPersonsDataSource::createAllContactsMonitor()
{
    return new KTpAllContacts();
}

K_PLUGIN_FACTORY( IMPersonsDataSourceFactory, registerPlugin<IMPersonsDataSource>(); )
K_EXPORT_PLUGIN( IMPersonsDataSourceFactory("im_persons_data_source_plugin") )

#include "im-persons-data-source.moc"<commit_msg>KPeople plugin: Implemented groups cache support.<commit_after>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>
    Copyright (C) 2014  David Edmundson <davidedmundson@kde.org>

    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "im-persons-data-source.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Presence>

#include "KTp/contact-factory.h"
#include "KTp/global-contact-manager.h"
#include "KTp/types.h"

#include <KPeople/AllContactsMonitor>
#include <KDE/KABC/Addressee>

#include <KDebug>
#include <KGlobal>
#include <KStandardDirs>
#include <KPluginFactory>
#include <KPluginLoader>

#include <QSqlDatabase>
#include <QSqlQuery>

using namespace KPeople;

class KTpAllContacts : public AllContactsMonitor
{
    Q_OBJECT
public:
    KTpAllContacts();
    ~KTpAllContacts();
    virtual KABC::Addressee::Map contacts();

private Q_SLOTS:
    void loadCache();
    void onAccountManagerReady(Tp::PendingOperation *op);
    void onContactChanged();
    void onContactInvalidated();
    void onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved);

private:
    QString createUri(const KTp::ContactPtr &contact) const;
    KABC::Addressee contactToAddressee(const Tp::ContactPtr &contact) const;
    QHash<QString, KTp::ContactPtr> m_contacts;
    KABC::Addressee::Map m_contactVCards;
};

KTpAllContacts::KTpAllContacts()
{
    Tp::registerTypes();

    QTimer::singleShot(0, this, SLOT(loadCache()));
}

KTpAllContacts::~KTpAllContacts()
{
}

void KTpAllContacts::loadCache()
{
    QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("ktpCache"));
    db.setDatabaseName(KGlobal::dirs()->locateLocal("data", QLatin1String("ktp/cache.db")));
    db.open();

    QSqlQuery query(db);
    query.exec(QLatin1String("SELECT groupName FROM groups ORDER BY groupId;"));

    QStringList groupsList;
    while (query.next()) {
        groupsList.append(query.value(0).toString());
    }

    if (!groupsList.isEmpty()) {
        query.exec(QLatin1String("SELECT accountId, contactId, alias, avatarFileName, groupsIds FROM contacts;"));
    } else {
        query.exec(QLatin1String("SELECT accountId, contactId, alias, avatarFileName FROM contacts;"));
    }

    while (query.next()) {
        KABC::Addressee addressee;

        const QString accountId =  query.value(0).toString();
        const QString contactId =  query.value(1).toString();
        addressee.setFormattedName(query.value(2).toString());
        addressee.setPhoto(KABC::Picture(query.value(3).toString()));

        if (!groupsList.isEmpty()) {
            QStringList contactGroups;

            Q_FOREACH (const QString &groupIdStr, query.value(4).toString().split(QLatin1String(","))) {
                bool convSuccess;
                int groupId = groupIdStr.toInt(&convSuccess);
                if ((!convSuccess) || (groupId >= groupsList.count()))
                    continue;

                contactGroups.append(groupsList.at(groupId));
            }

            addressee.setCategories(contactGroups);
        }

        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("contactId"), contactId);
        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("accountPath"), accountId);
        addressee.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), QLatin1String("offline"));

        const QString uri = QLatin1String("ktp://") + accountId + QLatin1Char('?') + contactId;

        m_contactVCards[uri] = addressee;
        Q_EMIT contactAdded(uri, addressee);
    }

    //now start fetching the up-to-date information
    connect(KTp::accountManager()->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
        this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));

    emitInitialFetchComplete();
}

QString KTpAllContacts::createUri(const KTp::ContactPtr &contact) const
{
    // so real ID will look like
    // ktp://gabble/jabber/blah/asdfjwer?foo@bar.com
    // ? is used as it is not a valid character in the dbus path that makes up the account UID
    return QLatin1String("ktp://") + contact->accountUniqueIdentifier() + QLatin1Char('?') + contact->id();
}

void KTpAllContacts::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kWarning() << "Failed to initialize AccountManager:" << op->errorName();
        kWarning() << op->errorMessage();

        return;
    }

    kDebug() << "Account manager ready";

    connect(KTp::contactManager(), SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(KTp::contactManager()->allKnownContacts(), Tp::Contacts());
}

void KTpAllContacts::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &c, contactsRemoved) {
            const KTp::ContactPtr &contact = KTp::ContactPtr::qObjectCast(c);
            const QString uri = createUri(contact);
            m_contacts.remove(uri);
            m_contactVCards.remove(uri);
            Q_EMIT contactRemoved(uri);
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        KTp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        const QString uri = createUri(ktpContact);

        const KABC::Addressee vcard = contactToAddressee(contact);

        m_contacts.insert(uri, ktpContact);

        //TODO OPTIMISATION if we already exist we shouldn't create a whole new KABC object, just update the existing one
        //onContactChanged should be split into the relevant onAliasChanged etc.
        if (m_contactVCards.contains(uri)) {
            m_contactVCards[uri] = vcard;
            Q_EMIT contactChanged(uri, vcard);
        } else {
            m_contactVCards.insert(uri, vcard);
            Q_EMIT contactAdded(uri, vcard);
        }

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactInvalidated()));

        connect(ktpContact.data(), SIGNAL(avatarDataChanged(Tp::AvatarData)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(addedToGroup(QString)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(removedFromGroup(QString)),
                this, SLOT(onContactChanged()));
    }
}

void KTpAllContacts::onContactChanged()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    m_contactVCards.insert(createUri(contact), contactToAddressee(contact));
    Q_EMIT contactChanged(createUri(contact), contactToAddressee(contact));
}

void KTpAllContacts::onContactInvalidated()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);

    m_contacts.remove(uri);

    //set to offline and emit changed
    KABC::Addressee &vcard = m_contactVCards[uri];
    vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), QLatin1String("offline"));
    Q_EMIT contactChanged(uri, vcard);
}

KABC::Addressee::Map KTpAllContacts::contacts()
{
    return m_contactVCards;
}

KABC::Addressee KTpAllContacts::contactToAddressee(const Tp::ContactPtr &contact) const
{
    KABC::Addressee vcard;
    Tp::AccountPtr account = KTp::contactManager()->accountForContact(contact);
    if (contact && account) {
        vcard.setFormattedName(contact->alias());
        vcard.setCategories(contact->groups());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("contactId"), contact->id());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("accountPath"), account->objectPath());
        vcard.insertCustom(QLatin1String("telepathy"), QLatin1String("presence"), contact->presence().status());
        if (!contact->avatarData().fileName.isEmpty()) {
            vcard.setPhoto(KABC::Picture(contact->avatarData().fileName));
        }
    }
    return vcard;
}

IMPersonsDataSource::IMPersonsDataSource(QObject *parent, const QVariantList &args)
    : BasePersonsDataSource(parent)
{
    Q_UNUSED(args);
}

IMPersonsDataSource::~IMPersonsDataSource()
{
}

QString IMPersonsDataSource::sourcePluginId() const
{
    return QLatin1String("ktp");
}

AllContactsMonitor* IMPersonsDataSource::createAllContactsMonitor()
{
    return new KTpAllContacts();
}

K_PLUGIN_FACTORY( IMPersonsDataSourceFactory, registerPlugin<IMPersonsDataSource>(); )
K_EXPORT_PLUGIN( IMPersonsDataSourceFactory("im_persons_data_source_plugin") )

#include "im-persons-data-source.moc"
<|endoftext|>


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

#include "cpu/view.h"

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ppapi/cpp/completion_callback.h>
#include <ppapi/cpp/graphics_2d.h>
#include <ppapi/cpp/image_data.h>
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/instance_handle.h>
#include <ppapi/cpp/point.h>
#include "palette.h"

namespace cpu {

View::View(LockedObject<AlignedUint32>* buffer)
    : factory_(this),
      graphics_2d_(NULL),
      pixel_buffer_(NULL),
      locked_buffer_(buffer),
      draw_loop_running_(false) {
}

View::~View() {
  delete graphics_2d_;
  delete pixel_buffer_;
}

bool View::DidChangeView(pp::Instance* instance,
                             const pp::View& view) {
  pp::Size old_size = GetSize();
  pp::Size new_size = view.GetRect().size();
  if (old_size == new_size)
    return true;

  printf("Size: %d x %d\n", new_size.width(), new_size.height());

  delete graphics_2d_;
  graphics_2d_ = new pp::Graphics2D(instance, new_size,
                                    true);  // is_always_opaque
  if (!instance->BindGraphics(*graphics_2d_)) {
    delete graphics_2d_;
    graphics_2d_ = NULL;
    return false;
  }

  // Create a new pixel buffer, the same size as the graphics context. We'll
  // write to this buffer directly, and copy regions of it to the graphics
  // context's backing store to draw to the screen.
  delete pixel_buffer_;
  pixel_buffer_ = new pp::ImageData(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                                    new_size,
                                    true);  // init_to_zero

  if (!draw_loop_running_) {
    DrawCallback(0);  // Start the draw loop.
    draw_loop_running_ = true;
  }

  return true;
}

pp::Size View::GetSize() const {
  return graphics_2d_ ? graphics_2d_->size() : pp::Size();
}

void View::DrawCallback(int32_t result) {
  if (!graphics_2d_) {
    draw_loop_running_ = false;
    return;
  }
  assert(pixel_buffer_);

  AlignedUint32* data = locked_buffer_->Lock();
  DrawBuffer(*data);
  locked_buffer_->Unlock();

  PaintRectToGraphics2D(pp::Rect(GetSize()));

  // Graphics2D::Flush writes all paints to the graphics context's backing
  // store. When it is finished, it calls the callback. By hooking our draw
  // function to the Flush callback, we will be able to draw as quickly as
  // possible.
  graphics_2d_->Flush(factory_.NewCallback(&View::DrawCallback));
}

void View::PaintRectToGraphics2D(const pp::Rect& rect) {
  const pp::Point top_left(0, 0);
  graphics_2d_->PaintImageData(*pixel_buffer_, top_left, rect);
}

void View::DrawBuffer(const AlignedUint32& a) {
  uint32_t* pixels = static_cast<uint32_t*>(pixel_buffer_->data());
  if (!pixels)
    return;

  double scale;
  int x_offset;
  int y_offset;
  GetScreenToSimScale(a.size(), &scale, &x_offset, &y_offset);

  int image_width = GetSize().width();
  int image_height = GetSize().height();
  int buffer_width = a.size().width();
  double buffer_x = 0;
  double buffer_y = 0;

  for (int y = y_offset; y < image_height - y_offset; ++y) {
    buffer_x = 0;
    for (int x = x_offset; x < image_width - x_offset; ++x) {
      uint32_t v = a[(int)buffer_y * buffer_width + (int)buffer_x];
      pixels[y * image_width + x] = v;
      buffer_x += scale;
    }
    buffer_y += scale;
  }
}

}  // namespace cpu
<commit_msg>clear area around drawn image (bug on mac). It was just drawing garbage.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cpu/view.h"

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ppapi/cpp/completion_callback.h>
#include <ppapi/cpp/graphics_2d.h>
#include <ppapi/cpp/image_data.h>
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/instance_handle.h>
#include <ppapi/cpp/point.h>
#include "palette.h"

namespace cpu {

View::View(LockedObject<AlignedUint32>* buffer)
    : factory_(this),
      graphics_2d_(NULL),
      pixel_buffer_(NULL),
      locked_buffer_(buffer),
      draw_loop_running_(false) {
}

View::~View() {
  delete graphics_2d_;
  delete pixel_buffer_;
}

bool View::DidChangeView(pp::Instance* instance,
                             const pp::View& view) {
  pp::Size old_size = GetSize();
  pp::Size new_size = view.GetRect().size();
  if (old_size == new_size)
    return true;

  printf("Size: %d x %d\n", new_size.width(), new_size.height());

  delete graphics_2d_;
  graphics_2d_ = new pp::Graphics2D(instance, new_size,
                                    true);  // is_always_opaque
  if (!instance->BindGraphics(*graphics_2d_)) {
    delete graphics_2d_;
    graphics_2d_ = NULL;
    return false;
  }

  // Create a new pixel buffer, the same size as the graphics context. We'll
  // write to this buffer directly, and copy regions of it to the graphics
  // context's backing store to draw to the screen.
  delete pixel_buffer_;
  pixel_buffer_ = new pp::ImageData(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                                    new_size,
                                    true);  // init_to_zero

  if (!draw_loop_running_) {
    DrawCallback(0);  // Start the draw loop.
    draw_loop_running_ = true;
  }

  return true;
}

pp::Size View::GetSize() const {
  return graphics_2d_ ? graphics_2d_->size() : pp::Size();
}

void View::DrawCallback(int32_t result) {
  if (!graphics_2d_) {
    draw_loop_running_ = false;
    return;
  }
  assert(pixel_buffer_);

  AlignedUint32* data = locked_buffer_->Lock();
  DrawBuffer(*data);
  locked_buffer_->Unlock();

  PaintRectToGraphics2D(pp::Rect(GetSize()));

  // Graphics2D::Flush writes all paints to the graphics context's backing
  // store. When it is finished, it calls the callback. By hooking our draw
  // function to the Flush callback, we will be able to draw as quickly as
  // possible.
  graphics_2d_->Flush(factory_.NewCallback(&View::DrawCallback));
}

void View::PaintRectToGraphics2D(const pp::Rect& rect) {
  const pp::Point top_left(0, 0);
  graphics_2d_->PaintImageData(*pixel_buffer_, top_left, rect);
}

void View::DrawBuffer(const AlignedUint32& a) {
  uint32_t* pixels = static_cast<uint32_t*>(pixel_buffer_->data());
  if (!pixels)
    return;

  double scale;
  int x_offset;
  int y_offset;
  GetScreenToSimScale(a.size(), &scale, &x_offset, &y_offset);

  int image_width = GetSize().width();
  int image_height = GetSize().height();
  int buffer_width = a.size().width();
  double buffer_x = 0;
  double buffer_y = 0;

  std::fill(pixels, pixels + image_width * image_height, 0xff000000);

  for (int y = y_offset; y < image_height - y_offset; ++y) {
    buffer_x = 0;
    for (int x = x_offset; x < image_width - x_offset; ++x) {
      uint32_t v = a[(int)buffer_y * buffer_width + (int)buffer_x];
      pixels[y * image_width + x] = v;
      buffer_x += scale;
    }
    buffer_y += scale;
  }
}

}  // namespace cpu
<|endoftext|>


<commit_before>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
	#include <SDL.h>
	#include <SDL_thread.h>
	#include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
	#ifndef RUNNINGONINTEL
	#define RUNNINGONINTEL
	#endif
#else
	#ifndef RUNNINGONPI
	#define RUNNINGONPI
	#endif
	#include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

IplImage threadImage1;
bool updatedImage1 = false;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
int cameraHeight;
int cameraWidth;

SDL_Thread* SDLCameraThread;
SDL_Thread* SDLMusicThread;

int quit;

/***********************************************************************
/*							SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
	bool success = true;

	if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
	{
		printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
		success = false;
	} else {
		window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (window == NULL)
		{
			printf("error");
			success = false;
		} else {
			renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
			if (renderer == NULL)
			{
				printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
				success = false;
			} else {
				SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
			}
		}
	}
	return success;
}

bool init_CameraSettings()
{
	bool success = true;
	videoRect.x = 0;
	videoRect.y = 0;
	videoRect.w = 1280;	//640 not actually sure why we have this
	videoRect.h = 720;	//480

	cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
	cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

	printf("Camera Width%d, Camera Height %d \n",cameraWidth,cameraHeight);
	return success;
}

int cameraWorker(void* data)
{
	while (!quit)
	{
		cap >> frame;
		threadImage1 = frame;
		updatedImage1 = true;
	}
	return 0;
}

// Shows an individual frame of the supplied video
int show_Camera(IplImage* img)
{
	if(updatedImage1 == true)
	{
		SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
			img->width,
			img->height,
			img->depth * img->nChannels,
			img->widthStep,
			0xff0000, 0x00ff00, 0x0000ff, 0
			);
		updatedImage1 = false;

		SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
		SDL_FreeSurface(surface);
		surface = NULL;
		SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
		SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
		SDL_DestroyTexture(texture);
		return 1;
	}
		return 0;

}

void processEvents()
{
	SDL_Event event;
 		while (SDL_PollEvent(&event))
 		{
	 		switch(event.type)
	 		{
	 			case SDL_QUIT:
	 				printf("SDL_QUIT was called\n");
	 				signalToQuit();
	 				close();
		 			break;

	 			case SDL_KEYDOWN:
	 				switch(event.key.keysym.sym)
	 				{
				 		case SDLK_ESCAPE:
				 		 	printf("Esc was Pressed!\n");
				 		 	signalToQuit();
				 		 	close();
							break;
						case SDLK_LEFT:
							printf("Left arrow was Pressed!\n");
							previousSong();
							break;
						case SDLK_RIGHT:
							printf("Right arrow was Pressed!\n");
							nextSong();
							break;
						case SDLK_UP:
							changeVolume(0.1);
							break;
						case SDLK_DOWN:
							changeVolume(-0.1);
							break;
						case SDLK_SPACE:
							printf("Space was pressed!\n");
							playPause();
			    	}
	 		}
 		}
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
	quit = true;
	songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
	closeSongPlayer();
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	window = NULL;
	renderer = NULL;
	SDL_Quit();
	exit(0);
}

int main(int argc, char* argv[])
{
	int noSongs;

 	if (!init_SDL()){
 		fprintf(stderr, "Could not initialize SDL!\n");
 		return -1;
 	}
 	if (!cap.isOpened()){
 		fprintf(stderr, "Failed to load file!\n");
 		return -1;
 	}
 	if (!init_CameraSettings()){
 		printf("failed to load settings\n");
 		return -1;
 	}

 	initSongPlayer();
 	noSongs = loadSong((char *)currentSong().c_str());

 	SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
 	if (!noSongs)
 	    SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

	int screenUpdate = 0;

 	while (!quit)
 	{

		screenUpdate = show_Camera(&threadImage1);
		processEvents();
		if (screenUpdate == 1){
			SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
			SDL_RenderPresent(renderer);
			SDL_RenderClear(renderer);
		}
	}

	SDL_WaitThread(SDLCameraThread, NULL);
	if (!noSongs)
	    SDL_WaitThread(SDLMusicThread, NULL);
	return 0;
}
<commit_msg>Changed code to double buffer<commit_after>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
	#include <SDL.h>
	#include <SDL_thread.h>
	#include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
	#ifndef RUNNINGONINTEL
	#define RUNNINGONINTEL
	#endif
#else
	#ifndef RUNNINGONPI
	#define RUNNINGONPI
	#endif
	#include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

//attempting double buffer
IplImage threadImage1;
IplImage threadImage2;
bool updatedImage = false;
int bufferNumber = 1;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
int cameraHeight;
int cameraWidth;
int noSongs;

SDL_Thread* SDLCameraThread;
SDL_Thread* SDLMusicThread;

int quit;

/***********************************************************************
/*							SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
	bool success = true;

	if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
	{
		printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
		success = false;
	} else {
		window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (window == NULL)
		{
			printf("error");
			success = false;
		} else {
			renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
			if (renderer == NULL)
			{
				printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
				success = false;
			} else {
				SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
			}
		}
	}
	return success;
}

bool init_CameraSettings()
{
	bool success = true;
	videoRect.x = 0;
	videoRect.y = 0;
	videoRect.w = 1280;	//640 not actually sure why we have this
	videoRect.h = 720;	//480

	cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
	cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);

	printf("Camera Width%d, Camera Height %d \n",cameraWidth,cameraHeight);
	return success;
}

int cameraWorker(void* data)
{
	while (!quit)
	{
		cap >> frame;
		if(bufferNumber == 1){
			threadImage2 = frame;
			bufferNumber = 2;
		} else {
			threadImage1 = frame;
			bufferNumber = 1;
		}
		updatedImage = true;
	}
	return 0;
}

// Shows an individual frame of the supplied video
int show_Camera()
{
	IplImage* img = NULL;
	if(updatedImage == true)
	{
		updatedImage = false;
		if(bufferNumber == 1){
			 img = &threadImage1;
		} else {
			 img = &threadImage2;
		}
		SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
			img->width,
			img->height,
			img->depth * img->nChannels,
			img->widthStep,
			0xff0000, 0x00ff00, 0x0000ff, 0
			);

		SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
		SDL_FreeSurface(surface);
		surface = NULL;
		SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
		SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
		SDL_DestroyTexture(texture);
		return 1;
	}
		return 0;

}

void processEvents()
{
	SDL_Event event;
 		while (SDL_PollEvent(&event))
 		{
	 		switch(event.type)
	 		{
	 			case SDL_QUIT:
	 				printf("SDL_QUIT was called\n");
	 				signalToQuit();
	 				close();
		 			break;

	 			case SDL_KEYDOWN:
	 				switch(event.key.keysym.sym)
	 				{
				 		case SDLK_ESCAPE:
				 		 	printf("Esc was Pressed!\n");
				 		 	signalToQuit();
				 		 	close();
							break;
						case SDLK_LEFT:
							printf("Left arrow was Pressed!\n");
							previousSong();
							break;
						case SDLK_RIGHT:
							printf("Right arrow was Pressed!\n");
							nextSong();
							break;
						case SDLK_UP:
							changeVolume(0.1);
							break;
						case SDLK_DOWN:
							changeVolume(-0.1);
							break;
						case SDLK_SPACE:
							printf("Space was pressed!\n");
							playPause();
			    	}
	 		}
 		}
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
	quit = true;
	songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
	closeSongPlayer();
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	window = NULL;
	renderer = NULL;
	SDL_Quit();
	exit(0);
}

int main(int argc, char* argv[])
{

 	if (!init_SDL()){
 		fprintf(stderr, "Could not initialize SDL!\n");
 		return -1;
 	}
 	if (!cap.isOpened()){
 		fprintf(stderr, "Failed to load file!\n");
 		return -1;
 	}
 	if (!init_CameraSettings()){
 		printf("failed to load settings\n");
 		return -1;
 	}

 	initSongPlayer();
 	noSongs = loadSong((char *)currentSong().c_str());

 	SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
 	if (!noSongs)
 	    SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

	int screenUpdate = 0;

 	while (!quit)
 	{

		screenUpdate = show_Camera();
		processEvents();
		if (screenUpdate == 1){
			SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
			SDL_RenderPresent(renderer);
			SDL_RenderClear(renderer);
		}
	}

	SDL_WaitThread(SDLCameraThread, NULL);
	if (!noSongs)
	    SDL_WaitThread(SDLMusicThread, NULL);
	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Kyle Isom <kyle@tyrfingr.is>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// This is a test of instructions from http://skilldrick.github.io/easy6502/index.html.
// As this library isn't an assembler, it won't assemble the files; I'm
// to check some of the expected behaviours from the emulator.

#include <iomanip>
#include <iostream>
using namespace std;

#include "cpu.h"

void	test1(void);
void	test2(void);
void	test3(void);
void	test4(void);
void	test5(void);
void	test6(void);

static void
dump_program(const unsigned char *program, size_t len)
{
	size_t	i = 0;
	int	l = 0;
	for (i = 0; i < len; ++i) {
		if (l == 0)
			std::cerr << std::setw(8) << std::hex << i << "| ";
		std::cerr << std::hex << std::setw(2) << std::setfill('0')
			  << (unsigned short)(program[i] & 0xff);
		std::cerr << " ";
		l++;
		if (l == 8) {
			std::cerr << " ";
		} else if (l == 16) {
			std::cerr << std::endl;
			l = 0;
		}
	}
	std::cerr << std::endl;
}

static void
run(const unsigned char *program, size_t size, bool trace)
{
	CPU	cpu(0x400);
	std::cerr << "\nPROGRAM:\n";
	dump_program(program, size);
	std::cerr << std::endl;

	cpu.load(program, 0x300, size);
	cpu.start_pc(0x300);

	cpu.run(trace);
	cpu.dump_memory();
	cpu.dump_registers();
}

void
test1()
{
	std::cerr << "\nStarting test 1\n";
	std::cerr << "\t(First compiled program)\n";

	// test1, compiled as opcodes
	unsigned char	program[] = {0xA9, 0x01, 0x8D, 0x01, 0x00};
	run(program, 5, false);
}

void
test2()
{
	std::cerr << "\nStarting test 2\n";
	std::cerr << "\t(First full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0x01, 0x8d, 0x00, 0x02, 0xa9, 0x05, 0x8d,
		0x01, 0x02, 0xa9, 0x08, 0x8d, 0x02, 0x02, 0x00
	};
	run(program, 15, false);
}

void
test3()
{
	std::cerr << "\nStarting test 3\n";
	std::cerr << "\t(Second full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0xc0, 0xaa, 0xe8, 0x69, 0xc4, 0x00
	};

	run(program, 7, false);
}

void
test4()
{
	std::cerr << "\nStarting test 4\n";
	std::cerr << "\t(Third full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0x80, 0x85, 0x01, 0x65, 0x01
	};

	run(program, 6, false);
}

void
test5()
{
	std::cerr << "\nStarting test 5\n";
	std::cerr << "\t(First branching easy6502 program)\n";

	unsigned char	program[] = {
		0xa2, 0x08, 0xca, 0x8e, 0x00, 0x02, 0xe0, 0x03,
		0xd0, 0xf8, 0x8e, 0x01, 0x02, 0x00
	};
	run(program, 14, false);
}

void
test6()
{
	std::cerr << "\nStarting test 6\n";
	std::cerr << "\t(Indexed indirect addressing)\n";

	unsigned char	program[] = {
		0xa2, 0x01, 0xa9, 0x05, 0x85, 0x01, 0xa9, 0x03,
		0x85, 0x02, 0xa0, 0x0a, 0x8c, 0x05, 0x03, 0xa1,
		0x00
	};
	run(program, 17, false);
}

int
main(void)
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
}
<commit_msg>Add indirect indexed addressing example<commit_after>/*
 * Copyright (c) 2014 Kyle Isom <kyle@tyrfingr.is>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

// This is a test of instructions from http://skilldrick.github.io/easy6502/index.html.
// As this library isn't an assembler, it won't assemble the files; I'm
// to check some of the expected behaviours from the emulator.

#include <iomanip>
#include <iostream>
using namespace std;

#include "cpu.h"

void	test1(void);
void	test2(void);
void	test3(void);
void	test4(void);
void	test5(void);
void	test6(void);
void	test7(void);

static void
dump_program(const unsigned char *program, size_t len)
{
	size_t	i = 0;
	int	l = 0;
	for (i = 0; i < len; ++i) {
		if (l == 0)
			std::cerr << std::setw(8) << std::hex << i << "| ";
		std::cerr << std::hex << std::setw(2) << std::setfill('0')
			  << (unsigned short)(program[i] & 0xff);
		std::cerr << " ";
		l++;
		if (l == 8) {
			std::cerr << " ";
		} else if (l == 16) {
			std::cerr << std::endl;
			l = 0;
		}
	}
	std::cerr << std::endl;
}

static void
run(const unsigned char *program, size_t size, bool trace)
{
	CPU	cpu(0x400);
	std::cerr << "\nPROGRAM:\n";
	dump_program(program, size);
	std::cerr << std::endl;

	cpu.load(program, 0x300, size);
	cpu.start_pc(0x300);

	cpu.run(trace);
	cpu.dump_memory();
	cpu.dump_registers();
}

void
test1()
{
	std::cerr << "\nStarting test 1\n";
	std::cerr << "\t(First compiled program)\n";

	// test1, compiled as opcodes
	unsigned char	program[] = {0xA9, 0x01, 0x8D, 0x01, 0x00};
	run(program, 5, false);
}

void
test2()
{
	std::cerr << "\nStarting test 2\n";
	std::cerr << "\t(First full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0x01, 0x8d, 0x00, 0x02, 0xa9, 0x05, 0x8d,
		0x01, 0x02, 0xa9, 0x08, 0x8d, 0x02, 0x02, 0x00
	};
	run(program, 15, false);
}

void
test3()
{
	std::cerr << "\nStarting test 3\n";
	std::cerr << "\t(Second full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0xc0, 0xaa, 0xe8, 0x69, 0xc4, 0x00
	};

	run(program, 7, false);
}

void
test4()
{
	std::cerr << "\nStarting test 4\n";
	std::cerr << "\t(Third full compiled easy6502 program)\n";

	unsigned char	program[] = {
		0xa9, 0x80, 0x85, 0x01, 0x65, 0x01
	};

	run(program, 6, false);
}

void
test5()
{
	std::cerr << "\nStarting test 5\n";
	std::cerr << "\t(First branching easy6502 program)\n";

	unsigned char	program[] = {
		0xa2, 0x08, 0xca, 0x8e, 0x00, 0x02, 0xe0, 0x03,
		0xd0, 0xf8, 0x8e, 0x01, 0x02, 0x00
	};
	run(program, 14, false);
}

void
test6()
{
	std::cerr << "\nStarting test 6\n";
	std::cerr << "\t(Indexed indirect addressing)\n";

	unsigned char	program[] = {
		0xa2, 0x01, 0xa9, 0x05, 0x85, 0x01, 0xa9, 0x03,
		0x85, 0x02, 0xa0, 0x0a, 0x8c, 0x05, 0x03, 0xa1,
		0x00
	};
	run(program, 17, false);
}

void
test7()
{
	std::cerr << "\nStarting test 7\n";
	std::cerr << "\t(Indirect indexed addressing)\n";

	unsigned char	program[] = {
		0xa0, 0x01, 0xa9, 0x03, 0x85, 0x01, 0xa9, 0x01,
		0x85, 0x02, 0xa2, 0x0a, 0x8e, 0x04, 0x01, 0xb1,
		0x01, 0x00
	};
	run(program, 18, false);
}

int
main(void)
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
	test7();
}
<|endoftext|>


<commit_before>/// random
//  Random implements a pseudo random number generator (PRNG).
// The PRNG is a nonlinear additive feedback random number generator using 256 bytes of state
// information and a period of up to 2^69.
// @module random
#include "Random.h"
#include <Poco/Exception.h>

int luaopen_poco_random(lua_State* L)
{
    LuaPoco::RandomUserdata::registerRandom(L);
    return LuaPoco::loadConstructor(L, LuaPoco::RandomUserdata::Random);
}

namespace LuaPoco
{

const char* POCO_RANDOM_METATABLE_NAME = "Poco.Random.metatable";

RandomUserdata::RandomUserdata(int stateSize)
    : mRandom(stateSize)
{
}

RandomUserdata::~RandomUserdata()
{
}

// register metatable for this class
bool RandomUserdata::registerRandom(lua_State* L)
{
    struct CFunctions methods[] =
    {
        { "__gc", metamethod__gc },
        { "__tostring", metamethod__tostring },
        { "next", next },
        { "nextNumber", nextNumber },
        { "nextByte", nextByte },
        { "nextBool", nextBool },
        { NULL, NULL}
    };

    setupUserdataMetatable(L, POCO_RANDOM_METATABLE_NAME, methods);
    return true;
}

/// Constructs a new random userdata.
// @tparam[opt] number stateSize (default: 256) state buffer size: 8, 16, 32, 64, 128, or 256.
// @tparam[opt] number seed seed for prng, if unspecified an internal RandomNumberStream is used.
// @return userdata or nil. (error)
// @return error message.
// @function new
int RandomUserdata::Random(lua_State* L)
{
    int rv = 0;
    int firstArg = lua_istable(L, 1) ? 2 : 1;

    lua_Integer stateSize = 256;
    lua_Integer seed = lua_isinteger(L, firstArg + 1) ? lua_tointeger(L, firstArg + 1) : 0;

    if (lua_isinteger(L, firstArg)) { stateSize = lua_tointeger(L, firstArg); }
    if (stateSize != 256 && stateSize != 128 && stateSize != 64 && stateSize != 32 &&
        stateSize != 16 && stateSize != 8)
    {
        lua_pushnil(L); lua_pushfstring(L, "invalid stateSize: %d", stateSize);
        return 2;
    }

    try
    {
        RandomUserdata* rud = new(lua_newuserdata(L, sizeof *rud))
            RandomUserdata(stateSize);
        setupPocoUserdata(L, rud, POCO_RANDOM_METATABLE_NAME);

        if (seed) { rud->mRandom.seed(seed); }
        else { rud->mRandom.seed(); }

        rv = 1;
    }
    catch (const Poco::Exception& e)
    {
        rv = pushPocoException(L, e);
    }
    catch (...)
    {
        rv = pushUnknownException(L);
    }

    return rv;
}

// metamethod infrastructure
int RandomUserdata::metamethod__tostring(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushfstring(L, "Poco.Random (%p)", static_cast<void*>(rud));

    return 1;
}

int RandomUserdata::metamethod__gc(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    rud->~RandomUserdata();

    return 0;
}
///
// @type random

/// Returns the next 31-bit pseudo random number. (modulo n, if supplied)
// @tparam[opt] integer n modulo value.
// @function next
int RandomUserdata::next(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_Integer rval = 0;

    if (lua_isinteger(L, 2))
        { rval = static_cast<lua_Integer>(rud->mRandom.next(lua_tointeger(L, 2))); }
    else { rval = rud->mRandom.next(); }

    lua_pushinteger(L, rval);
    return 1;
}

/// Returns the next pseudo random number between 0.0 and 1.0 as a double.
// @function nextNumber
int RandomUserdata::nextNumber(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushnumber(L, static_cast<lua_Number>(rud->mRandom.nextDouble()));
    return 1;
}

/// Returns the next pseudo random byte.
// @function nextByte
int RandomUserdata::nextByte(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    unsigned char rval = static_cast<unsigned char>(rud->mRandom.nextChar());
    lua_pushinteger(L, static_cast<lua_Integer>(rval));
    return 1;
}

/// Returns the next pseudo random boolean value.
// @function nextBool
int RandomUserdata::nextBool(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushboolean(L, static_cast<int>(rud->mRandom.nextBool()));
    return 1;
}

} // LuaPoco

<commit_msg>change to lua_isnumber for argument checks on constructor for 5.1/5.2 compat<commit_after>/// random
//  Random implements a pseudo random number generator (PRNG).
// The PRNG is a nonlinear additive feedback random number generator using 256 bytes of state
// information and a period of up to 2^69.
// @module random
#include "Random.h"
#include <Poco/Exception.h>

int luaopen_poco_random(lua_State* L)
{
    LuaPoco::RandomUserdata::registerRandom(L);
    return LuaPoco::loadConstructor(L, LuaPoco::RandomUserdata::Random);
}

namespace LuaPoco
{

const char* POCO_RANDOM_METATABLE_NAME = "Poco.Random.metatable";

RandomUserdata::RandomUserdata(int stateSize)
    : mRandom(stateSize)
{
}

RandomUserdata::~RandomUserdata()
{
}

// register metatable for this class
bool RandomUserdata::registerRandom(lua_State* L)
{
    struct CFunctions methods[] =
    {
        { "__gc", metamethod__gc },
        { "__tostring", metamethod__tostring },
        { "next", next },
        { "nextNumber", nextNumber },
        { "nextByte", nextByte },
        { "nextBool", nextBool },
        { NULL, NULL}
    };

    setupUserdataMetatable(L, POCO_RANDOM_METATABLE_NAME, methods);
    return true;
}

/// Constructs a new random userdata.
// @tparam[opt] number stateSize (default: 256) state buffer size: 8, 16, 32, 64, 128, or 256.
// @tparam[opt] number seed seed for prng, if unspecified an internal RandomNumberStream is used.
// @return userdata or nil. (error)
// @return error message.
// @function new
int RandomUserdata::Random(lua_State* L)
{
    int rv = 0;
    int firstArg = lua_istable(L, 1) ? 2 : 1;

    lua_Integer stateSize = 256;
    lua_Integer seed = lua_isinteger(L, firstArg + 1) ? lua_tointeger(L, firstArg + 1) : 0;

    if (lua_isnumber(L, firstArg)) { stateSize = lua_tointeger(L, firstArg); }
    if (stateSize != 256 && stateSize != 128 && stateSize != 64 && stateSize != 32 &&
        stateSize != 16 && stateSize != 8)
    {
        lua_pushnil(L); lua_pushfstring(L, "invalid stateSize: %d", stateSize);
        return 2;
    }

    try
    {
        RandomUserdata* rud = new(lua_newuserdata(L, sizeof *rud))
            RandomUserdata(stateSize);
        setupPocoUserdata(L, rud, POCO_RANDOM_METATABLE_NAME);

        if (seed) { rud->mRandom.seed(seed); }
        else { rud->mRandom.seed(); }

        rv = 1;
    }
    catch (const Poco::Exception& e)
    {
        rv = pushPocoException(L, e);
    }
    catch (...)
    {
        rv = pushUnknownException(L);
    }

    return rv;
}

// metamethod infrastructure
int RandomUserdata::metamethod__tostring(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushfstring(L, "Poco.Random (%p)", static_cast<void*>(rud));

    return 1;
}

int RandomUserdata::metamethod__gc(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    rud->~RandomUserdata();

    return 0;
}
///
// @type random

/// Returns the next 31-bit pseudo random number. (modulo n, if supplied)
// @tparam[opt] integer n modulo value.
// @function next
int RandomUserdata::next(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_Integer rval = 0;

    if (lua_isnumber(L, 2))
        { rval = static_cast<lua_Integer>(rud->mRandom.next(lua_tointeger(L, 2))); }
    else { rval = rud->mRandom.next(); }

    lua_pushinteger(L, rval);
    return 1;
}

/// Returns the next pseudo random number between 0.0 and 1.0 as a double.
// @function nextNumber
int RandomUserdata::nextNumber(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushnumber(L, static_cast<lua_Number>(rud->mRandom.nextDouble()));
    return 1;
}

/// Returns the next pseudo random byte.
// @function nextByte
int RandomUserdata::nextByte(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    unsigned char rval = static_cast<unsigned char>(rud->mRandom.nextChar());
    lua_pushinteger(L, static_cast<lua_Integer>(rval));
    return 1;
}

/// Returns the next pseudo random boolean value.
// @function nextBool
int RandomUserdata::nextBool(lua_State* L)
{
    RandomUserdata* rud = checkPrivateUserdata<RandomUserdata>(L, 1);
    lua_pushboolean(L, static_cast<int>(rud->mRandom.nextBool()));
    return 1;
}

} // LuaPoco

<|endoftext|>