Add 'restrict' to another parameter
[openal-soft.git] / Alc / ALc.c
blobdbda46f1f0626aa8761fabe10e1bd2ec428eb0ca
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "bformatdec.h"
39 #include "alu.h"
41 #include "compat.h"
42 #include "threads.h"
43 #include "alstring.h"
44 #include "almalloc.h"
46 #include "backends/base.h"
49 /************************************************
50 * Backends
51 ************************************************/
52 struct BackendInfo {
53 const char *name;
54 ALCbackendFactory* (*getFactory)(void);
55 ALCboolean (*Init)(BackendFuncs*);
56 void (*Deinit)(void);
57 void (*Probe)(enum DevProbe);
58 BackendFuncs Funcs;
61 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
62 static struct BackendInfo BackendList[] = {
63 #ifdef HAVE_JACK
64 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
68 #endif
69 #ifdef HAVE_ALSA
70 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
71 #endif
72 #ifdef HAVE_COREAUDIO
73 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_OSS
76 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
77 #endif
78 #ifdef HAVE_SOLARIS
79 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
80 #endif
81 #ifdef HAVE_SNDIO
82 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
83 #endif
84 #ifdef HAVE_QSA
85 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
86 #endif
87 #ifdef HAVE_MMDEVAPI
88 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
89 #endif
90 #ifdef HAVE_DSOUND
91 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
92 #endif
93 #ifdef HAVE_WINMM
94 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
95 #endif
96 #ifdef HAVE_PORTAUDIO
97 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
98 #endif
99 #ifdef HAVE_OPENSL
100 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
101 #endif
103 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #ifdef HAVE_WAVE
105 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #endif
108 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
110 #undef EmptyFuncs
112 static struct BackendInfo PlaybackBackend;
113 static struct BackendInfo CaptureBackend;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 typedef struct ALCfunction {
120 const ALCchar *funcName;
121 ALCvoid *address;
122 } ALCfunction;
124 typedef struct ALCenums {
125 const ALCchar *enumName;
126 ALCenum value;
127 } ALCenums;
129 #define DECL(x) { #x, (ALCvoid*)(x) }
130 static const ALCfunction alcFunctions[] = {
131 DECL(alcCreateContext),
132 DECL(alcMakeContextCurrent),
133 DECL(alcProcessContext),
134 DECL(alcSuspendContext),
135 DECL(alcDestroyContext),
136 DECL(alcGetCurrentContext),
137 DECL(alcGetContextsDevice),
138 DECL(alcOpenDevice),
139 DECL(alcCloseDevice),
140 DECL(alcGetError),
141 DECL(alcIsExtensionPresent),
142 DECL(alcGetProcAddress),
143 DECL(alcGetEnumValue),
144 DECL(alcGetString),
145 DECL(alcGetIntegerv),
146 DECL(alcCaptureOpenDevice),
147 DECL(alcCaptureCloseDevice),
148 DECL(alcCaptureStart),
149 DECL(alcCaptureStop),
150 DECL(alcCaptureSamples),
152 DECL(alcSetThreadContext),
153 DECL(alcGetThreadContext),
155 DECL(alcLoopbackOpenDeviceSOFT),
156 DECL(alcIsRenderFormatSupportedSOFT),
157 DECL(alcRenderSamplesSOFT),
159 DECL(alcDevicePauseSOFT),
160 DECL(alcDeviceResumeSOFT),
162 DECL(alcGetStringiSOFT),
163 DECL(alcResetDeviceSOFT),
165 DECL(alcGetInteger64vSOFT),
167 DECL(alEnable),
168 DECL(alDisable),
169 DECL(alIsEnabled),
170 DECL(alGetString),
171 DECL(alGetBooleanv),
172 DECL(alGetIntegerv),
173 DECL(alGetFloatv),
174 DECL(alGetDoublev),
175 DECL(alGetBoolean),
176 DECL(alGetInteger),
177 DECL(alGetFloat),
178 DECL(alGetDouble),
179 DECL(alGetError),
180 DECL(alIsExtensionPresent),
181 DECL(alGetProcAddress),
182 DECL(alGetEnumValue),
183 DECL(alListenerf),
184 DECL(alListener3f),
185 DECL(alListenerfv),
186 DECL(alListeneri),
187 DECL(alListener3i),
188 DECL(alListeneriv),
189 DECL(alGetListenerf),
190 DECL(alGetListener3f),
191 DECL(alGetListenerfv),
192 DECL(alGetListeneri),
193 DECL(alGetListener3i),
194 DECL(alGetListeneriv),
195 DECL(alGenSources),
196 DECL(alDeleteSources),
197 DECL(alIsSource),
198 DECL(alSourcef),
199 DECL(alSource3f),
200 DECL(alSourcefv),
201 DECL(alSourcei),
202 DECL(alSource3i),
203 DECL(alSourceiv),
204 DECL(alGetSourcef),
205 DECL(alGetSource3f),
206 DECL(alGetSourcefv),
207 DECL(alGetSourcei),
208 DECL(alGetSource3i),
209 DECL(alGetSourceiv),
210 DECL(alSourcePlayv),
211 DECL(alSourceStopv),
212 DECL(alSourceRewindv),
213 DECL(alSourcePausev),
214 DECL(alSourcePlay),
215 DECL(alSourceStop),
216 DECL(alSourceRewind),
217 DECL(alSourcePause),
218 DECL(alSourceQueueBuffers),
219 DECL(alSourceUnqueueBuffers),
220 DECL(alGenBuffers),
221 DECL(alDeleteBuffers),
222 DECL(alIsBuffer),
223 DECL(alBufferData),
224 DECL(alBufferf),
225 DECL(alBuffer3f),
226 DECL(alBufferfv),
227 DECL(alBufferi),
228 DECL(alBuffer3i),
229 DECL(alBufferiv),
230 DECL(alGetBufferf),
231 DECL(alGetBuffer3f),
232 DECL(alGetBufferfv),
233 DECL(alGetBufferi),
234 DECL(alGetBuffer3i),
235 DECL(alGetBufferiv),
236 DECL(alDopplerFactor),
237 DECL(alDopplerVelocity),
238 DECL(alSpeedOfSound),
239 DECL(alDistanceModel),
241 DECL(alGenFilters),
242 DECL(alDeleteFilters),
243 DECL(alIsFilter),
244 DECL(alFilteri),
245 DECL(alFilteriv),
246 DECL(alFilterf),
247 DECL(alFilterfv),
248 DECL(alGetFilteri),
249 DECL(alGetFilteriv),
250 DECL(alGetFilterf),
251 DECL(alGetFilterfv),
252 DECL(alGenEffects),
253 DECL(alDeleteEffects),
254 DECL(alIsEffect),
255 DECL(alEffecti),
256 DECL(alEffectiv),
257 DECL(alEffectf),
258 DECL(alEffectfv),
259 DECL(alGetEffecti),
260 DECL(alGetEffectiv),
261 DECL(alGetEffectf),
262 DECL(alGetEffectfv),
263 DECL(alGenAuxiliaryEffectSlots),
264 DECL(alDeleteAuxiliaryEffectSlots),
265 DECL(alIsAuxiliaryEffectSlot),
266 DECL(alAuxiliaryEffectSloti),
267 DECL(alAuxiliaryEffectSlotiv),
268 DECL(alAuxiliaryEffectSlotf),
269 DECL(alAuxiliaryEffectSlotfv),
270 DECL(alGetAuxiliaryEffectSloti),
271 DECL(alGetAuxiliaryEffectSlotiv),
272 DECL(alGetAuxiliaryEffectSlotf),
273 DECL(alGetAuxiliaryEffectSlotfv),
275 DECL(alDeferUpdatesSOFT),
276 DECL(alProcessUpdatesSOFT),
278 DECL(alSourcedSOFT),
279 DECL(alSource3dSOFT),
280 DECL(alSourcedvSOFT),
281 DECL(alGetSourcedSOFT),
282 DECL(alGetSource3dSOFT),
283 DECL(alGetSourcedvSOFT),
284 DECL(alSourcei64SOFT),
285 DECL(alSource3i64SOFT),
286 DECL(alSourcei64vSOFT),
287 DECL(alGetSourcei64SOFT),
288 DECL(alGetSource3i64SOFT),
289 DECL(alGetSourcei64vSOFT),
291 DECL(alBufferSamplesSOFT),
292 DECL(alGetBufferSamplesSOFT),
293 DECL(alIsBufferFormatSupportedSOFT),
295 { NULL, NULL }
297 #undef DECL
299 #define DECL(x) { #x, (x) }
300 static const ALCenums enumeration[] = {
301 DECL(ALC_INVALID),
302 DECL(ALC_FALSE),
303 DECL(ALC_TRUE),
305 DECL(ALC_MAJOR_VERSION),
306 DECL(ALC_MINOR_VERSION),
307 DECL(ALC_ATTRIBUTES_SIZE),
308 DECL(ALC_ALL_ATTRIBUTES),
309 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
310 DECL(ALC_DEVICE_SPECIFIER),
311 DECL(ALC_ALL_DEVICES_SPECIFIER),
312 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
313 DECL(ALC_EXTENSIONS),
314 DECL(ALC_FREQUENCY),
315 DECL(ALC_REFRESH),
316 DECL(ALC_SYNC),
317 DECL(ALC_MONO_SOURCES),
318 DECL(ALC_STEREO_SOURCES),
319 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
320 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
321 DECL(ALC_CAPTURE_SAMPLES),
322 DECL(ALC_CONNECTED),
324 DECL(ALC_EFX_MAJOR_VERSION),
325 DECL(ALC_EFX_MINOR_VERSION),
326 DECL(ALC_MAX_AUXILIARY_SENDS),
328 DECL(ALC_FORMAT_CHANNELS_SOFT),
329 DECL(ALC_FORMAT_TYPE_SOFT),
331 DECL(ALC_MONO_SOFT),
332 DECL(ALC_STEREO_SOFT),
333 DECL(ALC_QUAD_SOFT),
334 DECL(ALC_5POINT1_SOFT),
335 DECL(ALC_6POINT1_SOFT),
336 DECL(ALC_7POINT1_SOFT),
338 DECL(ALC_BYTE_SOFT),
339 DECL(ALC_UNSIGNED_BYTE_SOFT),
340 DECL(ALC_SHORT_SOFT),
341 DECL(ALC_UNSIGNED_SHORT_SOFT),
342 DECL(ALC_INT_SOFT),
343 DECL(ALC_UNSIGNED_INT_SOFT),
344 DECL(ALC_FLOAT_SOFT),
346 DECL(ALC_HRTF_SOFT),
347 DECL(ALC_DONT_CARE_SOFT),
348 DECL(ALC_HRTF_STATUS_SOFT),
349 DECL(ALC_HRTF_DISABLED_SOFT),
350 DECL(ALC_HRTF_ENABLED_SOFT),
351 DECL(ALC_HRTF_DENIED_SOFT),
352 DECL(ALC_HRTF_REQUIRED_SOFT),
353 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
354 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
355 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
356 DECL(ALC_HRTF_SPECIFIER_SOFT),
357 DECL(ALC_HRTF_ID_SOFT),
359 DECL(ALC_NO_ERROR),
360 DECL(ALC_INVALID_DEVICE),
361 DECL(ALC_INVALID_CONTEXT),
362 DECL(ALC_INVALID_ENUM),
363 DECL(ALC_INVALID_VALUE),
364 DECL(ALC_OUT_OF_MEMORY),
367 DECL(AL_INVALID),
368 DECL(AL_NONE),
369 DECL(AL_FALSE),
370 DECL(AL_TRUE),
372 DECL(AL_SOURCE_RELATIVE),
373 DECL(AL_CONE_INNER_ANGLE),
374 DECL(AL_CONE_OUTER_ANGLE),
375 DECL(AL_PITCH),
376 DECL(AL_POSITION),
377 DECL(AL_DIRECTION),
378 DECL(AL_VELOCITY),
379 DECL(AL_LOOPING),
380 DECL(AL_BUFFER),
381 DECL(AL_GAIN),
382 DECL(AL_MIN_GAIN),
383 DECL(AL_MAX_GAIN),
384 DECL(AL_ORIENTATION),
385 DECL(AL_REFERENCE_DISTANCE),
386 DECL(AL_ROLLOFF_FACTOR),
387 DECL(AL_CONE_OUTER_GAIN),
388 DECL(AL_MAX_DISTANCE),
389 DECL(AL_SEC_OFFSET),
390 DECL(AL_SAMPLE_OFFSET),
391 DECL(AL_BYTE_OFFSET),
392 DECL(AL_SOURCE_TYPE),
393 DECL(AL_STATIC),
394 DECL(AL_STREAMING),
395 DECL(AL_UNDETERMINED),
396 DECL(AL_METERS_PER_UNIT),
397 DECL(AL_LOOP_POINTS_SOFT),
398 DECL(AL_DIRECT_CHANNELS_SOFT),
400 DECL(AL_DIRECT_FILTER),
401 DECL(AL_AUXILIARY_SEND_FILTER),
402 DECL(AL_AIR_ABSORPTION_FACTOR),
403 DECL(AL_ROOM_ROLLOFF_FACTOR),
404 DECL(AL_CONE_OUTER_GAINHF),
405 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
406 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
407 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
409 DECL(AL_SOURCE_STATE),
410 DECL(AL_INITIAL),
411 DECL(AL_PLAYING),
412 DECL(AL_PAUSED),
413 DECL(AL_STOPPED),
415 DECL(AL_BUFFERS_QUEUED),
416 DECL(AL_BUFFERS_PROCESSED),
418 DECL(AL_FORMAT_MONO8),
419 DECL(AL_FORMAT_MONO16),
420 DECL(AL_FORMAT_MONO_FLOAT32),
421 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
422 DECL(AL_FORMAT_STEREO8),
423 DECL(AL_FORMAT_STEREO16),
424 DECL(AL_FORMAT_STEREO_FLOAT32),
425 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
426 DECL(AL_FORMAT_MONO_IMA4),
427 DECL(AL_FORMAT_STEREO_IMA4),
428 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
429 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
430 DECL(AL_FORMAT_QUAD8_LOKI),
431 DECL(AL_FORMAT_QUAD16_LOKI),
432 DECL(AL_FORMAT_QUAD8),
433 DECL(AL_FORMAT_QUAD16),
434 DECL(AL_FORMAT_QUAD32),
435 DECL(AL_FORMAT_51CHN8),
436 DECL(AL_FORMAT_51CHN16),
437 DECL(AL_FORMAT_51CHN32),
438 DECL(AL_FORMAT_61CHN8),
439 DECL(AL_FORMAT_61CHN16),
440 DECL(AL_FORMAT_61CHN32),
441 DECL(AL_FORMAT_71CHN8),
442 DECL(AL_FORMAT_71CHN16),
443 DECL(AL_FORMAT_71CHN32),
444 DECL(AL_FORMAT_REAR8),
445 DECL(AL_FORMAT_REAR16),
446 DECL(AL_FORMAT_REAR32),
447 DECL(AL_FORMAT_MONO_MULAW),
448 DECL(AL_FORMAT_MONO_MULAW_EXT),
449 DECL(AL_FORMAT_STEREO_MULAW),
450 DECL(AL_FORMAT_STEREO_MULAW_EXT),
451 DECL(AL_FORMAT_QUAD_MULAW),
452 DECL(AL_FORMAT_51CHN_MULAW),
453 DECL(AL_FORMAT_61CHN_MULAW),
454 DECL(AL_FORMAT_71CHN_MULAW),
455 DECL(AL_FORMAT_REAR_MULAW),
456 DECL(AL_FORMAT_MONO_ALAW_EXT),
457 DECL(AL_FORMAT_STEREO_ALAW_EXT),
459 DECL(AL_FORMAT_BFORMAT2D_8),
460 DECL(AL_FORMAT_BFORMAT2D_16),
461 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
462 DECL(AL_FORMAT_BFORMAT2D_MULAW),
463 DECL(AL_FORMAT_BFORMAT3D_8),
464 DECL(AL_FORMAT_BFORMAT3D_16),
465 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
466 DECL(AL_FORMAT_BFORMAT3D_MULAW),
468 DECL(AL_MONO8_SOFT),
469 DECL(AL_MONO16_SOFT),
470 DECL(AL_MONO32F_SOFT),
471 DECL(AL_STEREO8_SOFT),
472 DECL(AL_STEREO16_SOFT),
473 DECL(AL_STEREO32F_SOFT),
474 DECL(AL_QUAD8_SOFT),
475 DECL(AL_QUAD16_SOFT),
476 DECL(AL_QUAD32F_SOFT),
477 DECL(AL_REAR8_SOFT),
478 DECL(AL_REAR16_SOFT),
479 DECL(AL_REAR32F_SOFT),
480 DECL(AL_5POINT1_8_SOFT),
481 DECL(AL_5POINT1_16_SOFT),
482 DECL(AL_5POINT1_32F_SOFT),
483 DECL(AL_6POINT1_8_SOFT),
484 DECL(AL_6POINT1_16_SOFT),
485 DECL(AL_6POINT1_32F_SOFT),
486 DECL(AL_7POINT1_8_SOFT),
487 DECL(AL_7POINT1_16_SOFT),
488 DECL(AL_7POINT1_32F_SOFT),
489 DECL(AL_BFORMAT2D_8_SOFT),
490 DECL(AL_BFORMAT2D_16_SOFT),
491 DECL(AL_BFORMAT2D_32F_SOFT),
492 DECL(AL_BFORMAT3D_8_SOFT),
493 DECL(AL_BFORMAT3D_16_SOFT),
494 DECL(AL_BFORMAT3D_32F_SOFT),
496 DECL(AL_MONO_SOFT),
497 DECL(AL_STEREO_SOFT),
498 DECL(AL_QUAD_SOFT),
499 DECL(AL_REAR_SOFT),
500 DECL(AL_5POINT1_SOFT),
501 DECL(AL_6POINT1_SOFT),
502 DECL(AL_7POINT1_SOFT),
503 DECL(AL_BFORMAT2D_SOFT),
504 DECL(AL_BFORMAT3D_SOFT),
506 DECL(AL_BYTE_SOFT),
507 DECL(AL_UNSIGNED_BYTE_SOFT),
508 DECL(AL_SHORT_SOFT),
509 DECL(AL_UNSIGNED_SHORT_SOFT),
510 DECL(AL_INT_SOFT),
511 DECL(AL_UNSIGNED_INT_SOFT),
512 DECL(AL_FLOAT_SOFT),
513 DECL(AL_DOUBLE_SOFT),
514 DECL(AL_BYTE3_SOFT),
515 DECL(AL_UNSIGNED_BYTE3_SOFT),
516 DECL(AL_MULAW_SOFT),
518 DECL(AL_FREQUENCY),
519 DECL(AL_BITS),
520 DECL(AL_CHANNELS),
521 DECL(AL_SIZE),
522 DECL(AL_INTERNAL_FORMAT_SOFT),
523 DECL(AL_BYTE_LENGTH_SOFT),
524 DECL(AL_SAMPLE_LENGTH_SOFT),
525 DECL(AL_SEC_LENGTH_SOFT),
526 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
527 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_SOURCE_RADIUS),
531 DECL(AL_STEREO_ANGLES),
533 DECL(AL_UNUSED),
534 DECL(AL_PENDING),
535 DECL(AL_PROCESSED),
537 DECL(AL_NO_ERROR),
538 DECL(AL_INVALID_NAME),
539 DECL(AL_INVALID_ENUM),
540 DECL(AL_INVALID_VALUE),
541 DECL(AL_INVALID_OPERATION),
542 DECL(AL_OUT_OF_MEMORY),
544 DECL(AL_VENDOR),
545 DECL(AL_VERSION),
546 DECL(AL_RENDERER),
547 DECL(AL_EXTENSIONS),
549 DECL(AL_DOPPLER_FACTOR),
550 DECL(AL_DOPPLER_VELOCITY),
551 DECL(AL_DISTANCE_MODEL),
552 DECL(AL_SPEED_OF_SOUND),
553 DECL(AL_SOURCE_DISTANCE_MODEL),
554 DECL(AL_DEFERRED_UPDATES_SOFT),
556 DECL(AL_INVERSE_DISTANCE),
557 DECL(AL_INVERSE_DISTANCE_CLAMPED),
558 DECL(AL_LINEAR_DISTANCE),
559 DECL(AL_LINEAR_DISTANCE_CLAMPED),
560 DECL(AL_EXPONENT_DISTANCE),
561 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
563 DECL(AL_FILTER_TYPE),
564 DECL(AL_FILTER_NULL),
565 DECL(AL_FILTER_LOWPASS),
566 DECL(AL_FILTER_HIGHPASS),
567 DECL(AL_FILTER_BANDPASS),
569 DECL(AL_LOWPASS_GAIN),
570 DECL(AL_LOWPASS_GAINHF),
572 DECL(AL_HIGHPASS_GAIN),
573 DECL(AL_HIGHPASS_GAINLF),
575 DECL(AL_BANDPASS_GAIN),
576 DECL(AL_BANDPASS_GAINHF),
577 DECL(AL_BANDPASS_GAINLF),
579 DECL(AL_EFFECT_TYPE),
580 DECL(AL_EFFECT_NULL),
581 DECL(AL_EFFECT_REVERB),
582 DECL(AL_EFFECT_EAXREVERB),
583 DECL(AL_EFFECT_CHORUS),
584 DECL(AL_EFFECT_DISTORTION),
585 DECL(AL_EFFECT_ECHO),
586 DECL(AL_EFFECT_FLANGER),
587 #if 0
588 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
589 DECL(AL_EFFECT_VOCAL_MORPHER),
590 DECL(AL_EFFECT_PITCH_SHIFTER),
591 #endif
592 DECL(AL_EFFECT_RING_MODULATOR),
593 #if 0
594 DECL(AL_EFFECT_AUTOWAH),
595 #endif
596 DECL(AL_EFFECT_COMPRESSOR),
597 DECL(AL_EFFECT_EQUALIZER),
598 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
599 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
601 DECL(AL_EAXREVERB_DENSITY),
602 DECL(AL_EAXREVERB_DIFFUSION),
603 DECL(AL_EAXREVERB_GAIN),
604 DECL(AL_EAXREVERB_GAINHF),
605 DECL(AL_EAXREVERB_GAINLF),
606 DECL(AL_EAXREVERB_DECAY_TIME),
607 DECL(AL_EAXREVERB_DECAY_HFRATIO),
608 DECL(AL_EAXREVERB_DECAY_LFRATIO),
609 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
610 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
611 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
612 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
613 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
614 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
615 DECL(AL_EAXREVERB_ECHO_TIME),
616 DECL(AL_EAXREVERB_ECHO_DEPTH),
617 DECL(AL_EAXREVERB_MODULATION_TIME),
618 DECL(AL_EAXREVERB_MODULATION_DEPTH),
619 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
620 DECL(AL_EAXREVERB_HFREFERENCE),
621 DECL(AL_EAXREVERB_LFREFERENCE),
622 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
623 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
625 DECL(AL_REVERB_DENSITY),
626 DECL(AL_REVERB_DIFFUSION),
627 DECL(AL_REVERB_GAIN),
628 DECL(AL_REVERB_GAINHF),
629 DECL(AL_REVERB_DECAY_TIME),
630 DECL(AL_REVERB_DECAY_HFRATIO),
631 DECL(AL_REVERB_REFLECTIONS_GAIN),
632 DECL(AL_REVERB_REFLECTIONS_DELAY),
633 DECL(AL_REVERB_LATE_REVERB_GAIN),
634 DECL(AL_REVERB_LATE_REVERB_DELAY),
635 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
636 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
637 DECL(AL_REVERB_DECAY_HFLIMIT),
639 DECL(AL_CHORUS_WAVEFORM),
640 DECL(AL_CHORUS_PHASE),
641 DECL(AL_CHORUS_RATE),
642 DECL(AL_CHORUS_DEPTH),
643 DECL(AL_CHORUS_FEEDBACK),
644 DECL(AL_CHORUS_DELAY),
646 DECL(AL_DISTORTION_EDGE),
647 DECL(AL_DISTORTION_GAIN),
648 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
649 DECL(AL_DISTORTION_EQCENTER),
650 DECL(AL_DISTORTION_EQBANDWIDTH),
652 DECL(AL_ECHO_DELAY),
653 DECL(AL_ECHO_LRDELAY),
654 DECL(AL_ECHO_DAMPING),
655 DECL(AL_ECHO_FEEDBACK),
656 DECL(AL_ECHO_SPREAD),
658 DECL(AL_FLANGER_WAVEFORM),
659 DECL(AL_FLANGER_PHASE),
660 DECL(AL_FLANGER_RATE),
661 DECL(AL_FLANGER_DEPTH),
662 DECL(AL_FLANGER_FEEDBACK),
663 DECL(AL_FLANGER_DELAY),
665 DECL(AL_RING_MODULATOR_FREQUENCY),
666 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
667 DECL(AL_RING_MODULATOR_WAVEFORM),
669 DECL(AL_COMPRESSOR_ONOFF),
671 DECL(AL_EQUALIZER_LOW_GAIN),
672 DECL(AL_EQUALIZER_LOW_CUTOFF),
673 DECL(AL_EQUALIZER_MID1_GAIN),
674 DECL(AL_EQUALIZER_MID1_CENTER),
675 DECL(AL_EQUALIZER_MID1_WIDTH),
676 DECL(AL_EQUALIZER_MID2_GAIN),
677 DECL(AL_EQUALIZER_MID2_CENTER),
678 DECL(AL_EQUALIZER_MID2_WIDTH),
679 DECL(AL_EQUALIZER_HIGH_GAIN),
680 DECL(AL_EQUALIZER_HIGH_CUTOFF),
682 DECL(AL_DEDICATED_GAIN),
684 { NULL, (ALCenum)0 }
686 #undef DECL
688 static const ALCchar alcNoError[] = "No Error";
689 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
690 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
691 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
692 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
693 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
696 /************************************************
697 * Global variables
698 ************************************************/
700 /* Enumerated device names */
701 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
703 static al_string alcAllDevicesList;
704 static al_string alcCaptureDeviceList;
706 /* Default is always the first in the list */
707 static ALCchar *alcDefaultAllDevicesSpecifier;
708 static ALCchar *alcCaptureDefaultDeviceSpecifier;
710 /* Default context extensions */
711 static const ALchar alExtList[] =
712 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
713 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
714 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
715 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
716 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
717 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
718 "AL_SOFT_source_latency AL_SOFT_source_length";
720 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
722 /* Thread-local current context */
723 static altss_t LocalContext;
724 /* Process-wide current context */
725 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
727 /* Mixing thread piority level */
728 ALint RTPrioLevel;
730 FILE *LogFile;
731 #ifdef _DEBUG
732 enum LogLevel LogLevel = LogWarning;
733 #else
734 enum LogLevel LogLevel = LogError;
735 #endif
737 /* Flag to trap ALC device errors */
738 static ALCboolean TrapALCError = ALC_FALSE;
740 /* One-time configuration init control */
741 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
743 /* Default effect that applies to sources that don't have an effect on send 0 */
744 static ALeffect DefaultEffect;
746 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
747 * updates.
749 static ALCboolean SuspendDefers = ALC_TRUE;
752 /************************************************
753 * ALC information
754 ************************************************/
755 static const ALCchar alcNoDeviceExtList[] =
756 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
757 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
758 static const ALCchar alcExtensionList[] =
759 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
760 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
761 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
762 "ALC_SOFT_loopback ALC_SOFT_pause_device";
763 static const ALCint alcMajorVersion = 1;
764 static const ALCint alcMinorVersion = 1;
766 static const ALCint alcEFXMajorVersion = 1;
767 static const ALCint alcEFXMinorVersion = 0;
770 /************************************************
771 * Device lists
772 ************************************************/
773 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
775 static almtx_t ListLock;
776 static inline void LockLists(void)
778 int ret = almtx_lock(&ListLock);
779 assert(ret == althrd_success);
781 static inline void UnlockLists(void)
783 int ret = almtx_unlock(&ListLock);
784 assert(ret == althrd_success);
787 /************************************************
788 * Library initialization
789 ************************************************/
790 #if defined(_WIN32)
791 static void alc_init(void);
792 static void alc_deinit(void);
793 static void alc_deinit_safe(void);
795 #ifndef AL_LIBTYPE_STATIC
796 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
798 switch(reason)
800 case DLL_PROCESS_ATTACH:
801 /* Pin the DLL so we won't get unloaded until the process terminates */
802 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 (WCHAR*)hModule, &hModule);
804 alc_init();
805 break;
807 case DLL_THREAD_DETACH:
808 break;
810 case DLL_PROCESS_DETACH:
811 if(!lpReserved)
812 alc_deinit();
813 else
814 alc_deinit_safe();
815 break;
817 return TRUE;
819 #elif defined(_MSC_VER)
820 #pragma section(".CRT$XCU",read)
821 static void alc_constructor(void);
822 static void alc_destructor(void);
823 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
825 static void alc_constructor(void)
827 atexit(alc_destructor);
828 alc_init();
831 static void alc_destructor(void)
833 alc_deinit();
835 #elif defined(HAVE_GCC_DESTRUCTOR)
836 static void alc_init(void) __attribute__((constructor));
837 static void alc_deinit(void) __attribute__((destructor));
838 #else
839 #error "No static initialization available on this platform!"
840 #endif
842 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No global initialization available on this platform!"
849 #endif
851 static void ReleaseThreadCtx(void *ptr);
852 static void alc_init(void)
854 const char *str;
855 int ret;
857 LogFile = stderr;
859 AL_STRING_INIT(alcAllDevicesList);
860 AL_STRING_INIT(alcCaptureDeviceList);
862 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ConeScale *= 0.5f;
866 str = getenv("__ALSOFT_REVERSE_Z");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 ZScale *= -1.0f;
870 ret = altss_create(&LocalContext, ReleaseThreadCtx);
871 assert(ret == althrd_success);
873 ret = almtx_init(&ListLock, almtx_recursive);
874 assert(ret == althrd_success);
876 ThunkInit();
879 static void alc_initconfig(void)
881 const char *devs, *str;
882 ALuint capfilter;
883 float valf;
884 int i, n;
886 str = getenv("ALSOFT_LOGLEVEL");
887 if(str)
889 long lvl = strtol(str, NULL, 0);
890 if(lvl >= NoLog && lvl <= LogRef)
891 LogLevel = lvl;
894 str = getenv("ALSOFT_LOGFILE");
895 if(str && str[0])
897 FILE *logfile = al_fopen(str, "wt");
898 if(logfile) LogFile = logfile;
899 else ERR("Failed to open log file '%s'\n", str);
903 char buf[1024] = "";
904 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
905 for(i = 1;BackendList[i].name;i++)
906 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
907 TRACE("Supported backends: %s\n", buf);
909 ReadALConfig();
911 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
912 if(str && *str)
914 if(strcasecmp(str, "ignore") == 0)
916 SuspendDefers = ALC_FALSE;
917 TRACE("Selected context suspend behavior, \"ignore\"\n");
919 else
920 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
923 capfilter = 0;
924 #if defined(HAVE_SSE4_1)
925 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
926 #elif defined(HAVE_SSE3)
927 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
928 #elif defined(HAVE_SSE2)
929 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
930 #elif defined(HAVE_SSE)
931 capfilter |= CPU_CAP_SSE;
932 #endif
933 #ifdef HAVE_NEON
934 capfilter |= CPU_CAP_NEON;
935 #endif
936 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
938 if(strcasecmp(str, "all") == 0)
939 capfilter = 0;
940 else
942 size_t len;
943 const char *next = str;
945 do {
946 str = next;
947 while(isspace(str[0]))
948 str++;
949 next = strchr(str, ',');
951 if(!str[0] || str[0] == ',')
952 continue;
954 len = (next ? ((size_t)(next-str)) : strlen(str));
955 while(len > 0 && isspace(str[len-1]))
956 len--;
957 if(len == 3 && strncasecmp(str, "sse", len) == 0)
958 capfilter &= ~CPU_CAP_SSE;
959 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
960 capfilter &= ~CPU_CAP_SSE2;
961 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
962 capfilter &= ~CPU_CAP_SSE3;
963 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
964 capfilter &= ~CPU_CAP_SSE4_1;
965 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
966 capfilter &= ~CPU_CAP_NEON;
967 else
968 WARN("Invalid CPU extension \"%s\"\n", str);
969 } while(next++);
972 FillCPUCaps(capfilter);
974 #ifdef _WIN32
975 RTPrioLevel = 1;
976 #else
977 RTPrioLevel = 0;
978 #endif
979 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
981 aluInitMixer();
983 str = getenv("ALSOFT_TRAP_ERROR");
984 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
986 TrapALError = AL_TRUE;
987 TrapALCError = AL_TRUE;
989 else
991 str = getenv("ALSOFT_TRAP_AL_ERROR");
992 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
993 TrapALError = AL_TRUE;
994 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
996 str = getenv("ALSOFT_TRAP_ALC_ERROR");
997 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
998 TrapALCError = ALC_TRUE;
999 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1002 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1003 ReverbBoost *= powf(10.0f, valf / 20.0f);
1005 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1007 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1008 ConfigValueStr(NULL, NULL, "drivers", &devs))
1010 int n;
1011 size_t len;
1012 const char *next = devs;
1013 int endlist, delitem;
1015 i = 0;
1016 do {
1017 devs = next;
1018 while(isspace(devs[0]))
1019 devs++;
1020 next = strchr(devs, ',');
1022 delitem = (devs[0] == '-');
1023 if(devs[0] == '-') devs++;
1025 if(!devs[0] || devs[0] == ',')
1027 endlist = 0;
1028 continue;
1030 endlist = 1;
1032 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1033 while(len > 0 && isspace(devs[len-1]))
1034 len--;
1035 for(n = i;BackendList[n].name;n++)
1037 if(len == strlen(BackendList[n].name) &&
1038 strncmp(BackendList[n].name, devs, len) == 0)
1040 if(delitem)
1042 do {
1043 BackendList[n] = BackendList[n+1];
1044 ++n;
1045 } while(BackendList[n].name);
1047 else
1049 struct BackendInfo Bkp = BackendList[n];
1050 while(n > i)
1052 BackendList[n] = BackendList[n-1];
1053 --n;
1055 BackendList[n] = Bkp;
1057 i++;
1059 break;
1062 } while(next++);
1064 if(endlist)
1066 BackendList[i].name = NULL;
1067 BackendList[i].getFactory = NULL;
1068 BackendList[i].Init = NULL;
1069 BackendList[i].Deinit = NULL;
1070 BackendList[i].Probe = NULL;
1074 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1076 if(BackendList[i].getFactory)
1078 ALCbackendFactory *factory = BackendList[i].getFactory();
1079 if(!V0(factory,init)())
1081 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1082 continue;
1085 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1086 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1088 PlaybackBackend = BackendList[i];
1089 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1091 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1093 CaptureBackend = BackendList[i];
1094 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1097 continue;
1100 if(!BackendList[i].Init(&BackendList[i].Funcs))
1102 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1103 continue;
1106 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1107 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1109 PlaybackBackend = BackendList[i];
1110 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1112 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1114 CaptureBackend = BackendList[i];
1115 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1119 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1120 V0(factory,init)();
1123 if(!PlaybackBackend.name)
1124 WARN("No playback backend available!\n");
1125 if(!CaptureBackend.name)
1126 WARN("No capture backend available!\n");
1128 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1130 size_t len;
1131 const char *next = str;
1133 do {
1134 str = next;
1135 next = strchr(str, ',');
1137 if(!str[0] || next == str)
1138 continue;
1140 len = (next ? ((size_t)(next-str)) : strlen(str));
1141 for(n = 0;EffectList[n].name;n++)
1143 if(len == strlen(EffectList[n].name) &&
1144 strncmp(EffectList[n].name, str, len) == 0)
1145 DisabledEffects[EffectList[n].type] = AL_TRUE;
1147 } while(next++);
1150 InitEffectFactoryMap();
1152 InitEffect(&DefaultEffect);
1153 str = getenv("ALSOFT_DEFAULT_REVERB");
1154 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1155 LoadReverbPreset(str, &DefaultEffect);
1157 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1160 /************************************************
1161 * Library deinitialization
1162 ************************************************/
1163 static void alc_cleanup(void)
1165 ALCdevice *dev;
1167 AL_STRING_DEINIT(alcAllDevicesList);
1168 AL_STRING_DEINIT(alcCaptureDeviceList);
1170 free(alcDefaultAllDevicesSpecifier);
1171 alcDefaultAllDevicesSpecifier = NULL;
1172 free(alcCaptureDefaultDeviceSpecifier);
1173 alcCaptureDefaultDeviceSpecifier = NULL;
1175 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1177 ALCuint num = 0;
1178 do {
1179 num++;
1180 } while((dev=dev->next) != NULL);
1181 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1184 DeinitEffectFactoryMap();
1187 static void alc_deinit_safe(void)
1189 alc_cleanup();
1191 FreeHrtfs();
1192 FreeALConfig();
1194 ThunkExit();
1195 almtx_destroy(&ListLock);
1196 altss_delete(LocalContext);
1198 if(LogFile != stderr)
1199 fclose(LogFile);
1200 LogFile = NULL;
1203 static void alc_deinit(void)
1205 int i;
1207 alc_cleanup();
1209 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1210 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1212 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1214 if(!BackendList[i].getFactory)
1215 BackendList[i].Deinit();
1216 else
1218 ALCbackendFactory *factory = BackendList[i].getFactory();
1219 V0(factory,deinit)();
1223 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1224 V0(factory,deinit)();
1227 alc_deinit_safe();
1231 /************************************************
1232 * Device enumeration
1233 ************************************************/
1234 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1236 DO_INITCONFIG();
1238 LockLists();
1239 al_string_clear(list);
1241 if(backendinfo->Probe)
1242 backendinfo->Probe(type);
1243 else if(backendinfo->getFactory)
1245 ALCbackendFactory *factory = backendinfo->getFactory();
1246 V(factory,probe)(type);
1249 UnlockLists();
1251 static void ProbeAllDevicesList(void)
1252 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1253 static void ProbeCaptureDeviceList(void)
1254 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1256 static void AppendDevice(const ALCchar *name, al_string *devnames)
1258 size_t len = strlen(name);
1259 if(len > 0)
1260 al_string_append_range(devnames, name, name+len+1);
1262 void AppendAllDevicesList(const ALCchar *name)
1263 { AppendDevice(name, &alcAllDevicesList); }
1264 void AppendCaptureDeviceList(const ALCchar *name)
1265 { AppendDevice(name, &alcCaptureDeviceList); }
1268 /************************************************
1269 * Device format information
1270 ************************************************/
1271 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1273 switch(type)
1275 case DevFmtByte: return "Signed Byte";
1276 case DevFmtUByte: return "Unsigned Byte";
1277 case DevFmtShort: return "Signed Short";
1278 case DevFmtUShort: return "Unsigned Short";
1279 case DevFmtInt: return "Signed Int";
1280 case DevFmtUInt: return "Unsigned Int";
1281 case DevFmtFloat: return "Float";
1283 return "(unknown type)";
1285 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1287 switch(chans)
1289 case DevFmtMono: return "Mono";
1290 case DevFmtStereo: return "Stereo";
1291 case DevFmtQuad: return "Quadraphonic";
1292 case DevFmtX51: return "5.1 Surround";
1293 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1294 case DevFmtX61: return "6.1 Surround";
1295 case DevFmtX71: return "7.1 Surround";
1296 case DevFmtAmbi1: return "Ambisonic (1st Order)";
1297 case DevFmtAmbi2: return "Ambisonic (2nd Order)";
1298 case DevFmtAmbi3: return "Ambisonic (3rd Order)";
1300 return "(unknown channels)";
1303 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1304 ALuint BytesFromDevFmt(enum DevFmtType type)
1306 switch(type)
1308 case DevFmtByte: return sizeof(ALbyte);
1309 case DevFmtUByte: return sizeof(ALubyte);
1310 case DevFmtShort: return sizeof(ALshort);
1311 case DevFmtUShort: return sizeof(ALushort);
1312 case DevFmtInt: return sizeof(ALint);
1313 case DevFmtUInt: return sizeof(ALuint);
1314 case DevFmtFloat: return sizeof(ALfloat);
1316 return 0;
1318 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1320 switch(chans)
1322 case DevFmtMono: return 1;
1323 case DevFmtStereo: return 2;
1324 case DevFmtQuad: return 4;
1325 case DevFmtX51: return 6;
1326 case DevFmtX51Rear: return 6;
1327 case DevFmtX61: return 7;
1328 case DevFmtX71: return 8;
1329 case DevFmtAmbi1: return 4;
1330 case DevFmtAmbi2: return 9;
1331 case DevFmtAmbi3: return 16;
1333 return 0;
1336 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1337 enum DevFmtChannels *chans, enum DevFmtType *type)
1339 static const struct {
1340 ALenum format;
1341 enum DevFmtChannels channels;
1342 enum DevFmtType type;
1343 } list[] = {
1344 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1345 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1346 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1348 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1349 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1350 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1352 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1353 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1354 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1356 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1357 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1358 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1360 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1361 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1362 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1364 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1365 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1366 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1368 ALuint i;
1370 for(i = 0;i < COUNTOF(list);i++)
1372 if(list[i].format == format)
1374 *chans = list[i].channels;
1375 *type = list[i].type;
1376 return AL_TRUE;
1380 return AL_FALSE;
1383 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1385 switch(type)
1387 case ALC_BYTE_SOFT:
1388 case ALC_UNSIGNED_BYTE_SOFT:
1389 case ALC_SHORT_SOFT:
1390 case ALC_UNSIGNED_SHORT_SOFT:
1391 case ALC_INT_SOFT:
1392 case ALC_UNSIGNED_INT_SOFT:
1393 case ALC_FLOAT_SOFT:
1394 return ALC_TRUE;
1396 return ALC_FALSE;
1399 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1401 switch(channels)
1403 case ALC_MONO_SOFT:
1404 case ALC_STEREO_SOFT:
1405 case ALC_QUAD_SOFT:
1406 case ALC_5POINT1_SOFT:
1407 case ALC_6POINT1_SOFT:
1408 case ALC_7POINT1_SOFT:
1409 return ALC_TRUE;
1411 return ALC_FALSE;
1415 /************************************************
1416 * Miscellaneous ALC helpers
1417 ************************************************/
1419 extern inline void LockContext(ALCcontext *context);
1420 extern inline void UnlockContext(ALCcontext *context);
1422 void ALCdevice_Lock(ALCdevice *device)
1424 V0(device->Backend,lock)();
1427 void ALCdevice_Unlock(ALCdevice *device)
1429 V0(device->Backend,unlock)();
1433 /* SetDefaultWFXChannelOrder
1435 * Sets the default channel order used by WaveFormatEx.
1437 void SetDefaultWFXChannelOrder(ALCdevice *device)
1439 ALuint i;
1441 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1442 device->RealOut.ChannelName[i] = InvalidChannel;
1444 switch(device->FmtChans)
1446 case DevFmtMono:
1447 device->RealOut.ChannelName[0] = FrontCenter;
1448 break;
1449 case DevFmtStereo:
1450 device->RealOut.ChannelName[0] = FrontLeft;
1451 device->RealOut.ChannelName[1] = FrontRight;
1452 break;
1453 case DevFmtQuad:
1454 device->RealOut.ChannelName[0] = FrontLeft;
1455 device->RealOut.ChannelName[1] = FrontRight;
1456 device->RealOut.ChannelName[2] = BackLeft;
1457 device->RealOut.ChannelName[3] = BackRight;
1458 break;
1459 case DevFmtX51:
1460 device->RealOut.ChannelName[0] = FrontLeft;
1461 device->RealOut.ChannelName[1] = FrontRight;
1462 device->RealOut.ChannelName[2] = FrontCenter;
1463 device->RealOut.ChannelName[3] = LFE;
1464 device->RealOut.ChannelName[4] = SideLeft;
1465 device->RealOut.ChannelName[5] = SideRight;
1466 break;
1467 case DevFmtX51Rear:
1468 device->RealOut.ChannelName[0] = FrontLeft;
1469 device->RealOut.ChannelName[1] = FrontRight;
1470 device->RealOut.ChannelName[2] = FrontCenter;
1471 device->RealOut.ChannelName[3] = LFE;
1472 device->RealOut.ChannelName[4] = BackLeft;
1473 device->RealOut.ChannelName[5] = BackRight;
1474 break;
1475 case DevFmtX61:
1476 device->RealOut.ChannelName[0] = FrontLeft;
1477 device->RealOut.ChannelName[1] = FrontRight;
1478 device->RealOut.ChannelName[2] = FrontCenter;
1479 device->RealOut.ChannelName[3] = LFE;
1480 device->RealOut.ChannelName[4] = BackCenter;
1481 device->RealOut.ChannelName[5] = SideLeft;
1482 device->RealOut.ChannelName[6] = SideRight;
1483 break;
1484 case DevFmtX71:
1485 device->RealOut.ChannelName[0] = FrontLeft;
1486 device->RealOut.ChannelName[1] = FrontRight;
1487 device->RealOut.ChannelName[2] = FrontCenter;
1488 device->RealOut.ChannelName[3] = LFE;
1489 device->RealOut.ChannelName[4] = BackLeft;
1490 device->RealOut.ChannelName[5] = BackRight;
1491 device->RealOut.ChannelName[6] = SideLeft;
1492 device->RealOut.ChannelName[7] = SideRight;
1493 break;
1494 case DevFmtAmbi1:
1495 device->RealOut.ChannelName[0] = Aux0;
1496 device->RealOut.ChannelName[1] = Aux1;
1497 device->RealOut.ChannelName[2] = Aux2;
1498 device->RealOut.ChannelName[3] = Aux3;
1499 break;
1500 case DevFmtAmbi2:
1501 device->RealOut.ChannelName[0] = Aux0;
1502 device->RealOut.ChannelName[1] = Aux1;
1503 device->RealOut.ChannelName[2] = Aux2;
1504 device->RealOut.ChannelName[3] = Aux3;
1505 device->RealOut.ChannelName[4] = Aux4;
1506 device->RealOut.ChannelName[5] = Aux5;
1507 device->RealOut.ChannelName[6] = Aux6;
1508 device->RealOut.ChannelName[7] = Aux7;
1509 device->RealOut.ChannelName[8] = Aux8;
1510 break;
1511 case DevFmtAmbi3:
1512 device->RealOut.ChannelName[0] = Aux0;
1513 device->RealOut.ChannelName[1] = Aux1;
1514 device->RealOut.ChannelName[2] = Aux2;
1515 device->RealOut.ChannelName[3] = Aux3;
1516 device->RealOut.ChannelName[4] = Aux4;
1517 device->RealOut.ChannelName[5] = Aux5;
1518 device->RealOut.ChannelName[6] = Aux6;
1519 device->RealOut.ChannelName[7] = Aux7;
1520 device->RealOut.ChannelName[8] = Aux8;
1521 device->RealOut.ChannelName[9] = Aux9;
1522 device->RealOut.ChannelName[10] = Aux10;
1523 device->RealOut.ChannelName[11] = Aux11;
1524 device->RealOut.ChannelName[12] = Aux12;
1525 device->RealOut.ChannelName[13] = Aux13;
1526 device->RealOut.ChannelName[14] = Aux14;
1527 device->RealOut.ChannelName[15] = Aux15;
1528 break;
1532 /* SetDefaultChannelOrder
1534 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1536 void SetDefaultChannelOrder(ALCdevice *device)
1538 ALuint i;
1540 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1541 device->RealOut.ChannelName[i] = InvalidChannel;
1543 switch(device->FmtChans)
1545 case DevFmtX51Rear:
1546 device->RealOut.ChannelName[0] = FrontLeft;
1547 device->RealOut.ChannelName[1] = FrontRight;
1548 device->RealOut.ChannelName[2] = BackLeft;
1549 device->RealOut.ChannelName[3] = BackRight;
1550 device->RealOut.ChannelName[4] = FrontCenter;
1551 device->RealOut.ChannelName[5] = LFE;
1552 return;
1553 case DevFmtX71:
1554 device->RealOut.ChannelName[0] = FrontLeft;
1555 device->RealOut.ChannelName[1] = FrontRight;
1556 device->RealOut.ChannelName[2] = BackLeft;
1557 device->RealOut.ChannelName[3] = BackRight;
1558 device->RealOut.ChannelName[4] = FrontCenter;
1559 device->RealOut.ChannelName[5] = LFE;
1560 device->RealOut.ChannelName[6] = SideLeft;
1561 device->RealOut.ChannelName[7] = SideRight;
1562 return;
1564 /* Same as WFX order */
1565 case DevFmtMono:
1566 case DevFmtStereo:
1567 case DevFmtQuad:
1568 case DevFmtX51:
1569 case DevFmtX61:
1570 case DevFmtAmbi1:
1571 case DevFmtAmbi2:
1572 case DevFmtAmbi3:
1573 SetDefaultWFXChannelOrder(device);
1574 break;
1578 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1581 /* ALCcontext_DeferUpdates
1583 * Defers/suspends updates for the given context's listener and sources. This
1584 * does *NOT* stop mixing, but rather prevents certain property changes from
1585 * taking effect.
1587 void ALCcontext_DeferUpdates(ALCcontext *context)
1589 ATOMIC_STORE(&context->DeferUpdates, AL_TRUE);
1592 /* ALCcontext_ProcessUpdates
1594 * Resumes update processing after being deferred.
1596 void ALCcontext_ProcessUpdates(ALCcontext *context)
1598 ALCdevice *device = context->Device;
1600 ReadLock(&context->PropLock);
1601 if(ATOMIC_EXCHANGE(ALenum, &context->DeferUpdates, AL_FALSE))
1603 ALsizei pos;
1605 UpdateListenerProps(context);
1607 LockUIntMapRead(&context->SourceMap);
1608 V0(device->Backend,lock)();
1609 for(pos = 0;pos < context->SourceMap.size;pos++)
1611 ALsource *Source = context->SourceMap.values[pos];
1612 ALenum new_state;
1614 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1615 Source->OffsetType != AL_NONE)
1617 WriteLock(&Source->queue_lock);
1618 ApplyOffset(Source);
1619 WriteUnlock(&Source->queue_lock);
1622 new_state = Source->new_state;
1623 Source->new_state = AL_NONE;
1624 if(new_state)
1625 SetSourceState(Source, context, new_state);
1627 V0(device->Backend,unlock)();
1628 UnlockUIntMapRead(&context->SourceMap);
1629 UpdateAllSourceProps(context);
1631 ReadUnlock(&context->PropLock);
1635 /* alcSetError
1637 * Stores the latest ALC device error
1639 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1641 if(TrapALCError)
1643 #ifdef _WIN32
1644 /* DebugBreak() will cause an exception if there is no debugger */
1645 if(IsDebuggerPresent())
1646 DebugBreak();
1647 #elif defined(SIGTRAP)
1648 raise(SIGTRAP);
1649 #endif
1652 if(device)
1653 ATOMIC_STORE(&device->LastError, errorCode);
1654 else
1655 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1659 /* UpdateClockBase
1661 * Updates the device's base clock time with however many samples have been
1662 * done. This is used so frequency changes on the device don't cause the time
1663 * to jump forward or back.
1665 static inline void UpdateClockBase(ALCdevice *device)
1667 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1668 device->SamplesDone = 0;
1671 /* UpdateDeviceParams
1673 * Updates device parameters according to the attribute list (caller is
1674 * responsible for holding the list lock).
1676 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1678 ALCcontext *context;
1679 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1680 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1681 enum DevFmtChannels oldChans;
1682 enum DevFmtType oldType;
1683 ALCuint oldFreq;
1684 FPUCtl oldMode;
1685 ALCsizei hrtf_id = -1;
1686 size_t size;
1688 // Check for attributes
1689 if(device->Type == Loopback)
1691 enum {
1692 GotFreq = 1<<0,
1693 GotChans = 1<<1,
1694 GotType = 1<<2,
1695 GotAll = GotFreq|GotChans|GotType
1697 ALCuint freq, numMono, numStereo, numSends;
1698 enum DevFmtChannels schans;
1699 enum DevFmtType stype;
1700 ALCuint attrIdx = 0;
1701 ALCint gotFmt = 0;
1703 if(!attrList)
1705 WARN("Missing attributes for loopback device\n");
1706 return ALC_INVALID_VALUE;
1709 numMono = device->NumMonoSources;
1710 numStereo = device->NumStereoSources;
1711 numSends = device->NumAuxSends;
1712 schans = device->FmtChans;
1713 stype = device->FmtType;
1714 freq = device->Frequency;
1716 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1717 while(attrList[attrIdx])
1719 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1721 ALCint val = attrList[attrIdx + 1];
1722 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val);
1723 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1724 return ALC_INVALID_VALUE;
1725 schans = val;
1726 gotFmt |= GotChans;
1729 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1731 ALCint val = attrList[attrIdx + 1];
1732 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val);
1733 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1734 return ALC_INVALID_VALUE;
1735 stype = val;
1736 gotFmt |= GotType;
1739 if(attrList[attrIdx] == ALC_FREQUENCY)
1741 freq = attrList[attrIdx + 1];
1742 TRACE_ATTR(ALC_FREQUENCY, freq);
1743 if(freq < MIN_OUTPUT_RATE)
1744 return ALC_INVALID_VALUE;
1745 gotFmt |= GotFreq;
1748 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1750 numStereo = attrList[attrIdx + 1];
1751 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1752 if(numStereo > device->SourcesMax)
1753 numStereo = device->SourcesMax;
1755 numMono = device->SourcesMax - numStereo;
1758 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1760 numSends = attrList[attrIdx + 1];
1761 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1764 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1766 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1767 if(attrList[attrIdx + 1] == ALC_FALSE)
1768 hrtf_appreq = Hrtf_Disable;
1769 else if(attrList[attrIdx + 1] == ALC_TRUE)
1770 hrtf_appreq = Hrtf_Enable;
1771 else
1772 hrtf_appreq = Hrtf_Default;
1775 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1777 hrtf_id = attrList[attrIdx + 1];
1778 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1781 attrIdx += 2;
1783 #undef TRACE_ATTR
1785 if(gotFmt != GotAll)
1787 WARN("Missing format for loopback device\n");
1788 return ALC_INVALID_VALUE;
1791 ConfigValueUInt(NULL, NULL, "sends", &numSends);
1792 numSends = minu(MAX_SENDS, numSends);
1794 if((device->Flags&DEVICE_RUNNING))
1795 V0(device->Backend,stop)();
1796 device->Flags &= ~DEVICE_RUNNING;
1798 UpdateClockBase(device);
1800 device->Frequency = freq;
1801 device->FmtChans = schans;
1802 device->FmtType = stype;
1803 device->NumMonoSources = numMono;
1804 device->NumStereoSources = numStereo;
1805 device->NumAuxSends = numSends;
1807 else if(attrList && attrList[0])
1809 ALCuint freq, numMono, numStereo, numSends;
1810 ALCuint attrIdx = 0;
1812 /* If a context is already running on the device, stop playback so the
1813 * device attributes can be updated. */
1814 if((device->Flags&DEVICE_RUNNING))
1815 V0(device->Backend,stop)();
1816 device->Flags &= ~DEVICE_RUNNING;
1818 freq = device->Frequency;
1819 numMono = device->NumMonoSources;
1820 numStereo = device->NumStereoSources;
1821 numSends = device->NumAuxSends;
1823 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1824 while(attrList[attrIdx])
1826 if(attrList[attrIdx] == ALC_FREQUENCY)
1828 freq = attrList[attrIdx + 1];
1829 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1830 TRACE_ATTR(ALC_FREQUENCY, freq);
1833 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1835 numStereo = attrList[attrIdx + 1];
1836 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1837 if(numStereo > device->SourcesMax)
1838 numStereo = device->SourcesMax;
1840 numMono = device->SourcesMax - numStereo;
1843 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1845 numSends = attrList[attrIdx + 1];
1846 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1849 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1851 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1852 if(attrList[attrIdx + 1] == ALC_FALSE)
1853 hrtf_appreq = Hrtf_Disable;
1854 else if(attrList[attrIdx + 1] == ALC_TRUE)
1855 hrtf_appreq = Hrtf_Enable;
1856 else
1857 hrtf_appreq = Hrtf_Default;
1860 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1862 hrtf_id = attrList[attrIdx + 1];
1863 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1866 attrIdx += 2;
1868 #undef TRACE_ATTR
1870 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1871 freq = maxu(freq, MIN_OUTPUT_RATE);
1873 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
1874 numSends = minu(MAX_SENDS, numSends);
1876 UpdateClockBase(device);
1878 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1879 device->Frequency;
1880 /* SSE and Neon do best with the update size being a multiple of 4 */
1881 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1882 device->UpdateSize = (device->UpdateSize+3)&~3;
1884 device->Frequency = freq;
1885 device->NumMonoSources = numMono;
1886 device->NumStereoSources = numStereo;
1887 device->NumAuxSends = numSends;
1890 if((device->Flags&DEVICE_RUNNING))
1891 return ALC_NO_ERROR;
1893 al_free(device->Uhj_Encoder);
1894 device->Uhj_Encoder = NULL;
1896 al_free(device->Bs2b);
1897 device->Bs2b = NULL;
1899 al_free(device->Dry.Buffer);
1900 device->Dry.Buffer = NULL;
1901 device->Dry.NumChannels = 0;
1902 device->FOAOut.Buffer = NULL;
1903 device->FOAOut.NumChannels = 0;
1904 device->RealOut.Buffer = NULL;
1905 device->RealOut.NumChannels = 0;
1907 UpdateClockBase(device);
1909 /*************************************************************************
1910 * Update device format request if HRTF is requested
1912 device->Hrtf_Status = ALC_HRTF_DISABLED_SOFT;
1913 if(device->Type != Loopback)
1915 const char *hrtf;
1916 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
1918 if(strcasecmp(hrtf, "true") == 0)
1919 hrtf_userreq = Hrtf_Enable;
1920 else if(strcasecmp(hrtf, "false") == 0)
1921 hrtf_userreq = Hrtf_Disable;
1922 else if(strcasecmp(hrtf, "auto") != 0)
1923 ERR("Unexpected hrtf value: %s\n", hrtf);
1926 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1928 if(VECTOR_SIZE(device->Hrtf_List) == 0)
1930 VECTOR_DEINIT(device->Hrtf_List);
1931 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
1933 if(VECTOR_SIZE(device->Hrtf_List) > 0)
1935 device->FmtChans = DevFmtStereo;
1936 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf_List))
1937 device->Frequency = VECTOR_ELEM(device->Hrtf_List, hrtf_id).hrtf->sampleRate;
1938 else
1939 device->Frequency = VECTOR_ELEM(device->Hrtf_List, 0).hrtf->sampleRate;
1940 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
1942 else
1944 hrtf_userreq = Hrtf_Default;
1945 hrtf_appreq = Hrtf_Disable;
1946 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1950 else if(hrtf_appreq == Hrtf_Enable)
1952 size_t i = VECTOR_SIZE(device->Hrtf_List);
1953 /* Loopback device. We don't need to match to a specific HRTF entry
1954 * here. If the requested ID matches, we'll pick that later, if not,
1955 * we'll try to auto-select one anyway. Just make sure one exists
1956 * that'll work.
1958 if(device->FmtChans == DevFmtStereo)
1960 if(VECTOR_SIZE(device->Hrtf_List) == 0)
1962 VECTOR_DEINIT(device->Hrtf_List);
1963 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
1965 for(i = 0;i < VECTOR_SIZE(device->Hrtf_List);i++)
1967 const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf_List, i).hrtf;
1968 if(hrtf->sampleRate == device->Frequency)
1969 break;
1972 if(i == VECTOR_SIZE(device->Hrtf_List))
1974 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1975 DevFmtChannelsString(device->FmtChans), device->Frequency);
1976 hrtf_appreq = Hrtf_Disable;
1977 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1981 oldFreq = device->Frequency;
1982 oldChans = device->FmtChans;
1983 oldType = device->FmtType;
1985 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1986 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
1987 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
1988 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
1989 device->UpdateSize, device->NumUpdates
1992 if(V0(device->Backend,reset)() == ALC_FALSE)
1993 return ALC_INVALID_DEVICE;
1995 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1997 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1998 DevFmtChannelsString(device->FmtChans));
1999 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2001 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2003 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2004 DevFmtTypeString(device->FmtType));
2005 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2007 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2009 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2010 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2013 if((device->UpdateSize&3) != 0)
2015 if((CPUCapFlags&CPU_CAP_SSE))
2016 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2017 if((CPUCapFlags&CPU_CAP_NEON))
2018 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2021 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2022 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2023 device->Frequency, device->UpdateSize, device->NumUpdates
2026 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2028 /* Allocate extra channels for any post-filter output. */
2029 size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]);
2030 if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2))
2031 size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]);
2032 else if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder)
2033 size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]);
2034 else if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
2035 size += 4 * sizeof(device->Dry.Buffer[0]);
2036 device->Dry.Buffer = al_calloc(16, size);
2037 if(!device->Dry.Buffer)
2039 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2040 return ALC_INVALID_DEVICE;
2043 if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder)
2045 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2046 device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
2048 else
2050 device->RealOut.Buffer = device->Dry.Buffer;
2051 device->RealOut.NumChannels = device->Dry.NumChannels;
2054 if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) ||
2055 (device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3))
2057 /* Higher-order rendering requires upsampling first-order content, so
2058 * make sure to mix it separately.
2060 device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels;
2061 device->FOAOut.NumChannels = 4;
2063 else
2065 device->FOAOut.Buffer = device->Dry.Buffer;
2066 device->FOAOut.NumChannels = device->Dry.NumChannels;
2069 SetMixerFPUMode(&oldMode);
2070 if(device->DefaultSlot)
2072 ALeffectslot *slot = device->DefaultSlot;
2073 ALeffectState *state = slot->Effect.State;
2075 state->OutBuffer = device->Dry.Buffer;
2076 state->OutChannels = device->Dry.NumChannels;
2077 if(V(state,deviceUpdate)(device) == AL_FALSE)
2079 RestoreFPUMode(&oldMode);
2080 return ALC_INVALID_DEVICE;
2082 UpdateEffectSlotProps(slot);
2085 context = ATOMIC_LOAD(&device->ContextList);
2086 while(context)
2088 ALsizei pos;
2090 ReadLock(&context->PropLock);
2091 LockUIntMapRead(&context->EffectSlotMap);
2092 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2094 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2095 ALeffectState *state = slot->Effect.State;
2097 state->OutBuffer = device->Dry.Buffer;
2098 state->OutChannels = device->Dry.NumChannels;
2099 if(V(state,deviceUpdate)(device) == AL_FALSE)
2101 UnlockUIntMapRead(&context->EffectSlotMap);
2102 ReadUnlock(&context->PropLock);
2103 RestoreFPUMode(&oldMode);
2104 return ALC_INVALID_DEVICE;
2107 UpdateEffectSlotProps(slot);
2109 UnlockUIntMapRead(&context->EffectSlotMap);
2111 LockUIntMapRead(&context->SourceMap);
2112 for(pos = 0;pos < context->SourceMap.size;pos++)
2114 ALsource *source = context->SourceMap.values[pos];
2115 ALuint s = device->NumAuxSends;
2116 while(s < MAX_SENDS)
2118 if(source->Send[s].Slot)
2119 DecrementRef(&source->Send[s].Slot->ref);
2120 source->Send[s].Slot = NULL;
2121 source->Send[s].Gain = 1.0f;
2122 source->Send[s].GainHF = 1.0f;
2123 source->Send[s].HFReference = LOWPASSFREQREF;
2124 source->Send[s].GainLF = 1.0f;
2125 source->Send[s].LFReference = HIGHPASSFREQREF;
2126 s++;
2129 UnlockUIntMapRead(&context->SourceMap);
2131 UpdateAllSourceProps(context);
2132 ReadUnlock(&context->PropLock);
2134 context = context->next;
2136 RestoreFPUMode(&oldMode);
2138 if(!(device->Flags&DEVICE_PAUSED))
2140 if(V0(device->Backend,start)() == ALC_FALSE)
2141 return ALC_INVALID_DEVICE;
2142 device->Flags |= DEVICE_RUNNING;
2145 return ALC_NO_ERROR;
2148 /* FreeDevice
2150 * Frees the device structure, and destroys any objects the app failed to
2151 * delete. Called once there's no more references on the device.
2153 static ALCvoid FreeDevice(ALCdevice *device)
2155 TRACE("%p\n", device);
2157 V0(device->Backend,close)();
2158 DELETE_OBJ(device->Backend);
2159 device->Backend = NULL;
2161 almtx_destroy(&device->BackendLock);
2163 if(device->DefaultSlot)
2165 DeinitEffectSlot(device->DefaultSlot);
2166 device->DefaultSlot = NULL;
2169 if(device->BufferMap.size > 0)
2171 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2172 (device->BufferMap.size==1)?"":"s");
2173 ReleaseALBuffers(device);
2175 ResetUIntMap(&device->BufferMap);
2177 if(device->EffectMap.size > 0)
2179 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2180 (device->EffectMap.size==1)?"":"s");
2181 ReleaseALEffects(device);
2183 ResetUIntMap(&device->EffectMap);
2185 if(device->FilterMap.size > 0)
2187 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2188 (device->FilterMap.size==1)?"":"s");
2189 ReleaseALFilters(device);
2191 ResetUIntMap(&device->FilterMap);
2193 AL_STRING_DEINIT(device->Hrtf_Name);
2194 FreeHrtfList(&device->Hrtf_List);
2196 al_free(device->Bs2b);
2197 device->Bs2b = NULL;
2199 al_free(device->Uhj_Encoder);
2200 device->Uhj_Encoder = NULL;
2202 bformatdec_free(device->AmbiDecoder);
2203 device->AmbiDecoder = NULL;
2205 ambiup_free(device->AmbiUp);
2206 device->AmbiUp = NULL;
2208 AL_STRING_DEINIT(device->DeviceName);
2210 al_free(device->Dry.Buffer);
2211 device->Dry.Buffer = NULL;
2212 device->Dry.NumChannels = 0;
2213 device->FOAOut.Buffer = NULL;
2214 device->FOAOut.NumChannels = 0;
2215 device->RealOut.Buffer = NULL;
2216 device->RealOut.NumChannels = 0;
2218 al_free(device);
2222 void ALCdevice_IncRef(ALCdevice *device)
2224 uint ref;
2225 ref = IncrementRef(&device->ref);
2226 TRACEREF("%p increasing refcount to %u\n", device, ref);
2229 void ALCdevice_DecRef(ALCdevice *device)
2231 uint ref;
2232 ref = DecrementRef(&device->ref);
2233 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2234 if(ref == 0) FreeDevice(device);
2237 /* VerifyDevice
2239 * Checks if the device handle is valid, and increments its ref count if so.
2241 static ALCboolean VerifyDevice(ALCdevice **device)
2243 ALCdevice *tmpDevice;
2245 LockLists();
2246 tmpDevice = ATOMIC_LOAD(&DeviceList);
2247 while(tmpDevice)
2249 if(tmpDevice == *device)
2251 ALCdevice_IncRef(tmpDevice);
2252 UnlockLists();
2253 return ALC_TRUE;
2255 tmpDevice = tmpDevice->next;
2257 UnlockLists();
2259 *device = NULL;
2260 return ALC_FALSE;
2264 /* InitContext
2266 * Initializes context fields
2268 static ALvoid InitContext(ALCcontext *Context)
2270 ALlistener *listener = Context->Listener;
2272 //Initialise listener
2273 listener->Gain = 1.0f;
2274 listener->MetersPerUnit = 1.0f;
2275 listener->Position[0] = 0.0f;
2276 listener->Position[1] = 0.0f;
2277 listener->Position[2] = 0.0f;
2278 listener->Velocity[0] = 0.0f;
2279 listener->Velocity[1] = 0.0f;
2280 listener->Velocity[2] = 0.0f;
2281 listener->Forward[0] = 0.0f;
2282 listener->Forward[1] = 0.0f;
2283 listener->Forward[2] = -1.0f;
2284 listener->Up[0] = 0.0f;
2285 listener->Up[1] = 1.0f;
2286 listener->Up[2] = 0.0f;
2288 aluMatrixfSet(&listener->Params.Matrix,
2289 1.0f, 0.0f, 0.0f, 0.0f,
2290 0.0f, 1.0f, 0.0f, 0.0f,
2291 0.0f, 0.0f, 1.0f, 0.0f,
2292 0.0f, 0.0f, 0.0f, 1.0f
2294 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2295 listener->Params.Gain = 1.0f;
2296 listener->Params.MetersPerUnit = 1.0f;
2297 listener->Params.DopplerFactor = 1.0f;
2298 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2300 ATOMIC_INIT(&listener->Update, NULL);
2301 ATOMIC_INIT(&listener->FreeList, NULL);
2303 //Validate Context
2304 InitRef(&Context->UpdateCount, 0);
2305 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2306 RWLockInit(&Context->PropLock);
2307 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2308 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2309 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2311 //Set globals
2312 Context->DistanceModel = DefaultDistanceModel;
2313 Context->SourceDistanceModel = AL_FALSE;
2314 Context->DopplerFactor = 1.0f;
2315 Context->DopplerVelocity = 1.0f;
2316 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2317 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2319 Context->ExtensionList = alExtList;
2323 /* FreeContext
2325 * Cleans up the context, and destroys any remaining objects the app failed to
2326 * delete. Called once there's no more references on the context.
2328 static void FreeContext(ALCcontext *context)
2330 ALlistener *listener = context->Listener;
2331 struct ALlistenerProps *lprops;
2332 size_t count;
2334 TRACE("%p\n", context);
2336 if(context->SourceMap.size > 0)
2338 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2339 (context->SourceMap.size==1)?"":"s");
2340 ReleaseALSources(context);
2342 ResetUIntMap(&context->SourceMap);
2344 if(context->EffectSlotMap.size > 0)
2346 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2347 (context->EffectSlotMap.size==1)?"":"s");
2348 ReleaseALAuxiliaryEffectSlots(context);
2350 ResetUIntMap(&context->EffectSlotMap);
2352 al_free(context->Voices);
2353 context->Voices = NULL;
2354 context->VoiceCount = 0;
2355 context->MaxVoices = 0;
2357 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2359 TRACE("Freed unapplied listener update %p\n", lprops);
2360 al_free(lprops);
2362 count = 0;
2363 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_consume);
2364 while(lprops)
2366 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_consume);
2367 al_free(lprops);
2368 lprops = next;
2369 ++count;
2371 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2373 ALCdevice_DecRef(context->Device);
2374 context->Device = NULL;
2376 //Invalidate context
2377 memset(context, 0, sizeof(ALCcontext));
2378 al_free(context);
2381 /* ReleaseContext
2383 * Removes the context reference from the given device and removes it from
2384 * being current on the running thread or globally.
2386 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2388 ALCcontext *nextctx;
2389 ALCcontext *origctx;
2391 if(altss_get(LocalContext) == context)
2393 WARN("%p released while current on thread\n", context);
2394 altss_set(LocalContext, NULL);
2395 ALCcontext_DecRef(context);
2398 origctx = context;
2399 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2400 ALCcontext_DecRef(context);
2402 ALCdevice_Lock(device);
2403 origctx = context;
2404 nextctx = context->next;
2405 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2407 ALCcontext *list;
2408 do {
2409 list = origctx;
2410 origctx = context;
2411 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2413 ALCdevice_Unlock(device);
2415 ALCcontext_DecRef(context);
2418 void ALCcontext_IncRef(ALCcontext *context)
2420 uint ref = IncrementRef(&context->ref);
2421 TRACEREF("%p increasing refcount to %u\n", context, ref);
2424 void ALCcontext_DecRef(ALCcontext *context)
2426 uint ref = DecrementRef(&context->ref);
2427 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2428 if(ref == 0) FreeContext(context);
2431 static void ReleaseThreadCtx(void *ptr)
2433 ALCcontext *context = ptr;
2434 uint ref = DecrementRef(&context->ref);
2435 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2436 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2439 /* VerifyContext
2441 * Checks that the given context is valid, and increments its reference count.
2443 static ALCboolean VerifyContext(ALCcontext **context)
2445 ALCdevice *dev;
2447 LockLists();
2448 dev = ATOMIC_LOAD(&DeviceList);
2449 while(dev)
2451 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2452 while(ctx)
2454 if(ctx == *context)
2456 ALCcontext_IncRef(ctx);
2457 UnlockLists();
2458 return ALC_TRUE;
2460 ctx = ctx->next;
2462 dev = dev->next;
2464 UnlockLists();
2466 *context = NULL;
2467 return ALC_FALSE;
2471 /* GetContextRef
2473 * Returns the currently active context for this thread, and adds a reference
2474 * without locking it.
2476 ALCcontext *GetContextRef(void)
2478 ALCcontext *context;
2480 context = altss_get(LocalContext);
2481 if(context)
2482 ALCcontext_IncRef(context);
2483 else
2485 LockLists();
2486 context = ATOMIC_LOAD(&GlobalContext);
2487 if(context)
2488 ALCcontext_IncRef(context);
2489 UnlockLists();
2492 return context;
2496 /************************************************
2497 * Standard ALC functions
2498 ************************************************/
2500 /* alcGetError
2502 * Return last ALC generated error code for the given device
2504 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2506 ALCenum errorCode;
2508 if(VerifyDevice(&device))
2510 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2511 ALCdevice_DecRef(device);
2513 else
2514 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2516 return errorCode;
2520 /* alcSuspendContext
2522 * Suspends updates for the given context
2524 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2526 if(!SuspendDefers)
2527 return;
2529 if(!VerifyContext(&context))
2530 alcSetError(NULL, ALC_INVALID_CONTEXT);
2531 else
2533 ALCcontext_DeferUpdates(context);
2534 ALCcontext_DecRef(context);
2538 /* alcProcessContext
2540 * Resumes processing updates for the given context
2542 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2544 if(!SuspendDefers)
2545 return;
2547 if(!VerifyContext(&context))
2548 alcSetError(NULL, ALC_INVALID_CONTEXT);
2549 else
2551 ALCcontext_ProcessUpdates(context);
2552 ALCcontext_DecRef(context);
2557 /* alcGetString
2559 * Returns information about the device, and error strings
2561 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2563 const ALCchar *value = NULL;
2565 switch(param)
2567 case ALC_NO_ERROR:
2568 value = alcNoError;
2569 break;
2571 case ALC_INVALID_ENUM:
2572 value = alcErrInvalidEnum;
2573 break;
2575 case ALC_INVALID_VALUE:
2576 value = alcErrInvalidValue;
2577 break;
2579 case ALC_INVALID_DEVICE:
2580 value = alcErrInvalidDevice;
2581 break;
2583 case ALC_INVALID_CONTEXT:
2584 value = alcErrInvalidContext;
2585 break;
2587 case ALC_OUT_OF_MEMORY:
2588 value = alcErrOutOfMemory;
2589 break;
2591 case ALC_DEVICE_SPECIFIER:
2592 value = alcDefaultName;
2593 break;
2595 case ALC_ALL_DEVICES_SPECIFIER:
2596 if(VerifyDevice(&Device))
2598 value = al_string_get_cstr(Device->DeviceName);
2599 ALCdevice_DecRef(Device);
2601 else
2603 ProbeAllDevicesList();
2604 value = al_string_get_cstr(alcAllDevicesList);
2606 break;
2608 case ALC_CAPTURE_DEVICE_SPECIFIER:
2609 if(VerifyDevice(&Device))
2611 value = al_string_get_cstr(Device->DeviceName);
2612 ALCdevice_DecRef(Device);
2614 else
2616 ProbeCaptureDeviceList();
2617 value = al_string_get_cstr(alcCaptureDeviceList);
2619 break;
2621 /* Default devices are always first in the list */
2622 case ALC_DEFAULT_DEVICE_SPECIFIER:
2623 value = alcDefaultName;
2624 break;
2626 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2627 if(al_string_empty(alcAllDevicesList))
2628 ProbeAllDevicesList();
2630 VerifyDevice(&Device);
2632 free(alcDefaultAllDevicesSpecifier);
2633 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2634 if(!alcDefaultAllDevicesSpecifier)
2635 alcSetError(Device, ALC_OUT_OF_MEMORY);
2637 value = alcDefaultAllDevicesSpecifier;
2638 if(Device) ALCdevice_DecRef(Device);
2639 break;
2641 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2642 if(al_string_empty(alcCaptureDeviceList))
2643 ProbeCaptureDeviceList();
2645 VerifyDevice(&Device);
2647 free(alcCaptureDefaultDeviceSpecifier);
2648 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2649 if(!alcCaptureDefaultDeviceSpecifier)
2650 alcSetError(Device, ALC_OUT_OF_MEMORY);
2652 value = alcCaptureDefaultDeviceSpecifier;
2653 if(Device) ALCdevice_DecRef(Device);
2654 break;
2656 case ALC_EXTENSIONS:
2657 if(!VerifyDevice(&Device))
2658 value = alcNoDeviceExtList;
2659 else
2661 value = alcExtensionList;
2662 ALCdevice_DecRef(Device);
2664 break;
2666 case ALC_HRTF_SPECIFIER_SOFT:
2667 if(!VerifyDevice(&Device))
2668 alcSetError(NULL, ALC_INVALID_DEVICE);
2669 else
2671 almtx_lock(&Device->BackendLock);
2672 value = (Device->Hrtf ? al_string_get_cstr(Device->Hrtf_Name) : "");
2673 almtx_unlock(&Device->BackendLock);
2674 ALCdevice_DecRef(Device);
2676 break;
2678 default:
2679 VerifyDevice(&Device);
2680 alcSetError(Device, ALC_INVALID_ENUM);
2681 if(Device) ALCdevice_DecRef(Device);
2682 break;
2685 return value;
2689 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2691 ALCsizei i;
2693 if(size <= 0 || values == NULL)
2695 alcSetError(device, ALC_INVALID_VALUE);
2696 return 0;
2699 if(!device)
2701 switch(param)
2703 case ALC_MAJOR_VERSION:
2704 values[0] = alcMajorVersion;
2705 return 1;
2706 case ALC_MINOR_VERSION:
2707 values[0] = alcMinorVersion;
2708 return 1;
2710 case ALC_ATTRIBUTES_SIZE:
2711 case ALC_ALL_ATTRIBUTES:
2712 case ALC_FREQUENCY:
2713 case ALC_REFRESH:
2714 case ALC_SYNC:
2715 case ALC_MONO_SOURCES:
2716 case ALC_STEREO_SOURCES:
2717 case ALC_CAPTURE_SAMPLES:
2718 case ALC_FORMAT_CHANNELS_SOFT:
2719 case ALC_FORMAT_TYPE_SOFT:
2720 alcSetError(NULL, ALC_INVALID_DEVICE);
2721 return 0;
2723 default:
2724 alcSetError(NULL, ALC_INVALID_ENUM);
2725 return 0;
2727 return 0;
2730 if(device->Type == Capture)
2732 switch(param)
2734 case ALC_CAPTURE_SAMPLES:
2735 almtx_lock(&device->BackendLock);
2736 values[0] = V0(device->Backend,availableSamples)();
2737 almtx_unlock(&device->BackendLock);
2738 return 1;
2740 case ALC_CONNECTED:
2741 values[0] = device->Connected;
2742 return 1;
2744 default:
2745 alcSetError(device, ALC_INVALID_ENUM);
2746 return 0;
2748 return 0;
2751 /* render device */
2752 switch(param)
2754 case ALC_MAJOR_VERSION:
2755 values[0] = alcMajorVersion;
2756 return 1;
2758 case ALC_MINOR_VERSION:
2759 values[0] = alcMinorVersion;
2760 return 1;
2762 case ALC_EFX_MAJOR_VERSION:
2763 values[0] = alcEFXMajorVersion;
2764 return 1;
2766 case ALC_EFX_MINOR_VERSION:
2767 values[0] = alcEFXMinorVersion;
2768 return 1;
2770 case ALC_ATTRIBUTES_SIZE:
2771 values[0] = 17;
2772 return 1;
2774 case ALC_ALL_ATTRIBUTES:
2775 if(size < 17)
2777 alcSetError(device, ALC_INVALID_VALUE);
2778 return 0;
2781 i = 0;
2782 almtx_lock(&device->BackendLock);
2783 values[i++] = ALC_FREQUENCY;
2784 values[i++] = device->Frequency;
2786 if(device->Type != Loopback)
2788 values[i++] = ALC_REFRESH;
2789 values[i++] = device->Frequency / device->UpdateSize;
2791 values[i++] = ALC_SYNC;
2792 values[i++] = ALC_FALSE;
2794 else
2796 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2797 values[i++] = device->FmtChans;
2799 values[i++] = ALC_FORMAT_TYPE_SOFT;
2800 values[i++] = device->FmtType;
2803 values[i++] = ALC_MONO_SOURCES;
2804 values[i++] = device->NumMonoSources;
2806 values[i++] = ALC_STEREO_SOURCES;
2807 values[i++] = device->NumStereoSources;
2809 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2810 values[i++] = device->NumAuxSends;
2812 values[i++] = ALC_HRTF_SOFT;
2813 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2815 values[i++] = ALC_HRTF_STATUS_SOFT;
2816 values[i++] = device->Hrtf_Status;
2817 almtx_unlock(&device->BackendLock);
2819 values[i++] = 0;
2820 return i;
2822 case ALC_FREQUENCY:
2823 values[0] = device->Frequency;
2824 return 1;
2826 case ALC_REFRESH:
2827 if(device->Type == Loopback)
2829 alcSetError(device, ALC_INVALID_DEVICE);
2830 return 0;
2832 almtx_lock(&device->BackendLock);
2833 values[0] = device->Frequency / device->UpdateSize;
2834 almtx_unlock(&device->BackendLock);
2835 return 1;
2837 case ALC_SYNC:
2838 if(device->Type == Loopback)
2840 alcSetError(device, ALC_INVALID_DEVICE);
2841 return 0;
2843 values[0] = ALC_FALSE;
2844 return 1;
2846 case ALC_FORMAT_CHANNELS_SOFT:
2847 if(device->Type != Loopback)
2849 alcSetError(device, ALC_INVALID_DEVICE);
2850 return 0;
2852 values[0] = device->FmtChans;
2853 return 1;
2855 case ALC_FORMAT_TYPE_SOFT:
2856 if(device->Type != Loopback)
2858 alcSetError(device, ALC_INVALID_DEVICE);
2859 return 0;
2861 values[0] = device->FmtType;
2862 return 1;
2864 case ALC_MONO_SOURCES:
2865 values[0] = device->NumMonoSources;
2866 return 1;
2868 case ALC_STEREO_SOURCES:
2869 values[0] = device->NumStereoSources;
2870 return 1;
2872 case ALC_MAX_AUXILIARY_SENDS:
2873 values[0] = device->NumAuxSends;
2874 return 1;
2876 case ALC_CONNECTED:
2877 values[0] = device->Connected;
2878 return 1;
2880 case ALC_HRTF_SOFT:
2881 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2882 return 1;
2884 case ALC_HRTF_STATUS_SOFT:
2885 values[0] = device->Hrtf_Status;
2886 return 1;
2888 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2889 almtx_lock(&device->BackendLock);
2890 FreeHrtfList(&device->Hrtf_List);
2891 device->Hrtf_List = EnumerateHrtf(device->DeviceName);
2892 values[0] = (ALCint)VECTOR_SIZE(device->Hrtf_List);
2893 almtx_unlock(&device->BackendLock);
2894 return 1;
2896 default:
2897 alcSetError(device, ALC_INVALID_ENUM);
2898 return 0;
2900 return 0;
2903 /* alcGetIntegerv
2905 * Returns information about the device and the version of OpenAL
2907 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2909 VerifyDevice(&device);
2910 if(size <= 0 || values == NULL)
2911 alcSetError(device, ALC_INVALID_VALUE);
2912 else
2913 GetIntegerv(device, param, size, values);
2914 if(device) ALCdevice_DecRef(device);
2917 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2919 ALCint *ivals;
2920 ALsizei i;
2922 VerifyDevice(&device);
2923 if(size <= 0 || values == NULL)
2924 alcSetError(device, ALC_INVALID_VALUE);
2925 else if(!device || device->Type == Capture)
2927 ivals = malloc(size * sizeof(ALCint));
2928 size = GetIntegerv(device, pname, size, ivals);
2929 for(i = 0;i < size;i++)
2930 values[i] = ivals[i];
2931 free(ivals);
2933 else /* render device */
2935 ClockLatency clock;
2936 ALuint64 basecount;
2937 ALuint samplecount;
2938 ALuint refcount;
2940 switch(pname)
2942 case ALC_ATTRIBUTES_SIZE:
2943 *values = 21;
2944 break;
2946 case ALC_ALL_ATTRIBUTES:
2947 if(size < 21)
2948 alcSetError(device, ALC_INVALID_VALUE);
2949 else
2951 i = 0;
2952 almtx_lock(&device->BackendLock);
2953 values[i++] = ALC_FREQUENCY;
2954 values[i++] = device->Frequency;
2956 if(device->Type != Loopback)
2958 values[i++] = ALC_REFRESH;
2959 values[i++] = device->Frequency / device->UpdateSize;
2961 values[i++] = ALC_SYNC;
2962 values[i++] = ALC_FALSE;
2964 else
2966 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2967 values[i++] = device->FmtChans;
2969 values[i++] = ALC_FORMAT_TYPE_SOFT;
2970 values[i++] = device->FmtType;
2973 values[i++] = ALC_MONO_SOURCES;
2974 values[i++] = device->NumMonoSources;
2976 values[i++] = ALC_STEREO_SOURCES;
2977 values[i++] = device->NumStereoSources;
2979 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2980 values[i++] = device->NumAuxSends;
2982 values[i++] = ALC_HRTF_SOFT;
2983 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2985 values[i++] = ALC_HRTF_STATUS_SOFT;
2986 values[i++] = device->Hrtf_Status;
2988 clock = V0(device->Backend,getClockLatency)();
2989 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2990 values[i++] = clock.ClockTime;
2992 values[i++] = ALC_DEVICE_LATENCY_SOFT;
2993 values[i++] = clock.Latency;
2994 almtx_unlock(&device->BackendLock);
2996 values[i++] = 0;
2998 break;
3000 case ALC_DEVICE_CLOCK_SOFT:
3001 almtx_lock(&device->BackendLock);
3002 do {
3003 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3004 althrd_yield();
3005 basecount = device->ClockBase;
3006 samplecount = device->SamplesDone;
3007 } while(refcount != ReadRef(&device->MixCount));
3008 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3009 almtx_unlock(&device->BackendLock);
3010 break;
3012 case ALC_DEVICE_LATENCY_SOFT:
3014 almtx_lock(&device->BackendLock);
3015 clock = V0(device->Backend,getClockLatency)();
3016 almtx_unlock(&device->BackendLock);
3017 *values = clock.Latency;
3019 break;
3021 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3022 if(size < 2)
3023 alcSetError(device, ALC_INVALID_VALUE);
3024 else
3026 ClockLatency clock;
3027 almtx_lock(&device->BackendLock);
3028 clock = V0(device->Backend,getClockLatency)();
3029 almtx_unlock(&device->BackendLock);
3030 values[0] = clock.ClockTime;
3031 values[1] = clock.Latency;
3033 break;
3035 default:
3036 ivals = malloc(size * sizeof(ALCint));
3037 size = GetIntegerv(device, pname, size, ivals);
3038 for(i = 0;i < size;i++)
3039 values[i] = ivals[i];
3040 free(ivals);
3041 break;
3044 if(device)
3045 ALCdevice_DecRef(device);
3049 /* alcIsExtensionPresent
3051 * Determines if there is support for a particular extension
3053 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3055 ALCboolean bResult = ALC_FALSE;
3057 VerifyDevice(&device);
3059 if(!extName)
3060 alcSetError(device, ALC_INVALID_VALUE);
3061 else
3063 size_t len = strlen(extName);
3064 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3065 while(ptr && *ptr)
3067 if(strncasecmp(ptr, extName, len) == 0 &&
3068 (ptr[len] == '\0' || isspace(ptr[len])))
3070 bResult = ALC_TRUE;
3071 break;
3073 if((ptr=strchr(ptr, ' ')) != NULL)
3075 do {
3076 ++ptr;
3077 } while(isspace(*ptr));
3081 if(device)
3082 ALCdevice_DecRef(device);
3083 return bResult;
3087 /* alcGetProcAddress
3089 * Retrieves the function address for a particular extension function
3091 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3093 ALCvoid *ptr = NULL;
3095 if(!funcName)
3097 VerifyDevice(&device);
3098 alcSetError(device, ALC_INVALID_VALUE);
3099 if(device) ALCdevice_DecRef(device);
3101 else
3103 ALsizei i = 0;
3104 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3105 i++;
3106 ptr = alcFunctions[i].address;
3109 return ptr;
3113 /* alcGetEnumValue
3115 * Get the value for a particular ALC enumeration name
3117 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3119 ALCenum val = 0;
3121 if(!enumName)
3123 VerifyDevice(&device);
3124 alcSetError(device, ALC_INVALID_VALUE);
3125 if(device) ALCdevice_DecRef(device);
3127 else
3129 ALsizei i = 0;
3130 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3131 i++;
3132 val = enumeration[i].value;
3135 return val;
3139 /* alcCreateContext
3141 * Create and attach a context to the given device.
3143 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3145 ALCcontext *ALContext;
3146 ALCenum err;
3148 LockLists();
3149 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3151 UnlockLists();
3152 alcSetError(device, ALC_INVALID_DEVICE);
3153 if(device) ALCdevice_DecRef(device);
3154 return NULL;
3156 almtx_lock(&device->BackendLock);
3157 UnlockLists();
3159 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
3161 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3162 if(ALContext)
3164 InitRef(&ALContext->ref, 1);
3165 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3167 ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
3169 ALContext->VoiceCount = 0;
3170 ALContext->MaxVoices = 256;
3171 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3173 if(!ALContext || !ALContext->Voices)
3175 almtx_unlock(&device->BackendLock);
3177 if(ALContext)
3179 al_free(ALContext->Voices);
3180 ALContext->Voices = NULL;
3182 al_free(ALContext);
3183 ALContext = NULL;
3186 alcSetError(device, ALC_OUT_OF_MEMORY);
3187 ALCdevice_DecRef(device);
3188 return NULL;
3191 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3193 almtx_unlock(&device->BackendLock);
3195 al_free(ALContext->Voices);
3196 ALContext->Voices = NULL;
3198 al_free(ALContext);
3199 ALContext = NULL;
3201 alcSetError(device, err);
3202 if(err == ALC_INVALID_DEVICE)
3204 V0(device->Backend,lock)();
3205 aluHandleDisconnect(device);
3206 V0(device->Backend,unlock)();
3208 ALCdevice_DecRef(device);
3209 return NULL;
3212 ALContext->Device = device;
3213 ALCdevice_IncRef(device);
3214 InitContext(ALContext);
3217 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3218 do {
3219 ALContext->next = head;
3220 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3222 almtx_unlock(&device->BackendLock);
3224 ALCdevice_DecRef(device);
3226 TRACE("Created context %p\n", ALContext);
3227 return ALContext;
3230 /* alcDestroyContext
3232 * Remove a context from its device
3234 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3236 ALCdevice *Device;
3238 LockLists();
3239 /* alcGetContextsDevice sets an error for invalid contexts */
3240 Device = alcGetContextsDevice(context);
3241 if(Device)
3243 almtx_lock(&Device->BackendLock);
3244 ReleaseContext(context, Device);
3245 if(!ATOMIC_LOAD(&Device->ContextList))
3247 V0(Device->Backend,stop)();
3248 Device->Flags &= ~DEVICE_RUNNING;
3250 almtx_unlock(&Device->BackendLock);
3252 UnlockLists();
3256 /* alcGetCurrentContext
3258 * Returns the currently active context on the calling thread
3260 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3262 ALCcontext *Context = altss_get(LocalContext);
3263 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3264 return Context;
3267 /* alcGetThreadContext
3269 * Returns the currently active thread-local context
3271 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3273 return altss_get(LocalContext);
3277 /* alcMakeContextCurrent
3279 * Makes the given context the active process-wide context, and removes the
3280 * thread-local context for the calling thread.
3282 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3284 /* context must be valid or NULL */
3285 if(context && !VerifyContext(&context))
3287 alcSetError(NULL, ALC_INVALID_CONTEXT);
3288 return ALC_FALSE;
3290 /* context's reference count is already incremented */
3291 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3292 if(context) ALCcontext_DecRef(context);
3294 if((context=altss_get(LocalContext)) != NULL)
3296 altss_set(LocalContext, NULL);
3297 ALCcontext_DecRef(context);
3300 return ALC_TRUE;
3303 /* alcSetThreadContext
3305 * Makes the given context the active context for the current thread
3307 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3309 ALCcontext *old;
3311 /* context must be valid or NULL */
3312 if(context && !VerifyContext(&context))
3314 alcSetError(NULL, ALC_INVALID_CONTEXT);
3315 return ALC_FALSE;
3317 /* context's reference count is already incremented */
3318 old = altss_get(LocalContext);
3319 altss_set(LocalContext, context);
3320 if(old) ALCcontext_DecRef(old);
3322 return ALC_TRUE;
3326 /* alcGetContextsDevice
3328 * Returns the device that a particular context is attached to
3330 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3332 ALCdevice *Device;
3334 if(!VerifyContext(&Context))
3336 alcSetError(NULL, ALC_INVALID_CONTEXT);
3337 return NULL;
3339 Device = Context->Device;
3340 ALCcontext_DecRef(Context);
3342 return Device;
3346 /* alcOpenDevice
3348 * Opens the named device.
3350 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3352 const ALCchar *fmt;
3353 ALCdevice *device;
3354 ALCenum err;
3356 DO_INITCONFIG();
3358 if(!PlaybackBackend.name)
3360 alcSetError(NULL, ALC_INVALID_VALUE);
3361 return NULL;
3364 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3365 #ifdef _WIN32
3366 /* Some old Windows apps hardcode these expecting OpenAL to use a
3367 * specific audio API, even when they're not enumerated. Creative's
3368 * router effectively ignores them too.
3370 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3371 || strcasecmp(deviceName, "MMSYSTEM") == 0
3372 #endif
3374 deviceName = NULL;
3376 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3377 if(!device)
3379 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3380 return NULL;
3383 //Validate device
3384 InitRef(&device->ref, 1);
3385 device->Connected = ALC_TRUE;
3386 device->Type = Playback;
3387 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3389 device->Flags = 0;
3390 device->Bs2b = NULL;
3391 device->Uhj_Encoder = NULL;
3392 VECTOR_INIT(device->Hrtf_List);
3393 AL_STRING_INIT(device->Hrtf_Name);
3394 device->Render_Mode = NormalRender;
3395 AL_STRING_INIT(device->DeviceName);
3396 device->Dry.Buffer = NULL;
3397 device->Dry.NumChannels = 0;
3398 device->FOAOut.Buffer = NULL;
3399 device->FOAOut.NumChannels = 0;
3400 device->RealOut.Buffer = NULL;
3401 device->RealOut.NumChannels = 0;
3403 ATOMIC_INIT(&device->ContextList, NULL);
3405 device->ClockBase = 0;
3406 device->SamplesDone = 0;
3408 device->SourcesMax = 256;
3409 device->AuxiliaryEffectSlotMax = 4;
3410 device->NumAuxSends = MAX_SENDS;
3412 InitUIntMap(&device->BufferMap, ~0);
3413 InitUIntMap(&device->EffectMap, ~0);
3414 InitUIntMap(&device->FilterMap, ~0);
3416 //Set output format
3417 device->FmtChans = DevFmtChannelsDefault;
3418 device->FmtType = DevFmtTypeDefault;
3419 device->Frequency = DEFAULT_OUTPUT_RATE;
3420 device->IsHeadphones = AL_FALSE;
3421 device->AmbiFmt = AmbiFormat_Default;
3422 device->NumUpdates = 4;
3423 device->UpdateSize = 1024;
3425 if(!PlaybackBackend.getFactory)
3426 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3427 ALCbackend_Playback);
3428 else
3430 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3431 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3433 if(!device->Backend)
3435 al_free(device);
3436 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3437 return NULL;
3441 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3443 static const struct {
3444 const char name[16];
3445 enum DevFmtChannels chans;
3446 } chanlist[] = {
3447 { "mono", DevFmtMono },
3448 { "stereo", DevFmtStereo },
3449 { "quad", DevFmtQuad },
3450 { "surround51", DevFmtX51 },
3451 { "surround61", DevFmtX61 },
3452 { "surround71", DevFmtX71 },
3453 { "surround51rear", DevFmtX51Rear },
3454 { "ambi1", DevFmtAmbi1 },
3455 { "ambi2", DevFmtAmbi2 },
3456 { "ambi3", DevFmtAmbi3 },
3458 size_t i;
3460 for(i = 0;i < COUNTOF(chanlist);i++)
3462 if(strcasecmp(chanlist[i].name, fmt) == 0)
3464 device->FmtChans = chanlist[i].chans;
3465 device->Flags |= DEVICE_CHANNELS_REQUEST;
3466 break;
3469 if(i == COUNTOF(chanlist))
3470 ERR("Unsupported channels: %s\n", fmt);
3472 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3474 static const struct {
3475 const char name[16];
3476 enum DevFmtType type;
3477 } typelist[] = {
3478 { "int8", DevFmtByte },
3479 { "uint8", DevFmtUByte },
3480 { "int16", DevFmtShort },
3481 { "uint16", DevFmtUShort },
3482 { "int32", DevFmtInt },
3483 { "uint32", DevFmtUInt },
3484 { "float32", DevFmtFloat },
3486 size_t i;
3488 for(i = 0;i < COUNTOF(typelist);i++)
3490 if(strcasecmp(typelist[i].name, fmt) == 0)
3492 device->FmtType = typelist[i].type;
3493 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3494 break;
3497 if(i == COUNTOF(typelist))
3498 ERR("Unsupported sample-type: %s\n", fmt);
3501 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3503 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3504 if(device->Frequency < MIN_OUTPUT_RATE)
3505 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3506 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3509 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3510 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3512 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3513 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3514 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3515 device->UpdateSize = (device->UpdateSize+3)&~3;
3517 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3518 if(device->SourcesMax == 0) device->SourcesMax = 256;
3520 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3521 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3523 ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends);
3524 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3526 device->NumStereoSources = 1;
3527 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3529 // Find a playback device to open
3530 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3532 DELETE_OBJ(device->Backend);
3533 al_free(device);
3534 alcSetError(NULL, err);
3535 return NULL;
3537 almtx_init(&device->BackendLock, almtx_plain);
3539 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3541 if(strcasecmp(fmt, "fuma") == 0)
3542 device->AmbiFmt = AmbiFormat_FuMa;
3543 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3544 device->AmbiFmt = AmbiFormat_ACN_SN3D;
3545 else if(strcasecmp(fmt, "acn+n3d") == 0)
3546 device->AmbiFmt = AmbiFormat_ACN_N3D;
3547 else
3548 ERR("Unsupported ambi-format: %s\n", fmt);
3551 if(DefaultEffect.type != AL_EFFECT_NULL)
3553 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3554 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3556 device->DefaultSlot = NULL;
3557 ERR("Failed to initialize the default effect slot\n");
3559 else
3561 aluInitEffectPanning(device->DefaultSlot);
3562 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3564 DeinitEffectSlot(device->DefaultSlot);
3565 device->DefaultSlot = NULL;
3566 ERR("Failed to initialize the default effect\n");
3572 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3573 do {
3574 device->next = head;
3575 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3578 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3579 return device;
3582 /* alcCloseDevice
3584 * Closes the given device.
3586 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3588 ALCdevice *list, *origdev, *nextdev;
3589 ALCcontext *ctx;
3591 LockLists();
3592 list = ATOMIC_LOAD(&DeviceList);
3593 do {
3594 if(list == device)
3595 break;
3596 } while((list=list->next) != NULL);
3597 if(!list || list->Type == Capture)
3599 alcSetError(list, ALC_INVALID_DEVICE);
3600 UnlockLists();
3601 return ALC_FALSE;
3603 almtx_lock(&device->BackendLock);
3605 origdev = device;
3606 nextdev = device->next;
3607 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3609 do {
3610 list = origdev;
3611 origdev = device;
3612 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3614 UnlockLists();
3616 ctx = ATOMIC_LOAD(&device->ContextList);
3617 while(ctx != NULL)
3619 ALCcontext *next = ctx->next;
3620 WARN("Releasing context %p\n", ctx);
3621 ReleaseContext(ctx, device);
3622 ctx = next;
3624 if((device->Flags&DEVICE_RUNNING))
3625 V0(device->Backend,stop)();
3626 device->Flags &= ~DEVICE_RUNNING;
3627 almtx_unlock(&device->BackendLock);
3629 ALCdevice_DecRef(device);
3631 return ALC_TRUE;
3635 /************************************************
3636 * ALC capture functions
3637 ************************************************/
3638 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3640 ALCdevice *device = NULL;
3641 ALCenum err;
3643 DO_INITCONFIG();
3645 if(!CaptureBackend.name)
3647 alcSetError(NULL, ALC_INVALID_VALUE);
3648 return NULL;
3651 if(samples <= 0)
3653 alcSetError(NULL, ALC_INVALID_VALUE);
3654 return NULL;
3657 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3658 deviceName = NULL;
3660 device = al_calloc(16, sizeof(ALCdevice));
3661 if(!device)
3663 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3664 return NULL;
3667 //Validate device
3668 InitRef(&device->ref, 1);
3669 device->Connected = ALC_TRUE;
3670 device->Type = Capture;
3672 VECTOR_INIT(device->Hrtf_List);
3673 AL_STRING_INIT(device->Hrtf_Name);
3675 AL_STRING_INIT(device->DeviceName);
3676 device->Dry.Buffer = NULL;
3677 device->Dry.NumChannels = 0;
3678 device->FOAOut.Buffer = NULL;
3679 device->FOAOut.NumChannels = 0;
3680 device->RealOut.Buffer = NULL;
3681 device->RealOut.NumChannels = 0;
3683 InitUIntMap(&device->BufferMap, ~0);
3684 InitUIntMap(&device->EffectMap, ~0);
3685 InitUIntMap(&device->FilterMap, ~0);
3687 if(!CaptureBackend.getFactory)
3688 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3689 ALCbackend_Capture);
3690 else
3692 ALCbackendFactory *factory = CaptureBackend.getFactory();
3693 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3695 if(!device->Backend)
3697 al_free(device);
3698 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3699 return NULL;
3702 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3703 device->Frequency = frequency;
3705 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3706 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3708 al_free(device);
3709 alcSetError(NULL, ALC_INVALID_ENUM);
3710 return NULL;
3712 device->IsHeadphones = AL_FALSE;
3713 device->AmbiFmt = AmbiFormat_Default;
3715 device->UpdateSize = samples;
3716 device->NumUpdates = 1;
3718 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3720 al_free(device);
3721 alcSetError(NULL, err);
3722 return NULL;
3724 almtx_init(&device->BackendLock, almtx_plain);
3727 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3728 do {
3729 device->next = head;
3730 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3733 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3734 return device;
3737 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3739 ALCdevice *list, *next, *nextdev;
3741 LockLists();
3742 list = ATOMIC_LOAD(&DeviceList);
3743 do {
3744 if(list == device)
3745 break;
3746 } while((list=list->next) != NULL);
3747 if(!list || list->Type != Capture)
3749 alcSetError(list, ALC_INVALID_DEVICE);
3750 UnlockLists();
3751 return ALC_FALSE;
3754 next = device;
3755 nextdev = device->next;
3756 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3758 do {
3759 list = next;
3760 next = device;
3761 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3763 UnlockLists();
3765 ALCdevice_DecRef(device);
3767 return ALC_TRUE;
3770 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3772 if(!VerifyDevice(&device) || device->Type != Capture)
3773 alcSetError(device, ALC_INVALID_DEVICE);
3774 else
3776 almtx_lock(&device->BackendLock);
3777 if(!device->Connected)
3778 alcSetError(device, ALC_INVALID_DEVICE);
3779 else if(!(device->Flags&DEVICE_RUNNING))
3781 if(V0(device->Backend,start)())
3782 device->Flags |= DEVICE_RUNNING;
3783 else
3785 aluHandleDisconnect(device);
3786 alcSetError(device, ALC_INVALID_DEVICE);
3789 almtx_unlock(&device->BackendLock);
3792 if(device) ALCdevice_DecRef(device);
3795 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3797 if(!VerifyDevice(&device) || device->Type != Capture)
3798 alcSetError(device, ALC_INVALID_DEVICE);
3799 else
3801 almtx_lock(&device->BackendLock);
3802 if((device->Flags&DEVICE_RUNNING))
3803 V0(device->Backend,stop)();
3804 device->Flags &= ~DEVICE_RUNNING;
3805 almtx_unlock(&device->BackendLock);
3808 if(device) ALCdevice_DecRef(device);
3811 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3813 if(!VerifyDevice(&device) || device->Type != Capture)
3814 alcSetError(device, ALC_INVALID_DEVICE);
3815 else
3817 ALCenum err = ALC_INVALID_VALUE;
3819 almtx_lock(&device->BackendLock);
3820 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3821 err = V(device->Backend,captureSamples)(buffer, samples);
3822 almtx_unlock(&device->BackendLock);
3824 if(err != ALC_NO_ERROR)
3825 alcSetError(device, err);
3827 if(device) ALCdevice_DecRef(device);
3831 /************************************************
3832 * ALC loopback functions
3833 ************************************************/
3835 /* alcLoopbackOpenDeviceSOFT
3837 * Open a loopback device, for manual rendering.
3839 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3841 ALCbackendFactory *factory;
3842 ALCdevice *device;
3844 DO_INITCONFIG();
3846 /* Make sure the device name, if specified, is us. */
3847 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3849 alcSetError(NULL, ALC_INVALID_VALUE);
3850 return NULL;
3853 device = al_calloc(16, sizeof(ALCdevice));
3854 if(!device)
3856 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3857 return NULL;
3860 //Validate device
3861 InitRef(&device->ref, 1);
3862 device->Connected = ALC_TRUE;
3863 device->Type = Loopback;
3864 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3866 device->Flags = 0;
3867 VECTOR_INIT(device->Hrtf_List);
3868 AL_STRING_INIT(device->Hrtf_Name);
3869 device->Bs2b = NULL;
3870 device->Uhj_Encoder = NULL;
3871 device->Render_Mode = NormalRender;
3872 AL_STRING_INIT(device->DeviceName);
3873 device->Dry.Buffer = NULL;
3874 device->Dry.NumChannels = 0;
3875 device->FOAOut.Buffer = NULL;
3876 device->FOAOut.NumChannels = 0;
3877 device->RealOut.Buffer = NULL;
3878 device->RealOut.NumChannels = 0;
3880 ATOMIC_INIT(&device->ContextList, NULL);
3882 device->ClockBase = 0;
3883 device->SamplesDone = 0;
3885 device->SourcesMax = 256;
3886 device->AuxiliaryEffectSlotMax = 4;
3887 device->NumAuxSends = MAX_SENDS;
3889 InitUIntMap(&device->BufferMap, ~0);
3890 InitUIntMap(&device->EffectMap, ~0);
3891 InitUIntMap(&device->FilterMap, ~0);
3893 factory = ALCloopbackFactory_getFactory();
3894 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3895 if(!device->Backend)
3897 al_free(device);
3898 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3899 return NULL;
3901 almtx_init(&device->BackendLock, almtx_plain);
3903 //Set output format
3904 device->NumUpdates = 0;
3905 device->UpdateSize = 0;
3907 device->Frequency = DEFAULT_OUTPUT_RATE;
3908 device->FmtChans = DevFmtChannelsDefault;
3909 device->FmtType = DevFmtTypeDefault;
3910 device->IsHeadphones = AL_FALSE;
3911 device->AmbiFmt = AmbiFormat_Default;
3913 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
3914 if(device->SourcesMax == 0) device->SourcesMax = 256;
3916 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3917 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3919 ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends);
3920 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3922 device->NumStereoSources = 1;
3923 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3925 // Open the "backend"
3926 V(device->Backend,open)("Loopback");
3929 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3930 do {
3931 device->next = head;
3932 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3935 TRACE("Created device %p\n", device);
3936 return device;
3939 /* alcIsRenderFormatSupportedSOFT
3941 * Determines if the loopback device supports the given format for rendering.
3943 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3945 ALCboolean ret = ALC_FALSE;
3947 if(!VerifyDevice(&device) || device->Type != Loopback)
3948 alcSetError(device, ALC_INVALID_DEVICE);
3949 else if(freq <= 0)
3950 alcSetError(device, ALC_INVALID_VALUE);
3951 else
3953 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3954 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3955 freq >= MIN_OUTPUT_RATE)
3956 ret = ALC_TRUE;
3958 if(device) ALCdevice_DecRef(device);
3960 return ret;
3963 /* alcRenderSamplesSOFT
3965 * Renders some samples into a buffer, using the format last set by the
3966 * attributes given to alcCreateContext.
3968 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3970 if(!VerifyDevice(&device) || device->Type != Loopback)
3971 alcSetError(device, ALC_INVALID_DEVICE);
3972 else if(samples < 0 || (samples > 0 && buffer == NULL))
3973 alcSetError(device, ALC_INVALID_VALUE);
3974 else
3975 aluMixData(device, buffer, samples);
3976 if(device) ALCdevice_DecRef(device);
3980 /************************************************
3981 * ALC DSP pause/resume functions
3982 ************************************************/
3984 /* alcDevicePauseSOFT
3986 * Pause the DSP to stop audio processing.
3988 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3990 if(!VerifyDevice(&device) || device->Type != Playback)
3991 alcSetError(device, ALC_INVALID_DEVICE);
3992 else
3994 almtx_lock(&device->BackendLock);
3995 if((device->Flags&DEVICE_RUNNING))
3996 V0(device->Backend,stop)();
3997 device->Flags &= ~DEVICE_RUNNING;
3998 device->Flags |= DEVICE_PAUSED;
3999 almtx_unlock(&device->BackendLock);
4001 if(device) ALCdevice_DecRef(device);
4004 /* alcDeviceResumeSOFT
4006 * Resume the DSP to restart audio processing.
4008 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4010 if(!VerifyDevice(&device) || device->Type != Playback)
4011 alcSetError(device, ALC_INVALID_DEVICE);
4012 else
4014 almtx_lock(&device->BackendLock);
4015 if((device->Flags&DEVICE_PAUSED))
4017 device->Flags &= ~DEVICE_PAUSED;
4018 if(ATOMIC_LOAD(&device->ContextList) != NULL)
4020 if(V0(device->Backend,start)() != ALC_FALSE)
4021 device->Flags |= DEVICE_RUNNING;
4022 else
4024 alcSetError(device, ALC_INVALID_DEVICE);
4025 V0(device->Backend,lock)();
4026 aluHandleDisconnect(device);
4027 V0(device->Backend,unlock)();
4031 almtx_unlock(&device->BackendLock);
4033 if(device) ALCdevice_DecRef(device);
4037 /************************************************
4038 * ALC HRTF functions
4039 ************************************************/
4041 /* alcGetStringiSOFT
4043 * Gets a string parameter at the given index.
4045 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4047 const ALCchar *str = NULL;
4049 if(!VerifyDevice(&device) || device->Type == Capture)
4050 alcSetError(device, ALC_INVALID_DEVICE);
4051 else switch(paramName)
4053 case ALC_HRTF_SPECIFIER_SOFT:
4054 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf_List))
4055 str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf_List, index).name);
4056 else
4057 alcSetError(device, ALC_INVALID_VALUE);
4058 break;
4060 default:
4061 alcSetError(device, ALC_INVALID_ENUM);
4062 break;
4064 if(device) ALCdevice_DecRef(device);
4066 return str;
4069 /* alcResetDeviceSOFT
4071 * Resets the given device output, using the specified attribute list.
4073 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4075 ALCenum err;
4077 LockLists();
4078 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4080 UnlockLists();
4081 alcSetError(device, ALC_INVALID_DEVICE);
4082 if(device) ALCdevice_DecRef(device);
4083 return ALC_FALSE;
4085 almtx_lock(&device->BackendLock);
4086 UnlockLists();
4088 err = UpdateDeviceParams(device, attribs);
4089 almtx_unlock(&device->BackendLock);
4091 if(err != ALC_NO_ERROR)
4093 alcSetError(device, err);
4094 if(err == ALC_INVALID_DEVICE)
4096 V0(device->Backend,lock)();
4097 aluHandleDisconnect(device);
4098 V0(device->Backend,unlock)();
4100 ALCdevice_DecRef(device);
4101 return ALC_FALSE;
4103 ALCdevice_DecRef(device);
4105 return ALC_TRUE;