Add methods to clean up althrd and altss data
[openal-soft.git] / Alc / ALc.c
blobeee17768e43b75689baf379a349739f18ca59b76
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 "version.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "mastering.h"
40 #include "bformatdec.h"
41 #include "alu.h"
42 #include "alconfig.h"
43 #include "ringbuffer.h"
45 #include "fpu_modes.h"
46 #include "cpu_caps.h"
47 #include "compat.h"
48 #include "threads.h"
49 #include "alstring.h"
50 #include "almalloc.h"
52 #include "backends/base.h"
55 /************************************************
56 * Backends
57 ************************************************/
58 struct BackendInfo {
59 const char *name;
60 ALCbackendFactory* (*getFactory)(void);
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_JACK
65 { "jack", ALCjackBackendFactory_getFactory },
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory },
69 #endif
70 #ifdef HAVE_ALSA
71 { "alsa", ALCalsaBackendFactory_getFactory },
72 #endif
73 #ifdef HAVE_COREAUDIO
74 { "core", ALCcoreAudioBackendFactory_getFactory },
75 #endif
76 #ifdef HAVE_OSS
77 { "oss", ALCossBackendFactory_getFactory },
78 #endif
79 #ifdef HAVE_SOLARIS
80 { "solaris", ALCsolarisBackendFactory_getFactory },
81 #endif
82 #ifdef HAVE_SNDIO
83 { "sndio", ALCsndioBackendFactory_getFactory },
84 #endif
85 #ifdef HAVE_QSA
86 { "qsa", ALCqsaBackendFactory_getFactory },
87 #endif
88 #ifdef HAVE_WASAPI
89 { "wasapi", ALCwasapiBackendFactory_getFactory },
90 #endif
91 #ifdef HAVE_DSOUND
92 { "dsound", ALCdsoundBackendFactory_getFactory },
93 #endif
94 #ifdef HAVE_WINMM
95 { "winmm", ALCwinmmBackendFactory_getFactory },
96 #endif
97 #ifdef HAVE_PORTAUDIO
98 { "port", ALCportBackendFactory_getFactory },
99 #endif
100 #ifdef HAVE_OPENSL
101 { "opensl", ALCopenslBackendFactory_getFactory },
102 #endif
103 #ifdef HAVE_SDL2
104 { "sdl2", ALCsdl2BackendFactory_getFactory },
105 #endif
107 { "null", ALCnullBackendFactory_getFactory },
108 #ifdef HAVE_WAVE
109 { "wave", ALCwaveBackendFactory_getFactory },
110 #endif
112 static ALsizei BackendListSize = COUNTOF(BackendList);
113 #undef EmptyFuncs
115 static struct BackendInfo PlaybackBackend;
116 static struct BackendInfo CaptureBackend;
119 /************************************************
120 * Functions, enums, and errors
121 ************************************************/
122 #define DECL(x) { #x, (ALCvoid*)(x) }
123 static const struct {
124 const ALCchar *funcName;
125 ALCvoid *address;
126 } alcFunctions[] = {
127 DECL(alcCreateContext),
128 DECL(alcMakeContextCurrent),
129 DECL(alcProcessContext),
130 DECL(alcSuspendContext),
131 DECL(alcDestroyContext),
132 DECL(alcGetCurrentContext),
133 DECL(alcGetContextsDevice),
134 DECL(alcOpenDevice),
135 DECL(alcCloseDevice),
136 DECL(alcGetError),
137 DECL(alcIsExtensionPresent),
138 DECL(alcGetProcAddress),
139 DECL(alcGetEnumValue),
140 DECL(alcGetString),
141 DECL(alcGetIntegerv),
142 DECL(alcCaptureOpenDevice),
143 DECL(alcCaptureCloseDevice),
144 DECL(alcCaptureStart),
145 DECL(alcCaptureStop),
146 DECL(alcCaptureSamples),
148 DECL(alcSetThreadContext),
149 DECL(alcGetThreadContext),
151 DECL(alcLoopbackOpenDeviceSOFT),
152 DECL(alcIsRenderFormatSupportedSOFT),
153 DECL(alcRenderSamplesSOFT),
155 DECL(alcDevicePauseSOFT),
156 DECL(alcDeviceResumeSOFT),
158 DECL(alcGetStringiSOFT),
159 DECL(alcResetDeviceSOFT),
161 DECL(alcGetInteger64vSOFT),
163 DECL(alEnable),
164 DECL(alDisable),
165 DECL(alIsEnabled),
166 DECL(alGetString),
167 DECL(alGetBooleanv),
168 DECL(alGetIntegerv),
169 DECL(alGetFloatv),
170 DECL(alGetDoublev),
171 DECL(alGetBoolean),
172 DECL(alGetInteger),
173 DECL(alGetFloat),
174 DECL(alGetDouble),
175 DECL(alGetError),
176 DECL(alIsExtensionPresent),
177 DECL(alGetProcAddress),
178 DECL(alGetEnumValue),
179 DECL(alListenerf),
180 DECL(alListener3f),
181 DECL(alListenerfv),
182 DECL(alListeneri),
183 DECL(alListener3i),
184 DECL(alListeneriv),
185 DECL(alGetListenerf),
186 DECL(alGetListener3f),
187 DECL(alGetListenerfv),
188 DECL(alGetListeneri),
189 DECL(alGetListener3i),
190 DECL(alGetListeneriv),
191 DECL(alGenSources),
192 DECL(alDeleteSources),
193 DECL(alIsSource),
194 DECL(alSourcef),
195 DECL(alSource3f),
196 DECL(alSourcefv),
197 DECL(alSourcei),
198 DECL(alSource3i),
199 DECL(alSourceiv),
200 DECL(alGetSourcef),
201 DECL(alGetSource3f),
202 DECL(alGetSourcefv),
203 DECL(alGetSourcei),
204 DECL(alGetSource3i),
205 DECL(alGetSourceiv),
206 DECL(alSourcePlayv),
207 DECL(alSourceStopv),
208 DECL(alSourceRewindv),
209 DECL(alSourcePausev),
210 DECL(alSourcePlay),
211 DECL(alSourceStop),
212 DECL(alSourceRewind),
213 DECL(alSourcePause),
214 DECL(alSourceQueueBuffers),
215 DECL(alSourceUnqueueBuffers),
216 DECL(alGenBuffers),
217 DECL(alDeleteBuffers),
218 DECL(alIsBuffer),
219 DECL(alBufferData),
220 DECL(alBufferf),
221 DECL(alBuffer3f),
222 DECL(alBufferfv),
223 DECL(alBufferi),
224 DECL(alBuffer3i),
225 DECL(alBufferiv),
226 DECL(alGetBufferf),
227 DECL(alGetBuffer3f),
228 DECL(alGetBufferfv),
229 DECL(alGetBufferi),
230 DECL(alGetBuffer3i),
231 DECL(alGetBufferiv),
232 DECL(alDopplerFactor),
233 DECL(alDopplerVelocity),
234 DECL(alSpeedOfSound),
235 DECL(alDistanceModel),
237 DECL(alGenFilters),
238 DECL(alDeleteFilters),
239 DECL(alIsFilter),
240 DECL(alFilteri),
241 DECL(alFilteriv),
242 DECL(alFilterf),
243 DECL(alFilterfv),
244 DECL(alGetFilteri),
245 DECL(alGetFilteriv),
246 DECL(alGetFilterf),
247 DECL(alGetFilterfv),
248 DECL(alGenEffects),
249 DECL(alDeleteEffects),
250 DECL(alIsEffect),
251 DECL(alEffecti),
252 DECL(alEffectiv),
253 DECL(alEffectf),
254 DECL(alEffectfv),
255 DECL(alGetEffecti),
256 DECL(alGetEffectiv),
257 DECL(alGetEffectf),
258 DECL(alGetEffectfv),
259 DECL(alGenAuxiliaryEffectSlots),
260 DECL(alDeleteAuxiliaryEffectSlots),
261 DECL(alIsAuxiliaryEffectSlot),
262 DECL(alAuxiliaryEffectSloti),
263 DECL(alAuxiliaryEffectSlotiv),
264 DECL(alAuxiliaryEffectSlotf),
265 DECL(alAuxiliaryEffectSlotfv),
266 DECL(alGetAuxiliaryEffectSloti),
267 DECL(alGetAuxiliaryEffectSlotiv),
268 DECL(alGetAuxiliaryEffectSlotf),
269 DECL(alGetAuxiliaryEffectSlotfv),
271 DECL(alDeferUpdatesSOFT),
272 DECL(alProcessUpdatesSOFT),
274 DECL(alSourcedSOFT),
275 DECL(alSource3dSOFT),
276 DECL(alSourcedvSOFT),
277 DECL(alGetSourcedSOFT),
278 DECL(alGetSource3dSOFT),
279 DECL(alGetSourcedvSOFT),
280 DECL(alSourcei64SOFT),
281 DECL(alSource3i64SOFT),
282 DECL(alSourcei64vSOFT),
283 DECL(alGetSourcei64SOFT),
284 DECL(alGetSource3i64SOFT),
285 DECL(alGetSourcei64vSOFT),
287 DECL(alGetStringiSOFT),
289 DECL(alBufferStorageSOFT),
290 DECL(alMapBufferSOFT),
291 DECL(alUnmapBufferSOFT),
292 DECL(alFlushMappedBufferSOFT),
294 DECL(alEventControlSOFT),
295 DECL(alEventCallbackSOFT),
296 DECL(alGetPointerSOFT),
297 DECL(alGetPointervSOFT),
299 #undef DECL
301 #define DECL(x) { #x, (x) }
302 static const struct {
303 const ALCchar *enumName;
304 ALCenum value;
305 } alcEnumerations[] = {
306 DECL(ALC_INVALID),
307 DECL(ALC_FALSE),
308 DECL(ALC_TRUE),
310 DECL(ALC_MAJOR_VERSION),
311 DECL(ALC_MINOR_VERSION),
312 DECL(ALC_ATTRIBUTES_SIZE),
313 DECL(ALC_ALL_ATTRIBUTES),
314 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
315 DECL(ALC_DEVICE_SPECIFIER),
316 DECL(ALC_ALL_DEVICES_SPECIFIER),
317 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
318 DECL(ALC_EXTENSIONS),
319 DECL(ALC_FREQUENCY),
320 DECL(ALC_REFRESH),
321 DECL(ALC_SYNC),
322 DECL(ALC_MONO_SOURCES),
323 DECL(ALC_STEREO_SOURCES),
324 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
325 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
326 DECL(ALC_CAPTURE_SAMPLES),
327 DECL(ALC_CONNECTED),
329 DECL(ALC_EFX_MAJOR_VERSION),
330 DECL(ALC_EFX_MINOR_VERSION),
331 DECL(ALC_MAX_AUXILIARY_SENDS),
333 DECL(ALC_FORMAT_CHANNELS_SOFT),
334 DECL(ALC_FORMAT_TYPE_SOFT),
336 DECL(ALC_MONO_SOFT),
337 DECL(ALC_STEREO_SOFT),
338 DECL(ALC_QUAD_SOFT),
339 DECL(ALC_5POINT1_SOFT),
340 DECL(ALC_6POINT1_SOFT),
341 DECL(ALC_7POINT1_SOFT),
342 DECL(ALC_BFORMAT3D_SOFT),
344 DECL(ALC_BYTE_SOFT),
345 DECL(ALC_UNSIGNED_BYTE_SOFT),
346 DECL(ALC_SHORT_SOFT),
347 DECL(ALC_UNSIGNED_SHORT_SOFT),
348 DECL(ALC_INT_SOFT),
349 DECL(ALC_UNSIGNED_INT_SOFT),
350 DECL(ALC_FLOAT_SOFT),
352 DECL(ALC_HRTF_SOFT),
353 DECL(ALC_DONT_CARE_SOFT),
354 DECL(ALC_HRTF_STATUS_SOFT),
355 DECL(ALC_HRTF_DISABLED_SOFT),
356 DECL(ALC_HRTF_ENABLED_SOFT),
357 DECL(ALC_HRTF_DENIED_SOFT),
358 DECL(ALC_HRTF_REQUIRED_SOFT),
359 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
360 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
361 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
362 DECL(ALC_HRTF_SPECIFIER_SOFT),
363 DECL(ALC_HRTF_ID_SOFT),
365 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
366 DECL(ALC_AMBISONIC_SCALING_SOFT),
367 DECL(ALC_AMBISONIC_ORDER_SOFT),
368 DECL(ALC_ACN_SOFT),
369 DECL(ALC_FUMA_SOFT),
370 DECL(ALC_N3D_SOFT),
371 DECL(ALC_SN3D_SOFT),
373 DECL(ALC_OUTPUT_LIMITER_SOFT),
375 DECL(ALC_NO_ERROR),
376 DECL(ALC_INVALID_DEVICE),
377 DECL(ALC_INVALID_CONTEXT),
378 DECL(ALC_INVALID_ENUM),
379 DECL(ALC_INVALID_VALUE),
380 DECL(ALC_OUT_OF_MEMORY),
383 DECL(AL_INVALID),
384 DECL(AL_NONE),
385 DECL(AL_FALSE),
386 DECL(AL_TRUE),
388 DECL(AL_SOURCE_RELATIVE),
389 DECL(AL_CONE_INNER_ANGLE),
390 DECL(AL_CONE_OUTER_ANGLE),
391 DECL(AL_PITCH),
392 DECL(AL_POSITION),
393 DECL(AL_DIRECTION),
394 DECL(AL_VELOCITY),
395 DECL(AL_LOOPING),
396 DECL(AL_BUFFER),
397 DECL(AL_GAIN),
398 DECL(AL_MIN_GAIN),
399 DECL(AL_MAX_GAIN),
400 DECL(AL_ORIENTATION),
401 DECL(AL_REFERENCE_DISTANCE),
402 DECL(AL_ROLLOFF_FACTOR),
403 DECL(AL_CONE_OUTER_GAIN),
404 DECL(AL_MAX_DISTANCE),
405 DECL(AL_SEC_OFFSET),
406 DECL(AL_SAMPLE_OFFSET),
407 DECL(AL_BYTE_OFFSET),
408 DECL(AL_SOURCE_TYPE),
409 DECL(AL_STATIC),
410 DECL(AL_STREAMING),
411 DECL(AL_UNDETERMINED),
412 DECL(AL_METERS_PER_UNIT),
413 DECL(AL_LOOP_POINTS_SOFT),
414 DECL(AL_DIRECT_CHANNELS_SOFT),
416 DECL(AL_DIRECT_FILTER),
417 DECL(AL_AUXILIARY_SEND_FILTER),
418 DECL(AL_AIR_ABSORPTION_FACTOR),
419 DECL(AL_ROOM_ROLLOFF_FACTOR),
420 DECL(AL_CONE_OUTER_GAINHF),
421 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
422 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
423 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
425 DECL(AL_SOURCE_STATE),
426 DECL(AL_INITIAL),
427 DECL(AL_PLAYING),
428 DECL(AL_PAUSED),
429 DECL(AL_STOPPED),
431 DECL(AL_BUFFERS_QUEUED),
432 DECL(AL_BUFFERS_PROCESSED),
434 DECL(AL_FORMAT_MONO8),
435 DECL(AL_FORMAT_MONO16),
436 DECL(AL_FORMAT_MONO_FLOAT32),
437 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
438 DECL(AL_FORMAT_STEREO8),
439 DECL(AL_FORMAT_STEREO16),
440 DECL(AL_FORMAT_STEREO_FLOAT32),
441 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
442 DECL(AL_FORMAT_MONO_IMA4),
443 DECL(AL_FORMAT_STEREO_IMA4),
444 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
445 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
446 DECL(AL_FORMAT_QUAD8_LOKI),
447 DECL(AL_FORMAT_QUAD16_LOKI),
448 DECL(AL_FORMAT_QUAD8),
449 DECL(AL_FORMAT_QUAD16),
450 DECL(AL_FORMAT_QUAD32),
451 DECL(AL_FORMAT_51CHN8),
452 DECL(AL_FORMAT_51CHN16),
453 DECL(AL_FORMAT_51CHN32),
454 DECL(AL_FORMAT_61CHN8),
455 DECL(AL_FORMAT_61CHN16),
456 DECL(AL_FORMAT_61CHN32),
457 DECL(AL_FORMAT_71CHN8),
458 DECL(AL_FORMAT_71CHN16),
459 DECL(AL_FORMAT_71CHN32),
460 DECL(AL_FORMAT_REAR8),
461 DECL(AL_FORMAT_REAR16),
462 DECL(AL_FORMAT_REAR32),
463 DECL(AL_FORMAT_MONO_MULAW),
464 DECL(AL_FORMAT_MONO_MULAW_EXT),
465 DECL(AL_FORMAT_STEREO_MULAW),
466 DECL(AL_FORMAT_STEREO_MULAW_EXT),
467 DECL(AL_FORMAT_QUAD_MULAW),
468 DECL(AL_FORMAT_51CHN_MULAW),
469 DECL(AL_FORMAT_61CHN_MULAW),
470 DECL(AL_FORMAT_71CHN_MULAW),
471 DECL(AL_FORMAT_REAR_MULAW),
472 DECL(AL_FORMAT_MONO_ALAW_EXT),
473 DECL(AL_FORMAT_STEREO_ALAW_EXT),
475 DECL(AL_FORMAT_BFORMAT2D_8),
476 DECL(AL_FORMAT_BFORMAT2D_16),
477 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
478 DECL(AL_FORMAT_BFORMAT2D_MULAW),
479 DECL(AL_FORMAT_BFORMAT3D_8),
480 DECL(AL_FORMAT_BFORMAT3D_16),
481 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
482 DECL(AL_FORMAT_BFORMAT3D_MULAW),
484 DECL(AL_FREQUENCY),
485 DECL(AL_BITS),
486 DECL(AL_CHANNELS),
487 DECL(AL_SIZE),
488 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
489 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
491 DECL(AL_SOURCE_RADIUS),
493 DECL(AL_STEREO_ANGLES),
495 DECL(AL_UNUSED),
496 DECL(AL_PENDING),
497 DECL(AL_PROCESSED),
499 DECL(AL_NO_ERROR),
500 DECL(AL_INVALID_NAME),
501 DECL(AL_INVALID_ENUM),
502 DECL(AL_INVALID_VALUE),
503 DECL(AL_INVALID_OPERATION),
504 DECL(AL_OUT_OF_MEMORY),
506 DECL(AL_VENDOR),
507 DECL(AL_VERSION),
508 DECL(AL_RENDERER),
509 DECL(AL_EXTENSIONS),
511 DECL(AL_DOPPLER_FACTOR),
512 DECL(AL_DOPPLER_VELOCITY),
513 DECL(AL_DISTANCE_MODEL),
514 DECL(AL_SPEED_OF_SOUND),
515 DECL(AL_SOURCE_DISTANCE_MODEL),
516 DECL(AL_DEFERRED_UPDATES_SOFT),
517 DECL(AL_GAIN_LIMIT_SOFT),
519 DECL(AL_INVERSE_DISTANCE),
520 DECL(AL_INVERSE_DISTANCE_CLAMPED),
521 DECL(AL_LINEAR_DISTANCE),
522 DECL(AL_LINEAR_DISTANCE_CLAMPED),
523 DECL(AL_EXPONENT_DISTANCE),
524 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
526 DECL(AL_FILTER_TYPE),
527 DECL(AL_FILTER_NULL),
528 DECL(AL_FILTER_LOWPASS),
529 DECL(AL_FILTER_HIGHPASS),
530 DECL(AL_FILTER_BANDPASS),
532 DECL(AL_LOWPASS_GAIN),
533 DECL(AL_LOWPASS_GAINHF),
535 DECL(AL_HIGHPASS_GAIN),
536 DECL(AL_HIGHPASS_GAINLF),
538 DECL(AL_BANDPASS_GAIN),
539 DECL(AL_BANDPASS_GAINHF),
540 DECL(AL_BANDPASS_GAINLF),
542 DECL(AL_EFFECT_TYPE),
543 DECL(AL_EFFECT_NULL),
544 DECL(AL_EFFECT_REVERB),
545 DECL(AL_EFFECT_EAXREVERB),
546 DECL(AL_EFFECT_CHORUS),
547 DECL(AL_EFFECT_DISTORTION),
548 DECL(AL_EFFECT_ECHO),
549 DECL(AL_EFFECT_FLANGER),
550 #if 0
551 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
552 DECL(AL_EFFECT_VOCAL_MORPHER),
553 DECL(AL_EFFECT_PITCH_SHIFTER),
554 #endif
555 DECL(AL_EFFECT_RING_MODULATOR),
556 #if 0
557 DECL(AL_EFFECT_AUTOWAH),
558 #endif
559 DECL(AL_EFFECT_COMPRESSOR),
560 DECL(AL_EFFECT_EQUALIZER),
561 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
562 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
564 DECL(AL_EFFECTSLOT_EFFECT),
565 DECL(AL_EFFECTSLOT_GAIN),
566 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
567 DECL(AL_EFFECTSLOT_NULL),
569 DECL(AL_EAXREVERB_DENSITY),
570 DECL(AL_EAXREVERB_DIFFUSION),
571 DECL(AL_EAXREVERB_GAIN),
572 DECL(AL_EAXREVERB_GAINHF),
573 DECL(AL_EAXREVERB_GAINLF),
574 DECL(AL_EAXREVERB_DECAY_TIME),
575 DECL(AL_EAXREVERB_DECAY_HFRATIO),
576 DECL(AL_EAXREVERB_DECAY_LFRATIO),
577 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
578 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
579 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
580 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
581 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
582 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
583 DECL(AL_EAXREVERB_ECHO_TIME),
584 DECL(AL_EAXREVERB_ECHO_DEPTH),
585 DECL(AL_EAXREVERB_MODULATION_TIME),
586 DECL(AL_EAXREVERB_MODULATION_DEPTH),
587 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
588 DECL(AL_EAXREVERB_HFREFERENCE),
589 DECL(AL_EAXREVERB_LFREFERENCE),
590 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
591 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
593 DECL(AL_REVERB_DENSITY),
594 DECL(AL_REVERB_DIFFUSION),
595 DECL(AL_REVERB_GAIN),
596 DECL(AL_REVERB_GAINHF),
597 DECL(AL_REVERB_DECAY_TIME),
598 DECL(AL_REVERB_DECAY_HFRATIO),
599 DECL(AL_REVERB_REFLECTIONS_GAIN),
600 DECL(AL_REVERB_REFLECTIONS_DELAY),
601 DECL(AL_REVERB_LATE_REVERB_GAIN),
602 DECL(AL_REVERB_LATE_REVERB_DELAY),
603 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
604 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
605 DECL(AL_REVERB_DECAY_HFLIMIT),
607 DECL(AL_CHORUS_WAVEFORM),
608 DECL(AL_CHORUS_PHASE),
609 DECL(AL_CHORUS_RATE),
610 DECL(AL_CHORUS_DEPTH),
611 DECL(AL_CHORUS_FEEDBACK),
612 DECL(AL_CHORUS_DELAY),
614 DECL(AL_DISTORTION_EDGE),
615 DECL(AL_DISTORTION_GAIN),
616 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
617 DECL(AL_DISTORTION_EQCENTER),
618 DECL(AL_DISTORTION_EQBANDWIDTH),
620 DECL(AL_ECHO_DELAY),
621 DECL(AL_ECHO_LRDELAY),
622 DECL(AL_ECHO_DAMPING),
623 DECL(AL_ECHO_FEEDBACK),
624 DECL(AL_ECHO_SPREAD),
626 DECL(AL_FLANGER_WAVEFORM),
627 DECL(AL_FLANGER_PHASE),
628 DECL(AL_FLANGER_RATE),
629 DECL(AL_FLANGER_DEPTH),
630 DECL(AL_FLANGER_FEEDBACK),
631 DECL(AL_FLANGER_DELAY),
633 DECL(AL_RING_MODULATOR_FREQUENCY),
634 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
635 DECL(AL_RING_MODULATOR_WAVEFORM),
637 DECL(AL_COMPRESSOR_ONOFF),
639 DECL(AL_EQUALIZER_LOW_GAIN),
640 DECL(AL_EQUALIZER_LOW_CUTOFF),
641 DECL(AL_EQUALIZER_MID1_GAIN),
642 DECL(AL_EQUALIZER_MID1_CENTER),
643 DECL(AL_EQUALIZER_MID1_WIDTH),
644 DECL(AL_EQUALIZER_MID2_GAIN),
645 DECL(AL_EQUALIZER_MID2_CENTER),
646 DECL(AL_EQUALIZER_MID2_WIDTH),
647 DECL(AL_EQUALIZER_HIGH_GAIN),
648 DECL(AL_EQUALIZER_HIGH_CUTOFF),
650 DECL(AL_DEDICATED_GAIN),
652 DECL(AL_NUM_RESAMPLERS_SOFT),
653 DECL(AL_DEFAULT_RESAMPLER_SOFT),
654 DECL(AL_SOURCE_RESAMPLER_SOFT),
655 DECL(AL_RESAMPLER_NAME_SOFT),
657 DECL(AL_SOURCE_SPATIALIZE_SOFT),
658 DECL(AL_AUTO_SOFT),
660 DECL(AL_MAP_READ_BIT_SOFT),
661 DECL(AL_MAP_WRITE_BIT_SOFT),
662 DECL(AL_MAP_PERSISTENT_BIT_SOFT),
663 DECL(AL_PRESERVE_DATA_BIT_SOFT),
665 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT),
666 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT),
667 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT),
668 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT),
669 DECL(AL_EVENT_TYPE_ERROR_SOFT),
670 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT),
671 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT),
673 #undef DECL
675 static const ALCchar alcNoError[] = "No Error";
676 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
677 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
678 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
679 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
680 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
683 /************************************************
684 * Global variables
685 ************************************************/
687 /* Enumerated device names */
688 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
690 static al_string alcAllDevicesList;
691 static al_string alcCaptureDeviceList;
693 /* Default is always the first in the list */
694 static ALCchar *alcDefaultAllDevicesSpecifier;
695 static ALCchar *alcCaptureDefaultDeviceSpecifier;
697 /* Default context extensions */
698 static const ALchar alExtList[] =
699 "AL_EXT_ALAW "
700 "AL_EXT_BFORMAT "
701 "AL_EXT_DOUBLE "
702 "AL_EXT_EXPONENT_DISTANCE "
703 "AL_EXT_FLOAT32 "
704 "AL_EXT_IMA4 "
705 "AL_EXT_LINEAR_DISTANCE "
706 "AL_EXT_MCFORMATS "
707 "AL_EXT_MULAW "
708 "AL_EXT_MULAW_BFORMAT "
709 "AL_EXT_MULAW_MCFORMATS "
710 "AL_EXT_OFFSET "
711 "AL_EXT_source_distance_model "
712 "AL_EXT_SOURCE_RADIUS "
713 "AL_EXT_STEREO_ANGLES "
714 "AL_LOKI_quadriphonic "
715 "AL_SOFT_block_alignment "
716 "AL_SOFT_deferred_updates "
717 "AL_SOFT_direct_channels "
718 "AL_SOFTX_events "
719 "AL_SOFT_gain_clamp_ex "
720 "AL_SOFT_loop_points "
721 "AL_SOFTX_map_buffer "
722 "AL_SOFT_MSADPCM "
723 "AL_SOFT_source_latency "
724 "AL_SOFT_source_length "
725 "AL_SOFT_source_resampler "
726 "AL_SOFT_source_spatialize";
728 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
730 /* Thread-local current context */
731 static altss_t LocalContext;
732 /* Process-wide current context */
733 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
735 /* Mixing thread piority level */
736 ALint RTPrioLevel;
738 FILE *LogFile;
739 #ifdef _DEBUG
740 enum LogLevel LogLevel = LogWarning;
741 #else
742 enum LogLevel LogLevel = LogError;
743 #endif
745 /* Flag to trap ALC device errors */
746 static ALCboolean TrapALCError = ALC_FALSE;
748 /* One-time configuration init control */
749 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
751 /* Default effect that applies to sources that don't have an effect on send 0 */
752 static ALeffect DefaultEffect;
754 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
755 * updates.
757 static ALCboolean SuspendDefers = ALC_TRUE;
760 /************************************************
761 * ALC information
762 ************************************************/
763 static const ALCchar alcNoDeviceExtList[] =
764 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
765 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
766 static const ALCchar alcExtensionList[] =
767 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
768 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
769 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
770 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
771 static const ALCint alcMajorVersion = 1;
772 static const ALCint alcMinorVersion = 1;
774 static const ALCint alcEFXMajorVersion = 1;
775 static const ALCint alcEFXMinorVersion = 0;
778 /************************************************
779 * Device lists
780 ************************************************/
781 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
783 static almtx_t ListLock;
784 static inline void LockLists(void)
786 int ret = almtx_lock(&ListLock);
787 assert(ret == althrd_success);
789 static inline void UnlockLists(void)
791 int ret = almtx_unlock(&ListLock);
792 assert(ret == althrd_success);
795 /************************************************
796 * Library initialization
797 ************************************************/
798 #if defined(_WIN32)
799 static void alc_init(void);
800 static void alc_deinit(void);
801 static void alc_deinit_safe(void);
803 #ifndef AL_LIBTYPE_STATIC
804 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
806 switch(reason)
808 case DLL_PROCESS_ATTACH:
809 /* Pin the DLL so we won't get unloaded until the process terminates */
810 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
811 (WCHAR*)hModule, &hModule);
812 alc_init();
813 break;
815 case DLL_THREAD_DETACH:
816 althrd_thread_detach();
817 break;
819 case DLL_PROCESS_DETACH:
820 if(!lpReserved)
821 alc_deinit();
822 else
823 alc_deinit_safe();
824 break;
826 return TRUE;
828 #elif defined(_MSC_VER)
829 #pragma section(".CRT$XCU",read)
830 static void alc_constructor(void);
831 static void alc_destructor(void);
832 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
834 static void alc_constructor(void)
836 atexit(alc_destructor);
837 alc_init();
840 static void alc_destructor(void)
842 alc_deinit();
844 #elif defined(HAVE_GCC_DESTRUCTOR)
845 static void alc_init(void) __attribute__((constructor));
846 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No static initialization available on this platform!"
849 #endif
851 #elif defined(HAVE_GCC_DESTRUCTOR)
853 static void alc_init(void) __attribute__((constructor));
854 static void alc_deinit(void) __attribute__((destructor));
856 #else
857 #error "No global initialization available on this platform!"
858 #endif
860 static void ReleaseThreadCtx(void *ptr);
861 static void alc_init(void)
863 const char *str;
864 int ret;
866 LogFile = stderr;
868 AL_STRING_INIT(alcAllDevicesList);
869 AL_STRING_INIT(alcCaptureDeviceList);
871 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
872 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
873 ConeScale *= 0.5f;
875 str = getenv("__ALSOFT_REVERSE_Z");
876 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
877 ZScale *= -1.0f;
879 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
880 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
881 OverrideReverbSpeedOfSound = AL_TRUE;
883 ret = altss_create(&LocalContext, ReleaseThreadCtx);
884 assert(ret == althrd_success);
886 ret = almtx_init(&ListLock, almtx_recursive);
887 assert(ret == althrd_success);
890 static void alc_initconfig(void)
892 const char *devs, *str;
893 int capfilter;
894 float valf;
895 int i, n;
897 str = getenv("ALSOFT_LOGLEVEL");
898 if(str)
900 long lvl = strtol(str, NULL, 0);
901 if(lvl >= NoLog && lvl <= LogRef)
902 LogLevel = lvl;
905 str = getenv("ALSOFT_LOGFILE");
906 if(str && str[0])
908 FILE *logfile = al_fopen(str, "wt");
909 if(logfile) LogFile = logfile;
910 else ERR("Failed to open log file '%s'\n", str);
913 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
914 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
916 char buf[1024] = "";
917 int len = 0;
919 if(BackendListSize > 0)
920 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
921 for(i = 1;i < BackendListSize;i++)
922 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
923 TRACE("Supported backends: %s\n", buf);
925 ReadALConfig();
927 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
928 if(str && *str)
930 if(strcasecmp(str, "ignore") == 0)
932 SuspendDefers = ALC_FALSE;
933 TRACE("Selected context suspend behavior, \"ignore\"\n");
935 else
936 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
939 capfilter = 0;
940 #if defined(HAVE_SSE4_1)
941 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
942 #elif defined(HAVE_SSE3)
943 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
944 #elif defined(HAVE_SSE2)
945 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
946 #elif defined(HAVE_SSE)
947 capfilter |= CPU_CAP_SSE;
948 #endif
949 #ifdef HAVE_NEON
950 capfilter |= CPU_CAP_NEON;
951 #endif
952 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
954 if(strcasecmp(str, "all") == 0)
955 capfilter = 0;
956 else
958 size_t len;
959 const char *next = str;
961 do {
962 str = next;
963 while(isspace(str[0]))
964 str++;
965 next = strchr(str, ',');
967 if(!str[0] || str[0] == ',')
968 continue;
970 len = (next ? ((size_t)(next-str)) : strlen(str));
971 while(len > 0 && isspace(str[len-1]))
972 len--;
973 if(len == 3 && strncasecmp(str, "sse", len) == 0)
974 capfilter &= ~CPU_CAP_SSE;
975 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
976 capfilter &= ~CPU_CAP_SSE2;
977 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
978 capfilter &= ~CPU_CAP_SSE3;
979 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
980 capfilter &= ~CPU_CAP_SSE4_1;
981 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
982 capfilter &= ~CPU_CAP_NEON;
983 else
984 WARN("Invalid CPU extension \"%s\"\n", str);
985 } while(next++);
988 FillCPUCaps(capfilter);
990 #ifdef _WIN32
991 RTPrioLevel = 1;
992 #else
993 RTPrioLevel = 0;
994 #endif
995 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
997 aluInit();
998 aluInitMixer();
1000 str = getenv("ALSOFT_TRAP_ERROR");
1001 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1003 TrapALError = AL_TRUE;
1004 TrapALCError = AL_TRUE;
1006 else
1008 str = getenv("ALSOFT_TRAP_AL_ERROR");
1009 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1010 TrapALError = AL_TRUE;
1011 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1013 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1014 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1015 TrapALCError = ALC_TRUE;
1016 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1019 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1020 ReverbBoost *= powf(10.0f, valf / 20.0f);
1022 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1023 ConfigValueStr(NULL, NULL, "drivers", &devs))
1025 int n;
1026 size_t len;
1027 const char *next = devs;
1028 int endlist, delitem;
1030 i = 0;
1031 do {
1032 devs = next;
1033 while(isspace(devs[0]))
1034 devs++;
1035 next = strchr(devs, ',');
1037 delitem = (devs[0] == '-');
1038 if(devs[0] == '-') devs++;
1040 if(!devs[0] || devs[0] == ',')
1042 endlist = 0;
1043 continue;
1045 endlist = 1;
1047 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1048 while(len > 0 && isspace(devs[len-1]))
1049 len--;
1050 #ifdef HAVE_WASAPI
1051 /* HACK: For backwards compatibility, convert backend references of
1052 * mmdevapi to wasapi. This should eventually be removed.
1054 if(len == 8 && strncmp(devs, "mmdevapi", len) == 0)
1056 devs = "wasapi";
1057 len = 6;
1059 #endif
1060 for(n = i;n < BackendListSize;n++)
1062 if(len == strlen(BackendList[n].name) &&
1063 strncmp(BackendList[n].name, devs, len) == 0)
1065 if(delitem)
1067 for(;n+1 < BackendListSize;n++)
1068 BackendList[n] = BackendList[n+1];
1069 BackendListSize--;
1071 else
1073 struct BackendInfo Bkp = BackendList[n];
1074 for(;n > i;n--)
1075 BackendList[n] = BackendList[n-1];
1076 BackendList[n] = Bkp;
1078 i++;
1080 break;
1083 } while(next++);
1085 if(endlist)
1086 BackendListSize = i;
1089 for(n = i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1091 ALCbackendFactory *factory;
1092 BackendList[n] = BackendList[i];
1094 factory = BackendList[n].getFactory();
1095 if(!V0(factory,init)())
1097 WARN("Failed to initialize backend \"%s\"\n", BackendList[n].name);
1098 continue;
1101 TRACE("Initialized backend \"%s\"\n", BackendList[n].name);
1102 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1104 PlaybackBackend = BackendList[n];
1105 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1107 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1109 CaptureBackend = BackendList[n];
1110 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1112 n++;
1114 BackendListSize = n;
1117 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1118 V0(factory,init)();
1121 if(!PlaybackBackend.name)
1122 WARN("No playback backend available!\n");
1123 if(!CaptureBackend.name)
1124 WARN("No capture backend available!\n");
1126 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1128 size_t len;
1129 const char *next = str;
1131 do {
1132 str = next;
1133 next = strchr(str, ',');
1135 if(!str[0] || next == str)
1136 continue;
1138 len = (next ? ((size_t)(next-str)) : strlen(str));
1139 for(n = 0;n < EFFECTLIST_SIZE;n++)
1141 if(len == strlen(EffectList[n].name) &&
1142 strncmp(EffectList[n].name, str, len) == 0)
1143 DisabledEffects[EffectList[n].type] = AL_TRUE;
1145 } while(next++);
1148 InitEffect(&DefaultEffect);
1149 str = getenv("ALSOFT_DEFAULT_REVERB");
1150 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1151 LoadReverbPreset(str, &DefaultEffect);
1153 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1155 #ifdef __ANDROID__
1156 #include <jni.h>
1158 static JavaVM *gJavaVM;
1159 static pthread_key_t gJVMThreadKey;
1161 static void CleanupJNIEnv(void* UNUSED(ptr))
1163 JCALL0(gJavaVM,DetachCurrentThread)();
1166 void *Android_GetJNIEnv(void)
1168 if(!gJavaVM)
1170 WARN("gJavaVM is NULL!\n");
1171 return NULL;
1174 /* http://developer.android.com/guide/practices/jni.html
1176 * All threads are Linux threads, scheduled by the kernel. They're usually
1177 * started from managed code (using Thread.start), but they can also be
1178 * created elsewhere and then attached to the JavaVM. For example, a thread
1179 * started with pthread_create can be attached with the JNI
1180 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1181 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1182 * Attaching a natively-created thread causes a java.lang.Thread object to
1183 * be constructed and added to the "main" ThreadGroup, making it visible to
1184 * the debugger. Calling AttachCurrentThread on an already-attached thread
1185 * is a no-op.
1187 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1188 if(!env)
1190 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1191 if(status < 0)
1193 ERR("Failed to attach current thread\n");
1194 return NULL;
1196 pthread_setspecific(gJVMThreadKey, env);
1198 return env;
1201 /* Automatically called by JNI. */
1202 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1204 void *env;
1205 int err;
1207 gJavaVM = jvm;
1208 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1210 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1211 return JNI_ERR;
1214 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1215 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1217 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1218 ERR("pthread_key_create failed: %d\n", err);
1219 pthread_setspecific(gJVMThreadKey, env);
1220 return JNI_VERSION_1_4;
1222 #endif
1225 /************************************************
1226 * Library deinitialization
1227 ************************************************/
1228 static void alc_cleanup(void)
1230 ALCdevice *dev;
1232 AL_STRING_DEINIT(alcAllDevicesList);
1233 AL_STRING_DEINIT(alcCaptureDeviceList);
1235 free(alcDefaultAllDevicesSpecifier);
1236 alcDefaultAllDevicesSpecifier = NULL;
1237 free(alcCaptureDefaultDeviceSpecifier);
1238 alcCaptureDefaultDeviceSpecifier = NULL;
1240 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1242 ALCuint num = 0;
1243 do {
1244 num++;
1245 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
1246 } while(dev != NULL);
1247 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1251 static void alc_deinit_safe(void)
1253 alc_cleanup();
1255 FreeHrtfs();
1256 FreeALConfig();
1258 almtx_destroy(&ListLock);
1259 altss_delete(LocalContext);
1261 if(LogFile != stderr)
1262 fclose(LogFile);
1263 LogFile = NULL;
1265 althrd_deinit();
1268 static void alc_deinit(void)
1270 int i;
1272 alc_cleanup();
1274 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1275 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1277 for(i = 0;i < BackendListSize;i++)
1279 ALCbackendFactory *factory = BackendList[i].getFactory();
1280 V0(factory,deinit)();
1283 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1284 V0(factory,deinit)();
1287 alc_deinit_safe();
1291 /************************************************
1292 * Device enumeration
1293 ************************************************/
1294 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1296 DO_INITCONFIG();
1298 LockLists();
1299 alstr_clear(list);
1301 if(backendinfo->getFactory)
1303 ALCbackendFactory *factory = backendinfo->getFactory();
1304 V(factory,probe)(type);
1307 UnlockLists();
1309 static void ProbeAllDevicesList(void)
1310 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1311 static void ProbeCaptureDeviceList(void)
1312 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1314 static void AppendDevice(const ALCchar *name, al_string *devnames)
1316 size_t len = strlen(name);
1317 if(len > 0)
1318 alstr_append_range(devnames, name, name+len+1);
1320 void AppendAllDevicesList(const ALCchar *name)
1321 { AppendDevice(name, &alcAllDevicesList); }
1322 void AppendCaptureDeviceList(const ALCchar *name)
1323 { AppendDevice(name, &alcCaptureDeviceList); }
1326 /************************************************
1327 * Device format information
1328 ************************************************/
1329 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1331 switch(type)
1333 case DevFmtByte: return "Signed Byte";
1334 case DevFmtUByte: return "Unsigned Byte";
1335 case DevFmtShort: return "Signed Short";
1336 case DevFmtUShort: return "Unsigned Short";
1337 case DevFmtInt: return "Signed Int";
1338 case DevFmtUInt: return "Unsigned Int";
1339 case DevFmtFloat: return "Float";
1341 return "(unknown type)";
1343 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1345 switch(chans)
1347 case DevFmtMono: return "Mono";
1348 case DevFmtStereo: return "Stereo";
1349 case DevFmtQuad: return "Quadraphonic";
1350 case DevFmtX51: return "5.1 Surround";
1351 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1352 case DevFmtX61: return "6.1 Surround";
1353 case DevFmtX71: return "7.1 Surround";
1354 case DevFmtAmbi3D: return "Ambisonic 3D";
1356 return "(unknown channels)";
1359 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1360 ALsizei BytesFromDevFmt(enum DevFmtType type)
1362 switch(type)
1364 case DevFmtByte: return sizeof(ALbyte);
1365 case DevFmtUByte: return sizeof(ALubyte);
1366 case DevFmtShort: return sizeof(ALshort);
1367 case DevFmtUShort: return sizeof(ALushort);
1368 case DevFmtInt: return sizeof(ALint);
1369 case DevFmtUInt: return sizeof(ALuint);
1370 case DevFmtFloat: return sizeof(ALfloat);
1372 return 0;
1374 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1376 switch(chans)
1378 case DevFmtMono: return 1;
1379 case DevFmtStereo: return 2;
1380 case DevFmtQuad: return 4;
1381 case DevFmtX51: return 6;
1382 case DevFmtX51Rear: return 6;
1383 case DevFmtX61: return 7;
1384 case DevFmtX71: return 8;
1385 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1386 (ambiorder == 2) ? 9 :
1387 (ambiorder == 1) ? 4 : 1;
1389 return 0;
1392 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1393 enum DevFmtType *type)
1395 static const struct {
1396 ALenum format;
1397 enum DevFmtChannels channels;
1398 enum DevFmtType type;
1399 } list[] = {
1400 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1401 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1402 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1404 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1405 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1406 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1408 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1409 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1410 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1412 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1413 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1414 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1416 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1417 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1418 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1420 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1421 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1422 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1424 ALuint i;
1426 for(i = 0;i < COUNTOF(list);i++)
1428 if(list[i].format == format)
1430 *chans = list[i].channels;
1431 *type = list[i].type;
1432 return AL_TRUE;
1436 return AL_FALSE;
1439 static ALCboolean IsValidALCType(ALCenum type)
1441 switch(type)
1443 case ALC_BYTE_SOFT:
1444 case ALC_UNSIGNED_BYTE_SOFT:
1445 case ALC_SHORT_SOFT:
1446 case ALC_UNSIGNED_SHORT_SOFT:
1447 case ALC_INT_SOFT:
1448 case ALC_UNSIGNED_INT_SOFT:
1449 case ALC_FLOAT_SOFT:
1450 return ALC_TRUE;
1452 return ALC_FALSE;
1455 static ALCboolean IsValidALCChannels(ALCenum channels)
1457 switch(channels)
1459 case ALC_MONO_SOFT:
1460 case ALC_STEREO_SOFT:
1461 case ALC_QUAD_SOFT:
1462 case ALC_5POINT1_SOFT:
1463 case ALC_6POINT1_SOFT:
1464 case ALC_7POINT1_SOFT:
1465 case ALC_BFORMAT3D_SOFT:
1466 return ALC_TRUE;
1468 return ALC_FALSE;
1471 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1473 switch(layout)
1475 case ALC_ACN_SOFT:
1476 case ALC_FUMA_SOFT:
1477 return ALC_TRUE;
1479 return ALC_FALSE;
1482 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1484 switch(scaling)
1486 case ALC_N3D_SOFT:
1487 case ALC_SN3D_SOFT:
1488 case ALC_FUMA_SOFT:
1489 return ALC_TRUE;
1491 return ALC_FALSE;
1494 /************************************************
1495 * Miscellaneous ALC helpers
1496 ************************************************/
1498 /* SetDefaultWFXChannelOrder
1500 * Sets the default channel order used by WaveFormatEx.
1502 void SetDefaultWFXChannelOrder(ALCdevice *device)
1504 ALsizei i;
1506 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1507 device->RealOut.ChannelName[i] = InvalidChannel;
1509 switch(device->FmtChans)
1511 case DevFmtMono:
1512 device->RealOut.ChannelName[0] = FrontCenter;
1513 break;
1514 case DevFmtStereo:
1515 device->RealOut.ChannelName[0] = FrontLeft;
1516 device->RealOut.ChannelName[1] = FrontRight;
1517 break;
1518 case DevFmtQuad:
1519 device->RealOut.ChannelName[0] = FrontLeft;
1520 device->RealOut.ChannelName[1] = FrontRight;
1521 device->RealOut.ChannelName[2] = BackLeft;
1522 device->RealOut.ChannelName[3] = BackRight;
1523 break;
1524 case DevFmtX51:
1525 device->RealOut.ChannelName[0] = FrontLeft;
1526 device->RealOut.ChannelName[1] = FrontRight;
1527 device->RealOut.ChannelName[2] = FrontCenter;
1528 device->RealOut.ChannelName[3] = LFE;
1529 device->RealOut.ChannelName[4] = SideLeft;
1530 device->RealOut.ChannelName[5] = SideRight;
1531 break;
1532 case DevFmtX51Rear:
1533 device->RealOut.ChannelName[0] = FrontLeft;
1534 device->RealOut.ChannelName[1] = FrontRight;
1535 device->RealOut.ChannelName[2] = FrontCenter;
1536 device->RealOut.ChannelName[3] = LFE;
1537 device->RealOut.ChannelName[4] = BackLeft;
1538 device->RealOut.ChannelName[5] = BackRight;
1539 break;
1540 case DevFmtX61:
1541 device->RealOut.ChannelName[0] = FrontLeft;
1542 device->RealOut.ChannelName[1] = FrontRight;
1543 device->RealOut.ChannelName[2] = FrontCenter;
1544 device->RealOut.ChannelName[3] = LFE;
1545 device->RealOut.ChannelName[4] = BackCenter;
1546 device->RealOut.ChannelName[5] = SideLeft;
1547 device->RealOut.ChannelName[6] = SideRight;
1548 break;
1549 case DevFmtX71:
1550 device->RealOut.ChannelName[0] = FrontLeft;
1551 device->RealOut.ChannelName[1] = FrontRight;
1552 device->RealOut.ChannelName[2] = FrontCenter;
1553 device->RealOut.ChannelName[3] = LFE;
1554 device->RealOut.ChannelName[4] = BackLeft;
1555 device->RealOut.ChannelName[5] = BackRight;
1556 device->RealOut.ChannelName[6] = SideLeft;
1557 device->RealOut.ChannelName[7] = SideRight;
1558 break;
1559 case DevFmtAmbi3D:
1560 device->RealOut.ChannelName[0] = Aux0;
1561 if(device->AmbiOrder > 0)
1563 device->RealOut.ChannelName[1] = Aux1;
1564 device->RealOut.ChannelName[2] = Aux2;
1565 device->RealOut.ChannelName[3] = Aux3;
1567 if(device->AmbiOrder > 1)
1569 device->RealOut.ChannelName[4] = Aux4;
1570 device->RealOut.ChannelName[5] = Aux5;
1571 device->RealOut.ChannelName[6] = Aux6;
1572 device->RealOut.ChannelName[7] = Aux7;
1573 device->RealOut.ChannelName[8] = Aux8;
1575 if(device->AmbiOrder > 2)
1577 device->RealOut.ChannelName[9] = Aux9;
1578 device->RealOut.ChannelName[10] = Aux10;
1579 device->RealOut.ChannelName[11] = Aux11;
1580 device->RealOut.ChannelName[12] = Aux12;
1581 device->RealOut.ChannelName[13] = Aux13;
1582 device->RealOut.ChannelName[14] = Aux14;
1583 device->RealOut.ChannelName[15] = Aux15;
1585 break;
1589 /* SetDefaultChannelOrder
1591 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1593 void SetDefaultChannelOrder(ALCdevice *device)
1595 ALsizei i;
1597 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1598 device->RealOut.ChannelName[i] = InvalidChannel;
1600 switch(device->FmtChans)
1602 case DevFmtX51Rear:
1603 device->RealOut.ChannelName[0] = FrontLeft;
1604 device->RealOut.ChannelName[1] = FrontRight;
1605 device->RealOut.ChannelName[2] = BackLeft;
1606 device->RealOut.ChannelName[3] = BackRight;
1607 device->RealOut.ChannelName[4] = FrontCenter;
1608 device->RealOut.ChannelName[5] = LFE;
1609 return;
1610 case DevFmtX71:
1611 device->RealOut.ChannelName[0] = FrontLeft;
1612 device->RealOut.ChannelName[1] = FrontRight;
1613 device->RealOut.ChannelName[2] = BackLeft;
1614 device->RealOut.ChannelName[3] = BackRight;
1615 device->RealOut.ChannelName[4] = FrontCenter;
1616 device->RealOut.ChannelName[5] = LFE;
1617 device->RealOut.ChannelName[6] = SideLeft;
1618 device->RealOut.ChannelName[7] = SideRight;
1619 return;
1621 /* Same as WFX order */
1622 case DevFmtMono:
1623 case DevFmtStereo:
1624 case DevFmtQuad:
1625 case DevFmtX51:
1626 case DevFmtX61:
1627 case DevFmtAmbi3D:
1628 SetDefaultWFXChannelOrder(device);
1629 break;
1633 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1634 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1637 /* ALCcontext_DeferUpdates
1639 * Defers/suspends updates for the given context's listener and sources. This
1640 * does *NOT* stop mixing, but rather prevents certain property changes from
1641 * taking effect.
1643 void ALCcontext_DeferUpdates(ALCcontext *context)
1645 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1648 /* ALCcontext_ProcessUpdates
1650 * Resumes update processing after being deferred.
1652 void ALCcontext_ProcessUpdates(ALCcontext *context)
1654 almtx_lock(&context->PropLock);
1655 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1657 /* Tell the mixer to stop applying updates, then wait for any active
1658 * updating to finish, before providing updates.
1660 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1661 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1662 althrd_yield();
1664 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1665 UpdateContextProps(context);
1666 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1667 UpdateListenerProps(context);
1668 UpdateAllEffectSlotProps(context);
1669 UpdateAllSourceProps(context);
1671 /* Now with all updates declared, let the mixer continue applying them
1672 * so they all happen at once.
1674 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1676 almtx_unlock(&context->PropLock);
1680 /* alcSetError
1682 * Stores the latest ALC device error
1684 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1686 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1687 if(TrapALCError)
1689 #ifdef _WIN32
1690 /* DebugBreak() will cause an exception if there is no debugger */
1691 if(IsDebuggerPresent())
1692 DebugBreak();
1693 #elif defined(SIGTRAP)
1694 raise(SIGTRAP);
1695 #endif
1698 if(device)
1699 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1700 else
1701 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1705 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1707 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1708 0.0f, -3.0f, 3.0f, device->Frequency);
1711 /* UpdateClockBase
1713 * Updates the device's base clock time with however many samples have been
1714 * done. This is used so frequency changes on the device don't cause the time
1715 * to jump forward or back. Must not be called while the device is running/
1716 * mixing.
1718 static inline void UpdateClockBase(ALCdevice *device)
1720 IncrementRef(&device->MixCount);
1721 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1722 device->SamplesDone = 0;
1723 IncrementRef(&device->MixCount);
1726 /* UpdateDeviceParams
1728 * Updates device parameters according to the attribute list (caller is
1729 * responsible for holding the list lock).
1731 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1733 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1734 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1735 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1736 const ALsizei old_sends = device->NumAuxSends;
1737 ALsizei new_sends = device->NumAuxSends;
1738 enum DevFmtChannels oldChans;
1739 enum DevFmtType oldType;
1740 ALboolean update_failed;
1741 ALCsizei hrtf_id = -1;
1742 ALCcontext *context;
1743 ALCuint oldFreq;
1744 size_t size;
1745 ALCsizei i;
1746 int val;
1748 // Check for attributes
1749 if(device->Type == Loopback)
1751 ALCsizei numMono, numStereo, numSends;
1752 ALCenum alayout = AL_NONE;
1753 ALCenum ascale = AL_NONE;
1754 ALCenum schans = AL_NONE;
1755 ALCenum stype = AL_NONE;
1756 ALCsizei attrIdx = 0;
1757 ALCsizei aorder = 0;
1758 ALCuint freq = 0;
1760 if(!attrList)
1762 WARN("Missing attributes for loopback device\n");
1763 return ALC_INVALID_VALUE;
1766 numMono = device->NumMonoSources;
1767 numStereo = device->NumStereoSources;
1768 numSends = old_sends;
1770 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1771 while(attrList[attrIdx])
1773 switch(attrList[attrIdx])
1775 case ALC_FORMAT_CHANNELS_SOFT:
1776 schans = attrList[attrIdx + 1];
1777 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1778 if(!IsValidALCChannels(schans))
1779 return ALC_INVALID_VALUE;
1780 break;
1782 case ALC_FORMAT_TYPE_SOFT:
1783 stype = attrList[attrIdx + 1];
1784 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1785 if(!IsValidALCType(stype))
1786 return ALC_INVALID_VALUE;
1787 break;
1789 case ALC_FREQUENCY:
1790 freq = attrList[attrIdx + 1];
1791 TRACE_ATTR(ALC_FREQUENCY, freq);
1792 if(freq < MIN_OUTPUT_RATE)
1793 return ALC_INVALID_VALUE;
1794 break;
1796 case ALC_AMBISONIC_LAYOUT_SOFT:
1797 alayout = attrList[attrIdx + 1];
1798 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1799 if(!IsValidAmbiLayout(alayout))
1800 return ALC_INVALID_VALUE;
1801 break;
1803 case ALC_AMBISONIC_SCALING_SOFT:
1804 ascale = attrList[attrIdx + 1];
1805 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1806 if(!IsValidAmbiScaling(ascale))
1807 return ALC_INVALID_VALUE;
1808 break;
1810 case ALC_AMBISONIC_ORDER_SOFT:
1811 aorder = attrList[attrIdx + 1];
1812 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1813 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1814 return ALC_INVALID_VALUE;
1815 break;
1817 case ALC_MONO_SOURCES:
1818 numMono = attrList[attrIdx + 1];
1819 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1820 numMono = maxi(numMono, 0);
1821 break;
1823 case ALC_STEREO_SOURCES:
1824 numStereo = attrList[attrIdx + 1];
1825 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1826 numStereo = maxi(numStereo, 0);
1827 break;
1829 case ALC_MAX_AUXILIARY_SENDS:
1830 numSends = attrList[attrIdx + 1];
1831 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1832 numSends = clampi(numSends, 0, MAX_SENDS);
1833 break;
1835 case ALC_HRTF_SOFT:
1836 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1837 if(attrList[attrIdx + 1] == ALC_FALSE)
1838 hrtf_appreq = Hrtf_Disable;
1839 else if(attrList[attrIdx + 1] == ALC_TRUE)
1840 hrtf_appreq = Hrtf_Enable;
1841 else
1842 hrtf_appreq = Hrtf_Default;
1843 break;
1845 case ALC_HRTF_ID_SOFT:
1846 hrtf_id = attrList[attrIdx + 1];
1847 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1848 break;
1850 case ALC_OUTPUT_LIMITER_SOFT:
1851 gainLimiter = attrList[attrIdx + 1];
1852 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1853 break;
1855 default:
1856 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1857 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1858 break;
1861 attrIdx += 2;
1863 #undef TRACE_ATTR
1865 if(!schans || !stype || !freq)
1867 WARN("Missing format for loopback device\n");
1868 return ALC_INVALID_VALUE;
1870 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1872 WARN("Missing ambisonic info for loopback device\n");
1873 return ALC_INVALID_VALUE;
1876 if((device->Flags&DEVICE_RUNNING))
1877 V0(device->Backend,stop)();
1878 device->Flags &= ~DEVICE_RUNNING;
1880 UpdateClockBase(device);
1882 device->Frequency = freq;
1883 device->FmtChans = schans;
1884 device->FmtType = stype;
1885 if(schans == ALC_BFORMAT3D_SOFT)
1887 device->AmbiOrder = aorder;
1888 device->AmbiLayout = alayout;
1889 device->AmbiScale = ascale;
1892 if(numMono > INT_MAX-numStereo)
1893 numMono = INT_MAX-numStereo;
1894 numMono += numStereo;
1895 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1897 if(numMono <= 0)
1898 numMono = 256;
1900 else
1901 numMono = maxi(numMono, 256);
1902 numStereo = mini(numStereo, numMono);
1903 numMono -= numStereo;
1904 device->SourcesMax = numMono + numStereo;
1906 device->NumMonoSources = numMono;
1907 device->NumStereoSources = numStereo;
1909 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1910 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1911 else
1912 new_sends = numSends;
1914 else if(attrList && attrList[0])
1916 ALCsizei numMono, numStereo, numSends;
1917 ALCsizei attrIdx = 0;
1918 ALCuint freq;
1920 /* If a context is already running on the device, stop playback so the
1921 * device attributes can be updated. */
1922 if((device->Flags&DEVICE_RUNNING))
1923 V0(device->Backend,stop)();
1924 device->Flags &= ~DEVICE_RUNNING;
1926 UpdateClockBase(device);
1928 freq = device->Frequency;
1929 numMono = device->NumMonoSources;
1930 numStereo = device->NumStereoSources;
1931 numSends = old_sends;
1933 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1934 while(attrList[attrIdx])
1936 switch(attrList[attrIdx])
1938 case ALC_FREQUENCY:
1939 freq = attrList[attrIdx + 1];
1940 TRACE_ATTR(ALC_FREQUENCY, freq);
1941 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1942 break;
1944 case ALC_MONO_SOURCES:
1945 numMono = attrList[attrIdx + 1];
1946 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1947 numMono = maxi(numMono, 0);
1948 break;
1950 case ALC_STEREO_SOURCES:
1951 numStereo = attrList[attrIdx + 1];
1952 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1953 numStereo = maxi(numStereo, 0);
1954 break;
1956 case ALC_MAX_AUXILIARY_SENDS:
1957 numSends = attrList[attrIdx + 1];
1958 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1959 numSends = clampi(numSends, 0, MAX_SENDS);
1960 break;
1962 case ALC_HRTF_SOFT:
1963 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1964 if(attrList[attrIdx + 1] == ALC_FALSE)
1965 hrtf_appreq = Hrtf_Disable;
1966 else if(attrList[attrIdx + 1] == ALC_TRUE)
1967 hrtf_appreq = Hrtf_Enable;
1968 else
1969 hrtf_appreq = Hrtf_Default;
1970 break;
1972 case ALC_HRTF_ID_SOFT:
1973 hrtf_id = attrList[attrIdx + 1];
1974 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1975 break;
1977 case ALC_OUTPUT_LIMITER_SOFT:
1978 gainLimiter = attrList[attrIdx + 1];
1979 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1980 break;
1982 default:
1983 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1984 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1985 break;
1988 attrIdx += 2;
1990 #undef TRACE_ATTR
1992 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1993 freq = maxu(freq, MIN_OUTPUT_RATE);
1995 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1996 device->Frequency;
1997 /* SSE and Neon do best with the update size being a multiple of 4 */
1998 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1999 device->UpdateSize = (device->UpdateSize+3)&~3;
2001 device->Frequency = freq;
2003 if(numMono > INT_MAX-numStereo)
2004 numMono = INT_MAX-numStereo;
2005 numMono += numStereo;
2006 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
2008 if(numMono <= 0)
2009 numMono = 256;
2011 else
2012 numMono = maxi(numMono, 256);
2013 numStereo = mini(numStereo, numMono);
2014 numMono -= numStereo;
2015 device->SourcesMax = numMono + numStereo;
2017 device->NumMonoSources = numMono;
2018 device->NumStereoSources = numStereo;
2020 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2021 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2022 else
2023 new_sends = numSends;
2026 if((device->Flags&DEVICE_RUNNING))
2027 return ALC_NO_ERROR;
2029 al_free(device->Uhj_Encoder);
2030 device->Uhj_Encoder = NULL;
2032 al_free(device->Bs2b);
2033 device->Bs2b = NULL;
2035 al_free(device->ChannelDelay[0].Buffer);
2036 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2038 device->ChannelDelay[i].Length = 0;
2039 device->ChannelDelay[i].Buffer = NULL;
2042 al_free(device->Dry.Buffer);
2043 device->Dry.Buffer = NULL;
2044 device->Dry.NumChannels = 0;
2045 device->FOAOut.Buffer = NULL;
2046 device->FOAOut.NumChannels = 0;
2047 device->RealOut.Buffer = NULL;
2048 device->RealOut.NumChannels = 0;
2050 UpdateClockBase(device);
2052 device->DitherSeed = DITHER_RNG_SEED;
2054 /*************************************************************************
2055 * Update device format request if HRTF is requested
2057 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2058 if(device->Type != Loopback)
2060 const char *hrtf;
2061 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2063 if(strcasecmp(hrtf, "true") == 0)
2064 hrtf_userreq = Hrtf_Enable;
2065 else if(strcasecmp(hrtf, "false") == 0)
2066 hrtf_userreq = Hrtf_Disable;
2067 else if(strcasecmp(hrtf, "auto") != 0)
2068 ERR("Unexpected hrtf value: %s\n", hrtf);
2071 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2073 struct Hrtf *hrtf = NULL;
2074 if(VECTOR_SIZE(device->HrtfList) == 0)
2076 VECTOR_DEINIT(device->HrtfList);
2077 device->HrtfList = EnumerateHrtf(device->DeviceName);
2079 if(VECTOR_SIZE(device->HrtfList) > 0)
2081 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2082 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2083 else
2084 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2087 if(hrtf)
2089 device->FmtChans = DevFmtStereo;
2090 device->Frequency = hrtf->sampleRate;
2091 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2092 if(device->HrtfHandle)
2093 Hrtf_DecRef(device->HrtfHandle);
2094 device->HrtfHandle = hrtf;
2096 else
2098 hrtf_userreq = Hrtf_Default;
2099 hrtf_appreq = Hrtf_Disable;
2100 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2105 oldFreq = device->Frequency;
2106 oldChans = device->FmtChans;
2107 oldType = device->FmtType;
2109 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2110 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2111 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2112 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2113 device->UpdateSize, device->NumUpdates
2116 if(V0(device->Backend,reset)() == ALC_FALSE)
2117 return ALC_INVALID_DEVICE;
2119 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2121 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2122 DevFmtChannelsString(device->FmtChans));
2123 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2125 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2128 DevFmtTypeString(device->FmtType));
2129 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2131 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2133 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2134 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2137 if((device->UpdateSize&3) != 0)
2139 if((CPUCapFlags&CPU_CAP_SSE))
2140 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2141 if((CPUCapFlags&CPU_CAP_NEON))
2142 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2145 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2146 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2147 device->Frequency, device->UpdateSize, device->NumUpdates
2150 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2151 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2152 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2154 /* Allocate extra channels for any post-filter output. */
2155 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2156 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2158 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2159 device->Dry.Buffer = al_calloc(16, size);
2160 if(!device->Dry.Buffer)
2162 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2163 return ALC_INVALID_DEVICE;
2166 if(device->RealOut.NumChannels != 0)
2167 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2168 device->FOAOut.NumChannels;
2169 else
2171 device->RealOut.Buffer = device->Dry.Buffer;
2172 device->RealOut.NumChannels = device->Dry.NumChannels;
2175 if(device->FOAOut.NumChannels != 0)
2176 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2177 else
2179 device->FOAOut.Buffer = device->Dry.Buffer;
2180 device->FOAOut.NumChannels = device->Dry.NumChannels;
2183 device->NumAuxSends = new_sends;
2184 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2185 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2186 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2188 device->DitherDepth = 0.0f;
2189 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2191 ALint depth = 0;
2192 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2193 if(depth <= 0)
2195 switch(device->FmtType)
2197 case DevFmtByte:
2198 case DevFmtUByte:
2199 depth = 8;
2200 break;
2201 case DevFmtShort:
2202 case DevFmtUShort:
2203 depth = 16;
2204 break;
2205 case DevFmtInt:
2206 case DevFmtUInt:
2207 case DevFmtFloat:
2208 break;
2211 else if(depth > 24)
2212 depth = 24;
2213 device->DitherDepth = (depth > 0) ? powf(2.0f, (ALfloat)(depth-1)) : 0.0f;
2215 if(!(device->DitherDepth > 0.0f))
2216 TRACE("Dithering disabled\n");
2217 else
2218 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2219 device->DitherDepth);
2221 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2222 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2223 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2224 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2225 * ALC_TRUE.
2227 if(gainLimiter != ALC_FALSE)
2229 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2231 al_free(device->Limiter);
2232 device->Limiter = CreateDeviceLimiter(device);
2235 else
2237 al_free(device->Limiter);
2238 device->Limiter = NULL;
2240 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2242 aluSelectPostProcess(device);
2244 /* Need to delay returning failure until replacement Send arrays have been
2245 * allocated with the appropriate size.
2247 update_failed = AL_FALSE;
2248 START_MIXER_MODE();
2249 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2250 while(context)
2252 SourceSubList *sublist, *subend;
2253 struct ALvoiceProps *vprops;
2254 ALsizei pos;
2256 if(context->DefaultSlot)
2258 ALeffectslot *slot = context->DefaultSlot;
2259 ALeffectState *state = slot->Effect.State;
2261 state->OutBuffer = device->Dry.Buffer;
2262 state->OutChannels = device->Dry.NumChannels;
2263 if(V(state,deviceUpdate)(device) == AL_FALSE)
2264 update_failed = AL_TRUE;
2265 else
2266 UpdateEffectSlotProps(slot, context);
2269 almtx_lock(&context->PropLock);
2270 almtx_lock(&context->EffectSlotLock);
2271 for(pos = 0;pos < (ALsizei)VECTOR_SIZE(context->EffectSlotList);pos++)
2273 ALeffectslot *slot = VECTOR_ELEM(context->EffectSlotList, pos);
2274 ALeffectState *state = slot->Effect.State;
2276 state->OutBuffer = device->Dry.Buffer;
2277 state->OutChannels = device->Dry.NumChannels;
2278 if(V(state,deviceUpdate)(device) == AL_FALSE)
2279 update_failed = AL_TRUE;
2280 else
2281 UpdateEffectSlotProps(slot, context);
2283 almtx_unlock(&context->EffectSlotLock);
2285 almtx_lock(&context->SourceLock);
2286 sublist = VECTOR_BEGIN(context->SourceList);
2287 subend = VECTOR_END(context->SourceList);
2288 for(;sublist != subend;++sublist)
2290 ALuint64 usemask = ~sublist->FreeMask;
2291 while(usemask)
2293 ALsizei idx = CTZ64(usemask);
2294 ALsource *source = sublist->Sources + idx;
2296 usemask &= ~(U64(1) << idx);
2298 if(old_sends != device->NumAuxSends)
2300 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2301 ALsizei s;
2303 memcpy(sends, source->Send,
2304 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2306 for(s = device->NumAuxSends;s < old_sends;s++)
2308 if(source->Send[s].Slot)
2309 DecrementRef(&source->Send[s].Slot->ref);
2310 source->Send[s].Slot = NULL;
2312 al_free(source->Send);
2313 source->Send = sends;
2314 for(s = old_sends;s < device->NumAuxSends;s++)
2316 source->Send[s].Slot = NULL;
2317 source->Send[s].Gain = 1.0f;
2318 source->Send[s].GainHF = 1.0f;
2319 source->Send[s].HFReference = LOWPASSFREQREF;
2320 source->Send[s].GainLF = 1.0f;
2321 source->Send[s].LFReference = HIGHPASSFREQREF;
2325 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2329 /* Clear any pre-existing voice property structs, in case the number of
2330 * auxiliary sends is changing. Active sources will have updates
2331 * respecified in UpdateAllSourceProps.
2333 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2334 while(vprops)
2336 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2337 al_free(vprops);
2338 vprops = next;
2341 AllocateVoices(context, context->MaxVoices, old_sends);
2342 for(pos = 0;pos < context->VoiceCount;pos++)
2344 ALvoice *voice = context->Voices[pos];
2346 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2348 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2349 continue;
2351 if(device->AvgSpeakerDist > 0.0f)
2353 /* Reinitialize the NFC filters for new parameters. */
2354 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2355 (device->AvgSpeakerDist * device->Frequency);
2356 for(i = 0;i < voice->NumChannels;i++)
2357 NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1);
2360 almtx_unlock(&context->SourceLock);
2362 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2363 UpdateContextProps(context);
2364 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2365 UpdateListenerProps(context);
2366 UpdateAllSourceProps(context);
2367 almtx_unlock(&context->PropLock);
2369 context = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2371 END_MIXER_MODE();
2372 if(update_failed)
2373 return ALC_INVALID_DEVICE;
2375 if(!(device->Flags&DEVICE_PAUSED))
2377 if(V0(device->Backend,start)() == ALC_FALSE)
2378 return ALC_INVALID_DEVICE;
2379 device->Flags |= DEVICE_RUNNING;
2382 return ALC_NO_ERROR;
2386 static void InitDevice(ALCdevice *device, enum DeviceType type)
2388 ALsizei i;
2390 InitRef(&device->ref, 1);
2391 ATOMIC_INIT(&device->Connected, ALC_TRUE);
2392 device->Type = type;
2393 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
2395 device->Flags = 0;
2396 device->Render_Mode = NormalRender;
2397 device->AvgSpeakerDist = 0.0f;
2399 ATOMIC_INIT(&device->ContextList, NULL);
2401 device->ClockBase = 0;
2402 device->SamplesDone = 0;
2404 device->SourcesMax = 0;
2405 device->AuxiliaryEffectSlotMax = 0;
2406 device->NumAuxSends = 0;
2408 device->Dry.Buffer = NULL;
2409 device->Dry.NumChannels = 0;
2410 device->FOAOut.Buffer = NULL;
2411 device->FOAOut.NumChannels = 0;
2412 device->RealOut.Buffer = NULL;
2413 device->RealOut.NumChannels = 0;
2415 AL_STRING_INIT(device->DeviceName);
2417 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2419 device->ChannelDelay[i].Gain = 1.0f;
2420 device->ChannelDelay[i].Length = 0;
2421 device->ChannelDelay[i].Buffer = NULL;
2424 AL_STRING_INIT(device->HrtfName);
2425 VECTOR_INIT(device->HrtfList);
2426 device->HrtfHandle = NULL;
2427 device->Hrtf = NULL;
2428 device->Bs2b = NULL;
2429 device->Uhj_Encoder = NULL;
2430 device->AmbiDecoder = NULL;
2431 device->AmbiUp = NULL;
2432 device->Stablizer = NULL;
2433 device->Limiter = NULL;
2435 VECTOR_INIT(device->BufferList);
2436 almtx_init(&device->BufferLock, almtx_plain);
2438 VECTOR_INIT(device->EffectList);
2439 almtx_init(&device->EffectLock, almtx_plain);
2441 VECTOR_INIT(device->FilterList);
2442 almtx_init(&device->FilterLock, almtx_plain);
2444 almtx_init(&device->BackendLock, almtx_plain);
2445 device->Backend = NULL;
2447 ATOMIC_INIT(&device->next, NULL);
2450 /* FreeDevice
2452 * Frees the device structure, and destroys any objects the app failed to
2453 * delete. Called once there's no more references on the device.
2455 static ALCvoid FreeDevice(ALCdevice *device)
2457 ALsizei i;
2459 TRACE("%p\n", device);
2461 if(device->Backend)
2462 DELETE_OBJ(device->Backend);
2463 device->Backend = NULL;
2465 almtx_destroy(&device->BackendLock);
2467 ReleaseALBuffers(device);
2468 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2469 VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
2470 #undef FREE_BUFFERSUBLIST
2471 VECTOR_DEINIT(device->BufferList);
2472 almtx_destroy(&device->BufferLock);
2474 ReleaseALEffects(device);
2475 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2476 VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
2477 #undef FREE_EFFECTSUBLIST
2478 VECTOR_DEINIT(device->EffectList);
2479 almtx_destroy(&device->EffectLock);
2481 ReleaseALFilters(device);
2482 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2483 VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
2484 #undef FREE_FILTERSUBLIST
2485 VECTOR_DEINIT(device->FilterList);
2486 almtx_destroy(&device->FilterLock);
2488 AL_STRING_DEINIT(device->HrtfName);
2489 FreeHrtfList(&device->HrtfList);
2490 if(device->HrtfHandle)
2491 Hrtf_DecRef(device->HrtfHandle);
2492 device->HrtfHandle = NULL;
2493 al_free(device->Hrtf);
2494 device->Hrtf = NULL;
2496 al_free(device->Bs2b);
2497 device->Bs2b = NULL;
2499 al_free(device->Uhj_Encoder);
2500 device->Uhj_Encoder = NULL;
2502 bformatdec_free(&device->AmbiDecoder);
2503 ambiup_free(&device->AmbiUp);
2505 al_free(device->Stablizer);
2506 device->Stablizer = NULL;
2508 al_free(device->Limiter);
2509 device->Limiter = NULL;
2511 al_free(device->ChannelDelay[0].Buffer);
2512 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2514 device->ChannelDelay[i].Gain = 1.0f;
2515 device->ChannelDelay[i].Length = 0;
2516 device->ChannelDelay[i].Buffer = NULL;
2519 AL_STRING_DEINIT(device->DeviceName);
2521 al_free(device->Dry.Buffer);
2522 device->Dry.Buffer = NULL;
2523 device->Dry.NumChannels = 0;
2524 device->FOAOut.Buffer = NULL;
2525 device->FOAOut.NumChannels = 0;
2526 device->RealOut.Buffer = NULL;
2527 device->RealOut.NumChannels = 0;
2529 al_free(device);
2533 void ALCdevice_IncRef(ALCdevice *device)
2535 uint ref;
2536 ref = IncrementRef(&device->ref);
2537 TRACEREF("%p increasing refcount to %u\n", device, ref);
2540 void ALCdevice_DecRef(ALCdevice *device)
2542 uint ref;
2543 ref = DecrementRef(&device->ref);
2544 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2545 if(ref == 0) FreeDevice(device);
2548 /* VerifyDevice
2550 * Checks if the device handle is valid, and increments its ref count if so.
2552 static ALCboolean VerifyDevice(ALCdevice **device)
2554 ALCdevice *tmpDevice;
2556 LockLists();
2557 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2558 while(tmpDevice)
2560 if(tmpDevice == *device)
2562 ALCdevice_IncRef(tmpDevice);
2563 UnlockLists();
2564 return ALC_TRUE;
2566 tmpDevice = ATOMIC_LOAD(&tmpDevice->next, almemory_order_relaxed);
2568 UnlockLists();
2570 *device = NULL;
2571 return ALC_FALSE;
2575 /* InitContext
2577 * Initializes context fields
2579 static ALvoid InitContext(ALCcontext *Context)
2581 ALlistener *listener = Context->Listener;
2582 struct ALeffectslotArray *auxslots;
2584 //Initialise listener
2585 listener->Gain = 1.0f;
2586 listener->Position[0] = 0.0f;
2587 listener->Position[1] = 0.0f;
2588 listener->Position[2] = 0.0f;
2589 listener->Velocity[0] = 0.0f;
2590 listener->Velocity[1] = 0.0f;
2591 listener->Velocity[2] = 0.0f;
2592 listener->Forward[0] = 0.0f;
2593 listener->Forward[1] = 0.0f;
2594 listener->Forward[2] = -1.0f;
2595 listener->Up[0] = 0.0f;
2596 listener->Up[1] = 1.0f;
2597 listener->Up[2] = 0.0f;
2598 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2600 ATOMIC_INIT(&listener->Update, NULL);
2602 //Validate Context
2603 InitRef(&Context->UpdateCount, 0);
2604 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2605 Context->GainBoost = 1.0f;
2606 almtx_init(&Context->PropLock, almtx_plain);
2607 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2608 VECTOR_INIT(Context->SourceList);
2609 Context->NumSources = 0;
2610 almtx_init(&Context->SourceLock, almtx_plain);
2611 VECTOR_INIT(Context->EffectSlotList);
2612 almtx_init(&Context->EffectSlotLock, almtx_plain);
2614 if(Context->DefaultSlot)
2616 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2617 auxslots->count = 1;
2618 auxslots->slot[0] = Context->DefaultSlot;
2620 else
2622 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2623 auxslots->count = 0;
2625 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2627 //Set globals
2628 Context->DistanceModel = DefaultDistanceModel;
2629 Context->SourceDistanceModel = AL_FALSE;
2630 Context->DopplerFactor = 1.0f;
2631 Context->DopplerVelocity = 1.0f;
2632 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2633 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2634 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2635 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2636 almtx_init(&Context->EventThrdLock, almtx_plain);
2637 alsem_init(&Context->EventSem, 0);
2638 Context->AsyncEvents = NULL;
2639 ATOMIC_INIT(&Context->EnabledEvts, 0);
2640 almtx_init(&Context->EventCbLock, almtx_plain);
2641 Context->EventCb = NULL;
2642 Context->EventParam = NULL;
2644 ATOMIC_INIT(&Context->Update, NULL);
2645 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2646 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2647 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2648 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2650 Context->ExtensionList = alExtList;
2653 listener->Params.Matrix = IdentityMatrixf;
2654 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2655 listener->Params.Gain = listener->Gain;
2656 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2657 listener->Params.DopplerFactor = Context->DopplerFactor;
2658 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2659 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2660 listener->Params.MetersPerUnit;
2661 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2662 listener->Params.DistanceModel = Context->DistanceModel;
2666 /* FreeContext
2668 * Cleans up the context, and destroys any remaining objects the app failed to
2669 * delete. Called once there's no more references on the context.
2671 static void FreeContext(ALCcontext *context)
2673 ALlistener *listener = context->Listener;
2674 struct ALeffectslotArray *auxslots;
2675 struct ALeffectslotProps *eprops;
2676 struct ALlistenerProps *lprops;
2677 struct ALcontextProps *cprops;
2678 struct ALvoiceProps *vprops;
2679 size_t count;
2680 ALsizei i;
2682 TRACE("%p\n", context);
2684 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2686 TRACE("Freed unapplied context update %p\n", cprops);
2687 al_free(cprops);
2690 count = 0;
2691 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2692 while(cprops)
2694 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2695 al_free(cprops);
2696 cprops = next;
2697 ++count;
2699 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2701 if(context->DefaultSlot)
2703 DeinitEffectSlot(context->DefaultSlot);
2704 context->DefaultSlot = NULL;
2707 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2708 al_free(auxslots);
2710 ReleaseALSources(context);
2711 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2712 VECTOR_FOR_EACH(SourceSubList, context->SourceList, FREE_SOURCESUBLIST);
2713 #undef FREE_SOURCESUBLIST
2714 VECTOR_DEINIT(context->SourceList);
2715 context->NumSources = 0;
2716 almtx_destroy(&context->SourceLock);
2718 count = 0;
2719 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2720 while(eprops)
2722 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2723 if(eprops->State) ALeffectState_DecRef(eprops->State);
2724 al_free(eprops);
2725 eprops = next;
2726 ++count;
2728 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2730 ReleaseALAuxiliaryEffectSlots(context);
2731 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2732 VECTOR_FOR_EACH(ALeffectslotPtr, context->EffectSlotList, FREE_EFFECTSLOTPTR);
2733 #undef FREE_EFFECTSLOTPTR
2734 VECTOR_DEINIT(context->EffectSlotList);
2735 almtx_destroy(&context->EffectSlotLock);
2737 count = 0;
2738 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2739 while(vprops)
2741 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2742 al_free(vprops);
2743 vprops = next;
2744 ++count;
2746 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2748 for(i = 0;i < context->VoiceCount;i++)
2749 DeinitVoice(context->Voices[i]);
2750 al_free(context->Voices);
2751 context->Voices = NULL;
2752 context->VoiceCount = 0;
2753 context->MaxVoices = 0;
2755 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2757 TRACE("Freed unapplied listener update %p\n", lprops);
2758 al_free(lprops);
2760 count = 0;
2761 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2762 while(lprops)
2764 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2765 al_free(lprops);
2766 lprops = next;
2767 ++count;
2769 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2771 if(ATOMIC_EXCHANGE(&context->EnabledEvts, 0, almemory_order_acq_rel))
2773 static const AsyncEvent kill_evt = { 0 };
2774 while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
2775 althrd_yield();
2776 alsem_post(&context->EventSem);
2777 althrd_join(context->EventThread, NULL);
2780 almtx_destroy(&context->EventCbLock);
2781 almtx_destroy(&context->EventThrdLock);
2782 alsem_destroy(&context->EventSem);
2784 ll_ringbuffer_free(context->AsyncEvents);
2785 context->AsyncEvents = NULL;
2787 almtx_destroy(&context->PropLock);
2789 ALCdevice_DecRef(context->Device);
2790 context->Device = NULL;
2792 //Invalidate context
2793 memset(context, 0, sizeof(ALCcontext));
2794 al_free(context);
2797 /* ReleaseContext
2799 * Removes the context reference from the given device and removes it from
2800 * being current on the running thread or globally. Returns true if other
2801 * contexts still exist on the device.
2803 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2805 ALCcontext *origctx, *newhead;
2806 bool ret = true;
2808 if(altss_get(LocalContext) == context)
2810 WARN("%p released while current on thread\n", context);
2811 altss_set(LocalContext, NULL);
2812 ALCcontext_DecRef(context);
2815 origctx = context;
2816 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2817 ALCcontext_DecRef(context);
2819 V0(device->Backend,lock)();
2820 origctx = context;
2821 newhead = ATOMIC_LOAD(&context->next, almemory_order_relaxed);
2822 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2824 ALCcontext *list;
2825 do {
2826 /* origctx is what the desired context failed to match. Try
2827 * swapping out the next one in the list.
2829 list = origctx;
2830 origctx = context;
2831 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origctx, newhead));
2833 else
2834 ret = !!newhead;
2835 V0(device->Backend,unlock)();
2837 ALCcontext_DecRef(context);
2838 return ret;
2841 static void ALCcontext_IncRef(ALCcontext *context)
2843 uint ref = IncrementRef(&context->ref);
2844 TRACEREF("%p increasing refcount to %u\n", context, ref);
2847 void ALCcontext_DecRef(ALCcontext *context)
2849 uint ref = DecrementRef(&context->ref);
2850 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2851 if(ref == 0) FreeContext(context);
2854 static void ReleaseThreadCtx(void *ptr)
2856 ALCcontext *context = ptr;
2857 uint ref = DecrementRef(&context->ref);
2858 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2859 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2862 /* VerifyContext
2864 * Checks that the given context is valid, and increments its reference count.
2866 static ALCboolean VerifyContext(ALCcontext **context)
2868 ALCdevice *dev;
2870 LockLists();
2871 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2872 while(dev)
2874 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2875 while(ctx)
2877 if(ctx == *context)
2879 ALCcontext_IncRef(ctx);
2880 UnlockLists();
2881 return ALC_TRUE;
2883 ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
2885 dev = ATOMIC_LOAD(&dev->next, almemory_order_relaxed);
2887 UnlockLists();
2889 *context = NULL;
2890 return ALC_FALSE;
2894 /* GetContextRef
2896 * Returns the currently active context for this thread, and adds a reference
2897 * without locking it.
2899 ALCcontext *GetContextRef(void)
2901 ALCcontext *context;
2903 context = altss_get(LocalContext);
2904 if(context)
2905 ALCcontext_IncRef(context);
2906 else
2908 LockLists();
2909 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2910 if(context)
2911 ALCcontext_IncRef(context);
2912 UnlockLists();
2915 return context;
2919 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2921 ALCdevice *device = context->Device;
2922 ALsizei num_sends = device->NumAuxSends;
2923 struct ALvoiceProps *props;
2924 size_t sizeof_props;
2925 size_t sizeof_voice;
2926 ALvoice **voices;
2927 ALvoice *voice;
2928 ALsizei v = 0;
2929 size_t size;
2931 if(num_voices == context->MaxVoices && num_sends == old_sends)
2932 return;
2934 /* Allocate the voice pointers, voices, and the voices' stored source
2935 * property set (including the dynamically-sized Send[] array) in one
2936 * chunk.
2938 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2939 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2940 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2942 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2943 /* The voice and property objects are stored interleaved since they're
2944 * paired together.
2946 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2947 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2949 if(context->Voices)
2951 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2952 const ALsizei s_count = mini(old_sends, num_sends);
2954 for(;v < v_count;v++)
2956 ALvoice *old_voice = context->Voices[v];
2957 ALsizei i;
2959 /* Copy the old voice data and source property set to the new
2960 * storage.
2962 *voice = *old_voice;
2963 for(i = 0;i < s_count;i++)
2964 voice->Send[i] = old_voice->Send[i];
2965 *props = *(old_voice->Props);
2966 for(i = 0;i < s_count;i++)
2967 props->Send[i] = old_voice->Props->Send[i];
2969 /* Set this voice's property set pointer and voice reference. */
2970 voice->Props = props;
2971 voices[v] = voice;
2973 /* Increment pointers to the next storage space. */
2974 voice = (ALvoice*)((char*)props + sizeof_props);
2975 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2977 /* Deinit any left over voices that weren't copied over to the new
2978 * array. NOTE: If this does anything, v equals num_voices and
2979 * num_voices is less than VoiceCount, so the following loop won't do
2980 * anything.
2982 for(;v < context->VoiceCount;v++)
2983 DeinitVoice(context->Voices[v]);
2985 /* Finish setting the voices' property set pointers and references. */
2986 for(;v < num_voices;v++)
2988 ATOMIC_INIT(&voice->Update, NULL);
2990 voice->Props = props;
2991 voices[v] = voice;
2993 voice = (ALvoice*)((char*)props + sizeof_props);
2994 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2997 al_free(context->Voices);
2998 context->Voices = voices;
2999 context->MaxVoices = num_voices;
3000 context->VoiceCount = mini(context->VoiceCount, num_voices);
3004 /************************************************
3005 * Standard ALC functions
3006 ************************************************/
3008 /* alcGetError
3010 * Return last ALC generated error code for the given device
3012 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
3014 ALCenum errorCode;
3016 if(VerifyDevice(&device))
3018 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
3019 ALCdevice_DecRef(device);
3021 else
3022 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
3024 return errorCode;
3028 /* alcSuspendContext
3030 * Suspends updates for the given context
3032 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
3034 if(!SuspendDefers)
3035 return;
3037 if(!VerifyContext(&context))
3038 alcSetError(NULL, ALC_INVALID_CONTEXT);
3039 else
3041 ALCcontext_DeferUpdates(context);
3042 ALCcontext_DecRef(context);
3046 /* alcProcessContext
3048 * Resumes processing updates for the given context
3050 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
3052 if(!SuspendDefers)
3053 return;
3055 if(!VerifyContext(&context))
3056 alcSetError(NULL, ALC_INVALID_CONTEXT);
3057 else
3059 ALCcontext_ProcessUpdates(context);
3060 ALCcontext_DecRef(context);
3065 /* alcGetString
3067 * Returns information about the device, and error strings
3069 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
3071 const ALCchar *value = NULL;
3073 switch(param)
3075 case ALC_NO_ERROR:
3076 value = alcNoError;
3077 break;
3079 case ALC_INVALID_ENUM:
3080 value = alcErrInvalidEnum;
3081 break;
3083 case ALC_INVALID_VALUE:
3084 value = alcErrInvalidValue;
3085 break;
3087 case ALC_INVALID_DEVICE:
3088 value = alcErrInvalidDevice;
3089 break;
3091 case ALC_INVALID_CONTEXT:
3092 value = alcErrInvalidContext;
3093 break;
3095 case ALC_OUT_OF_MEMORY:
3096 value = alcErrOutOfMemory;
3097 break;
3099 case ALC_DEVICE_SPECIFIER:
3100 value = alcDefaultName;
3101 break;
3103 case ALC_ALL_DEVICES_SPECIFIER:
3104 if(VerifyDevice(&Device))
3106 value = alstr_get_cstr(Device->DeviceName);
3107 ALCdevice_DecRef(Device);
3109 else
3111 ProbeAllDevicesList();
3112 value = alstr_get_cstr(alcAllDevicesList);
3114 break;
3116 case ALC_CAPTURE_DEVICE_SPECIFIER:
3117 if(VerifyDevice(&Device))
3119 value = alstr_get_cstr(Device->DeviceName);
3120 ALCdevice_DecRef(Device);
3122 else
3124 ProbeCaptureDeviceList();
3125 value = alstr_get_cstr(alcCaptureDeviceList);
3127 break;
3129 /* Default devices are always first in the list */
3130 case ALC_DEFAULT_DEVICE_SPECIFIER:
3131 value = alcDefaultName;
3132 break;
3134 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3135 if(alstr_empty(alcAllDevicesList))
3136 ProbeAllDevicesList();
3138 VerifyDevice(&Device);
3140 free(alcDefaultAllDevicesSpecifier);
3141 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3142 if(!alcDefaultAllDevicesSpecifier)
3143 alcSetError(Device, ALC_OUT_OF_MEMORY);
3145 value = alcDefaultAllDevicesSpecifier;
3146 if(Device) ALCdevice_DecRef(Device);
3147 break;
3149 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3150 if(alstr_empty(alcCaptureDeviceList))
3151 ProbeCaptureDeviceList();
3153 VerifyDevice(&Device);
3155 free(alcCaptureDefaultDeviceSpecifier);
3156 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3157 if(!alcCaptureDefaultDeviceSpecifier)
3158 alcSetError(Device, ALC_OUT_OF_MEMORY);
3160 value = alcCaptureDefaultDeviceSpecifier;
3161 if(Device) ALCdevice_DecRef(Device);
3162 break;
3164 case ALC_EXTENSIONS:
3165 if(!VerifyDevice(&Device))
3166 value = alcNoDeviceExtList;
3167 else
3169 value = alcExtensionList;
3170 ALCdevice_DecRef(Device);
3172 break;
3174 case ALC_HRTF_SPECIFIER_SOFT:
3175 if(!VerifyDevice(&Device))
3176 alcSetError(NULL, ALC_INVALID_DEVICE);
3177 else
3179 almtx_lock(&Device->BackendLock);
3180 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3181 almtx_unlock(&Device->BackendLock);
3182 ALCdevice_DecRef(Device);
3184 break;
3186 default:
3187 VerifyDevice(&Device);
3188 alcSetError(Device, ALC_INVALID_ENUM);
3189 if(Device) ALCdevice_DecRef(Device);
3190 break;
3193 return value;
3197 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3199 if(device->Type == Capture) return 9;
3200 if(device->Type != Loopback) return 29;
3201 if(device->FmtChans == DevFmtAmbi3D)
3202 return 35;
3203 return 29;
3206 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3208 ALCsizei i;
3210 if(size <= 0 || values == NULL)
3212 alcSetError(device, ALC_INVALID_VALUE);
3213 return 0;
3216 if(!device)
3218 switch(param)
3220 case ALC_MAJOR_VERSION:
3221 values[0] = alcMajorVersion;
3222 return 1;
3223 case ALC_MINOR_VERSION:
3224 values[0] = alcMinorVersion;
3225 return 1;
3227 case ALC_ATTRIBUTES_SIZE:
3228 case ALC_ALL_ATTRIBUTES:
3229 case ALC_FREQUENCY:
3230 case ALC_REFRESH:
3231 case ALC_SYNC:
3232 case ALC_MONO_SOURCES:
3233 case ALC_STEREO_SOURCES:
3234 case ALC_CAPTURE_SAMPLES:
3235 case ALC_FORMAT_CHANNELS_SOFT:
3236 case ALC_FORMAT_TYPE_SOFT:
3237 case ALC_AMBISONIC_LAYOUT_SOFT:
3238 case ALC_AMBISONIC_SCALING_SOFT:
3239 case ALC_AMBISONIC_ORDER_SOFT:
3240 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3241 alcSetError(NULL, ALC_INVALID_DEVICE);
3242 return 0;
3244 default:
3245 alcSetError(NULL, ALC_INVALID_ENUM);
3246 return 0;
3248 return 0;
3251 if(device->Type == Capture)
3253 switch(param)
3255 case ALC_ATTRIBUTES_SIZE:
3256 values[0] = NumAttrsForDevice(device);
3257 return 1;
3259 case ALC_ALL_ATTRIBUTES:
3260 if(size < NumAttrsForDevice(device))
3262 alcSetError(device, ALC_INVALID_VALUE);
3263 return 0;
3266 i = 0;
3267 almtx_lock(&device->BackendLock);
3268 values[i++] = ALC_MAJOR_VERSION;
3269 values[i++] = alcMajorVersion;
3270 values[i++] = ALC_MINOR_VERSION;
3271 values[i++] = alcMinorVersion;
3272 values[i++] = ALC_CAPTURE_SAMPLES;
3273 values[i++] = V0(device->Backend,availableSamples)();
3274 values[i++] = ALC_CONNECTED;
3275 values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed);
3276 almtx_unlock(&device->BackendLock);
3278 values[i++] = 0;
3279 return i;
3281 case ALC_MAJOR_VERSION:
3282 values[0] = alcMajorVersion;
3283 return 1;
3284 case ALC_MINOR_VERSION:
3285 values[0] = alcMinorVersion;
3286 return 1;
3288 case ALC_CAPTURE_SAMPLES:
3289 almtx_lock(&device->BackendLock);
3290 values[0] = V0(device->Backend,availableSamples)();
3291 almtx_unlock(&device->BackendLock);
3292 return 1;
3294 case ALC_CONNECTED:
3295 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3296 return 1;
3298 default:
3299 alcSetError(device, ALC_INVALID_ENUM);
3300 return 0;
3302 return 0;
3305 /* render device */
3306 switch(param)
3308 case ALC_ATTRIBUTES_SIZE:
3309 values[0] = NumAttrsForDevice(device);
3310 return 1;
3312 case ALC_ALL_ATTRIBUTES:
3313 if(size < NumAttrsForDevice(device))
3315 alcSetError(device, ALC_INVALID_VALUE);
3316 return 0;
3319 i = 0;
3320 almtx_lock(&device->BackendLock);
3321 values[i++] = ALC_MAJOR_VERSION;
3322 values[i++] = alcMajorVersion;
3323 values[i++] = ALC_MINOR_VERSION;
3324 values[i++] = alcMinorVersion;
3325 values[i++] = ALC_EFX_MAJOR_VERSION;
3326 values[i++] = alcEFXMajorVersion;
3327 values[i++] = ALC_EFX_MINOR_VERSION;
3328 values[i++] = alcEFXMinorVersion;
3330 values[i++] = ALC_FREQUENCY;
3331 values[i++] = device->Frequency;
3332 if(device->Type != Loopback)
3334 values[i++] = ALC_REFRESH;
3335 values[i++] = device->Frequency / device->UpdateSize;
3337 values[i++] = ALC_SYNC;
3338 values[i++] = ALC_FALSE;
3340 else
3342 if(device->FmtChans == DevFmtAmbi3D)
3344 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3345 values[i++] = device->AmbiLayout;
3347 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3348 values[i++] = device->AmbiScale;
3350 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3351 values[i++] = device->AmbiOrder;
3354 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3355 values[i++] = device->FmtChans;
3357 values[i++] = ALC_FORMAT_TYPE_SOFT;
3358 values[i++] = device->FmtType;
3361 values[i++] = ALC_MONO_SOURCES;
3362 values[i++] = device->NumMonoSources;
3364 values[i++] = ALC_STEREO_SOURCES;
3365 values[i++] = device->NumStereoSources;
3367 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3368 values[i++] = device->NumAuxSends;
3370 values[i++] = ALC_HRTF_SOFT;
3371 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3373 values[i++] = ALC_HRTF_STATUS_SOFT;
3374 values[i++] = device->HrtfStatus;
3376 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3377 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3379 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3380 values[i++] = MAX_AMBI_ORDER;
3381 almtx_unlock(&device->BackendLock);
3383 values[i++] = 0;
3384 return i;
3386 case ALC_MAJOR_VERSION:
3387 values[0] = alcMajorVersion;
3388 return 1;
3390 case ALC_MINOR_VERSION:
3391 values[0] = alcMinorVersion;
3392 return 1;
3394 case ALC_EFX_MAJOR_VERSION:
3395 values[0] = alcEFXMajorVersion;
3396 return 1;
3398 case ALC_EFX_MINOR_VERSION:
3399 values[0] = alcEFXMinorVersion;
3400 return 1;
3402 case ALC_FREQUENCY:
3403 values[0] = device->Frequency;
3404 return 1;
3406 case ALC_REFRESH:
3407 if(device->Type == Loopback)
3409 alcSetError(device, ALC_INVALID_DEVICE);
3410 return 0;
3412 almtx_lock(&device->BackendLock);
3413 values[0] = device->Frequency / device->UpdateSize;
3414 almtx_unlock(&device->BackendLock);
3415 return 1;
3417 case ALC_SYNC:
3418 if(device->Type == Loopback)
3420 alcSetError(device, ALC_INVALID_DEVICE);
3421 return 0;
3423 values[0] = ALC_FALSE;
3424 return 1;
3426 case ALC_FORMAT_CHANNELS_SOFT:
3427 if(device->Type != Loopback)
3429 alcSetError(device, ALC_INVALID_DEVICE);
3430 return 0;
3432 values[0] = device->FmtChans;
3433 return 1;
3435 case ALC_FORMAT_TYPE_SOFT:
3436 if(device->Type != Loopback)
3438 alcSetError(device, ALC_INVALID_DEVICE);
3439 return 0;
3441 values[0] = device->FmtType;
3442 return 1;
3444 case ALC_AMBISONIC_LAYOUT_SOFT:
3445 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3447 alcSetError(device, ALC_INVALID_DEVICE);
3448 return 0;
3450 values[0] = device->AmbiLayout;
3451 return 1;
3453 case ALC_AMBISONIC_SCALING_SOFT:
3454 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3456 alcSetError(device, ALC_INVALID_DEVICE);
3457 return 0;
3459 values[0] = device->AmbiScale;
3460 return 1;
3462 case ALC_AMBISONIC_ORDER_SOFT:
3463 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3465 alcSetError(device, ALC_INVALID_DEVICE);
3466 return 0;
3468 values[0] = device->AmbiOrder;
3469 return 1;
3471 case ALC_MONO_SOURCES:
3472 values[0] = device->NumMonoSources;
3473 return 1;
3475 case ALC_STEREO_SOURCES:
3476 values[0] = device->NumStereoSources;
3477 return 1;
3479 case ALC_MAX_AUXILIARY_SENDS:
3480 values[0] = device->NumAuxSends;
3481 return 1;
3483 case ALC_CONNECTED:
3484 values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire);
3485 return 1;
3487 case ALC_HRTF_SOFT:
3488 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3489 return 1;
3491 case ALC_HRTF_STATUS_SOFT:
3492 values[0] = device->HrtfStatus;
3493 return 1;
3495 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3496 almtx_lock(&device->BackendLock);
3497 FreeHrtfList(&device->HrtfList);
3498 device->HrtfList = EnumerateHrtf(device->DeviceName);
3499 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3500 almtx_unlock(&device->BackendLock);
3501 return 1;
3503 case ALC_OUTPUT_LIMITER_SOFT:
3504 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3505 return 1;
3507 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3508 values[0] = MAX_AMBI_ORDER;
3509 return 1;
3511 default:
3512 alcSetError(device, ALC_INVALID_ENUM);
3513 return 0;
3515 return 0;
3518 /* alcGetIntegerv
3520 * Returns information about the device and the version of OpenAL
3522 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3524 VerifyDevice(&device);
3525 if(size <= 0 || values == NULL)
3526 alcSetError(device, ALC_INVALID_VALUE);
3527 else
3528 GetIntegerv(device, param, size, values);
3529 if(device) ALCdevice_DecRef(device);
3532 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3534 ALCint *ivals;
3535 ALsizei i;
3537 VerifyDevice(&device);
3538 if(size <= 0 || values == NULL)
3539 alcSetError(device, ALC_INVALID_VALUE);
3540 else if(!device || device->Type == Capture)
3542 ivals = malloc(size * sizeof(ALCint));
3543 size = GetIntegerv(device, pname, size, ivals);
3544 for(i = 0;i < size;i++)
3545 values[i] = ivals[i];
3546 free(ivals);
3548 else /* render device */
3550 ClockLatency clock;
3551 ALuint64 basecount;
3552 ALuint samplecount;
3553 ALuint refcount;
3555 switch(pname)
3557 case ALC_ATTRIBUTES_SIZE:
3558 *values = NumAttrsForDevice(device)+4;
3559 break;
3561 case ALC_ALL_ATTRIBUTES:
3562 if(size < NumAttrsForDevice(device)+4)
3563 alcSetError(device, ALC_INVALID_VALUE);
3564 else
3566 i = 0;
3567 almtx_lock(&device->BackendLock);
3568 values[i++] = ALC_FREQUENCY;
3569 values[i++] = device->Frequency;
3571 if(device->Type != Loopback)
3573 values[i++] = ALC_REFRESH;
3574 values[i++] = device->Frequency / device->UpdateSize;
3576 values[i++] = ALC_SYNC;
3577 values[i++] = ALC_FALSE;
3579 else
3581 if(device->FmtChans == DevFmtAmbi3D)
3583 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3584 values[i++] = device->AmbiLayout;
3586 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3587 values[i++] = device->AmbiScale;
3589 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3590 values[i++] = device->AmbiOrder;
3593 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3594 values[i++] = device->FmtChans;
3596 values[i++] = ALC_FORMAT_TYPE_SOFT;
3597 values[i++] = device->FmtType;
3600 values[i++] = ALC_MONO_SOURCES;
3601 values[i++] = device->NumMonoSources;
3603 values[i++] = ALC_STEREO_SOURCES;
3604 values[i++] = device->NumStereoSources;
3606 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3607 values[i++] = device->NumAuxSends;
3609 values[i++] = ALC_HRTF_SOFT;
3610 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3612 values[i++] = ALC_HRTF_STATUS_SOFT;
3613 values[i++] = device->HrtfStatus;
3615 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3616 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3618 clock = V0(device->Backend,getClockLatency)();
3619 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3620 values[i++] = clock.ClockTime;
3622 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3623 values[i++] = clock.Latency;
3624 almtx_unlock(&device->BackendLock);
3626 values[i++] = 0;
3628 break;
3630 case ALC_DEVICE_CLOCK_SOFT:
3631 almtx_lock(&device->BackendLock);
3632 do {
3633 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3634 althrd_yield();
3635 basecount = device->ClockBase;
3636 samplecount = device->SamplesDone;
3637 } while(refcount != ReadRef(&device->MixCount));
3638 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3639 almtx_unlock(&device->BackendLock);
3640 break;
3642 case ALC_DEVICE_LATENCY_SOFT:
3643 almtx_lock(&device->BackendLock);
3644 clock = V0(device->Backend,getClockLatency)();
3645 almtx_unlock(&device->BackendLock);
3646 *values = clock.Latency;
3647 break;
3649 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3650 if(size < 2)
3651 alcSetError(device, ALC_INVALID_VALUE);
3652 else
3654 almtx_lock(&device->BackendLock);
3655 clock = V0(device->Backend,getClockLatency)();
3656 almtx_unlock(&device->BackendLock);
3657 values[0] = clock.ClockTime;
3658 values[1] = clock.Latency;
3660 break;
3662 default:
3663 ivals = malloc(size * sizeof(ALCint));
3664 size = GetIntegerv(device, pname, size, ivals);
3665 for(i = 0;i < size;i++)
3666 values[i] = ivals[i];
3667 free(ivals);
3668 break;
3671 if(device)
3672 ALCdevice_DecRef(device);
3676 /* alcIsExtensionPresent
3678 * Determines if there is support for a particular extension
3680 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3682 ALCboolean bResult = ALC_FALSE;
3684 VerifyDevice(&device);
3686 if(!extName)
3687 alcSetError(device, ALC_INVALID_VALUE);
3688 else
3690 size_t len = strlen(extName);
3691 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3692 while(ptr && *ptr)
3694 if(strncasecmp(ptr, extName, len) == 0 &&
3695 (ptr[len] == '\0' || isspace(ptr[len])))
3697 bResult = ALC_TRUE;
3698 break;
3700 if((ptr=strchr(ptr, ' ')) != NULL)
3702 do {
3703 ++ptr;
3704 } while(isspace(*ptr));
3708 if(device)
3709 ALCdevice_DecRef(device);
3710 return bResult;
3714 /* alcGetProcAddress
3716 * Retrieves the function address for a particular extension function
3718 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3720 ALCvoid *ptr = NULL;
3722 if(!funcName)
3724 VerifyDevice(&device);
3725 alcSetError(device, ALC_INVALID_VALUE);
3726 if(device) ALCdevice_DecRef(device);
3728 else
3730 size_t i = 0;
3731 for(i = 0;i < COUNTOF(alcFunctions);i++)
3733 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3735 ptr = alcFunctions[i].address;
3736 break;
3741 return ptr;
3745 /* alcGetEnumValue
3747 * Get the value for a particular ALC enumeration name
3749 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3751 ALCenum val = 0;
3753 if(!enumName)
3755 VerifyDevice(&device);
3756 alcSetError(device, ALC_INVALID_VALUE);
3757 if(device) ALCdevice_DecRef(device);
3759 else
3761 size_t i = 0;
3762 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3764 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3766 val = alcEnumerations[i].value;
3767 break;
3772 return val;
3776 /* alcCreateContext
3778 * Create and attach a context to the given device.
3780 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3782 ALCcontext *ALContext;
3783 ALfloat valf;
3784 ALCenum err;
3786 /* Explicitly hold the list lock while taking the BackendLock in case the
3787 * device is asynchronously destropyed, to ensure this new context is
3788 * properly cleaned up after being made.
3790 LockLists();
3791 if(!VerifyDevice(&device) || device->Type == Capture ||
3792 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
3794 UnlockLists();
3795 alcSetError(device, ALC_INVALID_DEVICE);
3796 if(device) ALCdevice_DecRef(device);
3797 return NULL;
3799 almtx_lock(&device->BackendLock);
3800 UnlockLists();
3802 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3804 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3805 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3806 else
3807 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3808 if(!ALContext)
3810 almtx_unlock(&device->BackendLock);
3812 alcSetError(device, ALC_OUT_OF_MEMORY);
3813 ALCdevice_DecRef(device);
3814 return NULL;
3817 InitRef(&ALContext->ref, 1);
3818 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3819 ALContext->DefaultSlot = NULL;
3821 ALContext->Voices = NULL;
3822 ALContext->VoiceCount = 0;
3823 ALContext->MaxVoices = 0;
3824 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3825 ALContext->Device = device;
3826 ATOMIC_INIT(&ALContext->next, NULL);
3828 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3830 almtx_unlock(&device->BackendLock);
3832 al_free(ALContext);
3833 ALContext = NULL;
3835 alcSetError(device, err);
3836 if(err == ALC_INVALID_DEVICE)
3838 V0(device->Backend,lock)();
3839 aluHandleDisconnect(device, "Device update failure");
3840 V0(device->Backend,unlock)();
3842 ALCdevice_DecRef(device);
3843 return NULL;
3845 AllocateVoices(ALContext, 256, device->NumAuxSends);
3847 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3849 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3850 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3851 aluInitEffectPanning(ALContext->DefaultSlot);
3852 else
3854 ALContext->DefaultSlot = NULL;
3855 ERR("Failed to initialize the default effect slot\n");
3859 ALCdevice_IncRef(ALContext->Device);
3860 InitContext(ALContext);
3862 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3864 if(!isfinite(valf))
3865 ERR("volume-adjust must be finite: %f\n", valf);
3866 else
3868 ALfloat db = clampf(valf, -24.0f, 24.0f);
3869 if(db != valf)
3870 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3871 ALContext->GainBoost = powf(10.0f, db/20.0f);
3872 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3875 UpdateListenerProps(ALContext);
3878 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3879 do {
3880 ATOMIC_STORE(&ALContext->next, head, almemory_order_relaxed);
3881 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3882 ALContext) == 0);
3884 almtx_unlock(&device->BackendLock);
3886 if(ALContext->DefaultSlot)
3888 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3889 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3890 else
3891 ERR("Failed to initialize the default effect\n");
3894 ALCdevice_DecRef(device);
3896 TRACE("Created context %p\n", ALContext);
3897 return ALContext;
3900 /* alcDestroyContext
3902 * Remove a context from its device
3904 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3906 ALCdevice *Device;
3908 LockLists();
3909 if(!VerifyContext(&context))
3911 UnlockLists();
3912 alcSetError(NULL, ALC_INVALID_CONTEXT);
3913 return;
3916 Device = context->Device;
3917 if(Device)
3919 almtx_lock(&Device->BackendLock);
3920 if(!ReleaseContext(context, Device))
3922 V0(Device->Backend,stop)();
3923 Device->Flags &= ~DEVICE_RUNNING;
3925 almtx_unlock(&Device->BackendLock);
3927 UnlockLists();
3929 ALCcontext_DecRef(context);
3933 /* alcGetCurrentContext
3935 * Returns the currently active context on the calling thread
3937 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3939 ALCcontext *Context = altss_get(LocalContext);
3940 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3941 return Context;
3944 /* alcGetThreadContext
3946 * Returns the currently active thread-local context
3948 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3950 return altss_get(LocalContext);
3954 /* alcMakeContextCurrent
3956 * Makes the given context the active process-wide context, and removes the
3957 * thread-local context for the calling thread.
3959 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3961 /* context must be valid or NULL */
3962 if(context && !VerifyContext(&context))
3964 alcSetError(NULL, ALC_INVALID_CONTEXT);
3965 return ALC_FALSE;
3967 /* context's reference count is already incremented */
3968 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3969 if(context) ALCcontext_DecRef(context);
3971 if((context=altss_get(LocalContext)) != NULL)
3973 altss_set(LocalContext, NULL);
3974 ALCcontext_DecRef(context);
3977 return ALC_TRUE;
3980 /* alcSetThreadContext
3982 * Makes the given context the active context for the current thread
3984 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3986 ALCcontext *old;
3988 /* context must be valid or NULL */
3989 if(context && !VerifyContext(&context))
3991 alcSetError(NULL, ALC_INVALID_CONTEXT);
3992 return ALC_FALSE;
3994 /* context's reference count is already incremented */
3995 old = altss_get(LocalContext);
3996 altss_set(LocalContext, context);
3997 if(old) ALCcontext_DecRef(old);
3999 return ALC_TRUE;
4003 /* alcGetContextsDevice
4005 * Returns the device that a particular context is attached to
4007 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
4009 ALCdevice *Device;
4011 if(!VerifyContext(&Context))
4013 alcSetError(NULL, ALC_INVALID_CONTEXT);
4014 return NULL;
4016 Device = Context->Device;
4017 ALCcontext_DecRef(Context);
4019 return Device;
4023 /* alcOpenDevice
4025 * Opens the named device.
4027 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
4029 ALCbackendFactory *factory;
4030 const ALCchar *fmt;
4031 ALCdevice *device;
4032 ALCenum err;
4034 DO_INITCONFIG();
4036 if(!PlaybackBackend.name)
4038 alcSetError(NULL, ALC_INVALID_VALUE);
4039 return NULL;
4042 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
4043 #ifdef _WIN32
4044 /* Some old Windows apps hardcode these expecting OpenAL to use a
4045 * specific audio API, even when they're not enumerated. Creative's
4046 * router effectively ignores them too.
4048 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
4049 || strcasecmp(deviceName, "MMSYSTEM") == 0
4050 #endif
4052 deviceName = NULL;
4054 device = al_calloc(16, sizeof(ALCdevice));
4055 if(!device)
4057 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4058 return NULL;
4061 //Validate device
4062 InitDevice(device, Playback);
4064 //Set output format
4065 device->FmtChans = DevFmtChannelsDefault;
4066 device->FmtType = DevFmtTypeDefault;
4067 device->Frequency = DEFAULT_OUTPUT_RATE;
4068 device->IsHeadphones = AL_FALSE;
4069 device->AmbiLayout = AmbiLayout_Default;
4070 device->AmbiScale = AmbiNorm_Default;
4071 device->NumUpdates = 3;
4072 device->UpdateSize = 1024;
4074 device->SourcesMax = 256;
4075 device->AuxiliaryEffectSlotMax = 64;
4076 device->NumAuxSends = DEFAULT_SENDS;
4078 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4080 static const struct {
4081 const char name[16];
4082 enum DevFmtChannels chans;
4083 ALsizei order;
4084 } chanlist[] = {
4085 { "mono", DevFmtMono, 0 },
4086 { "stereo", DevFmtStereo, 0 },
4087 { "quad", DevFmtQuad, 0 },
4088 { "surround51", DevFmtX51, 0 },
4089 { "surround61", DevFmtX61, 0 },
4090 { "surround71", DevFmtX71, 0 },
4091 { "surround51rear", DevFmtX51Rear, 0 },
4092 { "ambi1", DevFmtAmbi3D, 1 },
4093 { "ambi2", DevFmtAmbi3D, 2 },
4094 { "ambi3", DevFmtAmbi3D, 3 },
4096 size_t i;
4098 for(i = 0;i < COUNTOF(chanlist);i++)
4100 if(strcasecmp(chanlist[i].name, fmt) == 0)
4102 device->FmtChans = chanlist[i].chans;
4103 device->AmbiOrder = chanlist[i].order;
4104 device->Flags |= DEVICE_CHANNELS_REQUEST;
4105 break;
4108 if(i == COUNTOF(chanlist))
4109 ERR("Unsupported channels: %s\n", fmt);
4111 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4113 static const struct {
4114 const char name[16];
4115 enum DevFmtType type;
4116 } typelist[] = {
4117 { "int8", DevFmtByte },
4118 { "uint8", DevFmtUByte },
4119 { "int16", DevFmtShort },
4120 { "uint16", DevFmtUShort },
4121 { "int32", DevFmtInt },
4122 { "uint32", DevFmtUInt },
4123 { "float32", DevFmtFloat },
4125 size_t i;
4127 for(i = 0;i < COUNTOF(typelist);i++)
4129 if(strcasecmp(typelist[i].name, fmt) == 0)
4131 device->FmtType = typelist[i].type;
4132 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4133 break;
4136 if(i == COUNTOF(typelist))
4137 ERR("Unsupported sample-type: %s\n", fmt);
4140 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4142 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4143 if(device->Frequency < MIN_OUTPUT_RATE)
4144 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4145 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4148 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4149 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4151 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4152 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4153 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4154 device->UpdateSize = (device->UpdateSize+3)&~3;
4156 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4157 if(device->SourcesMax == 0) device->SourcesMax = 256;
4159 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4160 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4161 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4163 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4164 device->NumAuxSends = clampi(
4165 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4168 device->NumStereoSources = 1;
4169 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4171 factory = PlaybackBackend.getFactory();
4172 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4173 if(!device->Backend)
4175 FreeDevice(device);
4176 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4177 return NULL;
4180 // Find a playback device to open
4181 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4183 FreeDevice(device);
4184 alcSetError(NULL, err);
4185 return NULL;
4188 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4190 if(strcasecmp(fmt, "fuma") == 0)
4192 device->AmbiLayout = AmbiLayout_FuMa;
4193 device->AmbiScale = AmbiNorm_FuMa;
4195 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4197 device->AmbiLayout = AmbiLayout_ACN;
4198 device->AmbiScale = AmbiNorm_SN3D;
4200 else if(strcasecmp(fmt, "acn+n3d") == 0)
4202 device->AmbiLayout = AmbiLayout_ACN;
4203 device->AmbiScale = AmbiNorm_N3D;
4205 else
4206 ERR("Unsupported ambi-format: %s\n", fmt);
4209 device->Limiter = CreateDeviceLimiter(device);
4212 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4213 do {
4214 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4215 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4218 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4219 return device;
4222 /* alcCloseDevice
4224 * Closes the given device.
4226 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4228 ALCdevice *iter, *origdev, *nextdev;
4229 ALCcontext *ctx;
4231 LockLists();
4232 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4233 do {
4234 if(iter == device)
4235 break;
4236 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4237 } while(iter != NULL);
4238 if(!iter || iter->Type == Capture)
4240 alcSetError(iter, ALC_INVALID_DEVICE);
4241 UnlockLists();
4242 return ALC_FALSE;
4244 almtx_lock(&device->BackendLock);
4246 origdev = device;
4247 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4248 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4250 ALCdevice *list;
4251 do {
4252 list = origdev;
4253 origdev = device;
4254 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4256 UnlockLists();
4258 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4259 while(ctx != NULL)
4261 ALCcontext *next = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
4262 WARN("Releasing context %p\n", ctx);
4263 ReleaseContext(ctx, device);
4264 ctx = next;
4266 if((device->Flags&DEVICE_RUNNING))
4267 V0(device->Backend,stop)();
4268 device->Flags &= ~DEVICE_RUNNING;
4269 almtx_unlock(&device->BackendLock);
4271 ALCdevice_DecRef(device);
4273 return ALC_TRUE;
4277 /************************************************
4278 * ALC capture functions
4279 ************************************************/
4280 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4282 ALCbackendFactory *factory;
4283 ALCdevice *device = NULL;
4284 ALCenum err;
4286 DO_INITCONFIG();
4288 if(!CaptureBackend.name)
4290 alcSetError(NULL, ALC_INVALID_VALUE);
4291 return NULL;
4294 if(samples <= 0)
4296 alcSetError(NULL, ALC_INVALID_VALUE);
4297 return NULL;
4300 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4301 deviceName = NULL;
4303 device = al_calloc(16, sizeof(ALCdevice));
4304 if(!device)
4306 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4307 return NULL;
4310 //Validate device
4311 InitDevice(device, Capture);
4313 device->Frequency = frequency;
4314 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4316 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4318 FreeDevice(device);
4319 alcSetError(NULL, ALC_INVALID_ENUM);
4320 return NULL;
4322 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4323 device->IsHeadphones = AL_FALSE;
4324 device->AmbiOrder = 0;
4325 device->AmbiLayout = AmbiLayout_Default;
4326 device->AmbiScale = AmbiNorm_Default;
4328 device->UpdateSize = samples;
4329 device->NumUpdates = 1;
4331 factory = CaptureBackend.getFactory();
4332 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4333 if(!device->Backend)
4335 FreeDevice(device);
4336 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4337 return NULL;
4340 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4341 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4342 device->Frequency, device->UpdateSize, device->NumUpdates
4344 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4346 FreeDevice(device);
4347 alcSetError(NULL, err);
4348 return NULL;
4352 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4353 do {
4354 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4355 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4358 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4359 return device;
4362 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4364 ALCdevice *iter, *origdev, *nextdev;
4366 LockLists();
4367 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4368 do {
4369 if(iter == device)
4370 break;
4371 iter = ATOMIC_LOAD(&iter->next, almemory_order_relaxed);
4372 } while(iter != NULL);
4373 if(!iter || iter->Type != Capture)
4375 alcSetError(iter, ALC_INVALID_DEVICE);
4376 UnlockLists();
4377 return ALC_FALSE;
4380 origdev = device;
4381 nextdev = ATOMIC_LOAD(&device->next, almemory_order_relaxed);
4382 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, nextdev))
4384 ALCdevice *list;
4385 do {
4386 list = origdev;
4387 origdev = device;
4388 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list->next, &origdev, nextdev));
4390 UnlockLists();
4392 ALCdevice_DecRef(device);
4394 return ALC_TRUE;
4397 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4399 if(!VerifyDevice(&device) || device->Type != Capture)
4400 alcSetError(device, ALC_INVALID_DEVICE);
4401 else
4403 almtx_lock(&device->BackendLock);
4404 if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
4405 alcSetError(device, ALC_INVALID_DEVICE);
4406 else if(!(device->Flags&DEVICE_RUNNING))
4408 if(V0(device->Backend,start)())
4409 device->Flags |= DEVICE_RUNNING;
4410 else
4412 aluHandleDisconnect(device, "Device start failure");
4413 alcSetError(device, ALC_INVALID_DEVICE);
4416 almtx_unlock(&device->BackendLock);
4419 if(device) ALCdevice_DecRef(device);
4422 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4424 if(!VerifyDevice(&device) || device->Type != Capture)
4425 alcSetError(device, ALC_INVALID_DEVICE);
4426 else
4428 almtx_lock(&device->BackendLock);
4429 if((device->Flags&DEVICE_RUNNING))
4430 V0(device->Backend,stop)();
4431 device->Flags &= ~DEVICE_RUNNING;
4432 almtx_unlock(&device->BackendLock);
4435 if(device) ALCdevice_DecRef(device);
4438 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4440 if(!VerifyDevice(&device) || device->Type != Capture)
4441 alcSetError(device, ALC_INVALID_DEVICE);
4442 else
4444 ALCenum err = ALC_INVALID_VALUE;
4446 almtx_lock(&device->BackendLock);
4447 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4448 err = V(device->Backend,captureSamples)(buffer, samples);
4449 almtx_unlock(&device->BackendLock);
4451 if(err != ALC_NO_ERROR)
4452 alcSetError(device, err);
4454 if(device) ALCdevice_DecRef(device);
4458 /************************************************
4459 * ALC loopback functions
4460 ************************************************/
4462 /* alcLoopbackOpenDeviceSOFT
4464 * Open a loopback device, for manual rendering.
4466 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4468 ALCbackendFactory *factory;
4469 ALCdevice *device;
4471 DO_INITCONFIG();
4473 /* Make sure the device name, if specified, is us. */
4474 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4476 alcSetError(NULL, ALC_INVALID_VALUE);
4477 return NULL;
4480 device = al_calloc(16, sizeof(ALCdevice));
4481 if(!device)
4483 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4484 return NULL;
4487 //Validate device
4488 InitDevice(device, Loopback);
4490 device->SourcesMax = 256;
4491 device->AuxiliaryEffectSlotMax = 64;
4492 device->NumAuxSends = DEFAULT_SENDS;
4494 //Set output format
4495 device->NumUpdates = 0;
4496 device->UpdateSize = 0;
4498 device->Frequency = DEFAULT_OUTPUT_RATE;
4499 device->FmtChans = DevFmtChannelsDefault;
4500 device->FmtType = DevFmtTypeDefault;
4501 device->IsHeadphones = AL_FALSE;
4502 device->AmbiLayout = AmbiLayout_Default;
4503 device->AmbiScale = AmbiNorm_Default;
4505 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4506 if(device->SourcesMax == 0) device->SourcesMax = 256;
4508 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4509 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4510 else device->AuxiliaryEffectSlotMax = minu(device->AuxiliaryEffectSlotMax, INT_MAX);
4512 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4513 device->NumAuxSends = clampi(
4514 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4517 device->NumStereoSources = 1;
4518 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4520 factory = ALCloopbackFactory_getFactory();
4521 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4522 if(!device->Backend)
4524 al_free(device);
4525 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4526 return NULL;
4529 // Open the "backend"
4530 V(device->Backend,open)("Loopback");
4532 device->Limiter = CreateDeviceLimiter(device);
4535 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4536 do {
4537 ATOMIC_STORE(&device->next, head, almemory_order_relaxed);
4538 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4541 TRACE("Created device %p\n", device);
4542 return device;
4545 /* alcIsRenderFormatSupportedSOFT
4547 * Determines if the loopback device supports the given format for rendering.
4549 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4551 ALCboolean ret = ALC_FALSE;
4553 if(!VerifyDevice(&device) || device->Type != Loopback)
4554 alcSetError(device, ALC_INVALID_DEVICE);
4555 else if(freq <= 0)
4556 alcSetError(device, ALC_INVALID_VALUE);
4557 else
4559 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4560 ret = ALC_TRUE;
4562 if(device) ALCdevice_DecRef(device);
4564 return ret;
4567 /* alcRenderSamplesSOFT
4569 * Renders some samples into a buffer, using the format last set by the
4570 * attributes given to alcCreateContext.
4572 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4574 if(!VerifyDevice(&device) || device->Type != Loopback)
4575 alcSetError(device, ALC_INVALID_DEVICE);
4576 else if(samples < 0 || (samples > 0 && buffer == NULL))
4577 alcSetError(device, ALC_INVALID_VALUE);
4578 else
4580 V0(device->Backend,lock)();
4581 aluMixData(device, buffer, samples);
4582 V0(device->Backend,unlock)();
4584 if(device) ALCdevice_DecRef(device);
4588 /************************************************
4589 * ALC DSP pause/resume functions
4590 ************************************************/
4592 /* alcDevicePauseSOFT
4594 * Pause the DSP to stop audio processing.
4596 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4598 if(!VerifyDevice(&device) || device->Type != Playback)
4599 alcSetError(device, ALC_INVALID_DEVICE);
4600 else
4602 almtx_lock(&device->BackendLock);
4603 if((device->Flags&DEVICE_RUNNING))
4604 V0(device->Backend,stop)();
4605 device->Flags &= ~DEVICE_RUNNING;
4606 device->Flags |= DEVICE_PAUSED;
4607 almtx_unlock(&device->BackendLock);
4609 if(device) ALCdevice_DecRef(device);
4612 /* alcDeviceResumeSOFT
4614 * Resume the DSP to restart audio processing.
4616 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4618 if(!VerifyDevice(&device) || device->Type != Playback)
4619 alcSetError(device, ALC_INVALID_DEVICE);
4620 else
4622 almtx_lock(&device->BackendLock);
4623 if((device->Flags&DEVICE_PAUSED))
4625 device->Flags &= ~DEVICE_PAUSED;
4626 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4628 if(V0(device->Backend,start)() != ALC_FALSE)
4629 device->Flags |= DEVICE_RUNNING;
4630 else
4632 V0(device->Backend,lock)();
4633 aluHandleDisconnect(device, "Device start failure");
4634 V0(device->Backend,unlock)();
4635 alcSetError(device, ALC_INVALID_DEVICE);
4639 almtx_unlock(&device->BackendLock);
4641 if(device) ALCdevice_DecRef(device);
4645 /************************************************
4646 * ALC HRTF functions
4647 ************************************************/
4649 /* alcGetStringiSOFT
4651 * Gets a string parameter at the given index.
4653 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4655 const ALCchar *str = NULL;
4657 if(!VerifyDevice(&device) || device->Type == Capture)
4658 alcSetError(device, ALC_INVALID_DEVICE);
4659 else switch(paramName)
4661 case ALC_HRTF_SPECIFIER_SOFT:
4662 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4663 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4664 else
4665 alcSetError(device, ALC_INVALID_VALUE);
4666 break;
4668 default:
4669 alcSetError(device, ALC_INVALID_ENUM);
4670 break;
4672 if(device) ALCdevice_DecRef(device);
4674 return str;
4677 /* alcResetDeviceSOFT
4679 * Resets the given device output, using the specified attribute list.
4681 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4683 ALCenum err;
4685 LockLists();
4686 if(!VerifyDevice(&device) || device->Type == Capture ||
4687 !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed))
4689 UnlockLists();
4690 alcSetError(device, ALC_INVALID_DEVICE);
4691 if(device) ALCdevice_DecRef(device);
4692 return ALC_FALSE;
4694 almtx_lock(&device->BackendLock);
4695 UnlockLists();
4697 err = UpdateDeviceParams(device, attribs);
4698 almtx_unlock(&device->BackendLock);
4700 if(err != ALC_NO_ERROR)
4702 alcSetError(device, err);
4703 if(err == ALC_INVALID_DEVICE)
4705 V0(device->Backend,lock)();
4706 aluHandleDisconnect(device, "Device start failure");
4707 V0(device->Backend,unlock)();
4709 ALCdevice_DecRef(device);
4710 return ALC_FALSE;
4712 ALCdevice_DecRef(device);
4714 return ALC_TRUE;