Added backend & sample for Android
[openal-soft/android/lowlatency.git] / Alc / ALc.c
blob62878d7c8c24ee363b9d2de05cd91749242347da
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>
29 #include "alMain.h"
30 #include "alSource.h"
31 #include "AL/al.h"
32 #include "AL/alc.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.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_PULSEAUDIO
52 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_ALSA
55 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_OSS
58 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_SOLARIS
61 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_DSOUND
64 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_WINMM
67 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_PORTAUDIO
70 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
71 #endif
72 #ifdef HAVE_ANDROID
73 { "android", alc_android_init, alc_android_deinit, alc_android_probe, EmptyFuncs },
74 #endif
76 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
77 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
79 { NULL, NULL, NULL, NULL, EmptyFuncs }
81 #undef EmptyFuncs
83 ///////////////////////////////////////////////////////
85 #define ALC_EFX_MAJOR_VERSION 0x20001
86 #define ALC_EFX_MINOR_VERSION 0x20002
87 #define ALC_MAX_AUXILIARY_SENDS 0x20003
89 ///////////////////////////////////////////////////////
90 // STRING and EXTENSIONS
92 typedef struct ALCfunction {
93 const ALCchar *funcName;
94 ALCvoid *address;
95 } ALCfunction;
97 typedef struct ALCenums {
98 const ALCchar *enumName;
99 ALCenum value;
100 } ALCenums;
103 static const ALCfunction alcFunctions[] = {
104 { "alcCreateContext", (ALCvoid *) alcCreateContext },
105 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },
106 { "alcProcessContext", (ALCvoid *) alcProcessContext },
107 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },
108 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },
109 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },
110 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },
111 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },
112 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },
113 { "alcGetError", (ALCvoid *) alcGetError },
114 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },
115 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },
116 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },
117 { "alcGetString", (ALCvoid *) alcGetString },
118 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },
119 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },
120 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },
121 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },
122 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },
123 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },
125 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },
126 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },
128 { "alEnable", (ALCvoid *) alEnable },
129 { "alDisable", (ALCvoid *) alDisable },
130 { "alIsEnabled", (ALCvoid *) alIsEnabled },
131 { "alGetString", (ALCvoid *) alGetString },
132 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },
133 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },
134 { "alGetFloatv", (ALCvoid *) alGetFloatv },
135 { "alGetDoublev", (ALCvoid *) alGetDoublev },
136 { "alGetBoolean", (ALCvoid *) alGetBoolean },
137 { "alGetInteger", (ALCvoid *) alGetInteger },
138 { "alGetFloat", (ALCvoid *) alGetFloat },
139 { "alGetDouble", (ALCvoid *) alGetDouble },
140 { "alGetError", (ALCvoid *) alGetError },
141 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },
142 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },
143 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },
144 { "alListenerf", (ALCvoid *) alListenerf },
145 { "alListener3f", (ALCvoid *) alListener3f },
146 { "alListenerfv", (ALCvoid *) alListenerfv },
147 { "alListeneri", (ALCvoid *) alListeneri },
148 { "alListener3i", (ALCvoid *) alListener3i },
149 { "alListeneriv", (ALCvoid *) alListeneriv },
150 { "alGetListenerf", (ALCvoid *) alGetListenerf },
151 { "alGetListener3f", (ALCvoid *) alGetListener3f },
152 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },
153 { "alGetListeneri", (ALCvoid *) alGetListeneri },
154 { "alGetListener3i", (ALCvoid *) alGetListener3i },
155 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },
156 { "alGenSources", (ALCvoid *) alGenSources },
157 { "alDeleteSources", (ALCvoid *) alDeleteSources },
158 { "alIsSource", (ALCvoid *) alIsSource },
159 { "alSourcef", (ALCvoid *) alSourcef },
160 { "alSource3f", (ALCvoid *) alSource3f },
161 { "alSourcefv", (ALCvoid *) alSourcefv },
162 { "alSourcei", (ALCvoid *) alSourcei },
163 { "alSource3i", (ALCvoid *) alSource3i },
164 { "alSourceiv", (ALCvoid *) alSourceiv },
165 { "alGetSourcef", (ALCvoid *) alGetSourcef },
166 { "alGetSource3f", (ALCvoid *) alGetSource3f },
167 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },
168 { "alGetSourcei", (ALCvoid *) alGetSourcei },
169 { "alGetSource3i", (ALCvoid *) alGetSource3i },
170 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },
171 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },
172 { "alSourceStopv", (ALCvoid *) alSourceStopv },
173 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },
174 { "alSourcePausev", (ALCvoid *) alSourcePausev },
175 { "alSourcePlay", (ALCvoid *) alSourcePlay },
176 { "alSourceStop", (ALCvoid *) alSourceStop },
177 { "alSourceRewind", (ALCvoid *) alSourceRewind },
178 { "alSourcePause", (ALCvoid *) alSourcePause },
179 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },
180 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },
181 { "alGenBuffers", (ALCvoid *) alGenBuffers },
182 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },
183 { "alIsBuffer", (ALCvoid *) alIsBuffer },
184 { "alBufferData", (ALCvoid *) alBufferData },
185 { "alBufferf", (ALCvoid *) alBufferf },
186 { "alBuffer3f", (ALCvoid *) alBuffer3f },
187 { "alBufferfv", (ALCvoid *) alBufferfv },
188 { "alBufferi", (ALCvoid *) alBufferi },
189 { "alBuffer3i", (ALCvoid *) alBuffer3i },
190 { "alBufferiv", (ALCvoid *) alBufferiv },
191 { "alGetBufferf", (ALCvoid *) alGetBufferf },
192 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },
193 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },
194 { "alGetBufferi", (ALCvoid *) alGetBufferi },
195 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },
196 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },
197 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },
198 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },
199 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },
200 { "alDistanceModel", (ALCvoid *) alDistanceModel },
202 { "alGenFilters", (ALCvoid *) alGenFilters },
203 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },
204 { "alIsFilter", (ALCvoid *) alIsFilter },
205 { "alFilteri", (ALCvoid *) alFilteri },
206 { "alFilteriv", (ALCvoid *) alFilteriv },
207 { "alFilterf", (ALCvoid *) alFilterf },
208 { "alFilterfv", (ALCvoid *) alFilterfv },
209 { "alGetFilteri", (ALCvoid *) alGetFilteri },
210 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },
211 { "alGetFilterf", (ALCvoid *) alGetFilterf },
212 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },
214 { "alGenEffects", (ALCvoid *) alGenEffects },
215 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },
216 { "alIsEffect", (ALCvoid *) alIsEffect },
217 { "alEffecti", (ALCvoid *) alEffecti },
218 { "alEffectiv", (ALCvoid *) alEffectiv },
219 { "alEffectf", (ALCvoid *) alEffectf },
220 { "alEffectfv", (ALCvoid *) alEffectfv },
221 { "alGetEffecti", (ALCvoid *) alGetEffecti },
222 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },
223 { "alGetEffectf", (ALCvoid *) alGetEffectf },
224 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },
226 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},
227 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},
228 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },
229 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },
230 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },
231 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },
232 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },
233 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},
234 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},
235 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},
236 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},
238 { "alBufferSubDataEXT", (ALCvoid *) alBufferSubDataEXT },
240 { "alGenDatabuffersEXT", (ALCvoid *) alGenDatabuffersEXT },
241 { "alDeleteDatabuffersEXT", (ALCvoid *) alDeleteDatabuffersEXT },
242 { "alIsDatabufferEXT", (ALCvoid *) alIsDatabufferEXT },
243 { "alDatabufferDataEXT", (ALCvoid *) alDatabufferDataEXT },
244 { "alDatabufferSubDataEXT", (ALCvoid *) alDatabufferSubDataEXT },
245 { "alGetDatabufferSubDataEXT", (ALCvoid *) alGetDatabufferSubDataEXT},
246 { "alDatabufferfEXT", (ALCvoid *) alDatabufferfEXT },
247 { "alDatabufferfvEXT", (ALCvoid *) alDatabufferfvEXT },
248 { "alDatabufferiEXT", (ALCvoid *) alDatabufferiEXT },
249 { "alDatabufferivEXT", (ALCvoid *) alDatabufferivEXT },
250 { "alGetDatabufferfEXT", (ALCvoid *) alGetDatabufferfEXT },
251 { "alGetDatabufferfvEXT", (ALCvoid *) alGetDatabufferfvEXT },
252 { "alGetDatabufferiEXT", (ALCvoid *) alGetDatabufferiEXT },
253 { "alGetDatabufferivEXT", (ALCvoid *) alGetDatabufferivEXT },
254 { "alSelectDatabufferEXT", (ALCvoid *) alSelectDatabufferEXT },
255 { "alMapDatabufferEXT", (ALCvoid *) alMapDatabufferEXT },
256 { "alUnmapDatabufferEXT", (ALCvoid *) alUnmapDatabufferEXT },
258 { NULL, (ALCvoid *) NULL }
261 static const ALCenums enumeration[] = {
262 // Types
263 { "ALC_INVALID", ALC_INVALID },
264 { "ALC_FALSE", ALC_FALSE },
265 { "ALC_TRUE", ALC_TRUE },
267 // ALC Properties
268 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
269 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },
270 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
271 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
272 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
273 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
274 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
275 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
276 { "ALC_EXTENSIONS", ALC_EXTENSIONS },
277 { "ALC_FREQUENCY", ALC_FREQUENCY },
278 { "ALC_REFRESH", ALC_REFRESH },
279 { "ALC_SYNC", ALC_SYNC },
280 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },
281 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
282 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
283 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
284 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
285 { "ALC_CONNECTED", ALC_CONNECTED },
287 // EFX Properties
288 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
289 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
290 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
292 // ALC Error Message
293 { "ALC_NO_ERROR", ALC_NO_ERROR },
294 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
295 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
296 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },
297 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },
298 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
299 { NULL, (ALCenum)0 }
301 // Error strings
302 static const ALCchar alcNoError[] = "No Error";
303 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
304 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
305 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
306 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
307 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
309 /* Device lists. Sizes only include the first ending null character, not the
310 * second */
311 static ALCchar *alcDeviceList;
312 static size_t alcDeviceListSize;
313 static ALCchar *alcAllDeviceList;
314 static size_t alcAllDeviceListSize;
315 static ALCchar *alcCaptureDeviceList;
316 static size_t alcCaptureDeviceListSize;
317 // Default is always the first in the list
318 static ALCchar *alcDefaultDeviceSpecifier;
319 static ALCchar *alcDefaultAllDeviceSpecifier;
320 static ALCchar *alcCaptureDefaultDeviceSpecifier;
323 static const ALCchar alcNoDeviceExtList[] =
324 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
325 "ALC_EXT_thread_local_context";
326 static const ALCchar alcExtensionList[] =
327 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
328 "ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context";
329 static const ALCint alcMajorVersion = 1;
330 static const ALCint alcMinorVersion = 1;
332 static const ALCint alcEFXMajorVersion = 1;
333 static const ALCint alcEFXMinorVersion = 0;
335 ///////////////////////////////////////////////////////
338 ///////////////////////////////////////////////////////
339 // Global Variables
341 static ALCdevice *g_pDeviceList = NULL;
342 static ALCuint g_ulDeviceCount = 0;
344 static CRITICAL_SECTION g_csMutex;
346 // Context List
347 static ALCcontext *g_pContextList = NULL;
348 static ALCuint g_ulContextCount = 0;
350 // Thread-local current context
351 static tls_type LocalContext;
352 // Process-wide current context
353 static ALCcontext *GlobalContext;
355 // Context Error
356 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
358 // Default context extensions
359 static const ALchar alExtList[] =
360 "AL_EXTX_buffer_sub_data AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
361 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXTX_loop_points "
362 "AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
363 "AL_EXTX_sample_buffer_object AL_EXT_source_distance_model "
364 "AL_LOKI_quadriphonic";
366 // Mixing Priority Level
367 static ALint RTPrioLevel;
369 // Resampler Quality
370 resampler_t DefaultResampler;
372 // Output Log File
373 static FILE *LogFile;
375 ///////////////////////////////////////////////////////
378 ///////////////////////////////////////////////////////
379 // ALC Related helper functions
380 #ifdef _WIN32
381 static void alc_init(void);
382 static void alc_deinit(void);
384 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
386 (void)lpReserved;
388 // Perform actions based on the reason for calling.
389 switch(ul_reason_for_call)
391 case DLL_PROCESS_ATTACH:
392 DisableThreadLibraryCalls(hModule);
393 alc_init();
394 break;
396 case DLL_PROCESS_DETACH:
397 alc_deinit();
398 break;
400 return TRUE;
402 #else
403 #ifdef HAVE_GCC_DESTRUCTOR
404 static void alc_init(void) __attribute__((constructor));
405 static void alc_deinit(void) __attribute__((destructor));
406 #endif
407 #endif
409 static void alc_init(void)
411 int i;
412 const char *devs, *str;
414 InitializeCriticalSection(&g_csMutex);
415 ALTHUNK_INIT();
416 ReadALConfig();
418 tls_create(&LocalContext);
420 str = getenv("ALSOFT_LOGFILE");
421 if(str && str[0])
423 LogFile = fopen(str, "w");
424 if(!LogFile)
425 fprintf(stderr, "AL lib: Failed to open log file '%s'\n", str);
427 if(!LogFile)
428 LogFile = stderr;
430 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
432 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
433 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
434 DefaultResampler = RESAMPLER_DEFAULT;
436 devs = GetConfigValue(NULL, "drivers", "");
437 if(devs[0])
439 int n;
440 size_t len;
441 const char *next = devs;
442 int endlist, delitem;
444 i = 0;
445 do {
446 devs = next;
447 next = strchr(devs, ',');
449 delitem = (devs[0] == '-');
450 if(devs[0] == '-') devs++;
452 if(!devs[0] || devs[0] == ',')
454 endlist = 0;
455 continue;
457 endlist = 1;
459 len = (next ? ((size_t)(next-devs)) : strlen(devs));
460 for(n = i;BackendList[n].Init;n++)
462 if(len == strlen(BackendList[n].name) &&
463 strncmp(BackendList[n].name, devs, len) == 0)
465 if(delitem)
467 do {
468 BackendList[n] = BackendList[n+1];
469 ++n;
470 } while(BackendList[n].Init);
472 else
474 BackendInfo Bkp = BackendList[n];
475 while(n > i)
477 BackendList[n] = BackendList[n-1];
478 --n;
480 BackendList[n] = Bkp;
482 i++;
484 break;
487 } while(next++);
489 if(endlist)
491 BackendList[i].name = NULL;
492 BackendList[i].Init = NULL;
493 BackendList[i].Deinit = NULL;
494 BackendList[i].Probe = NULL;
498 for(i = 0;BackendList[i].Init;i++)
499 BackendList[i].Init(&BackendList[i].Funcs);
501 str = GetConfigValue(NULL, "excludefx", "");
502 if(str[0])
504 const struct {
505 const char *name;
506 int type;
507 } EffectList[] = {
508 { "eaxreverb", EAXREVERB },
509 { "reverb", REVERB },
510 { "echo", ECHO },
511 { "modulator", MODULATOR },
512 { NULL, 0 }
514 int n;
515 size_t len;
516 const char *next = str;
518 do {
519 str = next;
520 next = strchr(str, ',');
522 if(!str[0] || next == str)
523 continue;
525 len = (next ? ((size_t)(next-str)) : strlen(str));
526 for(n = 0;EffectList[n].name;n++)
528 if(len == strlen(EffectList[n].name) &&
529 strncmp(EffectList[n].name, str, len) == 0)
530 DisabledEffects[EffectList[n].type] = AL_TRUE;
532 } while(next++);
536 static void alc_deinit(void)
538 int i;
540 ReleaseALC();
542 for(i = 0;BackendList[i].Deinit;i++)
543 BackendList[i].Deinit();
545 if(LogFile != stderr)
546 fclose(LogFile);
547 LogFile = NULL;
549 tls_delete(LocalContext);
551 FreeALConfig();
552 ALTHUNK_EXIT();
553 DeleteCriticalSection(&g_csMutex);
557 static void ProbeDeviceList()
559 ALint i;
561 free(alcDeviceList); alcDeviceList = NULL;
562 alcDeviceListSize = 0;
564 for(i = 0;BackendList[i].Probe;i++)
565 BackendList[i].Probe(DEVICE_PROBE);
568 static void ProbeAllDeviceList()
570 ALint i;
572 free(alcAllDeviceList); alcAllDeviceList = NULL;
573 alcAllDeviceListSize = 0;
575 for(i = 0;BackendList[i].Probe;i++)
576 BackendList[i].Probe(ALL_DEVICE_PROBE);
579 static void ProbeCaptureDeviceList()
581 ALint i;
583 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
584 alcCaptureDeviceListSize = 0;
586 for(i = 0;BackendList[i].Probe;i++)
587 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
591 #define DECL_APPEND_LIST_FUNC(type) \
592 void Append##type##List(const ALCchar *name) \
594 size_t len = strlen(name); \
595 void *temp; \
597 if(len == 0) \
598 return; \
600 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
601 if(!temp) \
603 AL_PRINT("Realloc failed to add %s!\n", name); \
604 return; \
606 alc##type##List = temp; \
607 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
608 alc##type##ListSize += len+1; \
609 alc##type##List[alc##type##ListSize] = 0; \
612 DECL_APPEND_LIST_FUNC(Device)
613 DECL_APPEND_LIST_FUNC(AllDevice)
614 DECL_APPEND_LIST_FUNC(CaptureDevice)
617 void al_print(const char *fname, unsigned int line, const char *fmt, ...)
619 const char *fn;
620 char str[256];
621 int i;
623 fn = strrchr(fname, '/');
624 if(!fn) fn = strrchr(fname, '\\');;
625 if(!fn) fn = fname;
626 else fn += 1;
628 i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
629 if(i < (int)sizeof(str) && i > 0)
631 va_list ap;
632 va_start(ap, fmt);
633 vsnprintf(str+i, sizeof(str)-i, fmt, ap);
634 va_end(ap);
636 str[sizeof(str)-1] = 0;
638 #ifdef ANDROID
639 __android_log_write(ANDROID_LOG_WARN, "OpenAL", str);
640 #endif
641 fprintf(LogFile, "%s", str);
642 fflush(LogFile);
645 void SetRTPriority(void)
647 ALboolean failed;
649 #ifdef _WIN32
650 if(RTPrioLevel > 0)
651 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
652 else
653 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
654 #elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
655 struct sched_param param;
657 if(RTPrioLevel > 0)
659 /* Use the minimum real-time priority possible for now (on Linux this
660 * should be 1 for SCHED_RR) */
661 param.sched_priority = sched_get_priority_min(SCHED_RR);
662 failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
664 else
666 param.sched_priority = 0;
667 failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
669 #else
670 /* Real-time priority not available */
671 failed = (RTPrioLevel>0);
672 #endif
673 if(failed)
674 AL_PRINT("Failed to set priority level for thread\n");
678 void InitUIntMap(UIntMap *map)
680 map->array = NULL;
681 map->size = 0;
682 map->maxsize = 0;
685 void ResetUIntMap(UIntMap *map)
687 free(map->array);
688 map->array = NULL;
689 map->size = 0;
690 map->maxsize = 0;
693 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
695 ALsizei pos = 0;
697 if(map->size > 0)
699 ALsizei low = 0;
700 ALsizei high = map->size - 1;
701 while(low < high)
703 ALsizei mid = low + (high-low)/2;
704 if(map->array[mid].key < key)
705 low = mid + 1;
706 else
707 high = mid;
709 if(map->array[low].key < key)
710 low++;
711 pos = low;
714 if(pos == map->size || map->array[pos].key != key)
716 if(map->size == map->maxsize)
718 ALvoid *temp;
719 ALsizei newsize;
721 newsize = (map->maxsize ? (map->maxsize<<1) : 4);
722 if(newsize < map->maxsize)
723 return AL_OUT_OF_MEMORY;
725 temp = realloc(map->array, newsize*sizeof(map->array[0]));
726 if(!temp) return AL_OUT_OF_MEMORY;
727 map->array = temp;
728 map->maxsize = newsize;
731 map->size++;
732 if(pos < map->size-1)
733 memmove(&map->array[pos+1], &map->array[pos],
734 (map->size-1-pos)*sizeof(map->array[0]));
736 map->array[pos].key = key;
737 map->array[pos].value = value;
739 return AL_NO_ERROR;
742 void RemoveUIntMapKey(UIntMap *map, ALuint key)
744 if(map->size > 0)
746 ALsizei low = 0;
747 ALsizei high = map->size - 1;
748 while(low < high)
750 ALsizei mid = low + (high-low)/2;
751 if(map->array[mid].key < key)
752 low = mid + 1;
753 else
754 high = mid;
756 if(map->array[low].key == key)
758 if(low < map->size-1)
759 memmove(&map->array[low], &map->array[low+1],
760 (map->size-1-low)*sizeof(map->array[0]));
761 map->size--;
768 IsDevice
770 Check pDevice is a valid Device pointer
772 static ALCboolean IsDevice(ALCdevice *pDevice)
774 ALCdevice *pTempDevice;
776 SuspendContext(NULL);
778 pTempDevice = g_pDeviceList;
779 while(pTempDevice && pTempDevice != pDevice)
780 pTempDevice = pTempDevice->next;
782 ProcessContext(NULL);
784 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
788 IsContext
790 Check pContext is a valid Context pointer
792 static ALCboolean IsContext(ALCcontext *pContext)
794 ALCcontext *pTempContext;
796 SuspendContext(NULL);
798 pTempContext = g_pContextList;
799 while (pTempContext && pTempContext != pContext)
800 pTempContext = pTempContext->next;
802 ProcessContext(NULL);
804 return (pTempContext ? ALC_TRUE : ALC_FALSE);
809 alcSetError
811 Store latest ALC Error
813 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
815 if(IsDevice(device))
816 device->LastError = errorCode;
817 else
818 g_eLastNullDeviceError = errorCode;
823 SuspendContext
825 Thread-safe entry
827 ALCvoid SuspendContext(ALCcontext *pContext)
829 (void)pContext;
830 EnterCriticalSection(&g_csMutex);
835 ProcessContext
837 Thread-safe exit
839 ALCvoid ProcessContext(ALCcontext *pContext)
841 (void)pContext;
842 LeaveCriticalSection(&g_csMutex);
847 GetContextSuspended
849 Returns the currently active Context, in a locked state
851 ALCcontext *GetContextSuspended(void)
853 ALCcontext *pContext = NULL;
855 SuspendContext(NULL);
857 pContext = tls_get(LocalContext);
858 if(pContext && !IsContext(pContext))
860 tls_set(LocalContext, NULL);
861 pContext = NULL;
863 if(!pContext)
864 pContext = GlobalContext;
866 if(pContext)
867 SuspendContext(pContext);
869 ProcessContext(NULL);
871 return pContext;
876 InitContext
878 Initialize Context variables
880 static ALvoid InitContext(ALCcontext *pContext)
882 //Initialise listener
883 pContext->Listener.Gain = 1.0f;
884 pContext->Listener.MetersPerUnit = 1.0f;
885 pContext->Listener.Position[0] = 0.0f;
886 pContext->Listener.Position[1] = 0.0f;
887 pContext->Listener.Position[2] = 0.0f;
888 pContext->Listener.Velocity[0] = 0.0f;
889 pContext->Listener.Velocity[1] = 0.0f;
890 pContext->Listener.Velocity[2] = 0.0f;
891 pContext->Listener.Forward[0] = 0.0f;
892 pContext->Listener.Forward[1] = 0.0f;
893 pContext->Listener.Forward[2] = -1.0f;
894 pContext->Listener.Up[0] = 0.0f;
895 pContext->Listener.Up[1] = 1.0f;
896 pContext->Listener.Up[2] = 0.0f;
898 //Validate pContext
899 pContext->LastError = AL_NO_ERROR;
900 pContext->Suspended = AL_FALSE;
901 pContext->ActiveSourceCount = 0;
902 InitUIntMap(&pContext->SourceMap);
903 InitUIntMap(&pContext->EffectSlotMap);
905 //Set globals
906 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
907 pContext->SourceDistanceModel = AL_FALSE;
908 pContext->DopplerFactor = 1.0f;
909 pContext->DopplerVelocity = 1.0f;
910 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
912 pContext->ExtensionList = alExtList;
917 ExitContext
919 Clean up Context, destroy any remaining Sources
921 static ALCvoid ExitContext(ALCcontext *pContext)
923 //Invalidate context
924 pContext->LastError = AL_NO_ERROR;
927 ///////////////////////////////////////////////////////
930 ///////////////////////////////////////////////////////
931 // ALC Functions calls
934 // This should probably move to another c file but for now ...
935 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
937 ALCboolean DeviceFound = ALC_FALSE;
938 ALCdevice *device = NULL;
939 ALCint i;
941 if(SampleSize <= 0)
943 alcSetError(NULL, ALC_INVALID_VALUE);
944 return NULL;
947 if(deviceName && !deviceName[0])
948 deviceName = NULL;
950 device = calloc(1, sizeof(ALCdevice));
951 if(!device)
953 alcSetError(NULL, ALC_OUT_OF_MEMORY);
954 return NULL;
957 //Validate device
958 device->Connected = ALC_TRUE;
959 device->IsCaptureDevice = AL_TRUE;
961 device->szDeviceName = NULL;
963 device->Frequency = frequency;
964 device->Format = format;
965 device->UpdateSize = SampleSize;
966 device->NumUpdates = 1;
968 SuspendContext(NULL);
969 for(i = 0;BackendList[i].Init;i++)
971 device->Funcs = &BackendList[i].Funcs;
972 if(ALCdevice_OpenCapture(device, deviceName))
974 device->next = g_pDeviceList;
975 g_pDeviceList = device;
976 g_ulDeviceCount++;
978 DeviceFound = ALC_TRUE;
979 break;
982 ProcessContext(NULL);
984 if(!DeviceFound)
986 alcSetError(NULL, ALC_INVALID_VALUE);
987 free(device);
988 device = NULL;
991 return device;
994 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
996 ALCdevice **list;
998 if(!IsDevice(pDevice) || !pDevice->IsCaptureDevice)
1000 alcSetError(pDevice, ALC_INVALID_DEVICE);
1001 return ALC_FALSE;
1004 SuspendContext(NULL);
1006 list = &g_pDeviceList;
1007 while(*list != pDevice)
1008 list = &(*list)->next;
1010 *list = (*list)->next;
1011 g_ulDeviceCount--;
1013 ProcessContext(NULL);
1015 ALCdevice_CloseCapture(pDevice);
1017 free(pDevice->szDeviceName);
1018 pDevice->szDeviceName = NULL;
1020 free(pDevice);
1022 return ALC_TRUE;
1025 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
1027 SuspendContext(NULL);
1028 if(!IsDevice(device) || !device->IsCaptureDevice)
1029 alcSetError(device, ALC_INVALID_DEVICE);
1030 else if(device->Connected)
1031 ALCdevice_StartCapture(device);
1032 ProcessContext(NULL);
1035 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
1037 SuspendContext(NULL);
1038 if(!IsDevice(device) || !device->IsCaptureDevice)
1039 alcSetError(device, ALC_INVALID_DEVICE);
1040 else
1041 ALCdevice_StopCapture(device);
1042 ProcessContext(NULL);
1045 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
1047 SuspendContext(NULL);
1048 if(!IsDevice(device) || !device->IsCaptureDevice)
1049 alcSetError(device, ALC_INVALID_DEVICE);
1050 else
1051 ALCdevice_CaptureSamples(device, buffer, samples);
1052 ProcessContext(NULL);
1056 alcGetError
1058 Return last ALC generated error code
1060 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1062 ALCenum errorCode;
1064 if(IsDevice(device))
1066 errorCode = device->LastError;
1067 device->LastError = ALC_NO_ERROR;
1069 else
1071 errorCode = g_eLastNullDeviceError;
1072 g_eLastNullDeviceError = ALC_NO_ERROR;
1074 return errorCode;
1079 alcSuspendContext
1081 Not functional
1083 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *pContext)
1085 SuspendContext(NULL);
1086 if(IsContext(pContext))
1087 pContext->Suspended = AL_TRUE;
1088 ProcessContext(NULL);
1093 alcProcessContext
1095 Not functional
1097 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *pContext)
1099 SuspendContext(NULL);
1100 if(IsContext(pContext))
1101 pContext->Suspended = AL_FALSE;
1102 ProcessContext(NULL);
1107 alcGetString
1109 Returns information about the Device, and error strings
1111 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
1113 const ALCchar *value = NULL;
1115 switch (param)
1117 case ALC_NO_ERROR:
1118 value = alcNoError;
1119 break;
1121 case ALC_INVALID_ENUM:
1122 value = alcErrInvalidEnum;
1123 break;
1125 case ALC_INVALID_VALUE:
1126 value = alcErrInvalidValue;
1127 break;
1129 case ALC_INVALID_DEVICE:
1130 value = alcErrInvalidDevice;
1131 break;
1133 case ALC_INVALID_CONTEXT:
1134 value = alcErrInvalidContext;
1135 break;
1137 case ALC_OUT_OF_MEMORY:
1138 value = alcErrOutOfMemory;
1139 break;
1141 case ALC_DEVICE_SPECIFIER:
1142 if(IsDevice(pDevice))
1143 value = pDevice->szDeviceName;
1144 else
1146 ProbeDeviceList();
1147 value = alcDeviceList;
1149 break;
1151 case ALC_ALL_DEVICES_SPECIFIER:
1152 ProbeAllDeviceList();
1153 value = alcAllDeviceList;
1154 break;
1156 case ALC_CAPTURE_DEVICE_SPECIFIER:
1157 if(IsDevice(pDevice))
1158 value = pDevice->szDeviceName;
1159 else
1161 ProbeCaptureDeviceList();
1162 value = alcCaptureDeviceList;
1164 break;
1166 /* Default devices are always first in the list */
1167 case ALC_DEFAULT_DEVICE_SPECIFIER:
1168 if(!alcDeviceList)
1169 ProbeDeviceList();
1171 free(alcDefaultDeviceSpecifier);
1172 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
1173 if(!alcDefaultDeviceSpecifier)
1174 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1175 value = alcDefaultDeviceSpecifier;
1176 break;
1178 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
1179 if(!alcAllDeviceList)
1180 ProbeAllDeviceList();
1182 free(alcDefaultAllDeviceSpecifier);
1183 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
1184 alcAllDeviceList : "");
1185 if(!alcDefaultAllDeviceSpecifier)
1186 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1187 value = alcDefaultAllDeviceSpecifier;
1188 break;
1190 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
1191 if(!alcCaptureDeviceList)
1192 ProbeCaptureDeviceList();
1194 free(alcCaptureDefaultDeviceSpecifier);
1195 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
1196 alcCaptureDeviceList : "");
1197 if(!alcCaptureDefaultDeviceSpecifier)
1198 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1199 value = alcCaptureDefaultDeviceSpecifier;
1200 break;
1202 case ALC_EXTENSIONS:
1203 if(IsDevice(pDevice))
1204 value = alcExtensionList;
1205 else
1206 value = alcNoDeviceExtList;
1207 break;
1209 default:
1210 alcSetError(pDevice, ALC_INVALID_ENUM);
1211 break;
1214 return value;
1219 alcGetIntegerv
1221 Returns information about the Device and the version of Open AL
1223 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
1225 if(size == 0 || data == NULL)
1227 alcSetError(device, ALC_INVALID_VALUE);
1228 return;
1231 if(IsDevice(device) && device->IsCaptureDevice)
1233 SuspendContext(NULL);
1235 // Capture device
1236 switch (param)
1238 case ALC_CAPTURE_SAMPLES:
1239 *data = ALCdevice_AvailableSamples(device);
1240 break;
1242 case ALC_CONNECTED:
1243 *data = device->Connected;
1244 break;
1246 default:
1247 alcSetError(device, ALC_INVALID_ENUM);
1248 break;
1251 ProcessContext(NULL);
1252 return;
1255 // Playback Device
1256 switch (param)
1258 case ALC_MAJOR_VERSION:
1259 *data = alcMajorVersion;
1260 break;
1262 case ALC_MINOR_VERSION:
1263 *data = alcMinorVersion;
1264 break;
1266 case ALC_EFX_MAJOR_VERSION:
1267 *data = alcEFXMajorVersion;
1268 break;
1270 case ALC_EFX_MINOR_VERSION:
1271 *data = alcEFXMinorVersion;
1272 break;
1274 case ALC_MAX_AUXILIARY_SENDS:
1275 if(!IsDevice(device))
1276 alcSetError(device, ALC_INVALID_DEVICE);
1277 else
1278 *data = device->NumAuxSends;
1279 break;
1281 case ALC_ATTRIBUTES_SIZE:
1282 if(!IsDevice(device))
1283 alcSetError(device, ALC_INVALID_DEVICE);
1284 else
1285 *data = 13;
1286 break;
1288 case ALC_ALL_ATTRIBUTES:
1289 if(!IsDevice(device))
1290 alcSetError(device, ALC_INVALID_DEVICE);
1291 else if (size < 13)
1292 alcSetError(device, ALC_INVALID_VALUE);
1293 else
1295 int i = 0;
1297 SuspendContext(NULL);
1298 data[i++] = ALC_FREQUENCY;
1299 data[i++] = device->Frequency;
1301 data[i++] = ALC_REFRESH;
1302 data[i++] = device->Frequency / device->UpdateSize;
1304 data[i++] = ALC_SYNC;
1305 data[i++] = ALC_FALSE;
1307 data[i++] = ALC_MONO_SOURCES;
1308 data[i++] = device->NumMonoSources;
1310 data[i++] = ALC_STEREO_SOURCES;
1311 data[i++] = device->NumStereoSources;
1313 data[i++] = ALC_MAX_AUXILIARY_SENDS;
1314 data[i++] = device->NumAuxSends;
1316 data[i++] = 0;
1317 ProcessContext(NULL);
1319 break;
1321 case ALC_FREQUENCY:
1322 if(!IsDevice(device))
1323 alcSetError(device, ALC_INVALID_DEVICE);
1324 else
1325 *data = device->Frequency;
1326 break;
1328 case ALC_REFRESH:
1329 if(!IsDevice(device))
1330 alcSetError(device, ALC_INVALID_DEVICE);
1331 else
1332 *data = device->Frequency / device->UpdateSize;
1333 break;
1335 case ALC_SYNC:
1336 if(!IsDevice(device))
1337 alcSetError(device, ALC_INVALID_DEVICE);
1338 else
1339 *data = ALC_FALSE;
1340 break;
1342 case ALC_MONO_SOURCES:
1343 if(!IsDevice(device))
1344 alcSetError(device, ALC_INVALID_DEVICE);
1345 else
1346 *data = device->NumMonoSources;
1347 break;
1349 case ALC_STEREO_SOURCES:
1350 if(!IsDevice(device))
1351 alcSetError(device, ALC_INVALID_DEVICE);
1352 else
1353 *data = device->NumStereoSources;
1354 break;
1356 case ALC_CONNECTED:
1357 if(!IsDevice(device))
1358 alcSetError(device, ALC_INVALID_DEVICE);
1359 else
1360 *data = device->Connected;
1361 break;
1363 default:
1364 alcSetError(device, ALC_INVALID_ENUM);
1365 break;
1371 alcIsExtensionPresent
1373 Determines if there is support for a particular extension
1375 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1377 ALCboolean bResult = ALC_FALSE;
1378 const char *ptr;
1379 size_t len;
1381 if(!extName)
1383 alcSetError(device, ALC_INVALID_VALUE);
1384 return ALC_FALSE;
1387 len = strlen(extName);
1388 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
1389 while(ptr && *ptr)
1391 if(strncasecmp(ptr, extName, len) == 0 &&
1392 (ptr[len] == '\0' || isspace(ptr[len])))
1394 bResult = ALC_TRUE;
1395 break;
1397 if((ptr=strchr(ptr, ' ')) != NULL)
1399 do {
1400 ++ptr;
1401 } while(isspace(*ptr));
1405 return bResult;
1410 alcGetProcAddress
1412 Retrieves the function address for a particular extension function
1414 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1416 ALsizei i = 0;
1418 if(!funcName)
1420 alcSetError(device, ALC_INVALID_VALUE);
1421 return NULL;
1424 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
1425 i++;
1426 return alcFunctions[i].address;
1431 alcGetEnumValue
1433 Get the value for a particular ALC Enumerated Value
1435 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1437 ALsizei i = 0;
1439 if(!enumName)
1441 alcSetError(device, ALC_INVALID_VALUE);
1442 return (ALCenum)0;
1445 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
1446 i++;
1447 return enumeration[i].value;
1452 alcCreateContext
1454 Create and attach a Context to a particular Device.
1456 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1458 ALCcontext *ALContext;
1459 ALboolean running;
1460 ALuint attrIdx;
1461 void *temp;
1462 ALuint i;
1464 SuspendContext(NULL);
1466 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1468 alcSetError(device, ALC_INVALID_DEVICE);
1469 ProcessContext(NULL);
1470 return NULL;
1473 running = ((device->NumContexts > 0) ? AL_TRUE : AL_FALSE);
1475 // Reset Context Last Error code
1476 device->LastError = ALC_NO_ERROR;
1478 // Check for attributes
1479 if(attrList && attrList[0])
1481 ALCuint freq, numMono, numStereo, numSends;
1483 // If a context is already running on the device, stop playback so the
1484 // device attributes can be updated
1485 if(running)
1487 ProcessContext(NULL);
1488 ALCdevice_StopPlayback(device);
1489 SuspendContext(NULL);
1490 running = AL_FALSE;
1493 freq = device->Frequency;
1494 numMono = device->NumMonoSources;
1495 numStereo = device->NumStereoSources;
1496 numSends = device->NumAuxSends;
1498 attrIdx = 0;
1499 while(attrList[attrIdx])
1501 if(attrList[attrIdx] == ALC_FREQUENCY &&
1502 !ConfigValueExists(NULL, "frequency"))
1504 freq = attrList[attrIdx + 1];
1505 if(freq < 8000)
1506 freq = 8000;
1509 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1511 numStereo = attrList[attrIdx + 1];
1512 if(numStereo > device->MaxNoOfSources)
1513 numStereo = device->MaxNoOfSources;
1515 numMono = device->MaxNoOfSources - numStereo;
1518 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
1519 !ConfigValueExists(NULL, "sends"))
1521 numSends = attrList[attrIdx + 1];
1522 if(numSends > MAX_SENDS)
1523 numSends = MAX_SENDS;
1526 attrIdx += 2;
1529 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1530 device->Frequency;
1532 device->Frequency = freq;
1533 device->NumMonoSources = numMono;
1534 device->NumStereoSources = numStereo;
1535 device->NumAuxSends = numSends;
1538 if(running == AL_FALSE && ALCdevice_ResetPlayback(device) == ALC_FALSE)
1540 alcSetError(device, ALC_INVALID_DEVICE);
1541 aluHandleDisconnect(device);
1542 ProcessContext(NULL);
1543 return NULL;
1545 aluInitPanning(device);
1547 for(i = 0;i < device->NumContexts;i++)
1549 ALCcontext *context = device->Contexts[i];
1550 ALsizei pos;
1552 SuspendContext(context);
1553 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1555 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1556 if(!slot->EffectState)
1557 continue;
1559 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1561 alcSetError(device, ALC_INVALID_DEVICE);
1562 aluHandleDisconnect(device);
1563 ProcessContext(context);
1564 ProcessContext(NULL);
1565 ALCdevice_StopPlayback(device);
1566 return NULL;
1568 ALEffect_Update(slot->EffectState, context, &slot->effect);
1571 for(pos = 0;pos < context->SourceMap.size;pos++)
1573 ALsource *source = context->SourceMap.array[pos].value;
1574 ALuint s = device->NumAuxSends;
1575 while(s < MAX_SENDS)
1577 if(source->Send[s].Slot)
1578 source->Send[s].Slot->refcount--;
1579 source->Send[s].Slot = NULL;
1580 source->Send[s].WetFilter.type = 0;
1581 source->Send[s].WetFilter.filter = 0;
1582 s++;
1584 source->NeedsUpdate = AL_TRUE;
1586 ProcessContext(context);
1589 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1591 if(!device->Bs2b)
1593 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1594 bs2b_clear(device->Bs2b);
1596 bs2b_set_srate(device->Bs2b, device->Frequency);
1597 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1599 else
1601 free(device->Bs2b);
1602 device->Bs2b = NULL;
1605 if(aluChannelsFromFormat(device->Format) <= 2)
1607 device->HeadDampen = GetConfigValueFloat(NULL, "head_dampen", DEFAULT_HEAD_DAMPEN);
1608 device->HeadDampen = __min(device->HeadDampen, 1.0f);
1609 device->HeadDampen = __max(device->HeadDampen, 0.0f);
1611 else
1612 device->HeadDampen = 0.0f;
1614 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1615 if(!temp)
1617 alcSetError(device, ALC_OUT_OF_MEMORY);
1618 ProcessContext(NULL);
1619 return NULL;
1621 device->Contexts = temp;
1623 ALContext = calloc(1, sizeof(ALCcontext));
1624 if(ALContext)
1626 ALContext->MaxActiveSources = 256;
1627 ALContext->ActiveSources = malloc(sizeof(*ALContext->ActiveSources) *
1628 ALContext->MaxActiveSources);
1630 if(!ALContext || !ALContext->ActiveSources)
1632 free(ALContext);
1633 alcSetError(device, ALC_OUT_OF_MEMORY);
1634 ProcessContext(NULL);
1635 return NULL;
1638 device->Contexts[device->NumContexts++] = ALContext;
1639 ALContext->Device = device;
1641 InitContext(ALContext);
1643 ALContext->next = g_pContextList;
1644 g_pContextList = ALContext;
1645 g_ulContextCount++;
1647 ProcessContext(NULL);
1649 return ALContext;
1654 alcDestroyContext
1656 Remove a Context
1658 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
1660 ALCdevice *Device;
1661 ALCcontext **list;
1662 ALuint i;
1664 if(!IsContext(context))
1666 alcSetError(NULL, ALC_INVALID_CONTEXT);
1667 return;
1670 Device = context->Device;
1672 if(Device->NumContexts == 1)
1673 ALCdevice_StopPlayback(Device);
1675 SuspendContext(NULL);
1677 if(context == GlobalContext)
1678 GlobalContext = NULL;
1680 for(i = 0;i < Device->NumContexts-1;i++)
1682 if(Device->Contexts[i] == context)
1684 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];
1685 break;
1688 Device->NumContexts--;
1690 // Lock context
1691 SuspendContext(context);
1693 if(context->SourceMap.size > 0)
1695 #ifdef _DEBUG
1696 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);
1697 #endif
1698 ReleaseALSources(context);
1700 ResetUIntMap(&context->SourceMap);
1702 if(context->EffectSlotMap.size > 0)
1704 #ifdef _DEBUG
1705 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);
1706 #endif
1707 ReleaseALAuxiliaryEffectSlots(context);
1709 ResetUIntMap(&context->EffectSlotMap);
1711 free(context->ActiveSources);
1712 context->ActiveSources = NULL;
1713 context->MaxActiveSources = 0;
1714 context->ActiveSourceCount = 0;
1716 list = &g_pContextList;
1717 while(*list != context)
1718 list = &(*list)->next;
1720 *list = (*list)->next;
1721 g_ulContextCount--;
1723 // Unlock context
1724 ProcessContext(context);
1725 ProcessContext(NULL);
1727 ExitContext(context);
1729 // Free memory (MUST do this after ProcessContext)
1730 memset(context, 0, sizeof(ALCcontext));
1731 free(context);
1736 alcGetCurrentContext
1738 Returns the currently active Context
1740 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
1742 ALCcontext *pContext;
1744 if((pContext=GetContextSuspended()) != NULL)
1745 ProcessContext(pContext);
1747 return pContext;
1751 alcGetThreadContext
1753 Returns the currently active thread-local Context
1755 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
1757 ALCcontext *pContext = NULL;
1759 SuspendContext(NULL);
1761 pContext = tls_get(LocalContext);
1762 if(pContext && !IsContext(pContext))
1764 tls_set(LocalContext, NULL);
1765 pContext = NULL;
1768 ProcessContext(NULL);
1770 return pContext;
1775 alcGetContextsDevice
1777 Returns the Device that a particular Context is attached to
1779 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)
1781 ALCdevice *pDevice = NULL;
1783 SuspendContext(NULL);
1784 if(IsContext(pContext))
1785 pDevice = pContext->Device;
1786 else
1787 alcSetError(NULL, ALC_INVALID_CONTEXT);
1788 ProcessContext(NULL);
1790 return pDevice;
1795 alcMakeContextCurrent
1797 Makes the given Context the active Context
1799 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
1801 ALboolean bReturn = AL_TRUE;
1803 SuspendContext(NULL);
1805 // context must be a valid Context or NULL
1806 if(context == NULL || IsContext(context))
1808 GlobalContext = context;
1809 tls_set(LocalContext, NULL);
1811 else
1813 alcSetError(NULL, ALC_INVALID_CONTEXT);
1814 bReturn = AL_FALSE;
1817 ProcessContext(NULL);
1819 return bReturn;
1823 alcSetThreadContext
1825 Makes the given Context the active Context for the current thread
1827 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
1829 ALboolean bReturn = AL_TRUE;
1831 SuspendContext(NULL);
1833 // context must be a valid Context or NULL
1834 if(context == NULL || IsContext(context))
1835 tls_set(LocalContext, context);
1836 else
1838 alcSetError(NULL, ALC_INVALID_CONTEXT);
1839 bReturn = AL_FALSE;
1842 ProcessContext(NULL);
1844 return bReturn;
1848 // Sets the default channel order used by most non-WaveFormatEx-based APIs
1849 void SetDefaultChannelOrder(ALCdevice *device)
1851 switch(aluChannelsFromFormat(device->Format))
1853 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1855 case 2: device->DevChannels[FRONT_LEFT] = 0;
1856 device->DevChannels[FRONT_RIGHT] = 1; break;
1858 case 4: device->DevChannels[FRONT_LEFT] = 0;
1859 device->DevChannels[FRONT_RIGHT] = 1;
1860 device->DevChannels[BACK_LEFT] = 2;
1861 device->DevChannels[BACK_RIGHT] = 3; break;
1863 case 6: device->DevChannels[FRONT_LEFT] = 0;
1864 device->DevChannels[FRONT_RIGHT] = 1;
1865 device->DevChannels[BACK_LEFT] = 2;
1866 device->DevChannels[BACK_RIGHT] = 3;
1867 device->DevChannels[FRONT_CENTER] = 4;
1868 device->DevChannels[LFE] = 5; break;
1870 case 7: device->DevChannels[FRONT_LEFT] = 0;
1871 device->DevChannels[FRONT_RIGHT] = 1;
1872 device->DevChannels[FRONT_CENTER] = 2;
1873 device->DevChannels[LFE] = 3;
1874 device->DevChannels[BACK_CENTER] = 4;
1875 device->DevChannels[SIDE_LEFT] = 5;
1876 device->DevChannels[SIDE_RIGHT] = 6; break;
1878 case 8: device->DevChannels[FRONT_LEFT] = 0;
1879 device->DevChannels[FRONT_RIGHT] = 1;
1880 device->DevChannels[BACK_LEFT] = 2;
1881 device->DevChannels[BACK_RIGHT] = 3;
1882 device->DevChannels[FRONT_CENTER] = 4;
1883 device->DevChannels[LFE] = 5;
1884 device->DevChannels[SIDE_LEFT] = 6;
1885 device->DevChannels[SIDE_RIGHT] = 7; break;
1888 // Sets the default order used by WaveFormatEx
1889 void SetDefaultWFXChannelOrder(ALCdevice *device)
1891 switch(aluChannelsFromFormat(device->Format))
1893 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1895 case 2: device->DevChannels[FRONT_LEFT] = 0;
1896 device->DevChannels[FRONT_RIGHT] = 1; break;
1898 case 4: device->DevChannels[FRONT_LEFT] = 0;
1899 device->DevChannels[FRONT_RIGHT] = 1;
1900 device->DevChannels[BACK_LEFT] = 2;
1901 device->DevChannels[BACK_RIGHT] = 3; break;
1903 case 6: device->DevChannels[FRONT_LEFT] = 0;
1904 device->DevChannels[FRONT_RIGHT] = 1;
1905 device->DevChannels[FRONT_CENTER] = 2;
1906 device->DevChannels[LFE] = 3;
1907 device->DevChannels[BACK_LEFT] = 4;
1908 device->DevChannels[BACK_RIGHT] = 5; break;
1910 case 7: device->DevChannels[FRONT_LEFT] = 0;
1911 device->DevChannels[FRONT_RIGHT] = 1;
1912 device->DevChannels[FRONT_CENTER] = 2;
1913 device->DevChannels[LFE] = 3;
1914 device->DevChannels[BACK_CENTER] = 4;
1915 device->DevChannels[SIDE_LEFT] = 5;
1916 device->DevChannels[SIDE_RIGHT] = 6; break;
1918 case 8: device->DevChannels[FRONT_LEFT] = 0;
1919 device->DevChannels[FRONT_RIGHT] = 1;
1920 device->DevChannels[FRONT_CENTER] = 2;
1921 device->DevChannels[LFE] = 3;
1922 device->DevChannels[BACK_LEFT] = 4;
1923 device->DevChannels[BACK_RIGHT] = 5;
1924 device->DevChannels[SIDE_LEFT] = 6;
1925 device->DevChannels[SIDE_RIGHT] = 7; break;
1929 static ALenum GetFormatFromString(const char *str)
1931 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1932 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1933 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1934 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1935 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1936 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1938 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1939 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1940 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1941 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1942 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1943 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1945 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1946 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1947 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1948 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1949 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1950 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1952 AL_PRINT("Unknown format: \"%s\"\n", str);
1953 return AL_FORMAT_STEREO16;
1957 alcOpenDevice
1959 Open the Device specified.
1961 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
1963 ALboolean bDeviceFound = AL_FALSE;
1964 const ALCchar *fmt;
1965 ALCdevice *device;
1966 ALint i;
1968 if(deviceName && !deviceName[0])
1969 deviceName = NULL;
1971 device = calloc(1, sizeof(ALCdevice));
1972 if(!device)
1974 alcSetError(NULL, ALC_OUT_OF_MEMORY);
1975 return NULL;
1978 //Validate device
1979 device->Connected = ALC_TRUE;
1980 device->IsCaptureDevice = AL_FALSE;
1981 device->LastError = ALC_NO_ERROR;
1983 device->Bs2b = NULL;
1984 device->szDeviceName = NULL;
1986 device->Contexts = NULL;
1987 device->NumContexts = 0;
1989 InitUIntMap(&device->BufferMap);
1990 InitUIntMap(&device->EffectMap);
1991 InitUIntMap(&device->FilterMap);
1992 InitUIntMap(&device->DatabufferMap);
1994 //Set output format
1995 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1996 if(device->Frequency < 8000)
1997 device->Frequency = 8000;
1999 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
2000 device->Format = GetFormatFromString(fmt);
2002 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
2003 if(device->NumUpdates < 2)
2004 device->NumUpdates = 4;
2006 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);
2007 if(device->UpdateSize <= 0)
2008 device->UpdateSize = 1024;
2010 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
2011 if((ALint)device->MaxNoOfSources <= 0)
2012 device->MaxNoOfSources = 256;
2014 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
2015 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
2016 device->AuxiliaryEffectSlotMax = 4;
2018 device->NumStereoSources = 1;
2019 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2021 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
2022 if(device->NumAuxSends > MAX_SENDS)
2023 device->NumAuxSends = MAX_SENDS;
2025 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
2027 device->HeadDampen = 0.0f;
2029 // Find a playback device to open
2030 SuspendContext(NULL);
2031 for(i = 0;BackendList[i].Init;i++)
2033 device->Funcs = &BackendList[i].Funcs;
2034 if(ALCdevice_OpenPlayback(device, deviceName))
2036 device->next = g_pDeviceList;
2037 g_pDeviceList = device;
2038 g_ulDeviceCount++;
2040 bDeviceFound = AL_TRUE;
2041 break;
2044 ProcessContext(NULL);
2046 if(!bDeviceFound)
2048 // No suitable output device found
2049 alcSetError(NULL, ALC_INVALID_VALUE);
2050 free(device);
2051 device = NULL;
2054 return device;
2059 alcCloseDevice
2061 Close the specified Device
2063 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
2065 ALCdevice **list;
2067 if(!IsDevice(pDevice) || pDevice->IsCaptureDevice)
2069 alcSetError(pDevice, ALC_INVALID_DEVICE);
2070 return ALC_FALSE;
2073 SuspendContext(NULL);
2075 list = &g_pDeviceList;
2076 while(*list != pDevice)
2077 list = &(*list)->next;
2079 *list = (*list)->next;
2080 g_ulDeviceCount--;
2082 ProcessContext(NULL);
2084 if(pDevice->NumContexts > 0)
2086 #ifdef _DEBUG
2087 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
2088 #endif
2089 while(pDevice->NumContexts > 0)
2090 alcDestroyContext(pDevice->Contexts[0]);
2092 ALCdevice_ClosePlayback(pDevice);
2094 if(pDevice->BufferMap.size > 0)
2096 #ifdef _DEBUG
2097 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);
2098 #endif
2099 ReleaseALBuffers(pDevice);
2101 ResetUIntMap(&pDevice->BufferMap);
2103 if(pDevice->EffectMap.size > 0)
2105 #ifdef _DEBUG
2106 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);
2107 #endif
2108 ReleaseALEffects(pDevice);
2110 ResetUIntMap(&pDevice->EffectMap);
2112 if(pDevice->FilterMap.size > 0)
2114 #ifdef _DEBUG
2115 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);
2116 #endif
2117 ReleaseALFilters(pDevice);
2119 ResetUIntMap(&pDevice->FilterMap);
2121 if(pDevice->DatabufferMap.size > 0)
2123 #ifdef _DEBUG
2124 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferMap.size);
2125 #endif
2126 ReleaseALDatabuffers(pDevice);
2128 ResetUIntMap(&pDevice->DatabufferMap);
2130 free(pDevice->Bs2b);
2131 pDevice->Bs2b = NULL;
2133 free(pDevice->szDeviceName);
2134 pDevice->szDeviceName = NULL;
2136 free(pDevice->Contexts);
2137 pDevice->Contexts = NULL;
2139 //Release device structure
2140 memset(pDevice, 0, sizeof(ALCdevice));
2141 free(pDevice);
2143 return ALC_TRUE;
2147 ALCvoid ReleaseALC(ALCvoid)
2149 free(alcDeviceList); alcDeviceList = NULL;
2150 alcDeviceListSize = 0;
2151 free(alcAllDeviceList); alcAllDeviceList = NULL;
2152 alcAllDeviceListSize = 0;
2153 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
2154 alcCaptureDeviceListSize = 0;
2156 free(alcDefaultDeviceSpecifier);
2157 alcDefaultDeviceSpecifier = NULL;
2158 free(alcDefaultAllDeviceSpecifier);
2159 alcDefaultAllDeviceSpecifier = NULL;
2160 free(alcCaptureDefaultDeviceSpecifier);
2161 alcCaptureDefaultDeviceSpecifier = NULL;
2163 #ifdef _DEBUG
2164 if(g_ulDeviceCount > 0)
2165 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
2166 #endif
2168 while(g_pDeviceList)
2170 if(g_pDeviceList->IsCaptureDevice)
2171 alcCaptureCloseDevice(g_pDeviceList);
2172 else
2173 alcCloseDevice(g_pDeviceList);
2177 ///////////////////////////////////////////////////////