//Copyright (C) 2007 SiegeLord
//See ReadMe.txt and License.txt for copying information

#include "../include/engine/sfx.h"
#include "../include/engine/error.h"
#include "../include/engine/math_types.h"

list<SSound*> g_lSounds;

int g_nMaxVoices;

SSound* PlaySound(SSoundFile* source, bool looping)
{
	if((int)g_lSounds.size() - 1 >= g_nMaxVoices)
		return 0;
	SSound* sound = new SSound();

	sound->source = new SSoundFile;

	sound->source->dataPtr = source->dataPtr;
	sound->source->dataRead = 0;
	sound->source->dataSize = source->dataSize;

	if(!PrepareSoundForPlayback(sound->source, &sound->oggStream, &sound->info))
		return 0;

	int num_chan = sound->info->channels == 2 ? 1 : 0;
	sound->stream = play_audio_stream(g_nBufferSize, 16, num_chan, sound->info->rate, 255, 128);
	sound->marked_for_stop = false;
	sound->section = 0;
	sound->looping = looping;
	sound->volume = 1.0f;
	sound->pan = 0.0f;

	g_lSounds.push_back(sound);

	return sound;
}

void DestroySound(SSound* sound)
{
	free_audio_stream_buffer(sound->stream);
	stop_audio_stream(sound->stream);
	StopSoundPlayback(&sound->oggStream);
	delete sound->source;
	delete sound;
}

void UpdateSounds()
{
	for(list<SSound*>::iterator it = g_lSounds.begin(); it != g_lSounds.end(); it++)
	{
		//first, we set the pan and volume
		SnapVar((*it)->pan, -1.0f, 1.0f);
		SnapVar((*it)->volume, 0.0f, 1.0f);

		voice_set_volume((*it)->stream->voice, int((*it)->volume * 255.0f));
		voice_set_pan((*it)->stream->voice, int(128 + 127.0f * (*it)->pan));

		//now we stream the rest of the file
		void* buf = 0;
		buf = get_audio_stream_buffer((*it)->stream);
		while(buf)
		{
			if((*it)->marked_for_stop)
			{
				DestroySound((*it));

				it = g_lSounds.erase(it);
				buf = 0;

				continue;
			}

			int len_to_read = g_nBufferSize * (16 / 8) * ((*it)->info->channels);
			int ret = Stream(&(*it)->oggStream, buf, &(*it)->section, len_to_read, (*it)->looping);

			if(ret == 0)
				(*it)->marked_for_stop = true;

			free_audio_stream_buffer((*it)->stream);
			buf = get_audio_stream_buffer((*it)->stream);
		}
	}
}


void InitSfx()
{
	reserve_voices(16, 0);
	if(install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) != 0)
	{
		Throw("Unable to set any sound mode...\n", allegro_error);
	}
	g_nMaxVoices = 8;
	InitVorbis();
}

void DeInitSfx()
{
	StopAllSounds();
}

void StopAllSounds()
{
	for(list<SSound*>::iterator it = g_lSounds.begin(); it != g_lSounds.end(); it++)
	{
		DestroySound((*it));
	}
	g_lSounds.clear();
}

//stops the sound... don't use the pointer afterwards
void StopSound(SSound* sound)
{
	sound->marked_for_stop = true;
}
//sets the sound's pan, -1 to 1
void SetSoundPan(SSound* sound, float pan)
{
	sound->pan = pan;
}
//sets the sounds volume, 0 to 1
void SetSoundVolume(SSound* sound, float volume)
{
	sound->volume = volume;
}
