//	OSCDispatcher.cpp - Class to dispatch OSC note on/off events.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#include "NiallsOSCLib/OSCMessage.h"
#include "OSCDispatcher.h"
#include "UTF8File.h"

//------------------------------------------------------------------------------
OSCDispatcher::OSCDispatcher():
frameCount(16),
lastTicks(0)
{

}

//------------------------------------------------------------------------------
OSCDispatcher::~OSCDispatcher()
{
	unsigned int i;
	int statusByte;
	int dataByte0, dataByte1;

	for(i=0;i<noteOffs.size();++i)
	{
		statusByte = 0x80;
		dataByte0 = noteOffs[i].note;
		dataByte1 = 0;

		sendMessage(noteOffs[i].address, statusByte, dataByte0, dataByte1);
	}
}

//------------------------------------------------------------------------------
void OSCDispatcher::update(uint32_t ticks)
{
	int i;
	int statusByte;
	int dataByte0, dataByte1;
	float timeElapsed = 0.0f;

	//Update our time count.
	if(lastTicks != 0)
		timeElapsed = (float)(ticks-lastTicks)/1000.0f;
	lastTicks = ticks;

	//Dispatch any elapsed Note Offs.
	for(i=(noteOffs.size()-1);i>=0;--i)
	{
		noteOffs[i].remainingTime -= timeElapsed;

		if(noteOffs[i].remainingTime <= 0.0f)
		{
			statusByte = 0x80;
			dataByte0 = noteOffs[i].note;
			dataByte1 = 0;

			sendMessage(noteOffs[i].address, statusByte, dataByte0, dataByte1);

			noteOffs.erase(noteOffs.begin()+i);
		}
	}

	frameCount = 16;
}

//------------------------------------------------------------------------------
void OSCDispatcher::setDestAddress(const std::wstring& addr)
{
	std::string tempstr;

	UTF8File::wstringToChar(addr, tempstr);
	socket.setAddress(tempstr);
}

//------------------------------------------------------------------------------
void OSCDispatcher::setDestPort(int val)
{
	socket.setPort(val);
}

//------------------------------------------------------------------------------
void OSCDispatcher::sendNote(const std::wstring& address,
							 int note,
							 float length)
{
	int statusByte;
	NoteData tempData;
	std::string tempstr;
	int dataByte0, dataByte1;

	UTF8File::wstringToChar(address, tempstr);

	//Send the Note On message.
	statusByte = 0x90;
	dataByte0 = note;
	dataByte1 = 0x60;
	sendMessage(tempstr, statusByte, dataByte0, dataByte1);

	//Store the Note Off message.
	tempData.address = tempstr;
	tempData.note = note;
	tempData.remainingTime = length;
	noteOffs.push_back(tempData);
}

//------------------------------------------------------------------------------
void OSCDispatcher::sendMessage(const std::string& address,
								int statusByte,
								int dataByte0,
								int dataByte1)
{
	OSC::Message message;
	OSC::Int32 messageSize;

	message.setAddress(address);
	message.addInt32(statusByte);
	message.addInt32(dataByte0);
	message.addInt32(dataByte1);

	messageSize = message.getSize();
	socket.sendData(message.getData(), messageSize);
}
