Update in properly-sized chunks for PulseAudio
[openal-soft.git] / Alc / ALc.c
blobff81d4b1d09507aea0ce94e6415c3bd0750428e4
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 typedef struct BackendInfo {
44 const char *name;
45 void (*Init)(BackendFuncs*);
46 void (*Deinit)(void);
47 void (*Probe)(int);
48 BackendFuncs Funcs;
49 } BackendInfo;
50 static BackendInfo BackendList[] = {
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_OSS
55 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_SOLARIS
58 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_DSOUND
61 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_WINMM
64 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PORTAUDIO
67 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_PULSEAUDIO
70 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
71 #endif
73 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
75 { NULL, NULL, NULL, NULL, EmptyFuncs }
77 #undef EmptyFuncs
79 ///////////////////////////////////////////////////////
81 #define ALC_EFX_MAJOR_VERSION 0x20001
82 #define ALC_EFX_MINOR_VERSION 0x20002
83 #define ALC_MAX_AUXILIARY_SENDS 0x20003
85 ///////////////////////////////////////////////////////
86 // STRING and EXTENSIONS
88 typedef struct ALCfunction_struct
90 ALCchar *funcName;
91 ALvoid *address;
92 } ALCfunction;
94 static ALCfunction alcFunctions[] = {
95 { "alcCreateContext", (ALvoid *) alcCreateContext },
96 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
97 { "alcProcessContext", (ALvoid *) alcProcessContext },
98 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
99 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
100 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
101 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
102 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
103 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
104 { "alcGetError", (ALvoid *) alcGetError },
105 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
106 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
107 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
108 { "alcGetString", (ALvoid *) alcGetString },
109 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
110 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
111 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
112 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
113 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
114 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
116 { "alcMakeCurrent", (ALvoid *) alcMakeCurrent },
117 { "alcGetThreadContext", (ALvoid *) alcGetThreadContext },
119 { NULL, (ALvoid *) NULL }
122 static ALenums enumeration[]={
123 // Types
124 { (ALchar *)"ALC_INVALID", ALC_INVALID },
125 { (ALchar *)"ALC_FALSE", ALC_FALSE },
126 { (ALchar *)"ALC_TRUE", ALC_TRUE },
128 // ALC Properties
129 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
130 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
131 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
132 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
133 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
134 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
135 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
136 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
137 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
138 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
139 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
140 { (ALchar *)"ALC_SYNC", ALC_SYNC },
141 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
142 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
143 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
144 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
145 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
147 // EFX Properties
148 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
149 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
150 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
152 // ALC Error Message
153 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
154 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
155 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
156 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
157 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
158 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
159 { (ALchar *)NULL, (ALenum)0 }
161 // Error strings
162 static const ALCchar alcNoError[] = "No Error";
163 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
164 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
165 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
166 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
167 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
169 /* Device lists. Sizes only include the first ending null character, not the
170 * second */
171 static ALCchar *alcDeviceList;
172 static ALCuint alcDeviceListSize;
173 static ALCchar *alcAllDeviceList;
174 static ALCuint alcAllDeviceListSize;
175 static ALCchar *alcCaptureDeviceList;
176 static ALCuint alcCaptureDeviceListSize;
177 // Default is always the first in the list
178 static ALCchar *alcDefaultDeviceSpecifier;
179 static ALCchar *alcDefaultAllDeviceSpecifier;
180 static ALCchar *alcCaptureDefaultDeviceSpecifier;
183 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_disconnect ALC_EXT_EFX ALC_EXTX_thread_local_context";
184 static ALCint alcMajorVersion = 1;
185 static ALCint alcMinorVersion = 1;
187 static ALCint alcEFXMajorVersion = 1;
188 static ALCint alcEFXMinorVersion = 0;
190 ///////////////////////////////////////////////////////
193 ///////////////////////////////////////////////////////
194 // Global Variables
196 static ALCdevice *g_pDeviceList = NULL;
197 static ALCuint g_ulDeviceCount = 0;
199 static CRITICAL_SECTION g_csMutex;
201 // Context List
202 static ALCcontext *g_pContextList = NULL;
203 static ALCuint g_ulContextCount = 0;
205 // Thread-local current context
206 static tls_type LocalContext;
208 // Context Error
209 static ALCenum g_eLastContextError = ALC_NO_ERROR;
211 ///////////////////////////////////////////////////////
214 ///////////////////////////////////////////////////////
215 // ALC Related helper functions
216 #ifdef _WIN32
217 static void alc_init(void);
218 static void alc_deinit(void);
220 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
222 (void)lpReserved;
224 // Perform actions based on the reason for calling.
225 switch(ul_reason_for_call)
227 case DLL_PROCESS_ATTACH:
228 DisableThreadLibraryCalls(hModule);
229 alc_init();
230 break;
232 case DLL_PROCESS_DETACH:
233 alc_deinit();
234 break;
236 return TRUE;
238 #else
239 #ifdef HAVE_GCC_DESTRUCTOR
240 static void alc_init(void) __attribute__((constructor));
241 static void alc_deinit(void) __attribute__((destructor));
242 #endif
243 #endif
245 static void alc_init(void)
247 int i;
248 const char *devs, *str;
250 InitializeCriticalSection(&g_csMutex);
251 ALTHUNK_INIT();
252 ReadALConfig();
254 tls_create(&LocalContext);
256 devs = GetConfigValue(NULL, "drivers", "");
257 if(devs[0])
259 int n;
260 size_t len;
261 const char *next = devs;
263 i = 0;
264 do {
265 devs = next;
266 next = strchr(devs, ',');
268 if(!devs[0] || devs[0] == ',')
269 continue;
271 len = (next ? ((size_t)(next-devs)) : strlen(devs));
272 for(n = i;BackendList[n].Init;n++)
274 if(len == strlen(BackendList[n].name) &&
275 strncmp(BackendList[n].name, devs, len) == 0)
277 BackendInfo Bkp = BackendList[i];
278 BackendList[i] = BackendList[n];
279 BackendList[n] = Bkp;
281 i++;
284 } while(next++);
286 BackendList[i].name = NULL;
287 BackendList[i].Init = NULL;
288 BackendList[i].Deinit = NULL;
289 BackendList[i].Probe = NULL;
292 for(i = 0;BackendList[i].Init;i++)
294 BackendList[i].Init(&BackendList[i].Funcs);
296 BackendList[i].Probe(DEVICE_PROBE);
297 BackendList[i].Probe(ALL_DEVICE_PROBE);
298 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
301 DuplicateStereo = GetConfigValueBool(NULL, "stereodup", 0);
303 str = GetConfigValue(NULL, "excludefx", "");
304 if(str[0])
306 const struct {
307 const char *name;
308 int type;
309 } EffectList[] = {
310 { "eaxreverb", EAXREVERB },
311 { "reverb", REVERB },
312 { "echo", ECHO },
313 { NULL, 0 }
315 int n;
316 size_t len;
317 const char *next = str;
319 do {
320 str = next;
321 next = strchr(str, ',');
323 if(!str[0] || next == str)
324 continue;
326 len = (next ? ((size_t)(next-str)) : strlen(str));
327 for(n = 0;EffectList[n].name;n++)
329 if(len == strlen(EffectList[n].name) &&
330 strncmp(EffectList[n].name, str, len) == 0)
331 DisabledEffects[EffectList[n].type] = AL_TRUE;
333 } while(next++);
337 static void alc_deinit(void)
339 int i;
341 ReleaseALC();
343 for(i = 0;BackendList[i].Deinit;i++)
344 BackendList[i].Deinit();
346 tls_delete(LocalContext);
348 FreeALConfig();
349 ALTHUNK_EXIT();
350 DeleteCriticalSection(&g_csMutex);
354 static void ProbeDeviceList()
356 ALint i;
358 free(alcDeviceList); alcDeviceList = NULL;
359 alcDeviceListSize = 0;
361 for(i = 0;BackendList[i].Probe;i++)
362 BackendList[i].Probe(DEVICE_PROBE);
365 static void ProbeAllDeviceList()
367 ALint i;
369 free(alcAllDeviceList); alcAllDeviceList = NULL;
370 alcAllDeviceListSize = 0;
372 for(i = 0;BackendList[i].Probe;i++)
373 BackendList[i].Probe(ALL_DEVICE_PROBE);
376 static void ProbeCaptureDeviceList()
378 ALint i;
380 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
381 alcCaptureDeviceListSize = 0;
383 for(i = 0;BackendList[i].Probe;i++)
384 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
388 #define DECL_APPEND_LIST_FUNC(type) \
389 void Append##type##List(const ALCchar *name) \
391 ALCuint len = strlen(name); \
392 void *temp; \
394 if(len == 0) \
395 return; \
397 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
398 if(!temp) \
400 AL_PRINT("Realloc failed to add %s!\n", name); \
401 return; \
403 alc##type##List = temp; \
404 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
405 alc##type##ListSize += len+1; \
406 alc##type##List[alc##type##ListSize] = 0; \
409 DECL_APPEND_LIST_FUNC(Device)
410 DECL_APPEND_LIST_FUNC(AllDevice)
411 DECL_APPEND_LIST_FUNC(CaptureDevice)
415 IsDevice
417 Check pDevice is a valid Device pointer
419 static ALCboolean IsDevice(ALCdevice *pDevice)
421 ALCdevice *pTempDevice;
423 SuspendContext(NULL);
425 pTempDevice = g_pDeviceList;
426 while(pTempDevice && pTempDevice != pDevice)
427 pTempDevice = pTempDevice->next;
429 ProcessContext(NULL);
431 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
435 IsContext
437 Check pContext is a valid Context pointer
439 static ALCboolean IsContext(ALCcontext *pContext)
441 ALCcontext *pTempContext;
443 SuspendContext(NULL);
445 pTempContext = g_pContextList;
446 while (pTempContext && pTempContext != pContext)
447 pTempContext = pTempContext->next;
449 ProcessContext(NULL);
451 return (pTempContext ? ALC_TRUE : ALC_FALSE);
456 SetALCError
458 Store latest ALC Error
460 ALCvoid SetALCError(ALenum errorCode)
462 g_eLastContextError = errorCode;
467 SuspendContext
469 Thread-safe entry
471 ALCvoid SuspendContext(ALCcontext *pContext)
473 (void)pContext;
474 EnterCriticalSection(&g_csMutex);
479 ProcessContext
481 Thread-safe exit
483 ALCvoid ProcessContext(ALCcontext *pContext)
485 (void)pContext;
486 LeaveCriticalSection(&g_csMutex);
491 GetContextSuspended
493 Returns the currently active Context, in a locked state
495 ALCcontext *GetContextSuspended(void)
497 ALCcontext *pContext = NULL;
499 SuspendContext(NULL);
501 pContext = tls_get(LocalContext);
502 if(pContext && !IsContext(pContext))
504 tls_set(LocalContext, NULL);
505 pContext = NULL;
507 if(!pContext)
509 pContext = g_pContextList;
510 while(pContext && !pContext->InUse)
511 pContext = pContext->next;
513 if(pContext)
514 SuspendContext(pContext);
516 ProcessContext(NULL);
518 return pContext;
523 InitContext
525 Initialize Context variables
527 static ALvoid InitContext(ALCcontext *pContext)
529 //Initialise listener
530 pContext->Listener.Gain = 1.0f;
531 pContext->Listener.MetersPerUnit = 1.0f;
532 pContext->Listener.Position[0] = 0.0f;
533 pContext->Listener.Position[1] = 0.0f;
534 pContext->Listener.Position[2] = 0.0f;
535 pContext->Listener.Velocity[0] = 0.0f;
536 pContext->Listener.Velocity[1] = 0.0f;
537 pContext->Listener.Velocity[2] = 0.0f;
538 pContext->Listener.Forward[0] = 0.0f;
539 pContext->Listener.Forward[1] = 0.0f;
540 pContext->Listener.Forward[2] = -1.0f;
541 pContext->Listener.Up[0] = 0.0f;
542 pContext->Listener.Up[1] = 1.0f;
543 pContext->Listener.Up[2] = 0.0f;
545 //Validate pContext
546 pContext->LastError = AL_NO_ERROR;
547 pContext->InUse = AL_FALSE;
549 //Set output format
550 pContext->Frequency = pContext->Device->Frequency;
552 //Set globals
553 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
554 pContext->DopplerFactor = 1.0f;
555 pContext->DopplerVelocity = 1.0f;
556 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
558 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";
560 aluInitPanning(pContext);
565 ExitContext
567 Clean up Context, destroy any remaining Sources
569 static ALCvoid ExitContext(ALCcontext *pContext)
571 //Invalidate context
572 pContext->LastError = AL_NO_ERROR;
573 pContext->InUse = AL_FALSE;
576 ///////////////////////////////////////////////////////
579 ///////////////////////////////////////////////////////
580 // ALC Functions calls
583 // This should probably move to another c file but for now ...
584 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
586 ALCboolean DeviceFound = ALC_FALSE;
587 ALCdevice *pDevice = NULL;
588 ALCint i;
590 if(SampleSize <= 0)
592 SetALCError(ALC_INVALID_VALUE);
593 return NULL;
596 if(deviceName && !deviceName[0])
597 deviceName = NULL;
599 pDevice = malloc(sizeof(ALCdevice));
600 if (pDevice)
602 //Initialise device structure
603 memset(pDevice, 0, sizeof(ALCdevice));
605 //Validate device
606 pDevice->Connected = ALC_TRUE;
607 pDevice->IsCaptureDevice = AL_TRUE;
609 pDevice->szDeviceName = NULL;
611 pDevice->Frequency = frequency;
612 pDevice->Format = format;
613 pDevice->UpdateSize = SampleSize;
614 pDevice->NumUpdates = 1;
616 SuspendContext(NULL);
617 for(i = 0;BackendList[i].Init;i++)
619 pDevice->Funcs = &BackendList[i].Funcs;
620 if(ALCdevice_OpenCapture(pDevice, deviceName))
622 pDevice->next = g_pDeviceList;
623 g_pDeviceList = pDevice;
624 g_ulDeviceCount++;
626 DeviceFound = ALC_TRUE;
627 break;
630 ProcessContext(NULL);
632 if(!DeviceFound)
634 SetALCError(ALC_INVALID_VALUE);
635 free(pDevice);
636 pDevice = NULL;
639 else
640 SetALCError(ALC_OUT_OF_MEMORY);
642 return pDevice;
645 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
647 ALCboolean bReturn = ALC_FALSE;
648 ALCdevice **list;
650 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
652 SuspendContext(NULL);
654 list = &g_pDeviceList;
655 while(*list != pDevice)
656 list = &(*list)->next;
658 *list = (*list)->next;
659 g_ulDeviceCount--;
661 ProcessContext(NULL);
663 free(pDevice->szDeviceName);
665 ALCdevice_CloseCapture(pDevice);
666 free(pDevice);
668 bReturn = ALC_TRUE;
670 else
671 SetALCError(ALC_INVALID_DEVICE);
673 return bReturn;
676 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
678 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
679 ALCdevice_StartCapture(pDevice);
680 else
681 SetALCError(ALC_INVALID_DEVICE);
684 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
686 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
687 ALCdevice_StopCapture(pDevice);
688 else
689 SetALCError(ALC_INVALID_DEVICE);
692 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
694 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
695 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
696 else
697 SetALCError(ALC_INVALID_DEVICE);
701 alcGetError
703 Return last ALC generated error code
705 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
707 ALCenum errorCode;
709 (void)device;
711 errorCode = g_eLastContextError;
712 g_eLastContextError = ALC_NO_ERROR;
713 return errorCode;
718 alcSuspendContext
720 Not functional
722 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
724 // Not a lot happens here !
725 (void)pContext;
730 alcProcessContext
732 Not functional
734 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
736 // Not a lot happens here !
737 (void)pContext;
742 alcGetString
744 Returns information about the Device, and error strings
746 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
748 const ALCchar *value = NULL;
750 switch (param)
752 case ALC_NO_ERROR:
753 value = alcNoError;
754 break;
756 case ALC_INVALID_ENUM:
757 value = alcErrInvalidEnum;
758 break;
760 case ALC_INVALID_VALUE:
761 value = alcErrInvalidValue;
762 break;
764 case ALC_INVALID_DEVICE:
765 value = alcErrInvalidDevice;
766 break;
768 case ALC_INVALID_CONTEXT:
769 value = alcErrInvalidContext;
770 break;
772 case ALC_OUT_OF_MEMORY:
773 value = alcErrOutOfMemory;
774 break;
776 case ALC_DEVICE_SPECIFIER:
777 if(IsDevice(pDevice))
778 value = pDevice->szDeviceName;
779 else
781 ProbeDeviceList();
782 value = alcDeviceList;
784 break;
786 case ALC_ALL_DEVICES_SPECIFIER:
787 ProbeAllDeviceList();
788 value = alcAllDeviceList;
789 break;
791 case ALC_CAPTURE_DEVICE_SPECIFIER:
792 if(IsDevice(pDevice))
793 value = pDevice->szDeviceName;
794 else
796 ProbeCaptureDeviceList();
797 value = alcCaptureDeviceList;
799 break;
801 /* Default devices are always first in the list */
802 case ALC_DEFAULT_DEVICE_SPECIFIER:
803 free(alcDefaultDeviceSpecifier);
804 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
805 if(!alcDefaultDeviceSpecifier)
806 SetALCError(ALC_OUT_OF_MEMORY);
807 value = alcDefaultDeviceSpecifier;
808 break;
810 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
811 free(alcDefaultAllDeviceSpecifier);
812 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
813 alcAllDeviceList : "");
814 if(!alcDefaultAllDeviceSpecifier)
815 SetALCError(ALC_OUT_OF_MEMORY);
816 value = alcDefaultAllDeviceSpecifier;
817 break;
819 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
820 free(alcCaptureDefaultDeviceSpecifier);
821 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
822 alcCaptureDeviceList : "");
823 if(!alcCaptureDefaultDeviceSpecifier)
824 SetALCError(ALC_OUT_OF_MEMORY);
825 value = alcCaptureDefaultDeviceSpecifier;
826 break;
828 case ALC_EXTENSIONS:
829 value = alcExtensionList;
830 break;
832 default:
833 SetALCError(ALC_INVALID_ENUM);
834 break;
837 return value;
842 alcGetIntegerv
844 Returns information about the Device and the version of Open AL
846 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
848 if(IsDevice(device) && device->IsCaptureDevice)
850 SuspendContext(NULL);
852 // Capture device
853 switch (param)
855 case ALC_CAPTURE_SAMPLES:
856 if ((size) && (data))
857 *data = ALCdevice_AvailableSamples(device);
858 else
859 SetALCError(ALC_INVALID_VALUE);
860 break;
862 case ALC_CONNECTED:
863 if(size <= 0)
864 SetALCError(ALC_INVALID_VALUE);
865 else
866 *data = device->Connected;
867 break;
869 default:
870 SetALCError(ALC_INVALID_ENUM);
871 break;
874 ProcessContext(NULL);
876 else
878 if(data)
880 // Playback Device
881 switch (param)
883 case ALC_MAJOR_VERSION:
884 if(size <= 0)
885 SetALCError(ALC_INVALID_VALUE);
886 else
887 *data = alcMajorVersion;
888 break;
890 case ALC_MINOR_VERSION:
891 if(size <= 0)
892 SetALCError(ALC_INVALID_VALUE);
893 else
894 *data = alcMinorVersion;
895 break;
897 case ALC_EFX_MAJOR_VERSION:
898 if(size <= 0)
899 SetALCError(ALC_INVALID_VALUE);
900 else
901 *data = alcEFXMajorVersion;
902 break;
904 case ALC_EFX_MINOR_VERSION:
905 if(size <= 0)
906 SetALCError(ALC_INVALID_VALUE);
907 else
908 *data = alcEFXMinorVersion;
909 break;
911 case ALC_MAX_AUXILIARY_SENDS:
912 if(size <= 0)
913 SetALCError(ALC_INVALID_VALUE);
914 else
915 *data = (device?device->NumAuxSends:MAX_SENDS);
916 break;
918 case ALC_ATTRIBUTES_SIZE:
919 if(!IsDevice(device))
920 SetALCError(ALC_INVALID_DEVICE);
921 else if(size <= 0)
922 SetALCError(ALC_INVALID_VALUE);
923 else
924 *data = 13;
925 break;
927 case ALC_ALL_ATTRIBUTES:
928 if(!IsDevice(device))
929 SetALCError(ALC_INVALID_DEVICE);
930 else if (size < 13)
931 SetALCError(ALC_INVALID_VALUE);
932 else
934 int i = 0;
936 SuspendContext(NULL);
937 data[i++] = ALC_FREQUENCY;
938 data[i++] = device->Frequency;
940 data[i++] = ALC_REFRESH;
941 data[i++] = device->Frequency / device->UpdateSize;
943 data[i++] = ALC_SYNC;
944 data[i++] = ALC_FALSE;
946 data[i++] = ALC_MONO_SOURCES;
947 data[i++] = device->lNumMonoSources;
949 data[i++] = ALC_STEREO_SOURCES;
950 data[i++] = device->lNumStereoSources;
952 data[i++] = ALC_MAX_AUXILIARY_SENDS;
953 data[i++] = device->NumAuxSends;
955 data[i++] = 0;
956 ProcessContext(NULL);
958 break;
960 case ALC_FREQUENCY:
961 if(!IsDevice(device))
962 SetALCError(ALC_INVALID_DEVICE);
963 else if(size <= 0)
964 SetALCError(ALC_INVALID_VALUE);
965 else
966 *data = device->Frequency;
967 break;
969 case ALC_REFRESH:
970 if(!IsDevice(device))
971 SetALCError(ALC_INVALID_DEVICE);
972 else if(size <= 0)
973 SetALCError(ALC_INVALID_VALUE);
974 else
975 *data = device->Frequency / device->UpdateSize;
976 break;
978 case ALC_SYNC:
979 if(!IsDevice(device))
980 SetALCError(ALC_INVALID_DEVICE);
981 else if(size <= 0)
982 SetALCError(ALC_INVALID_VALUE);
983 else
984 *data = ALC_FALSE;
985 break;
987 case ALC_MONO_SOURCES:
988 if(!IsDevice(device))
989 SetALCError(ALC_INVALID_DEVICE);
990 else if(size <= 0)
991 SetALCError(ALC_INVALID_VALUE);
992 else
993 *data = device->lNumMonoSources;
994 break;
996 case ALC_STEREO_SOURCES:
997 if(!IsDevice(device))
998 SetALCError(ALC_INVALID_DEVICE);
999 else if(size <= 0)
1000 SetALCError(ALC_INVALID_VALUE);
1001 else
1002 *data = device->lNumStereoSources;
1003 break;
1005 case ALC_CONNECTED:
1006 if(!IsDevice(device))
1007 SetALCError(ALC_INVALID_DEVICE);
1008 else if(size <= 0)
1009 SetALCError(ALC_INVALID_VALUE);
1010 else
1011 *data = device->Connected;
1012 break;
1014 default:
1015 SetALCError(ALC_INVALID_ENUM);
1016 break;
1019 else if(size)
1020 SetALCError(ALC_INVALID_VALUE);
1023 return;
1028 alcIsExtensionPresent
1030 Determines if there is support for a particular extension
1032 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1034 ALCboolean bResult = ALC_FALSE;
1036 (void)device;
1038 if (extName)
1040 const char *ptr;
1041 size_t len;
1043 len = strlen(extName);
1044 ptr = alcExtensionList;
1045 while(ptr && *ptr)
1047 if(strncasecmp(ptr, extName, len) == 0 &&
1048 (ptr[len] == '\0' || isspace(ptr[len])))
1050 bResult = ALC_TRUE;
1051 break;
1053 if((ptr=strchr(ptr, ' ')) != NULL)
1055 do {
1056 ++ptr;
1057 } while(isspace(*ptr));
1061 else
1062 SetALCError(ALC_INVALID_VALUE);
1064 return bResult;
1069 alcGetProcAddress
1071 Retrieves the function address for a particular extension function
1073 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1075 ALCvoid *pFunction = NULL;
1076 ALsizei i = 0;
1078 (void)device;
1080 if (funcName)
1082 while(alcFunctions[i].funcName &&
1083 strcmp(alcFunctions[i].funcName,funcName) != 0)
1084 i++;
1085 pFunction = alcFunctions[i].address;
1087 else
1088 SetALCError(ALC_INVALID_VALUE);
1090 return pFunction;
1095 alcGetEnumValue
1097 Get the value for a particular ALC Enumerated Value
1099 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1101 ALsizei i = 0;
1102 ALCenum val;
1104 (void)device;
1106 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1107 i++;
1108 val = enumeration[i].value;
1110 if(!enumeration[i].enumName)
1111 SetALCError(ALC_INVALID_VALUE);
1113 return val;
1118 alcCreateContext
1120 Create and attach a Context to a particular Device.
1122 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1124 ALCcontext *ALContext = NULL;
1125 ALuint ulAttributeIndex, ulRequestedStereoSources;
1126 ALuint RequestedSends;
1128 if(IsDevice(device) && !device->IsCaptureDevice && device->Connected)
1130 // Reset Context Last Error code
1131 g_eLastContextError = ALC_NO_ERROR;
1133 // Current implementation only allows one Context per Device
1134 if(!device->Context)
1136 ALContext = calloc(1, sizeof(ALCcontext));
1137 if(!ALContext)
1139 SetALCError(ALC_OUT_OF_MEMORY);
1140 return NULL;
1143 SuspendContext(NULL);
1145 ALContext->Device = device;
1146 InitContext(ALContext);
1148 device->Context = ALContext;
1150 ALContext->next = g_pContextList;
1151 g_pContextList = ALContext;
1152 g_ulContextCount++;
1154 // Check for attributes
1155 if (attrList)
1157 ALCint level = device->Bs2bLevel;
1158 ALCuint freq = device->Frequency;
1159 ALCint numMono = device->lNumMonoSources;
1160 ALCint numStereo = device->lNumStereoSources;
1161 ALCuint numSends = device->NumAuxSends;
1163 ulAttributeIndex = 0;
1164 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1166 if(attrList[ulAttributeIndex] == ALC_FREQUENCY)
1168 freq = attrList[ulAttributeIndex + 1];
1169 if(freq == 0)
1170 freq = device->Frequency;
1173 if(attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1175 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1177 if (ulRequestedStereoSources > device->MaxNoOfSources)
1178 ulRequestedStereoSources = device->MaxNoOfSources;
1180 numStereo = ulRequestedStereoSources;
1181 numMono = device->MaxNoOfSources - numStereo;
1184 if(attrList[ulAttributeIndex] == ALC_MAX_AUXILIARY_SENDS)
1186 RequestedSends = attrList[ulAttributeIndex + 1];
1188 if(RequestedSends > MAX_SENDS)
1189 RequestedSends = MAX_SENDS;
1191 numSends = RequestedSends;
1194 ulAttributeIndex += 2;
1197 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", level);
1198 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1199 device->lNumMonoSources = numMono;
1200 device->lNumStereoSources = numStereo;
1201 device->NumAuxSends = GetConfigValueInt(NULL, "sends", numSends);
1204 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1206 alcDestroyContext(ALContext);
1207 ALContext = NULL;
1208 SetALCError(ALC_INVALID_VALUE);
1211 ALContext->Frequency = device->Frequency;
1213 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1215 if(!device->Bs2b)
1217 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1218 bs2b_clear(device->Bs2b);
1220 bs2b_set_srate(device->Bs2b, device->Frequency);
1221 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1223 else
1225 free(device->Bs2b);
1226 device->Bs2b = NULL;
1229 ProcessContext(NULL);
1231 else
1233 SetALCError(ALC_INVALID_VALUE);
1234 ALContext = NULL;
1237 else
1238 SetALCError(ALC_INVALID_DEVICE);
1240 return ALContext;
1245 alcDestroyContext
1247 Remove a Context
1249 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1251 ALCcontext **list;
1253 if (IsContext(context))
1255 ALCdevice_StopPlayback(context->Device);
1257 // Lock context
1258 SuspendContext(context);
1260 if(context->SourceCount > 0)
1262 #ifdef _DEBUG
1263 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1264 #endif
1265 ReleaseALSources(context);
1267 if(context->AuxiliaryEffectSlotCount > 0)
1269 #ifdef _DEBUG
1270 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1271 #endif
1272 ReleaseALAuxiliaryEffectSlots(context);
1275 context->Device->Context = NULL;
1277 list = &g_pContextList;
1278 while(*list != context)
1279 list = &(*list)->next;
1281 *list = (*list)->next;
1282 g_ulContextCount--;
1284 // Unlock context
1285 ProcessContext(context);
1287 ExitContext(context);
1289 // Free memory (MUST do this after ProcessContext)
1290 memset(context, 0, sizeof(ALCcontext));
1291 free(context);
1293 else
1294 SetALCError(ALC_INVALID_CONTEXT);
1299 alcGetCurrentContext
1301 Returns the currently active Context
1303 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1305 ALCcontext *pContext;
1307 if((pContext=GetContextSuspended()) != NULL)
1308 ProcessContext(pContext);
1310 return pContext;
1314 alcGetThreadContext
1316 Returns the currently active thread-local Context
1318 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1320 ALCcontext *pContext = NULL;
1322 SuspendContext(NULL);
1324 pContext = tls_get(LocalContext);
1325 if(pContext && !IsContext(pContext))
1327 tls_set(LocalContext, NULL);
1328 pContext = NULL;
1331 ProcessContext(NULL);
1333 return pContext;
1338 alcGetContextsDevice
1340 Returns the Device that a particular Context is attached to
1342 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1344 ALCdevice *pDevice = NULL;
1346 SuspendContext(NULL);
1347 if (IsContext(pContext))
1348 pDevice = pContext->Device;
1349 else
1350 SetALCError(ALC_INVALID_CONTEXT);
1351 ProcessContext(NULL);
1353 return pDevice;
1358 alcMakeContextCurrent
1360 Makes the given Context the active Context
1362 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1364 ALCcontext *ALContext;
1365 ALboolean bReturn = AL_TRUE;
1367 SuspendContext(NULL);
1369 // context must be a valid Context or NULL
1370 if(context == NULL || IsContext(context))
1372 if((ALContext=GetContextSuspended()) != NULL)
1374 ALContext->InUse=AL_FALSE;
1375 ProcessContext(ALContext);
1378 if((ALContext=context) != NULL && ALContext->Device)
1380 SuspendContext(ALContext);
1381 ALContext->InUse=AL_TRUE;
1382 ProcessContext(ALContext);
1385 tls_set(LocalContext, NULL);
1387 else
1389 SetALCError(ALC_INVALID_CONTEXT);
1390 bReturn = AL_FALSE;
1393 ProcessContext(NULL);
1395 return bReturn;
1399 alcMakeCurrent
1401 Makes the given Context the active Context for the current thread
1403 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1405 ALboolean bReturn = AL_TRUE;
1407 SuspendContext(NULL);
1409 // context must be a valid Context or NULL
1410 if(context == NULL || IsContext(context))
1411 tls_set(LocalContext, context);
1412 else
1414 SetALCError(ALC_INVALID_CONTEXT);
1415 bReturn = AL_FALSE;
1418 ProcessContext(NULL);
1420 return bReturn;
1424 static ALenum GetFormatFromString(const char *str)
1426 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1427 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1428 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1429 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1430 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1431 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1433 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1434 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1435 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1436 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1437 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1438 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1440 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1441 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1442 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1443 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1444 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1445 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1447 AL_PRINT("Unknown format: \"%s\"\n", str);
1448 return AL_FORMAT_STEREO16;
1452 alcOpenDevice
1454 Open the Device specified.
1456 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1458 ALboolean bDeviceFound = AL_FALSE;
1459 ALCdevice *device;
1460 ALint i;
1462 if(deviceName && !deviceName[0])
1463 deviceName = NULL;
1465 device = malloc(sizeof(ALCdevice));
1466 if (device)
1468 const char *fmt;
1470 //Initialise device structure
1471 memset(device, 0, sizeof(ALCdevice));
1473 //Validate device
1474 device->Connected = ALC_TRUE;
1475 device->IsCaptureDevice = AL_FALSE;
1477 device->Bs2b = NULL;
1478 device->szDeviceName = NULL;
1480 //Set output format
1481 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1482 if(device->Frequency == 0)
1483 device->Frequency = SWMIXER_OUTPUT_RATE;
1485 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1486 device->Format = GetFormatFromString(fmt);
1488 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
1489 if(device->NumUpdates < 2)
1490 device->NumUpdates = 4;
1492 i = GetConfigValueInt(NULL, "refresh", 4096);
1493 if(i <= 0) i = 4096;
1495 device->UpdateSize = GetConfigValueInt(NULL, "period_size", i/device->NumUpdates);
1496 if(device->UpdateSize <= 0)
1497 device->UpdateSize = i/device->NumUpdates;
1499 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1500 if((ALint)device->MaxNoOfSources <= 0)
1501 device->MaxNoOfSources = 256;
1503 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1504 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1505 device->AuxiliaryEffectSlotMax = 4;
1507 device->lNumStereoSources = 1;
1508 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1510 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1511 if(device->NumAuxSends > MAX_SENDS)
1512 device->NumAuxSends = MAX_SENDS;
1514 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
1516 // Find a playback device to open
1517 SuspendContext(NULL);
1518 for(i = 0;BackendList[i].Init;i++)
1520 device->Funcs = &BackendList[i].Funcs;
1521 if(ALCdevice_OpenPlayback(device, deviceName))
1523 device->next = g_pDeviceList;
1524 g_pDeviceList = device;
1525 g_ulDeviceCount++;
1527 bDeviceFound = AL_TRUE;
1528 break;
1531 ProcessContext(NULL);
1533 if (!bDeviceFound)
1535 // No suitable output device found
1536 SetALCError(ALC_INVALID_VALUE);
1537 free(device);
1538 device = NULL;
1541 else
1542 SetALCError(ALC_OUT_OF_MEMORY);
1544 return device;
1549 alcCloseDevice
1551 Close the specified Device
1553 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1555 ALCboolean bReturn = ALC_FALSE;
1556 ALCdevice **list;
1558 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1560 SuspendContext(NULL);
1562 list = &g_pDeviceList;
1563 while(*list != pDevice)
1564 list = &(*list)->next;
1566 *list = (*list)->next;
1567 g_ulDeviceCount--;
1569 ProcessContext(NULL);
1571 if(pDevice->Context)
1573 #ifdef _DEBUG
1574 AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
1575 #endif
1576 alcDestroyContext(pDevice->Context);
1578 ALCdevice_ClosePlayback(pDevice);
1580 if(pDevice->BufferCount > 0)
1582 #ifdef _DEBUG
1583 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1584 #endif
1585 ReleaseALBuffers(pDevice);
1587 if(pDevice->EffectCount > 0)
1589 #ifdef _DEBUG
1590 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1591 #endif
1592 ReleaseALEffects(pDevice);
1594 if(pDevice->FilterCount > 0)
1596 #ifdef _DEBUG
1597 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1598 #endif
1599 ReleaseALFilters(pDevice);
1601 if(pDevice->DatabufferCount > 0)
1603 #ifdef _DEBUG
1604 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1605 #endif
1606 ReleaseALDatabuffers(pDevice);
1609 free(pDevice->Bs2b);
1610 pDevice->Bs2b = NULL;
1612 free(pDevice->szDeviceName);
1614 //Release device structure
1615 memset(pDevice, 0, sizeof(ALCdevice));
1616 free(pDevice);
1618 bReturn = ALC_TRUE;
1620 else
1621 SetALCError(ALC_INVALID_DEVICE);
1623 return bReturn;
1627 ALCvoid ReleaseALC(ALCvoid)
1629 free(alcDeviceList); alcDeviceList = NULL;
1630 alcDeviceListSize = 0;
1631 free(alcAllDeviceList); alcAllDeviceList = NULL;
1632 alcAllDeviceListSize = 0;
1633 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1634 alcCaptureDeviceListSize = 0;
1636 free(alcDefaultDeviceSpecifier);
1637 alcDefaultDeviceSpecifier = NULL;
1638 free(alcDefaultAllDeviceSpecifier);
1639 alcDefaultAllDeviceSpecifier = NULL;
1640 free(alcCaptureDefaultDeviceSpecifier);
1641 alcCaptureDefaultDeviceSpecifier = NULL;
1643 #ifdef _DEBUG
1644 if(g_ulDeviceCount > 0)
1645 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1646 #endif
1648 while(g_pDeviceList)
1650 if(g_pDeviceList->IsCaptureDevice)
1651 alcCaptureCloseDevice(g_pDeviceList);
1652 else
1653 alcCloseDevice(g_pDeviceList);
1657 ///////////////////////////////////////////////////////