Print source and auxiliary slot debug warnings from alcDestroyContext
[openal-soft.git] / Alc / ALc.c
blob1528c4e658483c548e4fb65fc3afa2af6ff73e0f
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include "alMain.h"
29 #include "alSource.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alThunk.h"
33 #include "alSource.h"
34 #include "alBuffer.h"
35 #include "alExtension.h"
36 #include "alAuxEffectSlot.h"
37 #include "alDatabuffer.h"
38 #include "bs2b.h"
39 #include "alu.h"
42 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
43 static struct {
44 const char *name;
45 void (*Init)(BackendFuncs*);
46 BackendFuncs Funcs;
47 } BackendList[] = {
48 #ifdef HAVE_ALSA
49 { "alsa", alc_alsa_init, EmptyFuncs },
50 #endif
51 #ifdef HAVE_OSS
52 { "oss", alc_oss_init, EmptyFuncs },
53 #endif
54 #ifdef HAVE_SOLARIS
55 { "solaris", alc_solaris_init, EmptyFuncs },
56 #endif
57 #ifdef HAVE_DSOUND
58 { "dsound", alcDSoundInit, EmptyFuncs },
59 #endif
60 #ifdef HAVE_WINMM
61 { "winmm", alcWinMMInit, EmptyFuncs },
62 #endif
63 #ifdef HAVE_PORTAUDIO
64 { "port", alc_pa_init, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", alc_pulse_init, EmptyFuncs },
68 #endif
70 { "wave", alc_wave_init, EmptyFuncs },
72 { NULL, NULL, EmptyFuncs }
74 #undef EmptyFuncs
76 ///////////////////////////////////////////////////////
78 #define ALC_EFX_MAJOR_VERSION 0x20001
79 #define ALC_EFX_MINOR_VERSION 0x20002
80 #define ALC_MAX_AUXILIARY_SENDS 0x20003
82 ///////////////////////////////////////////////////////
83 // STRING and EXTENSIONS
85 typedef struct ALCfunction_struct
87 ALCchar *funcName;
88 ALvoid *address;
89 } ALCfunction;
91 static ALCfunction alcFunctions[] = {
92 { "alcCreateContext", (ALvoid *) alcCreateContext },
93 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
94 { "alcProcessContext", (ALvoid *) alcProcessContext },
95 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
96 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
97 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
98 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
99 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
100 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
101 { "alcGetError", (ALvoid *) alcGetError },
102 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
103 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
104 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
105 { "alcGetString", (ALvoid *) alcGetString },
106 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
107 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
108 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
109 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
110 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
111 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
112 { NULL, (ALvoid *) NULL }
115 static ALenums enumeration[]={
116 // Types
117 { (ALchar *)"ALC_INVALID", ALC_INVALID },
118 { (ALchar *)"ALC_FALSE", ALC_FALSE },
119 { (ALchar *)"ALC_TRUE", ALC_TRUE },
121 // ALC Properties
122 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
123 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
124 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
125 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
126 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
127 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
128 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
129 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
130 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
131 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
132 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
133 { (ALchar *)"ALC_SYNC", ALC_SYNC },
134 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
135 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
136 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
137 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
138 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
140 // EFX Properties
141 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
142 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
143 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
145 // ALC Error Message
146 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
147 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
148 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
149 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
150 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
151 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
152 { (ALchar *)NULL, (ALenum)0 }
154 // Error strings
155 static const ALCchar alcNoError[] = "No Error";
156 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
157 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
158 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
159 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
160 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
162 // Context strings
163 static ALCchar alcDeviceList[2048];
164 static ALCchar alcAllDeviceList[2048];
165 static ALCchar alcCaptureDeviceList[2048];
166 // Default is always the first in the list
167 static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
168 static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
169 static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
172 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_EFX";
173 static ALCint alcMajorVersion = 1;
174 static ALCint alcMinorVersion = 1;
176 static ALCint alcEFXMajorVersion = 1;
177 static ALCint alcEFXMinorVersion = 0;
179 ///////////////////////////////////////////////////////
182 ///////////////////////////////////////////////////////
183 // Global Variables
185 static ALCdevice *g_pDeviceList = NULL;
186 static ALCuint g_ulDeviceCount = 0;
188 static CRITICAL_SECTION g_csMutex;
190 // Context List
191 static ALCcontext *g_pContextList = NULL;
192 static ALCuint g_ulContextCount = 0;
194 // Context Error
195 static ALCenum g_eLastContextError = ALC_NO_ERROR;
197 static ALboolean init_done = AL_FALSE;
199 ///////////////////////////////////////////////////////
202 ///////////////////////////////////////////////////////
203 // ALC Related helper functions
204 #ifdef _WIN32
205 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
207 (void)lpReserved;
209 // Perform actions based on the reason for calling.
210 switch(ul_reason_for_call)
212 case DLL_PROCESS_ATTACH:
213 DisableThreadLibraryCalls(hModule);
214 break;
216 case DLL_PROCESS_DETACH:
217 if(!init_done)
218 break;
219 ReleaseALC();
220 FreeALConfig();
221 ALTHUNK_EXIT();
222 DeleteCriticalSection(&g_csMutex);
223 break;
225 return TRUE;
227 #else
228 #ifdef HAVE_GCC_DESTRUCTOR
229 static void my_deinit() __attribute__((destructor));
230 static void my_deinit()
232 static ALenum once = AL_FALSE;
233 if(once || !init_done) return;
234 once = AL_TRUE;
236 ReleaseALC();
237 FreeALConfig();
238 ALTHUNK_EXIT();
239 DeleteCriticalSection(&g_csMutex);
241 #endif
242 #endif
244 static void InitAL(void)
246 if(!init_done)
248 int i;
249 const char *devs, *str;
251 init_done = AL_TRUE;
253 InitializeCriticalSection(&g_csMutex);
254 ALTHUNK_INIT();
255 ReadALConfig();
257 devs = GetConfigValue(NULL, "drivers", "");
258 if(devs[0])
260 int n;
261 size_t len;
262 const char *next = devs;
264 i = 0;
266 do {
267 devs = next;
268 next = strchr(devs, ',');
270 if(!devs[0] || devs[0] == ',')
271 continue;
273 len = (next ? ((size_t)(next-devs)) : strlen(devs));
274 for(n = i;BackendList[n].Init;n++)
276 if(len == strlen(BackendList[n].name) &&
277 strncmp(BackendList[n].name, devs, len) == 0)
279 const char *name = BackendList[i].name;
280 void (*Init)(BackendFuncs*) = BackendList[i].Init;
282 BackendList[i].name = BackendList[n].name;
283 BackendList[i].Init = BackendList[n].Init;
285 BackendList[n].name = name;
286 BackendList[n].Init = Init;
288 i++;
291 } while(next++);
293 BackendList[i].name = NULL;
294 BackendList[i].Init = NULL;
297 for(i = 0;BackendList[i].Init;i++)
298 BackendList[i].Init(&BackendList[i].Funcs);
300 str = GetConfigValue(NULL, "stereodup", "false");
301 DuplicateStereo = (strcasecmp(str, "true") == 0 ||
302 strcasecmp(str, "yes") == 0 ||
303 strcasecmp(str, "on") == 0 ||
304 atoi(str) != 0);
306 str = GetConfigValue(NULL, "excludefx", "");
307 if(str[0])
309 const struct {
310 const char *name;
311 int type;
312 } EffectList[] = {
313 { "eaxreverb", EAXREVERB },
314 { "reverb", REVERB },
315 { "echo", ECHO },
316 { NULL, 0 }
318 int n;
319 size_t len;
320 const char *next = str;
322 do {
323 str = next;
324 next = strchr(str, ',');
326 if(!str[0] || next == str)
327 continue;
329 len = (next ? ((size_t)(next-str)) : strlen(str));
330 for(n = 0;EffectList[n].name;n++)
332 if(len == strlen(EffectList[n].name) &&
333 strncmp(EffectList[n].name, str, len) == 0)
334 DisabledEffects[EffectList[n].type] = AL_TRUE;
336 } while(next++);
341 ALCchar *AppendDeviceList(char *name)
343 static size_t pos;
344 ALCchar *ret = alcDeviceList+pos;
345 if(pos >= sizeof(alcDeviceList))
347 AL_PRINT("Not enough room to add %s!\n", name);
348 return alcDeviceList + sizeof(alcDeviceList) - 1;
350 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos-1, "%s", name) + 1;
351 return ret;
354 ALCchar *AppendAllDeviceList(char *name)
356 static size_t pos;
357 ALCchar *ret = alcAllDeviceList+pos;
358 if(pos >= sizeof(alcAllDeviceList))
360 AL_PRINT("Not enough room to add %s!\n", name);
361 return alcAllDeviceList + sizeof(alcAllDeviceList) - 1;
363 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos-1, "%s", name) + 1;
364 return ret;
367 ALCchar *AppendCaptureDeviceList(char *name)
369 static size_t pos;
370 ALCchar *ret = alcCaptureDeviceList+pos;
371 if(pos >= sizeof(alcCaptureDeviceList))
373 AL_PRINT("Not enough room to add %s!\n", name);
374 return alcCaptureDeviceList + sizeof(alcCaptureDeviceList) - 1;
376 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos-1, "%s", name) + 1;
377 return ret;
381 IsDevice
383 Check pDevice is a valid Device pointer
385 static ALCboolean IsDevice(ALCdevice *pDevice)
387 ALCdevice *pTempDevice;
389 SuspendContext(NULL);
391 pTempDevice = g_pDeviceList;
392 while(pTempDevice && pTempDevice != pDevice)
393 pTempDevice = pTempDevice->next;
395 ProcessContext(NULL);
397 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
401 IsContext
403 Check pContext is a valid Context pointer
405 static ALCboolean IsContext(ALCcontext *pContext)
407 ALCcontext *pTempContext;
409 SuspendContext(NULL);
411 pTempContext = g_pContextList;
412 while (pTempContext && pTempContext != pContext)
413 pTempContext = pTempContext->next;
415 ProcessContext(NULL);
417 return (pTempContext ? ALC_TRUE : ALC_FALSE);
422 SetALCError
424 Store latest ALC Error
426 ALCvoid SetALCError(ALenum errorCode)
428 g_eLastContextError = errorCode;
433 SuspendContext
435 Thread-safe entry
437 ALCvoid SuspendContext(ALCcontext *pContext)
439 (void)pContext;
440 EnterCriticalSection(&g_csMutex);
445 ProcessContext
447 Thread-safe exit
449 ALCvoid ProcessContext(ALCcontext *pContext)
451 (void)pContext;
452 LeaveCriticalSection(&g_csMutex);
457 GetContextSuspended
459 Returns the currently active Context, in a locked state
461 ALCcontext *GetContextSuspended(void)
463 ALCcontext *pContext = NULL;
465 SuspendContext(NULL);
467 pContext = g_pContextList;
468 while(pContext && !pContext->InUse)
469 pContext = pContext->next;
471 if(pContext)
472 SuspendContext(pContext);
474 ProcessContext(NULL);
476 return pContext;
481 InitContext
483 Initialize Context variables
485 static ALvoid InitContext(ALCcontext *pContext)
487 int level;
489 //Initialise listener
490 pContext->Listener.Gain = 1.0f;
491 pContext->Listener.MetersPerUnit = 1.0f;
492 pContext->Listener.Position[0] = 0.0f;
493 pContext->Listener.Position[1] = 0.0f;
494 pContext->Listener.Position[2] = 0.0f;
495 pContext->Listener.Velocity[0] = 0.0f;
496 pContext->Listener.Velocity[1] = 0.0f;
497 pContext->Listener.Velocity[2] = 0.0f;
498 pContext->Listener.Forward[0] = 0.0f;
499 pContext->Listener.Forward[1] = 0.0f;
500 pContext->Listener.Forward[2] = -1.0f;
501 pContext->Listener.Up[0] = 0.0f;
502 pContext->Listener.Up[1] = 1.0f;
503 pContext->Listener.Up[2] = 0.0f;
505 //Validate pContext
506 pContext->LastError = AL_NO_ERROR;
507 pContext->InUse = AL_FALSE;
509 //Set output format
510 pContext->Frequency = pContext->Device->Frequency;
512 //Set globals
513 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
514 pContext->DopplerFactor = 1.0f;
515 pContext->DopplerVelocity = 1.0f;
516 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
518 pContext->ExtensionList = "AL_EXTX_buffer_sub_data AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_EXTX_sample_buffer_object AL_EXTX_source_distance_model AL_LOKI_quadriphonic";
520 level = GetConfigValueInt(NULL, "cf_level", 0);
521 if(level > 0 && level <= 6)
523 pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
524 bs2b_set_srate(pContext->bs2b, pContext->Frequency);
525 bs2b_set_level(pContext->bs2b, level);
528 aluInitPanning(pContext);
533 ExitContext
535 Clean up Context, destroy any remaining Sources
537 static ALCvoid ExitContext(ALCcontext *pContext)
539 //Invalidate context
540 pContext->LastError = AL_NO_ERROR;
541 pContext->InUse = AL_FALSE;
543 free(pContext->bs2b);
544 pContext->bs2b = NULL;
547 ///////////////////////////////////////////////////////
550 ///////////////////////////////////////////////////////
551 // ALC Functions calls
554 // This should probably move to another c file but for now ...
555 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
557 ALCboolean DeviceFound = ALC_FALSE;
558 ALCdevice *pDevice = NULL;
559 ALCint i;
561 InitAL();
563 if(SampleSize <= 0)
565 SetALCError(ALC_INVALID_VALUE);
566 return NULL;
569 if(deviceName && !deviceName[0])
570 deviceName = NULL;
572 pDevice = malloc(sizeof(ALCdevice));
573 if (pDevice)
575 //Initialise device structure
576 memset(pDevice, 0, sizeof(ALCdevice));
578 //Validate device
579 pDevice->IsCaptureDevice = AL_TRUE;
581 pDevice->Frequency = frequency;
582 pDevice->Format = format;
583 pDevice->BufferSize = SampleSize;
585 SuspendContext(NULL);
586 for(i = 0;BackendList[i].Init;i++)
588 pDevice->Funcs = &BackendList[i].Funcs;
589 if(ALCdevice_OpenCapture(pDevice, deviceName))
591 pDevice->next = g_pDeviceList;
592 g_pDeviceList = pDevice;
593 g_ulDeviceCount++;
595 DeviceFound = ALC_TRUE;
596 break;
599 ProcessContext(NULL);
601 if(!DeviceFound)
603 SetALCError(ALC_INVALID_VALUE);
604 free(pDevice);
605 pDevice = NULL;
608 else
609 SetALCError(ALC_OUT_OF_MEMORY);
611 return pDevice;
614 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
616 ALCboolean bReturn = ALC_FALSE;
617 ALCdevice **list;
619 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
621 SuspendContext(NULL);
623 list = &g_pDeviceList;
624 while(*list != pDevice)
625 list = &(*list)->next;
627 *list = (*list)->next;
628 g_ulDeviceCount--;
630 ProcessContext(NULL);
632 ALCdevice_CloseCapture(pDevice);
633 free(pDevice);
635 bReturn = ALC_TRUE;
637 else
638 SetALCError(ALC_INVALID_DEVICE);
640 return bReturn;
643 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
645 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
646 ALCdevice_StartCapture(pDevice);
647 else
648 SetALCError(ALC_INVALID_DEVICE);
651 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
653 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
654 ALCdevice_StopCapture(pDevice);
655 else
656 SetALCError(ALC_INVALID_DEVICE);
659 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
661 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
662 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
663 else
664 SetALCError(ALC_INVALID_DEVICE);
668 alcGetError
670 Return last ALC generated error code
672 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
674 ALCenum errorCode;
676 (void)device;
678 errorCode = g_eLastContextError;
679 g_eLastContextError = ALC_NO_ERROR;
680 return errorCode;
685 alcSuspendContext
687 Not functional
689 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
691 // Not a lot happens here !
692 (void)pContext;
697 alcProcessContext
699 Not functional
701 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
703 // Not a lot happens here !
704 (void)pContext;
709 alcGetString
711 Returns information about the Device, and error strings
713 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
715 const ALCchar *value = NULL;
717 InitAL();
719 switch (param)
721 case ALC_NO_ERROR:
722 value = alcNoError;
723 break;
725 case ALC_INVALID_ENUM:
726 value = alcErrInvalidEnum;
727 break;
729 case ALC_INVALID_VALUE:
730 value = alcErrInvalidValue;
731 break;
733 case ALC_INVALID_DEVICE:
734 value = alcErrInvalidDevice;
735 break;
737 case ALC_INVALID_CONTEXT:
738 value = alcErrInvalidContext;
739 break;
741 case ALC_OUT_OF_MEMORY:
742 value = alcErrOutOfMemory;
743 break;
745 case ALC_DEFAULT_DEVICE_SPECIFIER:
746 value = alcDefaultDeviceSpecifier;
747 break;
749 case ALC_DEVICE_SPECIFIER:
750 if(IsDevice(pDevice))
751 value = pDevice->szDeviceName;
752 else
753 value = alcDeviceList;
754 break;
756 case ALC_ALL_DEVICES_SPECIFIER:
757 value = alcAllDeviceList;
758 break;
760 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
761 value = alcDefaultAllDeviceSpecifier;
762 break;
764 case ALC_CAPTURE_DEVICE_SPECIFIER:
765 if(IsDevice(pDevice))
766 value = pDevice->szDeviceName;
767 else
768 value = alcCaptureDeviceList;
769 break;
771 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
772 value = alcCaptureDefaultDeviceSpecifier;
773 break;
775 case ALC_EXTENSIONS:
776 value = alcExtensionList;
777 break;
779 default:
780 SetALCError(ALC_INVALID_ENUM);
781 break;
784 return value;
789 alcGetIntegerv
791 Returns information about the Device and the version of Open AL
793 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
795 InitAL();
797 if(IsDevice(device) && device->IsCaptureDevice)
799 SuspendContext(NULL);
801 // Capture device
802 switch (param)
804 case ALC_CAPTURE_SAMPLES:
805 if ((size) && (data))
806 *data = ALCdevice_AvailableSamples(device);
807 else
808 SetALCError(ALC_INVALID_VALUE);
809 break;
811 default:
812 SetALCError(ALC_INVALID_ENUM);
813 break;
816 ProcessContext(NULL);
818 else
820 if(data)
822 // Playback Device
823 switch (param)
825 case ALC_MAJOR_VERSION:
826 if(size <= 0)
827 SetALCError(ALC_INVALID_VALUE);
828 else
829 *data = alcMajorVersion;
830 break;
832 case ALC_MINOR_VERSION:
833 if(size <= 0)
834 SetALCError(ALC_INVALID_VALUE);
835 else
836 *data = alcMinorVersion;
837 break;
839 case ALC_EFX_MAJOR_VERSION:
840 if(size <= 0)
841 SetALCError(ALC_INVALID_VALUE);
842 else
843 *data = alcEFXMajorVersion;
844 break;
846 case ALC_EFX_MINOR_VERSION:
847 if(size <= 0)
848 SetALCError(ALC_INVALID_VALUE);
849 else
850 *data = alcEFXMinorVersion;
851 break;
853 case ALC_MAX_AUXILIARY_SENDS:
854 if(size <= 0)
855 SetALCError(ALC_INVALID_VALUE);
856 else
857 *data = (device?device->NumAuxSends:MAX_SENDS);
858 break;
860 case ALC_ATTRIBUTES_SIZE:
861 if(!IsDevice(device))
862 SetALCError(ALC_INVALID_DEVICE);
863 else if(size <= 0)
864 SetALCError(ALC_INVALID_VALUE);
865 else
866 *data = 13;
867 break;
869 case ALC_ALL_ATTRIBUTES:
870 if(!IsDevice(device))
871 SetALCError(ALC_INVALID_DEVICE);
872 else if (size < 13)
873 SetALCError(ALC_INVALID_VALUE);
874 else
876 int i = 0;
878 SuspendContext(NULL);
879 data[i++] = ALC_FREQUENCY;
880 data[i++] = device->Frequency;
882 data[i++] = ALC_REFRESH;
883 data[i++] = device->Frequency / device->UpdateSize;
885 data[i++] = ALC_SYNC;
886 data[i++] = ALC_FALSE;
888 data[i++] = ALC_MONO_SOURCES;
889 data[i++] = device->lNumMonoSources;
891 data[i++] = ALC_STEREO_SOURCES;
892 data[i++] = device->lNumStereoSources;
894 data[i++] = ALC_MAX_AUXILIARY_SENDS;
895 data[i++] = device->NumAuxSends;
897 data[i++] = 0;
898 ProcessContext(NULL);
900 break;
902 case ALC_FREQUENCY:
903 if(!IsDevice(device))
904 SetALCError(ALC_INVALID_DEVICE);
905 else if(size <= 0)
906 SetALCError(ALC_INVALID_VALUE);
907 else
908 *data = device->Frequency;
909 break;
911 case ALC_REFRESH:
912 if(!IsDevice(device))
913 SetALCError(ALC_INVALID_DEVICE);
914 else if(size <= 0)
915 SetALCError(ALC_INVALID_VALUE);
916 else
917 *data = device->Frequency / device->UpdateSize;
918 break;
920 case ALC_SYNC:
921 if(!IsDevice(device))
922 SetALCError(ALC_INVALID_DEVICE);
923 else if(size <= 0)
924 SetALCError(ALC_INVALID_VALUE);
925 else
926 *data = ALC_FALSE;
927 break;
929 case ALC_MONO_SOURCES:
930 if(!IsDevice(device))
931 SetALCError(ALC_INVALID_DEVICE);
932 else if(size <= 0)
933 SetALCError(ALC_INVALID_VALUE);
934 else
935 *data = device->lNumMonoSources;
936 break;
938 case ALC_STEREO_SOURCES:
939 if(!IsDevice(device))
940 SetALCError(ALC_INVALID_DEVICE);
941 else if(size <= 0)
942 SetALCError(ALC_INVALID_VALUE);
943 else
944 *data = device->lNumStereoSources;
945 break;
947 default:
948 SetALCError(ALC_INVALID_ENUM);
949 break;
952 else if(size)
953 SetALCError(ALC_INVALID_VALUE);
956 return;
961 alcIsExtensionPresent
963 Determines if there is support for a particular extension
965 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
967 ALCboolean bResult = ALC_FALSE;
969 (void)device;
971 if (extName)
973 const char *ptr;
974 size_t len;
976 len = strlen(extName);
977 ptr = alcExtensionList;
978 while(ptr && *ptr)
980 if(strncasecmp(ptr, extName, len) == 0 &&
981 (ptr[len] == '\0' || isspace(ptr[len])))
983 bResult = ALC_TRUE;
984 break;
986 if((ptr=strchr(ptr, ' ')) != NULL)
988 do {
989 ++ptr;
990 } while(isspace(*ptr));
994 else
995 SetALCError(ALC_INVALID_VALUE);
997 return bResult;
1002 alcGetProcAddress
1004 Retrieves the function address for a particular extension function
1006 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1008 ALCvoid *pFunction = NULL;
1009 ALsizei i = 0;
1011 (void)device;
1013 if (funcName)
1015 while(alcFunctions[i].funcName &&
1016 strcmp(alcFunctions[i].funcName,funcName) != 0)
1017 i++;
1018 pFunction = alcFunctions[i].address;
1020 else
1021 SetALCError(ALC_INVALID_VALUE);
1023 return pFunction;
1028 alcGetEnumValue
1030 Get the value for a particular ALC Enumerated Value
1032 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1034 ALsizei i = 0;
1035 ALCenum val;
1037 (void)device;
1039 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1040 i++;
1041 val = enumeration[i].value;
1043 if(!enumeration[i].enumName)
1044 SetALCError(ALC_INVALID_VALUE);
1046 return val;
1051 alcCreateContext
1053 Create and attach a Context to a particular Device.
1055 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1057 ALCcontext *ALContext = NULL;
1058 ALuint ulAttributeIndex, ulRequestedStereoSources;
1059 ALuint RequestedSends;
1061 if(IsDevice(device) && !device->IsCaptureDevice)
1063 // Reset Context Last Error code
1064 g_eLastContextError = ALC_NO_ERROR;
1066 // Current implementation only allows one Context per Device
1067 if(!device->Context)
1069 ALContext = calloc(1, sizeof(ALCcontext));
1070 if(!ALContext)
1072 SetALCError(ALC_OUT_OF_MEMORY);
1073 return NULL;
1076 SuspendContext(NULL);
1078 ALContext->Device = device;
1079 InitContext(ALContext);
1081 device->Context = ALContext;
1083 ALContext->next = g_pContextList;
1084 g_pContextList = ALContext;
1085 g_ulContextCount++;
1087 // Check for attributes
1088 if (attrList)
1090 ALCuint freq = device->Frequency;
1091 ALCint numMono = device->lNumMonoSources;
1092 ALCint numStereo = device->lNumStereoSources;
1093 ALCuint numSends = device->NumAuxSends;
1095 ulAttributeIndex = 0;
1096 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1098 if(attrList[ulAttributeIndex] == ALC_FREQUENCY)
1100 freq = attrList[ulAttributeIndex + 1];
1101 if(freq == 0)
1102 freq = device->Frequency;
1105 if(attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1107 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1109 if (ulRequestedStereoSources > device->MaxNoOfSources)
1110 ulRequestedStereoSources = device->MaxNoOfSources;
1112 numStereo = ulRequestedStereoSources;
1113 numMono = device->MaxNoOfSources - numStereo;
1116 if(attrList[ulAttributeIndex] == ALC_MAX_AUXILIARY_SENDS)
1118 RequestedSends = attrList[ulAttributeIndex + 1];
1120 if(RequestedSends > device->NumAuxSends)
1121 RequestedSends = device->NumAuxSends;
1123 numSends = RequestedSends;
1126 ulAttributeIndex += 2;
1129 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1130 device->lNumMonoSources = numMono;
1131 device->lNumStereoSources = numStereo;
1132 device->NumAuxSends = numSends;
1135 if(ALCdevice_StartContext(device, ALContext) == ALC_FALSE)
1137 alcDestroyContext(ALContext);
1138 ALContext = NULL;
1139 SetALCError(ALC_INVALID_VALUE);
1141 else
1142 ALContext->Frequency = device->Frequency;
1144 ProcessContext(NULL);
1146 else
1148 SetALCError(ALC_INVALID_VALUE);
1149 ALContext = NULL;
1152 else
1153 SetALCError(ALC_INVALID_DEVICE);
1155 return ALContext;
1160 alcDestroyContext
1162 Remove a Context
1164 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1166 ALCcontext **list;
1168 InitAL();
1170 if (IsContext(context))
1172 ALCdevice_StopContext(context->Device, context);
1174 // Lock context
1175 SuspendContext(context);
1177 if(context->SourceCount > 0)
1179 #ifdef _DEBUG
1180 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1181 #endif
1182 ReleaseALSources(context);
1184 if(context->AuxiliaryEffectSlotCount > 0)
1186 #ifdef _DEBUG
1187 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1188 #endif
1189 ReleaseALAuxiliaryEffectSlots(context);
1192 context->Device->Context = NULL;
1194 list = &g_pContextList;
1195 while(*list != context)
1196 list = &(*list)->next;
1198 *list = (*list)->next;
1199 g_ulContextCount--;
1201 // Unlock context
1202 ProcessContext(context);
1204 ExitContext(context);
1206 // Free memory (MUST do this after ProcessContext)
1207 memset(context, 0, sizeof(ALCcontext));
1208 free(context);
1210 else
1211 SetALCError(ALC_INVALID_CONTEXT);
1216 alcGetCurrentContext
1218 Returns the currently active Context
1220 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1222 ALCcontext *pContext = NULL;
1224 InitAL();
1226 SuspendContext(NULL);
1228 pContext = g_pContextList;
1229 while ((pContext) && (!pContext->InUse))
1230 pContext = pContext->next;
1232 ProcessContext(NULL);
1234 return pContext;
1239 alcGetContextsDevice
1241 Returns the Device that a particular Context is attached to
1243 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1245 ALCdevice *pDevice = NULL;
1247 InitAL();
1249 SuspendContext(NULL);
1250 if (IsContext(pContext))
1251 pDevice = pContext->Device;
1252 else
1253 SetALCError(ALC_INVALID_CONTEXT);
1254 ProcessContext(NULL);
1256 return pDevice;
1261 alcMakeContextCurrent
1263 Makes the given Context the active Context
1265 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1267 ALCcontext *ALContext;
1268 ALboolean bReturn = AL_TRUE;
1270 InitAL();
1272 SuspendContext(NULL);
1274 // context must be a valid Context or NULL
1275 if(context == NULL || IsContext(context))
1277 if((ALContext=GetContextSuspended()) != NULL)
1279 ALContext->InUse=AL_FALSE;
1280 ProcessContext(ALContext);
1283 if((ALContext=context) != NULL && ALContext->Device)
1285 SuspendContext(ALContext);
1286 ALContext->InUse=AL_TRUE;
1287 ProcessContext(ALContext);
1290 else
1292 SetALCError(ALC_INVALID_CONTEXT);
1293 bReturn = AL_FALSE;
1296 ProcessContext(NULL);
1298 return bReturn;
1302 static ALenum GetFormatFromString(const char *str)
1304 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1305 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1306 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1307 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1308 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1309 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1311 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1312 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1313 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1314 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1315 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1316 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1318 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1319 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1320 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1321 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1322 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1323 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1325 AL_PRINT("Unknown format: \"%s\"\n", str);
1326 return AL_FORMAT_STEREO16;
1330 alcOpenDevice
1332 Open the Device specified.
1334 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1336 ALboolean bDeviceFound = AL_FALSE;
1337 ALCdevice *device;
1338 ALint i;
1340 InitAL();
1342 if(deviceName && !deviceName[0])
1343 deviceName = NULL;
1345 device = malloc(sizeof(ALCdevice));
1346 if (device)
1348 const char *fmt;
1350 //Initialise device structure
1351 memset(device, 0, sizeof(ALCdevice));
1353 //Validate device
1354 device->IsCaptureDevice = AL_FALSE;
1356 //Set output format
1357 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1358 if(device->Frequency == 0)
1359 device->Frequency = SWMIXER_OUTPUT_RATE;
1361 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1362 device->Format = GetFormatFromString(fmt);
1364 device->BufferSize = GetConfigValueInt(NULL, "refresh", 4096);
1365 if((ALint)device->BufferSize <= 0)
1366 device->BufferSize = 4096;
1368 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1369 if((ALint)device->MaxNoOfSources <= 0)
1370 device->MaxNoOfSources = 256;
1372 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1373 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1374 device->AuxiliaryEffectSlotMax = 4;
1376 device->lNumStereoSources = 1;
1377 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1379 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1380 if(device->NumAuxSends > MAX_SENDS)
1381 device->NumAuxSends = MAX_SENDS;
1383 // Find a playback device to open
1384 SuspendContext(NULL);
1385 for(i = 0;BackendList[i].Init;i++)
1387 device->Funcs = &BackendList[i].Funcs;
1388 if(ALCdevice_OpenPlayback(device, deviceName))
1390 device->next = g_pDeviceList;
1391 g_pDeviceList = device;
1392 g_ulDeviceCount++;
1394 bDeviceFound = AL_TRUE;
1395 break;
1398 ProcessContext(NULL);
1400 if (!bDeviceFound)
1402 // No suitable output device found
1403 SetALCError(ALC_INVALID_VALUE);
1404 free(device);
1405 device = NULL;
1408 else
1409 SetALCError(ALC_OUT_OF_MEMORY);
1411 return device;
1416 alcCloseDevice
1418 Close the specified Device
1420 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1422 ALCboolean bReturn = ALC_FALSE;
1423 ALCdevice **list;
1425 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1427 SuspendContext(NULL);
1429 list = &g_pDeviceList;
1430 while(*list != pDevice)
1431 list = &(*list)->next;
1433 *list = (*list)->next;
1434 g_ulDeviceCount--;
1436 ProcessContext(NULL);
1438 if(pDevice->Context)
1440 #ifdef _DEBUG
1441 AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
1442 #endif
1443 alcDestroyContext(pDevice->Context);
1445 ALCdevice_ClosePlayback(pDevice);
1447 if(pDevice->BufferCount > 0)
1449 #ifdef _DEBUG
1450 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1451 #endif
1452 ReleaseALBuffers(pDevice);
1454 if(pDevice->EffectCount > 0)
1456 #ifdef _DEBUG
1457 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1458 #endif
1459 ReleaseALEffects(pDevice);
1461 if(pDevice->FilterCount > 0)
1463 #ifdef _DEBUG
1464 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1465 #endif
1466 ReleaseALFilters(pDevice);
1468 if(pDevice->DatabufferCount > 0)
1470 #ifdef _DEBUG
1471 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1472 #endif
1473 ReleaseALDatabuffers(pDevice);
1476 //Release device structure
1477 memset(pDevice, 0, sizeof(ALCdevice));
1478 free(pDevice);
1480 bReturn = ALC_TRUE;
1482 else
1483 SetALCError(ALC_INVALID_DEVICE);
1485 return bReturn;
1489 ALCvoid ReleaseALC(ALCvoid)
1491 #ifdef _DEBUG
1492 if(g_ulDeviceCount > 0)
1493 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1494 #endif
1496 while(g_pDeviceList)
1498 if(g_pDeviceList->IsCaptureDevice)
1499 alcCaptureCloseDevice(g_pDeviceList);
1500 else
1501 alcCloseDevice(g_pDeviceList);
1505 ///////////////////////////////////////////////////////