Get rid of deinit code duplication
[openal-soft.git] / Alc / ALc.c
blob40a2606dac91e5ca5d3a7990bb86b8c6e9ea51a0
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 static ALboolean init_done = AL_FALSE;
212 ///////////////////////////////////////////////////////
215 ///////////////////////////////////////////////////////
216 // ALC Related helper functions
217 #ifdef _WIN32
218 static void alc_deinit();
220 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
222 int i;
224 (void)lpReserved;
226 // Perform actions based on the reason for calling.
227 switch(ul_reason_for_call)
229 case DLL_PROCESS_ATTACH:
230 DisableThreadLibraryCalls(hModule);
231 break;
233 case DLL_PROCESS_DETACH:
234 alc_deinit();
235 break;
237 return TRUE;
239 #else
240 #ifdef HAVE_GCC_DESTRUCTOR
241 static void alc_deinit() __attribute__((destructor));
242 #endif
243 #endif
245 static void alc_deinit()
247 static ALenum once = AL_FALSE;
248 int i;
250 if(once || !init_done) return;
251 once = AL_TRUE;
253 ReleaseALC();
255 for(i = 0;BackendList[i].Deinit;i++)
256 BackendList[i].Deinit();
258 tls_delete(LocalContext);
260 FreeALConfig();
261 ALTHUNK_EXIT();
262 DeleteCriticalSection(&g_csMutex);
265 static void ProbeDeviceList()
267 ALint i;
269 free(alcDeviceList); alcDeviceList = NULL;
270 alcDeviceListSize = 0;
272 for(i = 0;BackendList[i].Probe;i++)
273 BackendList[i].Probe(DEVICE_PROBE);
276 static void ProbeAllDeviceList()
278 ALint i;
280 free(alcAllDeviceList); alcAllDeviceList = NULL;
281 alcAllDeviceListSize = 0;
283 for(i = 0;BackendList[i].Probe;i++)
284 BackendList[i].Probe(ALL_DEVICE_PROBE);
287 static void ProbeCaptureDeviceList()
289 ALint i;
291 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
292 alcCaptureDeviceListSize = 0;
294 for(i = 0;BackendList[i].Probe;i++)
295 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
298 static void InitAL(void)
300 if(!init_done)
302 int i;
303 const char *devs, *str;
305 init_done = AL_TRUE;
307 InitializeCriticalSection(&g_csMutex);
308 ALTHUNK_INIT();
309 ReadALConfig();
311 tls_create(&LocalContext);
313 devs = GetConfigValue(NULL, "drivers", "");
314 if(devs[0])
316 int n;
317 size_t len;
318 const char *next = devs;
320 i = 0;
322 do {
323 devs = next;
324 next = strchr(devs, ',');
326 if(!devs[0] || devs[0] == ',')
327 continue;
329 len = (next ? ((size_t)(next-devs)) : strlen(devs));
330 for(n = i;BackendList[n].Init;n++)
332 if(len == strlen(BackendList[n].name) &&
333 strncmp(BackendList[n].name, devs, len) == 0)
335 const char *name = BackendList[i].name;
336 void (*Init)(BackendFuncs*) = BackendList[i].Init;
338 BackendList[i].name = BackendList[n].name;
339 BackendList[i].Init = BackendList[n].Init;
341 BackendList[n].name = name;
342 BackendList[n].Init = Init;
344 i++;
347 } while(next++);
349 BackendList[i].name = NULL;
350 BackendList[i].Init = NULL;
353 for(i = 0;BackendList[i].Init;i++)
355 BackendList[i].Init(&BackendList[i].Funcs);
357 BackendList[i].Probe(DEVICE_PROBE);
358 BackendList[i].Probe(ALL_DEVICE_PROBE);
359 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
362 str = GetConfigValue(NULL, "stereodup", "false");
363 DuplicateStereo = (strcasecmp(str, "true") == 0 ||
364 strcasecmp(str, "yes") == 0 ||
365 strcasecmp(str, "on") == 0 ||
366 atoi(str) != 0);
368 str = GetConfigValue(NULL, "excludefx", "");
369 if(str[0])
371 const struct {
372 const char *name;
373 int type;
374 } EffectList[] = {
375 { "eaxreverb", EAXREVERB },
376 { "reverb", REVERB },
377 { "echo", ECHO },
378 { NULL, 0 }
380 int n;
381 size_t len;
382 const char *next = str;
384 do {
385 str = next;
386 next = strchr(str, ',');
388 if(!str[0] || next == str)
389 continue;
391 len = (next ? ((size_t)(next-str)) : strlen(str));
392 for(n = 0;EffectList[n].name;n++)
394 if(len == strlen(EffectList[n].name) &&
395 strncmp(EffectList[n].name, str, len) == 0)
396 DisabledEffects[EffectList[n].type] = AL_TRUE;
398 } while(next++);
404 #define DECL_APPEND_LIST_FUNC(type) \
405 void Append##type##List(const ALCchar *name) \
407 ALCuint len = strlen(name); \
408 void *temp; \
410 if(len == 0) \
411 return; \
413 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
414 if(!temp) \
416 AL_PRINT("Realloc failed to add %s!\n", name); \
417 return; \
419 alc##type##List = temp; \
420 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
421 alc##type##ListSize += len+1; \
422 alc##type##List[alc##type##ListSize] = 0; \
425 DECL_APPEND_LIST_FUNC(Device)
426 DECL_APPEND_LIST_FUNC(AllDevice)
427 DECL_APPEND_LIST_FUNC(CaptureDevice)
431 IsDevice
433 Check pDevice is a valid Device pointer
435 static ALCboolean IsDevice(ALCdevice *pDevice)
437 ALCdevice *pTempDevice;
439 SuspendContext(NULL);
441 pTempDevice = g_pDeviceList;
442 while(pTempDevice && pTempDevice != pDevice)
443 pTempDevice = pTempDevice->next;
445 ProcessContext(NULL);
447 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
451 IsContext
453 Check pContext is a valid Context pointer
455 static ALCboolean IsContext(ALCcontext *pContext)
457 ALCcontext *pTempContext;
459 SuspendContext(NULL);
461 pTempContext = g_pContextList;
462 while (pTempContext && pTempContext != pContext)
463 pTempContext = pTempContext->next;
465 ProcessContext(NULL);
467 return (pTempContext ? ALC_TRUE : ALC_FALSE);
472 SetALCError
474 Store latest ALC Error
476 ALCvoid SetALCError(ALenum errorCode)
478 g_eLastContextError = errorCode;
483 SuspendContext
485 Thread-safe entry
487 ALCvoid SuspendContext(ALCcontext *pContext)
489 (void)pContext;
490 EnterCriticalSection(&g_csMutex);
495 ProcessContext
497 Thread-safe exit
499 ALCvoid ProcessContext(ALCcontext *pContext)
501 (void)pContext;
502 LeaveCriticalSection(&g_csMutex);
507 GetContextSuspended
509 Returns the currently active Context, in a locked state
511 ALCcontext *GetContextSuspended(void)
513 ALCcontext *pContext = NULL;
515 SuspendContext(NULL);
517 pContext = tls_get(LocalContext);
518 if(pContext && !IsContext(pContext))
520 tls_set(LocalContext, NULL);
521 pContext = NULL;
523 if(!pContext)
525 pContext = g_pContextList;
526 while(pContext && !pContext->InUse)
527 pContext = pContext->next;
529 if(pContext)
530 SuspendContext(pContext);
532 ProcessContext(NULL);
534 return pContext;
539 InitContext
541 Initialize Context variables
543 static ALvoid InitContext(ALCcontext *pContext)
545 int level;
547 //Initialise listener
548 pContext->Listener.Gain = 1.0f;
549 pContext->Listener.MetersPerUnit = 1.0f;
550 pContext->Listener.Position[0] = 0.0f;
551 pContext->Listener.Position[1] = 0.0f;
552 pContext->Listener.Position[2] = 0.0f;
553 pContext->Listener.Velocity[0] = 0.0f;
554 pContext->Listener.Velocity[1] = 0.0f;
555 pContext->Listener.Velocity[2] = 0.0f;
556 pContext->Listener.Forward[0] = 0.0f;
557 pContext->Listener.Forward[1] = 0.0f;
558 pContext->Listener.Forward[2] = -1.0f;
559 pContext->Listener.Up[0] = 0.0f;
560 pContext->Listener.Up[1] = 1.0f;
561 pContext->Listener.Up[2] = 0.0f;
563 //Validate pContext
564 pContext->LastError = AL_NO_ERROR;
565 pContext->InUse = AL_FALSE;
567 //Set output format
568 pContext->Frequency = pContext->Device->Frequency;
570 //Set globals
571 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
572 pContext->DopplerFactor = 1.0f;
573 pContext->DopplerVelocity = 1.0f;
574 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
576 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";
578 level = GetConfigValueInt(NULL, "cf_level", 0);
579 if(level > 0 && level <= 6)
581 pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
582 bs2b_set_srate(pContext->bs2b, pContext->Frequency);
583 bs2b_set_level(pContext->bs2b, level);
586 aluInitPanning(pContext);
591 ExitContext
593 Clean up Context, destroy any remaining Sources
595 static ALCvoid ExitContext(ALCcontext *pContext)
597 //Invalidate context
598 pContext->LastError = AL_NO_ERROR;
599 pContext->InUse = AL_FALSE;
601 free(pContext->bs2b);
602 pContext->bs2b = NULL;
605 ///////////////////////////////////////////////////////
608 ///////////////////////////////////////////////////////
609 // ALC Functions calls
612 // This should probably move to another c file but for now ...
613 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
615 ALCboolean DeviceFound = ALC_FALSE;
616 ALCdevice *pDevice = NULL;
617 ALCint i;
619 InitAL();
621 if(SampleSize <= 0)
623 SetALCError(ALC_INVALID_VALUE);
624 return NULL;
627 if(deviceName && !deviceName[0])
628 deviceName = NULL;
630 pDevice = malloc(sizeof(ALCdevice));
631 if (pDevice)
633 //Initialise device structure
634 memset(pDevice, 0, sizeof(ALCdevice));
636 //Validate device
637 pDevice->Connected = ALC_TRUE;
638 pDevice->IsCaptureDevice = AL_TRUE;
640 pDevice->szDeviceName = NULL;
642 pDevice->Frequency = frequency;
643 pDevice->Format = format;
644 pDevice->BufferSize = SampleSize;
646 SuspendContext(NULL);
647 for(i = 0;BackendList[i].Init;i++)
649 pDevice->Funcs = &BackendList[i].Funcs;
650 if(ALCdevice_OpenCapture(pDevice, deviceName))
652 pDevice->next = g_pDeviceList;
653 g_pDeviceList = pDevice;
654 g_ulDeviceCount++;
656 DeviceFound = ALC_TRUE;
657 break;
660 ProcessContext(NULL);
662 if(!DeviceFound)
664 SetALCError(ALC_INVALID_VALUE);
665 free(pDevice);
666 pDevice = NULL;
669 else
670 SetALCError(ALC_OUT_OF_MEMORY);
672 return pDevice;
675 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
677 ALCboolean bReturn = ALC_FALSE;
678 ALCdevice **list;
680 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
682 SuspendContext(NULL);
684 list = &g_pDeviceList;
685 while(*list != pDevice)
686 list = &(*list)->next;
688 *list = (*list)->next;
689 g_ulDeviceCount--;
691 ProcessContext(NULL);
693 free(pDevice->szDeviceName);
695 ALCdevice_CloseCapture(pDevice);
696 free(pDevice);
698 bReturn = ALC_TRUE;
700 else
701 SetALCError(ALC_INVALID_DEVICE);
703 return bReturn;
706 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
708 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
709 ALCdevice_StartCapture(pDevice);
710 else
711 SetALCError(ALC_INVALID_DEVICE);
714 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
716 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
717 ALCdevice_StopCapture(pDevice);
718 else
719 SetALCError(ALC_INVALID_DEVICE);
722 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
724 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
725 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
726 else
727 SetALCError(ALC_INVALID_DEVICE);
731 alcGetError
733 Return last ALC generated error code
735 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
737 ALCenum errorCode;
739 (void)device;
741 errorCode = g_eLastContextError;
742 g_eLastContextError = ALC_NO_ERROR;
743 return errorCode;
748 alcSuspendContext
750 Not functional
752 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
754 // Not a lot happens here !
755 (void)pContext;
760 alcProcessContext
762 Not functional
764 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
766 // Not a lot happens here !
767 (void)pContext;
772 alcGetString
774 Returns information about the Device, and error strings
776 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
778 const ALCchar *value = NULL;
780 InitAL();
782 switch (param)
784 case ALC_NO_ERROR:
785 value = alcNoError;
786 break;
788 case ALC_INVALID_ENUM:
789 value = alcErrInvalidEnum;
790 break;
792 case ALC_INVALID_VALUE:
793 value = alcErrInvalidValue;
794 break;
796 case ALC_INVALID_DEVICE:
797 value = alcErrInvalidDevice;
798 break;
800 case ALC_INVALID_CONTEXT:
801 value = alcErrInvalidContext;
802 break;
804 case ALC_OUT_OF_MEMORY:
805 value = alcErrOutOfMemory;
806 break;
808 case ALC_DEVICE_SPECIFIER:
809 if(IsDevice(pDevice))
810 value = pDevice->szDeviceName;
811 else
813 ProbeDeviceList();
814 value = alcDeviceList;
816 break;
818 case ALC_ALL_DEVICES_SPECIFIER:
819 ProbeAllDeviceList();
820 value = alcAllDeviceList;
821 break;
823 case ALC_CAPTURE_DEVICE_SPECIFIER:
824 if(IsDevice(pDevice))
825 value = pDevice->szDeviceName;
826 else
828 ProbeCaptureDeviceList();
829 value = alcCaptureDeviceList;
831 break;
833 /* Default devices are always first in the list */
834 case ALC_DEFAULT_DEVICE_SPECIFIER:
835 free(alcDefaultDeviceSpecifier);
836 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
837 if(!alcDefaultDeviceSpecifier)
838 SetALCError(ALC_OUT_OF_MEMORY);
839 value = alcDefaultDeviceSpecifier;
840 break;
842 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
843 free(alcDefaultAllDeviceSpecifier);
844 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
845 alcAllDeviceList : "");
846 if(!alcDefaultAllDeviceSpecifier)
847 SetALCError(ALC_OUT_OF_MEMORY);
848 value = alcDefaultAllDeviceSpecifier;
849 break;
851 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
852 free(alcCaptureDefaultDeviceSpecifier);
853 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
854 alcCaptureDeviceList : "");
855 if(!alcCaptureDefaultDeviceSpecifier)
856 SetALCError(ALC_OUT_OF_MEMORY);
857 value = alcCaptureDefaultDeviceSpecifier;
858 break;
860 case ALC_EXTENSIONS:
861 value = alcExtensionList;
862 break;
864 default:
865 SetALCError(ALC_INVALID_ENUM);
866 break;
869 return value;
874 alcGetIntegerv
876 Returns information about the Device and the version of Open AL
878 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
880 InitAL();
882 if(IsDevice(device) && device->IsCaptureDevice)
884 SuspendContext(NULL);
886 // Capture device
887 switch (param)
889 case ALC_CAPTURE_SAMPLES:
890 if ((size) && (data))
891 *data = ALCdevice_AvailableSamples(device);
892 else
893 SetALCError(ALC_INVALID_VALUE);
894 break;
896 case ALC_CONNECTED:
897 if(size <= 0)
898 SetALCError(ALC_INVALID_VALUE);
899 else
900 *data = device->Connected;
901 break;
903 default:
904 SetALCError(ALC_INVALID_ENUM);
905 break;
908 ProcessContext(NULL);
910 else
912 if(data)
914 // Playback Device
915 switch (param)
917 case ALC_MAJOR_VERSION:
918 if(size <= 0)
919 SetALCError(ALC_INVALID_VALUE);
920 else
921 *data = alcMajorVersion;
922 break;
924 case ALC_MINOR_VERSION:
925 if(size <= 0)
926 SetALCError(ALC_INVALID_VALUE);
927 else
928 *data = alcMinorVersion;
929 break;
931 case ALC_EFX_MAJOR_VERSION:
932 if(size <= 0)
933 SetALCError(ALC_INVALID_VALUE);
934 else
935 *data = alcEFXMajorVersion;
936 break;
938 case ALC_EFX_MINOR_VERSION:
939 if(size <= 0)
940 SetALCError(ALC_INVALID_VALUE);
941 else
942 *data = alcEFXMinorVersion;
943 break;
945 case ALC_MAX_AUXILIARY_SENDS:
946 if(size <= 0)
947 SetALCError(ALC_INVALID_VALUE);
948 else
949 *data = (device?device->NumAuxSends:MAX_SENDS);
950 break;
952 case ALC_ATTRIBUTES_SIZE:
953 if(!IsDevice(device))
954 SetALCError(ALC_INVALID_DEVICE);
955 else if(size <= 0)
956 SetALCError(ALC_INVALID_VALUE);
957 else
958 *data = 13;
959 break;
961 case ALC_ALL_ATTRIBUTES:
962 if(!IsDevice(device))
963 SetALCError(ALC_INVALID_DEVICE);
964 else if (size < 13)
965 SetALCError(ALC_INVALID_VALUE);
966 else
968 int i = 0;
970 SuspendContext(NULL);
971 data[i++] = ALC_FREQUENCY;
972 data[i++] = device->Frequency;
974 data[i++] = ALC_REFRESH;
975 data[i++] = device->Frequency / device->UpdateSize;
977 data[i++] = ALC_SYNC;
978 data[i++] = ALC_FALSE;
980 data[i++] = ALC_MONO_SOURCES;
981 data[i++] = device->lNumMonoSources;
983 data[i++] = ALC_STEREO_SOURCES;
984 data[i++] = device->lNumStereoSources;
986 data[i++] = ALC_MAX_AUXILIARY_SENDS;
987 data[i++] = device->NumAuxSends;
989 data[i++] = 0;
990 ProcessContext(NULL);
992 break;
994 case ALC_FREQUENCY:
995 if(!IsDevice(device))
996 SetALCError(ALC_INVALID_DEVICE);
997 else if(size <= 0)
998 SetALCError(ALC_INVALID_VALUE);
999 else
1000 *data = device->Frequency;
1001 break;
1003 case ALC_REFRESH:
1004 if(!IsDevice(device))
1005 SetALCError(ALC_INVALID_DEVICE);
1006 else if(size <= 0)
1007 SetALCError(ALC_INVALID_VALUE);
1008 else
1009 *data = device->Frequency / device->UpdateSize;
1010 break;
1012 case ALC_SYNC:
1013 if(!IsDevice(device))
1014 SetALCError(ALC_INVALID_DEVICE);
1015 else if(size <= 0)
1016 SetALCError(ALC_INVALID_VALUE);
1017 else
1018 *data = ALC_FALSE;
1019 break;
1021 case ALC_MONO_SOURCES:
1022 if(!IsDevice(device))
1023 SetALCError(ALC_INVALID_DEVICE);
1024 else if(size <= 0)
1025 SetALCError(ALC_INVALID_VALUE);
1026 else
1027 *data = device->lNumMonoSources;
1028 break;
1030 case ALC_STEREO_SOURCES:
1031 if(!IsDevice(device))
1032 SetALCError(ALC_INVALID_DEVICE);
1033 else if(size <= 0)
1034 SetALCError(ALC_INVALID_VALUE);
1035 else
1036 *data = device->lNumStereoSources;
1037 break;
1039 case ALC_CONNECTED:
1040 if(!IsDevice(device))
1041 SetALCError(ALC_INVALID_DEVICE);
1042 else if(size <= 0)
1043 SetALCError(ALC_INVALID_VALUE);
1044 else
1045 *data = device->Connected;
1046 break;
1048 default:
1049 SetALCError(ALC_INVALID_ENUM);
1050 break;
1053 else if(size)
1054 SetALCError(ALC_INVALID_VALUE);
1057 return;
1062 alcIsExtensionPresent
1064 Determines if there is support for a particular extension
1066 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1068 ALCboolean bResult = ALC_FALSE;
1070 (void)device;
1072 if (extName)
1074 const char *ptr;
1075 size_t len;
1077 len = strlen(extName);
1078 ptr = alcExtensionList;
1079 while(ptr && *ptr)
1081 if(strncasecmp(ptr, extName, len) == 0 &&
1082 (ptr[len] == '\0' || isspace(ptr[len])))
1084 bResult = ALC_TRUE;
1085 break;
1087 if((ptr=strchr(ptr, ' ')) != NULL)
1089 do {
1090 ++ptr;
1091 } while(isspace(*ptr));
1095 else
1096 SetALCError(ALC_INVALID_VALUE);
1098 return bResult;
1103 alcGetProcAddress
1105 Retrieves the function address for a particular extension function
1107 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1109 ALCvoid *pFunction = NULL;
1110 ALsizei i = 0;
1112 (void)device;
1114 if (funcName)
1116 while(alcFunctions[i].funcName &&
1117 strcmp(alcFunctions[i].funcName,funcName) != 0)
1118 i++;
1119 pFunction = alcFunctions[i].address;
1121 else
1122 SetALCError(ALC_INVALID_VALUE);
1124 return pFunction;
1129 alcGetEnumValue
1131 Get the value for a particular ALC Enumerated Value
1133 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1135 ALsizei i = 0;
1136 ALCenum val;
1138 (void)device;
1140 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1141 i++;
1142 val = enumeration[i].value;
1144 if(!enumeration[i].enumName)
1145 SetALCError(ALC_INVALID_VALUE);
1147 return val;
1152 alcCreateContext
1154 Create and attach a Context to a particular Device.
1156 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1158 ALCcontext *ALContext = NULL;
1159 ALuint ulAttributeIndex, ulRequestedStereoSources;
1160 ALuint RequestedSends;
1162 if(IsDevice(device) && !device->IsCaptureDevice && device->Connected)
1164 // Reset Context Last Error code
1165 g_eLastContextError = ALC_NO_ERROR;
1167 // Current implementation only allows one Context per Device
1168 if(!device->Context)
1170 ALContext = calloc(1, sizeof(ALCcontext));
1171 if(!ALContext)
1173 SetALCError(ALC_OUT_OF_MEMORY);
1174 return NULL;
1177 SuspendContext(NULL);
1179 ALContext->Device = device;
1180 InitContext(ALContext);
1182 device->Context = ALContext;
1184 ALContext->next = g_pContextList;
1185 g_pContextList = ALContext;
1186 g_ulContextCount++;
1188 // Check for attributes
1189 if (attrList)
1191 ALCuint freq = device->Frequency;
1192 ALCint numMono = device->lNumMonoSources;
1193 ALCint numStereo = device->lNumStereoSources;
1194 ALCuint numSends = device->NumAuxSends;
1196 ulAttributeIndex = 0;
1197 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1199 if(attrList[ulAttributeIndex] == ALC_FREQUENCY)
1201 freq = attrList[ulAttributeIndex + 1];
1202 if(freq == 0)
1203 freq = device->Frequency;
1206 if(attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1208 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1210 if (ulRequestedStereoSources > device->MaxNoOfSources)
1211 ulRequestedStereoSources = device->MaxNoOfSources;
1213 numStereo = ulRequestedStereoSources;
1214 numMono = device->MaxNoOfSources - numStereo;
1217 if(attrList[ulAttributeIndex] == ALC_MAX_AUXILIARY_SENDS)
1219 RequestedSends = attrList[ulAttributeIndex + 1];
1221 if(RequestedSends > device->NumAuxSends)
1222 RequestedSends = device->NumAuxSends;
1224 numSends = RequestedSends;
1227 ulAttributeIndex += 2;
1230 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1231 device->lNumMonoSources = numMono;
1232 device->lNumStereoSources = numStereo;
1233 device->NumAuxSends = numSends;
1236 if(ALCdevice_StartContext(device, ALContext) == ALC_FALSE)
1238 alcDestroyContext(ALContext);
1239 ALContext = NULL;
1240 SetALCError(ALC_INVALID_VALUE);
1242 else
1243 ALContext->Frequency = device->Frequency;
1245 ProcessContext(NULL);
1247 else
1249 SetALCError(ALC_INVALID_VALUE);
1250 ALContext = NULL;
1253 else
1254 SetALCError(ALC_INVALID_DEVICE);
1256 return ALContext;
1261 alcDestroyContext
1263 Remove a Context
1265 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1267 ALCcontext **list;
1269 InitAL();
1271 if (IsContext(context))
1273 ALCdevice_StopContext(context->Device, context);
1275 // Lock context
1276 SuspendContext(context);
1278 if(context->SourceCount > 0)
1280 #ifdef _DEBUG
1281 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1282 #endif
1283 ReleaseALSources(context);
1285 if(context->AuxiliaryEffectSlotCount > 0)
1287 #ifdef _DEBUG
1288 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1289 #endif
1290 ReleaseALAuxiliaryEffectSlots(context);
1293 context->Device->Context = NULL;
1295 list = &g_pContextList;
1296 while(*list != context)
1297 list = &(*list)->next;
1299 *list = (*list)->next;
1300 g_ulContextCount--;
1302 // Unlock context
1303 ProcessContext(context);
1305 ExitContext(context);
1307 // Free memory (MUST do this after ProcessContext)
1308 memset(context, 0, sizeof(ALCcontext));
1309 free(context);
1311 else
1312 SetALCError(ALC_INVALID_CONTEXT);
1317 alcGetCurrentContext
1319 Returns the currently active Context
1321 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1323 ALCcontext *pContext;
1325 if((pContext=GetContextSuspended()) != NULL)
1326 ProcessContext(pContext);
1328 return pContext;
1332 alcGetThreadContext
1334 Returns the currently active thread-local Context
1336 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1338 ALCcontext *pContext = NULL;
1340 InitAL();
1342 SuspendContext(NULL);
1344 pContext = tls_get(LocalContext);
1345 if(pContext && !IsContext(pContext))
1347 tls_set(LocalContext, NULL);
1348 pContext = NULL;
1351 ProcessContext(NULL);
1353 return pContext;
1358 alcGetContextsDevice
1360 Returns the Device that a particular Context is attached to
1362 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1364 ALCdevice *pDevice = NULL;
1366 InitAL();
1368 SuspendContext(NULL);
1369 if (IsContext(pContext))
1370 pDevice = pContext->Device;
1371 else
1372 SetALCError(ALC_INVALID_CONTEXT);
1373 ProcessContext(NULL);
1375 return pDevice;
1380 alcMakeContextCurrent
1382 Makes the given Context the active Context
1384 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1386 ALCcontext *ALContext;
1387 ALboolean bReturn = AL_TRUE;
1389 InitAL();
1391 SuspendContext(NULL);
1393 // context must be a valid Context or NULL
1394 if(context == NULL || IsContext(context))
1396 if((ALContext=GetContextSuspended()) != NULL)
1398 ALContext->InUse=AL_FALSE;
1399 ProcessContext(ALContext);
1402 if((ALContext=context) != NULL && ALContext->Device)
1404 SuspendContext(ALContext);
1405 ALContext->InUse=AL_TRUE;
1406 ProcessContext(ALContext);
1409 tls_set(LocalContext, NULL);
1411 else
1413 SetALCError(ALC_INVALID_CONTEXT);
1414 bReturn = AL_FALSE;
1417 ProcessContext(NULL);
1419 return bReturn;
1423 alcMakeCurrent
1425 Makes the given Context the active Context for the current thread
1427 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1429 ALboolean bReturn = AL_TRUE;
1431 InitAL();
1433 SuspendContext(NULL);
1435 // context must be a valid Context or NULL
1436 if(context == NULL || IsContext(context))
1437 tls_set(LocalContext, context);
1438 else
1440 SetALCError(ALC_INVALID_CONTEXT);
1441 bReturn = AL_FALSE;
1444 ProcessContext(NULL);
1446 return bReturn;
1450 static ALenum GetFormatFromString(const char *str)
1452 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1453 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1454 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1455 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1456 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1457 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1459 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1460 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1461 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1462 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1463 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1464 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1466 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1467 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1468 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1469 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1470 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1471 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1473 AL_PRINT("Unknown format: \"%s\"\n", str);
1474 return AL_FORMAT_STEREO16;
1478 alcOpenDevice
1480 Open the Device specified.
1482 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1484 ALboolean bDeviceFound = AL_FALSE;
1485 ALCdevice *device;
1486 ALint i;
1488 InitAL();
1490 if(deviceName && !deviceName[0])
1491 deviceName = NULL;
1493 device = malloc(sizeof(ALCdevice));
1494 if (device)
1496 const char *fmt;
1498 //Initialise device structure
1499 memset(device, 0, sizeof(ALCdevice));
1501 //Validate device
1502 device->Connected = ALC_TRUE;
1503 device->IsCaptureDevice = AL_FALSE;
1505 device->szDeviceName = NULL;
1507 //Set output format
1508 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1509 if(device->Frequency == 0)
1510 device->Frequency = SWMIXER_OUTPUT_RATE;
1512 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1513 device->Format = GetFormatFromString(fmt);
1515 device->BufferSize = GetConfigValueInt(NULL, "refresh", 4096);
1516 if((ALint)device->BufferSize <= 0)
1517 device->BufferSize = 4096;
1519 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1520 if((ALint)device->MaxNoOfSources <= 0)
1521 device->MaxNoOfSources = 256;
1523 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1524 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1525 device->AuxiliaryEffectSlotMax = 4;
1527 device->lNumStereoSources = 1;
1528 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1530 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1531 if(device->NumAuxSends > MAX_SENDS)
1532 device->NumAuxSends = MAX_SENDS;
1534 // Find a playback device to open
1535 SuspendContext(NULL);
1536 for(i = 0;BackendList[i].Init;i++)
1538 device->Funcs = &BackendList[i].Funcs;
1539 if(ALCdevice_OpenPlayback(device, deviceName))
1541 device->next = g_pDeviceList;
1542 g_pDeviceList = device;
1543 g_ulDeviceCount++;
1545 bDeviceFound = AL_TRUE;
1546 break;
1549 ProcessContext(NULL);
1551 if (!bDeviceFound)
1553 // No suitable output device found
1554 SetALCError(ALC_INVALID_VALUE);
1555 free(device);
1556 device = NULL;
1559 else
1560 SetALCError(ALC_OUT_OF_MEMORY);
1562 return device;
1567 alcCloseDevice
1569 Close the specified Device
1571 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1573 ALCboolean bReturn = ALC_FALSE;
1574 ALCdevice **list;
1576 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1578 SuspendContext(NULL);
1580 list = &g_pDeviceList;
1581 while(*list != pDevice)
1582 list = &(*list)->next;
1584 *list = (*list)->next;
1585 g_ulDeviceCount--;
1587 ProcessContext(NULL);
1589 if(pDevice->Context)
1591 #ifdef _DEBUG
1592 AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
1593 #endif
1594 alcDestroyContext(pDevice->Context);
1596 ALCdevice_ClosePlayback(pDevice);
1598 if(pDevice->BufferCount > 0)
1600 #ifdef _DEBUG
1601 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1602 #endif
1603 ReleaseALBuffers(pDevice);
1605 if(pDevice->EffectCount > 0)
1607 #ifdef _DEBUG
1608 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1609 #endif
1610 ReleaseALEffects(pDevice);
1612 if(pDevice->FilterCount > 0)
1614 #ifdef _DEBUG
1615 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1616 #endif
1617 ReleaseALFilters(pDevice);
1619 if(pDevice->DatabufferCount > 0)
1621 #ifdef _DEBUG
1622 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1623 #endif
1624 ReleaseALDatabuffers(pDevice);
1627 free(pDevice->szDeviceName);
1629 //Release device structure
1630 memset(pDevice, 0, sizeof(ALCdevice));
1631 free(pDevice);
1633 bReturn = ALC_TRUE;
1635 else
1636 SetALCError(ALC_INVALID_DEVICE);
1638 return bReturn;
1642 ALCvoid ReleaseALC(ALCvoid)
1644 free(alcDeviceList); alcDeviceList = NULL;
1645 alcDeviceListSize = 0;
1646 free(alcAllDeviceList); alcAllDeviceList = NULL;
1647 alcAllDeviceListSize = 0;
1648 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1649 alcCaptureDeviceListSize = 0;
1651 free(alcDefaultDeviceSpecifier);
1652 alcDefaultDeviceSpecifier = NULL;
1653 free(alcDefaultAllDeviceSpecifier);
1654 alcDefaultAllDeviceSpecifier = NULL;
1655 free(alcCaptureDefaultDeviceSpecifier);
1656 alcCaptureDefaultDeviceSpecifier = NULL;
1658 #ifdef _DEBUG
1659 if(g_ulDeviceCount > 0)
1660 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1661 #endif
1663 while(g_pDeviceList)
1665 if(g_pDeviceList->IsCaptureDevice)
1666 alcCaptureCloseDevice(g_pDeviceList);
1667 else
1668 alcCloseDevice(g_pDeviceList);
1672 ///////////////////////////////////////////////////////