Combine two arrays into one
[openal-soft.git] / Alc / ALc.c
blobd05bbebc3582efe25b42898f5191f6b3ed059ac9
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, 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
73 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
74 #ifdef HAVE_WAVE
75 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
76 #endif
78 { NULL, NULL, NULL, NULL, EmptyFuncs }
80 #undef EmptyFuncs
82 ///////////////////////////////////////////////////////
84 #define ALC_EFX_MAJOR_VERSION 0x20001
85 #define ALC_EFX_MINOR_VERSION 0x20002
86 #define ALC_MAX_AUXILIARY_SENDS 0x20003
88 ///////////////////////////////////////////////////////
89 // STRING and EXTENSIONS
91 typedef struct ALCfunction {
92 const ALCchar *funcName;
93 ALCvoid *address;
94 } ALCfunction;
96 typedef struct ALCenums {
97 const ALCchar *enumName;
98 ALCenum value;
99 } ALCenums;
102 static const ALCfunction alcFunctions[] = {
103 { "alcCreateContext", (ALCvoid *) alcCreateContext },
104 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },
105 { "alcProcessContext", (ALCvoid *) alcProcessContext },
106 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },
107 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },
108 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },
109 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },
110 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },
111 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },
112 { "alcGetError", (ALCvoid *) alcGetError },
113 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },
114 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },
115 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },
116 { "alcGetString", (ALCvoid *) alcGetString },
117 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },
118 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },
119 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },
120 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },
121 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },
122 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },
124 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },
125 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },
127 { "alEnable", (ALCvoid *) alEnable },
128 { "alDisable", (ALCvoid *) alDisable },
129 { "alIsEnabled", (ALCvoid *) alIsEnabled },
130 { "alGetString", (ALCvoid *) alGetString },
131 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },
132 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },
133 { "alGetFloatv", (ALCvoid *) alGetFloatv },
134 { "alGetDoublev", (ALCvoid *) alGetDoublev },
135 { "alGetBoolean", (ALCvoid *) alGetBoolean },
136 { "alGetInteger", (ALCvoid *) alGetInteger },
137 { "alGetFloat", (ALCvoid *) alGetFloat },
138 { "alGetDouble", (ALCvoid *) alGetDouble },
139 { "alGetError", (ALCvoid *) alGetError },
140 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },
141 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },
142 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },
143 { "alListenerf", (ALCvoid *) alListenerf },
144 { "alListener3f", (ALCvoid *) alListener3f },
145 { "alListenerfv", (ALCvoid *) alListenerfv },
146 { "alListeneri", (ALCvoid *) alListeneri },
147 { "alListener3i", (ALCvoid *) alListener3i },
148 { "alListeneriv", (ALCvoid *) alListeneriv },
149 { "alGetListenerf", (ALCvoid *) alGetListenerf },
150 { "alGetListener3f", (ALCvoid *) alGetListener3f },
151 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },
152 { "alGetListeneri", (ALCvoid *) alGetListeneri },
153 { "alGetListener3i", (ALCvoid *) alGetListener3i },
154 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },
155 { "alGenSources", (ALCvoid *) alGenSources },
156 { "alDeleteSources", (ALCvoid *) alDeleteSources },
157 { "alIsSource", (ALCvoid *) alIsSource },
158 { "alSourcef", (ALCvoid *) alSourcef },
159 { "alSource3f", (ALCvoid *) alSource3f },
160 { "alSourcefv", (ALCvoid *) alSourcefv },
161 { "alSourcei", (ALCvoid *) alSourcei },
162 { "alSource3i", (ALCvoid *) alSource3i },
163 { "alSourceiv", (ALCvoid *) alSourceiv },
164 { "alGetSourcef", (ALCvoid *) alGetSourcef },
165 { "alGetSource3f", (ALCvoid *) alGetSource3f },
166 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },
167 { "alGetSourcei", (ALCvoid *) alGetSourcei },
168 { "alGetSource3i", (ALCvoid *) alGetSource3i },
169 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },
170 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },
171 { "alSourceStopv", (ALCvoid *) alSourceStopv },
172 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },
173 { "alSourcePausev", (ALCvoid *) alSourcePausev },
174 { "alSourcePlay", (ALCvoid *) alSourcePlay },
175 { "alSourceStop", (ALCvoid *) alSourceStop },
176 { "alSourceRewind", (ALCvoid *) alSourceRewind },
177 { "alSourcePause", (ALCvoid *) alSourcePause },
178 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },
179 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },
180 { "alGenBuffers", (ALCvoid *) alGenBuffers },
181 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },
182 { "alIsBuffer", (ALCvoid *) alIsBuffer },
183 { "alBufferData", (ALCvoid *) alBufferData },
184 { "alBufferf", (ALCvoid *) alBufferf },
185 { "alBuffer3f", (ALCvoid *) alBuffer3f },
186 { "alBufferfv", (ALCvoid *) alBufferfv },
187 { "alBufferi", (ALCvoid *) alBufferi },
188 { "alBuffer3i", (ALCvoid *) alBuffer3i },
189 { "alBufferiv", (ALCvoid *) alBufferiv },
190 { "alGetBufferf", (ALCvoid *) alGetBufferf },
191 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },
192 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },
193 { "alGetBufferi", (ALCvoid *) alGetBufferi },
194 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },
195 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },
196 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },
197 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },
198 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },
199 { "alDistanceModel", (ALCvoid *) alDistanceModel },
201 { "alGenFilters", (ALCvoid *) alGenFilters },
202 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },
203 { "alIsFilter", (ALCvoid *) alIsFilter },
204 { "alFilteri", (ALCvoid *) alFilteri },
205 { "alFilteriv", (ALCvoid *) alFilteriv },
206 { "alFilterf", (ALCvoid *) alFilterf },
207 { "alFilterfv", (ALCvoid *) alFilterfv },
208 { "alGetFilteri", (ALCvoid *) alGetFilteri },
209 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },
210 { "alGetFilterf", (ALCvoid *) alGetFilterf },
211 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },
213 { "alGenEffects", (ALCvoid *) alGenEffects },
214 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },
215 { "alIsEffect", (ALCvoid *) alIsEffect },
216 { "alEffecti", (ALCvoid *) alEffecti },
217 { "alEffectiv", (ALCvoid *) alEffectiv },
218 { "alEffectf", (ALCvoid *) alEffectf },
219 { "alEffectfv", (ALCvoid *) alEffectfv },
220 { "alGetEffecti", (ALCvoid *) alGetEffecti },
221 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },
222 { "alGetEffectf", (ALCvoid *) alGetEffectf },
223 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },
225 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},
226 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},
227 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },
228 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },
229 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },
230 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },
231 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },
232 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},
233 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},
234 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},
235 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},
237 { "alBufferSubDataEXT", (ALCvoid *) alBufferSubDataEXT },
239 { "alGenDatabuffersEXT", (ALCvoid *) alGenDatabuffersEXT },
240 { "alDeleteDatabuffersEXT", (ALCvoid *) alDeleteDatabuffersEXT },
241 { "alIsDatabufferEXT", (ALCvoid *) alIsDatabufferEXT },
242 { "alDatabufferDataEXT", (ALCvoid *) alDatabufferDataEXT },
243 { "alDatabufferSubDataEXT", (ALCvoid *) alDatabufferSubDataEXT },
244 { "alGetDatabufferSubDataEXT", (ALCvoid *) alGetDatabufferSubDataEXT},
245 { "alDatabufferfEXT", (ALCvoid *) alDatabufferfEXT },
246 { "alDatabufferfvEXT", (ALCvoid *) alDatabufferfvEXT },
247 { "alDatabufferiEXT", (ALCvoid *) alDatabufferiEXT },
248 { "alDatabufferivEXT", (ALCvoid *) alDatabufferivEXT },
249 { "alGetDatabufferfEXT", (ALCvoid *) alGetDatabufferfEXT },
250 { "alGetDatabufferfvEXT", (ALCvoid *) alGetDatabufferfvEXT },
251 { "alGetDatabufferiEXT", (ALCvoid *) alGetDatabufferiEXT },
252 { "alGetDatabufferivEXT", (ALCvoid *) alGetDatabufferivEXT },
253 { "alSelectDatabufferEXT", (ALCvoid *) alSelectDatabufferEXT },
254 { "alMapDatabufferEXT", (ALCvoid *) alMapDatabufferEXT },
255 { "alUnmapDatabufferEXT", (ALCvoid *) alUnmapDatabufferEXT },
257 { NULL, (ALCvoid *) NULL }
260 static const ALCenums enumeration[] = {
261 // Types
262 { "ALC_INVALID", ALC_INVALID },
263 { "ALC_FALSE", ALC_FALSE },
264 { "ALC_TRUE", ALC_TRUE },
266 // ALC Properties
267 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
268 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },
269 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
270 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
271 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
272 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
273 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
274 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
275 { "ALC_EXTENSIONS", ALC_EXTENSIONS },
276 { "ALC_FREQUENCY", ALC_FREQUENCY },
277 { "ALC_REFRESH", ALC_REFRESH },
278 { "ALC_SYNC", ALC_SYNC },
279 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },
280 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
281 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
282 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
283 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
284 { "ALC_CONNECTED", ALC_CONNECTED },
286 // EFX Properties
287 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
288 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
289 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
291 // ALC Error Message
292 { "ALC_NO_ERROR", ALC_NO_ERROR },
293 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
294 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
295 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },
296 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },
297 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
298 { NULL, (ALCenum)0 }
300 // Error strings
301 static const ALCchar alcNoError[] = "No Error";
302 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
303 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
304 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
305 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
306 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
308 /* Device lists. Sizes only include the first ending null character, not the
309 * second */
310 static ALCchar *alcDeviceList;
311 static size_t alcDeviceListSize;
312 static ALCchar *alcAllDeviceList;
313 static size_t alcAllDeviceListSize;
314 static ALCchar *alcCaptureDeviceList;
315 static size_t alcCaptureDeviceListSize;
316 // Default is always the first in the list
317 static ALCchar *alcDefaultDeviceSpecifier;
318 static ALCchar *alcDefaultAllDeviceSpecifier;
319 static ALCchar *alcCaptureDefaultDeviceSpecifier;
322 static const ALCchar alcNoDeviceExtList[] =
323 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
324 "ALC_EXT_thread_local_context";
325 static const ALCchar alcExtensionList[] =
326 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
327 "ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context";
328 static const ALCint alcMajorVersion = 1;
329 static const ALCint alcMinorVersion = 1;
331 static const ALCint alcEFXMajorVersion = 1;
332 static const ALCint alcEFXMinorVersion = 0;
334 ///////////////////////////////////////////////////////
337 ///////////////////////////////////////////////////////
338 // Global Variables
340 static ALCdevice *g_pDeviceList = NULL;
341 static ALCuint g_ulDeviceCount = 0;
343 static CRITICAL_SECTION g_csMutex;
345 // Context List
346 static ALCcontext *g_pContextList = NULL;
347 static ALCuint g_ulContextCount = 0;
349 // Thread-local current context
350 static tls_type LocalContext;
351 // Process-wide current context
352 static ALCcontext *GlobalContext;
354 // Context Error
355 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
357 // Default context extensions
358 static const ALchar alExtList[] =
359 "AL_EXTX_buffer_sub_data AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
360 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXTX_loop_points "
361 "AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
362 "AL_EXTX_sample_buffer_object AL_EXT_source_distance_model "
363 "AL_LOKI_quadriphonic";
365 // Mixing Priority Level
366 static ALint RTPrioLevel;
368 // Resampler Quality
369 resampler_t DefaultResampler;
371 // Output Log File
372 static FILE *LogFile;
374 ///////////////////////////////////////////////////////
377 ///////////////////////////////////////////////////////
378 // ALC Related helper functions
379 #ifdef _WIN32
380 static void alc_init(void);
381 static void alc_deinit(void);
383 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
385 (void)lpReserved;
387 // Perform actions based on the reason for calling.
388 switch(ul_reason_for_call)
390 case DLL_PROCESS_ATTACH:
391 DisableThreadLibraryCalls(hModule);
392 alc_init();
393 break;
395 case DLL_PROCESS_DETACH:
396 alc_deinit();
397 break;
399 return TRUE;
401 #else
402 #ifdef HAVE_GCC_DESTRUCTOR
403 static void alc_init(void) __attribute__((constructor));
404 static void alc_deinit(void) __attribute__((destructor));
405 #endif
406 #endif
408 static void alc_init(void)
410 int i;
411 const char *devs, *str;
413 str = getenv("ALSOFT_LOGFILE");
414 if(str && str[0])
416 LogFile = fopen(str, "w");
417 if(!LogFile)
418 fprintf(stderr, "AL lib: Failed to open log file '%s'\n", str);
420 if(!LogFile)
421 LogFile = stderr;
423 InitializeCriticalSection(&g_csMutex);
424 ALTHUNK_INIT();
425 ReadALConfig();
427 tls_create(&LocalContext);
429 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
431 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
432 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
433 DefaultResampler = RESAMPLER_DEFAULT;
435 devs = GetConfigValue(NULL, "drivers", "");
436 if(devs[0])
438 int n;
439 size_t len;
440 const char *next = devs;
441 int endlist, delitem;
443 i = 0;
444 do {
445 devs = next;
446 next = strchr(devs, ',');
448 delitem = (devs[0] == '-');
449 if(devs[0] == '-') devs++;
451 if(!devs[0] || devs[0] == ',')
453 endlist = 0;
454 continue;
456 endlist = 1;
458 len = (next ? ((size_t)(next-devs)) : strlen(devs));
459 for(n = i;BackendList[n].Init;n++)
461 if(len == strlen(BackendList[n].name) &&
462 strncmp(BackendList[n].name, devs, len) == 0)
464 if(delitem)
466 do {
467 BackendList[n] = BackendList[n+1];
468 ++n;
469 } while(BackendList[n].Init);
471 else
473 BackendInfo Bkp = BackendList[n];
474 while(n > i)
476 BackendList[n] = BackendList[n-1];
477 --n;
479 BackendList[n] = Bkp;
481 i++;
483 break;
486 } while(next++);
488 if(endlist)
490 BackendList[i].name = NULL;
491 BackendList[i].Init = NULL;
492 BackendList[i].Deinit = NULL;
493 BackendList[i].Probe = NULL;
497 for(i = 0;BackendList[i].Init;i++)
498 BackendList[i].Init(&BackendList[i].Funcs);
500 str = GetConfigValue(NULL, "excludefx", "");
501 if(str[0])
503 const struct {
504 const char *name;
505 int type;
506 } EffectList[] = {
507 { "eaxreverb", EAXREVERB },
508 { "reverb", REVERB },
509 { "echo", ECHO },
510 { "modulator", MODULATOR },
511 { NULL, 0 }
513 int n;
514 size_t len;
515 const char *next = str;
517 do {
518 str = next;
519 next = strchr(str, ',');
521 if(!str[0] || next == str)
522 continue;
524 len = (next ? ((size_t)(next-str)) : strlen(str));
525 for(n = 0;EffectList[n].name;n++)
527 if(len == strlen(EffectList[n].name) &&
528 strncmp(EffectList[n].name, str, len) == 0)
529 DisabledEffects[EffectList[n].type] = AL_TRUE;
531 } while(next++);
535 static void alc_deinit(void)
537 int i;
539 ReleaseALC();
541 for(i = 0;BackendList[i].Deinit;i++)
542 BackendList[i].Deinit();
544 tls_delete(LocalContext);
546 FreeALConfig();
547 ALTHUNK_EXIT();
548 DeleteCriticalSection(&g_csMutex);
550 if(LogFile != stderr)
551 fclose(LogFile);
552 LogFile = NULL;
556 static void ProbeDeviceList()
558 ALint i;
560 free(alcDeviceList); alcDeviceList = NULL;
561 alcDeviceListSize = 0;
563 for(i = 0;BackendList[i].Probe;i++)
564 BackendList[i].Probe(DEVICE_PROBE);
567 static void ProbeAllDeviceList()
569 ALint i;
571 free(alcAllDeviceList); alcAllDeviceList = NULL;
572 alcAllDeviceListSize = 0;
574 for(i = 0;BackendList[i].Probe;i++)
575 BackendList[i].Probe(ALL_DEVICE_PROBE);
578 static void ProbeCaptureDeviceList()
580 ALint i;
582 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
583 alcCaptureDeviceListSize = 0;
585 for(i = 0;BackendList[i].Probe;i++)
586 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
590 #define DECL_APPEND_LIST_FUNC(type) \
591 void Append##type##List(const ALCchar *name) \
593 size_t len = strlen(name); \
594 void *temp; \
596 if(len == 0) \
597 return; \
599 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
600 if(!temp) \
602 AL_PRINT("Realloc failed to add %s!\n", name); \
603 return; \
605 alc##type##List = temp; \
606 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
607 alc##type##ListSize += len+1; \
608 alc##type##List[alc##type##ListSize] = 0; \
611 DECL_APPEND_LIST_FUNC(Device)
612 DECL_APPEND_LIST_FUNC(AllDevice)
613 DECL_APPEND_LIST_FUNC(CaptureDevice)
616 void al_print(const char *fname, unsigned int line, const char *fmt, ...)
618 const char *fn;
619 char str[256];
620 int i;
622 fn = strrchr(fname, '/');
623 if(!fn) fn = strrchr(fname, '\\');;
624 if(!fn) fn = fname;
625 else fn += 1;
627 i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
628 if(i < (int)sizeof(str) && i > 0)
630 va_list ap;
631 va_start(ap, fmt);
632 vsnprintf(str+i, sizeof(str)-i, fmt, ap);
633 va_end(ap);
635 str[sizeof(str)-1] = 0;
637 fprintf(LogFile, "%s", str);
638 fflush(LogFile);
641 void SetRTPriority(void)
643 ALboolean failed;
645 #ifdef _WIN32
646 if(RTPrioLevel > 0)
647 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
648 else
649 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
650 #elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
651 struct sched_param param;
653 if(RTPrioLevel > 0)
655 /* Use the minimum real-time priority possible for now (on Linux this
656 * should be 1 for SCHED_RR) */
657 param.sched_priority = sched_get_priority_min(SCHED_RR);
658 failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
660 else
662 param.sched_priority = 0;
663 failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
665 #else
666 /* Real-time priority not available */
667 failed = (RTPrioLevel>0);
668 #endif
669 if(failed)
670 AL_PRINT("Failed to set priority level for thread\n");
674 void InitUIntMap(UIntMap *map)
676 map->array = NULL;
677 map->size = 0;
678 map->maxsize = 0;
681 void ResetUIntMap(UIntMap *map)
683 free(map->array);
684 map->array = NULL;
685 map->size = 0;
686 map->maxsize = 0;
689 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
691 ALsizei pos = 0;
693 if(map->size > 0)
695 ALsizei low = 0;
696 ALsizei high = map->size - 1;
697 while(low < high)
699 ALsizei mid = low + (high-low)/2;
700 if(map->array[mid].key < key)
701 low = mid + 1;
702 else
703 high = mid;
705 if(map->array[low].key < key)
706 low++;
707 pos = low;
710 if(pos == map->size || map->array[pos].key != key)
712 if(map->size == map->maxsize)
714 ALvoid *temp;
715 ALsizei newsize;
717 newsize = (map->maxsize ? (map->maxsize<<1) : 4);
718 if(newsize < map->maxsize)
719 return AL_OUT_OF_MEMORY;
721 temp = realloc(map->array, newsize*sizeof(map->array[0]));
722 if(!temp) return AL_OUT_OF_MEMORY;
723 map->array = temp;
724 map->maxsize = newsize;
727 map->size++;
728 if(pos < map->size-1)
729 memmove(&map->array[pos+1], &map->array[pos],
730 (map->size-1-pos)*sizeof(map->array[0]));
732 map->array[pos].key = key;
733 map->array[pos].value = value;
735 return AL_NO_ERROR;
738 void RemoveUIntMapKey(UIntMap *map, ALuint key)
740 if(map->size > 0)
742 ALsizei low = 0;
743 ALsizei high = map->size - 1;
744 while(low < high)
746 ALsizei mid = low + (high-low)/2;
747 if(map->array[mid].key < key)
748 low = mid + 1;
749 else
750 high = mid;
752 if(map->array[low].key == key)
754 if(low < map->size-1)
755 memmove(&map->array[low], &map->array[low+1],
756 (map->size-1-low)*sizeof(map->array[0]));
757 map->size--;
764 IsDevice
766 Check pDevice is a valid Device pointer
768 static ALCboolean IsDevice(ALCdevice *pDevice)
770 ALCdevice *pTempDevice;
772 SuspendContext(NULL);
774 pTempDevice = g_pDeviceList;
775 while(pTempDevice && pTempDevice != pDevice)
776 pTempDevice = pTempDevice->next;
778 ProcessContext(NULL);
780 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
784 IsContext
786 Check pContext is a valid Context pointer
788 static ALCboolean IsContext(ALCcontext *pContext)
790 ALCcontext *pTempContext;
792 SuspendContext(NULL);
794 pTempContext = g_pContextList;
795 while (pTempContext && pTempContext != pContext)
796 pTempContext = pTempContext->next;
798 ProcessContext(NULL);
800 return (pTempContext ? ALC_TRUE : ALC_FALSE);
805 alcSetError
807 Store latest ALC Error
809 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
811 if(IsDevice(device))
812 device->LastError = errorCode;
813 else
814 g_eLastNullDeviceError = errorCode;
818 /* UpdateDeviceParams:
820 * Updates device parameters according to the attribute list.
822 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
824 ALCuint freq, numMono, numStereo, numSends;
825 ALboolean running;
826 ALuint oldRate;
827 ALuint attrIdx;
828 ALuint i;
830 running = ((device->NumContexts > 0) ? AL_TRUE : AL_FALSE);
831 oldRate = device->Frequency;
833 // Check for attributes
834 if(attrList && attrList[0])
836 // If a context is already running on the device, stop playback so the
837 // device attributes can be updated
838 if(running)
840 ProcessContext(NULL);
841 ALCdevice_StopPlayback(device);
842 SuspendContext(NULL);
843 running = AL_FALSE;
846 freq = device->Frequency;
847 numMono = device->NumMonoSources;
848 numStereo = device->NumStereoSources;
849 numSends = device->NumAuxSends;
851 attrIdx = 0;
852 while(attrList[attrIdx])
854 if(attrList[attrIdx] == ALC_FREQUENCY &&
855 !ConfigValueExists(NULL, "frequency"))
857 freq = attrList[attrIdx + 1];
858 if(freq < 8000)
859 freq = 8000;
862 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
864 numStereo = attrList[attrIdx + 1];
865 if(numStereo > device->MaxNoOfSources)
866 numStereo = device->MaxNoOfSources;
868 numMono = device->MaxNoOfSources - numStereo;
871 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
872 !ConfigValueExists(NULL, "sends"))
874 numSends = attrList[attrIdx + 1];
875 if(numSends > MAX_SENDS)
876 numSends = MAX_SENDS;
879 attrIdx += 2;
882 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
883 device->Frequency;
885 device->Frequency = freq;
886 device->NumMonoSources = numMono;
887 device->NumStereoSources = numStereo;
888 device->NumAuxSends = numSends;
891 if(running)
892 return ALC_TRUE;
894 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
895 return ALC_FALSE;
897 aluInitPanning(device);
899 // Scale the number of samples played according to the new sample rate
900 device->SamplesPlayed *= device->Frequency;
901 device->SamplesPlayed += oldRate-1;
902 device->SamplesPlayed /= oldRate;
904 for(i = 0;i < OUTPUTCHANNELS;i++)
906 device->ClickRemoval[i] = 0.0f;
907 device->PendingClicks[i] = 0.0f;
910 for(i = 0;i < device->NumContexts;i++)
912 ALCcontext *context = device->Contexts[i];
913 ALsizei pos;
915 SuspendContext(context);
916 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
918 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
920 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
922 ProcessContext(context);
923 return ALC_FALSE;
925 ALEffect_Update(slot->EffectState, context, &slot->effect);
928 for(pos = 0;pos < context->SourceMap.size;pos++)
930 ALsource *source = context->SourceMap.array[pos].value;
931 ALuint s = device->NumAuxSends;
932 while(s < MAX_SENDS)
934 if(source->Send[s].Slot)
935 source->Send[s].Slot->refcount--;
936 source->Send[s].Slot = NULL;
937 source->Send[s].WetFilter.type = 0;
938 source->Send[s].WetFilter.filter = 0;
939 s++;
941 source->NeedsUpdate = AL_TRUE;
943 ProcessContext(context);
946 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
948 if(!device->Bs2b)
950 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
951 bs2b_clear(device->Bs2b);
953 bs2b_set_srate(device->Bs2b, device->Frequency);
954 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
956 else
958 free(device->Bs2b);
959 device->Bs2b = NULL;
962 if(aluChannelsFromFormat(device->Format) <= 2)
964 device->HeadDampen = GetConfigValueFloat(NULL, "head_dampen", DEFAULT_HEAD_DAMPEN);
965 device->HeadDampen = __min(device->HeadDampen, 1.0f);
966 device->HeadDampen = __max(device->HeadDampen, 0.0f);
968 else
969 device->HeadDampen = 0.0f;
971 return ALC_TRUE;
976 SuspendContext
978 Thread-safe entry
980 ALCvoid SuspendContext(ALCcontext *pContext)
982 (void)pContext;
983 EnterCriticalSection(&g_csMutex);
988 ProcessContext
990 Thread-safe exit
992 ALCvoid ProcessContext(ALCcontext *pContext)
994 (void)pContext;
995 LeaveCriticalSection(&g_csMutex);
1000 GetContextSuspended
1002 Returns the currently active Context, in a locked state
1004 ALCcontext *GetContextSuspended(void)
1006 ALCcontext *pContext = NULL;
1008 SuspendContext(NULL);
1010 pContext = tls_get(LocalContext);
1011 if(pContext && !IsContext(pContext))
1013 tls_set(LocalContext, NULL);
1014 pContext = NULL;
1016 if(!pContext)
1017 pContext = GlobalContext;
1019 if(pContext)
1020 SuspendContext(pContext);
1022 ProcessContext(NULL);
1024 return pContext;
1029 InitContext
1031 Initialize Context variables
1033 static ALvoid InitContext(ALCcontext *pContext)
1035 //Initialise listener
1036 pContext->Listener.Gain = 1.0f;
1037 pContext->Listener.MetersPerUnit = 1.0f;
1038 pContext->Listener.Position[0] = 0.0f;
1039 pContext->Listener.Position[1] = 0.0f;
1040 pContext->Listener.Position[2] = 0.0f;
1041 pContext->Listener.Velocity[0] = 0.0f;
1042 pContext->Listener.Velocity[1] = 0.0f;
1043 pContext->Listener.Velocity[2] = 0.0f;
1044 pContext->Listener.Forward[0] = 0.0f;
1045 pContext->Listener.Forward[1] = 0.0f;
1046 pContext->Listener.Forward[2] = -1.0f;
1047 pContext->Listener.Up[0] = 0.0f;
1048 pContext->Listener.Up[1] = 1.0f;
1049 pContext->Listener.Up[2] = 0.0f;
1051 //Validate pContext
1052 pContext->LastError = AL_NO_ERROR;
1053 pContext->Suspended = AL_FALSE;
1054 pContext->ActiveSourceCount = 0;
1055 InitUIntMap(&pContext->SourceMap);
1056 InitUIntMap(&pContext->EffectSlotMap);
1058 //Set globals
1059 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1060 pContext->SourceDistanceModel = AL_FALSE;
1061 pContext->DopplerFactor = 1.0f;
1062 pContext->DopplerVelocity = 1.0f;
1063 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1065 pContext->ExtensionList = alExtList;
1070 ExitContext
1072 Clean up Context, destroy any remaining Sources
1074 static ALCvoid ExitContext(ALCcontext *pContext)
1076 //Invalidate context
1077 pContext->LastError = AL_NO_ERROR;
1080 ///////////////////////////////////////////////////////
1083 ///////////////////////////////////////////////////////
1084 // ALC Functions calls
1087 // This should probably move to another c file but for now ...
1088 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
1090 ALCboolean DeviceFound = ALC_FALSE;
1091 ALCdevice *device = NULL;
1092 ALCint i;
1094 if(SampleSize <= 0)
1096 alcSetError(NULL, ALC_INVALID_VALUE);
1097 return NULL;
1100 if(deviceName && !deviceName[0])
1101 deviceName = NULL;
1103 device = calloc(1, sizeof(ALCdevice));
1104 if(!device)
1106 alcSetError(NULL, ALC_OUT_OF_MEMORY);
1107 return NULL;
1110 //Validate device
1111 device->Connected = ALC_TRUE;
1112 device->IsCaptureDevice = AL_TRUE;
1114 device->szDeviceName = NULL;
1116 device->Frequency = frequency;
1117 device->Format = format;
1118 device->UpdateSize = SampleSize;
1119 device->NumUpdates = 1;
1121 SuspendContext(NULL);
1122 for(i = 0;BackendList[i].Init;i++)
1124 device->Funcs = &BackendList[i].Funcs;
1125 if(ALCdevice_OpenCapture(device, deviceName))
1127 device->next = g_pDeviceList;
1128 g_pDeviceList = device;
1129 g_ulDeviceCount++;
1131 DeviceFound = ALC_TRUE;
1132 break;
1135 ProcessContext(NULL);
1137 if(!DeviceFound)
1139 alcSetError(NULL, ALC_INVALID_VALUE);
1140 free(device);
1141 device = NULL;
1144 return device;
1147 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
1149 ALCdevice **list;
1151 if(!IsDevice(pDevice) || !pDevice->IsCaptureDevice)
1153 alcSetError(pDevice, ALC_INVALID_DEVICE);
1154 return ALC_FALSE;
1157 SuspendContext(NULL);
1159 list = &g_pDeviceList;
1160 while(*list != pDevice)
1161 list = &(*list)->next;
1163 *list = (*list)->next;
1164 g_ulDeviceCount--;
1166 ProcessContext(NULL);
1168 ALCdevice_CloseCapture(pDevice);
1170 free(pDevice->szDeviceName);
1171 pDevice->szDeviceName = NULL;
1173 free(pDevice);
1175 return ALC_TRUE;
1178 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
1180 SuspendContext(NULL);
1181 if(!IsDevice(device) || !device->IsCaptureDevice)
1182 alcSetError(device, ALC_INVALID_DEVICE);
1183 else if(device->Connected)
1184 ALCdevice_StartCapture(device);
1185 ProcessContext(NULL);
1188 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
1190 SuspendContext(NULL);
1191 if(!IsDevice(device) || !device->IsCaptureDevice)
1192 alcSetError(device, ALC_INVALID_DEVICE);
1193 else
1194 ALCdevice_StopCapture(device);
1195 ProcessContext(NULL);
1198 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
1200 SuspendContext(NULL);
1201 if(!IsDevice(device) || !device->IsCaptureDevice)
1202 alcSetError(device, ALC_INVALID_DEVICE);
1203 else
1204 ALCdevice_CaptureSamples(device, buffer, samples);
1205 ProcessContext(NULL);
1209 alcGetError
1211 Return last ALC generated error code
1213 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1215 ALCenum errorCode;
1217 if(IsDevice(device))
1219 errorCode = device->LastError;
1220 device->LastError = ALC_NO_ERROR;
1222 else
1224 errorCode = g_eLastNullDeviceError;
1225 g_eLastNullDeviceError = ALC_NO_ERROR;
1227 return errorCode;
1232 alcSuspendContext
1234 Not functional
1236 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *pContext)
1238 SuspendContext(NULL);
1239 if(IsContext(pContext))
1240 pContext->Suspended = AL_TRUE;
1241 ProcessContext(NULL);
1246 alcProcessContext
1248 Not functional
1250 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *pContext)
1252 SuspendContext(NULL);
1253 if(IsContext(pContext))
1254 pContext->Suspended = AL_FALSE;
1255 ProcessContext(NULL);
1260 alcGetString
1262 Returns information about the Device, and error strings
1264 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
1266 const ALCchar *value = NULL;
1268 switch (param)
1270 case ALC_NO_ERROR:
1271 value = alcNoError;
1272 break;
1274 case ALC_INVALID_ENUM:
1275 value = alcErrInvalidEnum;
1276 break;
1278 case ALC_INVALID_VALUE:
1279 value = alcErrInvalidValue;
1280 break;
1282 case ALC_INVALID_DEVICE:
1283 value = alcErrInvalidDevice;
1284 break;
1286 case ALC_INVALID_CONTEXT:
1287 value = alcErrInvalidContext;
1288 break;
1290 case ALC_OUT_OF_MEMORY:
1291 value = alcErrOutOfMemory;
1292 break;
1294 case ALC_DEVICE_SPECIFIER:
1295 if(IsDevice(pDevice))
1296 value = pDevice->szDeviceName;
1297 else
1299 ProbeDeviceList();
1300 value = alcDeviceList;
1302 break;
1304 case ALC_ALL_DEVICES_SPECIFIER:
1305 ProbeAllDeviceList();
1306 value = alcAllDeviceList;
1307 break;
1309 case ALC_CAPTURE_DEVICE_SPECIFIER:
1310 if(IsDevice(pDevice))
1311 value = pDevice->szDeviceName;
1312 else
1314 ProbeCaptureDeviceList();
1315 value = alcCaptureDeviceList;
1317 break;
1319 /* Default devices are always first in the list */
1320 case ALC_DEFAULT_DEVICE_SPECIFIER:
1321 if(!alcDeviceList)
1322 ProbeDeviceList();
1324 free(alcDefaultDeviceSpecifier);
1325 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
1326 if(!alcDefaultDeviceSpecifier)
1327 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1328 value = alcDefaultDeviceSpecifier;
1329 break;
1331 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
1332 if(!alcAllDeviceList)
1333 ProbeAllDeviceList();
1335 free(alcDefaultAllDeviceSpecifier);
1336 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
1337 alcAllDeviceList : "");
1338 if(!alcDefaultAllDeviceSpecifier)
1339 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1340 value = alcDefaultAllDeviceSpecifier;
1341 break;
1343 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
1344 if(!alcCaptureDeviceList)
1345 ProbeCaptureDeviceList();
1347 free(alcCaptureDefaultDeviceSpecifier);
1348 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
1349 alcCaptureDeviceList : "");
1350 if(!alcCaptureDefaultDeviceSpecifier)
1351 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1352 value = alcCaptureDefaultDeviceSpecifier;
1353 break;
1355 case ALC_EXTENSIONS:
1356 if(IsDevice(pDevice))
1357 value = alcExtensionList;
1358 else
1359 value = alcNoDeviceExtList;
1360 break;
1362 default:
1363 alcSetError(pDevice, ALC_INVALID_ENUM);
1364 break;
1367 return value;
1372 alcGetIntegerv
1374 Returns information about the Device and the version of Open AL
1376 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
1378 if(size == 0 || data == NULL)
1380 alcSetError(device, ALC_INVALID_VALUE);
1381 return;
1384 if(IsDevice(device) && device->IsCaptureDevice)
1386 SuspendContext(NULL);
1388 // Capture device
1389 switch (param)
1391 case ALC_CAPTURE_SAMPLES:
1392 *data = ALCdevice_AvailableSamples(device);
1393 break;
1395 case ALC_CONNECTED:
1396 *data = device->Connected;
1397 break;
1399 default:
1400 alcSetError(device, ALC_INVALID_ENUM);
1401 break;
1404 ProcessContext(NULL);
1405 return;
1408 // Playback Device
1409 switch (param)
1411 case ALC_MAJOR_VERSION:
1412 *data = alcMajorVersion;
1413 break;
1415 case ALC_MINOR_VERSION:
1416 *data = alcMinorVersion;
1417 break;
1419 case ALC_EFX_MAJOR_VERSION:
1420 *data = alcEFXMajorVersion;
1421 break;
1423 case ALC_EFX_MINOR_VERSION:
1424 *data = alcEFXMinorVersion;
1425 break;
1427 case ALC_MAX_AUXILIARY_SENDS:
1428 if(!IsDevice(device))
1429 alcSetError(device, ALC_INVALID_DEVICE);
1430 else
1431 *data = device->NumAuxSends;
1432 break;
1434 case ALC_ATTRIBUTES_SIZE:
1435 if(!IsDevice(device))
1436 alcSetError(device, ALC_INVALID_DEVICE);
1437 else
1438 *data = 13;
1439 break;
1441 case ALC_ALL_ATTRIBUTES:
1442 if(!IsDevice(device))
1443 alcSetError(device, ALC_INVALID_DEVICE);
1444 else if (size < 13)
1445 alcSetError(device, ALC_INVALID_VALUE);
1446 else
1448 int i = 0;
1450 SuspendContext(NULL);
1451 data[i++] = ALC_FREQUENCY;
1452 data[i++] = device->Frequency;
1454 data[i++] = ALC_REFRESH;
1455 data[i++] = device->Frequency / device->UpdateSize;
1457 data[i++] = ALC_SYNC;
1458 data[i++] = ALC_FALSE;
1460 data[i++] = ALC_MONO_SOURCES;
1461 data[i++] = device->NumMonoSources;
1463 data[i++] = ALC_STEREO_SOURCES;
1464 data[i++] = device->NumStereoSources;
1466 data[i++] = ALC_MAX_AUXILIARY_SENDS;
1467 data[i++] = device->NumAuxSends;
1469 data[i++] = 0;
1470 ProcessContext(NULL);
1472 break;
1474 case ALC_FREQUENCY:
1475 if(!IsDevice(device))
1476 alcSetError(device, ALC_INVALID_DEVICE);
1477 else
1478 *data = device->Frequency;
1479 break;
1481 case ALC_REFRESH:
1482 if(!IsDevice(device))
1483 alcSetError(device, ALC_INVALID_DEVICE);
1484 else
1485 *data = device->Frequency / device->UpdateSize;
1486 break;
1488 case ALC_SYNC:
1489 if(!IsDevice(device))
1490 alcSetError(device, ALC_INVALID_DEVICE);
1491 else
1492 *data = ALC_FALSE;
1493 break;
1495 case ALC_MONO_SOURCES:
1496 if(!IsDevice(device))
1497 alcSetError(device, ALC_INVALID_DEVICE);
1498 else
1499 *data = device->NumMonoSources;
1500 break;
1502 case ALC_STEREO_SOURCES:
1503 if(!IsDevice(device))
1504 alcSetError(device, ALC_INVALID_DEVICE);
1505 else
1506 *data = device->NumStereoSources;
1507 break;
1509 case ALC_CONNECTED:
1510 if(!IsDevice(device))
1511 alcSetError(device, ALC_INVALID_DEVICE);
1512 else
1513 *data = device->Connected;
1514 break;
1516 case ALC_GET_TIME_EXT:
1517 if(!IsDevice(device))
1518 alcSetError(device, ALC_INVALID_DEVICE);
1519 else if(size < 2)
1520 alcSetError(device, ALC_INVALID_VALUE);
1521 else
1523 ALuint64 t = ALCdevice_GetTime(device);
1524 t -= t%device->TimeRes;
1525 data[0] = t&0xffffffff;
1526 data[1] = t>>32;
1528 break;
1530 case ALC_GET_TIME_RES_EXT:
1531 if(!IsDevice(device))
1532 alcSetError(device, ALC_INVALID_DEVICE);
1533 else if(size < 2)
1534 alcSetError(device, ALC_INVALID_VALUE);
1535 else
1537 data[0] = device->TimeRes&0xffffffff;
1538 data[1] = device->TimeRes>>32;
1540 break;
1542 default:
1543 alcSetError(device, ALC_INVALID_ENUM);
1544 break;
1550 alcIsExtensionPresent
1552 Determines if there is support for a particular extension
1554 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1556 ALCboolean bResult = ALC_FALSE;
1557 const char *ptr;
1558 size_t len;
1560 if(!extName)
1562 alcSetError(device, ALC_INVALID_VALUE);
1563 return ALC_FALSE;
1566 len = strlen(extName);
1567 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
1568 while(ptr && *ptr)
1570 if(strncasecmp(ptr, extName, len) == 0 &&
1571 (ptr[len] == '\0' || isspace(ptr[len])))
1573 bResult = ALC_TRUE;
1574 break;
1576 if((ptr=strchr(ptr, ' ')) != NULL)
1578 do {
1579 ++ptr;
1580 } while(isspace(*ptr));
1584 return bResult;
1589 alcGetProcAddress
1591 Retrieves the function address for a particular extension function
1593 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1595 ALsizei i = 0;
1597 if(!funcName)
1599 alcSetError(device, ALC_INVALID_VALUE);
1600 return NULL;
1603 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
1604 i++;
1605 return alcFunctions[i].address;
1610 alcGetEnumValue
1612 Get the value for a particular ALC Enumerated Value
1614 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1616 ALsizei i = 0;
1618 if(!enumName)
1620 alcSetError(device, ALC_INVALID_VALUE);
1621 return (ALCenum)0;
1624 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
1625 i++;
1626 return enumeration[i].value;
1631 alcCreateContext
1633 Create and attach a Context to a particular Device.
1635 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1637 ALCcontext *ALContext;
1638 void *temp;
1640 SuspendContext(NULL);
1642 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1644 alcSetError(device, ALC_INVALID_DEVICE);
1645 ProcessContext(NULL);
1646 return NULL;
1649 // Reset Context Last Error code
1650 device->LastError = ALC_NO_ERROR;
1652 if(UpdateDeviceParams(device, attrList) == ALC_FALSE)
1654 alcSetError(device, ALC_INVALID_DEVICE);
1655 aluHandleDisconnect(device);
1656 ProcessContext(NULL);
1657 ALCdevice_StopPlayback(device);
1658 return NULL;
1661 ALContext = NULL;
1662 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1663 if(temp)
1665 device->Contexts = temp;
1667 ALContext = calloc(1, sizeof(ALCcontext));
1668 if(ALContext)
1670 ALContext->MaxActiveSources = 256;
1671 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
1672 ALContext->MaxActiveSources);
1675 if(!ALContext || !ALContext->ActiveSources)
1677 free(ALContext);
1678 alcSetError(device, ALC_OUT_OF_MEMORY);
1679 ProcessContext(NULL);
1680 if(device->NumContexts == 0)
1681 ALCdevice_StopPlayback(device);
1682 return NULL;
1685 device->Contexts[device->NumContexts++] = ALContext;
1686 ALContext->Device = device;
1688 InitContext(ALContext);
1690 ALContext->next = g_pContextList;
1691 g_pContextList = ALContext;
1692 g_ulContextCount++;
1694 ProcessContext(NULL);
1696 return ALContext;
1701 alcDestroyContext
1703 Remove a Context
1705 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
1707 ALCdevice *Device;
1708 ALCcontext **list;
1709 ALuint i;
1711 if(!IsContext(context))
1713 alcSetError(NULL, ALC_INVALID_CONTEXT);
1714 return;
1717 Device = context->Device;
1719 if(Device->NumContexts == 1)
1720 ALCdevice_StopPlayback(Device);
1722 SuspendContext(NULL);
1724 if(context == GlobalContext)
1725 GlobalContext = NULL;
1727 for(i = 0;i < Device->NumContexts;i++)
1729 if(Device->Contexts[i] == context)
1731 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];
1732 Device->NumContexts--;
1733 break;
1737 // Lock context
1738 SuspendContext(context);
1740 if(context->SourceMap.size > 0)
1742 #ifdef _DEBUG
1743 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);
1744 #endif
1745 ReleaseALSources(context);
1747 ResetUIntMap(&context->SourceMap);
1749 if(context->EffectSlotMap.size > 0)
1751 #ifdef _DEBUG
1752 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);
1753 #endif
1754 ReleaseALAuxiliaryEffectSlots(context);
1756 ResetUIntMap(&context->EffectSlotMap);
1758 free(context->ActiveSources);
1759 context->ActiveSources = NULL;
1760 context->MaxActiveSources = 0;
1761 context->ActiveSourceCount = 0;
1763 list = &g_pContextList;
1764 while(*list != context)
1765 list = &(*list)->next;
1767 *list = (*list)->next;
1768 g_ulContextCount--;
1770 // Unlock context
1771 ProcessContext(context);
1772 ProcessContext(NULL);
1774 ExitContext(context);
1776 // Free memory (MUST do this after ProcessContext)
1777 memset(context, 0, sizeof(ALCcontext));
1778 free(context);
1783 alcGetCurrentContext
1785 Returns the currently active Context
1787 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
1789 ALCcontext *pContext;
1791 if((pContext=GetContextSuspended()) != NULL)
1792 ProcessContext(pContext);
1794 return pContext;
1798 alcGetThreadContext
1800 Returns the currently active thread-local Context
1802 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
1804 ALCcontext *pContext = NULL;
1806 SuspendContext(NULL);
1808 pContext = tls_get(LocalContext);
1809 if(pContext && !IsContext(pContext))
1811 tls_set(LocalContext, NULL);
1812 pContext = NULL;
1815 ProcessContext(NULL);
1817 return pContext;
1822 alcGetContextsDevice
1824 Returns the Device that a particular Context is attached to
1826 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)
1828 ALCdevice *pDevice = NULL;
1830 SuspendContext(NULL);
1831 if(IsContext(pContext))
1832 pDevice = pContext->Device;
1833 else
1834 alcSetError(NULL, ALC_INVALID_CONTEXT);
1835 ProcessContext(NULL);
1837 return pDevice;
1842 alcMakeContextCurrent
1844 Makes the given Context the active Context
1846 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
1848 ALboolean bReturn = AL_TRUE;
1850 SuspendContext(NULL);
1852 // context must be a valid Context or NULL
1853 if(context == NULL || IsContext(context))
1855 GlobalContext = context;
1856 tls_set(LocalContext, NULL);
1858 else
1860 alcSetError(NULL, ALC_INVALID_CONTEXT);
1861 bReturn = AL_FALSE;
1864 ProcessContext(NULL);
1866 return bReturn;
1870 alcSetThreadContext
1872 Makes the given Context the active Context for the current thread
1874 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
1876 ALboolean bReturn = AL_TRUE;
1878 SuspendContext(NULL);
1880 // context must be a valid Context or NULL
1881 if(context == NULL || IsContext(context))
1882 tls_set(LocalContext, context);
1883 else
1885 alcSetError(NULL, ALC_INVALID_CONTEXT);
1886 bReturn = AL_FALSE;
1889 ProcessContext(NULL);
1891 return bReturn;
1895 // Sets the default channel order used by most non-WaveFormatEx-based APIs
1896 void SetDefaultChannelOrder(ALCdevice *device)
1898 switch(aluChannelsFromFormat(device->Format))
1900 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1902 case 2: device->DevChannels[FRONT_LEFT] = 0;
1903 device->DevChannels[FRONT_RIGHT] = 1; break;
1905 case 4: device->DevChannels[FRONT_LEFT] = 0;
1906 device->DevChannels[FRONT_RIGHT] = 1;
1907 device->DevChannels[BACK_LEFT] = 2;
1908 device->DevChannels[BACK_RIGHT] = 3; break;
1910 case 6: device->DevChannels[FRONT_LEFT] = 0;
1911 device->DevChannels[FRONT_RIGHT] = 1;
1912 device->DevChannels[BACK_LEFT] = 2;
1913 device->DevChannels[BACK_RIGHT] = 3;
1914 device->DevChannels[FRONT_CENTER] = 4;
1915 device->DevChannels[LFE] = 5; break;
1917 case 7: device->DevChannels[FRONT_LEFT] = 0;
1918 device->DevChannels[FRONT_RIGHT] = 1;
1919 device->DevChannels[FRONT_CENTER] = 2;
1920 device->DevChannels[LFE] = 3;
1921 device->DevChannels[BACK_CENTER] = 4;
1922 device->DevChannels[SIDE_LEFT] = 5;
1923 device->DevChannels[SIDE_RIGHT] = 6; break;
1925 case 8: device->DevChannels[FRONT_LEFT] = 0;
1926 device->DevChannels[FRONT_RIGHT] = 1;
1927 device->DevChannels[BACK_LEFT] = 2;
1928 device->DevChannels[BACK_RIGHT] = 3;
1929 device->DevChannels[FRONT_CENTER] = 4;
1930 device->DevChannels[LFE] = 5;
1931 device->DevChannels[SIDE_LEFT] = 6;
1932 device->DevChannels[SIDE_RIGHT] = 7; break;
1935 // Sets the default order used by WaveFormatEx
1936 void SetDefaultWFXChannelOrder(ALCdevice *device)
1938 switch(aluChannelsFromFormat(device->Format))
1940 case 1: device->DevChannels[FRONT_CENTER] = 0; break;
1942 case 2: device->DevChannels[FRONT_LEFT] = 0;
1943 device->DevChannels[FRONT_RIGHT] = 1; break;
1945 case 4: device->DevChannels[FRONT_LEFT] = 0;
1946 device->DevChannels[FRONT_RIGHT] = 1;
1947 device->DevChannels[BACK_LEFT] = 2;
1948 device->DevChannels[BACK_RIGHT] = 3; break;
1950 case 6: device->DevChannels[FRONT_LEFT] = 0;
1951 device->DevChannels[FRONT_RIGHT] = 1;
1952 device->DevChannels[FRONT_CENTER] = 2;
1953 device->DevChannels[LFE] = 3;
1954 device->DevChannels[BACK_LEFT] = 4;
1955 device->DevChannels[BACK_RIGHT] = 5; break;
1957 case 7: device->DevChannels[FRONT_LEFT] = 0;
1958 device->DevChannels[FRONT_RIGHT] = 1;
1959 device->DevChannels[FRONT_CENTER] = 2;
1960 device->DevChannels[LFE] = 3;
1961 device->DevChannels[BACK_CENTER] = 4;
1962 device->DevChannels[SIDE_LEFT] = 5;
1963 device->DevChannels[SIDE_RIGHT] = 6; break;
1965 case 8: device->DevChannels[FRONT_LEFT] = 0;
1966 device->DevChannels[FRONT_RIGHT] = 1;
1967 device->DevChannels[FRONT_CENTER] = 2;
1968 device->DevChannels[LFE] = 3;
1969 device->DevChannels[BACK_LEFT] = 4;
1970 device->DevChannels[BACK_RIGHT] = 5;
1971 device->DevChannels[SIDE_LEFT] = 6;
1972 device->DevChannels[SIDE_RIGHT] = 7; break;
1976 static ALenum GetFormatFromString(const char *str)
1978 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1979 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1980 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1981 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1982 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1983 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1985 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1986 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1987 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1988 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1989 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1990 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1992 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1993 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1994 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1995 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1996 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1997 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1999 AL_PRINT("Unknown format: \"%s\"\n", str);
2000 return AL_FORMAT_STEREO16;
2004 alcOpenDevice
2006 Open the Device specified.
2008 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2010 ALboolean bDeviceFound = AL_FALSE;
2011 const ALCchar *fmt;
2012 ALCdevice *device;
2013 ALint i;
2015 if(deviceName && !deviceName[0])
2016 deviceName = NULL;
2018 device = calloc(1, sizeof(ALCdevice));
2019 if(!device)
2021 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2022 return NULL;
2025 //Validate device
2026 device->Connected = ALC_TRUE;
2027 device->IsCaptureDevice = AL_FALSE;
2028 device->LastError = ALC_NO_ERROR;
2030 device->Bs2b = NULL;
2031 device->szDeviceName = NULL;
2033 device->Contexts = NULL;
2034 device->NumContexts = 0;
2036 device->SamplesPlayed = 0;
2038 device->TimeRes = 1;
2040 InitUIntMap(&device->BufferMap);
2041 InitUIntMap(&device->EffectMap);
2042 InitUIntMap(&device->FilterMap);
2043 InitUIntMap(&device->DatabufferMap);
2045 //Set output format
2046 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
2047 if(device->Frequency < 8000)
2048 device->Frequency = 8000;
2050 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
2051 device->Format = GetFormatFromString(fmt);
2053 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
2054 if(device->NumUpdates < 2)
2055 device->NumUpdates = 4;
2057 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);
2058 if(device->UpdateSize <= 0)
2059 device->UpdateSize = 1024;
2061 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
2062 if((ALint)device->MaxNoOfSources <= 0)
2063 device->MaxNoOfSources = 256;
2065 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
2066 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
2067 device->AuxiliaryEffectSlotMax = 4;
2069 device->NumStereoSources = 1;
2070 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2072 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
2073 if(device->NumAuxSends > MAX_SENDS)
2074 device->NumAuxSends = MAX_SENDS;
2076 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
2078 device->HeadDampen = 0.0f;
2080 // Find a playback device to open
2081 SuspendContext(NULL);
2082 for(i = 0;BackendList[i].Init;i++)
2084 device->Funcs = &BackendList[i].Funcs;
2085 if(ALCdevice_OpenPlayback(device, deviceName))
2087 device->next = g_pDeviceList;
2088 g_pDeviceList = device;
2089 g_ulDeviceCount++;
2091 bDeviceFound = AL_TRUE;
2092 break;
2095 ProcessContext(NULL);
2097 if(!bDeviceFound)
2099 // No suitable output device found
2100 alcSetError(NULL, ALC_INVALID_VALUE);
2101 free(device);
2102 device = NULL;
2105 return device;
2110 alcCloseDevice
2112 Close the specified Device
2114 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
2116 ALCdevice **list;
2118 if(!IsDevice(pDevice) || pDevice->IsCaptureDevice)
2120 alcSetError(pDevice, ALC_INVALID_DEVICE);
2121 return ALC_FALSE;
2124 SuspendContext(NULL);
2126 list = &g_pDeviceList;
2127 while(*list != pDevice)
2128 list = &(*list)->next;
2130 *list = (*list)->next;
2131 g_ulDeviceCount--;
2133 ProcessContext(NULL);
2135 if(pDevice->NumContexts > 0)
2137 #ifdef _DEBUG
2138 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
2139 #endif
2140 while(pDevice->NumContexts > 0)
2141 alcDestroyContext(pDevice->Contexts[0]);
2143 ALCdevice_ClosePlayback(pDevice);
2145 if(pDevice->BufferMap.size > 0)
2147 #ifdef _DEBUG
2148 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);
2149 #endif
2150 ReleaseALBuffers(pDevice);
2152 ResetUIntMap(&pDevice->BufferMap);
2154 if(pDevice->EffectMap.size > 0)
2156 #ifdef _DEBUG
2157 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);
2158 #endif
2159 ReleaseALEffects(pDevice);
2161 ResetUIntMap(&pDevice->EffectMap);
2163 if(pDevice->FilterMap.size > 0)
2165 #ifdef _DEBUG
2166 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);
2167 #endif
2168 ReleaseALFilters(pDevice);
2170 ResetUIntMap(&pDevice->FilterMap);
2172 if(pDevice->DatabufferMap.size > 0)
2174 #ifdef _DEBUG
2175 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferMap.size);
2176 #endif
2177 ReleaseALDatabuffers(pDevice);
2179 ResetUIntMap(&pDevice->DatabufferMap);
2181 free(pDevice->Bs2b);
2182 pDevice->Bs2b = NULL;
2184 free(pDevice->szDeviceName);
2185 pDevice->szDeviceName = NULL;
2187 free(pDevice->Contexts);
2188 pDevice->Contexts = NULL;
2190 //Release device structure
2191 memset(pDevice, 0, sizeof(ALCdevice));
2192 free(pDevice);
2194 return ALC_TRUE;
2198 ALCvoid ReleaseALC(ALCvoid)
2200 free(alcDeviceList); alcDeviceList = NULL;
2201 alcDeviceListSize = 0;
2202 free(alcAllDeviceList); alcAllDeviceList = NULL;
2203 alcAllDeviceListSize = 0;
2204 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
2205 alcCaptureDeviceListSize = 0;
2207 free(alcDefaultDeviceSpecifier);
2208 alcDefaultDeviceSpecifier = NULL;
2209 free(alcDefaultAllDeviceSpecifier);
2210 alcDefaultAllDeviceSpecifier = NULL;
2211 free(alcCaptureDefaultDeviceSpecifier);
2212 alcCaptureDefaultDeviceSpecifier = NULL;
2214 #ifdef _DEBUG
2215 if(g_ulDeviceCount > 0)
2216 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
2217 #endif
2219 while(g_pDeviceList)
2221 if(g_pDeviceList->IsCaptureDevice)
2222 alcCaptureCloseDevice(g_pDeviceList);
2223 else
2224 alcCloseDevice(g_pDeviceList);
2228 ///////////////////////////////////////////////////////