Initialize OpenAL with a constructor call instead of first-use
[openal-soft.git] / Alc / ALc.c
blob229af2e9d7dfc9a844c3f05a6480e24943668978
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 void (*Deinit)(void);
47 void (*Probe)(int);
48 BackendFuncs Funcs;
49 } BackendList[] = {
50 #ifdef HAVE_ALSA
51 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
52 #endif
53 #ifdef HAVE_OSS
54 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
55 #endif
56 #ifdef HAVE_SOLARIS
57 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
58 #endif
59 #ifdef HAVE_DSOUND
60 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
61 #endif
62 #ifdef HAVE_WINMM
63 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
64 #endif
65 #ifdef HAVE_PORTAUDIO
66 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
67 #endif
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
70 #endif
72 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
74 { NULL, NULL, NULL, NULL, EmptyFuncs }
76 #undef EmptyFuncs
78 ///////////////////////////////////////////////////////
80 #define ALC_EFX_MAJOR_VERSION 0x20001
81 #define ALC_EFX_MINOR_VERSION 0x20002
82 #define ALC_MAX_AUXILIARY_SENDS 0x20003
84 ///////////////////////////////////////////////////////
85 // STRING and EXTENSIONS
87 typedef struct ALCfunction_struct
89 ALCchar *funcName;
90 ALvoid *address;
91 } ALCfunction;
93 static ALCfunction alcFunctions[] = {
94 { "alcCreateContext", (ALvoid *) alcCreateContext },
95 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
96 { "alcProcessContext", (ALvoid *) alcProcessContext },
97 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
98 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
99 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
100 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
101 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
102 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
103 { "alcGetError", (ALvoid *) alcGetError },
104 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
105 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
106 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
107 { "alcGetString", (ALvoid *) alcGetString },
108 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
109 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
110 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
111 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
112 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
113 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
115 { "alcMakeCurrent", (ALvoid *) alcMakeCurrent },
116 { "alcGetThreadContext", (ALvoid *) alcGetThreadContext },
118 { NULL, (ALvoid *) NULL }
121 static ALenums enumeration[]={
122 // Types
123 { (ALchar *)"ALC_INVALID", ALC_INVALID },
124 { (ALchar *)"ALC_FALSE", ALC_FALSE },
125 { (ALchar *)"ALC_TRUE", ALC_TRUE },
127 // ALC Properties
128 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
129 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
130 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
131 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
132 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
133 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
134 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
135 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
136 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
137 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
138 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
139 { (ALchar *)"ALC_SYNC", ALC_SYNC },
140 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
141 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
142 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
143 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
144 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
146 // EFX Properties
147 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
148 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
149 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
151 // ALC Error Message
152 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
153 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
154 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
155 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
156 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
157 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
158 { (ALchar *)NULL, (ALenum)0 }
160 // Error strings
161 static const ALCchar alcNoError[] = "No Error";
162 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
163 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
164 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
165 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
166 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
168 /* Device lists. Sizes only include the first ending null character, not the
169 * second */
170 static ALCchar *alcDeviceList;
171 static ALCuint alcDeviceListSize;
172 static ALCchar *alcAllDeviceList;
173 static ALCuint alcAllDeviceListSize;
174 static ALCchar *alcCaptureDeviceList;
175 static ALCuint alcCaptureDeviceListSize;
176 // Default is always the first in the list
177 static ALCchar *alcDefaultDeviceSpecifier;
178 static ALCchar *alcDefaultAllDeviceSpecifier;
179 static ALCchar *alcCaptureDefaultDeviceSpecifier;
182 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_disconnect ALC_EXT_EFX ALC_EXTX_thread_local_context";
183 static ALCint alcMajorVersion = 1;
184 static ALCint alcMinorVersion = 1;
186 static ALCint alcEFXMajorVersion = 1;
187 static ALCint alcEFXMinorVersion = 0;
189 ///////////////////////////////////////////////////////
192 ///////////////////////////////////////////////////////
193 // Global Variables
195 static ALCdevice *g_pDeviceList = NULL;
196 static ALCuint g_ulDeviceCount = 0;
198 static CRITICAL_SECTION g_csMutex;
200 // Context List
201 static ALCcontext *g_pContextList = NULL;
202 static ALCuint g_ulContextCount = 0;
204 // Thread-local current context
205 static tls_type LocalContext;
207 // Context Error
208 static ALCenum g_eLastContextError = ALC_NO_ERROR;
210 ///////////////////////////////////////////////////////
213 ///////////////////////////////////////////////////////
214 // ALC Related helper functions
215 #ifdef _WIN32
216 static void alc_init(void);
217 static void alc_deinit(void);
219 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
221 (void)lpReserved;
223 // Perform actions based on the reason for calling.
224 switch(ul_reason_for_call)
226 case DLL_PROCESS_ATTACH:
227 DisableThreadLibraryCalls(hModule);
228 alc_init();
229 break;
231 case DLL_PROCESS_DETACH:
232 alc_deinit();
233 break;
235 return TRUE;
237 #else
238 #ifdef HAVE_GCC_DESTRUCTOR
239 static void alc_init(void) __attribute__((constructor));
240 static void alc_deinit(void) __attribute__((destructor));
241 #endif
242 #endif
244 static void alc_init(void)
246 int i;
247 const char *devs, *str;
249 InitializeCriticalSection(&g_csMutex);
250 ALTHUNK_INIT();
251 ReadALConfig();
253 tls_create(&LocalContext);
255 devs = GetConfigValue(NULL, "drivers", "");
256 if(devs[0])
258 int n;
259 size_t len;
260 const char *next = devs;
262 i = 0;
263 do {
264 devs = next;
265 next = strchr(devs, ',');
267 if(!devs[0] || devs[0] == ',')
268 continue;
270 len = (next ? ((size_t)(next-devs)) : strlen(devs));
271 for(n = i;BackendList[n].Init;n++)
273 if(len == strlen(BackendList[n].name) &&
274 strncmp(BackendList[n].name, devs, len) == 0)
276 const char *name = BackendList[i].name;
277 void (*Init)(BackendFuncs*) = BackendList[i].Init;
279 BackendList[i].name = BackendList[n].name;
280 BackendList[i].Init = BackendList[n].Init;
282 BackendList[n].name = name;
283 BackendList[n].Init = Init;
285 i++;
288 } while(next++);
290 BackendList[i].name = NULL;
291 BackendList[i].Init = NULL;
292 BackendList[i].Deinit = NULL;
293 BackendList[i].Probe = NULL;
296 for(i = 0;BackendList[i].Init;i++)
298 BackendList[i].Init(&BackendList[i].Funcs);
300 BackendList[i].Probe(DEVICE_PROBE);
301 BackendList[i].Probe(ALL_DEVICE_PROBE);
302 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
305 str = GetConfigValue(NULL, "stereodup", "false");
306 DuplicateStereo = (strcasecmp(str, "true") == 0 ||
307 strcasecmp(str, "yes") == 0 ||
308 strcasecmp(str, "on") == 0 ||
309 atoi(str) != 0);
311 str = GetConfigValue(NULL, "excludefx", "");
312 if(str[0])
314 const struct {
315 const char *name;
316 int type;
317 } EffectList[] = {
318 { "eaxreverb", EAXREVERB },
319 { "reverb", REVERB },
320 { "echo", ECHO },
321 { NULL, 0 }
323 int n;
324 size_t len;
325 const char *next = str;
327 do {
328 str = next;
329 next = strchr(str, ',');
331 if(!str[0] || next == str)
332 continue;
334 len = (next ? ((size_t)(next-str)) : strlen(str));
335 for(n = 0;EffectList[n].name;n++)
337 if(len == strlen(EffectList[n].name) &&
338 strncmp(EffectList[n].name, str, len) == 0)
339 DisabledEffects[EffectList[n].type] = AL_TRUE;
341 } while(next++);
345 static void alc_deinit(void)
347 int i;
349 ReleaseALC();
351 for(i = 0;BackendList[i].Deinit;i++)
352 BackendList[i].Deinit();
354 tls_delete(LocalContext);
356 FreeALConfig();
357 ALTHUNK_EXIT();
358 DeleteCriticalSection(&g_csMutex);
362 static void ProbeDeviceList()
364 ALint i;
366 free(alcDeviceList); alcDeviceList = NULL;
367 alcDeviceListSize = 0;
369 for(i = 0;BackendList[i].Probe;i++)
370 BackendList[i].Probe(DEVICE_PROBE);
373 static void ProbeAllDeviceList()
375 ALint i;
377 free(alcAllDeviceList); alcAllDeviceList = NULL;
378 alcAllDeviceListSize = 0;
380 for(i = 0;BackendList[i].Probe;i++)
381 BackendList[i].Probe(ALL_DEVICE_PROBE);
384 static void ProbeCaptureDeviceList()
386 ALint i;
388 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
389 alcCaptureDeviceListSize = 0;
391 for(i = 0;BackendList[i].Probe;i++)
392 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
396 #define DECL_APPEND_LIST_FUNC(type) \
397 void Append##type##List(const ALCchar *name) \
399 ALCuint len = strlen(name); \
400 void *temp; \
402 if(len == 0) \
403 return; \
405 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
406 if(!temp) \
408 AL_PRINT("Realloc failed to add %s!\n", name); \
409 return; \
411 alc##type##List = temp; \
412 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
413 alc##type##ListSize += len+1; \
414 alc##type##List[alc##type##ListSize] = 0; \
417 DECL_APPEND_LIST_FUNC(Device)
418 DECL_APPEND_LIST_FUNC(AllDevice)
419 DECL_APPEND_LIST_FUNC(CaptureDevice)
423 IsDevice
425 Check pDevice is a valid Device pointer
427 static ALCboolean IsDevice(ALCdevice *pDevice)
429 ALCdevice *pTempDevice;
431 SuspendContext(NULL);
433 pTempDevice = g_pDeviceList;
434 while(pTempDevice && pTempDevice != pDevice)
435 pTempDevice = pTempDevice->next;
437 ProcessContext(NULL);
439 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
443 IsContext
445 Check pContext is a valid Context pointer
447 static ALCboolean IsContext(ALCcontext *pContext)
449 ALCcontext *pTempContext;
451 SuspendContext(NULL);
453 pTempContext = g_pContextList;
454 while (pTempContext && pTempContext != pContext)
455 pTempContext = pTempContext->next;
457 ProcessContext(NULL);
459 return (pTempContext ? ALC_TRUE : ALC_FALSE);
464 SetALCError
466 Store latest ALC Error
468 ALCvoid SetALCError(ALenum errorCode)
470 g_eLastContextError = errorCode;
475 SuspendContext
477 Thread-safe entry
479 ALCvoid SuspendContext(ALCcontext *pContext)
481 (void)pContext;
482 EnterCriticalSection(&g_csMutex);
487 ProcessContext
489 Thread-safe exit
491 ALCvoid ProcessContext(ALCcontext *pContext)
493 (void)pContext;
494 LeaveCriticalSection(&g_csMutex);
499 GetContextSuspended
501 Returns the currently active Context, in a locked state
503 ALCcontext *GetContextSuspended(void)
505 ALCcontext *pContext = NULL;
507 SuspendContext(NULL);
509 pContext = tls_get(LocalContext);
510 if(pContext && !IsContext(pContext))
512 tls_set(LocalContext, NULL);
513 pContext = NULL;
515 if(!pContext)
517 pContext = g_pContextList;
518 while(pContext && !pContext->InUse)
519 pContext = pContext->next;
521 if(pContext)
522 SuspendContext(pContext);
524 ProcessContext(NULL);
526 return pContext;
531 InitContext
533 Initialize Context variables
535 static ALvoid InitContext(ALCcontext *pContext)
537 int level;
539 //Initialise listener
540 pContext->Listener.Gain = 1.0f;
541 pContext->Listener.MetersPerUnit = 1.0f;
542 pContext->Listener.Position[0] = 0.0f;
543 pContext->Listener.Position[1] = 0.0f;
544 pContext->Listener.Position[2] = 0.0f;
545 pContext->Listener.Velocity[0] = 0.0f;
546 pContext->Listener.Velocity[1] = 0.0f;
547 pContext->Listener.Velocity[2] = 0.0f;
548 pContext->Listener.Forward[0] = 0.0f;
549 pContext->Listener.Forward[1] = 0.0f;
550 pContext->Listener.Forward[2] = -1.0f;
551 pContext->Listener.Up[0] = 0.0f;
552 pContext->Listener.Up[1] = 1.0f;
553 pContext->Listener.Up[2] = 0.0f;
555 //Validate pContext
556 pContext->LastError = AL_NO_ERROR;
557 pContext->InUse = AL_FALSE;
559 //Set output format
560 pContext->Frequency = pContext->Device->Frequency;
562 //Set globals
563 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
564 pContext->DopplerFactor = 1.0f;
565 pContext->DopplerVelocity = 1.0f;
566 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
568 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";
570 level = GetConfigValueInt(NULL, "cf_level", 0);
571 if(level > 0 && level <= 6)
573 pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
574 bs2b_set_srate(pContext->bs2b, pContext->Frequency);
575 bs2b_set_level(pContext->bs2b, level);
578 aluInitPanning(pContext);
583 ExitContext
585 Clean up Context, destroy any remaining Sources
587 static ALCvoid ExitContext(ALCcontext *pContext)
589 //Invalidate context
590 pContext->LastError = AL_NO_ERROR;
591 pContext->InUse = AL_FALSE;
593 free(pContext->bs2b);
594 pContext->bs2b = NULL;
597 ///////////////////////////////////////////////////////
600 ///////////////////////////////////////////////////////
601 // ALC Functions calls
604 // This should probably move to another c file but for now ...
605 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
607 ALCboolean DeviceFound = ALC_FALSE;
608 ALCdevice *pDevice = NULL;
609 ALCint i;
611 if(SampleSize <= 0)
613 SetALCError(ALC_INVALID_VALUE);
614 return NULL;
617 if(deviceName && !deviceName[0])
618 deviceName = NULL;
620 pDevice = malloc(sizeof(ALCdevice));
621 if (pDevice)
623 //Initialise device structure
624 memset(pDevice, 0, sizeof(ALCdevice));
626 //Validate device
627 pDevice->Connected = ALC_TRUE;
628 pDevice->IsCaptureDevice = AL_TRUE;
630 pDevice->szDeviceName = NULL;
632 pDevice->Frequency = frequency;
633 pDevice->Format = format;
634 pDevice->BufferSize = SampleSize;
636 SuspendContext(NULL);
637 for(i = 0;BackendList[i].Init;i++)
639 pDevice->Funcs = &BackendList[i].Funcs;
640 if(ALCdevice_OpenCapture(pDevice, deviceName))
642 pDevice->next = g_pDeviceList;
643 g_pDeviceList = pDevice;
644 g_ulDeviceCount++;
646 DeviceFound = ALC_TRUE;
647 break;
650 ProcessContext(NULL);
652 if(!DeviceFound)
654 SetALCError(ALC_INVALID_VALUE);
655 free(pDevice);
656 pDevice = NULL;
659 else
660 SetALCError(ALC_OUT_OF_MEMORY);
662 return pDevice;
665 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
667 ALCboolean bReturn = ALC_FALSE;
668 ALCdevice **list;
670 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
672 SuspendContext(NULL);
674 list = &g_pDeviceList;
675 while(*list != pDevice)
676 list = &(*list)->next;
678 *list = (*list)->next;
679 g_ulDeviceCount--;
681 ProcessContext(NULL);
683 free(pDevice->szDeviceName);
685 ALCdevice_CloseCapture(pDevice);
686 free(pDevice);
688 bReturn = ALC_TRUE;
690 else
691 SetALCError(ALC_INVALID_DEVICE);
693 return bReturn;
696 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
698 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
699 ALCdevice_StartCapture(pDevice);
700 else
701 SetALCError(ALC_INVALID_DEVICE);
704 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
706 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
707 ALCdevice_StopCapture(pDevice);
708 else
709 SetALCError(ALC_INVALID_DEVICE);
712 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
714 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
715 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
716 else
717 SetALCError(ALC_INVALID_DEVICE);
721 alcGetError
723 Return last ALC generated error code
725 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
727 ALCenum errorCode;
729 (void)device;
731 errorCode = g_eLastContextError;
732 g_eLastContextError = ALC_NO_ERROR;
733 return errorCode;
738 alcSuspendContext
740 Not functional
742 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
744 // Not a lot happens here !
745 (void)pContext;
750 alcProcessContext
752 Not functional
754 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
756 // Not a lot happens here !
757 (void)pContext;
762 alcGetString
764 Returns information about the Device, and error strings
766 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
768 const ALCchar *value = NULL;
770 switch (param)
772 case ALC_NO_ERROR:
773 value = alcNoError;
774 break;
776 case ALC_INVALID_ENUM:
777 value = alcErrInvalidEnum;
778 break;
780 case ALC_INVALID_VALUE:
781 value = alcErrInvalidValue;
782 break;
784 case ALC_INVALID_DEVICE:
785 value = alcErrInvalidDevice;
786 break;
788 case ALC_INVALID_CONTEXT:
789 value = alcErrInvalidContext;
790 break;
792 case ALC_OUT_OF_MEMORY:
793 value = alcErrOutOfMemory;
794 break;
796 case ALC_DEVICE_SPECIFIER:
797 if(IsDevice(pDevice))
798 value = pDevice->szDeviceName;
799 else
801 ProbeDeviceList();
802 value = alcDeviceList;
804 break;
806 case ALC_ALL_DEVICES_SPECIFIER:
807 ProbeAllDeviceList();
808 value = alcAllDeviceList;
809 break;
811 case ALC_CAPTURE_DEVICE_SPECIFIER:
812 if(IsDevice(pDevice))
813 value = pDevice->szDeviceName;
814 else
816 ProbeCaptureDeviceList();
817 value = alcCaptureDeviceList;
819 break;
821 /* Default devices are always first in the list */
822 case ALC_DEFAULT_DEVICE_SPECIFIER:
823 free(alcDefaultDeviceSpecifier);
824 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
825 if(!alcDefaultDeviceSpecifier)
826 SetALCError(ALC_OUT_OF_MEMORY);
827 value = alcDefaultDeviceSpecifier;
828 break;
830 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
831 free(alcDefaultAllDeviceSpecifier);
832 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
833 alcAllDeviceList : "");
834 if(!alcDefaultAllDeviceSpecifier)
835 SetALCError(ALC_OUT_OF_MEMORY);
836 value = alcDefaultAllDeviceSpecifier;
837 break;
839 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
840 free(alcCaptureDefaultDeviceSpecifier);
841 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
842 alcCaptureDeviceList : "");
843 if(!alcCaptureDefaultDeviceSpecifier)
844 SetALCError(ALC_OUT_OF_MEMORY);
845 value = alcCaptureDefaultDeviceSpecifier;
846 break;
848 case ALC_EXTENSIONS:
849 value = alcExtensionList;
850 break;
852 default:
853 SetALCError(ALC_INVALID_ENUM);
854 break;
857 return value;
862 alcGetIntegerv
864 Returns information about the Device and the version of Open AL
866 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
868 if(IsDevice(device) && device->IsCaptureDevice)
870 SuspendContext(NULL);
872 // Capture device
873 switch (param)
875 case ALC_CAPTURE_SAMPLES:
876 if ((size) && (data))
877 *data = ALCdevice_AvailableSamples(device);
878 else
879 SetALCError(ALC_INVALID_VALUE);
880 break;
882 case ALC_CONNECTED:
883 if(size <= 0)
884 SetALCError(ALC_INVALID_VALUE);
885 else
886 *data = device->Connected;
887 break;
889 default:
890 SetALCError(ALC_INVALID_ENUM);
891 break;
894 ProcessContext(NULL);
896 else
898 if(data)
900 // Playback Device
901 switch (param)
903 case ALC_MAJOR_VERSION:
904 if(size <= 0)
905 SetALCError(ALC_INVALID_VALUE);
906 else
907 *data = alcMajorVersion;
908 break;
910 case ALC_MINOR_VERSION:
911 if(size <= 0)
912 SetALCError(ALC_INVALID_VALUE);
913 else
914 *data = alcMinorVersion;
915 break;
917 case ALC_EFX_MAJOR_VERSION:
918 if(size <= 0)
919 SetALCError(ALC_INVALID_VALUE);
920 else
921 *data = alcEFXMajorVersion;
922 break;
924 case ALC_EFX_MINOR_VERSION:
925 if(size <= 0)
926 SetALCError(ALC_INVALID_VALUE);
927 else
928 *data = alcEFXMinorVersion;
929 break;
931 case ALC_MAX_AUXILIARY_SENDS:
932 if(size <= 0)
933 SetALCError(ALC_INVALID_VALUE);
934 else
935 *data = (device?device->NumAuxSends:MAX_SENDS);
936 break;
938 case ALC_ATTRIBUTES_SIZE:
939 if(!IsDevice(device))
940 SetALCError(ALC_INVALID_DEVICE);
941 else if(size <= 0)
942 SetALCError(ALC_INVALID_VALUE);
943 else
944 *data = 13;
945 break;
947 case ALC_ALL_ATTRIBUTES:
948 if(!IsDevice(device))
949 SetALCError(ALC_INVALID_DEVICE);
950 else if (size < 13)
951 SetALCError(ALC_INVALID_VALUE);
952 else
954 int i = 0;
956 SuspendContext(NULL);
957 data[i++] = ALC_FREQUENCY;
958 data[i++] = device->Frequency;
960 data[i++] = ALC_REFRESH;
961 data[i++] = device->Frequency / device->UpdateSize;
963 data[i++] = ALC_SYNC;
964 data[i++] = ALC_FALSE;
966 data[i++] = ALC_MONO_SOURCES;
967 data[i++] = device->lNumMonoSources;
969 data[i++] = ALC_STEREO_SOURCES;
970 data[i++] = device->lNumStereoSources;
972 data[i++] = ALC_MAX_AUXILIARY_SENDS;
973 data[i++] = device->NumAuxSends;
975 data[i++] = 0;
976 ProcessContext(NULL);
978 break;
980 case ALC_FREQUENCY:
981 if(!IsDevice(device))
982 SetALCError(ALC_INVALID_DEVICE);
983 else if(size <= 0)
984 SetALCError(ALC_INVALID_VALUE);
985 else
986 *data = device->Frequency;
987 break;
989 case ALC_REFRESH:
990 if(!IsDevice(device))
991 SetALCError(ALC_INVALID_DEVICE);
992 else if(size <= 0)
993 SetALCError(ALC_INVALID_VALUE);
994 else
995 *data = device->Frequency / device->UpdateSize;
996 break;
998 case ALC_SYNC:
999 if(!IsDevice(device))
1000 SetALCError(ALC_INVALID_DEVICE);
1001 else if(size <= 0)
1002 SetALCError(ALC_INVALID_VALUE);
1003 else
1004 *data = ALC_FALSE;
1005 break;
1007 case ALC_MONO_SOURCES:
1008 if(!IsDevice(device))
1009 SetALCError(ALC_INVALID_DEVICE);
1010 else if(size <= 0)
1011 SetALCError(ALC_INVALID_VALUE);
1012 else
1013 *data = device->lNumMonoSources;
1014 break;
1016 case ALC_STEREO_SOURCES:
1017 if(!IsDevice(device))
1018 SetALCError(ALC_INVALID_DEVICE);
1019 else if(size <= 0)
1020 SetALCError(ALC_INVALID_VALUE);
1021 else
1022 *data = device->lNumStereoSources;
1023 break;
1025 case ALC_CONNECTED:
1026 if(!IsDevice(device))
1027 SetALCError(ALC_INVALID_DEVICE);
1028 else if(size <= 0)
1029 SetALCError(ALC_INVALID_VALUE);
1030 else
1031 *data = device->Connected;
1032 break;
1034 default:
1035 SetALCError(ALC_INVALID_ENUM);
1036 break;
1039 else if(size)
1040 SetALCError(ALC_INVALID_VALUE);
1043 return;
1048 alcIsExtensionPresent
1050 Determines if there is support for a particular extension
1052 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1054 ALCboolean bResult = ALC_FALSE;
1056 (void)device;
1058 if (extName)
1060 const char *ptr;
1061 size_t len;
1063 len = strlen(extName);
1064 ptr = alcExtensionList;
1065 while(ptr && *ptr)
1067 if(strncasecmp(ptr, extName, len) == 0 &&
1068 (ptr[len] == '\0' || isspace(ptr[len])))
1070 bResult = ALC_TRUE;
1071 break;
1073 if((ptr=strchr(ptr, ' ')) != NULL)
1075 do {
1076 ++ptr;
1077 } while(isspace(*ptr));
1081 else
1082 SetALCError(ALC_INVALID_VALUE);
1084 return bResult;
1089 alcGetProcAddress
1091 Retrieves the function address for a particular extension function
1093 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1095 ALCvoid *pFunction = NULL;
1096 ALsizei i = 0;
1098 (void)device;
1100 if (funcName)
1102 while(alcFunctions[i].funcName &&
1103 strcmp(alcFunctions[i].funcName,funcName) != 0)
1104 i++;
1105 pFunction = alcFunctions[i].address;
1107 else
1108 SetALCError(ALC_INVALID_VALUE);
1110 return pFunction;
1115 alcGetEnumValue
1117 Get the value for a particular ALC Enumerated Value
1119 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1121 ALsizei i = 0;
1122 ALCenum val;
1124 (void)device;
1126 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1127 i++;
1128 val = enumeration[i].value;
1130 if(!enumeration[i].enumName)
1131 SetALCError(ALC_INVALID_VALUE);
1133 return val;
1138 alcCreateContext
1140 Create and attach a Context to a particular Device.
1142 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1144 ALCcontext *ALContext = NULL;
1145 ALuint ulAttributeIndex, ulRequestedStereoSources;
1146 ALuint RequestedSends;
1148 if(IsDevice(device) && !device->IsCaptureDevice && device->Connected)
1150 // Reset Context Last Error code
1151 g_eLastContextError = ALC_NO_ERROR;
1153 // Current implementation only allows one Context per Device
1154 if(!device->Context)
1156 ALContext = calloc(1, sizeof(ALCcontext));
1157 if(!ALContext)
1159 SetALCError(ALC_OUT_OF_MEMORY);
1160 return NULL;
1163 SuspendContext(NULL);
1165 ALContext->Device = device;
1166 InitContext(ALContext);
1168 device->Context = ALContext;
1170 ALContext->next = g_pContextList;
1171 g_pContextList = ALContext;
1172 g_ulContextCount++;
1174 // Check for attributes
1175 if (attrList)
1177 ALCuint freq = device->Frequency;
1178 ALCint numMono = device->lNumMonoSources;
1179 ALCint numStereo = device->lNumStereoSources;
1180 ALCuint numSends = device->NumAuxSends;
1182 ulAttributeIndex = 0;
1183 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1185 if(attrList[ulAttributeIndex] == ALC_FREQUENCY)
1187 freq = attrList[ulAttributeIndex + 1];
1188 if(freq == 0)
1189 freq = device->Frequency;
1192 if(attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1194 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1196 if (ulRequestedStereoSources > device->MaxNoOfSources)
1197 ulRequestedStereoSources = device->MaxNoOfSources;
1199 numStereo = ulRequestedStereoSources;
1200 numMono = device->MaxNoOfSources - numStereo;
1203 if(attrList[ulAttributeIndex] == ALC_MAX_AUXILIARY_SENDS)
1205 RequestedSends = attrList[ulAttributeIndex + 1];
1207 if(RequestedSends > device->NumAuxSends)
1208 RequestedSends = device->NumAuxSends;
1210 numSends = RequestedSends;
1213 ulAttributeIndex += 2;
1216 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1217 device->lNumMonoSources = numMono;
1218 device->lNumStereoSources = numStereo;
1219 device->NumAuxSends = numSends;
1222 if(ALCdevice_StartContext(device, ALContext) == ALC_FALSE)
1224 alcDestroyContext(ALContext);
1225 ALContext = NULL;
1226 SetALCError(ALC_INVALID_VALUE);
1228 else
1229 ALContext->Frequency = device->Frequency;
1231 ProcessContext(NULL);
1233 else
1235 SetALCError(ALC_INVALID_VALUE);
1236 ALContext = NULL;
1239 else
1240 SetALCError(ALC_INVALID_DEVICE);
1242 return ALContext;
1247 alcDestroyContext
1249 Remove a Context
1251 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1253 ALCcontext **list;
1255 if (IsContext(context))
1257 ALCdevice_StopContext(context->Device, context);
1259 // Lock context
1260 SuspendContext(context);
1262 if(context->SourceCount > 0)
1264 #ifdef _DEBUG
1265 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1266 #endif
1267 ReleaseALSources(context);
1269 if(context->AuxiliaryEffectSlotCount > 0)
1271 #ifdef _DEBUG
1272 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1273 #endif
1274 ReleaseALAuxiliaryEffectSlots(context);
1277 context->Device->Context = NULL;
1279 list = &g_pContextList;
1280 while(*list != context)
1281 list = &(*list)->next;
1283 *list = (*list)->next;
1284 g_ulContextCount--;
1286 // Unlock context
1287 ProcessContext(context);
1289 ExitContext(context);
1291 // Free memory (MUST do this after ProcessContext)
1292 memset(context, 0, sizeof(ALCcontext));
1293 free(context);
1295 else
1296 SetALCError(ALC_INVALID_CONTEXT);
1301 alcGetCurrentContext
1303 Returns the currently active Context
1305 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1307 ALCcontext *pContext;
1309 if((pContext=GetContextSuspended()) != NULL)
1310 ProcessContext(pContext);
1312 return pContext;
1316 alcGetThreadContext
1318 Returns the currently active thread-local Context
1320 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1322 ALCcontext *pContext = NULL;
1324 SuspendContext(NULL);
1326 pContext = tls_get(LocalContext);
1327 if(pContext && !IsContext(pContext))
1329 tls_set(LocalContext, NULL);
1330 pContext = NULL;
1333 ProcessContext(NULL);
1335 return pContext;
1340 alcGetContextsDevice
1342 Returns the Device that a particular Context is attached to
1344 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1346 ALCdevice *pDevice = NULL;
1348 SuspendContext(NULL);
1349 if (IsContext(pContext))
1350 pDevice = pContext->Device;
1351 else
1352 SetALCError(ALC_INVALID_CONTEXT);
1353 ProcessContext(NULL);
1355 return pDevice;
1360 alcMakeContextCurrent
1362 Makes the given Context the active Context
1364 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1366 ALCcontext *ALContext;
1367 ALboolean bReturn = AL_TRUE;
1369 SuspendContext(NULL);
1371 // context must be a valid Context or NULL
1372 if(context == NULL || IsContext(context))
1374 if((ALContext=GetContextSuspended()) != NULL)
1376 ALContext->InUse=AL_FALSE;
1377 ProcessContext(ALContext);
1380 if((ALContext=context) != NULL && ALContext->Device)
1382 SuspendContext(ALContext);
1383 ALContext->InUse=AL_TRUE;
1384 ProcessContext(ALContext);
1387 tls_set(LocalContext, NULL);
1389 else
1391 SetALCError(ALC_INVALID_CONTEXT);
1392 bReturn = AL_FALSE;
1395 ProcessContext(NULL);
1397 return bReturn;
1401 alcMakeCurrent
1403 Makes the given Context the active Context for the current thread
1405 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1407 ALboolean bReturn = AL_TRUE;
1409 SuspendContext(NULL);
1411 // context must be a valid Context or NULL
1412 if(context == NULL || IsContext(context))
1413 tls_set(LocalContext, context);
1414 else
1416 SetALCError(ALC_INVALID_CONTEXT);
1417 bReturn = AL_FALSE;
1420 ProcessContext(NULL);
1422 return bReturn;
1426 static ALenum GetFormatFromString(const char *str)
1428 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1429 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1430 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1431 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1432 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1433 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1435 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1436 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1437 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1438 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1439 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1440 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1442 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1443 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1444 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1445 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1446 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1447 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1449 AL_PRINT("Unknown format: \"%s\"\n", str);
1450 return AL_FORMAT_STEREO16;
1454 alcOpenDevice
1456 Open the Device specified.
1458 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1460 ALboolean bDeviceFound = AL_FALSE;
1461 ALCdevice *device;
1462 ALint i;
1464 if(deviceName && !deviceName[0])
1465 deviceName = NULL;
1467 device = malloc(sizeof(ALCdevice));
1468 if (device)
1470 const char *fmt;
1472 //Initialise device structure
1473 memset(device, 0, sizeof(ALCdevice));
1475 //Validate device
1476 device->Connected = ALC_TRUE;
1477 device->IsCaptureDevice = AL_FALSE;
1479 device->szDeviceName = NULL;
1481 //Set output format
1482 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1483 if(device->Frequency == 0)
1484 device->Frequency = SWMIXER_OUTPUT_RATE;
1486 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1487 device->Format = GetFormatFromString(fmt);
1489 device->BufferSize = GetConfigValueInt(NULL, "refresh", 4096);
1490 if((ALint)device->BufferSize <= 0)
1491 device->BufferSize = 4096;
1493 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1494 if((ALint)device->MaxNoOfSources <= 0)
1495 device->MaxNoOfSources = 256;
1497 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1498 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1499 device->AuxiliaryEffectSlotMax = 4;
1501 device->lNumStereoSources = 1;
1502 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1504 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1505 if(device->NumAuxSends > MAX_SENDS)
1506 device->NumAuxSends = MAX_SENDS;
1508 // Find a playback device to open
1509 SuspendContext(NULL);
1510 for(i = 0;BackendList[i].Init;i++)
1512 device->Funcs = &BackendList[i].Funcs;
1513 if(ALCdevice_OpenPlayback(device, deviceName))
1515 device->next = g_pDeviceList;
1516 g_pDeviceList = device;
1517 g_ulDeviceCount++;
1519 bDeviceFound = AL_TRUE;
1520 break;
1523 ProcessContext(NULL);
1525 if (!bDeviceFound)
1527 // No suitable output device found
1528 SetALCError(ALC_INVALID_VALUE);
1529 free(device);
1530 device = NULL;
1533 else
1534 SetALCError(ALC_OUT_OF_MEMORY);
1536 return device;
1541 alcCloseDevice
1543 Close the specified Device
1545 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1547 ALCboolean bReturn = ALC_FALSE;
1548 ALCdevice **list;
1550 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1552 SuspendContext(NULL);
1554 list = &g_pDeviceList;
1555 while(*list != pDevice)
1556 list = &(*list)->next;
1558 *list = (*list)->next;
1559 g_ulDeviceCount--;
1561 ProcessContext(NULL);
1563 if(pDevice->Context)
1565 #ifdef _DEBUG
1566 AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
1567 #endif
1568 alcDestroyContext(pDevice->Context);
1570 ALCdevice_ClosePlayback(pDevice);
1572 if(pDevice->BufferCount > 0)
1574 #ifdef _DEBUG
1575 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1576 #endif
1577 ReleaseALBuffers(pDevice);
1579 if(pDevice->EffectCount > 0)
1581 #ifdef _DEBUG
1582 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1583 #endif
1584 ReleaseALEffects(pDevice);
1586 if(pDevice->FilterCount > 0)
1588 #ifdef _DEBUG
1589 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1590 #endif
1591 ReleaseALFilters(pDevice);
1593 if(pDevice->DatabufferCount > 0)
1595 #ifdef _DEBUG
1596 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1597 #endif
1598 ReleaseALDatabuffers(pDevice);
1601 free(pDevice->szDeviceName);
1603 //Release device structure
1604 memset(pDevice, 0, sizeof(ALCdevice));
1605 free(pDevice);
1607 bReturn = ALC_TRUE;
1609 else
1610 SetALCError(ALC_INVALID_DEVICE);
1612 return bReturn;
1616 ALCvoid ReleaseALC(ALCvoid)
1618 free(alcDeviceList); alcDeviceList = NULL;
1619 alcDeviceListSize = 0;
1620 free(alcAllDeviceList); alcAllDeviceList = NULL;
1621 alcAllDeviceListSize = 0;
1622 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1623 alcCaptureDeviceListSize = 0;
1625 free(alcDefaultDeviceSpecifier);
1626 alcDefaultDeviceSpecifier = NULL;
1627 free(alcDefaultAllDeviceSpecifier);
1628 alcDefaultAllDeviceSpecifier = NULL;
1629 free(alcCaptureDefaultDeviceSpecifier);
1630 alcCaptureDefaultDeviceSpecifier = NULL;
1632 #ifdef _DEBUG
1633 if(g_ulDeviceCount > 0)
1634 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1635 #endif
1637 while(g_pDeviceList)
1639 if(g_pDeviceList->IsCaptureDevice)
1640 alcCaptureCloseDevice(g_pDeviceList);
1641 else
1642 alcCloseDevice(g_pDeviceList);
1646 ///////////////////////////////////////////////////////