Blob Blame Raw


#include "ttimer.h"
#include "tthreadmessage.h"
#include "texception.h"

#ifdef _WIN32

#include <windows.h>
#include <mmsystem.h>
#include <cstdlib>

//moto strano: se togliamo l'include della glut non linka
#include <GL/glut.h>

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2);
};

//------------------------------------------------------------------------------

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer);
	~Imp();

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_timerID = timeSetEvent(delay, m_timerRes,
								 (LPTIMECALLBACK)ElapsedTimeCB, (DWORD) this,
								 m_type | TIME_CALLBACK_FUNCTION);

		m_delay = delay;
		m_ticks = 0;
		if (m_timerID == NULL)
			throw TException("Unable to start timer");

		m_started = true;
	}

	void stop()
	{
		if (m_started)
			timeKillEvent(m_timerID);
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

//------------------------------------------------------------------------------

TTimer::Imp::Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
	: m_name(name), m_timerRes(timerRes), m_timer(timer), m_type(type), m_timerID(NULL), m_ticks(0), m_delay(0), m_started(false), m_action(0)
{

	TIMECAPS tc;

	if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
		throw TException("Unable to create timer");
	}

	m_timerRes = std::min((int)std::max((int)tc.wPeriodMin, (int)m_timerRes), (int)tc.wPeriodMax);
	timeBeginPeriod(m_timerRes);

	switch (type) {
	case TTimer::OneShot:
		m_type = TIME_ONESHOT;
		break;

	case TTimer::Periodic:
		m_type = TIME_PERIODIC;
		break;

	default:
		throw TException("Unexpected timer type");
		break;
	}
}

//------------------------------------------------------------------------------

TTimer::Imp::~Imp()
{
	stop();
	timeEndPeriod(m_timerRes);

	if (m_action)
		delete m_action;
}

//------------------------------------------------------------------------------

namespace
{

void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg,
							DWORD dwUser, DWORD dw1,
							DWORD dw2)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(dwUser);
	imp->m_ticks++;
	if (imp->m_action)
		imp->m_action->sendCommand(imp->m_ticks);
}
};
#elif LINUX

#include <SDL/SDL_timer.h>
#include <SDL/SDL.h>
#include "tthread.h"
namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param);
}

class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0), m_ticks(0)
	{
	}
	~Imp() {}

	void start(UINT delay)
	{
		static bool first = true;
		if (first) {
			SDL_Init(SDL_INIT_TIMER);
			first = false;
		}
		m_timerID = SDL_AddTimer(delay, ElapsedTimeCB, this);
	}

	void stop()
	{
		SDL_RemoveTimer(m_timerID);
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	SDL_TimerID m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

class SendCommandMSG : public TThread::Message
{
	TTimer::Imp *m_ztimp;

public:
	SendCommandMSG(TTimer::Imp *ztimp) : TThread::Message(), m_ztimp(ztimp)
	{
	}
	~SendCommandMSG() {}
	TThread::Message *clone() const { return new SendCommandMSG(*this); }
	void onDeliver()
	{
		if (m_ztimp->m_action)
			m_ztimp->m_action->sendCommand(m_ztimp->m_ticks);
	}
};

namespace
{
Uint32 ElapsedTimeCB(Uint32 interval, void *param)
{
	TTimer::Imp *imp = reinterpret_cast<TTimer::Imp *>(param);
	imp->m_ticks++;
	SendCommandMSG(imp).send();
	return interval;
}
}

#elif __sgi
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");

		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};
#elif MACOSX
class TTimer::Imp
{
public:
	Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer)
		: m_action(0) {}
	~Imp() {}

	void start(UINT delay)
	{
		if (m_started)
			throw TException("The timer is already started");
		throw TException("The timer is not yet available under MAC :(");
		m_started = true;
	}

	void stop()
	{
		m_started = false;
	}

	std::string getName() { return m_name; }
	TUINT64 getTicks() { return m_ticks; }
	UINT getDelay() { return m_delay; }

	std::string m_name;

	UINT m_timerRes;
	UINT m_type;
	TTimer *m_timer;

	UINT m_timerID;
	UINT m_delay;
	TUINT64 m_ticks;
	bool m_started;

	TGenericTimerAction *m_action;
};

#endif

//===============================================================================
//
//  TTimer
//
//===============================================================================

TTimer::TTimer(const std::string &name, UINT timerRes, Type type)
	: m_imp(new TTimer::Imp(name, timerRes, type, this))
{
}

//--------------------------------------------------------------------------------

TTimer::~TTimer()
{
}

//--------------------------------------------------------------------------------

void TTimer::start(UINT delay)
{
	m_imp->start(delay);
}

//--------------------------------------------------------------------------------

bool TTimer::isStarted() const
{
	return m_imp->m_started;
}

//--------------------------------------------------------------------------------

void TTimer::stop()
{
	m_imp->stop();
}

//--------------------------------------------------------------------------------

std::string TTimer::getName() const
{
	return m_imp->getName();
}

//--------------------------------------------------------------------------------

TUINT64 TTimer::getTicks() const
{
	return m_imp->getTicks();
}

//--------------------------------------------------------------------------------

UINT TTimer::getDelay() const
{
	return m_imp->getDelay();
}

//--------------------------------------------------------------------------------

void TTimer::setAction(TGenericTimerAction *action)
{
	if (m_imp->m_action)
		delete m_imp->m_action;

	m_imp->m_action = action;
}