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