Merge branch 'master' of git://repo.or.cz/openal-soft
[openal-soft/android/lowlatency.git] / Alc / ALc.c
blobcc3896567a2d877398bcd2cac1772316fec8b0be
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 #ifdef HAVE_WAVE
78 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
79 #endif
81 { NULL, NULL, NULL, NULL, EmptyFuncs }
83 #undef EmptyFuncs
85 ///////////////////////////////////////////////////////
87 #define ALC_EFX_MAJOR_VERSION 0x20001
88 #define ALC_EFX_MINOR_VERSION 0x20002
89 #define ALC_MAX_AUXILIARY_SENDS 0x20003
91 ///////////////////////////////////////////////////////
92 // STRING and EXTENSIONS
94 typedef struct ALCfunction {
95 const ALCchar *funcName;
96 ALCvoid *address;
97 } ALCfunction;
99 typedef struct ALCenums {
100 const ALCchar *enumName;
101 ALCenum value;
102 } ALCenums;
105 static const ALCfunction alcFunctions[] = {
106 { "alcCreateContext", (ALCvoid *) alcCreateContext },
107 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },
108 { "alcProcessContext", (ALCvoid *) alcProcessContext },
109 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },
110 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },
111 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },
112 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },
113 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },
114 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },
115 { "alcGetError", (ALCvoid *) alcGetError },
116 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },
117 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },
118 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },
119 { "alcGetString", (ALCvoid *) alcGetString },
120 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },
121 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },
122 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },
123 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },
124 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },
125 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },
127 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },
128 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },
130 { "alEnable", (ALCvoid *) alEnable },
131 { "alDisable", (ALCvoid *) alDisable },
132 { "alIsEnabled", (ALCvoid *) alIsEnabled },
133 { "alGetString", (ALCvoid *) alGetString },
134 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },
135 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },
136 { "alGetFloatv", (ALCvoid *) alGetFloatv },
137 { "alGetDoublev", (ALCvoid *) alGetDoublev },
138 { "alGetBoolean", (ALCvoid *) alGetBoolean },
139 { "alGetInteger", (ALCvoid *) alGetInteger },
140 { "alGetFloat", (ALCvoid *) alGetFloat },
141 { "alGetDouble", (ALCvoid *) alGetDouble },
142 { "alGetError", (ALCvoid *) alGetError },
143 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },
144 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },
145 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },
146 { "alListenerf", (ALCvoid *) alListenerf },
147 { "alListener3f", (ALCvoid *) alListener3f },
148 { "alListenerfv", (ALCvoid *) alListenerfv },
149 { "alListeneri", (ALCvoid *) alListeneri },
150 { "alListener3i", (ALCvoid *) alListener3i },
151 { "alListeneriv", (ALCvoid *) alListeneriv },
152 { "alGetListenerf", (ALCvoid *) alGetListenerf },
153 { "alGetListener3f", (ALCvoid *) alGetListener3f },
154 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },
155 { "alGetListeneri", (ALCvoid *) alGetListeneri },
156 { "alGetListener3i", (ALCvoid *) alGetListener3i },
157 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },
158 { "alGenSources", (ALCvoid *) alGenSources },
159 { "alDeleteSources", (ALCvoid *) alDeleteSources },
160 { "alIsSource", (ALCvoid *) alIsSource },
161 { "alSourcef", (ALCvoid *) alSourcef },
162 { "alSource3f", (ALCvoid *) alSource3f },
163 { "alSourcefv", (ALCvoid *) alSourcefv },
164 { "alSourcei", (ALCvoid *) alSourcei },
165 { "alSource3i", (ALCvoid *) alSource3i },
166 { "alSourceiv", (ALCvoid *) alSourceiv },
167 { "alGetSourcef", (ALCvoid *) alGetSourcef },
168 { "alGetSource3f", (ALCvoid *) alGetSource3f },
169 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },
170 { "alGetSourcei", (ALCvoid *) alGetSourcei },
171 { "alGetSource3i", (ALCvoid *) alGetSource3i },
172 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },
173 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },
174 { "alSourceStopv", (ALCvoid *) alSourceStopv },
175 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },
176 { "alSourcePausev", (ALCvoid *) alSourcePausev },
177 { "alSourcePlay", (ALCvoid *) alSourcePlay },
178 { "alSourceStop", (ALCvoid *) alSourceStop },
179 { "alSourceRewind", (ALCvoid *) alSourceRewind },
180 { "alSourcePause", (ALCvoid *) alSourcePause },
181 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },
182 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },
183 { "alGenBuffers", (ALCvoid *) alGenBuffers },
184 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },
185 { "alIsBuffer", (ALCvoid *) alIsBuffer },
186 { "alBufferData", (ALCvoid *) alBufferData },
187 { "alBufferf", (ALCvoid *) alBufferf },
188 { "alBuffer3f", (ALCvoid *) alBuffer3f },
189 { "alBufferfv", (ALCvoid *) alBufferfv },
190 { "alBufferi", (ALCvoid *) alBufferi },
191 { "alBuffer3i", (ALCvoid *) alBuffer3i },
192 { "alBufferiv", (ALCvoid *) alBufferiv },
193 { "alGetBufferf", (ALCvoid *) alGetBufferf },
194 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },
195 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },
196 { "alGetBufferi", (ALCvoid *) alGetBufferi },
197 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },
198 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },
199 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },
200 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },
201 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },
202 { "alDistanceModel", (ALCvoid *) alDistanceModel },
204 { "alGenFilters", (ALCvoid *) alGenFilters },
205 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },
206 { "alIsFilter", (ALCvoid *) alIsFilter },
207 { "alFilteri", (ALCvoid *) alFilteri },
208 { "alFilteriv", (ALCvoid *) alFilteriv },
209 { "alFilterf", (ALCvoid *) alFilterf },
210 { "alFilterfv", (ALCvoid *) alFilterfv },
211 { "alGetFilteri", (ALCvoid *) alGetFilteri },
212 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },
213 { "alGetFilterf", (ALCvoid *) alGetFilterf },
214 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },
216 { "alGenEffects", (ALCvoid *) alGenEffects },
217 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },
218 { "alIsEffect", (ALCvoid *) alIsEffect },
219 { "alEffecti", (ALCvoid *) alEffecti },
220 { "alEffectiv", (ALCvoid *) alEffectiv },
221 { "alEffectf", (ALCvoid *) alEffectf },
222 { "alEffectfv", (ALCvoid *) alEffectfv },
223 { "alGetEffecti", (ALCvoid *) alGetEffecti },
224 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },
225 { "alGetEffectf", (ALCvoid *) alGetEffectf },
226 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },
228 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},
229 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},
230 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },
231 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },
232 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },
233 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },
234 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },
235 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},
236 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},
237 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},
238 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},
240 { "alBufferSubDataEXT", (ALCvoid *) alBufferSubDataEXT },
242 { "alGenDatabuffersEXT", (ALCvoid *) alGenDatabuffersEXT },
243 { "alDeleteDatabuffersEXT", (ALCvoid *) alDeleteDatabuffersEXT },
244 { "alIsDatabufferEXT", (ALCvoid *) alIsDatabufferEXT },
245 { "alDatabufferDataEXT", (ALCvoid *) alDatabufferDataEXT },
246 { "alDatabufferSubDataEXT", (ALCvoid *) alDatabufferSubDataEXT },
247 { "alGetDatabufferSubDataEXT", (ALCvoid *) alGetDatabufferSubDataEXT},
248 { "alDatabufferfEXT", (ALCvoid *) alDatabufferfEXT },
249 { "alDatabufferfvEXT", (ALCvoid *) alDatabufferfvEXT },
250 { "alDatabufferiEXT", (ALCvoid *) alDatabufferiEXT },
251 { "alDatabufferivEXT", (ALCvoid *) alDatabufferivEXT },
252 { "alGetDatabufferfEXT", (ALCvoid *) alGetDatabufferfEXT },
253 { "alGetDatabufferfvEXT", (ALCvoid *) alGetDatabufferfvEXT },
254 { "alGetDatabufferiEXT", (ALCvoid *) alGetDatabufferiEXT },
255 { "alGetDatabufferivEXT", (ALCvoid *) alGetDatabufferivEXT },
256 { "alSelectDatabufferEXT", (ALCvoid *) alSelectDatabufferEXT },
257 { "alMapDatabufferEXT", (ALCvoid *) alMapDatabufferEXT },
258 { "alUnmapDatabufferEXT", (ALCvoid *) alUnmapDatabufferEXT },
260 { NULL, (ALCvoid *) NULL }
263 static const ALCenums enumeration[] = {
264 // Types
265 { "ALC_INVALID", ALC_INVALID },
266 { "ALC_FALSE", ALC_FALSE },
267 { "ALC_TRUE", ALC_TRUE },
269 // ALC Properties
270 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
271 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },
272 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
273 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
274 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
275 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
276 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
277 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
278 { "ALC_EXTENSIONS", ALC_EXTENSIONS },
279 { "ALC_FREQUENCY", ALC_FREQUENCY },
280 { "ALC_REFRESH", ALC_REFRESH },
281 { "ALC_SYNC", ALC_SYNC },
282 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },
283 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
284 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
285 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
286 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
287 { "ALC_CONNECTED", ALC_CONNECTED },
289 // EFX Properties
290 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
291 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
292 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
294 // ALC Error Message
295 { "ALC_NO_ERROR", ALC_NO_ERROR },
296 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
297 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
298 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },
299 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },
300 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
301 { NULL, (ALCenum)0 }
303 // Error strings
304 static const ALCchar alcNoError[] = "No Error";
305 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
306 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
307 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
308 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
309 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
311 /* Device lists. Sizes only include the first ending null character, not the
312 * second */
313 static ALCchar *alcDeviceList;
314 static size_t alcDeviceListSize;
315 static ALCchar *alcAllDeviceList;
316 static size_t alcAllDeviceListSize;
317 static ALCchar *alcCaptureDeviceList;
318 static size_t alcCaptureDeviceListSize;
319 // Default is always the first in the list
320 static ALCchar *alcDefaultDeviceSpecifier;
321 static ALCchar *alcDefaultAllDeviceSpecifier;
322 static ALCchar *alcCaptureDefaultDeviceSpecifier;
325 static const ALCchar alcNoDeviceExtList[] =
326 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
327 "ALC_EXT_thread_local_context";
328 static const ALCchar alcExtensionList[] =
329 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
330 "ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context";
331 static const ALCint alcMajorVersion = 1;
332 static const ALCint alcMinorVersion = 1;
334 static const ALCint alcEFXMajorVersion = 1;
335 static const ALCint alcEFXMinorVersion = 0;
337 ///////////////////////////////////////////////////////
340 ///////////////////////////////////////////////////////
341 // Global Variables
343 static ALCdevice *g_pDeviceList = NULL;
344 static ALCuint g_ulDeviceCount = 0;
346 static CRITICAL_SECTION g_csMutex;
348 // Context List
349 static ALCcontext *g_pContextList = NULL;
350 static ALCuint g_ulContextCount = 0;
352 // Thread-local current context
353 static tls_type LocalContext;
354 // Process-wide current context
355 static ALCcontext *GlobalContext;
357 // Context Error
358 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
360 // Default context extensions
361 static const ALchar alExtList[] =
362 "AL_EXTX_buffer_sub_data AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
363 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXTX_loop_points "
364 "AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
365 "AL_EXTX_sample_buffer_object AL_EXT_source_distance_model "
366 "AL_LOKI_quadriphonic";
368 // Mixing Priority Level
369 static ALint RTPrioLevel;
371 // Resampler Quality
372 resampler_t DefaultResampler;
374 // Output Log File
375 static FILE *LogFile;
377 ///////////////////////////////////////////////////////
380 ///////////////////////////////////////////////////////
381 // ALC Related helper functions
382 #ifdef _WIN32
383 static void alc_init(void);
384 static void alc_deinit(void);
386 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
388 (void)lpReserved;
390 // Perform actions based on the reason for calling.
391 switch(ul_reason_for_call)
393 case DLL_PROCESS_ATTACH:
394 DisableThreadLibraryCalls(hModule);
395 alc_init();
396 break;
398 case DLL_PROCESS_DETACH:
399 alc_deinit();
400 break;
402 return TRUE;
404 #else
405 #ifdef HAVE_GCC_DESTRUCTOR
406 static void alc_init(void) __attribute__((constructor));
407 static void alc_deinit(void) __attribute__((destructor));
408 #endif
409 #endif
411 static void alc_init(void)
413 int i;
414 const char *devs, *str;
416 str = getenv("ALSOFT_LOGFILE");
417 if(str && str[0])
419 LogFile = fopen(str, "w");
420 if(!LogFile)
421 fprintf(stderr, "AL lib: Failed to open log file '%s'\n", str);
423 if(!LogFile)
424 LogFile = stderr;
426 InitializeCriticalSection(&g_csMutex);
427 ALTHUNK_INIT();
428 ReadALConfig();
430 tls_create(&LocalContext);
432 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
434 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
435 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
436 DefaultResampler = RESAMPLER_DEFAULT;
438 devs = GetConfigValue(NULL, "drivers", "");
439 if(devs[0])
441 int n;
442 size_t len;
443 const char *next = devs;
444 int endlist, delitem;
446 i = 0;
447 do {
448 devs = next;
449 next = strchr(devs, ',');
451 delitem = (devs[0] == '-');
452 if(devs[0] == '-') devs++;
454 if(!devs[0] || devs[0] == ',')
456 endlist = 0;
457 continue;
459 endlist = 1;
461 len = (next ? ((size_t)(next-devs)) : strlen(devs));
462 for(n = i;BackendList[n].Init;n++)
464 if(len == strlen(BackendList[n].name) &&
465 strncmp(BackendList[n].name, devs, len) == 0)
467 if(delitem)
469 do {
470 BackendList[n] = BackendList[n+1];
471 ++n;
472 } while(BackendList[n].Init);
474 else
476 BackendInfo Bkp = BackendList[n];
477 while(n > i)
479 BackendList[n] = BackendList[n-1];
480 --n;
482 BackendList[n] = Bkp;
484 i++;
486 break;
489 } while(next++);
491 if(endlist)
493 BackendList[i].name = NULL;
494 BackendList[i].Init = NULL;
495 BackendList[i].Deinit = NULL;
496 BackendList[i].Probe = NULL;
500 for(i = 0;BackendList[i].Init;i++)
501 BackendList[i].Init(&BackendList[i].Funcs);
503 str = GetConfigValue(NULL, "excludefx", "");
504 if(str[0])
506 const struct {
507 const char *name;
508 int type;
509 } EffectList[] = {
510 { "eaxreverb", EAXREVERB },
511 { "reverb", REVERB },
512 { "echo", ECHO },
513 { "modulator", MODULATOR },
514 { NULL, 0 }
516 int n;
517 size_t len;
518 const char *next = str;
520 do {
521 str = next;
522 next = strchr(str, ',');
524 if(!str[0] || next == str)
525 continue;
527 len = (next ? ((size_t)(next-str)) : strlen(str));
528 for(n = 0;EffectList[n].name;n++)
530 if(len == strlen(EffectList[n].name) &&
531 strncmp(EffectList[n].name, str, len) == 0)
532 DisabledEffects[EffectList[n].type] = AL_TRUE;
534 } while(next++);
538 static void alc_deinit(void)
540 int i;
542 ReleaseALC();
544 for(i = 0;BackendList[i].Deinit;i++)
545 BackendList[i].Deinit();
547 if(LogFile != stderr)
548 fclose(LogFile);
549 LogFile = NULL;
551 tls_delete(LocalContext);
553 FreeALConfig();
554 ALTHUNK_EXIT();
555 DeleteCriticalSection(&g_csMutex);
559 static void ProbeDeviceList()
561 ALint i;
563 free(alcDeviceList); alcDeviceList = NULL;
564 alcDeviceListSize = 0;
566 for(i = 0;BackendList[i].Probe;i++)
567 BackendList[i].Probe(DEVICE_PROBE);
570 static void ProbeAllDeviceList()
572 ALint i;
574 free(alcAllDeviceList); alcAllDeviceList = NULL;
575 alcAllDeviceListSize = 0;
577 for(i = 0;BackendList[i].Probe;i++)
578 BackendList[i].Probe(ALL_DEVICE_PROBE);
581 static void ProbeCaptureDeviceList()
583 ALint i;
585 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
586 alcCaptureDeviceListSize = 0;
588 for(i = 0;BackendList[i].Probe;i++)
589 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
593 #define DECL_APPEND_LIST_FUNC(type) \
594 void Append##type##List(const ALCchar *name) \
596 size_t len = strlen(name); \
597 void *temp; \
599 if(len == 0) \
600 return; \
602 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
603 if(!temp) \
605 AL_PRINT("Realloc failed to add %s!\n", name); \
606 return; \
608 alc##type##List = temp; \
609 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
610 alc##type##ListSize += len+1; \
611 alc##type##List[alc##type##ListSize] = 0; \
614 DECL_APPEND_LIST_FUNC(Device)
615 DECL_APPEND_LIST_FUNC(AllDevice)
616 DECL_APPEND_LIST_FUNC(CaptureDevice)
619 void al_print(const char *fname, unsigned int line, const char *fmt, ...)
621 const char *fn;
622 char str[256];
623 int i;
625 fn = strrchr(fname, '/');
626 if(!fn) fn = strrchr(fname, '\\');;
627 if(!fn) fn = fname;
628 else fn += 1;
630 i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
631 if(i < (int)sizeof(str) && i > 0)
633 va_list ap;
634 va_start(ap, fmt);
635 vsnprintf(str+i, sizeof(str)-i, fmt, ap);
636 va_end(ap);
638 str[sizeof(str)-1] = 0;
640 #ifdef ANDROID
641 __android_log_write(ANDROID_LOG_WARN, "OpenAL", str);
642 #endif
643 fprintf(LogFile, "%s", str);
644 fflush(LogFile);
647 void SetRTPriority(void)
649 ALboolean failed;
651 #ifdef _WIN32
652 if(RTPrioLevel > 0)
653 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
654 else
655 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
656 #elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
657 struct sched_param param;
659 if(RTPrioLevel > 0)
661 /* Use the minimum real-time priority possible for now (on Linux this
662 * should be 1 for SCHED_RR) */
663 param.sched_priority = sched_get_priority_min(SCHED_RR);
664 failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
666 else
668 param.sched_priority = 0;
669 failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
671 #else
672 /* Real-time priority not available */
673 failed = (RTPrioLevel>0);
674 #endif
675 if(failed)
676 AL_PRINT("Failed to set priority level for thread\n");
680 void InitUIntMap(UIntMap *map)
682 map->array = NULL;
683 map->size = 0;
684 map->maxsize = 0;
687 void ResetUIntMap(UIntMap *map)
689 free(map->array);
690 map->array = NULL;
691 map->size = 0;
692 map->maxsize = 0;
695 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
697 ALsizei pos = 0;
699 if(map->size > 0)
701 ALsizei low = 0;
702 ALsizei high = map->size - 1;
703 while(low < high)
705 ALsizei mid = low + (high-low)/2;
706 if(map->array[mid].key < key)
707 low = mid + 1;
708 else
709 high = mid;
711 if(map->array[low].key < key)
712 low++;
713 pos = low;
716 if(pos == map->size || map->array[pos].key != key)
718 if(map->size == map->maxsize)
720 ALvoid *temp;
721 ALsizei newsize;
723 newsize = (map->maxsize ? (map->maxsize<<1) : 4);
724 if(newsize < map->maxsize)
725 return AL_OUT_OF_MEMORY;
727 temp = realloc(map->array, newsize*sizeof(map->array[0]));
728 if(!temp) return AL_OUT_OF_MEMORY;
729 map->array = temp;
730 map->maxsize = newsize;
733 map->size++;
734 if(pos < map->size-1)
735 memmove(&map->array[pos+1], &map->array[pos],
736 (map->size-1-pos)*sizeof(map->array[0]));
738 map->array[pos].key = key;
739 map->array[pos].value = value;
741 return AL_NO_ERROR;
744 void RemoveUIntMapKey(UIntMap *map, ALuint key)
746 if(map->size > 0)
748 ALsizei low = 0;
749 ALsizei high = map->size - 1;
750 while(low < high)
752 ALsizei mid = low + (high-low)/2;
753 if(map->array[mid].key < key)
754 low = mid + 1;
755 else
756 high = mid;
758 if(map->array[low].key == key)
760 if(low < map->size-1)
761 memmove(&map->array[low], &map->array[low+1],
762 (map->size-1-low)*sizeof(map->array[0]));
763 map->size--;
770 IsDevice
772 Check pDevice is a valid Device pointer
774 static ALCboolean IsDevice(ALCdevice *pDevice)
776 ALCdevice *pTempDevice;
778 SuspendContext(NULL);
780 pTempDevice = g_pDeviceList;
781 while(pTempDevice && pTempDevice != pDevice)
782 pTempDevice = pTempDevice->next;
784 ProcessContext(NULL);
786 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
790 IsContext
792 Check pContext is a valid Context pointer
794 static ALCboolean IsContext(ALCcontext *pContext)
796 ALCcontext *pTempContext;
798 SuspendContext(NULL);
800 pTempContext = g_pContextList;
801 while (pTempContext && pTempContext != pContext)
802 pTempContext = pTempContext->next;
804 ProcessContext(NULL);
806 return (pTempContext ? ALC_TRUE : ALC_FALSE);
811 alcSetError
813 Store latest ALC Error
815 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
817 if(IsDevice(device))
818 device->LastError = errorCode;
819 else
820 g_eLastNullDeviceError = errorCode;
825 SuspendContext
827 Thread-safe entry
829 ALCvoid SuspendContext(ALCcontext *pContext)
831 (void)pContext;
832 EnterCriticalSection(&g_csMutex);
837 ProcessContext
839 Thread-safe exit
841 ALCvoid ProcessContext(ALCcontext *pContext)
843 (void)pContext;
844 LeaveCriticalSection(&g_csMutex);
849 GetContextSuspended
851 Returns the currently active Context, in a locked state
853 ALCcontext *GetContextSuspended(void)
855 ALCcontext *pContext = NULL;
857 SuspendContext(NULL);
859 pContext = tls_get(LocalContext);
860 if(pContext && !IsContext(pContext))
862 tls_set(LocalContext, NULL);
863 pContext = NULL;
865 if(!pContext)
866 pContext = GlobalContext;
868 if(pContext)
869 SuspendContext(pContext);
871 ProcessContext(NULL);
873 return pContext;
878 InitContext
880 Initialize Context variables
882 static ALvoid InitContext(ALCcontext *pContext)
884 //Initialise listener
885 pContext->Listener.Gain = 1.0f;
886 pContext->Listener.MetersPerUnit = 1.0f;
887 pContext->Listener.Position[0] = 0.0f;
888 pContext->Listener.Position[1] = 0.0f;
889 pContext->Listener.Position[2] = 0.0f;
890 pContext->Listener.Velocity[0] = 0.0f;
891 pContext->Listener.Velocity[1] = 0.0f;
892 pContext->Listener.Velocity[2] = 0.0f;
893 pContext->Listener.Forward[0] = 0.0f;
894 pContext->Listener.Forward[1] = 0.0f;
895 pContext->Listener.Forward[2] = -1.0f;
896 pContext->Listener.Up[0] = 0.0f;
897 pContext->Listener.Up[1] = 1.0f;
898 pContext->Listener.Up[2] = 0.0f;
900 //Validate pContext
901 pContext->LastError = AL_NO_ERROR;
902 pContext->Suspended = AL_FALSE;
903 pContext->ActiveSourceCount = 0;
904 InitUIntMap(&pContext->SourceMap);
905 InitUIntMap(&pContext->EffectSlotMap);
907 //Set globals
908 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
909 pContext->SourceDistanceModel = AL_FALSE;
910 pContext->DopplerFactor = 1.0f;
911 pContext->DopplerVelocity = 1.0f;
912 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
914 pContext->ExtensionList = alExtList;
919 ExitContext
921 Clean up Context, destroy any remaining Sources
923 static ALCvoid ExitContext(ALCcontext *pContext)
925 //Invalidate context
926 pContext->LastError = AL_NO_ERROR;
929 ///////////////////////////////////////////////////////
932 ///////////////////////////////////////////////////////
933 // ALC Functions calls
936 // This should probably move to another c file but for now ...
937 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
939 ALCboolean DeviceFound = ALC_FALSE;
940 ALCdevice *device = NULL;
941 ALCint i;
943 if(SampleSize <= 0)
945 alcSetError(NULL, ALC_INVALID_VALUE);
946 return NULL;
949 if(deviceName && !deviceName[0])
950 deviceName = NULL;
952 device = calloc(1, sizeof(ALCdevice));
953 if(!device)
955 alcSetError(NULL, ALC_OUT_OF_MEMORY);
956 return NULL;
959 //Validate device
960 device->Connected = ALC_TRUE;
961 device->IsCaptureDevice = AL_TRUE;
963 device->szDeviceName = NULL;
965 device->Frequency = frequency;
966 device->Format = format;
967 device->UpdateSize = SampleSize;
968 device->NumUpdates = 1;
970 SuspendContext(NULL);
971 for(i = 0;BackendList[i].Init;i++)
973 device->Funcs = &BackendList[i].Funcs;
974 if(ALCdevice_OpenCapture(device, deviceName))
976 device->next = g_pDeviceList;
977 g_pDeviceList = device;
978 g_ulDeviceCount++;
980 DeviceFound = ALC_TRUE;
981 break;
984 ProcessContext(NULL);
986 if(!DeviceFound)
988 alcSetError(NULL, ALC_INVALID_VALUE);
989 free(device);
990 device = NULL;
993 return device;
996 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
998 ALCdevice **list;
1000 if(!IsDevice(pDevice) || !pDevice->IsCaptureDevice)
1002 alcSetError(pDevice, ALC_INVALID_DEVICE);
1003 return ALC_FALSE;
1006 SuspendContext(NULL);
1008 list = &g_pDeviceList;
1009 while(*list != pDevice)
1010 list = &(*list)->next;
1012 *list = (*list)->next;
1013 g_ulDeviceCount--;
1015 ProcessContext(NULL);
1017 ALCdevice_CloseCapture(pDevice);
1019 free(pDevice->szDeviceName);
1020 pDevice->szDeviceName = NULL;
1022 free(pDevice);
1024 return ALC_TRUE;
1027 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
1029 SuspendContext(NULL);
1030 if(!IsDevice(device) || !device->IsCaptureDevice)
1031 alcSetError(device, ALC_INVALID_DEVICE);
1032 else if(device->Connected)
1033 ALCdevice_StartCapture(device);
1034 ProcessContext(NULL);
1037 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
1039 SuspendContext(NULL);
1040 if(!IsDevice(device) || !device->IsCaptureDevice)
1041 alcSetError(device, ALC_INVALID_DEVICE);
1042 else
1043 ALCdevice_StopCapture(device);
1044 ProcessContext(NULL);
1047 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
1049 SuspendContext(NULL);
1050 if(!IsDevice(device) || !device->IsCaptureDevice)
1051 alcSetError(device, ALC_INVALID_DEVICE);
1052 else
1053 ALCdevice_CaptureSamples(device, buffer, samples);
1054 ProcessContext(NULL);
1058 alcGetError
1060 Return last ALC generated error code
1062 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1064 ALCenum errorCode;
1066 if(IsDevice(device))
1068 errorCode = device->LastError;
1069 device->LastError = ALC_NO_ERROR;
1071 else
1073 errorCode = g_eLastNullDeviceError;
1074 g_eLastNullDeviceError = ALC_NO_ERROR;
1076 return errorCode;
1081 alcSuspendContext
1083 Not functional
1085 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *pContext)
1087 SuspendContext(NULL);
1088 if(IsContext(pContext))
1089 pContext->Suspended = AL_TRUE;
1090 ProcessContext(NULL);
1095 alcProcessContext
1097 Not functional
1099 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *pContext)
1101 SuspendContext(NULL);
1102 if(IsContext(pContext))
1103 pContext->Suspended = AL_FALSE;
1104 ProcessContext(NULL);
1109 alcGetString
1111 Returns information about the Device, and error strings
1113 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
1115 const ALCchar *value = NULL;
1117 switch (param)
1119 case ALC_NO_ERROR:
1120 value = alcNoError;
1121 break;
1123 case ALC_INVALID_ENUM:
1124 value = alcErrInvalidEnum;
1125 break;
1127 case ALC_INVALID_VALUE:
1128 value = alcErrInvalidValue;
1129 break;
1131 case ALC_INVALID_DEVICE:
1132 value = alcErrInvalidDevice;
1133 break;
1135 case ALC_INVALID_CONTEXT:
1136 value = alcErrInvalidContext;
1137 break;
1139 case ALC_OUT_OF_MEMORY:
1140 value = alcErrOutOfMemory;
1141 break;
1143 case ALC_DEVICE_SPECIFIER:
1144 if(IsDevice(pDevice))
1145 value = pDevice->szDeviceName;
1146 else
1148 ProbeDeviceList();
1149 value = alcDeviceList;
1151 break;
1153 case ALC_ALL_DEVICES_SPECIFIER:
1154 ProbeAllDeviceList();
1155 value = alcAllDeviceList;
1156 break;
1158 case ALC_CAPTURE_DEVICE_SPECIFIER:
1159 if(IsDevice(pDevice))
1160 value = pDevice->szDeviceName;
1161 else
1163 ProbeCaptureDeviceList();
1164 value = alcCaptureDeviceList;
1166 break;
1168 /* Default devices are always first in the list */
1169 case ALC_DEFAULT_DEVICE_SPECIFIER:
1170 if(!alcDeviceList)
1171 ProbeDeviceList();
1173 free(alcDefaultDeviceSpecifier);
1174 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
1175 if(!alcDefaultDeviceSpecifier)
1176 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1177 value = alcDefaultDeviceSpecifier;
1178 break;
1180 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
1181 if(!alcAllDeviceList)
1182 ProbeAllDeviceList();
1184 free(alcDefaultAllDeviceSpecifier);
1185 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
1186 alcAllDeviceList : "");
1187 if(!alcDefaultAllDeviceSpecifier)
1188 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1189 value = alcDefaultAllDeviceSpecifier;
1190 break;
1192 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
1193 if(!alcCaptureDeviceList)
1194 ProbeCaptureDeviceList();
1196 free(alcCaptureDefaultDeviceSpecifier);
1197 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
1198 alcCaptureDeviceList : "");
1199 if(!alcCaptureDefaultDeviceSpecifier)
1200 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1201 value = alcCaptureDefaultDeviceSpecifier;
1202 break;
1204 case ALC_EXTENSIONS:
1205 if(IsDevice(pDevice))
1206 value = alcExtensionList;
1207 else
1208 value = alcNoDeviceExtList;
1209 break;
1211 default:
1212 alcSetError(pDevice, ALC_INVALID_ENUM);
1213 break;
1216 return value;
1221 alcGetIntegerv
1223 Returns information about the Device and the version of Open AL
1225 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
1227 if(size == 0 || data == NULL)
1229 alcSetError(device, ALC_INVALID_VALUE);
1230 return;
1233 if(IsDevice(device) && device->IsCaptureDevice)
1235 SuspendContext(NULL);
1237 // Capture device
1238 switch (param)
1240 case ALC_CAPTURE_SAMPLES:
1241 *data = ALCdevice_AvailableSamples(device);
1242 break;
1244 case ALC_CONNECTED:
1245 *data = device->Connected;
1246 break;
1248 default:
1249 alcSetError(device, ALC_INVALID_ENUM);
1250 break;
1253 ProcessContext(NULL);
1254 return;
1257 // Playback Device
1258 switch (param)
1260 case ALC_MAJOR_VERSION:
1261 *data = alcMajorVersion;
1262 break;
1264 case ALC_MINOR_VERSION:
1265 *data = alcMinorVersion;
1266 break;
1268 case ALC_EFX_MAJOR_VERSION:
1269 *data = alcEFXMajorVersion;
1270 break;
1272 case ALC_EFX_MINOR_VERSION:
1273 *data = alcEFXMinorVersion;
1274 break;
1276 case ALC_MAX_AUXILIARY_SENDS:
1277 if(!IsDevice(device))
1278 alcSetError(device, ALC_INVALID_DEVICE);
1279 else
1280 *data = device->NumAuxSends;
1281 break;
1283 case ALC_ATTRIBUTES_SIZE:
1284 if(!IsDevice(device))
1285 alcSetError(device, ALC_INVALID_DEVICE);
1286 else
1287 *data = 13;
1288 break;
1290 case ALC_ALL_ATTRIBUTES:
1291 if(!IsDevice(device))
1292 alcSetError(device, ALC_INVALID_DEVICE);
1293 else if (size < 13)
1294 alcSetError(device, ALC_INVALID_VALUE);
1295 else
1297 int i = 0;
1299 SuspendContext(NULL);
1300 data[i++] = ALC_FREQUENCY;
1301 data[i++] = device->Frequency;
1303 data[i++] = ALC_REFRESH;
1304 data[i++] = device->Frequency / device->UpdateSize;
1306 data[i++] = ALC_SYNC;
1307 data[i++] = ALC_FALSE;
1309 data[i++] = ALC_MONO_SOURCES;
1310 data[i++] = device->NumMonoSources;
1312 data[i++] = ALC_STEREO_SOURCES;
1313 data[i++] = device->NumStereoSources;
1315 data[i++] = ALC_MAX_AUXILIARY_SENDS;
1316 data[i++] = device->NumAuxSends;
1318 data[i++] = 0;
1319 ProcessContext(NULL);
1321 break;
1323 case ALC_FREQUENCY:
1324 if(!IsDevice(device))
1325 alcSetError(device, ALC_INVALID_DEVICE);
1326 else
1327 *data = device->Frequency;
1328 break;
1330 case ALC_REFRESH:
1331 if(!IsDevice(device))
1332 alcSetError(device, ALC_INVALID_DEVICE);
1333 else
1334 *data = device->Frequency / device->UpdateSize;
1335 break;
1337 case ALC_SYNC:
1338 if(!IsDevice(device))
1339 alcSetError(device, ALC_INVALID_DEVICE);
1340 else
1341 *data = ALC_FALSE;
1342 break;
1344 case ALC_MONO_SOURCES:
1345 if(!IsDevice(device))
1346 alcSetError(device, ALC_INVALID_DEVICE);
1347 else
1348 *data = device->NumMonoSources;
1349 break;
1351 case ALC_STEREO_SOURCES:
1352 if(!IsDevice(device))
1353 alcSetError(device, ALC_INVALID_DEVICE);
1354 else
1355 *data = device->NumStereoSources;
1356 break;
1358 case ALC_CONNECTED:
1359 if(!IsDevice(device))
1360 alcSetError(device, ALC_INVALID_DEVICE);
1361 else
1362 *data = device->Connected;
1363 break;
1365 default:
1366 alcSetError(device, ALC_INVALID_ENUM);
1367 break;
1373 alcIsExtensionPresent
1375 Determines if there is support for a particular extension
1377 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1379 ALCboolean bResult = ALC_FALSE;
1380 const char *ptr;
1381 size_t len;
1383 if(!extName)
1385 alcSetError(device, ALC_INVALID_VALUE);
1386 return ALC_FALSE;
1389 len = strlen(extName);
1390 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
1391 while(ptr && *ptr)
1393 if(strncasecmp(ptr, extName, len) == 0 &&
1394 (ptr[len] == '\0' || isspace(ptr[len])))
1396 bResult = ALC_TRUE;
1397 break;
1399 if((ptr=strchr(ptr, ' ')) != NULL)
1401 do {
1402 ++ptr;
1403 } while(isspace(*ptr));
1407 return bResult;
1412 alcGetProcAddress
1414 Retrieves the function address for a particular extension function
1416 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1418 ALsizei i = 0;
1420 if(!funcName)
1422 alcSetError(device, ALC_INVALID_VALUE);
1423 return NULL;
1426 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
1427 i++;
1428 return alcFunctions[i].address;
1433 alcGetEnumValue
1435 Get the value for a particular ALC Enumerated Value
1437 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1439 ALsizei i = 0;
1441 if(!enumName)
1443 alcSetError(device, ALC_INVALID_VALUE);
1444 return (ALCenum)0;
1447 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
1448 i++;
1449 return enumeration[i].value;
1454 alcCreateContext
1456 Create and attach a Context to a particular Device.
1458 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1460 ALCcontext *ALContext;
1461 ALboolean running;
1462 ALuint attrIdx;
1463 void *temp;
1464 ALuint i;
1466 SuspendContext(NULL);
1468 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1470 alcSetError(device, ALC_INVALID_DEVICE);
1471 ProcessContext(NULL);
1472 return NULL;
1475 running = ((device->NumContexts > 0) ? AL_TRUE : AL_FALSE);
1477 // Reset Context Last Error code
1478 device->LastError = ALC_NO_ERROR;
1480 // Check for attributes
1481 if(attrList && attrList[0])
1483 ALCuint freq, numMono, numStereo, numSends;
1485 // If a context is already running on the device, stop playback so the
1486 // device attributes can be updated
1487 if(running)
1489 ProcessContext(NULL);
1490 ALCdevice_StopPlayback(device);
1491 SuspendContext(NULL);
1492 running = AL_FALSE;
1495 freq = device->Frequency;
1496 numMono = device->NumMonoSources;
1497 numStereo = device->NumStereoSources;
1498 numSends = device->NumAuxSends;
1500 attrIdx = 0;
1501 while(attrList[attrIdx])
1503 if(attrList[attrIdx] == ALC_FREQUENCY &&
1504 !ConfigValueExists(NULL, "frequency"))
1506 freq = attrList[attrIdx + 1];
1507 if(freq < 8000)
1508 freq = 8000;
1511 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1513 numStereo = attrList[attrIdx + 1];
1514 if(numStereo > device->MaxNoOfSources)
1515 numStereo = device->MaxNoOfSources;
1517 numMono = device->MaxNoOfSources - numStereo;
1520 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
1521 !ConfigValueExists(NULL, "sends"))
1523 numSends = attrList[attrIdx + 1];
1524 if(numSends > MAX_SENDS)
1525 numSends = MAX_SENDS;
1528 attrIdx += 2;
1531 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1532 device->Frequency;
1534 device->Frequency = freq;
1535 device->NumMonoSources = numMono;
1536 device->NumStereoSources = numStereo;
1537 device->NumAuxSends = numSends;
1540 if(running == AL_FALSE && ALCdevice_ResetPlayback(device) == ALC_FALSE)
1542 alcSetError(device, ALC_INVALID_DEVICE);
1543 aluHandleDisconnect(device);
1544 ProcessContext(NULL);
1545 return NULL;
1547 aluInitPanning(device);
1549 for(i = 0;i < device->NumContexts;i++)
1551 ALCcontext *context = device->Contexts[i];
1552 ALsizei pos;
1554 SuspendContext(context);
1555 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1557 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1558 if(!slot->EffectState)
1559 continue;
1561 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1563 alcSetError(device, ALC_INVALID_DEVICE);
1564 aluHandleDisconnect(device);
1565 ProcessContext(context);
1566 ProcessContext(NULL);
1567 ALCdevice_StopPlayback(device);
1568 return NULL;
1570 ALEffect_Update(slot->EffectState, context, &slot->effect);
1573 for(pos = 0;pos < context->SourceMap.size;pos++)
1575 ALsource *source = context->SourceMap.array[pos].value;
1576 ALuint s = device->NumAuxSends;
1577 while(s < MAX_SENDS)
1579 if(source->Send[s].Slot)
1580 source->Send[s].Slot->refcount--;
1581 source->Send[s].Slot = NULL;
1582 source->Send[s].WetFilter.type = 0;
1583 source->Send[s].WetFilter.filter = 0;
1584 s++;
1586 source->NeedsUpdate = AL_TRUE;
1588 ProcessContext(context);
1591 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1593 if(!device->Bs2b)
1595 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1596 bs2b_clear(device->Bs2b);
1598 bs2b_set_srate(device->Bs2b, device->Frequency);
1599 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1601 else
1603 free(device->Bs2b);
1604 device->Bs2b = NULL;
1607 if(aluChannelsFromFormat(device->Format) <= 2)
1609 device->HeadDampen = GetConfigValueFloat(NULL, "head_dampen", DEFAULT_HEAD_DAMPEN);
1610 device->HeadDampen = __min(device->HeadDampen, 1.0f);
1611 device->HeadDampen = __max(device->HeadDampen, 0.0f);
1613 else
1614 device->HeadDampen = 0.0f;
1616 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1617 if(!temp)
1619 alcSetError(device, ALC_OUT_OF_MEMORY);
1620 ProcessContext(NULL);
1621 return NULL;
1623 device->Contexts = temp;
1625 ALContext = calloc(1, sizeof(ALCcontext));
1626 if(ALContext)
1628 ALContext->MaxActiveSources = 256;
1629 ALContext->ActiveSources = malloc(sizeof(*ALContext->ActiveSources) *
1630 ALContext->MaxActiveSources);
1632 if(!ALContext || !ALContext->ActiveSources)
1634 free(ALContext);
1635 alcSetError(device, ALC_OUT_OF_MEMORY);
1636 ProcessContext(NULL);
1637 return NULL;
1640 device->Contexts[device->NumContexts++] = ALContext;
1641 ALContext->Device = device;
1643 InitContext(ALContext);
1645 ALContext->next = g_pContextList;
1646 g_pContextList = ALContext;
1647 g_ulContextCount++;
1649 ProcessContext(NULL);
1651 return ALContext;
1656 alcDestroyContext
1658 Remove a Context
1660 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
1662 ALCdevice *Device;
1663 ALCcontext **list;
1664 ALuint i;
1666 if(!IsContext(context))
1668 alcSetError(NULL, ALC_INVALID_CONTEXT);
1669 return;
1672 Device = context->Device;
1674 if(Device->NumContexts == 1)
1675 ALCdevice_StopPlayback(Device);
1677 SuspendContext(NULL);
1679 if(context == GlobalContext)
1680 GlobalContext = NULL;
1682 for(i = 0;i < Device->NumContexts-1;i++)
1684 if(Device->Contexts[i] == context)
1686 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];
1687 break;
1690 Device->NumContexts--;
1692 // Lock context
1693 SuspendContext(context);
1695 if(context->SourceMap.size > 0)
1697 #ifdef _DEBUG
1698 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);
1699 #endif
1700 ReleaseALSources(context);
1702 ResetUIntMap(&context->SourceMap);
1704 if(context->EffectSlotMap.size > 0)
1706 #ifdef _DEBUG
1707 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);
1708 #endif
1709 ReleaseALAuxiliaryEffectSlots(context);
1711 ResetUIntMap(&context->EffectSlotMap);
1713 free(context->ActiveSources);
1714 context->ActiveSources = NULL;
1715 context->MaxActiveSources = 0;
1716 context->ActiveSourceCount = 0;
1718 list = &g_pContextList;
1719 while(*list != context)
1720 list = &(*list)->next;
1722 *list = (*list)->next;
1723 g_ulContextCount--;
1725 // Unlock context
1726 ProcessContext(context);
1727 ProcessContext(NULL);
1729 ExitContext(context);
1731 // Free memory (MUST do this after ProcessContext)
1732 memset(context, 0, sizeof(ALCcontext));
1733 free(context);
1738 alcGetCurrentContext
1740 Returns the currently active Context
1742 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
1744 ALCcontext *pContext;
1746 if((pContext=GetContextSuspended()) != NULL)
1747 ProcessContext(pContext);
1749 return pContext;
1753 alcGetThreadContext
1755 Returns the currently active thread-local Context
1757 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
1759 ALCcontext *pContext = NULL;
1761 SuspendContext(NULL);
1763 pContext = tls_get(LocalContext);
1764 if(pContext && !IsContext(pContext))
1766 tls_set(LocalContext, NULL);
1767 pContext = NULL;
1770 ProcessContext(NULL);
1772 return pContext;
1777 alcGetContextsDevice
1779 Returns the Device that a particular Context is attached to
1781 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)
1783 ALCdevice *pDevice = NULL;
1785 SuspendContext(NULL);
1786 if(IsContext(pContext))
1787 pDevice = pContext->Device;
1788 else
1789 alcSetError(NULL, ALC_INVALID_CONTEXT);
1790 ProcessContext(NULL);
1792 return pDevice;
1797 alcMakeContextCurrent
1799 Makes the given Context the active Context
1801 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
1803 ALboolean bReturn = AL_TRUE;
1805 SuspendContext(NULL);
1807 // context must be a valid Context or NULL
1808 if(context == NULL || IsContext(context))
1810 GlobalContext = context;
1811 tls_set(LocalContext, NULL);
1813 else
1815 alcSetError(NULL, ALC_INVALID_CONTEXT);
1816 bReturn = AL_FALSE;
1819 ProcessContext(NULL);
1821 return bReturn;
1825 alcSetThreadContext
1827 Makes the given Context the active Context for the current thread
1829 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
1831 ALboolean bReturn = AL_TRUE;
1833 SuspendContext(NULL);
1835 // context must be a valid Context or NULL
1836 if(context == NULL || IsContext(context))
1837 tls_set(LocalContext, context);
1838 else
1840 alcSetError(NULL, ALC_INVALID_CONTEXT);
1841 bReturn = AL_FALSE;
1844 ProcessContext(NULL);
1846 return bReturn;
1850 // Sets the default channel order used by most non-WaveFormatEx-based APIs
1851 void SetDefaultChannelOrder(ALCdevice *device)
1853 switch(aluChannelsFromFormat(device->Format))
1855 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1857 case 2: device->DevChannels[FRONT_LEFT] = 0;
1858 device->DevChannels[FRONT_RIGHT] = 1; break;
1860 case 4: device->DevChannels[FRONT_LEFT] = 0;
1861 device->DevChannels[FRONT_RIGHT] = 1;
1862 device->DevChannels[BACK_LEFT] = 2;
1863 device->DevChannels[BACK_RIGHT] = 3; break;
1865 case 6: device->DevChannels[FRONT_LEFT] = 0;
1866 device->DevChannels[FRONT_RIGHT] = 1;
1867 device->DevChannels[BACK_LEFT] = 2;
1868 device->DevChannels[BACK_RIGHT] = 3;
1869 device->DevChannels[FRONT_CENTER] = 4;
1870 device->DevChannels[LFE] = 5; break;
1872 case 7: device->DevChannels[FRONT_LEFT] = 0;
1873 device->DevChannels[FRONT_RIGHT] = 1;
1874 device->DevChannels[FRONT_CENTER] = 2;
1875 device->DevChannels[LFE] = 3;
1876 device->DevChannels[BACK_CENTER] = 4;
1877 device->DevChannels[SIDE_LEFT] = 5;
1878 device->DevChannels[SIDE_RIGHT] = 6; break;
1880 case 8: device->DevChannels[FRONT_LEFT] = 0;
1881 device->DevChannels[FRONT_RIGHT] = 1;
1882 device->DevChannels[BACK_LEFT] = 2;
1883 device->DevChannels[BACK_RIGHT] = 3;
1884 device->DevChannels[FRONT_CENTER] = 4;
1885 device->DevChannels[LFE] = 5;
1886 device->DevChannels[SIDE_LEFT] = 6;
1887 device->DevChannels[SIDE_RIGHT] = 7; break;
1890 // Sets the default order used by WaveFormatEx
1891 void SetDefaultWFXChannelOrder(ALCdevice *device)
1893 switch(aluChannelsFromFormat(device->Format))
1895 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1897 case 2: device->DevChannels[FRONT_LEFT] = 0;
1898 device->DevChannels[FRONT_RIGHT] = 1; break;
1900 case 4: device->DevChannels[FRONT_LEFT] = 0;
1901 device->DevChannels[FRONT_RIGHT] = 1;
1902 device->DevChannels[BACK_LEFT] = 2;
1903 device->DevChannels[BACK_RIGHT] = 3; break;
1905 case 6: device->DevChannels[FRONT_LEFT] = 0;
1906 device->DevChannels[FRONT_RIGHT] = 1;
1907 device->DevChannels[FRONT_CENTER] = 2;
1908 device->DevChannels[LFE] = 3;
1909 device->DevChannels[BACK_LEFT] = 4;
1910 device->DevChannels[BACK_RIGHT] = 5; break;
1912 case 7: device->DevChannels[FRONT_LEFT] = 0;
1913 device->DevChannels[FRONT_RIGHT] = 1;
1914 device->DevChannels[FRONT_CENTER] = 2;
1915 device->DevChannels[LFE] = 3;
1916 device->DevChannels[BACK_CENTER] = 4;
1917 device->DevChannels[SIDE_LEFT] = 5;
1918 device->DevChannels[SIDE_RIGHT] = 6; break;
1920 case 8: device->DevChannels[FRONT_LEFT] = 0;
1921 device->DevChannels[FRONT_RIGHT] = 1;
1922 device->DevChannels[FRONT_CENTER] = 2;
1923 device->DevChannels[LFE] = 3;
1924 device->DevChannels[BACK_LEFT] = 4;
1925 device->DevChannels[BACK_RIGHT] = 5;
1926 device->DevChannels[SIDE_LEFT] = 6;
1927 device->DevChannels[SIDE_RIGHT] = 7; break;
1931 static ALenum GetFormatFromString(const char *str)
1933 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1934 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1935 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1936 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1937 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1938 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1940 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1941 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1942 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1943 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1944 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1945 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1947 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1948 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1949 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1950 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1951 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1952 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1954 AL_PRINT("Unknown format: \"%s\"\n", str);
1955 return AL_FORMAT_STEREO16;
1959 alcOpenDevice
1961 Open the Device specified.
1963 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
1965 ALboolean bDeviceFound = AL_FALSE;
1966 const ALCchar *fmt;
1967 ALCdevice *device;
1968 ALint i;
1970 if(deviceName && !deviceName[0])
1971 deviceName = NULL;
1973 device = calloc(1, sizeof(ALCdevice));
1974 if(!device)
1976 alcSetError(NULL, ALC_OUT_OF_MEMORY);
1977 return NULL;
1980 //Validate device
1981 device->Connected = ALC_TRUE;
1982 device->IsCaptureDevice = AL_FALSE;
1983 device->LastError = ALC_NO_ERROR;
1985 device->Bs2b = NULL;
1986 device->szDeviceName = NULL;
1988 device->Contexts = NULL;
1989 device->NumContexts = 0;
1991 InitUIntMap(&device->BufferMap);
1992 InitUIntMap(&device->EffectMap);
1993 InitUIntMap(&device->FilterMap);
1994 InitUIntMap(&device->DatabufferMap);
1996 //Set output format
1997 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1998 if(device->Frequency < 8000)
1999 device->Frequency = 8000;
2001 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
2002 device->Format = GetFormatFromString(fmt);
2004 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
2005 if(device->NumUpdates < 2)
2006 device->NumUpdates = 4;
2008 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);
2009 if(device->UpdateSize <= 0)
2010 device->UpdateSize = 1024;
2012 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
2013 if((ALint)device->MaxNoOfSources <= 0)
2014 device->MaxNoOfSources = 256;
2016 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
2017 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
2018 device->AuxiliaryEffectSlotMax = 4;
2020 device->NumStereoSources = 1;
2021 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2023 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
2024 if(device->NumAuxSends > MAX_SENDS)
2025 device->NumAuxSends = MAX_SENDS;
2027 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
2029 device->HeadDampen = 0.0f;
2031 // Find a playback device to open
2032 SuspendContext(NULL);
2033 for(i = 0;BackendList[i].Init;i++)
2035 device->Funcs = &BackendList[i].Funcs;
2036 if(ALCdevice_OpenPlayback(device, deviceName))
2038 device->next = g_pDeviceList;
2039 g_pDeviceList = device;
2040 g_ulDeviceCount++;
2042 bDeviceFound = AL_TRUE;
2043 break;
2046 ProcessContext(NULL);
2048 if(!bDeviceFound)
2050 // No suitable output device found
2051 alcSetError(NULL, ALC_INVALID_VALUE);
2052 free(device);
2053 device = NULL;
2056 return device;
2061 alcCloseDevice
2063 Close the specified Device
2065 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
2067 ALCdevice **list;
2069 if(!IsDevice(pDevice) || pDevice->IsCaptureDevice)
2071 alcSetError(pDevice, ALC_INVALID_DEVICE);
2072 return ALC_FALSE;
2075 SuspendContext(NULL);
2077 list = &g_pDeviceList;
2078 while(*list != pDevice)
2079 list = &(*list)->next;
2081 *list = (*list)->next;
2082 g_ulDeviceCount--;
2084 ProcessContext(NULL);
2086 if(pDevice->NumContexts > 0)
2088 #ifdef _DEBUG
2089 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
2090 #endif
2091 while(pDevice->NumContexts > 0)
2092 alcDestroyContext(pDevice->Contexts[0]);
2094 ALCdevice_ClosePlayback(pDevice);
2096 if(pDevice->BufferMap.size > 0)
2098 #ifdef _DEBUG
2099 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);
2100 #endif
2101 ReleaseALBuffers(pDevice);
2103 ResetUIntMap(&pDevice->BufferMap);
2105 if(pDevice->EffectMap.size > 0)
2107 #ifdef _DEBUG
2108 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);
2109 #endif
2110 ReleaseALEffects(pDevice);
2112 ResetUIntMap(&pDevice->EffectMap);
2114 if(pDevice->FilterMap.size > 0)
2116 #ifdef _DEBUG
2117 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);
2118 #endif
2119 ReleaseALFilters(pDevice);
2121 ResetUIntMap(&pDevice->FilterMap);
2123 if(pDevice->DatabufferMap.size > 0)
2125 #ifdef _DEBUG
2126 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferMap.size);
2127 #endif
2128 ReleaseALDatabuffers(pDevice);
2130 ResetUIntMap(&pDevice->DatabufferMap);
2132 free(pDevice->Bs2b);
2133 pDevice->Bs2b = NULL;
2135 free(pDevice->szDeviceName);
2136 pDevice->szDeviceName = NULL;
2138 free(pDevice->Contexts);
2139 pDevice->Contexts = NULL;
2141 //Release device structure
2142 memset(pDevice, 0, sizeof(ALCdevice));
2143 free(pDevice);
2145 return ALC_TRUE;
2149 ALCvoid ReleaseALC(ALCvoid)
2151 free(alcDeviceList); alcDeviceList = NULL;
2152 alcDeviceListSize = 0;
2153 free(alcAllDeviceList); alcAllDeviceList = NULL;
2154 alcAllDeviceListSize = 0;
2155 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
2156 alcCaptureDeviceListSize = 0;
2158 free(alcDefaultDeviceSpecifier);
2159 alcDefaultDeviceSpecifier = NULL;
2160 free(alcDefaultAllDeviceSpecifier);
2161 alcDefaultAllDeviceSpecifier = NULL;
2162 free(alcCaptureDefaultDeviceSpecifier);
2163 alcCaptureDefaultDeviceSpecifier = NULL;
2165 #ifdef _DEBUG
2166 if(g_ulDeviceCount > 0)
2167 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
2168 #endif
2170 while(g_pDeviceList)
2172 if(g_pDeviceList->IsCaptureDevice)
2173 alcCaptureCloseDevice(g_pDeviceList);
2174 else
2175 alcCloseDevice(g_pDeviceList);
2179 ///////////////////////////////////////////////////////