//============================================================
// Program:		CGFSoundSystem
// Description:	DirectSound Wrapper
// Author:		Benjamin Gottemoller
// Website:		http://www.particlefield.com
// Date:		who knows
// Legal:		Licensed under the gnu GPL (see gpl.txt for details)
//============================================================

#include "GameFrame.h"
#include "GameFrameSoundSystem.h"
#include "GFDebugHandler.h"
#include <dmusici.h>

CGFSoundSystem::CGFSoundSystem()
{
	GFParent = NULL;
	Performance = NULL;
	Loader = NULL;
	Library = NULL;
	NumNodes = 0;
	NumUsed = 0;
}

CGFSoundSystem::~CGFSoundSystem()
{
	DestroyDirectSound();
}

void CGFSoundSystem::BeginDirectSound(GameFrame *gfparent, char *search_path, int num_nodes)
{
	WCHAR wSearchPath[MAX_PATH];
	GFParent = gfparent;

	if(num_nodes > 0)
	{
		if(Library != NULL) DestroyDirectSound();

		Library = new SOUND_NODE[num_nodes];
		Confirm(Library != NULL);
		NumNodes = num_nodes;
		NumUsed = 0;
		
		for(int i=0; i<NumNodes; i++)
		{
			Library[i].Segment = NULL;
		}
	}

	CoInitialize(NULL);
	Confirm(S_OK  == CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, 
									  IID_IDirectMusicPerformance8, (void**) &Performance));

	Confirm(S_OK  == Performance->InitAudio(NULL, NULL, GFParent->WinHandle, DMUS_APATH_SHARED_STEREOPLUSREVERB, 
											64, DMUS_AUDIOF_ALL, NULL));

	Confirm(S_OK  == CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, 
									  (void**) &Loader));

	MultiByteToWideChar(CP_ACP, 0, search_path, -1, wSearchPath, MAX_PATH);
	Confirm(S_OK == Loader->SetSearchDirectory(GUID_DirectMusicAllTypes, wSearchPath, FALSE));
}

void CGFSoundSystem::DestroyDirectSound(void)
{
	if(Performance != NULL)
	{
		Performance->Stop(NULL, NULL, 0, 0);
		Performance->CloseDown();
	}

	SAFE_RELEASE(Loader);
	SAFE_RELEASE(Performance);
	
	if(Library != NULL)
	{
		for(int i=0; i<NumUsed; i++)
		{
			SAFE_RELEASE(Library[i].Segment);
		}
	}
	
	SAFE_DELETE_ARRAY(Library);
	NumNodes = 0;
	NumUsed = 0;
	GFParent = NULL;

	CoUninitialize();
}

int CGFSoundSystem::AddSound(char *file)
{
	if((NumNodes <= 0) || (Library == NULL) || (GFParent == NULL)) return -1;
	int result = -1;
	WCHAR wFilename[MAX_PATH];

	if(NumUsed >= NumNodes)
	{
		int i = 0;
		SOUND_NODE *tmp = NULL;
		tmp = new SOUND_NODE[NumNodes * 2];

		if(tmp == NULL) return -1;

		for(i=0; i<NumNodes; i++)
		{
			tmp[i].Segment = Library[i].Segment;
		}

		for(i=NumNodes; i<(NumNodes * 2); i++)
		{
			tmp[i].Segment = NULL;
		}

		delete[] Library;
		Library = tmp;
		tmp = NULL;
		NumNodes *= 2;
	}

	if(S_OK  != CoCreateInstance(CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC, 
							     IID_IDirectMusicSegment8, (void**) &(Library[NumUsed].Segment)))
	{
		return result;
	}
	
	MultiByteToWideChar(CP_ACP, 0, file, -1, wFilename, MAX_PATH);

	if(S_OK  == Loader->LoadObjectFromFile(CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, 
										   wFilename, (void**) &(Library[NumUsed].Segment)))
	{
		result = NumUsed;
		NumUsed++;
	}

	return result;
}

void CGFSoundSystem::PlaySound(int index, DWORD delay, DWORD flags)
{
	if(GFParent->IsGamePaused || GFParent->IsGameLocked) return;
	Library[index].Segment->Download(Performance);
	Performance->PlaySegmentEx(Library[index].Segment, NULL, NULL, flags, 
							   delay, NULL, NULL, NULL);
}

void CGFSoundSystem::StopSound(int index, DWORD msec)
{
	if(GFParent->IsGamePaused || GFParent->IsGameLocked) return;
	Performance->StopEx(Library[index].Segment, msec, 0);
}

void CGFSoundSystem::SetRepeats(int index, DWORD num)
{
	if(GFParent->IsGamePaused || GFParent->IsGameLocked) return;
	Library[index].Segment->SetRepeats(num);
}

int CGFSoundSystem::IsPlaying(int index)
{
	if(S_OK == Performance->IsPlaying(Library[index].Segment, NULL))
	{
		return 1;
	}

	return 0;
}
