#include <qtimer.h>
#include "plugin.h"
#include "plugin_deps.h"
#include "player.h"
#include <artsflow.h>
#include <vector>
#include "pluginloader.h"
#include "noatunapp.h"
#include "engine.h"
#include <artsflow.h>
#include <soundserver.h>
#include "StereoEffectStack_Noatun.h"
#include "FFTScopeStereo.h"
#include "FFTScope.h"
#include "RawScope.h"
#include "RawScopeStereo.h"

Plugin::Plugin()
{
}

Plugin::~Plugin()
{
}

void Plugin::init()
{
}

bool Plugin::unload()
{
	return napp->libraryLoader()->remove(this);
}

TimerThingy::TimerThingy(Visualization *vis)
{
	mTimer=new QTimer(this);
	mVis=vis;
	connect(mTimer, SIGNAL(timeout()), SLOT(timeout()));
}

void TimerThingy::timeout()
{
	mVis->timeout();
}




Visualization::Visualization(int timeout)
{
	mTimerThingy=new TimerThingy(this);
	setInterval(timeout);
}

Visualization::~Visualization()
{
//	napp->player()->engine()->visualizationStack()->remove(mId);
	delete mTimerThingy;
}

void Visualization::start()
{
	mTimerThingy->mTimer->start(mTimeout);
}

void Visualization::stop()
{
	mTimerThingy->mTimer->stop();
}

void Visualization::setInterval(int msec)
{
	mTimeout=msec;
	if (!msec)
		stop();
	mTimerThingy->mTimer->changeInterval(msec);
}

int Visualization::interval() const
{
	return mTimeout;
}

FFTScope::FFTScope(int interval) : Visualization(interval)
{
}


StereoFFTScope::StereoFFTScope(int timeout) : FFTScope(timeout)
{
	mScope=new Arts::FFTScopeStereo;
	*mScope=Arts::DynamicCast(napp->player()->engine()->server()->createObject("Arts::FFTScopeStereo"));

	if ((*mScope).isNull())
	{
		delete mScope;
		mScope=0;
	}
	else
	{
		mScope->start();
		mId=napp->player()->engine()->visualizationStack()->insertBottom(*mScope, "Noatun FFT");
	}
}

StereoFFTScope::~StereoFFTScope()
{
	if (mScope)
	{
		napp->player()->engine()->visualizationStack()->remove(mId);
		mScope->stop();
		delete mScope;
	}
}

void StereoFFTScope::scopeData(vector<float> *&left, vector<float> *&right)
{
	left=mScope->scopeLeft();
	right=mScope->scopeRight();
}

void StereoFFTScope::timeout()
{
	vector<float> *left, *right;
	scopeData(left, right);

	if (left->size())
		scopeEvent(&left->front(), &right->front(), left->size());
	delete left;
	delete right;
		
}
int StereoFFTScope::bands() const
{
	vector<float> *d=mScope->scopeLeft();
	int size=d->size();
	delete d;
	return size;
}

MonoFFTScope::MonoFFTScope(int timeout) : FFTScope(timeout)
{
	mScope=new Arts::FFTScope;
	*mScope=Arts::DynamicCast(napp->player()->engine()->server()->createObject("Arts::FFTScope"));

	if ((*mScope).isNull())
	{
		delete mScope;
		mScope=0;
	}
	else
	{
		mScope->start();
		mId=napp->player()->engine()->visualizationStack()->insertBottom(*mScope, "Noatun FFT");
	}
}

MonoFFTScope::~MonoFFTScope()
{
	if (mScope)
	{
		napp->player()->engine()->visualizationStack()->remove(mId);
		mScope->stop();
		delete mScope;
	}
}

void MonoFFTScope::scopeData(vector<float> *&data)
{
	data=mScope->scope();
}

void MonoFFTScope::timeout()
{
	vector<float> *data(mScope->scope());

	float *f=&data->front();
	if (data->size()) scopeEvent(f, data->size());
	delete data;
}

int MonoFFTScope::bands() const
{
	vector<float> *d=mScope->scope();
	int size=d->size();
	delete d;
	return size;

}



Scope::Scope(int interval) : Visualization(interval)
{
}



MonoScope::MonoScope(int timeout) : Scope(timeout)
{
	mScope=new Arts::RawScope;
	*mScope=Arts::DynamicCast(napp->player()->engine()->server()->createObject("Arts::RawScope"));

	if ((*mScope).isNull())
	{
		delete mScope;
		mScope=0;
	}
	else
	{
		mScope->start();
		mId=napp->player()->engine()->visualizationStack()->insertBottom(*mScope, "Noatun Scope");
	}
}

MonoScope::~MonoScope()
{
	if (mScope)
	{
		napp->player()->engine()->visualizationStack()->remove(mId);
		mScope->stop();
		delete mScope;
	}
}

void MonoScope::scopeData(vector<float> *&data)
{
	data=mScope->scope();
}

void MonoScope::timeout()
{
	vector<float> *data(mScope->scope());

	float *f=&data->front();
	if (data->size()) scopeEvent(f, data->size());
	delete data;
}

int MonoScope::samples() const
{
	return (long)mScope->buffer();
}

void MonoScope::setSamples(int len)
{
	mScope->buffer((long)len);
}



StereoScope::StereoScope(int timeout) : Scope(timeout)
{
	mScope=new Arts::RawScopeStereo;
	*mScope=Arts::DynamicCast(napp->player()->engine()->server()->createObject("Arts::RawScopeStereo"));

	if ((*mScope).isNull())
	{
		delete mScope;
		mScope=0;
	}
	else
	{
		mScope->start();
		mId=napp->player()->engine()->visualizationStack()->insertBottom(*mScope, "Noatun Stereo Scope");
	}
}

StereoScope::~StereoScope()
{
	if (mScope)
	{
		napp->player()->engine()->visualizationStack()->remove(mId);
		mScope->stop();
		delete mScope;
	}
}

void StereoScope::scopeData(vector<float> *&left, vector<float> *&right)
{
	left=mScope->scopeLeft();
	right=mScope->scopeRight();
}

void StereoScope::timeout()
{
	vector<float> *left(mScope->scopeLeft());
	vector<float> *right(mScope->scopeRight());

	float *l=&left->front();
	float *r=&right->front();
	
	if (left->size()==right->size() && left->size())
		scopeEvent(l, r, left->size());
	delete left;
	delete right;
}

int StereoScope::samples() const
{
	return (long)mScope->buffer();
}

void StereoScope::setSamples(int len)
{
	mScope->buffer((long)len);
}




SessionManagement::SessionManagement() { }
SessionManagement::~SessionManagement() { }
void SessionManagement::restore() { }

