1/**********************************************************************************************************************************
2*
3*   OpenAL cross platform audio library
4*	Copyright (c) 2004, Apple Computer, Inc., Copyright (c) 2012, Apple Inc. All rights reserved.
5*
6*	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
7*	conditions are met:
8*
9*	1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10*	2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
11*		disclaimer in the documentation and/or other materials provided with the distribution.
12*	3.  Neither the name of Apple Inc. ("Apple") nor the names of its contributors may be used to endorse or promote products derived
13*		from this software without specific prior written permission.
14*
15*	THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16*	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS
17*	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
18*	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
19*	AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
20*	ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21*
22**********************************************************************************************************************************/
23/*
24	This source file contains all the entry points into the oal state via the defined OpenAL API set.
25*/
26
27#include "oalImp.h"
28#include "oalContext.h"
29#include "oalDevice.h"
30#include "oalSource.h"
31#include "oalBuffer.h"
32#include "oalCaptureDevice.h"
33#include "MacOSX_OALExtensions.h"
34
35// ~~~~~~~~~~~~~~~~~~~~~~
36// development build flags
37#define		LOG_API_USAGE		0
38#define		LOG_BUFFER_USAGE	0
39#define		LOG_SOURCE_USAGE	0
40#define		LOG_CAPTURE_USAGE	0
41#define		LOG_EXTRAS			0
42#define		LOG_ERRORS			0
43#define		LOG_ASA_USAGE		0
44
45#define		kMajorVersion	1
46#define		kMinorVersion	1
47
48
49char*		alcExtensions = NULL;
50char*		alExtensions = NULL;
51
52//these will be used to construct the actual strings
53#define		alcExtensionsBase		"ALC_EXT_CAPTURE ALC_ENUMERATION_EXT ALC_EXT_MAC_OSX"
54#define		alcExtensionsASA		" ALC_EXT_ASA"
55#define		alcExtensionsDistortion	" ALC_EXT_ASA_DISTORTION"
56#define		alcExtensionsRogerBeep	" ALC_EXT_ASA_ROGER_BEEP"
57
58#define		alExtensionsBase		"AL_EXT_OFFSET AL_EXT_LINEAR_DISTANCE AL_EXT_EXPONENT_DISTANCE AL_EXT_float32 AL_EXT_STATIC_BUFFER AL_EXT_SOURCE_NOTIFICATIONS"
59
60// ~~~~~~~~~~~~~~~~~~~~~~
61// VERSION
62#define alVersion					"1.1"
63
64#define 	unknownImplementationError "Unknown Internal Error"
65
66// AL_STATE info
67#define 	alVendor				"Apple Computer Inc."
68#define		alRenderer				"Software"
69
70#define		alNoError				"No Error"
71#define		alErrInvalidName		"Invalid Name"
72#define		alErrInvalidEnum		"Invalid Enum"
73#define		alErrInvalidValue		"Invalid Value"
74#define		alErrInvalidOp			"Invalid Operation"
75#define		alErrOutOfMemory		"Out of Memory"
76
77#define		alcErrInvalidDevice		"ALC Invalid Device"
78#define		alcErrInvalidContext	"ALC Invalid Context"
79
80// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81// globals
82// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
83
84UInt32		gCurrentError = 0;										// globally stored error code
85uintptr_t	gCurrentContext = 0;                                    // token for the current context
86uintptr_t	gCurrentDevice = 0;                                     // token for the device of the current context
87UInt32      gMaximumMixerBusCount = kDefaultMaximumMixerBusCount;   // use gMaximumMixerBusCount for settinmg the bus count when a device is opened
88ALdouble	gMixerOutputRate = 0.0;
89ALint		gRenderChannelSetting = ALC_MAC_OSX_RENDER_CHANNEL_COUNT_MULTICHANNEL;	// default setting is multi channel
90
91ALCchar 	gDefaultOutputDeviceName[maxLen];
92ALCchar 	gDefaultOutputDeviceNameList[maxLen];
93ALCchar		gDefaultInputDeviceName[maxLen];
94ALCchar 	gDefaultInputDeviceNameList[maxLen];
95
96// At this time, only mono CBR formats would work - no problem as only pcm formats are currently valid
97// The feature is turned on using ALC_CONVERT_DATA_UPON_LOADING and the alEnable()/alDisable() APIs
98bool        gConvertBufferNow = false;                              // do not convert data into mixer format by default
99
100// global object maps
101OALDeviceMap*			gOALDeviceMap			= NULL;			// this map will be created upon the first call to alcOpenDevice()
102OALContextMap*			gOALContextMap			= NULL;			// this map will be created upon the first call to alcCreateContext()
103OALBufferMap*			gOALBufferMap			= NULL;			// this map will be created upon the first call to alcGenBuffers()
104OALBufferMap*			gDeadOALBufferMap		= NULL;			// this map will be created upon the first call to alcGenBuffers()
105OALCaptureDeviceMap*	gOALCaptureDeviceMap	= NULL;			// this map will be created upon the first call to alcCaptureOpenDevice()
106
107// global API lock
108CAGuard*				gBufferMapLock			= NULL;			// this is used to prevent threading collisions in buffer manipulation API
109CAGuard*				gContextMapLock			= NULL;			// this is used to prevent threading collisions in context manipulation API
110CAGuard*				gDeviceMapLock			= NULL;			// this is used to prevent threading collisions in device manipulation API
111CAGuard*				gCaptureDeviceMapLock	= NULL;			// this is used to prevent threading collisions in capture device manipulation API
112
113// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114#pragma mark ***** Support Methods *****
115// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116void WaitOneRenderCycle()
117{
118	if (gOALContextMap == NULL) return;
119
120	OALContext*		context = gOALContextMap->Get(gCurrentContext);
121	if (context != NULL)
122	{
123		UInt32	microseconds = (UInt32)((context->GetFramesPerSlice() / (context->GetMixerRate()/1000)) * 1000);
124		usleep (microseconds * 2);
125	}
126}
127
128// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129char* GetALCExtensionList()
130{
131	// if the string has already been allocated and created, return it
132	if(alcExtensions != NULL) return alcExtensions;
133
134	// first create the base extension string
135	alcExtensions = (char*)malloc(strlen(alcExtensionsBase)+1);
136	memcpy(alcExtensions, alcExtensionsBase, strlen(alcExtensionsBase)+1);
137
138	// now add the extensions if they are found on the system
139	if (Get3DMixerVersion() >= k3DMixerVersion_2_2)
140	{
141		alcExtensions = (char*)realloc(alcExtensions, strlen(alcExtensions) + strlen(alcExtensionsASA) + 1);
142		strcat(alcExtensions, alcExtensionsASA);
143	}
144
145	if(IsDistortionPresent())
146	{
147		alcExtensions = (char*)realloc(alcExtensions, strlen(alcExtensions) + strlen(alcExtensionsDistortion) + 1);
148		strcat(alcExtensions, alcExtensionsDistortion);
149	}
150
151	if(IsRogerBeepPresent())
152	{
153		alcExtensions = (char*)realloc(alcExtensions, strlen(alcExtensions) + strlen(alcExtensionsRogerBeep) + 1);
154		strcat(alcExtensions, alcExtensionsRogerBeep);
155	}
156
157	return alcExtensions;
158}
159
160// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161char* GetALExtensionList()
162{
163	if(alExtensions != NULL) return alExtensions;
164
165	// if list is not created, allocate and create a new string
166	alExtensions = (char*)malloc(strlen(alExtensionsBase)+1);
167	memcpy(alExtensions, alExtensionsBase, strlen(alExtensionsBase)+1);
168
169	return alExtensions;
170}
171
172// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173UInt32 Get3DMixerVersion ()
174{
175	static	UInt32		mixerVersion = kUnknown3DMixerVersion;
176
177	if (mixerVersion == kUnknown3DMixerVersion)
178	{
179		ComponentDescription	mixerCD;
180		mixerCD.componentFlags = 0;
181		mixerCD.componentFlagsMask = 0;
182		mixerCD.componentType = kAudioUnitType_Mixer;
183		mixerCD.componentSubType = kAudioUnitSubType_3DMixer;
184		mixerCD.componentManufacturer = kAudioUnitManufacturer_Apple;
185
186		ComponentInstance   mixerInstance = OpenComponent(FindNextComponent(0, &mixerCD));
187		long  version = CallComponentVersion(mixerInstance);
188		CloseComponent(mixerInstance);
189
190		if (version < kMinimumMixerVersion)
191		{
192			mixerVersion = kUnsupported3DMixer;                           // we do not have a current enough 3DMixer to use
193		}
194		else if (version < 0x20000)
195		{
196			mixerVersion = k3DMixerVersion_1_3;
197		}
198		else if (version == 0x20000)
199		{
200			mixerVersion = k3DMixerVersion_2_0;
201		}
202		else if (version == 0x20100)
203		{
204			mixerVersion = k3DMixerVersion_2_1;
205		}
206		else if (version == 0x20200)
207		{
208			mixerVersion = k3DMixerVersion_2_2;
209		}
210		else if (version >= 0x20300)
211		{
212			mixerVersion = k3DMixerVersion_2_3;
213		}
214	}
215
216    return	mixerVersion;
217}
218
219// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
220ALdouble	GetMixerOutputRate()
221{
222	ALdouble	returnValue = 0.0;
223
224	if (gMixerOutputRate > 0.0)
225		returnValue = gMixerOutputRate; // return the user's explicit setting
226	else
227	{
228		OALDevice	*oalDevice = NULL;
229		if (gOALDeviceMap)
230			oalDevice = gOALDeviceMap->Get(gCurrentDevice);
231
232		if (oalDevice)
233		{
234			// there has been no explicit setting yet, but there is an open device, return it's sample rate
235			// as that will be the mixer setting as well, until gMixerOutputRate gets set before creating a context
236			returnValue = (ALdouble) oalDevice->GetDeviceSampleRate();
237
238		}
239		else
240		{
241			// The default device has not yet been opened, go get the sample rate of the default hw
242			AudioDeviceID	device;
243			UInt32			propSize = sizeof(device);
244			OSStatus	result = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &propSize, &device);
245			if (result == noErr)
246			{
247				Float64		sr;
248				propSize = sizeof(sr);
249				result = AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyNominalSampleRate, &propSize, &sr);
250				if (result == noErr)
251					returnValue = sr;
252			}
253			else
254			{
255				returnValue	= 0.0;
256				throw (AL_INVALID_OPERATION);
257			}
258		}
259	}
260	return (returnValue);
261}
262
263// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
264void alSetError (ALenum errorCode)
265{
266    // only set an error if we are in a no error state
267    if (gCurrentError == AL_NO_ERROR)
268		gCurrentError = errorCode;
269}
270
271// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
272void	CleanUpDeadBufferList()
273{
274	if (gDeadOALBufferMap)
275	{
276		UInt32	index = 0;
277		UInt32	count = gDeadOALBufferMap->Size();
278		for (UInt32 i = 0; i < count; i++)
279		{
280			OALBuffer*		buffer = gDeadOALBufferMap->GetBufferByIndex(index);
281			if (buffer)
282			{
283				if (buffer->IsPurgable())
284				{
285					gDeadOALBufferMap->Remove(buffer->GetToken());
286#if LOG_BUFFER_USAGE
287	DebugMessageN1("CleanUpDeadBufferList--> deleting buffers = %ld", (long int) buffer->GetToken());
288#endif
289					delete (buffer);
290				}
291				else
292					index++;
293			}
294			else
295				index++;
296		}
297	}
298}
299
300// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
301// ReleaseContextObject must be called when finished using the returned object
302OALContext*		ProtectContextObject (uintptr_t	inContextToken)
303{
304	OALContext		*oalContext = NULL;
305
306	if (gOALContextMap == NULL)
307		throw ((OSStatus) AL_INVALID_OPERATION);
308
309	CAGuard::Locker locked(*gContextMapLock);
310
311	oalContext = gOALContextMap->Get(inContextToken);
312	if (oalContext == NULL)
313		throw ((OSStatus) ALC_INVALID_CONTEXT);
314
315	oalContext->SetInUseFlag();
316
317	return oalContext;
318}
319
320// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
321void ReleaseContextObject(OALContext* inContext)
322{
323	if (inContext) inContext->ClearInUseFlag();
324}
325
326// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327void	SetDeviceError(uintptr_t inDeviceToken, UInt32	inError)
328{
329	if (gOALDeviceMap != NULL)
330	{
331		OALDevice			*oalDevice = gOALDeviceMap->Get(inDeviceToken);	// get the requested oal device
332		if (oalDevice)
333			oalDevice->SetError(inError);
334	}
335
336	if (gOALCaptureDeviceMap != NULL)
337	{
338		OALCaptureDevice			*oalCaptureDevice = gOALCaptureDeviceMap->Get(inDeviceToken);	// get the requested oal device
339		if (oalCaptureDevice)
340			oalCaptureDevice->SetError(inError);
341	}
342}
343
344// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
345// ReleaseDeviceObject must be called when finished using the returned object
346OALDevice*		ProtectDeviceObject (uintptr_t inDeviceToken)
347{
348	if (gOALDeviceMap == NULL)
349		throw ((OSStatus)AL_INVALID_OPERATION);
350	OALDevice *oalDevice = NULL;
351
352	CAGuard::Locker locked(*gDeviceMapLock);
353
354	oalDevice = gOALDeviceMap->Get(inDeviceToken);	// get the requested oal device
355	if (oalDevice == NULL)
356		throw ((OSStatus) AL_INVALID_VALUE);
357
358	oalDevice->SetInUseFlag();
359
360	return oalDevice;
361}
362
363// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
364void	ReleaseDeviceObject(OALDevice* inDevice)
365{
366	if (inDevice) inDevice->ClearInUseFlag();
367}
368
369// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
370// ReleaseCaptureDeviceObject must be called when finished using the returned object
371OALCaptureDevice*		ProtectCaptureDeviceObject (uintptr_t inDeviceToken)
372{
373	if (gOALCaptureDeviceMap == NULL)
374		throw ((OSStatus)AL_INVALID_OPERATION);
375
376	OALCaptureDevice			*oalCaptureDevice = NULL;
377
378	CAGuard::Locker locked(*gCaptureDeviceMapLock);
379
380	oalCaptureDevice = gOALCaptureDeviceMap->Get(inDeviceToken);	// get the requested oal device
381	if (oalCaptureDevice == NULL)
382		throw ((OSStatus) AL_INVALID_VALUE);
383
384	oalCaptureDevice->SetInUseFlag();
385
386	return oalCaptureDevice;
387}
388
389// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
390void	ReleaseCaptureDeviceObject(OALCaptureDevice* inDevice)
391{
392	if (inDevice) inDevice->ClearInUseFlag();
393}
394
395// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
396// ReleaseSourceObject must be called when finished using the returned object
397OALSource*	ProtectSourceObjectInCurrentContext(ALuint	inSID)
398{
399	OALContext	*oalContext = NULL;
400	OALSource	*oalSource	= NULL;
401
402	try {
403		oalContext = ProtectContextObject(gCurrentContext);
404		oalSource = oalContext->ProtectSource(inSID);
405		if (oalSource == NULL)
406			throw ((OSStatus) AL_INVALID_NAME);		// per OpenAL 1.1 spec
407
408		ReleaseContextObject(oalContext);
409	}
410	catch (OSStatus stat) {
411		ReleaseContextObject(oalContext);
412		throw stat;
413	}
414	catch (...) {
415		ReleaseContextObject(oalContext);
416		throw -1;
417	}
418
419	return oalSource;
420}
421
422// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423void ReleaseSourceObject(OALSource *inSource)
424{
425	if (inSource) inSource->ClearInUseFlag();
426}
427
428// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
429OALBuffer*	ProtectBufferObject(ALuint	inBID)
430{
431	OALBuffer *oalBuffer = NULL;
432
433	if (gOALBufferMap == NULL)
434		throw ((OSStatus) AL_INVALID_OPERATION);
435
436	CAGuard::Locker locked(*gBufferMapLock);
437
438	CleanUpDeadBufferList();
439
440	oalBuffer = gOALBufferMap->Get(inBID);
441	if (oalBuffer == NULL)
442		throw ((OSStatus) AL_INVALID_VALUE);
443
444	// we need to signal the buffer is being used, and cannot be deleted yet
445	oalBuffer->SetInUseFlag();
446
447	return oalBuffer;
448}
449
450// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
451// ReleaseBufferObject must be called when finished using the returned object
452void ReleaseBufferObject(OALBuffer* inBuffer)
453{
454	if (inBuffer) inBuffer->ClearInUseFlag();
455}
456
457// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
458ALboolean	IsValidBufferObject(ALuint	inBID)
459{
460	if (inBID == 0) return true;	// 0 == AL_NONE which is valid
461
462	ALboolean isBuffer = AL_FALSE;
463	OALBuffer *oalBuffer = NULL;
464
465	try {
466        if (gOALBufferMap == NULL)
467            throw ((OSStatus) AL_INVALID_OPERATION);
468
469		oalBuffer = ProtectBufferObject(inBID);
470
471        if (oalBuffer != NULL)
472            isBuffer = AL_TRUE;
473        else
474            isBuffer = AL_FALSE;
475    }
476	catch (OSStatus result) {
477		isBuffer = AL_FALSE;
478		ReleaseBufferObject(oalBuffer);
479		throw result;
480	}
481	ReleaseBufferObject(oalBuffer);
482	return isBuffer;
483}
484
485// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
486void	InitializeBufferMap()
487{
488	if (gOALBufferMap == NULL)
489	{
490		gOALBufferMap = new OALBufferMap ();						// create the buffer map since there isn't one yet
491		gBufferMapLock = new CAGuard("OAL:BufferMapLock");				// create the buffer map mutex
492		gDeadOALBufferMap = new OALBufferMap ();					// create the buffer map since there isn't one yet
493
494		// populate the good buffer with the AL_NONE buffer, it should never be deleted
495		OALBuffer	*newBuffer = new OALBuffer (AL_NONE);
496		gOALBufferMap->Add(AL_NONE, &newBuffer);							// add the new buffer to the buffer map
497	}
498}
499
500// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
501// walk through the context map and find the ones that are linked to this device
502void	DeleteContextsOfThisDevice(uintptr_t inDeviceToken)
503{
504	if (gOALContextMap == NULL)
505		return;
506
507	try {
508		CAGuard::Locker locked(*gContextMapLock);
509
510		for (UInt32	i = 0; i < gOALContextMap->Size(); i++)
511		{
512			uintptr_t		contextToken = 0;
513			OALContext		*oalContext = gOALContextMap->GetContextByIndex(i, contextToken);
514
515            if (oalContext == NULL)
516                throw ((OSStatus) AL_INVALID_OPERATION);
517
518			if (oalContext->GetDeviceToken() == inDeviceToken)
519			{
520				// delete this context, it belongs to the device that is going away
521				if (contextToken == gCurrentContext)
522				{
523					// this context is the current context, so remove it as the current context first
524					alcMakeContextCurrent(NULL);
525				}
526
527				if (gOALContextMap->Remove(contextToken)) {
528					while(oalContext->IsInUse())
529						usleep(10000);
530
531					delete (oalContext);
532					i--; // try this index again since it was just deleted
533				}
534			}
535		}
536	}
537	catch (OSStatus     result) {
538		alSetError(result);
539	}
540	catch (...) {
541		alSetError(AL_INVALID_VALUE);
542	}
543}
544
545// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
546// Walk through the context map and reconfigure the ones that are linked to this device.
547// They should all be disconnected right now so it is safe to do so - called from the device object
548void	ReconfigureContextsOfThisDevice(uintptr_t inDeviceToken)
549{
550	if (gOALContextMap == NULL)
551		return; // there aren't any contexts to configure
552
553	uintptr_t		contextToken;
554	OALContext		*oalContext = NULL;
555	for (UInt32	i = 0; i < gOALContextMap->Size(); i++)
556	{
557		oalContext = gOALContextMap->GetContextByIndex(i, contextToken);
558		if (oalContext != NULL && (oalContext->GetDeviceToken() == inDeviceToken))  {
559			// found a context that uses this device
560			oalContext->ConfigureMixerFormat();	// reconfigure the output format of the context's mixer
561		}
562	}
563}
564
565// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566ALCint   alcCheckUnitIsPresent(OSType componentSubType)
567{
568	ALCint isPresent = kUnknownAUState;
569
570	ComponentDescription	desc;
571	desc.componentFlags = 0;
572	desc.componentFlagsMask = 0;
573	desc.componentType = kAudioUnitType_Effect;
574	desc.componentSubType = componentSubType;
575	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
576
577	isPresent = (FindNextComponent(0, &desc) != 0) ? kAUIsPresent : kAUIsNotPresent;
578
579	return isPresent;
580}
581
582// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
583ALCint  IsRogerBeepPresent()
584{
585	static	ALCint isPresent = kUnknownAUState;
586	if (isPresent == kUnknownAUState)
587		isPresent = alcCheckUnitIsPresent(kRogerBeepType);
588
589	return isPresent;
590}
591
592// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
593ALCint  IsDistortionPresent()
594{
595	static	ALCint isPresent = kUnknownAUState;
596	if (isPresent == kUnknownAUState)
597		isPresent = alcCheckUnitIsPresent(kDistortionType);
598
599	return isPresent;
600}
601
602// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
603// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
604// ALC Methods
605// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
606// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
607#pragma mark ***** ALC - METHODS *****
608
609// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
610// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
611// Device APIs
612// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
613// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614
615// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
616#pragma mark ***** Capture Devices*****
617// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
618ALC_API ALCdevice*      ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize )
619{
620#if LOG_CAPTURE_USAGE
621	DebugMessageN3("alcCaptureOpenDevice:  format %s : sample rate = %ld : buffer size = %ld", GetFormatString(format), (long int) frequency, (long int) buffersize);
622#endif
623
624	uintptr_t			newDeviceToken = 0;
625	OALCaptureDevice	*newDevice = NULL;
626
627	try {
628		if(!IsFormatSupported(format))
629			throw ((OSStatus) AL_INVALID_VALUE);
630
631		if (gOALCaptureDeviceMap == NULL)
632		{
633			gOALCaptureDeviceMap = new OALCaptureDeviceMap ();                          // create the device map if there isn't one yet
634			gCaptureDeviceMapLock = new CAGuard("OAL:CaptureLock");								// create the list guard for thread safety
635		}
636
637        newDeviceToken = GetNewPtrToken();                                              // get a unique token
638        newDevice = new OALCaptureDevice((const char *) devicename, newDeviceToken, frequency, format, buffersize);	// create a new device object
639        if (newDevice == NULL)
640			throw ((OSStatus) AL_INVALID_OPERATION);
641
642		{
643			CAGuard::Locker locked(*gCaptureDeviceMapLock);
644			gOALCaptureDeviceMap->Add(newDeviceToken, &newDevice);						// add the new device to the device map
645
646		}
647	}
648	catch (OSStatus result) {
649		DebugMessageN1("ERROR: alcCaptureOpenDevice FAILED = %s\n", alcGetString(NULL, result));
650		if (newDevice) delete (newDevice);
651		newDeviceToken = 0;
652	}
653	catch (...) {
654		DebugMessage("ERROR: alcCaptureOpenDevice FAILED");
655		if (newDevice) delete (newDevice);
656		newDeviceToken = 0;
657	}
658
659	return ((ALCdevice *) newDeviceToken);
660}
661
662// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
663ALC_API ALCboolean	ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device )
664{
665#if LOG_CAPTURE_USAGE
666	DebugMessage("alcCaptureCloseDevice");
667#endif
668
669	try {
670		if (gOALCaptureDeviceMap == NULL)
671			throw ((OSStatus)AL_INVALID_OPERATION);
672
673		OALCaptureDevice *oalCaptureDevice = NULL;
674
675		{
676			CAGuard::Locker locked(*gCaptureDeviceMapLock);												// map operations are not thread-safe
677
678			oalCaptureDevice = gOALCaptureDeviceMap->Get((uintptr_t) device);
679			if (oalCaptureDevice == NULL)
680				throw ((OSStatus) AL_INVALID_VALUE);
681
682			gOALCaptureDeviceMap->Remove((uintptr_t) device);									// remove the device from the map
683
684			while(oalCaptureDevice->IsInUse())
685				usleep(10000);
686
687			delete (oalCaptureDevice);															// destruct the device object
688
689			if (gOALCaptureDeviceMap->Empty())
690			{
691				// there are no more devices in the map, so delete the map and create again later if needed
692				delete (gOALCaptureDeviceMap);
693				gOALCaptureDeviceMap = NULL;
694			}
695		}
696
697		// if we deleted the map, we can delete the lock as well
698		if (gOALCaptureDeviceMap == NULL)
699			delete gCaptureDeviceMapLock;
700	}
701	catch (OSStatus   result) {
702		DebugMessageN1("ERROR: alcCaptureCloseDevice FAILED = %s\n", alcGetString(NULL, result));
703	}
704    catch (...) {
705		DebugMessage("ERROR: alcCaptureCloseDevice FAILED");
706	}
707
708	return AL_TRUE;
709}
710
711// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
712ALC_API void   ALC_APIENTRY alcCaptureStart( ALCdevice *device )
713{
714#if LOG_CAPTURE_USAGE
715	DebugMessage("alcCaptureStart");
716#endif
717
718	OALCaptureDevice *oalCaptureDevice = NULL;
719
720	try {
721		oalCaptureDevice = ProtectCaptureDeviceObject ((uintptr_t) device);
722        oalCaptureDevice->StartCapture();
723	}
724	catch (OSStatus   result) {
725		DebugMessageN1("ERROR: alcCaptureStart FAILED = %s\n", alcGetString(NULL, result));
726		SetDeviceError((uintptr_t) device, result);
727	}
728    catch (...) {
729		DebugMessage("ERROR: alcCaptureStart FAILED");
730		SetDeviceError((uintptr_t) device, AL_INVALID_OPERATION);
731	}
732
733	ReleaseCaptureDeviceObject(oalCaptureDevice);
734}
735
736// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
737ALC_API void	ALC_APIENTRY alcCaptureStop( ALCdevice *device )
738{
739#if LOG_CAPTURE_USAGE
740	DebugMessage("alcCaptureStop");
741#endif
742
743	OALCaptureDevice *oalCaptureDevice = NULL;
744
745	try {
746		oalCaptureDevice = ProtectCaptureDeviceObject ((uintptr_t) device);
747        oalCaptureDevice->StopCapture();
748	}
749	catch (OSStatus   result) {
750		DebugMessageN1("ERROR: alcCaptureStop FAILED = %s\n", alcGetString(NULL, result));
751		SetDeviceError((uintptr_t) device, result);
752	}
753    catch (...) {
754		DebugMessage("ERROR: alcCaptureStop FAILED");
755		SetDeviceError((uintptr_t) device, AL_INVALID_OPERATION);
756	}
757
758	ReleaseCaptureDeviceObject(oalCaptureDevice);
759}
760
761// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
762ALC_API void	ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples )
763{
764#if LOG_CAPTURE_USAGE
765	DebugMessage("alcCaptureSamples");
766#endif
767
768	OALCaptureDevice *oalCaptureDevice = NULL;
769
770	try {
771		oalCaptureDevice = ProtectCaptureDeviceObject ((uintptr_t) device);
772        oalCaptureDevice->GetFrames(samples, (UInt8*) buffer);
773	}
774	catch (OSStatus   result) {
775		DebugMessageN1("ERROR: alcCaptureSamples FAILED = %s\n", alcGetString(NULL, result));
776		SetDeviceError((uintptr_t) device, result);
777	}
778    catch (...) {
779		DebugMessage("ERROR: alcCaptureSamples FAILED");
780		SetDeviceError((uintptr_t) device, AL_INVALID_OPERATION);
781	}
782
783	ReleaseCaptureDeviceObject(oalCaptureDevice);
784}
785
786// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
787#pragma mark ***** Devices *****
788// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
789ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALchar *deviceName)
790{
791	uintptr_t	newDeviceToken = 0;
792	OALDevice	*newDevice = NULL;
793
794#if LOG_API_USAGE
795	DebugMessage("alcOpenDevice");
796#endif
797
798	try {
799		if (Get3DMixerVersion() == kUnsupported3DMixer)
800			throw -1;
801
802		if (gOALDeviceMap == NULL)
803		{
804			gOALDeviceMap = new OALDeviceMap ();                                // create the device map if there isn't one yet
805			gDeviceMapLock = new CAGuard("OAL:DeviceLock");
806		}
807
808        newDeviceToken = GetNewPtrToken();																// get a unique token
809        newDevice = new OALDevice((const char *) deviceName, newDeviceToken, gRenderChannelSetting);	// create a new device object
810        if (newDevice == NULL)
811			throw ((OSStatus) AL_INVALID_OPERATION);
812		{
813			// the map is not thread-safe. We need to protect any manipulation to it
814			CAGuard::Locker locked(*gDeviceMapLock);
815			gOALDeviceMap->Add(newDeviceToken, &newDevice);												// add the new device to the device map
816		}
817	}
818	catch (OSStatus result) {
819		DebugMessageN1("ERROR: alcOpenDevice FAILED = %s\n", alcGetString(NULL, result));
820		if (newDevice) delete (newDevice);
821		SetDeviceError(gCurrentDevice, result);
822		newDeviceToken = 0;
823    }
824	catch (...) {
825		DebugMessage("ERROR: alcOpenDevice FAILED");
826		if (newDevice) delete (newDevice);
827		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
828		newDeviceToken = 0;
829	}
830
831	return ((ALCdevice *) newDeviceToken);
832}
833
834
835// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
836ALC_API ALCboolean   ALC_APIENTRY alcCloseDevice(ALCdevice *device)
837{
838#if LOG_API_USAGE
839	DebugMessage("alcCloseDevice");
840#endif
841	ALCboolean result = ALC_TRUE;
842
843	OALDevice *oalDevice = NULL;
844
845	try {
846		if (gOALDeviceMap == NULL)
847            throw ((OSStatus) AL_INVALID_OPERATION);
848
849		oalDevice = gOALDeviceMap->Get((uintptr_t) device);	// get the requested oal device
850		if (oalDevice == NULL)
851			throw ((OSStatus) AL_INVALID_VALUE);
852
853		{
854			CAGuard::Locker locked(*gDeviceMapLock);
855
856			gOALDeviceMap->Remove((uintptr_t) device);								// remove the device from the map
857
858			DeleteContextsOfThisDevice((uintptr_t) device);
859
860			// we cannot delete this object until all methods using it have released it
861			while(oalDevice->IsInUse())
862				usleep(10000);
863
864			delete (oalDevice);														// destruct the device object
865
866			if (gOALDeviceMap->Empty())
867			{
868				// there are no more devices in the map, so delete the map and create again later if needed
869				delete (gOALDeviceMap);
870				gOALDeviceMap = NULL;
871			}
872		}
873
874		// if we deleted the map, we can delete the lock as well
875		if (gOALDeviceMap == NULL)
876			delete gDeviceMapLock;
877	}
878	catch (OSStatus   result) {
879		DebugMessageN1("ERROR: alcCloseDevice FAILED = %s\n", alcGetString(NULL, result));
880		SetDeviceError(gCurrentDevice, result);
881		result = ALC_FALSE;
882	}
883    catch (...) {
884		DebugMessage("ERROR: alcCloseDevice FAILED");
885		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
886		result = ALC_FALSE;
887	}
888
889	return result;
890}
891
892// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
893ALC_API ALCenum  ALC_APIENTRY alcGetError(ALCdevice *device)
894{
895#if LOG_API_USAGE
896	DebugMessage("alcGetError");
897#endif
898	ALCenum error = noErr;
899
900	try {
901		if (gOALDeviceMap)
902		{
903			OALDevice*		oalDevice = gOALDeviceMap->Get((uintptr_t) device);
904			if (oalDevice)
905				error = oalDevice->GetError();
906		}
907		else if (gOALCaptureDeviceMap)
908		{
909			CAGuard::Locker locked(*gCaptureDeviceMapLock);
910
911			OALCaptureDevice			*oalCaptureDevice = gOALCaptureDeviceMap->Get((uintptr_t) device);	// get the requested oal device
912			if (oalCaptureDevice)
913				error = oalCaptureDevice->GetError();
914		}
915		else
916			error = ALC_INVALID_DEVICE;
917	}
918	catch (OSStatus	result) {
919		DebugMessage("ERROR: alcGetError FAILED: ALC_INVALID_DEVICE");
920		error = ALC_INVALID_DEVICE;
921	}
922	catch (...) {
923		DebugMessage("ERROR: alcGetError FAILED: ALC_INVALID_DEVICE");
924		error = ALC_INVALID_DEVICE;
925	}
926
927	return error;	// don't know about this device
928}
929
930// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
931// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
932// Context APIs
933// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
934// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
935#pragma mark ***** Contexts *****
936
937// There is no attribute support yet
938ALC_API ALCcontext* 	ALC_APIENTRY alcCreateContext(ALCdevice *device,	const ALCint *attrList)
939{
940	uintptr_t		newContextToken = 0;
941	OALContext		*newContext = NULL;
942
943#if LOG_API_USAGE
944	DebugMessageN1("alcCreateContext--> device = %ld", (long int) device);
945#endif
946
947	OALDevice	*oalDevice = NULL;
948
949	try {
950
951		oalDevice = ProtectDeviceObject ((uintptr_t) device);
952
953		// create the context map if there isn't one yet
954		if (gOALContextMap == NULL)
955		{
956			gOALContextMap = new OALContextMap();
957			gContextMapLock = new CAGuard("OAL:ContextMapLock");
958		}
959		newContextToken = GetNewPtrToken();
960
961		// use the attribute hint for mono/stereo sources to set gMaximumMixerBusCount
962		// will only grow gMaximumMixerBusCount not shrink it below the default mixer bus count of 64
963		UInt32	sourceCount = CalculateNeededMixerBusses(attrList, gMaximumMixerBusCount);
964
965		// if the application has explicitly set a mixer output rate, use it,
966		// otherwise just use the device's sample rate
967		Float64		mixerOutputRate = gMixerOutputRate > 0.0 ? gMixerOutputRate : oalDevice->GetDeviceSampleRate();
968		newContext = new OALContext(newContextToken, oalDevice, attrList, sourceCount, mixerOutputRate);
969		{
970			CAGuard::Locker locked(*gContextMapLock);
971			gOALContextMap->Add(newContextToken, &newContext);
972		}
973	}
974	catch (OSStatus     result){
975		DebugMessageN1("ERROR: alcCreateContext FAILED = %s\n", alcGetString(NULL, result));
976		if (newContext) delete (newContext);
977		SetDeviceError(gCurrentDevice, result);
978		newContextToken = 0;
979	}
980    catch (...) {
981		DebugMessage("ERROR: alcCreateContext FAILED");
982		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
983		newContextToken = 0;
984	}
985
986	ReleaseDeviceObject(oalDevice);
987
988	return ((ALCcontext *) newContextToken);
989}
990
991// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
992ALC_API ALCboolean  ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
993{
994#if LOG_API_USAGE
995	DebugMessageN1("alcMakeContextCurrent--> context = %ld", (long int) context);
996#endif
997
998	OALContext		*newContext = NULL;
999	OALContext		*currentContext = NULL;
1000	ALCboolean		result = ALC_TRUE;
1001
1002	if ((uintptr_t) context == gCurrentContext)
1003		return ALC_TRUE;								// no change necessary, already using this context
1004
1005	try {
1006		if ((gOALContextMap == NULL) || (gOALDeviceMap == NULL))
1007            throw ((OSStatus) AL_INVALID_OPERATION);
1008
1009		// get the current context if there is one
1010		if (gCurrentContext != 0)
1011			currentContext = ProtectContextObject(gCurrentContext);
1012
1013		if (context == 0)
1014		{
1015			// Changing Current Context to NULL
1016			gCurrentDevice = 0;
1017			gCurrentContext = 0;
1018
1019			currentContext->DisconnectMixerFromDevice();
1020		}
1021		else
1022		{
1023			// Switching to a new Context
1024			newContext = ProtectContextObject((uintptr_t) context);
1025
1026			uintptr_t newCurrentDeviceToken = 0;
1027			{
1028				CAGuard::Locker locked(*gContextMapLock);
1029				// find the device that owns this context
1030				newCurrentDeviceToken = gOALContextMap->GetDeviceTokenForContext((uintptr_t) context);
1031			}
1032			// store the new current context and device
1033			gCurrentDevice = newCurrentDeviceToken;
1034			gCurrentContext = (uintptr_t) context;
1035
1036			newContext->ConnectMixerToDevice();
1037		}
1038
1039		result = ALC_TRUE;
1040	}
1041	catch (OSStatus result) {
1042		DebugMessageN1("ERROR: alcMakeContextCurrent FAILED = %s\n", alcGetString(NULL, result));
1043		// get the Device object for this context so we can set an error code
1044		SetDeviceError(gCurrentDevice, result);
1045		result = ALC_FALSE;
1046	}
1047	catch (...) {
1048		DebugMessage("ERROR: alcMakeContextCurrent FAILED");
1049		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
1050		result = ALC_FALSE;
1051	}
1052
1053	ReleaseContextObject(currentContext);
1054	ReleaseContextObject(newContext);
1055
1056	return result;
1057}
1058
1059// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1060ALC_API ALCvoid	  ALC_APIENTRY alcProcessContext(ALCcontext *context)
1061{
1062#if LOG_API_USAGE
1063	DebugMessageN1("alcProcessContext--> context = %ld", (long int) context);
1064#endif
1065
1066	return; // no op
1067}
1068
1069// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1070ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
1071{
1072#if LOG_API_USAGE
1073	DebugMessage("alcGetCurrentContext");
1074#endif
1075
1076	return ((ALCcontext *) gCurrentContext);
1077}
1078
1079// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1080// find out what device the context uses
1081ALC_API ALCdevice*  ALC_APIENTRY alcGetContextsDevice(ALCcontext *context)
1082{
1083	UInt32	returnValue = 0;
1084
1085#if LOG_API_USAGE
1086	DebugMessageN1("alcGetContextsDevice--> context = %ld", (long int) context);
1087#endif
1088
1089	try {
1090        if (gOALContextMap == NULL)
1091            throw ((OSStatus) AL_INVALID_OPERATION);
1092		{
1093			CAGuard::Locker locked(*gContextMapLock);
1094			returnValue = gOALContextMap->GetDeviceTokenForContext((uintptr_t) context);
1095		}
1096    }
1097    catch (OSStatus result) {
1098		DebugMessageN1("ERROR: alcGetContextsDevice FAILED = %s\n", alcGetString(NULL, result));
1099		SetDeviceError(gCurrentDevice, result);
1100    }
1101    catch (...) {
1102		DebugMessage("ERROR: alcGetContextsDevice FAILED");
1103		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
1104	}
1105
1106	return ((ALCdevice*) returnValue);
1107}
1108
1109// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1110ALC_API ALCvoid	  ALC_APIENTRY alcSuspendContext(ALCcontext *context)
1111{
1112#if LOG_API_USAGE
1113	DebugMessageN1("alcSuspendContext--> context = %ld", (long int) context);
1114#endif
1115
1116	return; // no op
1117}
1118
1119// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1120ALC_API ALCvoid	ALC_APIENTRY alcDestroyContext (ALCcontext *context)
1121{
1122#if LOG_API_USAGE
1123	DebugMessageN1("alcDestroyContext--> context = %ld", (long int) context);
1124#endif
1125
1126	try {
1127        // if this was the current context, return an error
1128        if (gCurrentContext == (uintptr_t) context)
1129            throw ((OSStatus) AL_INVALID_OPERATION);
1130
1131		if (gOALContextMap == NULL)
1132            throw ((OSStatus) AL_INVALID_OPERATION);
1133
1134		CAGuard::Locker locked(*gContextMapLock);
1135
1136		bool			stopGraph = true;
1137		OALContext*		deleteThisContext = gOALContextMap->Get((uintptr_t) context);
1138		uintptr_t		deviceForThisContext = deleteThisContext->GetDeviceToken();
1139
1140		if (!gOALContextMap->Remove((uintptr_t) context))	// remove from the map
1141			throw ((OSStatus) ALC_INVALID_CONTEXT);
1142
1143		// if there are no other contexts that use the same device, the device graph can be stopped now
1144		for (UInt32 i = 0; i < gOALContextMap->Size(); i++)
1145		{
1146			uintptr_t		token;
1147			OALContext		*context = gOALContextMap->GetContextByIndex(i, token);
1148			if (context)
1149			{
1150				if (context->GetDeviceToken() == deviceForThisContext)
1151				{
1152					// some other context still exists that uses this device, so leave it running
1153					stopGraph = false;
1154					break;
1155				}
1156			}
1157		}
1158
1159		if (stopGraph)
1160		{
1161			OALDevice		*owningDevice = ProtectDeviceObject(deviceForThisContext);
1162			if (owningDevice)
1163			{
1164				owningDevice->StopGraph();	// if there are no context's there is no reason for the device's graph to be running
1165				ReleaseDeviceObject(owningDevice);
1166			}
1167		}
1168
1169        //only delete the context after the graph has been stopped.
1170        delete(deleteThisContext);
1171        deleteThisContext = NULL;
1172
1173	}
1174	catch (OSStatus     result) {
1175		DebugMessageN1("ERROR: alcDestroyContext FAILED = %s\n", alcGetString(NULL, result));
1176		SetDeviceError(gCurrentDevice, result);
1177	}
1178    catch (...) {
1179		DebugMessage("ERROR: alcDestroyContext FAILED");
1180		SetDeviceError(gCurrentDevice, AL_INVALID_OPERATION);
1181	}
1182}
1183
1184// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1185// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1186// Other APIs
1187// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1188// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1189#pragma mark ***** Other *****
1190
1191// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1192ALC_API const ALCchar *	ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum pname)
1193{
1194#if LOG_API_USAGE
1195	DebugMessageN1("alcGetString-->  %s", GetALCAttributeString(pname));
1196#endif
1197
1198	try {
1199
1200		switch (pname)
1201		{
1202			case ALC_DEFAULT_DEVICE_SPECIFIER:
1203				GetDefaultDeviceName(gDefaultOutputDeviceName, false);
1204				return gDefaultOutputDeviceName;
1205				break;
1206
1207			case ALC_DEVICE_SPECIFIER:
1208			{
1209				GetDefaultDeviceName(gDefaultOutputDeviceName, false);
1210				// if a null pointer is specified, double terminate the device list
1211				// currently we only allow use of the default device. if this changes
1212				// we will need to update this mechanism to return all the devices available
1213				if (device == NULL)
1214				{
1215					UInt32	length = strlen(gDefaultOutputDeviceName);
1216					gDefaultOutputDeviceName[length + 1] = '\0'; // double terminator
1217				}
1218				return gDefaultOutputDeviceName;
1219			}
1220				break;
1221
1222			case ALC_EXTENSIONS:
1223				// 1.1 doc: if deviceHandle is NULL for this, set error to ALC_INVALID_DEVICE
1224				if (device == NULL)
1225					throw (OSStatus) ALC_INVALID_DEVICE;
1226				else
1227					return (ALchar *) GetALCExtensionList();
1228				break;
1229
1230			case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
1231				GetDefaultDeviceName(gDefaultInputDeviceName, true);
1232				return gDefaultInputDeviceName;
1233				break;
1234
1235			case ALC_CAPTURE_DEVICE_SPECIFIER:
1236			{
1237				GetDefaultDeviceName(gDefaultInputDeviceName, true);
1238				// if a null pointer is specified, double terminate the device list
1239				// currently we only allow use of the default device. if this changes
1240				// we will need to update this mechanism to return all the devices available
1241				if (device == NULL)
1242				{
1243					UInt32	length = strlen(gDefaultInputDeviceName);
1244					gDefaultInputDeviceName[length + 1] = '\0'; // double terminator
1245				}
1246				return gDefaultInputDeviceName;
1247			}
1248				break;
1249
1250			case ALC_NO_ERROR:
1251				return (ALchar *) alNoError;
1252				break;
1253
1254			case ALC_INVALID_DEVICE:
1255				return (ALchar *) alcErrInvalidDevice;
1256				break;
1257
1258			case ALC_INVALID_CONTEXT:
1259				return (ALchar *) alcErrInvalidContext;
1260				break;
1261
1262			case ALC_INVALID_ENUM:
1263				return (ALchar *) alErrInvalidEnum;
1264				break;
1265
1266			case ALC_INVALID_VALUE:
1267				return (ALchar *) alErrInvalidValue;
1268				break;
1269
1270			default:
1271				throw (OSStatus) AL_INVALID_VALUE;
1272				break;
1273		}
1274	}
1275	catch (OSStatus		result) {
1276		alSetError(result);
1277 		DebugMessageN2("ERROR: alcGetString FAILED - attribute = %s error = %s\n", GetALCAttributeString(pname), alcGetString(NULL, result));
1278    }
1279	catch (...) {
1280 		DebugMessageN1("ERROR: alcGetString FAILED - attribute = %s", GetALCAttributeString(pname));
1281	}
1282
1283	return NULL;
1284}
1285
1286// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1287ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname)
1288{
1289#if LOG_API_USAGE
1290	DebugMessageN1("alcIsExtensionPresent-->  extension = %s", extname);
1291#endif
1292
1293	ALCboolean	returnValue = AL_FALSE;
1294
1295	if (extname == NULL)
1296	{
1297		if (device)
1298			SetDeviceError((uintptr_t) device, ALC_INVALID_VALUE);
1299		else
1300			SetDeviceError(gCurrentDevice, ALC_INVALID_VALUE);
1301	}
1302	else
1303	{
1304        //first compare to see if the strings match
1305        if(strstr(GetALCExtensionList(), extname) != NULL)
1306        {
1307            returnValue = AL_TRUE;
1308        }
1309        else
1310        {
1311            //convert the extension base to upper case
1312            ALCchar* extbase = GetALCExtensionList();
1313            ALCchar* extbaseUpper = (ALCchar*)calloc(1, (strlen(extbase)+1)*sizeof(ALCchar));
1314            if (extbaseUpper)
1315            {
1316                for (unsigned int i=0; i < strlen(extbase); i++)
1317                {
1318                    extbaseUpper[i] = toupper(extbase[i]);
1319                }
1320
1321                ALCchar* extnameUpper = (ALCchar*)calloc(1, (strlen(extname)+1)*sizeof(ALCchar));
1322                if (extnameUpper)
1323                {
1324                    for (unsigned int i=0; i < strlen(extname); i++)
1325                    {
1326                        extnameUpper[i] = toupper(extname[i]);
1327                    }
1328
1329                    //compare the strings after having converted both to upper case
1330                    if (strstr(extbaseUpper, extnameUpper) != NULL) {
1331                        returnValue = AL_TRUE;
1332                    }
1333
1334                    free(extnameUpper);
1335                }
1336
1337                free(extbaseUpper);
1338            }
1339        }
1340	}
1341
1342	return returnValue;    // extension not present in this implementation
1343}
1344
1345// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1346ALC_API void*  ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
1347{
1348#if LOG_API_USAGE
1349	DebugMessageN1("alcGetProcAddress--> function name = %s", funcname);
1350#endif
1351
1352	return (alGetProcAddress(funcname));
1353}
1354
1355// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1356ALC_API ALenum  ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1357{
1358#if LOG_API_USAGE
1359	DebugMessageN1("alcGetEnumValue--> enum name = %s", enumName);
1360#endif
1361
1362	return (alGetEnumValue (enumName));
1363}
1364
1365// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1366AL_API ALint AL_APIENTRY alcGetInteger (ALCdevice *device, ALenum pname)
1367{
1368#if LOG_API_USAGE
1369	DebugMessageN2("alcGetInteger--> device = %ld attribute name = %s", (long int) device, GetALCAttributeString(pname));
1370#endif
1371
1372	UInt32				returnValue	= 0;
1373	OALCaptureDevice	*oalCaptureDevice = NULL;
1374	OALDevice			*oalDevice = NULL;
1375	OALContext			*oalContext = NULL;
1376
1377	if (gOALDeviceMap)
1378	{
1379		CAGuard::Locker locked(*gDeviceMapLock);
1380		oalDevice = gOALDeviceMap->Get((uintptr_t) device);	// get the requested oal device
1381
1382		if (oalDevice) oalDevice->SetInUseFlag();
1383	}
1384
1385	if (!oalDevice && gOALCaptureDeviceMap != NULL)
1386	{
1387		CAGuard::Locker locked(*gCaptureDeviceMapLock);
1388		oalCaptureDevice = gOALCaptureDeviceMap->Get((uintptr_t) device);		// it's not an output device, look for a capture device
1389
1390		if (oalCaptureDevice) oalCaptureDevice->SetInUseFlag();
1391	}
1392
1393	try {
1394
1395		switch (pname)
1396		{
1397			case ALC_ATTRIBUTES_SIZE:
1398
1399				if (device == NULL || !oalDevice || device != alcGetContextsDevice((ALCcontext*) gCurrentContext))
1400					throw (OSStatus) ALC_INVALID_DEVICE;
1401				else
1402				{
1403					oalContext = ProtectContextObject(gCurrentContext);
1404					returnValue = oalContext->GetAttributeListSize();
1405				}
1406				break;
1407
1408			case ALC_MAJOR_VERSION:
1409				returnValue = kMajorVersion;
1410				break;
1411
1412			case ALC_MINOR_VERSION:
1413				returnValue = kMinorVersion;
1414				break;
1415
1416			case ALC_CAPTURE_SAMPLES:
1417				if (oalCaptureDevice == NULL)
1418					throw (OSStatus) ALC_INVALID_DEVICE;
1419				returnValue = oalCaptureDevice->AvailableFrames();
1420				break;
1421
1422			default:
1423				throw (OSStatus) AL_INVALID_VALUE;
1424				break;
1425		}
1426	}
1427	catch (OSStatus		result) {
1428		if (oalDevice)
1429			oalDevice->SetError(result);
1430		else if(oalCaptureDevice)
1431			oalCaptureDevice->SetError(result);
1432		else
1433			alSetError(result);
1434
1435		DebugMessageN3("ERROR: alcGetInteger FAILED: device = %ld attribute name = %s error = %s", (long int) device, GetALCAttributeString(pname), alcGetString(NULL, result));
1436    }
1437	catch (...) {
1438		DebugMessageN3("ERROR: alcGetInteger FAILED: device = %ld attribute name = %s error = %s", (long int) device, GetALCAttributeString(pname), "Unknown Error");
1439	}
1440
1441	ReleaseDeviceObject(oalDevice);
1442	ReleaseCaptureDeviceObject(oalCaptureDevice);
1443	ReleaseContextObject(oalContext);
1444
1445	return (returnValue);
1446}
1447
1448// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1449ALC_API ALCvoid     ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint *data)
1450{
1451#if LOG_API_USAGE
1452	DebugMessageN2("alcGetIntegerv--> device = %ld attribute name = %s", (long int) device, GetALCAttributeString(pname));
1453#endif
1454
1455	// get the device
1456	OALCaptureDevice	*oalCaptureDevice = NULL;
1457	OALDevice			*oalDevice = NULL;
1458	OALContext			*oalContext = NULL;
1459
1460	if (gOALDeviceMap)
1461	{
1462		CAGuard::Locker locked(*gDeviceMapLock);
1463		oalDevice = gOALDeviceMap->Get((uintptr_t) device);	// get the requested oal device
1464
1465		if (oalDevice) oalDevice->SetInUseFlag();
1466	}
1467
1468	if (!oalDevice && gOALCaptureDeviceMap != NULL)
1469	{
1470		CAGuard::Locker locked(*gCaptureDeviceMapLock);
1471		oalCaptureDevice = gOALCaptureDeviceMap->Get((uintptr_t) device);		// it's not an output device, look for a capture device
1472
1473		if (oalCaptureDevice) oalCaptureDevice->SetInUseFlag();
1474	}
1475	try {
1476
1477		if ((data == NULL) || (size == 0))
1478			throw (OSStatus)ALC_INVALID_VALUE;
1479
1480		switch (pname)
1481		{
1482			case ALC_ATTRIBUTES_SIZE:
1483
1484				if (device == NULL || !oalDevice || device != alcGetContextsDevice((ALCcontext*) gCurrentContext))
1485					throw (OSStatus) ALC_INVALID_DEVICE;
1486				else
1487				{
1488					oalContext = ProtectContextObject(gCurrentContext);
1489					*data = oalContext->GetAttributeListSize();
1490				}
1491				break;
1492
1493			case ALC_ALL_ATTRIBUTES:
1494
1495				if (device == NULL || !oalDevice || device != alcGetContextsDevice((ALCcontext*) gCurrentContext))
1496					throw (OSStatus) ALC_INVALID_DEVICE;
1497				else
1498				{
1499					oalContext = ProtectContextObject(gCurrentContext);
1500					if (size < (ALCsizei) oalContext->GetAttributeListSize())
1501						throw (OSStatus) ALC_INVALID_VALUE;
1502
1503					oalContext->CopyAttributeList(data);
1504				}
1505				break;
1506
1507			case ALC_MAJOR_VERSION:
1508				*data = kMajorVersion;
1509				break;
1510
1511			case ALC_MINOR_VERSION:
1512				*data = kMinorVersion;
1513				break;
1514			case ALC_CAPTURE_SAMPLES:
1515				if (oalCaptureDevice == NULL)
1516					throw (OSStatus) ALC_INVALID_DEVICE;
1517				*data = oalCaptureDevice->AvailableFrames();
1518				break;
1519
1520			default:
1521				throw (OSStatus) AL_INVALID_VALUE;
1522				break;
1523		}
1524	}
1525	catch (OSStatus		result) {
1526		if (oalDevice)
1527			oalDevice->SetError(result);
1528		else if(oalCaptureDevice)
1529			oalCaptureDevice->SetError(result);
1530		else
1531			alSetError(result);
1532
1533		DebugMessageN3("ERROR: alcGetInteger FAILED: device = %ld attribute name = %s error = %s", (long int) device, GetALCAttributeString(pname), alcGetString(NULL, result));
1534    }
1535	catch (...) {
1536		DebugMessageN3("ERROR: alcGetInteger FAILED: device = %ld attribute name = %s error = %s", (long int) device, GetALCAttributeString(pname), "Unknown Error");
1537	}
1538
1539	ReleaseDeviceObject(oalDevice);
1540	ReleaseCaptureDeviceObject(oalCaptureDevice);
1541	ReleaseContextObject(oalContext);
1542}
1543
1544// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1545// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1546// AL Methods
1547// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1548// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1549#pragma mark ***** AL - METHODS *****
1550
1551// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1552AL_API ALenum AL_APIENTRY alGetError ()
1553{
1554    ALenum	error = AL_NO_ERROR;
1555
1556#if LOG_API_USAGE && LOG_EXTRAS
1557	DebugMessage("alGetError");
1558#endif
1559
1560	if (gCurrentError != AL_NO_ERROR)
1561    {
1562#if LOG_ERRORS
1563		DebugMessageN1("alGetError: error = 0x%X\n", (uint) gCurrentError);
1564#endif
1565		error = gCurrentError;
1566		gCurrentError = AL_NO_ERROR;
1567
1568		// this call should also clear the error on the current device as well
1569    	if (gOALDeviceMap)
1570    	{
1571			OALDevice		*device = gOALDeviceMap->Get((UInt32) gCurrentDevice);
1572			if (device)
1573				device->SetError(AL_NO_ERROR);
1574		}
1575	}
1576
1577	return (error);
1578}
1579
1580// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1581// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1582// Buffer APIs
1583// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1584// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1585#pragma mark ***** Buffers *****
1586
1587// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1588AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *bids)
1589{
1590#if LOG_BUFFER_USAGE
1591	DebugMessageN1("alGenBuffers--> requested buffers = %ld", (long int) n);
1592#endif
1593
1594	try {
1595		if (n < 0)
1596            throw ((OSStatus) AL_INVALID_VALUE);
1597
1598        InitializeBufferMap();
1599        if (gOALBufferMap == NULL)
1600            throw ((OSStatus) AL_INVALID_OPERATION);
1601
1602		CAGuard::Locker locked(*gBufferMapLock);
1603
1604		CleanUpDeadBufferList();		// take the opportunity to clean up the dead list
1605
1606		if ((n + gOALBufferMap->Size() > AL_MAXBUFFERS) || (n > AL_MAXBUFFERS))
1607		{
1608			DebugMessageN2("alGenBuffers ERROR --> requested buffers:gOALBufferMap->Size() = %ld:%ld", (long int) n, (long int) gOALBufferMap->Size());
1609            throw ((OSStatus) AL_INVALID_VALUE);
1610		}
1611
1612        for (UInt32	i = 0; i < (UInt32) n; i++)
1613        {
1614			ALuint	newBufferToken = GetNewToken();		// get a unique token
1615
1616			OALBuffer	*newBuffer = new OALBuffer (newBufferToken);
1617
1618            gOALBufferMap->Add(newBufferToken, &newBuffer);			// add the new buffer to the buffer map
1619            bids[i] = newBufferToken;
1620        }
1621	}
1622	catch (OSStatus     result) {
1623		DebugMessageN2("ERROR: alGenBuffers FAILED: requested buffers = %ld error %s", (long int) n, alGetString(result));
1624        alSetError (result);
1625	}
1626    catch (...) {
1627		DebugMessageN1("ERROR: alGenBuffers FAILED: requested buffers = %ld", (long int) n);
1628        alSetError(AL_INVALID_OPERATION);
1629	}
1630
1631#if LOG_BUFFER_USAGE
1632	printf("alGenBuffers--> (%ld) ", (long int) n);
1633	for (UInt32	i = 0; i < (UInt32) n; i++) {
1634		printf("%ld, ", (long int) bids[i]);
1635	}
1636	printf("\n");
1637#endif
1638}
1639
1640// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1641AL_API void	AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* bids )
1642{
1643#if LOG_BUFFER_USAGE
1644	printf("alDeleteBuffers--> (%ld) ", (long int) n);
1645	for (UInt32	i = 0; i < (UInt32) n; i++) {
1646		printf("%ld, ", (long int) bids[i]);
1647	}
1648	printf("\n");
1649#endif
1650	if (n == 0)
1651		return; // NOP
1652
1653	try {
1654        if (gOALBufferMap == NULL)
1655        {
1656            DebugMessage("alDeleteBuffers: gOALBufferMap == NULL");
1657            throw ((OSStatus) AL_INVALID_VALUE);
1658        }
1659		else if (n < 0)
1660		{
1661			DebugMessage("alDeleteBuffers: Invalid number of buffers");
1662			throw ((OSStatus) AL_INVALID_VALUE);
1663		}
1664
1665		CAGuard::Locker locked(*gBufferMapLock);
1666
1667		CleanUpDeadBufferList();		// take the opportunity to clean up the dead list
1668
1669		// see if any of the buffers are attached to a source or are invalid names
1670		for (UInt32 i = 0; i < (UInt32) n; i++)
1671		{
1672			// don't bother verifying the NONE buffer, it won't be deleted anyway
1673			if (bids[i] != AL_NONE)
1674			{
1675				OALBuffer	*oalBuffer = gOALBufferMap->Get(bids[i]);
1676				if (oalBuffer == NULL)
1677				{
1678					DebugMessageN1("alDeleteBuffers: oalBuffer == NULL, bid = %ld", (long int) bids[i]);
1679					throw ((OSStatus) AL_INVALID_NAME);			// the buffer is invalid
1680				}
1681				else if (!oalBuffer->CanBeRemovedFromBufferMap())
1682				{
1683					DebugMessageN1("alDeleteBuffers: oalBuffer cannot currently be removed, a source is still attached, bid = %ld", (long int) bids[i]);
1684					throw ((OSStatus) AL_INVALID_OPERATION);    // the buffer is attached to a source so set an error and bail
1685				}
1686			}
1687		}
1688
1689		// All the buffers are OK'd for deletion, so delete them now
1690		for (UInt32 i = 0; i < (UInt32) n; i++)
1691		{
1692			// do not delete the NONE buffer at the beginning of the map
1693			if (bids[i] != AL_NONE)
1694			{
1695				OALBuffer	*buffer = gOALBufferMap->Get((UInt32) bids[i]);
1696				if (buffer->IsPurgable())
1697				{
1698					// delete it right now, it's not attached
1699					gOALBufferMap->Remove((UInt32) bids[i]);
1700					delete (buffer);
1701				}
1702				else
1703				{
1704					// The buffer is currently attached to a source that is transitioning to stop
1705					// it can be deleted later. By removing it from the map, it can't be attached to another source before
1706					// it has a chance to be deleted
1707					gDeadOALBufferMap->Add(buffer->GetToken(), &buffer);	// add this buffer object to a dead list that can be cleaned up later
1708					gOALBufferMap->Remove((UInt32) bids[i]);				// remove it from the good list so it won't be used again
1709				}
1710			}
1711		}
1712	}
1713    catch (OSStatus     result) {
1714		DebugMessageN1("ERROR: alDeleteBuffers FAILED = %s", alGetString(result));
1715        alSetError(result);
1716    }
1717    catch (...) {
1718		DebugMessage("ERROR: alDeleteBuffers FAILED");
1719        alSetError(AL_INVALID_OPERATION);
1720	}
1721}
1722
1723// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1724AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint bid)
1725{
1726#if LOG_BUFFER_USAGE
1727	//DebugMessageN1("alIsBuffer--> buffer %ld", (long int) bid);
1728#endif
1729
1730	ALboolean isBuffer = AL_FALSE;
1731
1732	try {
1733		isBuffer = IsValidBufferObject(bid);
1734    }
1735    catch (OSStatus     result) {
1736		DebugMessageN2("ERROR: alIsBuffer FAILED: buffer = %ld error = %s", (long int) bid, alGetString(result));
1737        alSetError(result);
1738    }
1739    catch (...) {
1740		DebugMessageN1("ERROR: alIsBuffer FAILED: buffer = %ld", (long int) bid);
1741        alSetError(AL_INVALID_OPERATION);
1742	}
1743
1744    return isBuffer;
1745}
1746
1747// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1748AL_API void	AL_APIENTRY alBufferData(	ALuint			bid,
1749										ALenum			format,
1750										const ALvoid*	data,
1751										ALsizei			size,
1752										ALsizei			freq )
1753{
1754#if LOG_BUFFER_USAGE
1755	DebugMessageN4("alBufferData-->  buffer %ld : %s : %ld bytes : %ldHz", (long int) bid, GetFormatString(format), (long int) size, (long int) freq);
1756#endif
1757
1758	OALBuffer *oalBuffer = NULL;
1759
1760	try {
1761        if (gOALBufferMap == NULL)
1762            throw ((OSStatus) AL_INVALID_OPERATION);
1763
1764		oalBuffer = ProtectBufferObject(bid);
1765        if (data==NULL) throw ((OSStatus) AL_INVALID_VALUE);
1766        if (size<=0) throw ((OSStatus) AL_INVALID_VALUE);
1767
1768		oalBuffer->AddAudioData((char*)data, size, format, freq, gConvertBufferNow); // should also check for a valid format IsFormatSupported()
1769    }
1770    catch (OSStatus     result) {
1771		DebugMessageN5("ERROR: alBufferData FAILED: buffer %ld : %s : %ld bytes : %ldHz error = %s", (long int) bid, GetFormatString(format), (long int) size, (long int) freq,  alGetString(result));
1772        alSetError(result);
1773    }
1774    catch (...) {
1775		DebugMessageN4("ERROR: alBufferData FAILED: buffer %ld : %s : %ld bytes : %ldHz", (long int) bid, GetFormatString(format), (long int) size, (long int) freq);
1776        alSetError(AL_INVALID_OPERATION);
1777	}
1778
1779	ReleaseBufferObject(oalBuffer);
1780}
1781
1782// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1783AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum pname, ALfloat value )
1784{
1785#if LOG_BUFFER_USAGE
1786	DebugMessage("alBufferf--> there are currently no valid enums for this API");
1787#endif
1788	// there are currently no valid enums for this API
1789	alSetError(AL_INVALID_ENUM);
1790}
1791// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1792AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum pname, ALfloat value1, ALfloat value2, ALfloat value3 )
1793{
1794#if LOG_BUFFER_USAGE
1795	DebugMessage("alBuffer3f--> there are currently no valid enums for this API");
1796#endif
1797	// there are currently no valid enums for this API
1798	alSetError(AL_INVALID_ENUM);
1799}
1800// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1801AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum pname, const ALfloat* values )
1802{
1803#if LOG_BUFFER_USAGE
1804	DebugMessage("alBufferfv--> there are currently no valid enums for this API");
1805#endif
1806	// there are currently no valid enums for this API
1807	alSetError(AL_INVALID_ENUM);
1808}
1809// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1810AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum pname, ALint value )
1811{
1812#if LOG_BUFFER_USAGE
1813	DebugMessage("alBufferi--> there are currently no valid enums for this API");
1814#endif
1815	// there are currently no valid enums for this API
1816	alSetError(AL_INVALID_ENUM);
1817}
1818// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1819AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum pname, ALint value1, ALint value2, ALint value3 )
1820{
1821#if LOG_BUFFER_USAGE
1822	DebugMessage("alBuffer3i--> there are currently no valid enums for this API");
1823#endif
1824	// there are currently no valid enums for this API
1825	alSetError(AL_INVALID_ENUM);
1826}
1827
1828// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1829AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum pname, const ALint* values )
1830{
1831#if LOG_BUFFER_USAGE
1832	DebugMessage("alBufferiv--> there are currently no valid enums for this API");
1833#endif
1834	// there are currently no valid enums for this API
1835	alSetError(AL_INVALID_ENUM);
1836}
1837
1838// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1839AL_API ALvoid AL_APIENTRY alGetBufferf (ALuint bid, ALenum pname, ALfloat *value)
1840{
1841#if LOG_BUFFER_USAGE
1842	DebugMessageN2("alGetBufferf--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1843#endif
1844	OALBuffer	*oalBuffer = NULL;
1845
1846    try {
1847        if (gOALBufferMap == NULL)
1848            throw ((OSStatus) AL_INVALID_OPERATION);
1849
1850		oalBuffer = ProtectBufferObject(bid);
1851
1852        switch (pname)
1853        {
1854            case AL_FREQUENCY:
1855                *value = oalBuffer->GetSampleRate();
1856                break;
1857            default:
1858                alSetError(AL_INVALID_ENUM);
1859                break;
1860        }
1861    }
1862    catch (OSStatus result) {
1863		DebugMessageN3("ERROR: alGetBufferf FAILED: buffer %ld : property = %s error = %s", (long int) bid, GetALAttributeString(pname), alGetString(result));
1864        alSetError(result);
1865    }
1866    catch (...) {
1867		DebugMessageN2("ERROR: alGetBufferf FAILED: buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1868        alSetError(AL_INVALID_OPERATION);
1869	}
1870
1871	ReleaseBufferObject(oalBuffer);
1872}
1873
1874// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1875AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum pname, ALfloat* value1, ALfloat* value2, ALfloat* value3)
1876{
1877#if LOG_BUFFER_USAGE
1878	DebugMessageN2("alGetBuffer3f--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1879#endif
1880	// there are currently no valid enums for this API
1881	alSetError(AL_INVALID_ENUM);
1882}
1883// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1884AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum pname, ALfloat* values )
1885{
1886#if LOG_BUFFER_USAGE
1887	DebugMessageN2("alGetBufferfv--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1888#endif
1889	// there are currently no valid enums for this API
1890	alSetError(AL_INVALID_ENUM);
1891}
1892
1893// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1894AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint bid, ALenum pname, ALint *value)
1895{
1896#if LOG_BUFFER_USAGE
1897	DebugMessageN2("alGetBufferi--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1898#endif
1899
1900	OALBuffer	*oalBuffer = NULL;
1901
1902	try {
1903        if (gOALBufferMap == NULL)
1904            throw ((OSStatus) AL_INVALID_OPERATION);
1905
1906		oalBuffer = ProtectBufferObject(bid);
1907
1908        switch (pname)
1909        {
1910            case AL_FREQUENCY:
1911                *value = (UInt32) oalBuffer->GetSampleRate();
1912                break;
1913            case AL_BITS:
1914                *value = oalBuffer->GetPreConvertedBitsPerChannel();
1915                break;
1916            case AL_CHANNELS:
1917                *value = oalBuffer->GetNumberChannels();
1918                break;
1919            case AL_SIZE:
1920                *value = oalBuffer->GetPreConvertedDataSize();
1921                break;
1922            default:
1923                *value = 0;
1924				alSetError(AL_INVALID_ENUM);
1925                break;
1926        }
1927    }
1928    catch (OSStatus result) {
1929		DebugMessageN3("ERROR: alGetBufferi FAILED: buffer = %ld property = %s error = %s", (long int) bid, GetALAttributeString(pname), alGetString(result));
1930		*value = 0;
1931		alSetError(result);
1932    }
1933    catch (...) {
1934		DebugMessageN2("ERROR: alGetBufferi FAILED: buffer = %ld property = %s", (long int) bid, GetALAttributeString(pname));
1935		*value = 0;
1936        alSetError(AL_INVALID_OPERATION);
1937	}
1938
1939	ReleaseBufferObject(oalBuffer);
1940}
1941
1942// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1943AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum pname, ALint* value1, ALint* value2, ALint* value3)
1944{
1945#if LOG_BUFFER_USAGE
1946	DebugMessageN2("alGetBuffer3i--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1947#endif
1948	// there are currently no valid enums for this API
1949	alSetError(AL_INVALID_ENUM);
1950}
1951
1952// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1953AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum pname, ALint* values )
1954{
1955#if LOG_BUFFER_USAGE
1956	DebugMessageN2("alGetBufferi--> buffer %ld : property = %s", (long int) bid, GetALAttributeString(pname));
1957#endif
1958
1959	OALBuffer	*oalBuffer = NULL;
1960
1961    try {
1962        if (gOALBufferMap == NULL)
1963            throw ((OSStatus) AL_INVALID_OPERATION);
1964
1965		oalBuffer = ProtectBufferObject(bid);
1966
1967       switch (pname)
1968        {
1969            case AL_FREQUENCY:
1970                *values = (UInt32) oalBuffer->GetSampleRate();
1971                break;
1972            case AL_BITS:
1973                *values = oalBuffer->GetPreConvertedBitsPerChannel();
1974                break;
1975            case AL_CHANNELS:
1976                *values = oalBuffer->GetNumberChannels();
1977                break;
1978            case AL_SIZE:
1979                *values = oalBuffer->GetPreConvertedDataSize();
1980                break;
1981            default:
1982                *values = 0;
1983				alSetError(AL_INVALID_ENUM);
1984                break;
1985        }
1986    }
1987    catch (OSStatus result) {
1988		DebugMessageN3("ERROR: alGetBufferiv FAILED: buffer = %ld property = %s error = %s", (long int) bid, GetALAttributeString(pname), alGetString(result));
1989		*values = 0;
1990		alSetError(result);
1991    }
1992    catch (...) {
1993		DebugMessageN2("ERROR: alGetBufferiv FAILED: buffer = %ld property = %s", (long int) bid, GetALAttributeString(pname));
1994		*values = 0;
1995        alSetError(AL_INVALID_OPERATION);
1996	}
1997
1998	ReleaseBufferObject(oalBuffer);
1999}
2000
2001// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2002// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2003// Source APIs
2004// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2005// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2006#pragma mark ***** Sources *****
2007// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2008ALC_API ALvoid  AL_APIENTRY alGenSources(ALsizei n, ALuint *sids)
2009{
2010#if LOG_SOURCE_USAGE
2011	DebugMessageN1("alGenSources--> requested sources = %ld", (long int) n);
2012#endif
2013
2014	if (n == 0)
2015		return; // NOP
2016
2017	UInt32      i = 0,
2018                count = 0;
2019
2020	OALContext *oalContext = NULL;
2021
2022	try {
2023		if (n < 0)
2024            throw ((OSStatus) AL_INVALID_VALUE);
2025
2026        if ((n > AL_MAXSOURCES) || (sids == NULL))
2027            throw ((OSStatus) AL_INVALID_VALUE);
2028
2029		oalContext = ProtectContextObject(gCurrentContext);
2030
2031		for (i = 0; i < (UInt32) n; i++)
2032        {
2033            ALuint	newToken = GetNewToken();		// get a unique token
2034
2035            oalContext->AddSource(newToken);		// add this source to the context
2036            sids[i] = newToken; 					// return the source token
2037            count++;
2038        }
2039	}
2040	catch (OSStatus     result){
2041		DebugMessageN2("ERROR: alGenSources FAILED: source count = %ld error = %s", (long int) n, alGetString(result));
2042		// some of the sources could not be created, so delete the ones that were and return none
2043		alSetError(result);
2044		alDeleteSources(i, sids);
2045		for (i = 0; i < count; i++)
2046			sids[i] = 0;
2047	}
2048    catch (...) {
2049		DebugMessageN1("ERROR: alGenSources FAILED: source count = %ld", (long int) n);
2050        alSetError(AL_INVALID_OPERATION);
2051		// some of the sources could not be created, so delete the ones that were and return none
2052		alDeleteSources(i, sids);
2053		for (i = 0; i < count; i++)
2054			sids[i] = 0;
2055	}
2056
2057	ReleaseContextObject(oalContext);
2058}
2059
2060// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2061AL_API void	AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sids )
2062{
2063#if LOG_SOURCE_USAGE
2064	//DebugMessageN1("alDeleteSources: count = %ld", (long int) n);
2065	printf("alDeleteSources--> (%ld) ", (long int) n);
2066	for (UInt32	i = 0; i < (UInt32) n; i++) {
2067		printf("%ld, ", (long int) sids[i]);
2068	}
2069	printf("\n");
2070#endif
2071
2072	if (n == 0)
2073		return; // NOP
2074
2075	OALContext *oalContext = NULL;
2076
2077	try {
2078		oalContext = ProtectContextObject(gCurrentContext);
2079
2080        if ((UInt32) n > oalContext->GetSourceCount())
2081            throw ((OSStatus) AL_INVALID_VALUE);
2082		else if (n < 0)
2083			throw ((OSStatus) AL_INVALID_VALUE);
2084
2085        for (UInt32 i = 0; i < (UInt32) n; i++)
2086        {
2087			alSourceStop (sids[i]);
2088            oalContext->RemoveSource(sids[i]);
2089        }
2090	}
2091	catch (OSStatus     result) {
2092		DebugMessageN2("ERROR: alDeleteSources FAILED: source count = %ld error = %s", (long int) n, alGetString(result));
2093		alSetError(result);
2094	}
2095    catch (...) {
2096		DebugMessageN1("ERROR: alDeleteSources FAILED: source count = %ld", (long int) n);
2097        alSetError(AL_INVALID_OPERATION);
2098	}
2099
2100	ReleaseContextObject(oalContext);
2101}
2102
2103// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2104ALC_API ALboolean  AL_APIENTRY alIsSource(ALuint sid)
2105{
2106#if LOG_SOURCE_USAGE
2107	DebugMessageN1("alIsSource--> source %ld", (long int) sid);
2108#endif
2109	ALboolean isSource = AL_FALSE;
2110	OALSource *oalSource = NULL;
2111
2112	try {
2113		oalSource = ProtectSourceObjectInCurrentContext(sid);
2114		if (oalSource)
2115			isSource = AL_TRUE;
2116	}
2117	catch (OSStatus     result) {
2118		DebugMessageN2("ERROR: alIsSource FAILED: source = %ld error = %s", (long int) sid, alGetString(result));
2119		alSetError(result);
2120	}
2121    catch (...) {
2122		DebugMessageN1("ERROR: alIsSource FAILED: source = %ld", (long int) sid);
2123        alSetError(AL_INVALID_OPERATION);
2124	}
2125
2126	ReleaseSourceObject(oalSource);
2127
2128	return isSource;
2129}
2130
2131// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2132AL_API ALvoid AL_APIENTRY alSourcef (ALuint sid, ALenum pname, ALfloat value)
2133{
2134#if LOG_SOURCE_USAGE
2135	DebugMessageN3("alSourcef--> source %ld : %s : value = %.2f", (long int) sid, GetALAttributeString(pname), value);
2136#endif
2137
2138	OALSource *oalSource = NULL;
2139
2140	try {
2141		oalSource = ProtectSourceObjectInCurrentContext(sid);
2142
2143        switch (pname)
2144        {
2145			// Source ONLY Attributes
2146            case AL_MIN_GAIN:
2147                oalSource->SetMinGain(value);
2148                break;
2149            case AL_MAX_GAIN:
2150                oalSource->SetMaxGain(value);
2151                break;
2152            case AL_REFERENCE_DISTANCE:
2153                oalSource->SetReferenceDistance(value);
2154                break;
2155            case AL_ROLLOFF_FACTOR:
2156                oalSource->SetRollOffFactor(value);
2157                break;
2158            case AL_MAX_DISTANCE:
2159                oalSource->SetMaxDistance(value);
2160                break;
2161            case AL_PITCH:
2162                oalSource->SetPitch(value);
2163                break;
2164            case AL_CONE_INNER_ANGLE:
2165                oalSource->SetConeInnerAngle(value);
2166                break;
2167            case AL_CONE_OUTER_ANGLE:
2168                oalSource->SetConeOuterAngle(value);
2169                break;
2170            case AL_CONE_OUTER_GAIN:
2171				oalSource->SetConeOuterGain(value);
2172                break;
2173            case AL_SEC_OFFSET:
2174                oalSource->SetQueueOffset(kSecondsOffset, value);
2175                break;
2176            case AL_SAMPLE_OFFSET:
2177                oalSource->SetQueueOffset(kSampleOffset, value);
2178                break;
2179            case AL_BYTE_OFFSET:
2180                oalSource->SetQueueOffset(kByteOffset, value);
2181                break;
2182
2183			// Source & Listener Attributes
2184            case AL_GAIN:
2185                oalSource->SetGain(value);
2186                break;
2187
2188            default:
2189                alSetError(AL_INVALID_OPERATION);
2190                break;
2191        }
2192	}
2193	catch (OSStatus     result) {
2194		DebugMessageN4("ERROR alSourcef FAILED: source %ld : property = %s : value = %.f2 : error = %s", (long int) sid, GetALAttributeString(pname), value, alGetString(result));
2195		alSetError(result);
2196	}
2197    catch (...) {
2198		DebugMessageN4("ERROR alSourcef FAILED: source %ld : property = %s : value = %.f2 : error = %s", (long int) sid, GetALAttributeString(pname), value, alGetString(-1));
2199        alSetError(AL_INVALID_OPERATION);
2200	}
2201
2202	ReleaseSourceObject(oalSource);
2203}
2204
2205// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2206AL_API ALvoid AL_APIENTRY alSourcefv (ALuint sid, ALenum pname, const ALfloat *values)
2207{
2208#if LOG_SOURCE_USAGE
2209	DebugMessageN2("alSourcefv--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2210#endif
2211
2212	OALSource *oalSource = NULL;
2213
2214	try {
2215		oalSource = ProtectSourceObjectInCurrentContext(sid);
2216
2217        switch(pname)
2218        {
2219			// Source ONLY Attributes
2220            case AL_MIN_GAIN:
2221                oalSource->SetMinGain(*values);
2222                break;
2223            case AL_MAX_GAIN:
2224                oalSource->SetMaxGain(*values);
2225                break;
2226            case AL_REFERENCE_DISTANCE:
2227                oalSource->SetReferenceDistance(*values);
2228                break;
2229            case AL_ROLLOFF_FACTOR:
2230                if (*values < 0.0f)
2231                    throw ((OSStatus) AL_INVALID_VALUE);
2232                oalSource->SetRollOffFactor(*values);
2233                break;
2234            case AL_MAX_DISTANCE:
2235                oalSource->SetMaxDistance(*values);
2236                break;
2237            case AL_PITCH:
2238                oalSource->SetPitch(*values);
2239                break;
2240            case AL_DIRECTION:
2241                oalSource->SetDirection(values[0], values[1], values[2]);
2242                break;
2243            case AL_CONE_INNER_ANGLE:
2244                oalSource->SetConeInnerAngle(*values);
2245                break;
2246            case AL_CONE_OUTER_ANGLE:
2247                oalSource->SetConeOuterAngle(*values);
2248                break;
2249            case AL_CONE_OUTER_GAIN:
2250				oalSource->SetConeOuterGain(*values);
2251                break;
2252            case AL_SEC_OFFSET:
2253                oalSource->SetQueueOffset(kSecondsOffset, values[0]);
2254                break;
2255            case AL_SAMPLE_OFFSET:
2256                oalSource->SetQueueOffset(kSampleOffset, values[0]);
2257                break;
2258            case AL_BYTE_OFFSET:
2259                oalSource->SetQueueOffset(kByteOffset, values[0]);
2260                break;
2261
2262			// Source & Listener Attributes
2263            case AL_POSITION:
2264                oalSource->SetPosition(values[0], values[1], values[2]);
2265                break;
2266            case AL_VELOCITY:
2267                oalSource->SetVelocity(values[0], values[1], values[2]);
2268                break;
2269            case AL_GAIN:
2270                oalSource->SetGain(*values);
2271                break;
2272
2273            default:
2274                alSetError(AL_INVALID_ENUM);
2275                break;
2276        }
2277	}
2278	catch(OSStatus      result) {
2279		DebugMessageN3("ERROR alSourcefv FAILED: source = %ld property = %s result = %s\n", (long int) sid, GetALAttributeString(pname), alGetString(result));
2280		alSetError(result);
2281	}
2282    catch (...) {
2283		DebugMessageN3("ERROR alSourcefv: FAILED : property : result %ld : %s : %s\n", (long int) sid, GetALAttributeString(pname), alGetString(-1));
2284        alSetError(AL_INVALID_OPERATION);
2285	}
2286
2287	ReleaseSourceObject(oalSource);
2288}
2289
2290// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2291AL_API ALvoid AL_APIENTRY alSource3f (ALuint sid, ALenum pname, ALfloat v1, ALfloat v2, ALfloat v3)
2292{
2293#if LOG_SOURCE_USAGE
2294	DebugMessageN5("alSource3f--> source %ld : %s : values = %.2f:%.2f:%.2f", (long int) sid, GetALAttributeString(pname), v1, v2, v3);
2295#endif
2296
2297	OALSource *oalSource = NULL;
2298
2299	try {
2300		oalSource = ProtectSourceObjectInCurrentContext(sid);
2301
2302        switch (pname)
2303        {
2304			// Source ONLY Attributes
2305            case AL_DIRECTION:
2306                oalSource->SetDirection(v1, v2, v3);
2307                break;
2308
2309			// Source & Listener Attributes
2310            case AL_POSITION:
2311                oalSource->SetPosition(v1, v2, v3);
2312                break;
2313            case AL_VELOCITY:
2314                oalSource->SetVelocity(v1, v2, v3);
2315                break;
2316
2317            default:
2318                alSetError(AL_INVALID_ENUM);
2319                break;
2320        }
2321	}
2322	catch (OSStatus      result) {
2323		DebugMessageN6("ERROR: alSource3f FAILED: source %ld : %s : values = %.f2:%.f2:%.f2 error = %s", (long int) sid, GetALAttributeString(pname), v1, v2, v3, alGetString(result));
2324		alSetError(result);
2325	}
2326    catch (...) {
2327		DebugMessageN5("ERROR: alSource3f FAILED: source %ld : %s : values = %.f2:%.f2:%.f2", (long int) sid, GetALAttributeString(pname), v1, v2, v3);
2328        alSetError(AL_INVALID_OPERATION);
2329	}
2330
2331	ReleaseSourceObject(oalSource);
2332}
2333
2334// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2335AL_API ALvoid AL_APIENTRY alSourcei (ALuint sid, ALenum pname, ALint value)
2336{
2337#if LOG_SOURCE_USAGE
2338	DebugMessageN3("alSourcei--> source %ld : %s : value = %ld", (long int) sid, GetALAttributeString(pname), (long int)value);
2339#endif
2340
2341	OALSource *oalSource = NULL;
2342
2343	try {
2344		oalSource = ProtectSourceObjectInCurrentContext(sid);
2345
2346		switch (pname)
2347        {
2348			// Source ONLY Attributes
2349            case AL_SOURCE_RELATIVE:
2350				oalSource->SetSourceRelative(value);
2351                break;
2352            case AL_LOOPING:
2353                oalSource->SetLooping(value);
2354                break;
2355            case AL_BUFFER:
2356                {
2357					// The source type must first be checked for static or streaming
2358					if (oalSource->GetSourceType() == AL_STREAMING && value != 0)
2359						throw ((OSStatus) AL_INVALID_OPERATION);
2360					try {
2361						if (IsValidBufferObject(value))
2362						{
2363							// if no buffers have been made yet but IsValidBufferObject() is true, then this is a AL_NONE buffer
2364							if (gOALBufferMap)
2365							{
2366								CAGuard::Locker locked(*gBufferMapLock);
2367								oalSource->SetBuffer(value, gOALBufferMap->Get((UInt32) value));
2368							}
2369						}
2370						else
2371							throw ((OSStatus) AL_INVALID_VALUE);	// per the OpenAL 1.1 spec
2372					}
2373					catch (OSStatus result) {
2374						if (result == AL_INVALID_NAME)
2375							result = AL_INVALID_VALUE;	// convert result from IsValidBufferObject() when buffer is not primary object
2376						throw result;
2377					}
2378                }
2379                break;
2380            case AL_REFERENCE_DISTANCE:
2381                oalSource->SetReferenceDistance(value);
2382                break;
2383            case AL_ROLLOFF_FACTOR:
2384                oalSource->SetRollOffFactor(value);
2385                break;
2386            case AL_MAX_DISTANCE:
2387                oalSource->SetMaxDistance(value);
2388                break;
2389			case AL_CONE_INNER_ANGLE:
2390                oalSource->SetConeInnerAngle(value);
2391                break;
2392            case AL_CONE_OUTER_ANGLE:
2393                oalSource->SetConeOuterAngle(value);
2394                break;
2395            case AL_CONE_OUTER_GAIN:
2396				oalSource->SetConeOuterGain(value);
2397                break;
2398            case AL_SEC_OFFSET:
2399                oalSource->SetQueueOffset(kSecondsOffset, value);
2400                break;
2401            case AL_SAMPLE_OFFSET:
2402                oalSource->SetQueueOffset(kSampleOffset, value);
2403                break;
2404            case AL_BYTE_OFFSET:
2405                oalSource->SetQueueOffset(kByteOffset, value);
2406                break;
2407
2408            default:
2409                alSetError(AL_INVALID_ENUM);
2410                break;
2411        }
2412	}
2413	catch (OSStatus      result) {
2414		DebugMessageN4("ERROR: alSourcei FAILED - sid:pname:value:result %ld:%s:%ld:%s", (long int) sid, GetALAttributeString( pname), (long int) value, alGetString(result));
2415		alSetError(result);
2416	}
2417    catch (...) {
2418		DebugMessageN3("ERROR: alSourcei FAILED - sid:pname:value %ld:%s:%ld", (long int) sid, GetALAttributeString( pname), (long int) value);
2419        alSetError(AL_INVALID_OPERATION);
2420	}
2421
2422	ReleaseSourceObject(oalSource);
2423}
2424
2425// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2426AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum pname, const ALint* values )
2427{
2428#if LOG_SOURCE_USAGE
2429	DebugMessageN2("alSourceiv--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2430#endif
2431
2432	OALSource *oalSource = NULL;
2433
2434	try {
2435		if (values == NULL)
2436			throw ((OSStatus) AL_INVALID_VALUE);
2437
2438		oalSource = ProtectSourceObjectInCurrentContext(sid);
2439		switch (pname)
2440        {
2441			// Source ONLY Attributes
2442            case AL_SOURCE_RELATIVE:
2443                if ((*values == AL_FALSE) || (*values == AL_TRUE))
2444                    oalSource->SetSourceRelative(*values);
2445                else
2446                    throw ((OSStatus) AL_INVALID_VALUE);
2447                break;
2448            case AL_LOOPING:
2449                oalSource->SetLooping(*values);
2450                break;
2451            case AL_BUFFER:
2452			{
2453				// The source type must first be checked for static or streaming
2454				if (oalSource->GetSourceType() == AL_STREAMING)
2455					throw ((OSStatus) AL_INVALID_OPERATION);
2456
2457				if (IsValidBufferObject(*values))
2458				{
2459					// if no buffers have been made yet but IsValidBufferObject() is true, then this is a AL_NONE buffer
2460					if (gOALBufferMap)
2461					{
2462						CAGuard::Locker locked(*gBufferMapLock);
2463						oalSource->SetBuffer(*values, gOALBufferMap->Get((UInt32) *values));
2464					}
2465				}
2466				else
2467					throw ((OSStatus) AL_INVALID_OPERATION);
2468			}
2469                break;
2470			case AL_REFERENCE_DISTANCE:
2471                oalSource->SetReferenceDistance(*values);
2472                break;
2473            case AL_ROLLOFF_FACTOR:
2474                oalSource->SetRollOffFactor(*values);
2475                break;
2476            case AL_MAX_DISTANCE:
2477                oalSource->SetMaxDistance(*values);
2478                break;
2479            case AL_DIRECTION:
2480                oalSource->SetDirection(values[0], values[1], values[2]);
2481                break;
2482			case AL_CONE_INNER_ANGLE:
2483                oalSource->SetConeInnerAngle(*values);
2484                break;
2485            case AL_CONE_OUTER_ANGLE:
2486                oalSource->SetConeOuterAngle(*values);
2487                break;
2488			case AL_SEC_OFFSET:
2489                oalSource->SetQueueOffset(kSecondsOffset, *values);
2490                break;
2491            case AL_SAMPLE_OFFSET:
2492                oalSource->SetQueueOffset(kSampleOffset, *values);
2493                break;
2494            case AL_BYTE_OFFSET:
2495                oalSource->SetQueueOffset(kByteOffset, *values);
2496                break;
2497
2498			// Source & Listener Attributes
2499            case AL_POSITION:
2500                oalSource->SetPosition(values[0], values[1], values[2]);
2501                break;
2502            case AL_VELOCITY:
2503                oalSource->SetVelocity(values[0], values[1], values[2]);
2504                break;
2505
2506            default:
2507                alSetError(AL_INVALID_ENUM);
2508                break;
2509		}
2510	}
2511	catch (OSStatus      result) {
2512		DebugMessageN3("ERROR: alSourcei FAILED: source %ld : %s error = %s", (long int) sid, GetALAttributeString(pname), alGetString(result));
2513		alSetError(result);
2514	}
2515    catch (...) {
2516		DebugMessageN2("ERROR: alSourcei FAILED: source %ld : %s", (long int) sid, GetALAttributeString(pname));
2517        alSetError(AL_INVALID_OPERATION);
2518	}
2519
2520	ReleaseSourceObject(oalSource);
2521}
2522
2523// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2524AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum pname, ALint v1, ALint v2, ALint v3 )
2525{
2526#if LOG_SOURCE_USAGE
2527	DebugMessageN5("alSource3i--> source %ld : %s : values = %ld:%ld:%ld", (long int) sid, GetALAttributeString(pname), (long int)v1, (long int)v2, (long int)v3);
2528#endif
2529
2530	OALSource *oalSource = NULL;
2531
2532	try {
2533		oalSource = ProtectSourceObjectInCurrentContext(sid);
2534
2535        switch (pname)
2536        {
2537			// Source ONLY Attributes
2538            case AL_DIRECTION:
2539                oalSource->SetDirection(v1, v2, v3);
2540                break;
2541
2542			// Source & Listener Attributes
2543            case AL_POSITION:
2544                oalSource->SetPosition(v1, v2, v3);
2545                break;
2546            case AL_VELOCITY:
2547                oalSource->SetVelocity(v1, v2, v3);
2548                break;
2549
2550            default:
2551                alSetError(AL_INVALID_ENUM);
2552                break;
2553        }
2554	}
2555	catch (OSStatus      result) {
2556		DebugMessageN6("ERROR: alSource3f FAILED: source %ld : %s : values = %ld:%ld:%ld error = %s", (long int) sid, GetALAttributeString(pname), (long int)v1, (long int)v2, (long int)v3, alGetString(result));
2557		alSetError(result);
2558	}
2559    catch (...) {
2560		DebugMessageN5("ERROR: alSource3f FAILED: source %ld : %s : values = %ld:%ld:%ld", (long int) sid, GetALAttributeString(pname), (long int)v1, (long int)v2, (long int)v3);
2561        alSetError(AL_INVALID_OPERATION);
2562	}
2563
2564	ReleaseSourceObject(oalSource);
2565}
2566
2567// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2568AL_API ALvoid AL_APIENTRY alGetSourcef (ALuint sid, ALenum pname, ALfloat *value)
2569{
2570#if LOG_SOURCE_USAGE
2571	DebugMessageN2("alGetSourcef--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2572#endif
2573
2574	OALSource *oalSource = NULL;
2575	try {
2576		oalSource = ProtectSourceObjectInCurrentContext(sid);
2577
2578        switch (pname)
2579        {
2580			// Source ONLY Attributes
2581            case AL_MIN_GAIN:
2582                *value = oalSource->GetMinGain();
2583                break;
2584            case AL_MAX_GAIN:
2585                *value = oalSource->GetMaxGain();
2586                break;
2587            case AL_REFERENCE_DISTANCE:
2588                *value = oalSource->GetReferenceDistance();
2589                break;
2590            case AL_ROLLOFF_FACTOR:
2591                *value = oalSource->GetRollOffFactor();
2592                break;
2593            case AL_MAX_DISTANCE:
2594                *value = oalSource->GetMaxDistance();
2595                break;
2596            case AL_PITCH:
2597                *value = oalSource->GetPitch();
2598                break;
2599            case AL_CONE_INNER_ANGLE:
2600                *value = oalSource->GetConeInnerAngle();
2601                break;
2602            case AL_CONE_OUTER_ANGLE:
2603                *value = oalSource->GetConeOuterAngle();
2604                break;
2605            case AL_CONE_OUTER_GAIN:
2606                *value = oalSource->GetConeOuterGain();
2607                break;
2608            case AL_SEC_OFFSET:
2609                *value = oalSource->GetQueueOffsetSecondsFloat();
2610                break;
2611            case AL_SAMPLE_OFFSET:
2612                *value = oalSource->GetQueueOffset(kSampleOffset);
2613                break;
2614            case AL_BYTE_OFFSET:
2615                *value = oalSource->GetQueueOffset(kByteOffset);
2616                break;
2617
2618			// Source & Listener Attributes
2619            case AL_GAIN:
2620                *value = oalSource->GetGain();
2621                break;
2622
2623            default:
2624                alSetError(AL_INVALID_ENUM);
2625                break;
2626        }
2627	}
2628	catch (OSStatus      result) {
2629		DebugMessageN1("ERROR: alGetSourcef FAILED = %s\n", alGetString(result));
2630		alSetError(result);
2631	}
2632    catch (...) {
2633		DebugMessage("ERROR: alGetSourcef FAILED");
2634        alSetError(AL_INVALID_OPERATION);
2635	}
2636
2637	ReleaseSourceObject(oalSource);
2638}
2639
2640// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2641AL_API ALvoid AL_APIENTRY alGetSourcefv (ALuint sid, ALenum pname, ALfloat *values)
2642{
2643#if LOG_SOURCE_USAGE
2644	DebugMessageN2("alGetSourcefv--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2645#endif
2646
2647	OALSource *oalSource = NULL;
2648	try {
2649		oalSource = ProtectSourceObjectInCurrentContext(sid);
2650
2651        switch(pname)
2652        {
2653			// Source ONLY Attributes
2654            case AL_MIN_GAIN:
2655                *values = oalSource->GetMinGain();
2656                break;
2657            case AL_MAX_GAIN:
2658                *values = oalSource->GetMaxGain();
2659                break;
2660            case AL_REFERENCE_DISTANCE:
2661                *values = oalSource->GetReferenceDistance();
2662                break;
2663            case AL_ROLLOFF_FACTOR:
2664                *values = oalSource->GetRollOffFactor();
2665                break;
2666            case AL_MAX_DISTANCE:
2667                *values = oalSource->GetMaxDistance();
2668                break;
2669            case AL_PITCH:
2670                *values = oalSource->GetPitch();
2671                break;
2672            case AL_DIRECTION:
2673                oalSource->GetDirection(values[0], values[1], values[2]);
2674                break;
2675            case AL_CONE_INNER_ANGLE:
2676                *values = oalSource->GetConeInnerAngle();
2677                break;
2678            case AL_CONE_OUTER_ANGLE:
2679                *values = oalSource->GetConeOuterAngle();
2680                break;
2681            case AL_CONE_OUTER_GAIN:
2682                *values = oalSource->GetConeOuterGain();
2683                break;
2684            case AL_SEC_OFFSET:
2685                *values = oalSource->GetQueueOffsetSecondsFloat();
2686                break;
2687            case AL_SAMPLE_OFFSET:
2688                *values = oalSource->GetQueueOffset(kSampleOffset);
2689                break;
2690            case AL_BYTE_OFFSET:
2691                *values = oalSource->GetQueueOffset(kByteOffset);
2692                break;
2693
2694			// Source & Listener Attributes
2695            case AL_POSITION:
2696                oalSource->GetPosition(values[0], values[1], values[2]);
2697                break;
2698            case AL_VELOCITY:
2699                oalSource->GetVelocity(values[0], values[1], values[2]);
2700                break;
2701            case AL_GAIN:
2702                *values = oalSource->GetGain();
2703                break;
2704
2705            default:
2706                alSetError(AL_INVALID_ENUM);
2707                break;
2708        }
2709	}
2710	catch (OSStatus      result) {
2711		DebugMessageN1("ERROR: alGetSourcefv FAILED = %s\n", alGetString(result));
2712		alSetError(result);
2713	}
2714    catch (...) {
2715		DebugMessage("ERROR: alGetSourcefv FAILED");
2716        alSetError(AL_INVALID_OPERATION);
2717	}
2718
2719	ReleaseSourceObject(oalSource);
2720}
2721
2722// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2723AL_API ALvoid AL_APIENTRY alGetSource3f (ALuint sid, ALenum pname, ALfloat *v1, ALfloat *v2, ALfloat *v3)
2724{
2725#if LOG_SOURCE_USAGE
2726	DebugMessageN2("alGetSource3f--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2727#endif
2728
2729	OALSource *oalSource = NULL;
2730	try {
2731		oalSource = ProtectSourceObjectInCurrentContext(sid);
2732
2733        switch (pname)
2734        {
2735			// Source ONLY Attributes
2736            case AL_DIRECTION:
2737                oalSource->GetDirection(*v1, *v2, *v3);
2738                break;
2739
2740			// Source & Listener Attributes
2741            case AL_POSITION:
2742                oalSource->GetPosition(*v1, *v2, *v3);
2743                break;
2744            case AL_VELOCITY:
2745                oalSource->GetVelocity(*v1, *v2, *v3);
2746                break;
2747
2748            default:
2749                alSetError(AL_INVALID_ENUM);
2750                break;
2751        }
2752	}
2753	catch (OSStatus      result) {
2754		DebugMessageN1("ERROR: alGetSource3f FAILED = %s\n", alGetString(result));
2755		alSetError(result);
2756	}
2757    catch (...) {
2758		DebugMessage("ERROR: alGetSource3f FAILED");
2759        alSetError(AL_INVALID_OPERATION);
2760	}
2761
2762	ReleaseSourceObject(oalSource);
2763}
2764
2765
2766// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2767AL_API ALvoid AL_APIENTRY alGetSourcei (ALuint sid, ALenum pname, ALint *value)
2768{
2769#if LOG_SOURCE_USAGE
2770	DebugMessageN2("alGetSourcei--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2771#endif
2772
2773	OALSource *oalSource = NULL;
2774	try {
2775		oalSource = ProtectSourceObjectInCurrentContext(sid);
2776
2777        switch (pname)
2778        {
2779			// Source ONLY Attributes
2780            case AL_SOURCE_RELATIVE:
2781                *value = oalSource->GetSourceRelative();
2782                break;
2783            case AL_SOURCE_TYPE:
2784                *value = oalSource->GetSourceType();
2785                break;
2786            case AL_LOOPING:
2787                *value = oalSource->GetLooping();
2788                break;
2789            case AL_BUFFER:
2790                *value = oalSource->GetBuffer();
2791                break;
2792            case AL_BUFFERS_QUEUED:
2793                *value = oalSource->GetQLength();
2794                break;
2795            case AL_BUFFERS_PROCESSED:
2796                *value = oalSource->GetBuffersProcessed();
2797                break;
2798            case AL_REFERENCE_DISTANCE:
2799                *value = (ALint) oalSource->GetReferenceDistance();
2800                break;
2801            case AL_ROLLOFF_FACTOR:
2802                *value = (ALint) oalSource->GetRollOffFactor();
2803                break;
2804            case AL_MAX_DISTANCE:
2805                *value = (ALint) oalSource->GetMaxDistance();
2806                break;
2807            case AL_CONE_INNER_ANGLE:
2808                *value = (UInt32) oalSource->GetConeInnerAngle();
2809                break;
2810            case AL_CONE_OUTER_ANGLE:
2811                *value = (UInt32) oalSource->GetConeOuterAngle();
2812                break;
2813            case AL_CONE_OUTER_GAIN:
2814                *value = (UInt32) oalSource->GetConeOuterGain();
2815                break;
2816            case AL_SEC_OFFSET:
2817                *value = oalSource->GetQueueOffset(kSecondsOffset);
2818                break;
2819            case AL_SAMPLE_OFFSET:
2820                *value = oalSource->GetQueueOffset(kSampleOffset);
2821                break;
2822            case AL_BYTE_OFFSET:
2823                *value = oalSource->GetQueueOffset(kByteOffset);
2824                break;
2825            case AL_SOURCE_STATE:
2826                *value = oalSource->GetState();
2827                break;
2828
2829			default:
2830                alSetError(AL_INVALID_ENUM);
2831                break;
2832        }
2833	}
2834	catch (OSStatus      result) {
2835		DebugMessageN1("ERROR: alGetSourcei FAILED = %s\n", alGetString(result));
2836		alSetError(result);
2837	}
2838    catch (...) {
2839		DebugMessage("ERROR: alGetSourcei FAILED");
2840        alSetError(AL_INVALID_OPERATION);
2841	}
2842
2843	ReleaseSourceObject(oalSource);
2844}
2845
2846// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2847AL_API void AL_APIENTRY alGetSourceiv( ALuint sid,  ALenum pname, ALint* values )
2848{
2849#if LOG_SOURCE_USAGE
2850	DebugMessageN2("alGetSourceiv--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2851#endif
2852
2853	OALSource *oalSource = NULL;
2854	try {
2855		oalSource = ProtectSourceObjectInCurrentContext(sid);
2856
2857        switch(pname)
2858        {
2859			// Source ONLY Attributes
2860            case AL_SOURCE_RELATIVE:
2861                *values = oalSource->GetSourceRelative();
2862                break;
2863            case AL_SOURCE_TYPE:
2864                *values = oalSource->GetSourceType();
2865                break;
2866            case AL_LOOPING:
2867                *values = oalSource->GetLooping();
2868                break;
2869            case AL_BUFFER:
2870                *values = oalSource->GetBuffer();
2871                break;
2872            case AL_BUFFERS_QUEUED:
2873                *values = oalSource->GetQLength();
2874                break;
2875            case AL_BUFFERS_PROCESSED:
2876                *values = oalSource->GetBuffersProcessed();
2877                break;
2878            case AL_REFERENCE_DISTANCE:
2879                *values = (ALint) oalSource->GetReferenceDistance();
2880                break;
2881            case AL_ROLLOFF_FACTOR:
2882                *values = (ALint) oalSource->GetRollOffFactor();
2883                break;
2884            case AL_MAX_DISTANCE:
2885                *values = (ALint) oalSource->GetMaxDistance();
2886                break;
2887            case AL_DIRECTION:
2888                oalSource->GetDirection((Float32&) values[0], (Float32&) values[1], (Float32&) values[2]);
2889                break;
2890            case AL_CONE_INNER_ANGLE:
2891                *values = (UInt32) oalSource->GetConeInnerAngle();
2892                break;
2893            case AL_CONE_OUTER_ANGLE:
2894                *values = (UInt32) oalSource->GetConeOuterAngle();
2895                break;
2896            case AL_SEC_OFFSET:
2897                *values = oalSource->GetQueueOffset(kSecondsOffset);
2898                break;
2899            case AL_SAMPLE_OFFSET:
2900                *values = oalSource->GetQueueOffset(kSampleOffset);
2901                break;
2902            case AL_BYTE_OFFSET:
2903                *values = oalSource->GetQueueOffset(kByteOffset);
2904                break;
2905            case AL_SOURCE_STATE:
2906                *values = oalSource->GetState();
2907                break;
2908
2909			// Source & Listener Attributes
2910            case AL_POSITION:
2911                oalSource->GetPosition((Float32&) values[0], (Float32&) values[1], (Float32&) values[2]);
2912                break;
2913            case AL_VELOCITY:
2914                oalSource->GetVelocity((Float32&) values[0], (Float32&) values[1], (Float32&) values[2]);
2915                break;
2916
2917            default:
2918                alSetError(AL_INVALID_ENUM);
2919                break;
2920        }
2921	}
2922	catch (OSStatus      result) {
2923		DebugMessageN1("ERROR: alGetSourceiv FAILED = %s\n", alGetString(result));
2924		alSetError(result);
2925	}
2926    catch (...) {
2927		DebugMessage("ERROR: alGetSourceiv FAILED");
2928        alSetError(AL_INVALID_OPERATION);
2929	}
2930
2931	ReleaseSourceObject(oalSource);
2932}
2933
2934// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2935AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum pname, ALint* v1, ALint*  v2, ALint*  v3)
2936{
2937#if LOG_SOURCE_USAGE
2938	DebugMessageN2("alGetSource3i--> source %ld : %s", (long int) sid, GetALAttributeString(pname));
2939#endif
2940
2941	OALSource *oalSource = NULL;
2942	try {
2943		oalSource = ProtectSourceObjectInCurrentContext(sid);
2944
2945        switch (pname)
2946        {
2947			// Source ONLY Attributes
2948            case AL_DIRECTION:
2949                oalSource->GetDirection((Float32&) *v1, (Float32&)*v2, (Float32&)*v3);
2950                break;
2951
2952			// Source & Listener Attributes
2953            case AL_POSITION:
2954                oalSource->GetPosition((Float32&) *v1, (Float32&)*v2, (Float32&)*v3);
2955                break;
2956            case AL_VELOCITY:
2957                oalSource->GetVelocity((Float32&) *v1, (Float32&)*v2, (Float32&)*v3);
2958                break;
2959
2960            default:
2961                alSetError(AL_INVALID_ENUM);
2962                break;
2963        }
2964	}
2965	catch (OSStatus      result) {
2966		DebugMessageN1("ERROR: alGetSource3i FAILED = %s\n", alGetString(result));
2967		alSetError(result);
2968	}
2969    catch (...) {
2970		DebugMessage("ERROR: alGetSource3i FAILED");
2971        alSetError(AL_INVALID_OPERATION);
2972	}
2973
2974	ReleaseSourceObject(oalSource);
2975}
2976
2977// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2978AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint sid)
2979{
2980#if LOG_SOURCE_USAGE
2981	DebugMessageN1("alSourcePlay--> source %ld", (long int) sid);
2982#endif
2983
2984	OALSource *oalSource = NULL;
2985	try {
2986		oalSource = ProtectSourceObjectInCurrentContext(sid);
2987
2988		oalSource->Play();					// start playing the queue
2989	}
2990	catch (OSStatus      result) {
2991		DebugMessageN1("ERROR: alSourcePlay FAILED = %s\n", alGetString(result));
2992		alSetError(result);
2993	}
2994    catch (...) {
2995		DebugMessage("ERROR: alSourcePlay FAILED");
2996        alSetError(AL_INVALID_OPERATION);
2997	}
2998
2999	ReleaseSourceObject(oalSource);
3000}
3001
3002// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3003AL_API ALvoid AL_APIENTRY alSourcePause (ALuint sid)
3004{
3005#if LOG_SOURCE_USAGE
3006	DebugMessageN1("alSourcePause--> source %ld", (long int) sid);
3007#endif
3008
3009	OALSource *oalSource = NULL;
3010	try {
3011		oalSource = ProtectSourceObjectInCurrentContext(sid);
3012
3013		oalSource->Pause();
3014	}
3015	catch (OSStatus      result) {
3016		DebugMessageN1("ERROR: alSourcePause FAILED = %s\n", alGetString(result));
3017		alSetError(result);
3018	}
3019    catch (...) {
3020		DebugMessage("ERROR: alSourcePause FAILED");
3021        alSetError(AL_INVALID_OPERATION);
3022	}
3023
3024	ReleaseSourceObject(oalSource);
3025}
3026
3027// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3028AL_API ALvoid AL_APIENTRY alSourceStop (ALuint sid)
3029{
3030#if LOG_SOURCE_USAGE
3031	DebugMessageN1("alSourceStop--> source %ld", (long int) sid);
3032#endif
3033
3034	OALSource *oalSource = NULL;
3035	try {
3036		oalSource = ProtectSourceObjectInCurrentContext(sid);
3037
3038        oalSource->Stop();
3039	}
3040	catch (OSStatus      result) {
3041		DebugMessageN1("ERROR: alSourceStop FAILED = %s\n", alGetString(result));
3042		alSetError(result);
3043	}
3044    catch (...) {
3045		DebugMessage("ERROR: alSourceStop FAILED");
3046        alSetError(AL_INVALID_OPERATION);
3047	}
3048
3049	ReleaseSourceObject(oalSource);
3050}
3051
3052// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3053AL_API ALvoid AL_APIENTRY alSourceRewind (ALuint sid)
3054{
3055#if LOG_SOURCE_USAGE
3056	DebugMessageN1("alSourceRewind--> source %ld", (long int) sid);
3057#endif
3058
3059	OALSource *oalSource = NULL;
3060	try {
3061		oalSource = ProtectSourceObjectInCurrentContext(sid);
3062
3063        oalSource->Rewind();
3064	}
3065	catch (OSStatus      result) {
3066		DebugMessageN1("ERROR: alSourceRewind FAILED = %s\n", alGetString(result));
3067		alSetError(result);
3068	}
3069    catch (...) {
3070		DebugMessage("ERROR: alSourceRewind FAILED");
3071        alSetError(AL_INVALID_OPERATION);
3072	}
3073
3074	ReleaseSourceObject(oalSource);
3075}
3076
3077// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3078AL_API void	AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids )
3079{
3080#if LOG_SOURCE_USAGE
3081	DebugMessage("alSourcePlayv--> sources = ");
3082	for (UInt32	i = 0; i < (UInt32) ns; i++) {
3083		printf("%ld ", (long int) sids[i]);
3084	}
3085	printf("\n");
3086#endif
3087
3088	try {
3089        for (UInt32	i = 0; i < (UInt32) ns; i++)
3090            alSourcePlay(sids[i]);
3091    }
3092	catch (OSStatus      result) {
3093		DebugMessageN1("ERROR: alSourcePlayv FAILED = %s\n", alGetString(result));
3094		alSetError(result);
3095	}
3096    catch (...) {
3097		DebugMessage("ERROR: alSourcePlayv FAILED");
3098        alSetError(AL_INVALID_OPERATION);
3099	}
3100}
3101
3102// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3103AL_API void	AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids )
3104{
3105#if LOG_SOURCE_USAGE
3106	DebugMessage("alSourcePausev--> sources = ");
3107	for (UInt32	i = 0; i < (UInt32) ns; i++) {
3108		printf("%ld ", (long int) sids[i]);
3109	}
3110	printf("\n");
3111#endif
3112
3113	try {
3114        for (UInt32	i = 0; i < (UInt32) ns; i++)
3115            alSourcePause(sids[i]);
3116    }
3117	catch (OSStatus      result) {
3118		DebugMessageN1("ERROR: alSourcePausev FAILED = %s\n", alGetString(result));
3119		alSetError(result);
3120	}
3121    catch (...) {
3122		DebugMessage("ERROR: alSourcePausev FAILED");
3123        alSetError(AL_INVALID_OPERATION);
3124	}
3125}
3126
3127// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3128AL_API void	AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids )
3129{
3130#if LOG_SOURCE_USAGE
3131	DebugMessage("alSourceStopv--> sources = ");
3132	for (UInt32	i = 0; i < (UInt32) ns; i++) {
3133		printf("%ld ", (long int) sids[i]);
3134	}
3135	printf("\n");
3136#endif
3137
3138	try {
3139        for (UInt32	i = 0; i < (UInt32) ns; i++)
3140            alSourceStop(sids[i]);
3141    }
3142	catch (OSStatus      result) {
3143		DebugMessageN1("ERROR: alSourceStopv FAILED = %s\n", alGetString(result));
3144		alSetError(result);
3145	}
3146    catch (...) {
3147		DebugMessage("ERROR: alSourceStopv FAILED");
3148        alSetError(AL_INVALID_OPERATION);
3149	}
3150}
3151
3152// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3153AL_API void	AL_APIENTRY alSourceRewindv(ALsizei ns, const ALuint *sids)
3154{
3155#if LOG_SOURCE_USAGE
3156	DebugMessage("alSourceRewindv--> sources = ");
3157	for (UInt32	i = 0; i < (UInt32) ns; i++) {
3158		printf("%ld ", (long int) sids[i]);
3159	}
3160	printf("\n");
3161#endif
3162
3163	try {
3164        for (UInt32	i = 0; i < (UInt32) ns; i++)
3165            alSourceRewind(sids[i]);
3166    }
3167	catch (OSStatus      result) {
3168		DebugMessageN1("ERROR: alSourceRewindv FAILED = %s\n", alGetString(result));
3169		alSetError(result);
3170	}
3171    catch (...) {
3172		DebugMessage("ERROR: alSourceRewindv FAILED");
3173        alSetError(AL_INVALID_OPERATION);
3174	}
3175}
3176
3177// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3178AL_API void	AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint* bids )
3179{
3180#if LOG_SOURCE_USAGE
3181	DebugMessageN2("alSourceQueueBuffers--> source %ld : numEntries = %ld", (long int) sid, (long int) numEntries);
3182#endif
3183
3184#if LOG_BUFFER_USAGE
3185	printf("alSourceQueueBuffers--> (%ld) ", (long int) numEntries);
3186	for (UInt32	i = 0; i < (UInt32) numEntries; i++) {
3187		printf("%ld, ", (long int) bids[i]);
3188	}
3189	printf("\n");
3190#endif
3191
3192
3193	if (numEntries == 0)
3194		return;	// no buffers were actually requested for queueing
3195
3196	OALSource		*oalSource = NULL;
3197
3198	try {
3199        if (gOALBufferMap == NULL)
3200            throw ((OSStatus) AL_INVALID_OPERATION);
3201
3202		oalSource = ProtectSourceObjectInCurrentContext(sid);
3203
3204        //If the source is transitioning to flush Q, add the buffers to the temporary queue for now
3205        if(oalSource->IsSourceTransitioningToFlushQ())
3206        {
3207            // verify that buffers provided are valid before queueing them.
3208            for (UInt32	i = 0; i < (UInt32) numEntries; i++)
3209            {
3210                if (bids[i] != AL_NONE)
3211                {
3212                    // verify that this is a valid buffer
3213                    OALBuffer *oalBuffer = gOALBufferMap->Get(bids[i]);
3214                    if (oalBuffer == NULL)
3215                        throw ((OSStatus) AL_INVALID_VALUE);
3216                }
3217            }
3218
3219            // all valid buffers, so add them to the queue in Post Render
3220            for (UInt32	i = 0; i < (UInt32) numEntries; i++)
3221            {
3222                oalSource->AddToTempQueue(bids[i], gOALBufferMap->Get(bids[i]));
3223            }
3224        }
3225        else
3226        {
3227            // The source type must now be checked for static or streaming
3228            // It is illegal to append buffers to a Q, because a static designation means it only can use 1 buffer
3229            if (oalSource->GetSourceType() == AL_STATIC)
3230            {
3231                DebugMessage("ERROR: alSourceQueueBuffers FAILED oalSource->GetSourceType() == AL_STATIC");
3232                throw ((OSStatus) AL_INVALID_OPERATION);
3233            }
3234
3235            CAGuard::Locker locked(*gBufferMapLock);
3236
3237            // verify that buffers provided are valid before queueing them.
3238            for (UInt32	i = 0; i < (UInt32) numEntries; i++)
3239            {
3240                if (bids[i] != AL_NONE)
3241                {
3242                    // verify that this is a valid buffer
3243                    OALBuffer *oalBuffer = gOALBufferMap->Get(bids[i]);
3244                    if (oalBuffer == NULL)
3245                    {
3246                        DebugMessage("ERROR: alSourceQueueBuffers FAILED oalBuffer == NULL");
3247                        throw ((OSStatus) AL_INVALID_VALUE);				// an invalid buffer id has been provided
3248                    }
3249                }
3250            }
3251
3252            // all valid buffers, so append them to the queue
3253            for (UInt32	i = 0; i < (UInt32) numEntries; i++)
3254            {
3255                oalSource->AddToQueue(bids[i], gOALBufferMap->Get(bids[i]));
3256            }
3257        }
3258	}
3259	catch (OSStatus		result) {
3260		DebugMessageN1("ERROR: alSourceQueueBuffers FAILED = %s\n", alGetString(result));
3261		alSetError(result);
3262	}
3263	catch (...) {
3264		DebugMessage("ERROR: alSourceQueueBuffers FAILED");
3265        alSetError(AL_INVALID_OPERATION);
3266	}
3267
3268	ReleaseSourceObject(oalSource);
3269}
3270
3271// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3272AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers (ALuint sid, ALsizei n, ALuint *buffers)
3273{
3274#if LOG_SOURCE_USAGE
3275	DebugMessageN2("alSourceUnqueueBuffers--> source %ld : count = %ld", (long int) sid, (long int) n);
3276#endif
3277
3278	if (n == 0)
3279		return;
3280
3281	OALSource		*oalSource = NULL;
3282
3283	try {
3284        if (buffers == NULL)
3285            throw ((OSStatus) AL_INVALID_VALUE);
3286
3287        if (gOALBufferMap == NULL)
3288            throw ((OSStatus) AL_INVALID_OPERATION);
3289
3290		oalSource = ProtectSourceObjectInCurrentContext(sid);
3291
3292		CAGuard::Locker locked(*gBufferMapLock);
3293
3294        if (oalSource->GetQLength() < (UInt32) n)
3295            throw (OSStatus) AL_INVALID_VALUE;				// n is greater than the source's Q length
3296
3297		oalSource->RemoveBuffersFromQueue(n, buffers);
3298	}
3299	catch (OSStatus		result) {
3300		DebugMessageN1("ERROR: alSourceUnqueueBuffers FAILED = %s\n", alGetString(result));
3301		// reinitialize the elements in the buffers array
3302		if (buffers)
3303		{
3304			for (UInt32	i = 0; i < (UInt32) n; i++)
3305				buffers[i] = 0;
3306		}
3307		// this would be real bad, as now we have a buffer queue in an unknown state
3308		alSetError(result);
3309	}
3310	catch (...){
3311		DebugMessage("ERROR: alSourceUnqueueBuffers FAILED");
3312        alSetError(AL_INVALID_OPERATION);
3313	}
3314
3315	ReleaseSourceObject(oalSource);
3316
3317#if LOG_BUFFER_USAGE
3318	printf("sid = %ld alSourceUnqueueBuffers--> (%ld) ", (long int) sid, (long int) n);
3319	for (UInt32	i = 0; i < (UInt32) n; i++) {
3320		printf("%ld, ", (long int) buffers[i]);
3321	}
3322	printf("\n");
3323#endif
3324}
3325
3326// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3327// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3328
3329// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3330#pragma mark ***** Listeners *****
3331// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3332AL_API ALvoid AL_APIENTRY alListenerf (ALenum pname, ALfloat value)
3333{
3334#if LOG_API_USAGE
3335	DebugMessageN2("alListenerf--> attribute = %s : value %.2f", GetALAttributeString(pname), value);
3336#endif
3337	OALContext		*oalContext = NULL;
3338
3339	try {
3340        oalContext = ProtectContextObject(gCurrentContext);
3341        switch (pname)
3342        {
3343            case AL_GAIN:
3344				oalContext->SetListenerGain((Float32) value);     //gListener.Gain=value;
3345                break;
3346
3347			default:
3348                alSetError(AL_INVALID_ENUM);
3349                break;
3350        }
3351	}
3352	catch (OSStatus		result) {
3353 		DebugMessageN1("ERROR: alListenerf FAILED = %s\n", alGetString(result));
3354        alSetError(result);
3355    }
3356	catch (...) {
3357 		DebugMessage("ERROR: alListenerf FAILED");
3358        alSetError(AL_INVALID_OPERATION);   // by default
3359	}
3360
3361	ReleaseContextObject(oalContext);
3362}
3363
3364// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3365AL_API ALvoid AL_APIENTRY alListenerfv (ALenum pname, const ALfloat *values)
3366{
3367#if LOG_API_USAGE
3368	DebugMessageN1("alListenerfv--> attribute = %s", GetALAttributeString(pname));
3369#endif
3370
3371	OALContext		*oalContext = NULL;
3372
3373	try {
3374
3375		oalContext = ProtectContextObject(gCurrentContext);
3376        switch(pname)
3377        {
3378            case AL_POSITION:
3379                oalContext->SetListenerPosition(values[0], values[1], values[2]);
3380                break;
3381            case AL_VELOCITY:
3382                oalContext->SetListenerVelocity(values[0], values[1], values[2]);
3383                break;
3384            case AL_GAIN:
3385                oalContext->SetListenerGain((Float32) *values);
3386                break;
3387            case AL_ORIENTATION:
3388                oalContext->SetListenerOrientation(	values[0], values[1], values[2],
3389                                                    values[3], values[4], values[5]);
3390                break;
3391            default:
3392                alSetError(AL_INVALID_ENUM);
3393                break;
3394        }
3395	}
3396	catch (OSStatus		result) {
3397 		DebugMessageN1("ERROR: alListenerfv FAILED = %s\n", alGetString(result));
3398       alSetError(result);
3399    }
3400	catch (...) {
3401 		DebugMessage("ERROR: alListenerfv FAILED");
3402        alSetError(AL_INVALID_OPERATION);   // by default
3403	}
3404
3405	ReleaseContextObject(oalContext);
3406}
3407
3408// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3409AL_API ALvoid AL_APIENTRY alListener3f (ALenum pname, ALfloat v1, ALfloat v2, ALfloat v3)
3410{
3411#if LOG_API_USAGE
3412	DebugMessageN4("alListener3f--> attribute = %s : %.2f : %.2f : %.2f", GetALAttributeString(pname), v1, v2, v3);
3413#endif
3414
3415	OALContext		*oalContext = NULL;
3416
3417	try {
3418        oalContext = ProtectContextObject(gCurrentContext);
3419        switch (pname)
3420        {
3421            case AL_POSITION:
3422                oalContext->SetListenerPosition(v1, v2, v3);
3423                break;
3424            case AL_VELOCITY:
3425                oalContext->SetListenerVelocity(v1, v2, v3);
3426                break;
3427            default:
3428                alSetError(AL_INVALID_ENUM);
3429                break;
3430        }
3431	}
3432	catch (OSStatus		result) {
3433		DebugMessageN1("ERROR: alListener3f FAILED = %s\n", alGetString(result));
3434        alSetError(result);
3435    }
3436	catch (...) {
3437		DebugMessage("ERROR: alListener3f FAILED");
3438        alSetError(AL_INVALID_OPERATION);   // by default
3439	}
3440
3441	ReleaseContextObject(oalContext);
3442}
3443
3444// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3445AL_API ALvoid AL_APIENTRY alListeneri (ALenum pname, ALint value)
3446{
3447#if LOG_API_USAGE
3448	DebugMessage("***** alListeneri");
3449#endif
3450	alSetError(AL_INVALID_ENUM);
3451}
3452
3453// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3454AL_API void AL_APIENTRY alListeneriv( ALenum pname, const ALint* values )
3455{
3456#if LOG_API_USAGE
3457	DebugMessageN1("alListeneriv--> attribute = %s", GetALAttributeString(pname));
3458#endif
3459
3460	OALContext		*oalContext = NULL;
3461
3462	try {
3463		oalContext = ProtectContextObject(gCurrentContext);
3464        switch(pname)
3465        {
3466            case AL_POSITION:
3467                oalContext->SetListenerPosition(values[0], values[1], values[2]);
3468                break;
3469            case AL_VELOCITY:
3470                oalContext->SetListenerVelocity(values[0], values[1], values[2]);
3471                break;
3472            case AL_ORIENTATION:
3473                oalContext->SetListenerOrientation(	values[0], values[1], values[2],
3474                                                    values[3], values[4], values[5]);
3475                break;
3476            default:
3477                alSetError(AL_INVALID_ENUM);
3478                break;
3479        }
3480	}
3481	catch (OSStatus		result) {
3482 		DebugMessageN1("ERROR: alListeneriv FAILED = %s\n", alGetString(result));
3483       alSetError(result);
3484    }
3485	catch (...) {
3486 		DebugMessage("ERROR: alListeneriv FAILED");
3487        alSetError(AL_INVALID_OPERATION);   // by default
3488	}
3489
3490	ReleaseContextObject(oalContext);
3491}
3492
3493// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3494AL_API void AL_APIENTRY alListener3i( ALenum pname, ALint v1, ALint v2, ALint v3 )
3495{
3496#if LOG_API_USAGE
3497	DebugMessageN4("alListener3i--> attribute = %s : %ld : %ld : %ld", GetALAttributeString(pname), (long int) v1, (long int) v2, (long int) v3);
3498#endif
3499
3500	OALContext		*oalContext = NULL;
3501
3502	try {
3503        oalContext = ProtectContextObject(gCurrentContext);
3504        switch (pname)
3505        {
3506            case AL_POSITION:
3507                oalContext->SetListenerPosition(v1, v2, v3);
3508                break;
3509            case AL_VELOCITY:
3510                oalContext->SetListenerVelocity(v1, v2, v3);
3511                break;
3512            default:
3513                alSetError(AL_INVALID_ENUM);
3514                break;
3515        }
3516	}
3517	catch (OSStatus		result) {
3518		DebugMessageN1("ERROR: alListener3f FAILED = %s\n", alGetString(result));
3519        alSetError(result);
3520    }
3521	catch (...) {
3522		DebugMessage("ERROR: alListener3f FAILED");
3523        alSetError(AL_INVALID_OPERATION);   // by default
3524	}
3525
3526	ReleaseContextObject(oalContext);
3527}
3528
3529// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3530AL_API ALvoid AL_APIENTRY alGetListenerf( ALenum pname, ALfloat* value )
3531{
3532#if LOG_API_USAGE
3533	DebugMessageN1("alGetListenerf--> attribute = %s", GetALAttributeString(pname));
3534#endif
3535
3536	OALContext* oalContext = NULL;
3537
3538	try {
3539        oalContext = ProtectContextObject(gCurrentContext);
3540        switch(pname)
3541        {
3542            case AL_GAIN:
3543                *value = oalContext->GetListenerGain();
3544                break;
3545            default:
3546                alSetError(AL_INVALID_ENUM);
3547                break;
3548        }
3549	}
3550	catch (OSStatus		result) {
3551		DebugMessageN1("ERROR: alGetListenerf FAILED = %s\n", alGetString(result));
3552        alSetError(result);
3553    }
3554	catch (...) {
3555		DebugMessage("ERROR: alGetListenerf FAILED");
3556        alSetError(AL_INVALID_OPERATION);   // by default
3557	}
3558
3559	ReleaseContextObject(oalContext);
3560}
3561
3562// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3563AL_API ALvoid AL_APIENTRY alGetListenerfv( ALenum pname, ALfloat* values )
3564{
3565#if LOG_API_USAGE
3566	DebugMessageN1("alGetListenerfv--> attribute = %s", GetALAttributeString(pname));
3567#endif
3568
3569	OALContext* oalContext = NULL;
3570
3571	try {
3572        oalContext = ProtectContextObject(gCurrentContext);
3573        switch (pname)
3574        {
3575            case AL_POSITION:
3576                oalContext->GetListenerPosition(&values[0], &values[1], &values[2]);
3577                break;
3578            case AL_VELOCITY:
3579                oalContext->GetListenerVelocity(&values[0], &values[1], &values[2]);
3580                break;
3581            case AL_GAIN:
3582                *values = oalContext->GetListenerGain();
3583                break;
3584            case AL_ORIENTATION:
3585                oalContext->GetListenerOrientation( &values[0], &values[1], &values[2],
3586                                                    &values[3], &values[4], &values[5]);
3587                break;
3588            default:
3589                alSetError(AL_INVALID_ENUM);
3590                break;
3591        }
3592	}
3593	catch (OSStatus		result) {
3594		DebugMessageN1("ERROR: alGetListenerfv FAILED = %s\n", alGetString(result));
3595        alSetError(result);
3596    }
3597	catch (...) {
3598		DebugMessage("ERROR: alGetListenerfv FAILED");
3599        alSetError(AL_INVALID_OPERATION);   // by default
3600	}
3601
3602	ReleaseContextObject(oalContext);
3603}
3604
3605// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3606AL_API ALvoid AL_APIENTRY alGetListener3f( ALenum pname, ALfloat* v1, ALfloat* v2, ALfloat* v3 )
3607{
3608#if LOG_API_USAGE
3609	DebugMessageN1("alGetListener3f--> attribute = %s", GetALAttributeString(pname));
3610#endif
3611
3612	OALContext* oalContext = NULL;
3613
3614	try {
3615        oalContext = ProtectContextObject(gCurrentContext);
3616        switch(pname)
3617        {
3618            case AL_POSITION:
3619                oalContext->GetListenerPosition(v1, v2, v3);
3620                break;
3621            case AL_VELOCITY:
3622                oalContext->GetListenerVelocity(v1, v2, v3);
3623                break;
3624            default:
3625                alSetError(AL_INVALID_ENUM);
3626                break;
3627        }
3628	}
3629	catch (OSStatus		result) {
3630		DebugMessageN1("ERROR: alGetListener3f FAILED = %s\n", alGetString(result));
3631        alSetError(result);
3632    }
3633	catch (...) {
3634		DebugMessage("ERROR: alGetListener3f FAILED");
3635        alSetError(AL_INVALID_OPERATION);   // by default
3636	}
3637
3638	ReleaseContextObject(oalContext);
3639}
3640
3641// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3642AL_API ALvoid AL_APIENTRY alGetListeneri( ALenum pname, ALint* value )
3643{
3644#if LOG_API_USAGE
3645	DebugMessageN1("alGetListeneri--> attribute = %s", GetALAttributeString(pname));
3646#endif
3647
3648	*value = 0;
3649
3650	try {
3651		switch (pname)
3652		{
3653			default:
3654				alSetError(AL_INVALID_VALUE);
3655				break;
3656		}
3657	}
3658	catch (...) {
3659 		DebugMessage("ERROR: alGetListeneri FAILED");
3660        alSetError(AL_INVALID_OPERATION); // not available yet as the device is not setup
3661	}
3662}
3663
3664// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3665AL_API void AL_APIENTRY alGetListeneriv( ALenum pname, ALint* values )
3666{
3667#if LOG_API_USAGE
3668	DebugMessageN1("alGetListeneriv--> attribute = %s", GetALAttributeString(pname));
3669#endif
3670
3671	OALContext* oalContext = NULL;
3672
3673	try {
3674        oalContext = ProtectContextObject(gCurrentContext);
3675        switch (pname)
3676        {
3677            case AL_POSITION:
3678                oalContext->GetListenerPosition((Float32*) &values[0], (Float32*) &values[1], (Float32*) &values[2]);
3679                break;
3680            case AL_VELOCITY:
3681                oalContext->GetListenerVelocity((Float32*) &values[0], (Float32*) &values[1], (Float32*) &values[2]);
3682                break;
3683            case AL_ORIENTATION:
3684                oalContext->GetListenerOrientation( (Float32*) &values[0], (Float32*) &values[1], (Float32*) &values[2],
3685                                                    (Float32*) &values[3], (Float32*) &values[4], (Float32*) &values[5]);
3686                break;
3687            default:
3688                alSetError(AL_INVALID_ENUM);
3689                break;
3690        }
3691	}
3692	catch (OSStatus		result) {
3693		DebugMessageN1("ERROR: alGetListenerfv FAILED = %s\n", alGetString(result));
3694        alSetError(result);
3695    }
3696	catch (...) {
3697		DebugMessage("ERROR: alGetListenerfv FAILED");
3698        alSetError(AL_INVALID_OPERATION);   // by default
3699	}
3700
3701	ReleaseContextObject(oalContext);
3702}
3703
3704// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3705AL_API void AL_APIENTRY alGetListener3i( ALenum pname, ALint *v1, ALint *v2, ALint *v3 )
3706{
3707#if LOG_API_USAGE
3708	DebugMessageN1("alGetListener3i--> attribute = %s", GetALAttributeString(pname));
3709#endif
3710
3711	OALContext* oalContext = NULL;
3712
3713	try {
3714        oalContext = ProtectContextObject(gCurrentContext);
3715        switch(pname)
3716        {
3717            case AL_POSITION:
3718                oalContext->GetListenerPosition((Float32*) v1, (Float32*) v2, (Float32*) v3);
3719                break;
3720            case AL_VELOCITY:
3721                oalContext->GetListenerVelocity((Float32*) v1, (Float32*) v2, (Float32*) v3);
3722                break;
3723            default:
3724                alSetError(AL_INVALID_ENUM);
3725                break;
3726        }
3727	}
3728	catch (OSStatus		result) {
3729		DebugMessageN1("ERROR: alGetListener3f FAILED = %s\n", alGetString(result));
3730        alSetError(result);
3731    }
3732	catch (...) {
3733		DebugMessage("ERROR: alGetListener3f FAILED");
3734        alSetError(AL_INVALID_OPERATION);   // by default
3735	}
3736
3737	ReleaseContextObject(oalContext);
3738}
3739
3740// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3741#pragma mark ***** Global Settings *****
3742// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3743AL_API ALvoid AL_APIENTRY	alDistanceModel (ALenum value)
3744{
3745#if LOG_API_USAGE
3746	DebugMessageN1("alDistanceModel--> model = %s", GetALAttributeString(value));
3747#endif
3748
3749	OALContext* oalContext = NULL;
3750
3751	try {
3752        switch (value)
3753        {
3754            case AL_NONE:
3755            case AL_INVERSE_DISTANCE:
3756            case AL_INVERSE_DISTANCE_CLAMPED:
3757            case AL_LINEAR_DISTANCE:
3758            case AL_LINEAR_DISTANCE_CLAMPED:
3759            case AL_EXPONENT_DISTANCE:
3760            case AL_EXPONENT_DISTANCE_CLAMPED:
3761            {
3762				oalContext = ProtectContextObject(gCurrentContext);
3763				oalContext->SetDistanceModel(value);
3764            }
3765            break;
3766
3767            default:
3768                alSetError(AL_INVALID_VALUE);
3769                break;
3770        }
3771    }
3772	catch (OSStatus		result) {
3773		DebugMessageN1("ERROR: alDistanceModel FAILED = %s\n", alGetString(result));
3774        alSetError(result);
3775    }
3776    catch (...) {
3777		DebugMessage("ERROR: alDistanceModel FAILED");
3778        alSetError(AL_INVALID_OPERATION);   // by default
3779    }
3780
3781	ReleaseContextObject(oalContext);
3782}
3783
3784// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3785AL_API ALvoid AL_APIENTRY alDopplerFactor (ALfloat value)
3786{
3787#if LOG_API_USAGE
3788	DebugMessageN1("alDopplerFactor---> setting = %.f2", value);
3789#endif
3790
3791	OALContext* oalContext = NULL;
3792
3793	try {
3794        if (value < 0.0f)
3795            throw ((OSStatus) AL_INVALID_VALUE);
3796
3797        oalContext = ProtectContextObject(gCurrentContext);
3798		oalContext->SetDopplerFactor(value);
3799	}
3800	catch (OSStatus		result) {
3801		DebugMessageN1("ERROR: alDopplerFactor FAILED = %s\n", alGetString(result));
3802        alSetError(result);
3803    }
3804    catch (...) {
3805		DebugMessage("ERROR: alDopplerFactor FAILED");
3806        alSetError(AL_INVALID_OPERATION);   // by default
3807    }
3808
3809	ReleaseContextObject(oalContext);
3810}
3811
3812// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3813AL_API ALvoid AL_APIENTRY alDopplerVelocity (ALfloat value)
3814{
3815#if LOG_API_USAGE
3816	DebugMessageN1("alDopplerVelocity---> setting = %.f2", value);
3817#endif
3818
3819	OALContext* oalContext = NULL;
3820
3821	try {
3822        if (value <= 0.0f)
3823            throw ((OSStatus) AL_INVALID_VALUE);
3824
3825        oalContext = ProtectContextObject(gCurrentContext);
3826		oalContext->SetDopplerVelocity(value);
3827	}
3828	catch (OSStatus		result) {
3829		DebugMessageN1("ERROR: alDopplerVelocity FAILED = %s\n", alGetString(result));
3830        alSetError(result);
3831    }
3832    catch (...) {
3833		DebugMessage("ERROR: alDopplerVelocity FAILED");
3834        alSetError(AL_INVALID_OPERATION);   // by default
3835    }
3836
3837	ReleaseContextObject(oalContext);
3838}
3839
3840// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3841AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value )
3842{
3843#if LOG_API_USAGE
3844	DebugMessageN1("alSpeedOfSound---> setting = %.f2", value);
3845#endif
3846
3847	OALContext* oalContext = NULL;
3848
3849	try {
3850		if (value <= 0.0f)
3851			throw ((OSStatus) AL_INVALID_VALUE);
3852
3853        oalContext = ProtectContextObject(gCurrentContext);
3854		oalContext->SetSpeedOfSound(value);
3855	}
3856	catch (OSStatus		result) {
3857		DebugMessageN1("ERROR: alSpeedOfSound FAILED = %s\n", alGetString(result));
3858        alSetError(result);
3859    }
3860    catch (...) {
3861		DebugMessage("ERROR: alSpeedOfSound FAILED");
3862        alSetError(AL_INVALID_OPERATION);   // by default
3863    }
3864
3865	ReleaseContextObject(oalContext);
3866}
3867
3868// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3869AL_API const ALchar* AL_APIENTRY alGetString( ALenum pname )
3870{
3871#if LOG_API_USAGE
3872	DebugMessageN1("alGetString = %s", GetALAttributeString(pname));
3873#endif
3874
3875	switch (pname)
3876	{
3877		case AL_VENDOR:
3878			return (ALchar *)alVendor;
3879		case AL_VERSION:
3880			return (ALchar *)alVersion;
3881		case AL_RENDERER:
3882			return (ALchar *)alRenderer;
3883		case AL_EXTENSIONS:
3884			return (ALchar *)GetALExtensionList();
3885		case AL_NO_ERROR:
3886			return (ALchar *)alNoError;
3887		case AL_INVALID_NAME:
3888			return (ALchar *)alErrInvalidName;
3889		case AL_INVALID_ENUM:
3890			return (ALchar *)alErrInvalidEnum;
3891		case AL_INVALID_VALUE:
3892			return (ALchar *)alErrInvalidValue;
3893		case AL_INVALID_OPERATION:
3894			return (ALchar *)alErrInvalidOp;
3895		case AL_OUT_OF_MEMORY:
3896			return (ALchar *)alErrOutOfMemory;
3897		case -1:
3898			return (ALchar *)unknownImplementationError;
3899		default:
3900			alSetError(AL_INVALID_ENUM);
3901			break;
3902	}
3903	return NULL;
3904}
3905
3906// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3907AL_API ALenum	AL_APIENTRY alGetEnumValue( const ALchar* ename )
3908{
3909#if LOG_API_USAGE
3910	DebugMessageN1("alGetEnumValue: %s", ename);
3911#endif
3912
3913	// AL
3914	if (strcmp("AL_INVALID", (const char *)ename) == 0) { return AL_INVALID; }
3915	if (strcmp("AL_NONE", (const char *)ename) == 0) { return AL_NONE; }
3916	if (strcmp("AL_FALSE", (const char *)ename) == 0) { return AL_FALSE; }
3917	if (strcmp("AL_TRUE", (const char *)ename) == 0) { return AL_TRUE; }
3918	if (strcmp("AL_SOURCE_RELATIVE", (const char *)ename) == 0) { return AL_SOURCE_RELATIVE; }
3919	if (strcmp("AL_CONE_INNER_ANGLE", (const char *)ename) == 0) { return AL_CONE_INNER_ANGLE; }
3920	if (strcmp("AL_CONE_OUTER_ANGLE", (const char *)ename) == 0) { return AL_CONE_OUTER_ANGLE; }
3921	if (strcmp("AL_CONE_OUTER_GAIN", (const char *)ename) == 0) { return AL_CONE_OUTER_GAIN; }
3922	if (strcmp("AL_PITCH", (const char *)ename) == 0) { return AL_PITCH; }
3923	if (strcmp("AL_POSITION", (const char *)ename) == 0) { return AL_POSITION; }
3924	if (strcmp("AL_DIRECTION", (const char *)ename) == 0) { return AL_DIRECTION; }
3925	if (strcmp("AL_VELOCITY", (const char *)ename) == 0) { return AL_VELOCITY; }
3926	if (strcmp("AL_LOOPING", (const char *)ename) == 0) { return AL_LOOPING; }
3927	if (strcmp("AL_BUFFER", (const char *)ename) == 0) { return AL_BUFFER; }
3928	if (strcmp("AL_GAIN", (const char *)ename) == 0) { return AL_GAIN; }
3929	if (strcmp("AL_MIN_GAIN", (const char *)ename) == 0) { return AL_MIN_GAIN; }
3930	if (strcmp("AL_MAX_GAIN", (const char *)ename) == 0) { return AL_MAX_GAIN; }
3931	if (strcmp("AL_ORIENTATION", (const char *)ename) == 0) { return AL_ORIENTATION; }
3932	if (strcmp("AL_REFERENCE_DISTANCE", (const char *)ename) == 0) { return AL_REFERENCE_DISTANCE; }
3933	if (strcmp("AL_ROLLOFF_FACTOR", (const char *)ename) == 0) { return AL_ROLLOFF_FACTOR; }
3934	if (strcmp("AL_MAX_DISTANCE", (const char *)ename) == 0) { return AL_MAX_DISTANCE; }
3935	if (strcmp("AL_SOURCE_STATE", (const char *)ename) == 0) { return AL_SOURCE_STATE; }
3936	if (strcmp("AL_INITIAL", (const char *)ename) == 0) { return AL_INITIAL; }
3937	if (strcmp("AL_PLAYING", (const char *)ename) == 0) { return AL_PLAYING; }
3938	if (strcmp("AL_PAUSED", (const char *)ename) == 0) { return AL_PAUSED; }
3939	if (strcmp("AL_STOPPED", (const char *)ename) == 0) { return AL_STOPPED; }
3940	if (strcmp("AL_BUFFERS_QUEUED", (const char *)ename) == 0) { return AL_BUFFERS_QUEUED; }
3941	if (strcmp("AL_BUFFERS_PROCESSED", (const char *)ename) == 0) { return AL_BUFFERS_PROCESSED; }
3942	if (strcmp("AL_FORMAT_MONO8", (const char *)ename) == 0) { return AL_FORMAT_MONO8; }
3943	if (strcmp("AL_FORMAT_MONO16", (const char *)ename) == 0) { return AL_FORMAT_MONO16; }
3944	if (strcmp("AL_FORMAT_STEREO8", (const char *)ename) == 0) { return AL_FORMAT_STEREO8; }
3945	if (strcmp("AL_FORMAT_STEREO16", (const char *)ename) == 0) { return AL_FORMAT_STEREO16; }
3946	if (strcmp("AL_FREQUENCY", (const char *)ename) == 0) { return AL_FREQUENCY; }
3947	if (strcmp("AL_SIZE", (const char *)ename) == 0) { return AL_SIZE; }
3948	if (strcmp("AL_UNUSED", (const char *)ename) == 0) { return AL_UNUSED; }
3949	if (strcmp("AL_PENDING", (const char *)ename) == 0) { return AL_PENDING; }
3950	if (strcmp("AL_PROCESSED", (const char *)ename) == 0) { return AL_PROCESSED; }
3951	if (strcmp("AL_NO_ERROR", (const char *)ename) == 0) { return AL_NO_ERROR; }
3952	if (strcmp("AL_INVALID_NAME", (const char *)ename) == 0) { return AL_INVALID_NAME; }
3953	if (strcmp("AL_INVALID_ENUM", (const char *)ename) == 0) { return AL_INVALID_ENUM; }
3954	if (strcmp("AL_INVALID_VALUE", (const char *)ename) == 0) { return AL_INVALID_VALUE; }
3955	if (strcmp("AL_INVALID_OPERATION", (const char *)ename) == 0) { return AL_INVALID_OPERATION; }
3956	if (strcmp("AL_OUT_OF_MEMORY", (const char *)ename) == 0) { return AL_OUT_OF_MEMORY; }
3957	if (strcmp("AL_VENDOR", (const char *)ename) == 0) { return AL_VENDOR; }
3958	if (strcmp("AL_VERSION", (const char *)ename) == 0) { return AL_VERSION; }
3959	if (strcmp("AL_RENDERER", (const char *)ename) == 0) { return AL_RENDERER; }
3960	if (strcmp("AL_EXTENSIONS", (const char *)ename) == 0) { return AL_EXTENSIONS; }
3961	if (strcmp("AL_DOPPLER_FACTOR", (const char *)ename) == 0) { return AL_DOPPLER_FACTOR; }
3962	if (strcmp("AL_DOPPLER_VELOCITY", (const char *)ename) == 0) { return AL_DOPPLER_VELOCITY; }
3963	if (strcmp("AL_DISTANCE_MODEL", (const char *)ename) == 0) { return AL_DISTANCE_MODEL; }
3964	if (strcmp("AL_INVERSE_DISTANCE", (const char *)ename) == 0) { return AL_INVERSE_DISTANCE; }
3965	if (strcmp("AL_INVERSE_DISTANCE_CLAMPED", (const char *)ename) == 0) { return AL_INVERSE_DISTANCE_CLAMPED; }
3966	if (strcmp("AL_LINEAR_DISTANCE", (const char *)ename) == 0) { return AL_LINEAR_DISTANCE; }
3967	if (strcmp("AL_LINEAR_DISTANCE_CLAMPED", (const char *)ename) == 0) { return AL_LINEAR_DISTANCE_CLAMPED; }
3968	if (strcmp("AL_EXPONENT_DISTANCE", (const char *)ename) == 0) { return AL_EXPONENT_DISTANCE; }
3969	if (strcmp("AL_EXPONENT_DISTANCE_CLAMPED", (const char *)ename) == 0) { return AL_EXPONENT_DISTANCE_CLAMPED; }
3970	if (strcmp("AL_SPEED_OF_SOUND", (const char *)ename) == 0) { return AL_SPEED_OF_SOUND; }
3971	if (strcmp("AL_SOURCE_TYPE", (const char *)ename) == 0) { return AL_SOURCE_TYPE; }
3972	// ALC
3973	if (strcmp("ALC_INVALID", (const char *)ename) == 0) { return ALC_INVALID; }
3974	if (strcmp("ALC_FALSE", (const char *)ename) == 0) { return ALC_FALSE; }
3975	if (strcmp("ALC_TRUE", (const char *)ename) == 0) { return ALC_TRUE; }
3976	if (strcmp("ALC_MAJOR_VERSION", (const char *)ename) == 0) { return ALC_MAJOR_VERSION; }
3977	if (strcmp("ALC_MINOR_VERSION", (const char *)ename) == 0) { return ALC_MINOR_VERSION; }
3978	if (strcmp("ALC_ATTRIBUTES_SIZE", (const char *)ename) == 0) { return ALC_ATTRIBUTES_SIZE; }
3979	if (strcmp("ALC_ALL_ATTRIBUTES", (const char *)ename) == 0) { return ALC_ALL_ATTRIBUTES; }
3980	if (strcmp("ALC_DEFAULT_DEVICE_SPECIFIER", (const char *)ename) == 0) { return ALC_DEFAULT_DEVICE_SPECIFIER; }
3981	if (strcmp("ALC_DEVICE_SPECIFIER", (const char *)ename) == 0) { return ALC_DEVICE_SPECIFIER; }
3982	if (strcmp("ALC_EXTENSIONS", (const char *)ename) == 0) { return ALC_EXTENSIONS; }
3983	if (strcmp("ALC_FREQUENCY", (const char *)ename) == 0) { return ALC_FREQUENCY; }
3984	if (strcmp("ALC_REFRESH", (const char *)ename) == 0) { return ALC_REFRESH; }
3985	if (strcmp("ALC_SYNC", (const char *)ename) == 0) { return ALC_SYNC; }
3986	if (strcmp("ALC_NO_ERROR", (const char *)ename) == 0) { return ALC_NO_ERROR; }
3987	if (strcmp("ALC_INVALID_DEVICE", (const char *)ename) == 0) { return ALC_INVALID_DEVICE; }
3988	if (strcmp("ALC_INVALID_CONTEXT", (const char *)ename) == 0) { return ALC_INVALID_CONTEXT; }
3989	if (strcmp("ALC_INVALID_ENUM", (const char *)ename) == 0) { return ALC_INVALID_ENUM; }
3990	if (strcmp("ALC_INVALID_VALUE", (const char *)ename) == 0) { return ALC_INVALID_VALUE; }
3991	if (strcmp("ALC_OUT_OF_MEMORY", (const char *)ename) == 0) { return ALC_OUT_OF_MEMORY; }
3992	if (strcmp("ALC_MONO_SOURCES", (const char *)ename) == 0) { return ALC_MONO_SOURCES; }
3993	if (strcmp("ALC_STEREO_SOURCES", (const char *)ename) == 0) { return ALC_STEREO_SOURCES; }
3994	// AL_EXT_OFFSET
3995	if (strcmp("AL_SEC_OFFSET", (const char *)ename) == 0) { return AL_SEC_OFFSET; }
3996	if (strcmp("AL_SAMPLE_OFFSET", (const char *)ename) == 0) { return AL_SAMPLE_OFFSET; }
3997	if (strcmp("AL_BYTE_OFFSET", (const char *)ename) == 0) { return AL_BYTE_OFFSET; }
3998	// ALC_EXT_capture
3999	if (strcmp("ALC_CAPTURE_DEVICE_SPECIFIER", (const char *)ename) == 0) { return ALC_CAPTURE_DEVICE_SPECIFIER; }
4000	if (strcmp("ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", (const char *)ename) == 0) { return ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER; }
4001	if (strcmp("ALC_CAPTURE_SAMPLES", (const char *)ename) == 0) { return ALC_CAPTURE_SAMPLES; }
4002	// ALC_EXT_float32
4003	if (strcmp("AL_FORMAT_MONO_FLOAT32", (const char *)ename) == 0) { return AL_FORMAT_MONO_FLOAT32; }
4004	if (strcmp("AL_FORMAT_STEREO_FLOAT32", (const char *)ename) == 0) { return AL_FORMAT_STEREO_FLOAT32; }
4005	// ALC_EXT_MAC_OSX
4006	// 1.0 implementation names (remains for backward compatibility)
4007	if (strcmp("ALC_SPATIAL_RENDERING_QUALITY", (const char *)ename) == 0) { return ALC_SPATIAL_RENDERING_QUALITY; }
4008	if (strcmp("ALC_MIXER_OUTPUT_RATE", (const char *)ename) == 0) { return ALC_MIXER_OUTPUT_RATE; }
4009	if (strcmp("ALC_MIXER_MAXIMUM_BUSSES", (const char *)ename) == 0) { return ALC_MIXER_MAXIMUM_BUSSES; }
4010	if (strcmp("ALC_RENDER_CHANNEL_COUNT", (const char *)ename) == 0) { return ALC_RENDER_CHANNEL_COUNT; }
4011
4012	if (strcmp("ALC_CONVERT_DATA_UPON_LOADING", (const char *)ename) == 0) { return ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING; }
4013	if (strcmp("ALC_SPATIAL_RENDERING_QUALITY_HIGH", (const char *)ename) == 0) { return ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_HIGH; }
4014	if (strcmp("ALC_SPATIAL_RENDERING_QUALITY_LOW", (const char *)ename) == 0) { return ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_LOW; }
4015	if (strcmp("ALC_RENDER_CHANNEL_COUNT_STEREO", (const char *)ename) == 0) { return ALC_MAC_OSX_RENDER_CHANNEL_COUNT_STEREO; }
4016	if (strcmp("ALC_RENDER_CHANNEL_COUNT_MULTICHANNEL", (const char *)ename) == 0) { return ALC_MAC_OSX_RENDER_CHANNEL_COUNT_MULTICHANNEL; }
4017	// 1.1 implementation names
4018	if (strcmp("ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING", (const char *)ename) == 0) { return ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING; }
4019	if (strcmp("ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_HIGH", (const char *)ename) == 0) { return ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_HIGH; }
4020	if (strcmp("ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_LOW", (const char *)ename) == 0) { return ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_LOW; }
4021	if (strcmp("ALC_MAC_OSX_RENDER_CHANNEL_COUNT_STEREO", (const char *)ename) == 0) { return ALC_MAC_OSX_RENDER_CHANNEL_COUNT_STEREO; }
4022	if (strcmp("ALC_MAC_OSX_RENDER_CHANNEL_COUNT_MULTICHANNEL", (const char *)ename) == 0) { return ALC_MAC_OSX_RENDER_CHANNEL_COUNT_MULTICHANNEL; }
4023
4024	if (strcmp("ALC_ASA_REVERB_ON", (const char *)ename) == 0) { return ALC_ASA_REVERB_ON; }
4025	if (strcmp("ALC_ASA_REVERB_EQ_GAIN", (const char *)ename) == 0) { return ALC_ASA_REVERB_EQ_GAIN; }
4026	if (strcmp("ALC_ASA_REVERB_EQ_BANDWITH", (const char *)ename) == 0) { return ALC_ASA_REVERB_EQ_BANDWITH; }
4027	if (strcmp("ALC_ASA_REVERB_EQ_FREQ", (const char *)ename) == 0) { return ALC_ASA_REVERB_EQ_FREQ; }
4028	if (strcmp("ALC_ASA_REVERB_PRESET", (const char *)ename) == 0) { return ALC_ASA_REVERB_PRESET; }
4029	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE; }
4030	if (strcmp("ALC_ASA_REVERB_SEND_LEVEL", (const char *)ename) == 0) { return ALC_ASA_REVERB_SEND_LEVEL; }
4031	if (strcmp("ALC_ASA_REVERB_GLOBAL_LEVEL", (const char *)ename) == 0) { return ALC_ASA_REVERB_GLOBAL_LEVEL; }
4032	if (strcmp("ALC_ASA_REVERB_QUALITY", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY; }
4033	if (strcmp("ALC_ASA_OCCLUSION", (const char *)ename) == 0) { return ALC_ASA_OCCLUSION; }
4034	if (strcmp("ALC_ASA_OBSTRUCTION", (const char *)ename) == 0) { return ALC_ASA_OBSTRUCTION; }
4035
4036	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_SmallRoom", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_SmallRoom; }
4037	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_MediumRoom", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_MediumRoom; }
4038	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_LargeRoom", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_LargeRoom; }
4039	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_MediumHall", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_MediumHall; }
4040	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_LargeHall", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_LargeHall; }
4041	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_Plate", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_Plate; }
4042	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_MediumChamber", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_MediumChamber; }
4043	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_LargeChamber", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_LargeChamber; }
4044	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_Cathedral", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_Cathedral; }
4045	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_LargeRoom2", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_LargeRoom2; }
4046	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_MediumHall2", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_MediumHall2; }
4047	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_MediumHall3", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_MediumHall3; }
4048	if (strcmp("ALC_ASA_REVERB_ROOM_TYPE_LargeHall2", (const char *)ename) == 0) { return ALC_ASA_REVERB_ROOM_TYPE_LargeHall2; }
4049
4050	if (strcmp("ALC_ASA_REVERB_QUALITY_Max", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY_Max; }
4051	if (strcmp("ALC_ASA_REVERB_QUALITY_High", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY_High; }
4052	if (strcmp("ALC_ASA_REVERB_QUALITY_Medium", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY_Medium; }
4053	if (strcmp("ALC_ASA_REVERB_QUALITY_Low", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY_Low; }
4054	if (strcmp("ALC_ASA_REVERB_QUALITY_Min", (const char *)ename) == 0) { return ALC_ASA_REVERB_QUALITY_Min; }
4055
4056	if (strcmp("ALC_ASA_ROGER_BEEP_ENABLE", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_ENABLE; }
4057	if (strcmp("ALC_ASA_ROGER_BEEP_ON", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_ON; }
4058	if (strcmp("ALC_ASA_ROGER_BEEP_GAIN", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_GAIN; }
4059	if (strcmp("ALC_ASA_ROGER_BEEP_SENSITIVITY", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_SENSITIVITY; }
4060	if (strcmp("ALC_ASA_ROGER_BEEP_TYPE", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_TYPE; }
4061	if (strcmp("ALC_ASA_ROGER_BEEP_PRESET", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_PRESET; }
4062
4063	if (strcmp("ALC_ASA_ROGER_BEEP_TYPE_quindartone", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_TYPE_quindartone; }
4064	if (strcmp("ALC_ASA_ROGER_BEEP_TYPE_whitenoise", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_TYPE_whitenoise; }
4065	if (strcmp("ALC_ASA_ROGER_BEEP_TYPE_walkietalkie", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_TYPE_walkietalkie; }
4066	if (strcmp("ALC_ASA_ROGER_BEEP_SENSITIVITY_Light", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_SENSITIVITY_Light; }
4067	if (strcmp("ALC_ASA_ROGER_BEEP_SENSITIVITY_Medium", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_SENSITIVITY_Medium; }
4068	if (strcmp("ALC_ASA_ROGER_BEEP_SENSITIVITY_Heavy", (const char *)ename) == 0) { return ALC_ASA_ROGER_BEEP_SENSITIVITY_Heavy; }
4069
4070	if (strcmp("ALC_ASA_DISTORTION_ENABLE", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_ENABLE; }
4071	if (strcmp("ALC_ASA_DISTORTION_ON", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_ON; }
4072	if (strcmp("ALC_ASA_DISTORTION_MIX", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_MIX; }
4073	if (strcmp("ALC_ASA_DISTORTION_TYPE", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE; }
4074	if (strcmp("ALC_ASA_DISTORTION_PRESET", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_PRESET; }
4075
4076	if (strcmp("ALC_ASA_DISTORTION_TYPE_BitBrush", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_BitBrush; }
4077	if (strcmp("ALC_ASA_DISTORTION_TYPE_BufferBeats", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_BufferBeats; }
4078	if (strcmp("ALC_ASA_DISTORTION_TYPE_LoFi", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_LoFi; }
4079	if (strcmp("ALC_ASA_DISTORTION_TYPE_BitBrush", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_BitBrush; }
4080	if (strcmp("ALC_ASA_DISTORTION_TYPE_BrokenSpeaker", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_BrokenSpeaker; }
4081	if (strcmp("ALC_ASA_DISTORTION_TYPE_Cellphone", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Cellphone; }
4082	if (strcmp("ALC_ASA_DISTORTION_TYPE_Decimated1", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Decimated1; }
4083	if (strcmp("ALC_ASA_DISTORTION_TYPE_Decimated2", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Decimated2; }
4084	if (strcmp("ALC_ASA_DISTORTION_TYPE_Decimated3", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Decimated3; }
4085	if (strcmp("ALC_ASA_DISTORTION_TYPE_Decimated4", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Decimated4; }
4086	if (strcmp("ALC_ASA_DISTORTION_TYPE_DistortedFunk", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_DistortedFunk; }
4087	if (strcmp("ALC_ASA_DISTORTION_TYPE_DistortionCubed", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_DistortionCubed; }
4088	if (strcmp("ALC_ASA_DISTORTION_TYPE_DistortionSquared", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_DistortionSquared; }
4089	if (strcmp("ALC_ASA_DISTORTION_TYPE_Echo1", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Echo1; }
4090	if (strcmp("ALC_ASA_DISTORTION_TYPE_Echo2", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Echo2; }
4091	if (strcmp("ALC_ASA_DISTORTION_TYPE_EchoTight1", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_EchoTight1; }
4092	if (strcmp("ALC_ASA_DISTORTION_TYPE_EchoTight2", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_EchoTight2; }
4093	if (strcmp("ALC_ASA_DISTORTION_TYPE_EverythingBroken", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_EverythingBroken; }
4094	if (strcmp("ALC_ASA_DISTORTION_TYPE_AlienChatter", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_AlienChatter; }
4095	if (strcmp("ALC_ASA_DISTORTION_TYPE_CosmicInteference", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_CosmicInteference; }
4096	if (strcmp("ALC_ASA_DISTORTION_TYPE_GoldenPi", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_GoldenPi; }
4097	if (strcmp("ALC_ASA_DISTORTION_TYPE_RadioTower", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_RadioTower; }
4098	if (strcmp("ALC_ASA_DISTORTION_TYPE_Waves", (const char *)ename) == 0) { return ALC_ASA_DISTORTION_TYPE_Waves; }
4099
4100	return -1;
4101}
4102// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4103AL_API ALboolean AL_APIENTRY alGetBoolean (ALenum pname)
4104{
4105#if LOG_API_USAGE
4106	DebugMessage("***** alGetBoolean");
4107#endif
4108	return AL_FALSE;
4109}
4110
4111// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4112AL_API ALvoid AL_APIENTRY alGetBooleanv (ALenum pname, ALboolean *data)
4113{
4114#if LOG_API_USAGE
4115	DebugMessage("***** alGetBooleanv");
4116#endif
4117}
4118
4119// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4120AL_API ALfloat AL_APIENTRY alGetFloat (ALenum pname)
4121{
4122	Float32			returnValue = 0.0f;
4123
4124#if LOG_API_USAGE
4125	DebugMessageN1("alGetFloat ---> attribute = %s", GetALAttributeString(pname));
4126#endif
4127
4128	OALContext* oalContext = NULL;
4129
4130	try {
4131        oalContext = ProtectContextObject(gCurrentContext);
4132        switch (pname)
4133        {
4134            case AL_SPEED_OF_SOUND:
4135                returnValue = oalContext->GetSpeedOfSound();
4136                break;
4137            case AL_DOPPLER_FACTOR:
4138                returnValue = oalContext->GetDopplerFactor();
4139                break;
4140            case AL_DOPPLER_VELOCITY:
4141                returnValue = oalContext->GetDopplerVelocity();
4142                break;
4143            default:
4144                break;
4145        }
4146	}
4147	catch (OSStatus		result) {
4148 		DebugMessageN1("ERROR: alGetFloat FAILED = %s\n", alGetString(result));
4149        alSetError(result);
4150    }
4151	catch (...) {
4152 		DebugMessage("ERROR: alGetFloat FAILED");
4153        alSetError(AL_INVALID_OPERATION);   // by default
4154	}
4155
4156	ReleaseContextObject(oalContext);
4157
4158	return (returnValue);
4159}
4160
4161// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4162AL_API ALvoid AL_APIENTRY alGetFloatv (ALenum pname, ALfloat *data)
4163{
4164#if LOG_API_USAGE
4165	DebugMessageN1("alGetFloatv ---> attribute = %s", GetALAttributeString(pname));
4166#endif
4167
4168	OALContext* oalContext = NULL;
4169
4170	try {
4171        oalContext = ProtectContextObject(gCurrentContext);
4172        switch(pname)
4173        {
4174            case AL_SPEED_OF_SOUND:
4175                *data = oalContext->GetSpeedOfSound();
4176                break;
4177            case AL_DOPPLER_FACTOR:
4178                *data = oalContext->GetDopplerFactor();
4179                break;
4180            case AL_DOPPLER_VELOCITY:
4181                *data = oalContext->GetDopplerVelocity();
4182                break;
4183            default:
4184                alSetError(AL_INVALID_ENUM);
4185                break;
4186        }
4187	}
4188	catch (OSStatus		result) {
4189 		DebugMessageN1("ERROR: alGetFloatv FAILED = %s\n", alGetString(result));
4190        alSetError(result);
4191    }
4192	catch (...) {
4193 		DebugMessage("ERROR: alGetFloatv FAILED");
4194        alSetError(AL_INVALID_OPERATION);   // by default
4195	}
4196
4197	ReleaseContextObject(oalContext);
4198}
4199
4200// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4201AL_API ALdouble AL_APIENTRY alGetDouble (ALenum pname)
4202{
4203#if LOG_API_USAGE
4204	DebugMessageN1("alGetDouble ---> attribute = %s", GetALCAttributeString(pname));
4205#endif
4206
4207    double      returnValue = 0.0;
4208
4209	try {
4210		switch (pname)
4211		{
4212			case ALC_MIXER_OUTPUT_RATE:
4213				returnValue = GetMixerOutputRate();
4214				break;
4215
4216			default:
4217				alSetError(AL_INVALID_VALUE);
4218				break;
4219		}
4220	}
4221	catch (OSStatus		result) {
4222 		DebugMessageN1("ERROR: alGetDouble FAILED = %s\n", alGetString(result));
4223        alSetError(result);
4224    }
4225	catch (...) {
4226 		DebugMessage("ERROR: alGetDouble FAILED");
4227        alSetError(AL_INVALID_OPERATION);   // by default
4228	}
4229
4230	return returnValue;
4231}
4232
4233// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4234AL_API ALvoid AL_APIENTRY alGetDoublev (ALenum pname, ALdouble *data)
4235{
4236#if LOG_API_USAGE
4237	DebugMessageN1("alGetDoublev ---> attribute = %s", GetALCAttributeString(pname));
4238#endif
4239
4240	try {
4241		switch (pname)
4242		{
4243			case ALC_MIXER_OUTPUT_RATE:
4244				*data = GetMixerOutputRate();
4245				break;
4246
4247			default:
4248				alSetError(AL_INVALID_VALUE);
4249				break;
4250		}
4251	}
4252	catch (OSStatus		result) {
4253 		DebugMessageN1("ERROR: alGetDoublev FAILED = %s\n", alGetString(result));
4254        alSetError(result);
4255    }
4256	catch (...) {
4257 		DebugMessage("ERROR: alGetDoublev FAILED");
4258        alSetError(AL_INVALID_OPERATION);   // by default
4259	}
4260}
4261
4262// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4263AL_API ALint AL_APIENTRY alGetInteger (ALenum pname)
4264{
4265#if LOG_API_USAGE
4266	DebugMessageN1("alGetInteger ---> attribute = 0x%X", pname);
4267#endif
4268
4269	UInt32			returnValue	= 0;
4270	OALContext		*oalContext = NULL;
4271	OALDevice		*oalDevice = NULL;
4272
4273	try {
4274		switch (pname)
4275		{
4276            case AL_DISTANCE_MODEL:
4277				oalContext = ProtectContextObject(gCurrentContext);
4278				returnValue = oalContext->GetDistanceModel();
4279                break;
4280
4281			case ALC_SPATIAL_RENDERING_QUALITY:
4282				oalContext = ProtectContextObject(gCurrentContext);
4283				returnValue = oalContext->GetRenderQuality();
4284				break;
4285
4286			case ALC_RENDER_CHANNEL_COUNT:
4287			{
4288				oalDevice = ProtectDeviceObject (gCurrentDevice);
4289				returnValue = oalDevice->GetRenderChannelSetting();
4290			}
4291				break;
4292
4293            case ALC_MIXER_MAXIMUM_BUSSES:
4294				oalContext = ProtectContextObject(gCurrentContext);
4295				if (oalContext)
4296					returnValue = oalContext->GetBusCount();
4297				else
4298					returnValue = gMaximumMixerBusCount;
4299                break;
4300
4301			default:
4302				alSetError(AL_INVALID_VALUE);
4303				break;
4304		}
4305	}
4306	catch (OSStatus		result) {
4307 		DebugMessageN1("ERROR: alGetInteger FAILED = %s\n", alGetString(result));
4308    }
4309	catch (...) {
4310 		DebugMessage("ERROR: alGetInteger FAILED");
4311	}
4312
4313	ReleaseContextObject(oalContext);
4314	ReleaseDeviceObject(oalDevice);
4315
4316	return (returnValue);
4317}
4318
4319// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4320AL_API ALvoid AL_APIENTRY alGetIntegerv (ALenum pname, ALint *data)
4321{
4322#if LOG_API_USAGE
4323	DebugMessageN1("alGetIntegerv ---> attribute = 0x%X", pname);
4324#endif
4325
4326	OALContext* oalContext	= NULL;
4327	OALDevice*	oalDevice	= NULL;
4328
4329	try {
4330		oalContext = NULL;
4331        switch (pname)
4332        {
4333            case AL_DISTANCE_MODEL:
4334				oalContext = ProtectContextObject(gCurrentContext);
4335				*data = oalContext->GetDistanceModel();
4336                break;
4337
4338			case ALC_SPATIAL_RENDERING_QUALITY:
4339				oalContext = ProtectContextObject(gCurrentContext);
4340				*data = oalContext->GetRenderQuality();
4341				break;
4342
4343			case ALC_RENDER_CHANNEL_COUNT:
4344			{
4345				oalDevice = ProtectDeviceObject (gCurrentDevice);
4346				*data = oalDevice->GetRenderChannelSetting();
4347			}
4348				break;
4349
4350            case ALC_MIXER_MAXIMUM_BUSSES:
4351				oalContext = ProtectContextObject(gCurrentContext);
4352				if (oalContext)
4353					*data = oalContext->GetBusCount();
4354				else
4355					*data = gMaximumMixerBusCount;
4356                break;
4357
4358            default:
4359                alSetError(AL_INVALID_ENUM);
4360                break;
4361        }
4362	}
4363	catch (OSStatus     result) {
4364		DebugMessageN1("ERROR: alGetIntegerv FAILED = %s\n", alGetString(result));
4365        alSetError(result);
4366    }
4367    catch (...) {
4368		DebugMessage("ERROR: alGetIntegerv FAILED");
4369        alSetError(AL_INVALID_OPERATION);
4370	}
4371
4372	ReleaseContextObject(oalContext);
4373	ReleaseDeviceObject(oalDevice);
4374}
4375
4376// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4377AL_API void*	AL_APIENTRY alGetProcAddress( const ALchar* fname )
4378{
4379#if LOG_API_USAGE
4380	DebugMessageN1("alGetProcAddress function name = %s", fname);
4381#endif
4382
4383	if (fname == NULL)
4384		SetDeviceError(gCurrentDevice, ALC_INVALID_VALUE);
4385	else
4386	{
4387		// core APIs
4388		if (strcmp("alcOpenDevice", (const char *)fname) == 0) { return (void*) alcOpenDevice; }
4389		if (strcmp("alcCloseDevice", (const char *)fname) == 0) { return (void*) alcCloseDevice; }
4390		if (strcmp("alcGetError", (const char *)fname) == 0) { return (void*) alcGetError; }
4391		if (strcmp("alcCreateContext", (const char *)fname) == 0) { return (void*) alcCreateContext; }
4392		if (strcmp("alcMakeContextCurrent", (const char *)fname) == 0) { return (void*) alcMakeContextCurrent; }
4393		if (strcmp("alcProcessContext", (const char *)fname) == 0) { return (void*) alcProcessContext; }
4394		if (strcmp("alcGetCurrentContext", (const char *)fname) == 0) { return (void*) alcGetCurrentContext; }
4395		if (strcmp("alcGetContextsDevice", (const char *)fname) == 0) { return (void*) alcGetContextsDevice; }
4396		if (strcmp("alcSuspendContext", (const char *)fname) == 0) { return (void*) alcSuspendContext; }
4397		if (strcmp("alcDestroyContext", (const char *)fname) == 0) { return (void*)alcDestroyContext; }
4398		if (strcmp("alcGetString", (const char *)fname) == 0) { return (void*) alcGetString; }
4399		if (strcmp("alcIsExtensionPresent", (const char *)fname) == 0) { return (void*) alcIsExtensionPresent; }
4400		if (strcmp("alcGetProcAddress", (const char *)fname) == 0) { return (void*) alcGetProcAddress; }
4401		if (strcmp("alcGetEnumValue", (const char *)fname) == 0) { return (void*) alcGetEnumValue; }
4402		if (strcmp("alcGetInteger", (const char *)fname) == 0) { return (void*) alcGetInteger; }
4403		if (strcmp("alcGetIntegerv", (const char *)fname) == 0) { return (void*) alcGetIntegerv; }
4404		if (strcmp("alGetError", (const char *)fname) == 0) { return (void*) alGetError; }
4405		if (strcmp("alGenBuffers", (const char *)fname) == 0) { return (void*) alGenBuffers; }
4406		if (strcmp("alDeleteBuffers", (const char *)fname) == 0) { return (void*) alDeleteBuffers; }
4407		if (strcmp("alIsBuffer", (const char *)fname) == 0) { return (void*) alIsBuffer; }
4408		if (strcmp("alBufferData", (const char *)fname) == 0) { return (void*) alBufferData; }
4409		if (strcmp("alBufferf", (const char *)fname) == 0) { return (void*) alBufferf; }
4410		if (strcmp("alBuffer3f", (const char *)fname) == 0) { return (void*) alBuffer3f; }
4411		if (strcmp("alBufferfv", (const char *)fname) == 0) { return (void*) alBufferfv; }
4412		if (strcmp("alBufferi", (const char *)fname) == 0) { return (void*) alBufferi; }
4413		if (strcmp("alBuffer3i", (const char *)fname) == 0) { return (void*) alBuffer3i; }
4414		if (strcmp("alBufferiv", (const char *)fname) == 0) { return (void*) alBufferiv; }
4415		if (strcmp("alGetBufferf", (const char *)fname) == 0) { return (void*) alGetBufferf; }
4416		if (strcmp("alGetBuffer3f", (const char *)fname) == 0) { return (void*) alGetBuffer3f; }
4417		if (strcmp("alGetBufferfv", (const char *)fname) == 0) { return (void*) alGetBufferfv; }
4418		if (strcmp("alGetBufferi", (const char *)fname) == 0) { return (void*) alGetBufferi; }
4419		if (strcmp("alGetBuffer3i", (const char *)fname) == 0) { return (void*) alGetBuffer3i; }
4420		if (strcmp("alGetBufferiv", (const char *)fname) == 0) { return (void*) alGetBufferiv; }
4421		if (strcmp("alGenSources", (const char *)fname) == 0) { return (void*) alGenSources; }
4422		if (strcmp("alDeleteSources", (const char *)fname) == 0) { return (void*) alDeleteSources; }
4423		if (strcmp("alIsSource", (const char *)fname) == 0) { return (void*) alIsSource; }
4424		if (strcmp("alSourcef", (const char *)fname) == 0) { return (void*) alSourcef; }
4425		if (strcmp("alSourcefv", (const char *)fname) == 0) { return (void*) alSourcefv; }
4426		if (strcmp("alSource3f", (const char *)fname) == 0) { return (void*) alSource3f; }
4427		if (strcmp("alSourcei", (const char *)fname) == 0) { return (void*) alSourcei; }
4428		if (strcmp("alSourceiv", (const char *)fname) == 0) { return (void*) alSourceiv; }
4429		if (strcmp("alSource3i", (const char *)fname) == 0) { return (void*) alSource3i; }
4430		if (strcmp("alGetSourcef", (const char *)fname) == 0) { return (void*) alGetSourcef; }
4431		if (strcmp("alGetSourcefv", (const char *)fname) == 0) { return (void*) alGetSourcefv; }
4432		if (strcmp("alGetSource3f", (const char *)fname) == 0) { return (void*) alGetSource3f; }
4433		if (strcmp("alGetSourcei", (const char *)fname) == 0) { return (void*) alGetSourcei; }
4434		if (strcmp("alGetSourceiv", (const char *)fname) == 0) { return (void*) alGetSourceiv; }
4435		if (strcmp("alGetSource3i", (const char *)fname) == 0) { return (void*) alGetSource3i; }
4436		if (strcmp("alSourcePlay", (const char *)fname) == 0) { return (void*) alSourcePlay; }
4437		if (strcmp("alSourcePause", (const char *)fname) == 0) { return (void*) alSourcePause; }
4438		if (strcmp("alSourceStop", (const char *)fname) == 0) { return (void*) alSourceStop; }
4439		if (strcmp("alSourceRewind", (const char *)fname) == 0) { return (void*) alSourceRewind; }
4440		if (strcmp("alSourcePlayv", (const char *)fname) == 0) { return (void*) alSourcePlayv; }
4441		if (strcmp("alSourcePausev", (const char *)fname) == 0) { return (void*) alSourcePausev; }
4442		if (strcmp("alSourceStopv", (const char *)fname) == 0) { return (void*) alSourceStopv; }
4443		if (strcmp("alSourceRewindv", (const char *)fname) == 0) { return (void*) alSourceRewindv; }
4444		if (strcmp("alSourceQueueBuffers", (const char *)fname) == 0) { return (void*) alSourceQueueBuffers; }
4445		if (strcmp("alSourceUnqueueBuffers", (const char *)fname) == 0) { return (void*) alSourceUnqueueBuffers; }
4446		if (strcmp("alListenerf", (const char *)fname) == 0) { return (void*) alListenerf; }
4447		if (strcmp("alListenerfv", (const char *)fname) == 0) { return (void*) alListenerfv; }
4448		if (strcmp("alListener3f", (const char *)fname) == 0) { return (void*) alListener3f; }
4449		if (strcmp("alListeneri", (const char *)fname) == 0) { return (void*) alListeneri; }
4450		if (strcmp("alListeneriv", (const char *)fname) == 0) { return (void*) alListeneriv; }
4451		if (strcmp("alListener3i", (const char *)fname) == 0) { return (void*) alListener3i; }
4452		if (strcmp("alGetListenerf", (const char *)fname) == 0) { return (void*) alGetListenerf; }
4453		if (strcmp("alGetListenerfv", (const char *)fname) == 0) { return (void*) alGetListenerfv; }
4454		if (strcmp("alGetListener3f", (const char *)fname) == 0) { return (void*) alGetListener3f; }
4455		if (strcmp("alGetListeneri", (const char *)fname) == 0) { return (void*) alGetListeneri; }
4456		if (strcmp("alGetListeneriv", (const char *)fname) == 0) { return (void*) alGetListeneriv; }
4457		if (strcmp("alGetListener3i", (const char *)fname) == 0) { return (void*) alGetListener3i; }
4458		if (strcmp("alDistanceModel", (const char *)fname) == 0) { return (void*) alDistanceModel; }
4459		if (strcmp("alDopplerFactor", (const char *)fname) == 0) { return (void*) alDopplerFactor; }
4460		if (strcmp("alDopplerVelocity", (const char *)fname) == 0) { return (void*) alDopplerVelocity; }
4461		if (strcmp("alSpeedOfSound", (const char *)fname) == 0) { return (void*) alSpeedOfSound; }
4462		if (strcmp("alGetString", (const char *)fname) == 0) { return (void*) alGetString; }
4463		if (strcmp("alGetEnumValue", (const char *)fname) == 0) { return (void*) alGetEnumValue; }
4464		if (strcmp("alGetBoolean", (const char *)fname) == 0) { return (void*) alGetBoolean; }
4465		if (strcmp("alGetBooleanv", (const char *)fname) == 0) { return (void*) alGetBooleanv; }
4466		if (strcmp("alGetFloat", (const char *)fname) == 0) { return (void*) alGetFloat; }
4467		if (strcmp("alGetFloatv", (const char *)fname) == 0) { return (void*) alGetFloatv; }
4468		if (strcmp("alGetDouble", (const char *)fname) == 0) { return (void*) alGetDouble; }
4469		if (strcmp("alGetDoublev", (const char *)fname) == 0) { return (void*) alGetDoublev; }
4470		if (strcmp("alGetInteger", (const char *)fname) == 0) { return (void*) alGetInteger; }
4471		if (strcmp("alGetIntegerv", (const char *)fname) == 0) { return (void*) alGetIntegerv; }
4472		if (strcmp("alGetProcAddress", (const char *)fname) == 0) { return (void*) alGetProcAddress; }
4473		if (strcmp("alIsExtensionPresent", (const char *)fname) == 0) { return (void*) alIsExtensionPresent; }
4474		if (strcmp("alDisable", (const char *)fname) == 0) { return (void*) alDisable; }
4475		if (strcmp("alEnable", (const char *)fname) == 0) { return (void*) alEnable; }
4476		if (strcmp("alIsEnabled", (const char *)fname) == 0) { return (void*) alIsEnabled; }
4477
4478		// Capture Extension
4479		if (strcmp("alcCaptureOpenDevice", (const char *)fname) == 0) { return (void*) alcCaptureOpenDevice; }
4480		if (strcmp("alcCaptureCloseDevice", (const char *)fname) == 0) { return (void*) alcCaptureCloseDevice; }
4481		if (strcmp("alcCaptureStart", (const char *)fname) == 0) { return (void*) alcCaptureStart; }
4482		if (strcmp("alcCaptureStop", (const char *)fname) == 0) { return (void*) alcCaptureStop; }
4483		if (strcmp("alcCaptureSamples", (const char *)fname) == 0) { return (void*) alcCaptureSamples; }
4484
4485		// OSX Extension
4486		if (strcmp("alcMacOSXRenderingQuality", (const char *)fname) == 0) { return (void*) alcMacOSXRenderingQuality; }
4487		if (strcmp("alMacOSXRenderChannelCount", (const char *)fname) == 0) { return (void*) alMacOSXRenderChannelCount; }
4488		if (strcmp("alcMacOSXMixerMaxiumumBusses", (const char *)fname) == 0) { return (void*) alcMacOSXMixerMaxiumumBusses; }
4489		if (strcmp("alcMacOSXMixerOutputRate", (const char *)fname) == 0) { return (void*) alcMacOSXMixerOutputRate; }
4490		if (strcmp("alcMacOSXGetRenderingQuality", (const char *)fname) == 0) { return (void*) alcMacOSXGetRenderingQuality; }
4491		if (strcmp("alMacOSXGetRenderChannelCount", (const char *)fname) == 0) { return (void*) alMacOSXGetRenderChannelCount; }
4492		if (strcmp("alcMacOSXGetMixerMaxiumumBusses", (const char *)fname) == 0) { return (void*) alcMacOSXGetMixerMaxiumumBusses; }
4493		if (strcmp("alcMacOSXGetMixerOutputRate", (const char *)fname) == 0) { return (void*) alcMacOSXGetMixerOutputRate; }
4494
4495		// Buffer Static Extension
4496		if (strcmp("alBufferDataStatic", (const char *)fname) == 0) { return (void*) alBufferDataStatic; }
4497
4498		// Source Notifications Extension
4499		if (strcmp("alSourceAddNotification", (const char *)fname) == 0) { return (ALenum*) alSourceAddNotification; }
4500		if (strcmp("alSourceRemoveNotification", (const char *)fname) == 0) { return (ALvoid*) alSourceRemoveNotification; }
4501
4502		// ASA Extension
4503		if (strcmp("alcASASetListener", (const char *)fname) == 0) { return (void*) alcASASetListener; }
4504		if (strcmp("alcASAGetListener", (const char *)fname) == 0) { return (void*) alcASAGetListener; }
4505		if (strcmp("alcASASetSource", (const char *)fname) == 0) { return (void*) alcASASetSource; }
4506		if (strcmp("alcASAGetSource", (const char *)fname) == 0) { return (void*) alcASAGetSource; }
4507
4508	}
4509
4510	return NULL;
4511}
4512
4513// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4514AL_API ALboolean AL_APIENTRY alIsEnvironmentIASIG (ALuint environment)
4515{
4516#if LOG_API_USAGE
4517	DebugMessage("***** alIsEnvironmentIASIG");
4518#endif
4519	return AL_FALSE;
4520}
4521
4522// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4523AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname )
4524{
4525#if LOG_API_USAGE
4526	DebugMessageN1("alIsExtensionPresent function name = %s", extname);
4527#endif
4528
4529	ALboolean	returnValue = AL_FALSE;
4530
4531	if (extname == NULL)
4532		SetDeviceError(gCurrentDevice, ALC_INVALID_VALUE);
4533	else
4534	{
4535        // first compare to see if the strings match
4536        if(strstr(GetALExtensionList(), extname) != NULL)
4537        {
4538            returnValue = AL_TRUE;
4539        }
4540        else
4541        {
4542            //convert the extension base to upper case
4543            ALchar* extbase = GetALExtensionList();
4544            ALchar* extbaseUpper = (ALchar*)calloc(1, (strlen(extbase)+1)*sizeof(ALchar));
4545            if (extbaseUpper)
4546            {
4547                for (unsigned int i=0; i < strlen(extbase); i++)
4548                {
4549                    extbaseUpper[i] = toupper(extbase[i]);
4550                }
4551
4552                ALchar* extnameUpper = (ALchar*)calloc(1, (strlen(extname)+1)*sizeof(ALchar));
4553                if (extnameUpper)
4554                {
4555                    for (unsigned int i=0; i < strlen(extname); i++)
4556                    {
4557                        extnameUpper[i] = toupper(extname[i]);
4558                    }
4559
4560                    //compare the strings after having converted both to upper case
4561                    if (strstr(extbaseUpper, extnameUpper) != NULL) {
4562                        returnValue = AL_TRUE;
4563                    }
4564
4565                    free(extnameUpper);
4566                }
4567
4568                free(extbaseUpper);
4569            }
4570         }
4571	}
4572
4573	return returnValue;    // extension not present in this implementation
4574}
4575
4576// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4577AL_API ALvoid AL_APIENTRY alDisable (ALenum capability)
4578{
4579#if LOG_API_USAGE
4580	DebugMessageN1("alDisable--> capability = 0x%X", capability);
4581#endif
4582
4583	switch (capability)
4584	{
4585		case ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING:
4586			gConvertBufferNow = false;
4587			break;
4588		default:
4589			alSetError(AL_INVALID_VALUE);
4590			break;
4591	}
4592}
4593
4594// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4595AL_API ALvoid AL_APIENTRY alEnable (ALenum capability)
4596{
4597#if LOG_API_USAGE
4598	DebugMessageN1("alEnable--> capability = 0x%X", capability);
4599#endif
4600
4601	switch(capability)
4602	{
4603		case ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING:
4604			gConvertBufferNow = true;
4605			break;
4606		default:
4607			alSetError(AL_INVALID_VALUE);
4608			break;
4609	}
4610}
4611
4612// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4613AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
4614{
4615#if LOG_API_USAGE
4616	DebugMessageN1("alIsEnabled--> capability = 0x%X", capability);
4617#endif
4618	switch(capability)
4619	{
4620		case ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING:
4621			return (gConvertBufferNow);
4622			break;
4623		default:
4624			break;
4625	}
4626	return (false);
4627}
4628
4629// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4630// ALC_EXT_MAC_OSX
4631// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4632#pragma mark ***** OSX Extension *****
4633ALC_API ALvoid alcMacOSXRenderingQuality (ALint value)
4634{
4635#if LOG_API_USAGE
4636	DebugMessageN1("alcOSXRenderingQuality--> value = %ld", (long int) value);
4637#endif
4638	alSetInteger(ALC_SPATIAL_RENDERING_QUALITY, value);
4639}
4640
4641// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4642ALC_API ALvoid alMacOSXRenderChannelCount (ALint value)
4643{
4644#if LOG_API_USAGE
4645	DebugMessageN1("alOSXRenderChannelCount--> value = %ld", (long int) value);
4646#endif
4647	alSetInteger(ALC_RENDER_CHANNEL_COUNT, value);
4648}
4649
4650// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4651ALC_API ALvoid alcMacOSXMixerMaxiumumBusses (ALint value)
4652{
4653#if LOG_API_USAGE
4654	DebugMessageN1("alcOSXMixerMaxiumumBusses--> value = %ld", (long int) value);
4655#endif
4656	alSetInteger(ALC_MIXER_MAXIMUM_BUSSES, value);
4657}
4658
4659// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4660ALC_API ALvoid alcMacOSXMixerOutputRate(ALdouble value)
4661{
4662#if LOG_API_USAGE
4663	DebugMessageN1("alcOSXMixerOutputRate--> value = %.f2", value);
4664#endif
4665	alSetDouble(ALC_MIXER_OUTPUT_RATE, value);
4666}
4667
4668// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4669ALC_API ALint alcMacOSXGetRenderingQuality ()
4670{
4671#if LOG_API_USAGE
4672	DebugMessage("alcOSXGetRenderingQuality-->");
4673#endif
4674	return alGetInteger(ALC_SPATIAL_RENDERING_QUALITY);
4675}
4676
4677// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4678ALC_API ALint alMacOSXGetRenderChannelCount ()
4679{
4680#if LOG_API_USAGE
4681	DebugMessage("alOSXGetRenderChannelCount-->");
4682#endif
4683	return alGetInteger(ALC_RENDER_CHANNEL_COUNT);
4684}
4685
4686// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4687ALC_API ALint alcMacOSXGetMixerMaxiumumBusses ()
4688{
4689#if LOG_API_USAGE
4690	DebugMessage("alcOSXGetMixerMaxiumumBusses-->");
4691#endif
4692	return alGetInteger(ALC_MIXER_MAXIMUM_BUSSES);
4693}
4694
4695// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4696ALC_API ALdouble alcMacOSXGetMixerOutputRate ()
4697{
4698#if LOG_API_USAGE
4699	DebugMessage("alcMacOSXGetMixerOutputRate-->");
4700#endif
4701	return alGetDouble(ALC_MIXER_OUTPUT_RATE);
4702}
4703
4704// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4705AL_API ALvoid	AL_APIENTRY	alBufferDataStatic (ALint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq)
4706{
4707#if LOG_BUFFER_USAGE
4708	DebugMessageN4("alBufferDataStatic-->  buffer %ld : %s : %ld bytes : %ldHz", (long int) bid, GetFormatString(format), (long int) size, (long int) freq);
4709#endif
4710
4711	OALBuffer *oalBuffer = NULL;
4712
4713	try {
4714		oalBuffer = ProtectBufferObject(bid);
4715        if (data==NULL) throw ((OSStatus) AL_INVALID_VALUE);
4716        if (size<=0) throw ((OSStatus) AL_INVALID_VALUE);
4717
4718		oalBuffer->AddAudioDataStatic((char*)data, size, format, freq);
4719    }
4720    catch (OSStatus     result) {
4721		DebugMessageN5("ERROR: alBufferDataStatic FAILED: buffer %ld : %s : %ld bytes : %ldHz error = %s", (long int) bid, GetFormatString(format), (long int) size, (long int) freq,  alGetString(result));
4722        alSetError(result);
4723    }
4724    catch (...) {
4725		DebugMessageN4("ERROR: alBufferDataStatic FAILED: buffer %ld : %s : %ld bytes : %ldHz", (long int) bid, GetFormatString(format), (long int) size, (long int) freq);
4726        alSetError(AL_INVALID_OPERATION);
4727	}
4728
4729	ReleaseBufferObject(oalBuffer);
4730}
4731
4732// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4733// AL_EXT_SOURCE_NOTIFICATIONS
4734// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4735#pragma mark ***** Source Notifications Ext*****
4736
4737AL_API ALenum AL_APIENTRY alSourceAddNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData)
4738{
4739#if LOG_API_USAGE
4740	DebugMessage("alSourceAddNotification-->");
4741#endif
4742
4743	if (notifyProc == NULL)
4744		return AL_INVALID_VALUE;
4745
4746	ALenum		result = AL_NO_ERROR;
4747	OALSource	*oalSource = NULL;
4748
4749	try {
4750
4751		oalSource = ProtectSourceObjectInCurrentContext(sid);
4752		if (oalSource)
4753			result = oalSource->AddNotification(notificationID, notifyProc, userData);
4754		else
4755			result = (OSStatus) AL_INVALID_VALUE;
4756
4757		if (result)
4758		{
4759			DebugMessageN3("ERROR: alSourceAddNotification FAILED: source: %ld : proc: %p : userData: %p", (long int) sid, notifyProc, userData);
4760		}
4761	}
4762	catch (OSStatus      result) {
4763		DebugMessageN1("ERROR: alSourceAddNotification FAILED = %s\n", alGetString(result));
4764	}
4765	catch (...) {
4766		DebugMessage("ERROR: alSourceAddNotification FAILED");
4767		result = AL_INVALID_OPERATION;
4768	}
4769
4770	ReleaseSourceObject(oalSource);
4771
4772	return result;
4773}
4774
4775// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4776AL_API ALvoid AL_APIENTRY alSourceRemoveNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData)
4777{
4778#if LOG_API_USAGE
4779	DebugMessage("alSourceRemoveNotification-->");
4780#endif
4781
4782	if (notifyProc == NULL)
4783		return;
4784
4785	OALSource	*oalSource = NULL;
4786
4787	try {
4788		oalSource = ProtectSourceObjectInCurrentContext(sid);
4789		if (oalSource)
4790			oalSource->RemoveNotification(notificationID, notifyProc, userData);
4791	}
4792	catch (OSStatus      result) {
4793		DebugMessageN1("ERROR: alSourceRemoveNotification FAILED = %s\n", alGetString(result));
4794	}
4795	catch (...) {
4796		DebugMessage("ERROR: alSourceRemoveNotification FAILED");
4797	}
4798
4799	ReleaseSourceObject(oalSource);
4800	return;
4801}
4802
4803// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4804// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4805// APPLE ENVIRONMENTAL AUDIO
4806// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4807// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4808
4809#pragma mark ***** ASA Extension *****
4810ALC_API ALenum  alcASAGetSource(ALuint property, ALuint sid, ALvoid *data, ALuint* dataSize)
4811{
4812#if LOG_ASA_USAGE
4813	DebugMessageN2("ASAGetSource--> source %ld : property %s", (long int) sid, GetALCAttributeString(property));
4814#endif
4815
4816	if (Get3DMixerVersion() < k3DMixerVersion_2_2)
4817		return  AL_INVALID_OPERATION;
4818
4819	ALCenum		err = ALC_NO_ERROR;
4820	OALSource*	oalSource = NULL;
4821
4822	try {
4823		oalSource = ProtectSourceObjectInCurrentContext(sid);
4824
4825        switch (property)
4826        {
4827            case ALC_ASA_REVERB_SEND_LEVEL:
4828				if (*dataSize < sizeof(ALfloat))
4829					throw (OSStatus) AL_INVALID_OPERATION;
4830				*dataSize = sizeof(ALfloat);
4831                *(ALfloat*)data = oalSource->GetReverbSendLevel();
4832                break;
4833
4834            case ALC_ASA_OCCLUSION:
4835				if (*dataSize < sizeof(ALfloat))
4836					throw (OSStatus) AL_INVALID_OPERATION;
4837				*dataSize = sizeof(ALfloat);
4838                *(ALfloat*)data =  oalSource->GetOcclusion();
4839                break;
4840
4841            case ALC_ASA_OBSTRUCTION:
4842				if (*dataSize < sizeof(ALfloat))
4843					throw (OSStatus) AL_INVALID_OPERATION;
4844				*dataSize = sizeof(ALfloat);
4845                *(ALfloat*)data =  oalSource->GetObstruction();
4846                break;
4847            case ALC_ASA_ROGER_BEEP_ENABLE:
4848				if(!IsRogerBeepPresent() || (*dataSize < sizeof(ALboolean)))
4849					throw (OSStatus) AL_INVALID_OPERATION;
4850				*dataSize = sizeof(ALboolean);
4851                *(ALboolean*)data =  oalSource->GetRogerBeepEnable();
4852                break;
4853            case ALC_ASA_ROGER_BEEP_ON:
4854				if(!IsRogerBeepPresent() || (*dataSize < sizeof(ALboolean)))
4855					throw (OSStatus) AL_INVALID_OPERATION;
4856				*dataSize = sizeof(ALboolean);
4857                *(ALboolean*)data =  oalSource->GetRogerBeepOn();
4858                break;
4859            case ALC_ASA_ROGER_BEEP_GAIN:
4860				if(!IsRogerBeepPresent() || (*dataSize < sizeof(ALfloat)))
4861					throw (OSStatus) AL_INVALID_OPERATION;
4862				*dataSize = sizeof(ALfloat);
4863                *(ALfloat*)data =  oalSource->GetRogerBeepGain();
4864                break;
4865            case ALC_ASA_ROGER_BEEP_SENSITIVITY:
4866				if(!IsRogerBeepPresent() || (*dataSize < sizeof(ALint)))
4867					throw (OSStatus) AL_INVALID_OPERATION;
4868				*dataSize = sizeof(ALint);
4869                *(ALint*)data =  oalSource->GetRogerBeepSensitivity();
4870                break;
4871            case ALC_ASA_ROGER_BEEP_TYPE:
4872				if(!IsRogerBeepPresent() || (*dataSize < sizeof(ALint)))
4873					throw (OSStatus) AL_INVALID_OPERATION;
4874				*dataSize = sizeof(ALint);
4875                *(ALint*)data =  oalSource->GetRogerBeepType();
4876                break;
4877            case ALC_ASA_DISTORTION_ENABLE:
4878				if(!IsDistortionPresent() || (*dataSize < sizeof(ALboolean)))
4879					throw (OSStatus) AL_INVALID_OPERATION;
4880				*dataSize = sizeof(ALboolean);
4881                *(ALboolean*)data =  oalSource->GetDistortionEnable();
4882                break;
4883            case ALC_ASA_DISTORTION_ON:
4884				if(!IsDistortionPresent() || (*dataSize < sizeof(ALboolean)))
4885					throw (OSStatus) AL_INVALID_OPERATION;
4886				*dataSize = sizeof(ALboolean);
4887                *(ALboolean*)data =  oalSource->GetDistortionOn();
4888                break;
4889            case ALC_ASA_DISTORTION_MIX:
4890				if(!IsDistortionPresent() || (*dataSize < sizeof(ALfloat)))
4891					throw (OSStatus) AL_INVALID_OPERATION;
4892				*dataSize = sizeof(ALfloat);
4893                *(ALfloat*)data =  oalSource->GetDistortionMix();
4894                break;
4895            case ALC_ASA_DISTORTION_TYPE:
4896				if(!IsDistortionPresent() || (*dataSize < sizeof(ALint)))
4897					throw (OSStatus) AL_INVALID_OPERATION;
4898				*dataSize = sizeof(ALint);
4899                *(ALint*)data =  oalSource->GetDistortionType();
4900                break;
4901
4902            default:
4903				err = AL_INVALID_NAME;
4904                break;
4905        }
4906	}
4907	catch (OSStatus     result) {
4908		DebugMessageN3("ERROR ASAGetSource FAILED--> source %ld : property %s : error = %s", (long int) sid, GetALCAttributeString(property), alGetString(result));
4909		err = result;
4910	}
4911    catch (...) {
4912		DebugMessageN3("ERROR ASAGetSource FAILED--> source %ld : property %s : error = %s", (long int) sid, GetALCAttributeString(property), alGetString(-1));
4913		err = AL_INVALID_OPERATION;
4914	}
4915
4916	ReleaseSourceObject(oalSource);
4917	return err;
4918}
4919
4920// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4921ALC_API ALenum  alcASASetSource(ALuint property, ALuint sid, ALvoid *data, ALuint dataSize)
4922{
4923#if LOG_ASA_USAGE
4924	DebugMessageN2("ASASetSource--> source %ld : property %s", (long int) sid, GetALCAttributeString(property));
4925#endif
4926
4927	if (Get3DMixerVersion() < k3DMixerVersion_2_2)
4928		return  AL_INVALID_OPERATION;
4929
4930	ALCenum			err = ALC_NO_ERROR;
4931	OALSource*		oalSource = NULL;
4932
4933	try {
4934		oalSource = ProtectSourceObjectInCurrentContext(sid);
4935
4936		FSRef nuRef;
4937        switch (property)
4938        {
4939			// Source & Listener Attributes
4940            case ALC_ASA_REVERB_SEND_LEVEL:
4941				if (dataSize < sizeof(ALfloat))
4942					throw (OSStatus) AL_INVALID_OPERATION;
4943                oalSource->SetReverbSendLevel(*(ALfloat*)data);
4944                break;
4945
4946            case ALC_ASA_OCCLUSION:
4947				if (dataSize < sizeof(ALfloat))
4948					throw (OSStatus) AL_INVALID_OPERATION;
4949                oalSource->SetOcclusion(*(ALfloat*)data);
4950                break;
4951
4952            case ALC_ASA_OBSTRUCTION:
4953				if (dataSize < sizeof(ALfloat))
4954					throw (OSStatus) AL_INVALID_OPERATION;
4955                oalSource->SetObstruction(*(ALfloat*)data);
4956                break;
4957            case ALC_ASA_ROGER_BEEP_ENABLE:
4958				if((!IsRogerBeepPresent()) || (dataSize < sizeof(Boolean)))
4959					throw (OSStatus) AL_INVALID_OPERATION;
4960                oalSource->SetRogerBeepEnable(*(Boolean*)data);
4961                break;
4962            case ALC_ASA_ROGER_BEEP_ON:
4963				if((!IsRogerBeepPresent()) || (dataSize < sizeof(Boolean)))
4964					throw (OSStatus) AL_INVALID_OPERATION;
4965                oalSource->SetRogerBeepOn(*(Boolean*)data);
4966                break;
4967            case ALC_ASA_ROGER_BEEP_GAIN:
4968				if((!IsRogerBeepPresent()) || (dataSize < sizeof(ALfloat)))
4969					throw (OSStatus) AL_INVALID_OPERATION;
4970                oalSource->SetRogerBeepGain(*(ALfloat*)data);
4971                break;
4972            case ALC_ASA_ROGER_BEEP_SENSITIVITY:
4973				if((!IsRogerBeepPresent()) || (dataSize < sizeof(ALint)))
4974					throw (OSStatus) AL_INVALID_OPERATION;
4975                oalSource->SetRogerBeepSensitivity(*(ALint*)data);
4976                break;
4977            case ALC_ASA_ROGER_BEEP_TYPE:
4978				if((!IsRogerBeepPresent()) || (dataSize < sizeof(ALint)))
4979					throw (OSStatus) AL_INVALID_OPERATION;
4980                oalSource->SetRogerBeepType(*(ALint*)data);
4981                break;
4982            case ALC_ASA_ROGER_BEEP_PRESET:
4983				if(!IsRogerBeepPresent())
4984					throw (OSStatus) AL_INVALID_OPERATION;
4985				if (FSPathMakeRef((UInt8 *) data , &nuRef, NULL))
4986					throw (OSStatus) AL_INVALID_OPERATION;
4987				oalSource->SetRogerBeepPreset(&nuRef);
4988                break;
4989            case ALC_ASA_DISTORTION_ENABLE:
4990				if((!IsDistortionPresent()) || (dataSize < sizeof(Boolean)))
4991					throw (OSStatus) AL_INVALID_OPERATION;
4992                oalSource->SetDistortionEnable(*(Boolean*)data);
4993                break;
4994            case ALC_ASA_DISTORTION_ON:
4995				if((!IsDistortionPresent()) || (dataSize < sizeof(Boolean)))
4996					throw (OSStatus) AL_INVALID_OPERATION;
4997                oalSource->SetDistortionOn(*(Boolean*)data);
4998                break;
4999            case ALC_ASA_DISTORTION_MIX:
5000				if((!IsDistortionPresent()) || (dataSize < sizeof(ALfloat)))
5001					throw (OSStatus) AL_INVALID_OPERATION;
5002                oalSource->SetDistortionMix(*(ALfloat*)data);
5003                break;
5004            case ALC_ASA_DISTORTION_TYPE:
5005				if((!IsDistortionPresent()) || (dataSize < sizeof(ALint)))
5006					throw (OSStatus) AL_INVALID_OPERATION;
5007                oalSource->SetDistortionType(*(ALint*)data);
5008                break;
5009            case ALC_ASA_DISTORTION_PRESET:
5010				if(!IsDistortionPresent())
5011					throw (OSStatus) AL_INVALID_OPERATION;
5012				if (FSPathMakeRef((UInt8 *) data , &nuRef, NULL))
5013					throw (OSStatus) AL_INVALID_OPERATION;
5014				oalSource->SetDistortionPreset(&nuRef);
5015                break;
5016            default:
5017				err = AL_INVALID_NAME;
5018                break;
5019        }
5020	}
5021	catch (OSStatus     result) {
5022		DebugMessageN3("ERROR ASASetSource FAILED--> source %ld : property %s : error = %s", (long int) sid, GetALCAttributeString(property), alGetString(result));
5023		err = result;
5024	}
5025    catch (...) {
5026		DebugMessageN3("ERROR ASASetSource FAILED--> source %ld : property %s : error = %s", (long int) sid, GetALCAttributeString(property), alGetString(-1));
5027		err = AL_INVALID_OPERATION;
5028	}
5029
5030	ReleaseSourceObject(oalSource);
5031
5032	return err;
5033}
5034
5035// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5036ALC_API ALenum  alcASAGetListener(ALuint property, ALvoid *data, ALuint* dataSize)
5037{
5038#if LOG_ASA_USAGE
5039	DebugMessageN1("ASAGetListener--> property %s", GetALCAttributeString(property));
5040#endif
5041
5042	if (Get3DMixerVersion() < k3DMixerVersion_2_2)
5043		return  AL_INVALID_OPERATION;
5044
5045	ALCenum err = ALC_NO_ERROR;
5046
5047	OALContext* oalContext = NULL;
5048
5049	try {
5050        oalContext = ProtectContextObject(gCurrentContext);
5051        switch (property)
5052        {
5053			case ALC_ASA_REVERB_ON:
5054				if (*dataSize < sizeof(ALuint))
5055					throw (OSStatus)AL_INVALID_OPERATION;
5056				*dataSize = sizeof(ALuint);
5057                *(ALuint*)data = oalContext->GetReverbState();
5058
5059            case ALC_ASA_REVERB_ROOM_TYPE:
5060				if (*dataSize < sizeof(ALint))
5061					throw (OSStatus)AL_INVALID_OPERATION;
5062				*dataSize = sizeof(ALint);
5063                *(ALint*)data =  oalContext->GetReverbRoomType();
5064                break;
5065
5066            case ALC_ASA_REVERB_GLOBAL_LEVEL:
5067				if (*dataSize < sizeof(ALfloat))
5068					throw (OSStatus)AL_INVALID_OPERATION;
5069				*dataSize = sizeof(ALfloat);
5070                *(ALfloat*) data =  oalContext->GetReverbLevel();
5071                break;
5072
5073            case ALC_ASA_REVERB_QUALITY:
5074				if (*dataSize < sizeof(ALint))
5075					throw (OSStatus)AL_INVALID_OPERATION;
5076				*dataSize = sizeof(ALint);
5077				*(ALint*) data =  oalContext->GetReverbQuality();
5078				break;
5079
5080            case ALC_ASA_REVERB_EQ_GAIN:
5081				if (*dataSize < sizeof(ALfloat))
5082					throw (OSStatus)AL_INVALID_OPERATION;
5083				*dataSize = sizeof(ALfloat);
5084					 *(ALfloat*) data =  oalContext->GetReverbEQGain();
5085				break;
5086
5087            case ALC_ASA_REVERB_EQ_BANDWITH:
5088				if (*dataSize < sizeof(ALfloat))
5089					throw (OSStatus)AL_INVALID_OPERATION;
5090				*dataSize = sizeof(ALfloat);
5091				*(ALfloat*) data =  oalContext->GetReverbEQBandwidth();
5092				break;
5093
5094            case ALC_ASA_REVERB_EQ_FREQ:
5095				if (*dataSize < sizeof(ALfloat))
5096					throw (OSStatus)AL_INVALID_OPERATION;
5097				*dataSize = sizeof(ALfloat);
5098				*(ALfloat*) data =  oalContext->GetReverbEQFrequency();
5099				break;
5100
5101			default:
5102				err = AL_INVALID_NAME;
5103                break;
5104        }
5105	}
5106	catch (OSStatus     result) {
5107		DebugMessageN2("ERROR ASAGetListener FAILED--> property %s : error = %s", GetALCAttributeString(property), alGetString(result));
5108		err = result;
5109	}
5110    catch (...) {
5111		DebugMessageN2("ERROR ASAGetListener FAILED--> property %s : error = %s", GetALCAttributeString(property), alGetString(-1));
5112        err = AL_INVALID_OPERATION;
5113	}
5114
5115	ReleaseContextObject(oalContext);
5116
5117	return err;
5118}
5119
5120// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5121ALC_API ALenum  alcASASetListener(ALuint property, ALvoid *data, ALuint dataSize)
5122{
5123#if LOG_ASA_USAGE
5124	DebugMessageN1("ASAGetListener--> property %s", GetALCAttributeString(property));
5125#endif
5126
5127	if (data == NULL)
5128		return AL_INVALID_VALUE;
5129
5130	if (Get3DMixerVersion() < k3DMixerVersion_2_2)
5131		return  AL_INVALID_OPERATION;
5132
5133	ALCenum err = ALC_NO_ERROR;
5134
5135	OALContext* oalContext = NULL;
5136
5137	try {
5138        oalContext = ProtectContextObject(gCurrentContext);
5139        switch (property)
5140        {
5141            case ALC_ASA_REVERB_ON:
5142				if (dataSize < sizeof(UInt32))
5143					throw ((OSStatus) AL_INVALID_OPERATION);
5144                oalContext->SetReverbState(*(UInt32*)data);
5145                break;
5146
5147            case ALC_ASA_REVERB_ROOM_TYPE:
5148				if (dataSize < sizeof(ALint))
5149					throw ((OSStatus) AL_INVALID_OPERATION);
5150                oalContext->SetReverbRoomType(*(ALint *)data);
5151                break;
5152
5153            case ALC_ASA_REVERB_GLOBAL_LEVEL:
5154			{
5155				if (dataSize < sizeof(ALfloat))
5156					throw ((OSStatus) AL_INVALID_OPERATION);
5157
5158				Float32		level = *(ALfloat *) data;
5159                oalContext->SetReverbLevel(level);
5160            }
5161			    break;
5162
5163            case ALC_ASA_REVERB_PRESET:
5164			{
5165				if ((dataSize == 0) || (data == NULL))
5166					throw ((OSStatus) AL_INVALID_OPERATION);
5167
5168				FSRef	nuRef;
5169				if (FSPathMakeRef((UInt8 *) data , &nuRef, NULL))
5170					throw ((OSStatus) AL_INVALID_OPERATION);
5171
5172				oalContext->SetReverbPreset(&nuRef);
5173			}
5174				break;
5175
5176            case ALC_ASA_REVERB_QUALITY:
5177			{
5178				UInt32		quality = *(ALint *) data;
5179				oalContext->SetReverbQuality(quality);
5180			}
5181				break;
5182
5183            case ALC_ASA_REVERB_EQ_GAIN:
5184			{
5185				// check range of -18.0 - 18.0 or pin it anyway
5186				Float32		gain = *(ALfloat *) data;
5187				if ((gain < -18.0) || (gain > 18.0))
5188					throw ((OSStatus) AL_INVALID_VALUE);
5189				oalContext->SetReverbEQGain(gain);
5190			}
5191				break;
5192
5193            case ALC_ASA_REVERB_EQ_BANDWITH:
5194			{
5195				// check range of 0.5 - 4.0 or pin it anyway
5196				Float32		bandwidth = *(ALfloat *) data;
5197				if ((bandwidth < 0.5) || (bandwidth > 4.0))
5198					throw ((OSStatus) AL_INVALID_VALUE);
5199				oalContext->SetReverbEQBandwidth(bandwidth);
5200			}
5201				break;
5202
5203            case ALC_ASA_REVERB_EQ_FREQ:
5204			{
5205				// check range of 10.0 - 20000.0 or pin it anyway
5206				Float32		frequency = *(ALfloat *) data;
5207				if ((frequency < 10.0) || (frequency > 20000.0))
5208					throw ((OSStatus) AL_INVALID_VALUE);
5209				oalContext->SetReverbEQFrequency(frequency);
5210			}
5211				break;
5212
5213            default:
5214				err = AL_INVALID_NAME;
5215                break;
5216        }
5217	}
5218	catch (OSStatus     result) {
5219		DebugMessageN2("ERROR ASAGetListener FAILED--> property %s : error = %s", GetALCAttributeString(property), alGetString(result));
5220		err = result;
5221	}
5222    catch (...) {
5223		DebugMessageN2("ERROR ASAGetListener FAILED--> property %s : error = %s", GetALCAttributeString(property), alGetString(-1));
5224        err = AL_INVALID_OPERATION;
5225	}
5226
5227	ReleaseContextObject(oalContext);
5228
5229	return err;
5230}
5231
5232// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5233// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5234// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5235// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5236#pragma mark ***** DEPRECATED for 1.1 *****
5237AL_API void	AL_APIENTRY alHint( ALenum target, ALenum mode )
5238{
5239	// Removed from headers for 1.1 but left in to avoid runtime link errors
5240	// Prototype has been removed from the public headers
5241	return;
5242}
5243
5244// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5245// Never actually in official OpenAL headers because no tokens were defined to use it
5246// keep building for 1.0 released binary compatibility
5247AL_API ALvoid AL_APIENTRY alSetInteger (ALenum pname, ALint value)
5248{
5249#if LOG_API_USAGE
5250	DebugMessage("***** alSetIntegeri");
5251#endif
5252
5253	OALContext* oalContext	= NULL;
5254
5255	try {
5256		switch(pname)
5257		{
5258			case ALC_SPATIAL_RENDERING_QUALITY:
5259				if (IsValidRenderQuality ((UInt32) value))
5260				{
5261        			oalContext = ProtectContextObject(gCurrentContext);
5262					oalContext->SetRenderQuality ((UInt32) value);
5263				}
5264				break;
5265
5266			case ALC_RENDER_CHANNEL_COUNT:
5267			{
5268				if (value != gRenderChannelSetting)
5269				{
5270					if (gOALDeviceMap == NULL)
5271						throw ((OSStatus) AL_INVALID_OPERATION);
5272
5273					// it's a new setting, so make sure all open devices now use it
5274					// if there are no open devices, then all subsequent device creations will use this setting to start with
5275					uintptr_t	token;
5276					OALDevice	*oalDevice = NULL;
5277					gRenderChannelSetting = (UInt32) value;
5278
5279					CAGuard::Locker locked(*gDeviceMapLock);
5280
5281					for (UInt32 i = 0; i < gOALDeviceMap->Size(); i++)
5282					{
5283						oalDevice = gOALDeviceMap->GetDeviceByIndex(i, token);
5284						// this device may already be using this setting
5285						if ((ALint) oalDevice->GetRenderChannelSetting() != gRenderChannelSetting)
5286						{
5287							oalDevice->SetInUseFlag();
5288							oalDevice->SetRenderChannelSetting (gRenderChannelSetting); // SetRenderChannelSetting tells the library to walk the context list and adjust all context's for this device
5289							oalDevice->ClearInUseFlag();
5290						}
5291					}
5292				}
5293			}
5294				break;
5295
5296            case ALC_MIXER_MAXIMUM_BUSSES:
5297                gMaximumMixerBusCount = value;
5298                break;
5299
5300			default:
5301				alSetError(AL_INVALID_VALUE);
5302				break;
5303		}
5304	}
5305	catch (OSStatus		result) {
5306 		DebugMessageN1("ERROR: alSetInteger FAILED = %s\n", alGetString(result));
5307        alSetError(result);
5308    }
5309	catch (...) {
5310 		DebugMessage("ERROR: alSetInteger FAILED");
5311		alSetError(AL_INVALID_OPERATION);
5312	}
5313
5314	ReleaseContextObject(oalContext);
5315}
5316
5317// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5318// Never actually in official OpenAL headers because no tokens were defined to use it
5319// deprecated, keep building for 1.0 released binary compatibility
5320AL_API ALvoid AL_APIENTRY alSetDouble (ALenum pname, ALdouble value)
5321{
5322#if LOG_API_USAGE
5323	DebugMessage("***** alSetDouble");
5324#endif
5325
5326	try {
5327		switch (pname)
5328		{
5329			case ALC_MIXER_OUTPUT_RATE:
5330				gMixerOutputRate = value;
5331				break;
5332
5333			default:
5334				alSetError(AL_INVALID_VALUE);
5335				break;
5336		}
5337	}
5338	catch (OSStatus		result) {
5339 		DebugMessageN1("ERROR: alSetDouble FAILED = %s\n", alGetString(result));
5340        alSetError(result);
5341    }
5342	catch (...) {
5343 		DebugMessage("ERROR: alSetDouble FAILED");
5344		alSetError(AL_INVALID_OPERATION);
5345	}
5346}
5347
5348// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5349AL_API ALvoid AL_APIENTRY alPropagationSpeed (ALfloat value)
5350{
5351#if LOG_API_USAGE
5352	DebugMessage("***** alPropagationSpeed");
5353#endif
5354	if (value > 0.0f)
5355	{
5356	}
5357    else
5358	{
5359        alSetError(AL_INVALID_VALUE);
5360	}
5361}
5362// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5363AL_API ALvoid AL_APIENTRY alDistanceScale (ALfloat value)
5364{
5365#if LOG_API_USAGE
5366	DebugMessage("***** alDistanceScale");
5367#endif
5368
5369	if (value > 0.0f)
5370	{
5371		// gDistanceScale = value;
5372	}
5373    else
5374	{
5375		alSetError(AL_INVALID_VALUE);
5376	}
5377}
5378// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5379AL_API ALvoid AL_APIENTRY alEnviromentiIASIG (ALuint environment, ALenum pname, ALint value)
5380{
5381#if LOG_API_USAGE
5382	DebugMessage("***** alEnviromentiIASIG");
5383#endif
5384}
5385
5386// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5387AL_API ALvoid AL_APIENTRY alEnvironmentfIASIG (ALuint environment, ALenum pname, ALfloat value)
5388{
5389#if LOG_API_USAGE
5390	DebugMessage("***** alEnvironmentfIASIG");
5391#endif
5392}
5393
5394// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5395AL_API ALsizei AL_APIENTRY alGenEnvironmentIASIG (ALsizei n, ALuint *environments)
5396{
5397#if LOG_API_USAGE
5398	DebugMessage("***** alGenEnvironmentIASIG");
5399#endif
5400	return 0;
5401}
5402// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5403AL_API ALvoid AL_APIENTRY alDeleteEnvironmentIASIG (ALsizei n, ALuint *environments)
5404{
5405#if LOG_API_USAGE
5406	DebugMessage("***** alDeleteEnvironmentIASIG");
5407#endif
5408}
5409
5410// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5411// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5412// MAYBE LATER
5413// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5414// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5415/*
5416// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5417ALCchar 					gOutputDeviceList[maxLen*2];
5418ALCchar 					gInputDeviceList[maxLen*2];
5419
5420void	GetDefaultDeviceNameList(ALCchar*		outDeviceNameList, bool	isInput)
5421{
5422	UInt32		size = 0;
5423	OSStatus	result = noErr;
5424	UInt32		deviceProperty = isInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice;
5425
5426	try {
5427		AudioDeviceID	defaultDevice = 0;
5428		// Get the default output device
5429		size = sizeof(defaultDevice);
5430		result = AudioHardwareGetProperty(deviceProperty, &size, &defaultDevice);
5431			THROW_RESULT
5432
5433		result = AudioDeviceGetPropertyInfo( defaultDevice, 0, false, kAudioDevicePropertyDeviceName, &size, NULL);
5434			THROW_RESULT
5435
5436		if (size > maxLen)
5437			throw -1;
5438
5439		size = maxLen;
5440		result = AudioDeviceGetProperty(defaultDevice, 0, false, kAudioDevicePropertyDeviceName, &size, outDeviceNameList);
5441			THROW_RESULT
5442
5443		outDeviceNameList[size] = '\0'; // double terminator
5444
5445	} catch (...) {
5446		outDeviceNameList[0] = '\0'; // failure case, make it a zero length string
5447		outDeviceNameList[1] = '\0'; // failure case, make it a zero length string
5448	}
5449}
5450
5451void	GetDeviceList(ALCchar*		outDeviceName, bool	inMakeInputDeviceList)
5452{
5453	UInt32		size = 0;
5454	OSStatus	result = noErr;
5455	UInt32		deviceCount = 0;
5456	ALCchar		*curStrPtr = outDeviceName;
5457	UInt32		charCount = 0;
5458
5459	result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL);
5460		THROW_RESULT
5461	deviceCount = size / sizeof(AudioDeviceID);
5462
5463	AudioDeviceID	*ids = (AudioDeviceID*) calloc(1, size);
5464	result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, ids);
5465		THROW_RESULT
5466
5467	bool deviceDoesInput;
5468	bool deviceDoesOutput;
5469
5470	for (UInt32	i; i < deviceCount; i++)
5471	{
5472		size = 0;
5473		AudioDeviceGetPropertyInfo( ids[i], 0, true, kAudioDevicePropertyStreams, &size, NULL);
5474		deviceDoesInput = size > 0 ? true : false;
5475
5476		size = 0;
5477		AudioDeviceGetPropertyInfo( ids[i], 0, false, kAudioDevicePropertyStreams, &size, NULL);
5478		deviceDoesOutput = size > 0 ? true : false;
5479
5480		if ((inMakeInputDeviceList && deviceDoesInput) || (!inMakeInputDeviceList && deviceDoesOutput))
5481		{
5482			size = 0;
5483			result = AudioDeviceGetPropertyInfo( ids[i], 0, inMakeInputDeviceList, kAudioDevicePropertyDeviceName, &size, NULL);
5484				THROW_RESULT
5485			if (charCount + size > maxLen*2)
5486				throw -1;
5487
5488			// get name
5489			result = AudioDeviceGetProperty(ids[i], 0, inMakeInputDeviceList, kAudioDevicePropertyDeviceName, &size, curStrPtr);
5490				THROW_RESULT
5491
5492			curStrPtr +=size;
5493			charCount +=size;
5494		}
5495	}
5496
5497	*curStrPtr = '\0';
5498	if(charCount == 0)
5499	{
5500		curStrPtr++;
5501		*curStrPtr = '\0';
5502	}
5503
5504}
5505*/
5506
5507