Use DSound notifications to wake up the mixer thread
[openal-soft/android.git] / Alc / ALc.c
blob9423ebc35d82e9f7a6110c3293d548c917989060
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 #if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
24 #define INITGUID
25 #include <windows.h>
26 #ifdef HAVE_GUIDDEF_H
27 #include <guiddef.h>
28 #else
29 #include <initguid.h>
30 #endif
32 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
33 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
35 DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
37 DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e);
38 DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6);
39 DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
40 DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
42 #endif
44 #include <math.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <memory.h>
48 #include <ctype.h>
49 #ifdef HAVE_DLFCN_H
50 #include <dlfcn.h>
51 #endif
53 #include "alMain.h"
54 #include "alSource.h"
55 #include "AL/al.h"
56 #include "AL/alc.h"
57 #include "alThunk.h"
58 #include "alSource.h"
59 #include "alBuffer.h"
60 #include "alAuxEffectSlot.h"
61 #include "bs2b.h"
62 #include "alu.h"
65 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
66 typedef struct BackendInfo {
67 const char *name;
68 void (*Init)(BackendFuncs*);
69 void (*Deinit)(void);
70 void (*Probe)(enum DevProbe);
71 BackendFuncs Funcs;
72 } BackendInfo;
73 static BackendInfo BackendList[] = {
74 #ifdef HAVE_PULSEAUDIO
75 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
76 #endif
77 #ifdef HAVE_ALSA
78 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
79 #endif
80 #ifdef HAVE_COREAUDIO
81 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
82 #endif
83 #ifdef HAVE_OSS
84 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
85 #endif
86 #ifdef HAVE_SOLARIS
87 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
88 #endif
89 #ifdef HAVE_SNDIO
90 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
91 #endif
92 #ifdef HAVE_MMDEVAPI
93 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
94 #endif
95 #ifdef HAVE_DSOUND
96 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
97 #endif
98 #ifdef HAVE_WINMM
99 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
100 #endif
101 #ifdef HAVE_PORTAUDIO
102 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
103 #endif
104 #ifdef HAVE_OPENSL
105 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
106 #endif
108 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
109 #ifdef HAVE_WAVE
110 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
111 #endif
113 { NULL, NULL, NULL, NULL, EmptyFuncs }
115 static BackendInfo BackendLoopback = {
116 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
118 #undef EmptyFuncs
120 ///////////////////////////////////////////////////////
121 // STRING and EXTENSIONS
123 typedef struct ALCfunction {
124 const ALCchar *funcName;
125 ALCvoid *address;
126 } ALCfunction;
128 typedef struct ALCenums {
129 const ALCchar *enumName;
130 ALCenum value;
131 } ALCenums;
134 static const ALCfunction alcFunctions[] = {
135 { "alcCreateContext", (ALCvoid *) alcCreateContext },
136 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },
137 { "alcProcessContext", (ALCvoid *) alcProcessContext },
138 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },
139 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },
140 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },
141 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },
142 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },
143 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },
144 { "alcGetError", (ALCvoid *) alcGetError },
145 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },
146 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },
147 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },
148 { "alcGetString", (ALCvoid *) alcGetString },
149 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },
150 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },
151 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },
152 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },
153 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },
154 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },
156 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },
157 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },
159 { "alcLoopbackOpenDeviceSOFT", (ALCvoid *) alcLoopbackOpenDeviceSOFT},
160 { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT},
161 { "alcRenderSamplesSOFT", (ALCvoid *) alcRenderSamplesSOFT },
163 { "alEnable", (ALCvoid *) alEnable },
164 { "alDisable", (ALCvoid *) alDisable },
165 { "alIsEnabled", (ALCvoid *) alIsEnabled },
166 { "alGetString", (ALCvoid *) alGetString },
167 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },
168 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },
169 { "alGetFloatv", (ALCvoid *) alGetFloatv },
170 { "alGetDoublev", (ALCvoid *) alGetDoublev },
171 { "alGetBoolean", (ALCvoid *) alGetBoolean },
172 { "alGetInteger", (ALCvoid *) alGetInteger },
173 { "alGetFloat", (ALCvoid *) alGetFloat },
174 { "alGetDouble", (ALCvoid *) alGetDouble },
175 { "alGetError", (ALCvoid *) alGetError },
176 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },
177 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },
178 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },
179 { "alListenerf", (ALCvoid *) alListenerf },
180 { "alListener3f", (ALCvoid *) alListener3f },
181 { "alListenerfv", (ALCvoid *) alListenerfv },
182 { "alListeneri", (ALCvoid *) alListeneri },
183 { "alListener3i", (ALCvoid *) alListener3i },
184 { "alListeneriv", (ALCvoid *) alListeneriv },
185 { "alGetListenerf", (ALCvoid *) alGetListenerf },
186 { "alGetListener3f", (ALCvoid *) alGetListener3f },
187 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },
188 { "alGetListeneri", (ALCvoid *) alGetListeneri },
189 { "alGetListener3i", (ALCvoid *) alGetListener3i },
190 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },
191 { "alGenSources", (ALCvoid *) alGenSources },
192 { "alDeleteSources", (ALCvoid *) alDeleteSources },
193 { "alIsSource", (ALCvoid *) alIsSource },
194 { "alSourcef", (ALCvoid *) alSourcef },
195 { "alSource3f", (ALCvoid *) alSource3f },
196 { "alSourcefv", (ALCvoid *) alSourcefv },
197 { "alSourcei", (ALCvoid *) alSourcei },
198 { "alSource3i", (ALCvoid *) alSource3i },
199 { "alSourceiv", (ALCvoid *) alSourceiv },
200 { "alGetSourcef", (ALCvoid *) alGetSourcef },
201 { "alGetSource3f", (ALCvoid *) alGetSource3f },
202 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },
203 { "alGetSourcei", (ALCvoid *) alGetSourcei },
204 { "alGetSource3i", (ALCvoid *) alGetSource3i },
205 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },
206 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },
207 { "alSourceStopv", (ALCvoid *) alSourceStopv },
208 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },
209 { "alSourcePausev", (ALCvoid *) alSourcePausev },
210 { "alSourcePlay", (ALCvoid *) alSourcePlay },
211 { "alSourceStop", (ALCvoid *) alSourceStop },
212 { "alSourceRewind", (ALCvoid *) alSourceRewind },
213 { "alSourcePause", (ALCvoid *) alSourcePause },
214 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },
215 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },
216 { "alGenBuffers", (ALCvoid *) alGenBuffers },
217 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },
218 { "alIsBuffer", (ALCvoid *) alIsBuffer },
219 { "alBufferData", (ALCvoid *) alBufferData },
220 { "alBufferf", (ALCvoid *) alBufferf },
221 { "alBuffer3f", (ALCvoid *) alBuffer3f },
222 { "alBufferfv", (ALCvoid *) alBufferfv },
223 { "alBufferi", (ALCvoid *) alBufferi },
224 { "alBuffer3i", (ALCvoid *) alBuffer3i },
225 { "alBufferiv", (ALCvoid *) alBufferiv },
226 { "alGetBufferf", (ALCvoid *) alGetBufferf },
227 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },
228 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },
229 { "alGetBufferi", (ALCvoid *) alGetBufferi },
230 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },
231 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },
232 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },
233 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },
234 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },
235 { "alDistanceModel", (ALCvoid *) alDistanceModel },
237 { "alGenFilters", (ALCvoid *) alGenFilters },
238 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },
239 { "alIsFilter", (ALCvoid *) alIsFilter },
240 { "alFilteri", (ALCvoid *) alFilteri },
241 { "alFilteriv", (ALCvoid *) alFilteriv },
242 { "alFilterf", (ALCvoid *) alFilterf },
243 { "alFilterfv", (ALCvoid *) alFilterfv },
244 { "alGetFilteri", (ALCvoid *) alGetFilteri },
245 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },
246 { "alGetFilterf", (ALCvoid *) alGetFilterf },
247 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },
249 { "alGenEffects", (ALCvoid *) alGenEffects },
250 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },
251 { "alIsEffect", (ALCvoid *) alIsEffect },
252 { "alEffecti", (ALCvoid *) alEffecti },
253 { "alEffectiv", (ALCvoid *) alEffectiv },
254 { "alEffectf", (ALCvoid *) alEffectf },
255 { "alEffectfv", (ALCvoid *) alEffectfv },
256 { "alGetEffecti", (ALCvoid *) alGetEffecti },
257 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },
258 { "alGetEffectf", (ALCvoid *) alGetEffectf },
259 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },
261 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},
262 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},
263 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },
264 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },
265 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },
266 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },
267 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },
268 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},
269 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},
270 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},
271 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},
273 { "alBufferSubDataSOFT", (ALCvoid *) alBufferSubDataSOFT },
275 { "alBufferSamplesSOFT", (ALCvoid *) alBufferSamplesSOFT },
276 { "alBufferSubSamplesSOFT", (ALCvoid *) alBufferSubSamplesSOFT },
277 { "alGetBufferSamplesSOFT", (ALCvoid *) alGetBufferSamplesSOFT },
278 { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT},
280 { "alDeferUpdatesSOFT", (ALCvoid *) alDeferUpdatesSOFT },
281 { "alProcessUpdatesSOFT", (ALCvoid *) alProcessUpdatesSOFT },
283 { NULL, (ALCvoid *) NULL }
286 static const ALCenums enumeration[] = {
287 // Types
288 { "ALC_INVALID", ALC_INVALID },
289 { "ALC_FALSE", ALC_FALSE },
290 { "ALC_TRUE", ALC_TRUE },
292 // ALC Properties
293 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
294 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },
295 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
296 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
297 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
298 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
299 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
300 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
301 { "ALC_EXTENSIONS", ALC_EXTENSIONS },
302 { "ALC_FREQUENCY", ALC_FREQUENCY },
303 { "ALC_REFRESH", ALC_REFRESH },
304 { "ALC_SYNC", ALC_SYNC },
305 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },
306 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
307 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
308 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
309 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
310 { "ALC_CONNECTED", ALC_CONNECTED },
312 // EFX Properties
313 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
314 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
315 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
317 // Loopback device Properties
318 { "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT },
319 { "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT },
321 // Buffer Channel Configurations
322 { "ALC_MONO", ALC_MONO },
323 { "ALC_STEREO", ALC_STEREO },
324 { "ALC_QUAD", ALC_QUAD },
325 { "ALC_5POINT1", ALC_5POINT1 },
326 { "ALC_6POINT1", ALC_6POINT1 },
327 { "ALC_7POINT1", ALC_7POINT1 },
329 // Buffer Sample Types
330 { "ALC_BYTE", ALC_BYTE },
331 { "ALC_UNSIGNED_BYTE", ALC_UNSIGNED_BYTE },
332 { "ALC_SHORT", ALC_SHORT },
333 { "ALC_UNSIGNED_SHORT", ALC_UNSIGNED_SHORT },
334 { "ALC_INT", ALC_INT },
335 { "ALC_UNSIGNED_INT", ALC_UNSIGNED_INT },
336 { "ALC_FLOAT", ALC_FLOAT },
338 // ALC Error Message
339 { "ALC_NO_ERROR", ALC_NO_ERROR },
340 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
341 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
342 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },
343 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },
344 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
346 { NULL, (ALCenum)0 }
348 // Error strings
349 static const ALCchar alcNoError[] = "No Error";
350 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
351 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
352 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
353 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
354 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
356 /* Device lists. Sizes only include the first ending null character, not the
357 * second */
358 static ALCchar *alcDeviceList;
359 static size_t alcDeviceListSize;
360 static ALCchar *alcAllDeviceList;
361 static size_t alcAllDeviceListSize;
362 static ALCchar *alcCaptureDeviceList;
363 static size_t alcCaptureDeviceListSize;
364 // Default is always the first in the list
365 static ALCchar *alcDefaultDeviceSpecifier;
366 static ALCchar *alcDefaultAllDeviceSpecifier;
367 static ALCchar *alcCaptureDefaultDeviceSpecifier;
370 static const ALCchar alcNoDeviceExtList[] =
371 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
372 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";
373 static const ALCchar alcExtensionList[] =
374 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
375 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
376 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";
377 static const ALCint alcMajorVersion = 1;
378 static const ALCint alcMinorVersion = 1;
380 static const ALCint alcEFXMajorVersion = 1;
381 static const ALCint alcEFXMinorVersion = 0;
383 ///////////////////////////////////////////////////////
386 ///////////////////////////////////////////////////////
387 // Global Variables
389 static CRITICAL_SECTION ListLock;
391 /* Device List */
392 static ALCdevice *g_pDeviceList = NULL;
393 static ALCuint g_ulDeviceCount = 0;
395 // Context List
396 static ALCcontext *g_pContextList = NULL;
397 static ALCuint g_ulContextCount = 0;
399 // Thread-local current context
400 static tls_type LocalContext;
401 // Process-wide current context
402 static ALCcontext *GlobalContext;
404 // Context Error
405 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
407 // Default context extensions
408 static const ALchar alExtList[] =
409 "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 "
410 "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
411 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
412 "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data "
413 "AL_SOFT_loop_points AL_SOFTX_non_virtual_channels";
415 // Mixing Priority Level
416 static ALint RTPrioLevel;
418 // Output Log File
419 static FILE *LogFile;
421 // Output Log Level
422 #ifdef _DEBUG
423 enum LogLevel LogLevel = LogWarning;
424 #else
425 enum LogLevel LogLevel = LogError;
426 #endif
428 // Cone scalar
429 ALdouble ConeScale = 0.5;
431 // Localized Z scalar for mono sources
432 ALdouble ZScale = 1.0;
434 ///////////////////////////////////////////////////////
437 ///////////////////////////////////////////////////////
438 // ALC Related helper functions
439 static void ReleaseALC(void);
441 static void alc_initconfig(void);
443 #if defined(_WIN32)
444 static void alc_init(void);
445 static void alc_deinit(void);
447 #ifndef AL_LIBTYPE_STATIC
448 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
450 (void)lpReserved;
452 // Perform actions based on the reason for calling.
453 switch(ul_reason_for_call)
455 case DLL_PROCESS_ATTACH:
456 DisableThreadLibraryCalls(hModule);
457 alc_init();
458 break;
460 case DLL_PROCESS_DETACH:
461 alc_deinit();
462 break;
464 return TRUE;
466 #elif defined(_MSC_VER)
467 #pragma section(".CRT$XCU",read)
468 static void alc_constructor(void);
469 static void alc_destructor(void);
470 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
472 static void alc_constructor(void)
474 atexit(alc_destructor);
475 alc_init();
478 static void alc_destructor(void)
480 alc_deinit();
482 #elif defined(HAVE_GCC_DESTRUCTOR)
483 static void alc_init(void) __attribute__((constructor));
484 static void alc_deinit(void) __attribute__((destructor));
485 #else
486 #error "No static initialization available on this platform!"
487 #endif
488 #elif defined(HAVE_GCC_DESTRUCTOR)
489 static void alc_init(void) __attribute__((constructor));
490 static void alc_deinit(void) __attribute__((destructor));
491 #else
492 #error "No global initialization available on this platform!"
493 #endif
495 static void alc_init(void)
497 const char *str;
499 LogFile = stderr;
501 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
502 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
503 ConeScale = 1.0;
505 str = getenv("__ALSOFT_REVERSE_Z");
506 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
507 ZScale = -1.0;
509 tls_create(&LocalContext);
510 InitializeCriticalSection(&ListLock);
511 ALTHUNK_INIT();
513 #ifdef _WIN32
514 alc_initconfig();
515 #endif
518 static void alc_deinit(void)
520 int i;
522 ReleaseALC();
524 for(i = 0;BackendList[i].Deinit;i++)
525 BackendList[i].Deinit();
526 BackendLoopback.Deinit();
528 FreeALConfig();
529 ALTHUNK_EXIT();
530 DeleteCriticalSection(&ListLock);
531 tls_delete(LocalContext);
533 if(LogFile != stderr)
534 fclose(LogFile);
535 LogFile = NULL;
538 static void alc_initconfig(void)
540 int i;
541 const char *devs, *str;
543 str = getenv("ALSOFT_LOGLEVEL");
544 if(str)
546 long lvl = strtol(str, NULL, 0);
547 if(lvl >= NoLog && lvl <= LogTrace)
548 LogLevel = lvl;
551 str = getenv("ALSOFT_LOGFILE");
552 if(str && str[0])
554 FILE *logfile = fopen(str, "wat");
555 if(logfile) LogFile = logfile;
556 else ERR("Failed to open log file '%s'\n", str);
559 ReadALConfig();
561 InitHrtf();
563 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
565 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
566 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
567 DefaultResampler = RESAMPLER_DEFAULT;
569 ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) /
570 20.0f);
571 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
573 devs = GetConfigValue(NULL, "drivers", "");
574 if(devs[0])
576 int n;
577 size_t len;
578 const char *next = devs;
579 int endlist, delitem;
581 i = 0;
582 do {
583 devs = next;
584 next = strchr(devs, ',');
586 delitem = (devs[0] == '-');
587 if(devs[0] == '-') devs++;
589 if(!devs[0] || devs[0] == ',')
591 endlist = 0;
592 continue;
594 endlist = 1;
596 len = (next ? ((size_t)(next-devs)) : strlen(devs));
597 for(n = i;BackendList[n].Init;n++)
599 if(len == strlen(BackendList[n].name) &&
600 strncmp(BackendList[n].name, devs, len) == 0)
602 if(delitem)
604 do {
605 BackendList[n] = BackendList[n+1];
606 ++n;
607 } while(BackendList[n].Init);
609 else
611 BackendInfo Bkp = BackendList[n];
612 while(n > i)
614 BackendList[n] = BackendList[n-1];
615 --n;
617 BackendList[n] = Bkp;
619 i++;
621 break;
624 } while(next++);
626 if(endlist)
628 BackendList[i].name = NULL;
629 BackendList[i].Init = NULL;
630 BackendList[i].Deinit = NULL;
631 BackendList[i].Probe = NULL;
635 for(i = 0;BackendList[i].Init;i++)
636 BackendList[i].Init(&BackendList[i].Funcs);
637 BackendLoopback.Init(&BackendLoopback.Funcs);
639 str = GetConfigValue(NULL, "excludefx", "");
640 if(str[0])
642 int n;
643 size_t len;
644 const char *next = str;
646 do {
647 str = next;
648 next = strchr(str, ',');
650 if(!str[0] || next == str)
651 continue;
653 len = (next ? ((size_t)(next-str)) : strlen(str));
654 for(n = 0;EffectList[n].name;n++)
656 if(len == strlen(EffectList[n].name) &&
657 strncmp(EffectList[n].name, str, len) == 0)
658 DisabledEffects[EffectList[n].type] = AL_TRUE;
660 } while(next++);
664 #ifndef _WIN32
665 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
666 #define DO_INITCONFIG() pthread_once(&once_control, alc_initconfig)
667 #else
668 #define DO_INITCONFIG()
669 #endif
671 static void ProbeList(ALCchar **list, size_t *listsize, int type)
673 ALint i;
675 free(*list);
676 *list = NULL;
677 *listsize = 0;
679 DO_INITCONFIG();
680 for(i = 0;BackendList[i].Probe;i++)
681 BackendList[i].Probe(type);
684 static void ProbeDeviceList()
685 { ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }
686 static void ProbeAllDeviceList()
687 { ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }
688 static void ProbeCaptureDeviceList()
689 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
692 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
694 size_t len = strlen(name);
695 void *temp;
697 if(len == 0)
698 return;
700 temp = realloc(*List, (*ListSize) + len + 2);
701 if(!temp)
703 ERR("Realloc failed to add %s!\n", name);
704 return;
706 *List = temp;
708 memcpy((*List)+(*ListSize), name, len+1);
709 *ListSize += len+1;
710 (*List)[*ListSize] = 0;
713 #define DECL_APPEND_LIST_FUNC(type) \
714 void Append##type##List(const ALCchar *name) \
715 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
717 DECL_APPEND_LIST_FUNC(Device)
718 DECL_APPEND_LIST_FUNC(AllDevice)
719 DECL_APPEND_LIST_FUNC(CaptureDevice)
721 #undef DECL_APPEND_LIST_FUNC
724 void al_print(const char *fname, unsigned int line, const char *fmt, ...)
726 const char *fn;
727 char str[256];
728 int i;
730 fn = strrchr(fname, '/');
731 if(!fn) fn = strrchr(fname, '\\');
732 if(!fn) fn = fname;
733 else fn += 1;
735 i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
736 if(i < (int)sizeof(str) && i > 0)
738 va_list ap;
739 va_start(ap, fmt);
740 vsnprintf(str+i, sizeof(str)-i, fmt, ap);
741 va_end(ap);
743 str[sizeof(str)-1] = 0;
745 fprintf(LogFile, "%s", str);
746 fflush(LogFile);
749 void SetRTPriority(void)
751 ALboolean failed;
753 #ifdef _WIN32
754 if(RTPrioLevel > 0)
755 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
756 else
757 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
758 #elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__)
759 struct sched_param param;
761 if(RTPrioLevel > 0)
763 /* Use the minimum real-time priority possible for now (on Linux this
764 * should be 1 for SCHED_RR) */
765 param.sched_priority = sched_get_priority_min(SCHED_RR);
766 failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
768 else
770 param.sched_priority = 0;
771 failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
773 #else
774 /* Real-time priority not available */
775 failed = (RTPrioLevel>0);
776 #endif
777 if(failed)
778 ERR("Failed to set priority level for thread\n");
782 void InitUIntMap(UIntMap *map)
784 map->array = NULL;
785 map->size = 0;
786 map->maxsize = 0;
789 void ResetUIntMap(UIntMap *map)
791 free(map->array);
792 map->array = NULL;
793 map->size = 0;
794 map->maxsize = 0;
797 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
799 ALsizei pos = 0;
801 if(map->size > 0)
803 ALsizei low = 0;
804 ALsizei high = map->size - 1;
805 while(low < high)
807 ALsizei mid = low + (high-low)/2;
808 if(map->array[mid].key < key)
809 low = mid + 1;
810 else
811 high = mid;
813 if(map->array[low].key < key)
814 low++;
815 pos = low;
818 if(pos == map->size || map->array[pos].key != key)
820 if(map->size == map->maxsize)
822 ALvoid *temp;
823 ALsizei newsize;
825 newsize = (map->maxsize ? (map->maxsize<<1) : 4);
826 if(newsize < map->maxsize)
827 return AL_OUT_OF_MEMORY;
829 temp = realloc(map->array, newsize*sizeof(map->array[0]));
830 if(!temp) return AL_OUT_OF_MEMORY;
831 map->array = temp;
832 map->maxsize = newsize;
835 map->size++;
836 if(pos < map->size-1)
837 memmove(&map->array[pos+1], &map->array[pos],
838 (map->size-1-pos)*sizeof(map->array[0]));
840 map->array[pos].key = key;
841 map->array[pos].value = value;
843 return AL_NO_ERROR;
846 void RemoveUIntMapKey(UIntMap *map, ALuint key)
848 if(map->size > 0)
850 ALsizei low = 0;
851 ALsizei high = map->size - 1;
852 while(low < high)
854 ALsizei mid = low + (high-low)/2;
855 if(map->array[mid].key < key)
856 low = mid + 1;
857 else
858 high = mid;
860 if(map->array[low].key == key)
862 if(low < map->size-1)
863 memmove(&map->array[low], &map->array[low+1],
864 (map->size-1-low)*sizeof(map->array[0]));
865 map->size--;
870 ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
872 if(map->size > 0)
874 ALsizei low = 0;
875 ALsizei high = map->size - 1;
876 while(low < high)
878 ALsizei mid = low + (high-low)/2;
879 if(map->array[mid].key < key)
880 low = mid + 1;
881 else
882 high = mid;
884 if(map->array[low].key == key)
885 return map->array[low].value;
887 return NULL;
891 const ALCchar *DevFmtTypeString(enum DevFmtType type)
893 switch(type)
895 case DevFmtByte: return "Signed Byte";
896 case DevFmtUByte: return "Unsigned Byte";
897 case DevFmtShort: return "Signed Short";
898 case DevFmtUShort: return "Unsigned Short";
899 case DevFmtFloat: return "Float";
901 return "(unknown type)";
903 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
905 switch(chans)
907 case DevFmtMono: return "Mono";
908 case DevFmtStereo: return "Stereo";
909 case DevFmtQuad: return "Quadraphonic";
910 case DevFmtX51: return "5.1 Surround";
911 case DevFmtX51Side: return "5.1 Side";
912 case DevFmtX61: return "6.1 Surround";
913 case DevFmtX71: return "7.1 Surround";
915 return "(unknown channels)";
918 ALuint BytesFromDevFmt(enum DevFmtType type)
920 switch(type)
922 case DevFmtByte: return sizeof(ALbyte);
923 case DevFmtUByte: return sizeof(ALubyte);
924 case DevFmtShort: return sizeof(ALshort);
925 case DevFmtUShort: return sizeof(ALushort);
926 case DevFmtFloat: return sizeof(ALfloat);
928 return 0;
930 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
932 switch(chans)
934 case DevFmtMono: return 1;
935 case DevFmtStereo: return 2;
936 case DevFmtQuad: return 4;
937 case DevFmtX51: return 6;
938 case DevFmtX51Side: return 6;
939 case DevFmtX61: return 7;
940 case DevFmtX71: return 8;
942 return 0;
944 ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
945 enum DevFmtType *type)
947 switch(format)
949 case AL_FORMAT_MONO8:
950 *chans = DevFmtMono;
951 *type = DevFmtUByte;
952 return AL_TRUE;
953 case AL_FORMAT_MONO16:
954 *chans = DevFmtMono;
955 *type = DevFmtShort;
956 return AL_TRUE;
957 case AL_FORMAT_MONO_FLOAT32:
958 *chans = DevFmtMono;
959 *type = DevFmtFloat;
960 return AL_TRUE;
961 case AL_FORMAT_STEREO8:
962 *chans = DevFmtStereo;
963 *type = DevFmtUByte;
964 return AL_TRUE;
965 case AL_FORMAT_STEREO16:
966 *chans = DevFmtStereo;
967 *type = DevFmtShort;
968 return AL_TRUE;
969 case AL_FORMAT_STEREO_FLOAT32:
970 *chans = DevFmtStereo;
971 *type = DevFmtFloat;
972 return AL_TRUE;
973 case AL_FORMAT_QUAD8:
974 *chans = DevFmtQuad;
975 *type = DevFmtUByte;
976 return AL_TRUE;
977 case AL_FORMAT_QUAD16:
978 *chans = DevFmtQuad;
979 *type = DevFmtShort;
980 return AL_TRUE;
981 case AL_FORMAT_QUAD32:
982 *chans = DevFmtQuad;
983 *type = DevFmtFloat;
984 return AL_TRUE;
985 case AL_FORMAT_51CHN8:
986 *chans = DevFmtX51;
987 *type = DevFmtUByte;
988 return AL_TRUE;
989 case AL_FORMAT_51CHN16:
990 *chans = DevFmtX51;
991 *type = DevFmtShort;
992 return AL_TRUE;
993 case AL_FORMAT_51CHN32:
994 *chans = DevFmtX51;
995 *type = DevFmtFloat;
996 return AL_TRUE;
997 case AL_FORMAT_61CHN8:
998 *chans = DevFmtX61;
999 *type = DevFmtUByte;
1000 return AL_TRUE;
1001 case AL_FORMAT_61CHN16:
1002 *chans = DevFmtX61;
1003 *type = DevFmtShort;
1004 return AL_TRUE;
1005 case AL_FORMAT_61CHN32:
1006 *chans = DevFmtX61;
1007 *type = DevFmtFloat;
1008 return AL_TRUE;
1009 case AL_FORMAT_71CHN8:
1010 *chans = DevFmtX71;
1011 *type = DevFmtUByte;
1012 return AL_TRUE;
1013 case AL_FORMAT_71CHN16:
1014 *chans = DevFmtX71;
1015 *type = DevFmtShort;
1016 return AL_TRUE;
1017 case AL_FORMAT_71CHN32:
1018 *chans = DevFmtX71;
1019 *type = DevFmtFloat;
1020 return AL_TRUE;
1022 return AL_FALSE;
1025 static ALCboolean IsValidALCType(ALCenum type)
1027 switch(type)
1029 case ALC_BYTE:
1030 case ALC_UNSIGNED_BYTE:
1031 case ALC_SHORT:
1032 case ALC_UNSIGNED_SHORT:
1033 case ALC_INT:
1034 case ALC_UNSIGNED_INT:
1035 case ALC_FLOAT:
1036 return ALC_TRUE;
1038 return ALC_FALSE;
1041 static ALCboolean IsValidALCChannels(ALCenum channels)
1043 switch(channels)
1045 case ALC_MONO:
1046 case ALC_STEREO:
1047 case ALC_QUAD:
1048 case ALC_5POINT1:
1049 case ALC_6POINT1:
1050 case ALC_7POINT1:
1051 return ALC_TRUE;
1053 return ALC_FALSE;
1057 #ifndef _WIN32
1058 void InitializeCriticalSection(CRITICAL_SECTION *cs)
1060 pthread_mutexattr_t attrib;
1061 int ret;
1063 ret = pthread_mutexattr_init(&attrib);
1064 assert(ret == 0);
1066 ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
1067 #ifdef HAVE_PTHREAD_NP_H
1068 if(ret != 0)
1069 ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
1070 #endif
1071 assert(ret == 0);
1072 ret = pthread_mutex_init(cs, &attrib);
1073 assert(ret == 0);
1075 pthread_mutexattr_destroy(&attrib);
1077 void DeleteCriticalSection(CRITICAL_SECTION *cs)
1079 int ret;
1080 ret = pthread_mutex_destroy(cs);
1081 assert(ret == 0);
1083 void EnterCriticalSection(CRITICAL_SECTION *cs)
1085 int ret;
1086 ret = pthread_mutex_lock(cs);
1087 assert(ret == 0);
1089 void LeaveCriticalSection(CRITICAL_SECTION *cs)
1091 int ret;
1092 ret = pthread_mutex_unlock(cs);
1093 assert(ret == 0);
1096 /* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
1097 * to the expected DWORD. Both are defined as unsigned 32-bit types, however.
1098 * Additionally, Win32 is supposed to measure the time since Windows started,
1099 * as opposed to the actual time. */
1100 ALuint timeGetTime(void)
1102 #if _POSIX_TIMERS > 0
1103 struct timespec ts;
1104 int ret = -1;
1106 #if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
1107 #if _POSIX_MONOTONIC_CLOCK == 0
1108 static int hasmono = 0;
1109 if(hasmono > 0 || (hasmono == 0 &&
1110 (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0))
1111 #endif
1112 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
1113 #endif
1114 if(ret != 0)
1115 ret = clock_gettime(CLOCK_REALTIME, &ts);
1116 assert(ret == 0);
1118 return ts.tv_nsec/1000000 + ts.tv_sec*1000;
1119 #else
1120 struct timeval tv;
1121 int ret;
1123 ret = gettimeofday(&tv, NULL);
1124 assert(ret == 0);
1126 return tv.tv_usec/1000 + tv.tv_sec*1000;
1127 #endif
1129 #endif
1131 #if defined(_WIN32)
1132 void *LoadLib(const char *name)
1133 { return LoadLibraryA(name); }
1135 void CloseLib(void *handle)
1136 { FreeLibrary((HANDLE)handle); }
1138 void *GetSymbol(void *handle, const char *name)
1140 void *ret;
1142 ret = (void*)GetProcAddress((HANDLE)handle, name);
1143 if(ret == NULL)
1144 ERR("Failed to load %s\n", name);
1145 return ret;
1148 #elif defined(HAVE_DLFCN_H)
1150 void *LoadLib(const char *name)
1152 const char *err;
1153 void *handle;
1155 dlerror();
1156 handle = dlopen(name, RTLD_NOW);
1157 if((err=dlerror()) != NULL)
1158 handle = NULL;
1159 return handle;
1162 void CloseLib(void *handle)
1163 { dlclose(handle); }
1165 void *GetSymbol(void *handle, const char *name)
1167 const char *err;
1168 void *sym;
1170 dlerror();
1171 sym = dlsym(handle, name);
1172 if((err=dlerror()) != NULL)
1174 ERR("Failed to load %s: %s\n", name, err);
1175 sym = NULL;
1177 return sym;
1179 #endif
1181 static void LockLists(void)
1183 EnterCriticalSection(&ListLock);
1186 static void UnlockLists(void)
1188 LeaveCriticalSection(&ListLock);
1192 IsDevice
1194 Check pDevice is a valid Device pointer
1196 static ALCboolean IsDevice(ALCdevice *pDevice)
1198 ALCdevice *pTempDevice;
1200 pTempDevice = g_pDeviceList;
1201 while(pTempDevice && pTempDevice != pDevice)
1202 pTempDevice = pTempDevice->next;
1204 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
1208 IsContext
1210 Check pContext is a valid Context pointer
1212 static ALCboolean IsContext(ALCcontext *pContext)
1214 ALCcontext *pTempContext;
1216 pTempContext = g_pContextList;
1217 while (pTempContext && pTempContext != pContext)
1218 pTempContext = pTempContext->next;
1220 return (pTempContext ? ALC_TRUE : ALC_FALSE);
1225 alcSetError
1227 Store latest ALC Error
1229 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
1231 LockLists();
1232 if(IsDevice(device))
1233 device->LastError = errorCode;
1234 else
1235 g_eLastNullDeviceError = errorCode;
1236 UnlockLists();
1240 /* UpdateDeviceParams:
1242 * Updates device parameters according to the attribute list.
1244 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1246 ALuint i;
1248 // Check for attributes
1249 if(attrList && attrList[0])
1251 ALCuint freq, numMono, numStereo, numSends;
1252 enum DevFmtChannels schans;
1253 enum DevFmtType stype;
1254 ALuint attrIdx;
1256 // If a context is already running on the device, stop playback so the
1257 // device attributes can be updated
1258 if((device->Flags&DEVICE_RUNNING))
1259 ALCdevice_StopPlayback(device);
1260 device->Flags &= ~DEVICE_RUNNING;
1262 freq = device->Frequency;
1263 schans = device->FmtChans;
1264 stype = device->FmtType;
1265 numMono = device->NumMonoSources;
1266 numStereo = device->NumStereoSources;
1267 numSends = device->NumAuxSends;
1269 freq = GetConfigValueInt(NULL, "frequency", freq);
1270 if(freq < 8000) freq = 8000;
1272 attrIdx = 0;
1273 while(attrList[attrIdx])
1275 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT &&
1276 device->IsLoopbackDevice)
1278 ALCint val = attrList[attrIdx + 1];
1279 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1281 alcSetError(device, ALC_INVALID_VALUE);
1282 return ALC_FALSE;
1284 schans = val;
1287 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT &&
1288 device->IsLoopbackDevice)
1290 ALCint val = attrList[attrIdx + 1];
1291 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1293 alcSetError(device, ALC_INVALID_VALUE);
1294 return ALC_FALSE;
1296 stype = val;
1299 if(attrList[attrIdx] == ALC_FREQUENCY)
1301 if(device->IsLoopbackDevice)
1303 freq = attrList[attrIdx + 1];
1304 if(freq < 8000)
1306 alcSetError(device, ALC_INVALID_VALUE);
1307 return ALC_FALSE;
1310 else if(!ConfigValueExists(NULL, "frequency"))
1312 freq = attrList[attrIdx + 1];
1313 if(freq < 8000) freq = 8000;
1314 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1318 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1320 numStereo = attrList[attrIdx + 1];
1321 if(numStereo > device->MaxNoOfSources)
1322 numStereo = device->MaxNoOfSources;
1324 numMono = device->MaxNoOfSources - numStereo;
1327 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
1328 !ConfigValueExists(NULL, "sends"))
1330 numSends = attrList[attrIdx + 1];
1331 if(numSends > MAX_SENDS)
1332 numSends = MAX_SENDS;
1335 attrIdx += 2;
1338 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1339 device->Frequency;
1341 device->Frequency = freq;
1342 device->FmtChans = schans;
1343 device->FmtType = stype;
1344 device->NumMonoSources = numMono;
1345 device->NumStereoSources = numStereo;
1346 device->NumAuxSends = numSends;
1349 if((device->Flags&DEVICE_RUNNING))
1350 return ALC_TRUE;
1352 LockDevice(device);
1353 TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n",
1354 DevFmtChannelsString(device->FmtChans),
1355 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1356 DevFmtTypeString(device->FmtType), device->Frequency,
1357 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1358 device->UpdateSize, device->NumUpdates);
1359 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1361 UnlockDevice(device);
1362 return ALC_FALSE;
1364 device->Flags |= DEVICE_RUNNING;
1365 TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n",
1366 DevFmtChannelsString(device->FmtChans),
1367 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1368 DevFmtTypeString(device->FmtType), device->Frequency,
1369 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1370 device->UpdateSize, device->NumUpdates);
1372 aluInitPanning(device);
1374 for(i = 0;i < MAXCHANNELS;i++)
1376 device->ClickRemoval[i] = 0.0f;
1377 device->PendingClicks[i] = 0.0f;
1380 if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1381 device->Flags |= DEVICE_USE_HRTF;
1382 if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device))
1383 device->Flags &= ~DEVICE_USE_HRTF;
1384 TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled");
1386 if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1388 if(!device->Bs2b)
1390 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1391 bs2b_clear(device->Bs2b);
1393 bs2b_set_srate(device->Bs2b, device->Frequency);
1394 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1395 TRACE("BS2B level %d\n", device->Bs2bLevel);
1397 else
1399 free(device->Bs2b);
1400 device->Bs2b = NULL;
1401 TRACE("BS2B disabled\n");
1404 device->Flags &= ~DEVICE_DUPLICATE_STEREO;
1405 switch(device->FmtChans)
1407 case DevFmtMono:
1408 case DevFmtStereo:
1409 break;
1410 case DevFmtQuad:
1411 case DevFmtX51:
1412 case DevFmtX51Side:
1413 case DevFmtX61:
1414 case DevFmtX71:
1415 if(GetConfigValueBool(NULL, "stereodup", AL_TRUE))
1416 device->Flags |= DEVICE_DUPLICATE_STEREO;
1417 break;
1419 TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");
1421 for(i = 0;i < device->NumContexts;i++)
1423 ALCcontext *context = device->Contexts[i];
1424 ALsizei pos;
1426 context->UpdateSources = AL_FALSE;
1427 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1429 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1431 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1433 UnlockDevice(device);
1434 ALCdevice_StopPlayback(device);
1435 device->Flags &= ~DEVICE_RUNNING;
1436 return ALC_FALSE;
1438 slot->NeedsUpdate = AL_FALSE;
1439 ALEffect_Update(slot->EffectState, context, slot);
1442 for(pos = 0;pos < context->SourceMap.size;pos++)
1444 ALsource *source = context->SourceMap.array[pos].value;
1445 ALuint s = device->NumAuxSends;
1446 while(s < MAX_SENDS)
1448 if(source->Send[s].Slot)
1449 source->Send[s].Slot->refcount--;
1450 source->Send[s].Slot = NULL;
1451 source->Send[s].WetFilter.type = 0;
1452 source->Send[s].WetFilter.filter = 0;
1453 s++;
1455 source->NeedsUpdate = AL_FALSE;
1456 ALsource_Update(source, context);
1459 UnlockDevice(device);
1461 return ALC_TRUE;
1465 ALCvoid LockDevice(ALCdevice *device)
1467 EnterCriticalSection(&device->Mutex);
1470 ALCvoid UnlockDevice(ALCdevice *device)
1472 LeaveCriticalSection(&device->Mutex);
1476 LockContext
1478 Thread-safe entry
1480 ALCvoid LockContext(ALCcontext *context)
1482 EnterCriticalSection(&context->Device->Mutex);
1487 UnlockContext
1489 Thread-safe exit
1491 ALCvoid UnlockContext(ALCcontext *context)
1493 LeaveCriticalSection(&context->Device->Mutex);
1498 GetLockedContext
1500 Returns the currently active Context, in a locked state
1502 ALCcontext *GetLockedContext(void)
1504 ALCcontext *pContext = NULL;
1506 LockLists();
1508 pContext = tls_get(LocalContext);
1509 if(pContext && !IsContext(pContext))
1511 tls_set(LocalContext, NULL);
1512 pContext = NULL;
1514 if(!pContext)
1515 pContext = GlobalContext;
1516 if(pContext)
1517 LockContext(pContext);
1519 UnlockLists();
1521 return pContext;
1526 InitContext
1528 Initialize Context variables
1530 static ALvoid InitContext(ALCcontext *pContext)
1532 //Initialise listener
1533 pContext->Listener.Gain = 1.0f;
1534 pContext->Listener.MetersPerUnit = 1.0f;
1535 pContext->Listener.Position[0] = 0.0f;
1536 pContext->Listener.Position[1] = 0.0f;
1537 pContext->Listener.Position[2] = 0.0f;
1538 pContext->Listener.Velocity[0] = 0.0f;
1539 pContext->Listener.Velocity[1] = 0.0f;
1540 pContext->Listener.Velocity[2] = 0.0f;
1541 pContext->Listener.Forward[0] = 0.0f;
1542 pContext->Listener.Forward[1] = 0.0f;
1543 pContext->Listener.Forward[2] = -1.0f;
1544 pContext->Listener.Up[0] = 0.0f;
1545 pContext->Listener.Up[1] = 1.0f;
1546 pContext->Listener.Up[2] = 0.0f;
1548 //Validate pContext
1549 pContext->LastError = AL_NO_ERROR;
1550 pContext->UpdateSources = AL_FALSE;
1551 pContext->ActiveSourceCount = 0;
1552 InitUIntMap(&pContext->SourceMap);
1553 InitUIntMap(&pContext->EffectSlotMap);
1555 //Set globals
1556 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1557 pContext->SourceDistanceModel = AL_FALSE;
1558 pContext->DopplerFactor = 1.0f;
1559 pContext->DopplerVelocity = 1.0f;
1560 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1561 pContext->DeferUpdates = AL_FALSE;
1563 pContext->ExtensionList = alExtList;
1568 ExitContext
1570 Clean up Context, destroy any remaining Sources
1572 static ALCvoid ExitContext(ALCcontext *pContext)
1574 //Invalidate context
1575 pContext->LastError = AL_NO_ERROR;
1578 ///////////////////////////////////////////////////////
1581 ///////////////////////////////////////////////////////
1582 // ALC Functions calls
1585 // This should probably move to another c file but for now ...
1586 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
1588 ALCboolean DeviceFound = ALC_FALSE;
1589 ALCdevice *device = NULL;
1590 ALCint i;
1592 DO_INITCONFIG();
1594 if(SampleSize <= 0)
1596 alcSetError(NULL, ALC_INVALID_VALUE);
1597 return NULL;
1600 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))
1601 deviceName = NULL;
1603 device = calloc(1, sizeof(ALCdevice));
1604 if(!device)
1606 alcSetError(NULL, ALC_OUT_OF_MEMORY);
1607 return NULL;
1610 //Validate device
1611 device->Connected = ALC_TRUE;
1612 device->IsCaptureDevice = AL_TRUE;
1613 device->IsLoopbackDevice = AL_FALSE;
1614 InitializeCriticalSection(&device->Mutex);
1616 device->szDeviceName = NULL;
1618 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1619 device->Frequency = frequency;
1621 device->Flags |= DEVICE_CHANNELS_REQUEST;
1622 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
1624 free(device);
1625 alcSetError(NULL, ALC_INVALID_ENUM);
1626 return NULL;
1629 device->UpdateSize = SampleSize;
1630 device->NumUpdates = 1;
1632 LockLists();
1633 for(i = 0;BackendList[i].Init;i++)
1635 device->Funcs = &BackendList[i].Funcs;
1636 if(ALCdevice_OpenCapture(device, deviceName))
1638 device->next = g_pDeviceList;
1639 g_pDeviceList = device;
1640 g_ulDeviceCount++;
1642 DeviceFound = ALC_TRUE;
1643 break;
1646 UnlockLists();
1648 if(!DeviceFound)
1650 alcSetError(NULL, ALC_INVALID_VALUE);
1651 free(device);
1652 device = NULL;
1655 return device;
1658 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
1660 ALCdevice **list;
1662 LockLists();
1663 list = &g_pDeviceList;
1664 while(*list && *list != pDevice)
1665 list = &(*list)->next;
1667 if(!*list || !(*list)->IsCaptureDevice)
1669 alcSetError(*list, ALC_INVALID_DEVICE);
1670 UnlockLists();
1671 return ALC_FALSE;
1674 *list = (*list)->next;
1675 g_ulDeviceCount--;
1677 UnlockLists();
1679 LockDevice(pDevice);
1680 ALCdevice_CloseCapture(pDevice);
1681 UnlockDevice(pDevice);
1683 free(pDevice->szDeviceName);
1684 pDevice->szDeviceName = NULL;
1686 DeleteCriticalSection(&pDevice->Mutex);
1688 free(pDevice);
1690 return ALC_TRUE;
1693 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
1695 LockLists();
1696 if(!IsDevice(device) || !device->IsCaptureDevice)
1698 alcSetError(device, ALC_INVALID_DEVICE);
1699 UnlockLists();
1700 return;
1702 LockDevice(device);
1703 UnlockLists();
1704 if(device->Connected)
1705 ALCdevice_StartCapture(device);
1706 UnlockDevice(device);
1709 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
1711 LockLists();
1712 if(!IsDevice(device) || !device->IsCaptureDevice)
1714 alcSetError(device, ALC_INVALID_DEVICE);
1715 UnlockLists();
1716 return;
1718 LockDevice(device);
1719 UnlockLists();
1720 if(device->Connected)
1721 ALCdevice_StopCapture(device);
1722 UnlockDevice(device);
1725 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
1727 LockLists();
1728 if(!IsDevice(device) || !device->IsCaptureDevice)
1730 alcSetError(device, ALC_INVALID_DEVICE);
1731 UnlockLists();
1732 return;
1734 LockDevice(device);
1735 UnlockLists();
1736 if(device->Connected)
1737 ALCdevice_CaptureSamples(device, buffer, samples);
1738 UnlockDevice(device);
1742 alcGetError
1744 Return last ALC generated error code
1746 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1748 ALCenum errorCode;
1750 LockLists();
1751 if(IsDevice(device))
1753 errorCode = device->LastError;
1754 device->LastError = ALC_NO_ERROR;
1756 else
1758 errorCode = g_eLastNullDeviceError;
1759 g_eLastNullDeviceError = ALC_NO_ERROR;
1761 UnlockLists();
1762 return errorCode;
1767 alcSuspendContext
1769 Not functional
1771 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1773 (void)Context;
1778 alcProcessContext
1780 Not functional
1782 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
1784 (void)Context;
1789 alcGetString
1791 Returns information about the Device, and error strings
1793 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
1795 const ALCchar *value = NULL;
1797 switch(param)
1799 case ALC_NO_ERROR:
1800 value = alcNoError;
1801 break;
1803 case ALC_INVALID_ENUM:
1804 value = alcErrInvalidEnum;
1805 break;
1807 case ALC_INVALID_VALUE:
1808 value = alcErrInvalidValue;
1809 break;
1811 case ALC_INVALID_DEVICE:
1812 value = alcErrInvalidDevice;
1813 break;
1815 case ALC_INVALID_CONTEXT:
1816 value = alcErrInvalidContext;
1817 break;
1819 case ALC_OUT_OF_MEMORY:
1820 value = alcErrOutOfMemory;
1821 break;
1823 case ALC_DEVICE_SPECIFIER:
1824 LockLists();
1825 if(IsDevice(pDevice))
1826 value = pDevice->szDeviceName;
1827 else
1829 ProbeDeviceList();
1830 value = alcDeviceList;
1832 UnlockLists();
1833 break;
1835 case ALC_ALL_DEVICES_SPECIFIER:
1836 ProbeAllDeviceList();
1837 value = alcAllDeviceList;
1838 break;
1840 case ALC_CAPTURE_DEVICE_SPECIFIER:
1841 LockLists();
1842 if(IsDevice(pDevice))
1843 value = pDevice->szDeviceName;
1844 else
1846 ProbeCaptureDeviceList();
1847 value = alcCaptureDeviceList;
1849 UnlockLists();
1850 break;
1852 /* Default devices are always first in the list */
1853 case ALC_DEFAULT_DEVICE_SPECIFIER:
1854 if(!alcDeviceList)
1855 ProbeDeviceList();
1857 free(alcDefaultDeviceSpecifier);
1858 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
1859 if(!alcDefaultDeviceSpecifier)
1860 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1861 value = alcDefaultDeviceSpecifier;
1862 break;
1864 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
1865 if(!alcAllDeviceList)
1866 ProbeAllDeviceList();
1868 free(alcDefaultAllDeviceSpecifier);
1869 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
1870 alcAllDeviceList : "");
1871 if(!alcDefaultAllDeviceSpecifier)
1872 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1873 value = alcDefaultAllDeviceSpecifier;
1874 break;
1876 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
1877 if(!alcCaptureDeviceList)
1878 ProbeCaptureDeviceList();
1880 free(alcCaptureDefaultDeviceSpecifier);
1881 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
1882 alcCaptureDeviceList : "");
1883 if(!alcCaptureDefaultDeviceSpecifier)
1884 alcSetError(pDevice, ALC_OUT_OF_MEMORY);
1885 value = alcCaptureDefaultDeviceSpecifier;
1886 break;
1888 case ALC_EXTENSIONS:
1889 LockLists();
1890 if(IsDevice(pDevice))
1891 value = alcExtensionList;
1892 else
1893 value = alcNoDeviceExtList;
1894 UnlockLists();
1895 break;
1897 default:
1898 alcSetError(pDevice, ALC_INVALID_ENUM);
1899 break;
1902 return value;
1907 alcGetIntegerv
1909 Returns information about the Device and the version of Open AL
1911 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
1913 if(size == 0 || data == NULL)
1915 alcSetError(device, ALC_INVALID_VALUE);
1916 return;
1919 LockLists();
1920 if(!IsDevice(device))
1922 switch(param)
1924 case ALC_MAJOR_VERSION:
1925 *data = alcMajorVersion;
1926 break;
1927 case ALC_MINOR_VERSION:
1928 *data = alcMinorVersion;
1929 break;
1931 case ALC_ATTRIBUTES_SIZE:
1932 case ALC_ALL_ATTRIBUTES:
1933 case ALC_FREQUENCY:
1934 case ALC_REFRESH:
1935 case ALC_SYNC:
1936 case ALC_MONO_SOURCES:
1937 case ALC_STEREO_SOURCES:
1938 case ALC_CAPTURE_SAMPLES:
1939 case ALC_FORMAT_CHANNELS_SOFT:
1940 case ALC_FORMAT_TYPE_SOFT:
1941 alcSetError(NULL, ALC_INVALID_DEVICE);
1942 break;
1944 default:
1945 alcSetError(NULL, ALC_INVALID_ENUM);
1946 break;
1949 else if(device->IsCaptureDevice)
1951 switch(param)
1953 case ALC_CAPTURE_SAMPLES:
1954 LockDevice(device);
1955 *data = ALCdevice_AvailableSamples(device);
1956 UnlockDevice(device);
1957 break;
1959 case ALC_CONNECTED:
1960 *data = device->Connected;
1961 break;
1963 default:
1964 alcSetError(device, ALC_INVALID_ENUM);
1965 break;
1968 else /* render device */
1970 switch(param)
1972 case ALC_MAJOR_VERSION:
1973 *data = alcMajorVersion;
1974 break;
1976 case ALC_MINOR_VERSION:
1977 *data = alcMinorVersion;
1978 break;
1980 case ALC_EFX_MAJOR_VERSION:
1981 *data = alcEFXMajorVersion;
1982 break;
1984 case ALC_EFX_MINOR_VERSION:
1985 *data = alcEFXMinorVersion;
1986 break;
1988 case ALC_ATTRIBUTES_SIZE:
1989 *data = 13;
1990 break;
1992 case ALC_ALL_ATTRIBUTES:
1993 if(size < 13)
1994 alcSetError(device, ALC_INVALID_VALUE);
1995 else
1997 int i = 0;
1999 data[i++] = ALC_FREQUENCY;
2000 data[i++] = device->Frequency;
2002 if(!device->IsLoopbackDevice)
2004 data[i++] = ALC_REFRESH;
2005 data[i++] = device->Frequency / device->UpdateSize;
2007 data[i++] = ALC_SYNC;
2008 data[i++] = ALC_FALSE;
2010 else
2012 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2013 data[i++] = device->FmtChans;
2015 data[i++] = ALC_FORMAT_TYPE_SOFT;
2016 data[i++] = device->FmtType;
2019 data[i++] = ALC_MONO_SOURCES;
2020 data[i++] = device->NumMonoSources;
2022 data[i++] = ALC_STEREO_SOURCES;
2023 data[i++] = device->NumStereoSources;
2025 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2026 data[i++] = device->NumAuxSends;
2028 data[i++] = 0;
2030 break;
2032 case ALC_FREQUENCY:
2033 *data = device->Frequency;
2034 break;
2036 case ALC_REFRESH:
2037 if(device->IsLoopbackDevice)
2038 alcSetError(device, ALC_INVALID_DEVICE);
2039 else
2040 *data = device->Frequency / device->UpdateSize;
2041 break;
2043 case ALC_SYNC:
2044 if(device->IsLoopbackDevice)
2045 alcSetError(device, ALC_INVALID_DEVICE);
2046 else
2047 *data = ALC_FALSE;
2048 break;
2050 case ALC_FORMAT_CHANNELS_SOFT:
2051 if(!device->IsLoopbackDevice)
2052 alcSetError(device, ALC_INVALID_DEVICE);
2053 else
2054 *data = device->FmtChans;
2055 break;
2057 case ALC_FORMAT_TYPE_SOFT:
2058 if(!device->IsLoopbackDevice)
2059 alcSetError(device, ALC_INVALID_DEVICE);
2060 else
2061 *data = device->FmtType;
2062 break;
2064 case ALC_MONO_SOURCES:
2065 *data = device->NumMonoSources;
2066 break;
2068 case ALC_STEREO_SOURCES:
2069 *data = device->NumStereoSources;
2070 break;
2072 case ALC_MAX_AUXILIARY_SENDS:
2073 *data = device->NumAuxSends;
2074 break;
2076 case ALC_CONNECTED:
2077 *data = device->Connected;
2078 break;
2080 default:
2081 alcSetError(device, ALC_INVALID_ENUM);
2082 break;
2085 UnlockLists();
2090 alcIsExtensionPresent
2092 Determines if there is support for a particular extension
2094 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2096 ALCboolean bResult = ALC_FALSE;
2097 const char *ptr;
2098 size_t len;
2100 if(!extName)
2102 alcSetError(device, ALC_INVALID_VALUE);
2103 return ALC_FALSE;
2106 len = strlen(extName);
2107 LockLists();
2108 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
2109 UnlockLists();
2110 while(ptr && *ptr)
2112 if(strncasecmp(ptr, extName, len) == 0 &&
2113 (ptr[len] == '\0' || isspace(ptr[len])))
2115 bResult = ALC_TRUE;
2116 break;
2118 if((ptr=strchr(ptr, ' ')) != NULL)
2120 do {
2121 ++ptr;
2122 } while(isspace(*ptr));
2126 return bResult;
2131 alcGetProcAddress
2133 Retrieves the function address for a particular extension function
2135 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2137 ALsizei i = 0;
2139 if(!funcName)
2141 alcSetError(device, ALC_INVALID_VALUE);
2142 return NULL;
2145 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
2146 i++;
2147 return alcFunctions[i].address;
2152 alcGetEnumValue
2154 Get the value for a particular ALC Enumerated Value
2156 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2158 ALsizei i = 0;
2160 if(!enumName)
2162 alcSetError(device, ALC_INVALID_VALUE);
2163 return (ALCenum)0;
2166 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
2167 i++;
2168 return enumeration[i].value;
2173 alcCreateContext
2175 Create and attach a Context to a particular Device.
2177 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2179 ALCcontext *ALContext;
2180 void *temp;
2182 LockLists();
2183 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
2185 alcSetError(device, ALC_INVALID_DEVICE);
2186 UnlockLists();
2187 return NULL;
2190 // Reset Context Last Error code
2191 device->LastError = ALC_NO_ERROR;
2193 if(UpdateDeviceParams(device, attrList) == ALC_FALSE)
2195 alcSetError(device, ALC_INVALID_DEVICE);
2196 aluHandleDisconnect(device);
2197 UnlockLists();
2198 return NULL;
2201 LockDevice(device);
2202 ALContext = NULL;
2203 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
2204 if(temp)
2206 device->Contexts = temp;
2208 ALContext = calloc(1, sizeof(ALCcontext));
2209 if(ALContext)
2211 ALContext->MaxActiveSources = 256;
2212 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2213 ALContext->MaxActiveSources);
2216 if(!ALContext || !ALContext->ActiveSources)
2218 free(ALContext);
2219 alcSetError(device, ALC_OUT_OF_MEMORY);
2220 UnlockDevice(device);
2221 if(device->NumContexts == 0)
2223 ALCdevice_StopPlayback(device);
2224 device->Flags &= ~DEVICE_RUNNING;
2226 UnlockLists();
2227 return NULL;
2230 device->Contexts[device->NumContexts++] = ALContext;
2231 ALContext->Device = device;
2233 InitContext(ALContext);
2234 UnlockDevice(device);
2236 ALContext->next = g_pContextList;
2237 g_pContextList = ALContext;
2238 g_ulContextCount++;
2240 UnlockLists();
2242 return ALContext;
2247 alcDestroyContext
2249 Remove a Context
2251 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2253 ALCdevice *Device;
2254 ALCcontext **list;
2255 ALuint i;
2257 LockLists();
2258 list = &g_pContextList;
2259 while(*list && *list != context)
2260 list = &(*list)->next;
2262 if(!*list)
2264 alcSetError(NULL, ALC_INVALID_CONTEXT);
2265 UnlockLists();
2266 return;
2269 *list = (*list)->next;
2270 g_ulContextCount--;
2272 if(context == tls_get(LocalContext))
2273 tls_set(LocalContext, NULL);
2274 if(context == GlobalContext)
2275 GlobalContext = NULL;
2277 Device = context->Device;
2278 LockDevice(Device);
2279 for(i = 0;i < Device->NumContexts;i++)
2281 if(Device->Contexts[i] == context)
2283 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];
2284 Device->NumContexts--;
2285 break;
2288 UnlockDevice(Device);
2290 if(Device->NumContexts == 0)
2292 ALCdevice_StopPlayback(Device);
2293 Device->Flags &= ~DEVICE_RUNNING;
2295 UnlockLists();
2297 if(context->SourceMap.size > 0)
2299 ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);
2300 ReleaseALSources(context);
2302 ResetUIntMap(&context->SourceMap);
2304 if(context->EffectSlotMap.size > 0)
2306 ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);
2307 ReleaseALAuxiliaryEffectSlots(context);
2309 ResetUIntMap(&context->EffectSlotMap);
2311 free(context->ActiveSources);
2312 context->ActiveSources = NULL;
2313 context->MaxActiveSources = 0;
2314 context->ActiveSourceCount = 0;
2316 ExitContext(context);
2318 memset(context, 0, sizeof(ALCcontext));
2319 free(context);
2324 alcGetCurrentContext
2326 Returns the currently active Context
2328 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
2330 ALCcontext *Context;
2332 LockLists();
2333 Context = tls_get(LocalContext);
2334 if(Context && !IsContext(Context))
2336 tls_set(LocalContext, NULL);
2337 Context = NULL;
2339 if(!Context)
2340 Context = GlobalContext;
2341 UnlockLists();
2343 return Context;
2347 alcGetThreadContext
2349 Returns the currently active thread-local Context
2351 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2353 ALCcontext *pContext = NULL;
2355 LockLists();
2357 pContext = tls_get(LocalContext);
2358 if(pContext && !IsContext(pContext))
2360 tls_set(LocalContext, NULL);
2361 pContext = NULL;
2364 UnlockLists();
2366 return pContext;
2371 alcGetContextsDevice
2373 Returns the Device that a particular Context is attached to
2375 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)
2377 ALCdevice *pDevice = NULL;
2379 LockLists();
2380 if(IsContext(pContext))
2381 pDevice = pContext->Device;
2382 else
2383 alcSetError(NULL, ALC_INVALID_CONTEXT);
2384 UnlockLists();
2386 return pDevice;
2391 alcMakeContextCurrent
2393 Makes the given Context the active Context
2395 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2397 ALboolean bReturn = AL_TRUE;
2399 LockLists();
2401 // context must be a valid Context or NULL
2402 if(context == NULL || IsContext(context))
2404 GlobalContext = context;
2405 tls_set(LocalContext, NULL);
2407 else
2409 alcSetError(NULL, ALC_INVALID_CONTEXT);
2410 bReturn = AL_FALSE;
2413 UnlockLists();
2415 return bReturn;
2419 alcSetThreadContext
2421 Makes the given Context the active Context for the current thread
2423 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2425 ALboolean bReturn = AL_TRUE;
2427 LockLists();
2429 // context must be a valid Context or NULL
2430 if(context == NULL || IsContext(context))
2431 tls_set(LocalContext, context);
2432 else
2434 alcSetError(NULL, ALC_INVALID_CONTEXT);
2435 bReturn = AL_FALSE;
2438 UnlockLists();
2440 return bReturn;
2444 // Sets the default channel order used by most non-WaveFormatEx-based APIs
2445 void SetDefaultChannelOrder(ALCdevice *device)
2447 switch(device->FmtChans)
2449 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
2450 device->DevChannels[1] = FRONT_RIGHT;
2451 device->DevChannels[2] = BACK_LEFT;
2452 device->DevChannels[3] = BACK_RIGHT;
2453 device->DevChannels[4] = FRONT_CENTER;
2454 device->DevChannels[5] = LFE;
2455 return;
2457 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
2458 device->DevChannels[1] = FRONT_RIGHT;
2459 device->DevChannels[2] = BACK_LEFT;
2460 device->DevChannels[3] = BACK_RIGHT;
2461 device->DevChannels[4] = FRONT_CENTER;
2462 device->DevChannels[5] = LFE;
2463 device->DevChannels[6] = SIDE_LEFT;
2464 device->DevChannels[7] = SIDE_RIGHT;
2465 return;
2467 /* Same as WFX order */
2468 case DevFmtMono:
2469 case DevFmtStereo:
2470 case DevFmtQuad:
2471 case DevFmtX51Side:
2472 case DevFmtX61:
2473 break;
2475 SetDefaultWFXChannelOrder(device);
2477 // Sets the default order used by WaveFormatEx
2478 void SetDefaultWFXChannelOrder(ALCdevice *device)
2480 switch(device->FmtChans)
2482 case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
2484 case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
2485 device->DevChannels[1] = FRONT_RIGHT; break;
2487 case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
2488 device->DevChannels[1] = FRONT_RIGHT;
2489 device->DevChannels[2] = BACK_LEFT;
2490 device->DevChannels[3] = BACK_RIGHT; break;
2492 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
2493 device->DevChannels[1] = FRONT_RIGHT;
2494 device->DevChannels[2] = FRONT_CENTER;
2495 device->DevChannels[3] = LFE;
2496 device->DevChannels[4] = BACK_LEFT;
2497 device->DevChannels[5] = BACK_RIGHT; break;
2499 case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
2500 device->DevChannels[1] = FRONT_RIGHT;
2501 device->DevChannels[2] = FRONT_CENTER;
2502 device->DevChannels[3] = LFE;
2503 device->DevChannels[4] = SIDE_LEFT;
2504 device->DevChannels[5] = SIDE_RIGHT; break;
2506 case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
2507 device->DevChannels[1] = FRONT_RIGHT;
2508 device->DevChannels[2] = FRONT_CENTER;
2509 device->DevChannels[3] = LFE;
2510 device->DevChannels[4] = BACK_CENTER;
2511 device->DevChannels[5] = SIDE_LEFT;
2512 device->DevChannels[6] = SIDE_RIGHT; break;
2514 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
2515 device->DevChannels[1] = FRONT_RIGHT;
2516 device->DevChannels[2] = FRONT_CENTER;
2517 device->DevChannels[3] = LFE;
2518 device->DevChannels[4] = BACK_LEFT;
2519 device->DevChannels[5] = BACK_RIGHT;
2520 device->DevChannels[6] = SIDE_LEFT;
2521 device->DevChannels[7] = SIDE_RIGHT; break;
2525 static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)
2527 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)
2529 *chans = DevFmtMono;
2530 *type = DevFmtFloat;
2531 return;
2533 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0)
2535 *chans = DevFmtStereo;
2536 *type = DevFmtFloat;
2537 return;
2539 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0)
2541 *chans = DevFmtQuad;
2542 *type = DevFmtFloat;
2543 return;
2545 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0)
2547 *chans = DevFmtX51;
2548 *type = DevFmtFloat;
2549 return;
2551 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0)
2553 *chans = DevFmtX61;
2554 *type = DevFmtFloat;
2555 return;
2557 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0)
2559 *chans = DevFmtX71;
2560 *type = DevFmtFloat;
2561 return;
2564 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0)
2566 *chans = DevFmtMono;
2567 *type = DevFmtShort;
2568 return;
2570 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0)
2572 *chans = DevFmtStereo;
2573 *type = DevFmtShort;
2574 return;
2576 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0)
2578 *chans = DevFmtQuad;
2579 *type = DevFmtShort;
2580 return;
2582 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0)
2584 *chans = DevFmtX51;
2585 *type = DevFmtShort;
2586 return;
2588 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0)
2590 *chans = DevFmtX61;
2591 *type = DevFmtShort;
2592 return;
2594 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0)
2596 *chans = DevFmtX71;
2597 *type = DevFmtShort;
2598 return;
2601 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0)
2603 *chans = DevFmtMono;
2604 *type = DevFmtByte;
2605 return;
2607 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0)
2609 *chans = DevFmtStereo;
2610 *type = DevFmtByte;
2611 return;
2613 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0)
2615 *chans = DevFmtQuad;
2616 *type = DevFmtByte;
2617 return;
2619 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0)
2621 *chans = DevFmtX51;
2622 *type = DevFmtByte;
2623 return;
2625 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0)
2627 *chans = DevFmtX61;
2628 *type = DevFmtByte;
2629 return;
2631 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0)
2633 *chans = DevFmtX71;
2634 *type = DevFmtByte;
2635 return;
2638 ERR("Unknown format: \"%s\"\n", str);
2639 *chans = DevFmtStereo;
2640 *type = DevFmtShort;
2644 alcOpenDevice
2646 Open the Device specified.
2648 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2650 ALboolean bDeviceFound = AL_FALSE;
2651 const ALCchar *fmt;
2652 ALCdevice *device;
2653 ALint i;
2655 DO_INITCONFIG();
2657 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2658 deviceName = NULL;
2660 device = calloc(1, sizeof(ALCdevice));
2661 if(!device)
2663 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2664 return NULL;
2667 //Validate device
2668 device->Connected = ALC_TRUE;
2669 device->IsCaptureDevice = AL_FALSE;
2670 device->IsLoopbackDevice = AL_FALSE;
2671 InitializeCriticalSection(&device->Mutex);
2672 device->LastError = ALC_NO_ERROR;
2674 device->Flags = 0;
2675 device->Bs2b = NULL;
2676 device->szDeviceName = NULL;
2678 device->Contexts = NULL;
2679 device->NumContexts = 0;
2681 InitUIntMap(&device->BufferMap);
2682 InitUIntMap(&device->EffectMap);
2683 InitUIntMap(&device->FilterMap);
2685 //Set output format
2686 if(ConfigValueExists(NULL, "frequency"))
2687 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2688 device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE);
2689 if(device->Frequency < 8000)
2690 device->Frequency = 8000;
2692 if(ConfigValueExists(NULL, "format"))
2693 device->Flags |= DEVICE_CHANNELS_REQUEST;
2694 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
2695 GetFormatFromString(fmt, &device->FmtChans, &device->FmtType);
2697 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
2698 if(device->NumUpdates < 2)
2699 device->NumUpdates = 4;
2701 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);
2702 if(device->UpdateSize <= 0)
2703 device->UpdateSize = 1024;
2705 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
2706 if(device->MaxNoOfSources <= 0)
2707 device->MaxNoOfSources = 256;
2709 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
2710 if(device->AuxiliaryEffectSlotMax <= 0)
2711 device->AuxiliaryEffectSlotMax = 4;
2713 device->NumStereoSources = 1;
2714 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2716 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
2717 if(device->NumAuxSends > MAX_SENDS)
2718 device->NumAuxSends = MAX_SENDS;
2720 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
2722 // Find a playback device to open
2723 LockLists();
2724 for(i = 0;BackendList[i].Init;i++)
2726 device->Funcs = &BackendList[i].Funcs;
2727 if(ALCdevice_OpenPlayback(device, deviceName))
2729 device->next = g_pDeviceList;
2730 g_pDeviceList = device;
2731 g_ulDeviceCount++;
2733 bDeviceFound = AL_TRUE;
2734 break;
2737 UnlockLists();
2739 if(!bDeviceFound)
2741 // No suitable output device found
2742 alcSetError(NULL, ALC_INVALID_VALUE);
2743 free(device);
2744 device = NULL;
2747 return device;
2752 alcCloseDevice
2754 Close the specified Device
2756 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
2758 ALCdevice **list;
2760 LockLists();
2761 list = &g_pDeviceList;
2762 while(*list && *list != pDevice)
2763 list = &(*list)->next;
2765 if(!*list || (*list)->IsCaptureDevice)
2767 alcSetError(*list, ALC_INVALID_DEVICE);
2768 UnlockLists();
2769 return ALC_FALSE;
2772 *list = (*list)->next;
2773 g_ulDeviceCount--;
2775 UnlockLists();
2777 if(pDevice->NumContexts > 0)
2779 WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
2780 while(pDevice->NumContexts > 0)
2781 alcDestroyContext(pDevice->Contexts[0]);
2783 ALCdevice_ClosePlayback(pDevice);
2785 if(pDevice->BufferMap.size > 0)
2787 WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);
2788 ReleaseALBuffers(pDevice);
2790 ResetUIntMap(&pDevice->BufferMap);
2792 if(pDevice->EffectMap.size > 0)
2794 WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);
2795 ReleaseALEffects(pDevice);
2797 ResetUIntMap(&pDevice->EffectMap);
2799 if(pDevice->FilterMap.size > 0)
2801 WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);
2802 ReleaseALFilters(pDevice);
2804 ResetUIntMap(&pDevice->FilterMap);
2806 free(pDevice->Bs2b);
2807 pDevice->Bs2b = NULL;
2809 free(pDevice->szDeviceName);
2810 pDevice->szDeviceName = NULL;
2812 free(pDevice->Contexts);
2813 pDevice->Contexts = NULL;
2815 DeleteCriticalSection(&pDevice->Mutex);
2817 //Release device structure
2818 memset(pDevice, 0, sizeof(ALCdevice));
2819 free(pDevice);
2821 return ALC_TRUE;
2825 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void)
2827 ALCdevice *device;
2829 DO_INITCONFIG();
2831 device = calloc(1, sizeof(ALCdevice));
2832 if(!device)
2834 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2835 return NULL;
2838 //Validate device
2839 device->Connected = ALC_TRUE;
2840 device->IsCaptureDevice = AL_FALSE;
2841 device->IsLoopbackDevice = AL_TRUE;
2842 InitializeCriticalSection(&device->Mutex);
2843 device->LastError = ALC_NO_ERROR;
2845 device->Flags = 0;
2846 device->Bs2b = NULL;
2847 device->szDeviceName = NULL;
2849 device->Contexts = NULL;
2850 device->NumContexts = 0;
2852 InitUIntMap(&device->BufferMap);
2853 InitUIntMap(&device->EffectMap);
2854 InitUIntMap(&device->FilterMap);
2856 //Set output format
2857 device->Frequency = 44100;
2858 device->FmtChans = DevFmtStereo;
2859 device->FmtType = DevFmtShort;
2861 device->NumUpdates = 0;
2862 device->UpdateSize = 0;
2864 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
2865 if(device->MaxNoOfSources <= 0)
2866 device->MaxNoOfSources = 256;
2868 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
2869 if(device->AuxiliaryEffectSlotMax <= 0)
2870 device->AuxiliaryEffectSlotMax = 4;
2872 device->NumStereoSources = 1;
2873 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2875 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
2876 if(device->NumAuxSends > MAX_SENDS)
2877 device->NumAuxSends = MAX_SENDS;
2879 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
2881 // Open the "backend"
2882 LockLists();
2883 device->Funcs = &BackendLoopback.Funcs;
2884 ALCdevice_OpenPlayback(device, "Loopback");
2886 device->next = g_pDeviceList;
2887 g_pDeviceList = device;
2888 g_ulDeviceCount++;
2889 UnlockLists();
2891 return device;
2894 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
2896 ALCboolean ret = ALC_FALSE;
2898 LockLists();
2899 if(!IsDevice(device) || !device->IsLoopbackDevice)
2900 alcSetError(device, ALC_INVALID_DEVICE);
2901 else if(freq <= 0)
2902 alcSetError(device, ALC_INVALID_VALUE);
2903 else if(!IsValidALCType(type) || !IsValidALCChannels(channels))
2904 alcSetError(device, ALC_INVALID_ENUM);
2905 else
2907 if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 &&
2908 freq >= 8000)
2909 ret = ALC_TRUE;
2911 UnlockLists();
2913 return ret;
2916 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
2918 LockLists();
2919 if(!IsDevice(device) || !device->IsLoopbackDevice)
2920 alcSetError(device, ALC_INVALID_DEVICE);
2921 else if(samples < 0)
2922 alcSetError(device, ALC_INVALID_VALUE);
2923 else
2924 aluMixData(device, buffer, samples);
2925 UnlockLists();
2929 static void ReleaseALC(void)
2931 free(alcDeviceList); alcDeviceList = NULL;
2932 alcDeviceListSize = 0;
2933 free(alcAllDeviceList); alcAllDeviceList = NULL;
2934 alcAllDeviceListSize = 0;
2935 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
2936 alcCaptureDeviceListSize = 0;
2938 free(alcDefaultDeviceSpecifier);
2939 alcDefaultDeviceSpecifier = NULL;
2940 free(alcDefaultAllDeviceSpecifier);
2941 alcDefaultAllDeviceSpecifier = NULL;
2942 free(alcCaptureDefaultDeviceSpecifier);
2943 alcCaptureDefaultDeviceSpecifier = NULL;
2945 if(g_ulDeviceCount > 0)
2946 WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
2948 while(g_pDeviceList)
2950 if(g_pDeviceList->IsCaptureDevice)
2951 alcCaptureCloseDevice(g_pDeviceList);
2952 else
2953 alcCloseDevice(g_pDeviceList);
2957 ///////////////////////////////////////////////////////