/****************************************************************************

   PROGRAM: audioenv.cpp

   DESCRIPTION: audio object class code

****************************************************************************/
#include "audioenv.h"

// EAX-test
#define OPENAL
#ifdef MACOS
#include "eax.h"
#endif

// constructor
AudioEnv::AudioEnv ()
{
	nextBuffer = 0;
	nextSource = 0;
}

// destructor
AudioEnv::~AudioEnv ()
{
#ifdef MACOS
#ifdef ALFUNCTIONS
	alExit();
#endif
#endif
}

// init
void AudioEnv::Init ()
{
#ifdef WINDOWS
#ifdef ALFUNCTIONS
   alutInit (NULL, 0); // init OpenAL
#endif
#endif

#ifdef MACOS
#ifdef ALFUNCTIONS
   alInit (NULL, 0); // init OpenAL
   
    // EAX test -- set EAX environment if EAX is available
	PropSetFunction pfPropSet;
	PropGetFunction pfPropGet;
	unsigned long ulEAXVal;
	long lGlobalReverb;
	if (alIsExtensionPresent((ALubyte *)"EAX") == AL_TRUE)
	{
		pfPropSet = (PropSetFunction) alGetProcAddress((ALubyte *)"EAXSet");
		if (pfPropSet != NULL)
		{
		    lGlobalReverb = 0;
			pfPropSet(PROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, 0, &lGlobalReverb, sizeof(unsigned long));
			ulEAXVal = EAX_ENVIRONMENT_GENERIC;
			pfPropSet(PROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, 0, &ulEAXVal, sizeof(unsigned long));
		}
	}
#endif
#endif
   
#ifdef LINUX
#ifdef ALFUNCTIONS
   alutInit (NULL, 0); // init OpenAL
#endif
#endif
}

// init
void AudioEnv::ListenerPosition (ALfloat* position, ALfloat* angle)
{
	alListenerfv(AL_POSITION, position);
	alListenerfv(AL_ORIENTATION, angle);
}

#ifdef MACOS
int AudioEnv::LoadFile (const unsigned char *filename, bool loop, int bits, int rate, bool stereo)
#else
int AudioEnv::LoadFile (char *filename, bool loop)
#endif
{
   // create buffer
   alGetError(); /* clear */
   alGenBuffers(1, &buffer[nextBuffer]);
   if(alGetError() != AL_NO_ERROR) {
	   return 0;
   }

   // create source
   alGetError(); /* clear */
   alGenSources(1, &source[nextSource]);
   if(alGetError() != AL_NO_ERROR) {
	   return 0;
   }

   // load data into buffer
#ifdef WINDOWS
   ALsizei size, freq;
   ALenum format;
   ALvoid *data;
   
   alutLoadWAVFile(filename, &format, &data, &size, &freq);
   alBufferData (buffer[nextBuffer], format, data, size, freq);
#endif
#ifdef LINUX
   ALsizei size, freq, bits;
   ALenum format;
   ALvoid *data;
   ALboolean err;
   
   err = alutLoadWAV(filename, &data, &format, &size, &bits, &freq);
   if(err == AL_FALSE) {
	   fprintf(stderr, "Could not load %s\n", filename);
	   return 0;
   }

   alBufferData (buffer[nextBuffer], format, data, size, freq);
#endif   
#ifdef MACOS
	char *pBuffer;
	long lBufferLen;
	FSSpec sfFile;
	short fRefNum;
	ALenum format;
	// load up some audio data...
	lBufferLen = 1000000; // max amount of data to read
	pBuffer = NewPtrClear(lBufferLen); // create a small buffer
	if (pBuffer != NULL)
	{
		if (FSMakeFSSpec((short)0,(long)0,filename,&sfFile) == 0)
		{
			FSpOpenDF(&sfFile, fsRdPerm, &fRefNum); // load some data into the buffer
			FSRead(fRefNum, &lBufferLen, pBuffer);			
			FSClose(fRefNum);
		}
		if ((bits == 8) || (bits == 16))
		{
		    if ((bits == 8) && (stereo == false)) { format = AL_FORMAT_MONO8; }
		    if ((bits == 16) && (stereo == false)) { format = AL_FORMAT_MONO16; }
		    if ((bits == 8) && (stereo == true)) { format = AL_FORMAT_STEREO8; }
		    if ((bits == 16) && (stereo == true)) { format = AL_FORMAT_STEREO16; }
			alBufferData(buffer[nextBuffer], format, pBuffer, lBufferLen, rate);
			DisposePtr(pBuffer);
		}
	}
#endif

   // setup source
   alSourcei(source[nextSource], AL_BUFFER, buffer[nextBuffer]);
   alSourcei(source[nextSource], AL_LOOP_COUNT, (loop == true) ? 65535 : 1);

   nextBuffer++;
   nextSource++;
   return nextBuffer;
}

// Playfile
#ifdef MACOS
int AudioEnv::PlayFile (const unsigned char *filename, bool loop, int bits, int rate, bool stereo)
#else
int AudioEnv::PlayFile (char *filename, bool loop)
#endif
{
	int loadhandle;

#ifdef MACOS
	loadhandle = LoadFile(filename, loop, bits, rate, stereo);
#else
	loadhandle = LoadFile(filename, loop);
#endif

	if (loadhandle != 0) { 
		Play(loadhandle); 
	} else
	{
		return 0;
	}

	return loadhandle;
}

//SetSourcePosition
void AudioEnv::SetSourcePosition (int handle, float *position)
{
	alSourcefv(source[handle-1], AL_POSITION, position);
}

// Play

void AudioEnv::Play(int handle)
{
	alSourcePlay(source[handle-1]); 
}

// Stop
void AudioEnv::Stop(int handle)
{
	alSourceStop(source[handle-1]);
}

// IncrementEnv
int AudioEnv::IncrementEnv()
{
#ifdef MACOS
	// increment EAX environment if EAX is available
	PropSetFunction pfPropSet;
	PropGetFunction pfPropGet;
	unsigned long ulEAXVal;
	static unsigned long ulEAXEnv = 0;
	if (alIsExtensionPresent((ALubyte *)"EAX") == AL_TRUE)
	{
		pfPropSet = (PropSetFunction) alGetProcAddress((ALubyte *)"EAXSet");
		if (pfPropSet != NULL)
		{
		    ulEAXVal = 65535;
			pfPropSet(PROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ROOM, 0, &ulEAXVal, sizeof(unsigned long));
			ulEAXEnv += 1;
			if (ulEAXEnv >= EAX_ENVIRONMENT_COUNT) { ulEAXEnv = EAX_ENVIRONMENT_GENERIC; }
			pfPropSet(PROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, 0, &ulEAXEnv, sizeof(unsigned long));
		}
	}
	return (int) ulEAXEnv;
#else
    return 0;
#endif
}



