Use separate macros for atomics that don't take a memory order
[openal-soft.git] / Alc / ALc.c
blob95d5e178d1b3efe031dc91dc15143887552a9b19
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "bformatdec.h"
39 #include "alu.h"
41 #include "compat.h"
42 #include "threads.h"
43 #include "alstring.h"
44 #include "almalloc.h"
46 #include "backends/base.h"
49 /************************************************
50 * Backends
51 ************************************************/
52 struct BackendInfo {
53 const char *name;
54 ALCbackendFactory* (*getFactory)(void);
55 ALCboolean (*Init)(BackendFuncs*);
56 void (*Deinit)(void);
57 void (*Probe)(enum DevProbe);
58 BackendFuncs Funcs;
61 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
62 static struct BackendInfo BackendList[] = {
63 #ifdef HAVE_JACK
64 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
68 #endif
69 #ifdef HAVE_ALSA
70 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
71 #endif
72 #ifdef HAVE_COREAUDIO
73 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_OSS
76 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
77 #endif
78 #ifdef HAVE_SOLARIS
79 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
80 #endif
81 #ifdef HAVE_SNDIO
82 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
83 #endif
84 #ifdef HAVE_QSA
85 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
86 #endif
87 #ifdef HAVE_MMDEVAPI
88 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
89 #endif
90 #ifdef HAVE_DSOUND
91 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
92 #endif
93 #ifdef HAVE_WINMM
94 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
95 #endif
96 #ifdef HAVE_PORTAUDIO
97 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
98 #endif
99 #ifdef HAVE_OPENSL
100 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
101 #endif
103 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #ifdef HAVE_WAVE
105 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #endif
108 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
110 #undef EmptyFuncs
112 static struct BackendInfo PlaybackBackend;
113 static struct BackendInfo CaptureBackend;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 typedef struct ALCfunction {
120 const ALCchar *funcName;
121 ALCvoid *address;
122 } ALCfunction;
124 typedef struct ALCenums {
125 const ALCchar *enumName;
126 ALCenum value;
127 } ALCenums;
129 #define DECL(x) { #x, (ALCvoid*)(x) }
130 static const ALCfunction alcFunctions[] = {
131 DECL(alcCreateContext),
132 DECL(alcMakeContextCurrent),
133 DECL(alcProcessContext),
134 DECL(alcSuspendContext),
135 DECL(alcDestroyContext),
136 DECL(alcGetCurrentContext),
137 DECL(alcGetContextsDevice),
138 DECL(alcOpenDevice),
139 DECL(alcCloseDevice),
140 DECL(alcGetError),
141 DECL(alcIsExtensionPresent),
142 DECL(alcGetProcAddress),
143 DECL(alcGetEnumValue),
144 DECL(alcGetString),
145 DECL(alcGetIntegerv),
146 DECL(alcCaptureOpenDevice),
147 DECL(alcCaptureCloseDevice),
148 DECL(alcCaptureStart),
149 DECL(alcCaptureStop),
150 DECL(alcCaptureSamples),
152 DECL(alcSetThreadContext),
153 DECL(alcGetThreadContext),
155 DECL(alcLoopbackOpenDeviceSOFT),
156 DECL(alcIsRenderFormatSupportedSOFT),
157 DECL(alcRenderSamplesSOFT),
159 DECL(alcDevicePauseSOFT),
160 DECL(alcDeviceResumeSOFT),
162 DECL(alcGetStringiSOFT),
163 DECL(alcResetDeviceSOFT),
165 DECL(alcGetInteger64vSOFT),
167 DECL(alEnable),
168 DECL(alDisable),
169 DECL(alIsEnabled),
170 DECL(alGetString),
171 DECL(alGetBooleanv),
172 DECL(alGetIntegerv),
173 DECL(alGetFloatv),
174 DECL(alGetDoublev),
175 DECL(alGetBoolean),
176 DECL(alGetInteger),
177 DECL(alGetFloat),
178 DECL(alGetDouble),
179 DECL(alGetError),
180 DECL(alIsExtensionPresent),
181 DECL(alGetProcAddress),
182 DECL(alGetEnumValue),
183 DECL(alListenerf),
184 DECL(alListener3f),
185 DECL(alListenerfv),
186 DECL(alListeneri),
187 DECL(alListener3i),
188 DECL(alListeneriv),
189 DECL(alGetListenerf),
190 DECL(alGetListener3f),
191 DECL(alGetListenerfv),
192 DECL(alGetListeneri),
193 DECL(alGetListener3i),
194 DECL(alGetListeneriv),
195 DECL(alGenSources),
196 DECL(alDeleteSources),
197 DECL(alIsSource),
198 DECL(alSourcef),
199 DECL(alSource3f),
200 DECL(alSourcefv),
201 DECL(alSourcei),
202 DECL(alSource3i),
203 DECL(alSourceiv),
204 DECL(alGetSourcef),
205 DECL(alGetSource3f),
206 DECL(alGetSourcefv),
207 DECL(alGetSourcei),
208 DECL(alGetSource3i),
209 DECL(alGetSourceiv),
210 DECL(alSourcePlayv),
211 DECL(alSourceStopv),
212 DECL(alSourceRewindv),
213 DECL(alSourcePausev),
214 DECL(alSourcePlay),
215 DECL(alSourceStop),
216 DECL(alSourceRewind),
217 DECL(alSourcePause),
218 DECL(alSourceQueueBuffers),
219 DECL(alSourceUnqueueBuffers),
220 DECL(alGenBuffers),
221 DECL(alDeleteBuffers),
222 DECL(alIsBuffer),
223 DECL(alBufferData),
224 DECL(alBufferf),
225 DECL(alBuffer3f),
226 DECL(alBufferfv),
227 DECL(alBufferi),
228 DECL(alBuffer3i),
229 DECL(alBufferiv),
230 DECL(alGetBufferf),
231 DECL(alGetBuffer3f),
232 DECL(alGetBufferfv),
233 DECL(alGetBufferi),
234 DECL(alGetBuffer3i),
235 DECL(alGetBufferiv),
236 DECL(alDopplerFactor),
237 DECL(alDopplerVelocity),
238 DECL(alSpeedOfSound),
239 DECL(alDistanceModel),
241 DECL(alGenFilters),
242 DECL(alDeleteFilters),
243 DECL(alIsFilter),
244 DECL(alFilteri),
245 DECL(alFilteriv),
246 DECL(alFilterf),
247 DECL(alFilterfv),
248 DECL(alGetFilteri),
249 DECL(alGetFilteriv),
250 DECL(alGetFilterf),
251 DECL(alGetFilterfv),
252 DECL(alGenEffects),
253 DECL(alDeleteEffects),
254 DECL(alIsEffect),
255 DECL(alEffecti),
256 DECL(alEffectiv),
257 DECL(alEffectf),
258 DECL(alEffectfv),
259 DECL(alGetEffecti),
260 DECL(alGetEffectiv),
261 DECL(alGetEffectf),
262 DECL(alGetEffectfv),
263 DECL(alGenAuxiliaryEffectSlots),
264 DECL(alDeleteAuxiliaryEffectSlots),
265 DECL(alIsAuxiliaryEffectSlot),
266 DECL(alAuxiliaryEffectSloti),
267 DECL(alAuxiliaryEffectSlotiv),
268 DECL(alAuxiliaryEffectSlotf),
269 DECL(alAuxiliaryEffectSlotfv),
270 DECL(alGetAuxiliaryEffectSloti),
271 DECL(alGetAuxiliaryEffectSlotiv),
272 DECL(alGetAuxiliaryEffectSlotf),
273 DECL(alGetAuxiliaryEffectSlotfv),
275 DECL(alDeferUpdatesSOFT),
276 DECL(alProcessUpdatesSOFT),
278 DECL(alSourcedSOFT),
279 DECL(alSource3dSOFT),
280 DECL(alSourcedvSOFT),
281 DECL(alGetSourcedSOFT),
282 DECL(alGetSource3dSOFT),
283 DECL(alGetSourcedvSOFT),
284 DECL(alSourcei64SOFT),
285 DECL(alSource3i64SOFT),
286 DECL(alSourcei64vSOFT),
287 DECL(alGetSourcei64SOFT),
288 DECL(alGetSource3i64SOFT),
289 DECL(alGetSourcei64vSOFT),
291 DECL(alBufferSamplesSOFT),
292 DECL(alGetBufferSamplesSOFT),
293 DECL(alIsBufferFormatSupportedSOFT),
295 { NULL, NULL }
297 #undef DECL
299 #define DECL(x) { #x, (x) }
300 static const ALCenums enumeration[] = {
301 DECL(ALC_INVALID),
302 DECL(ALC_FALSE),
303 DECL(ALC_TRUE),
305 DECL(ALC_MAJOR_VERSION),
306 DECL(ALC_MINOR_VERSION),
307 DECL(ALC_ATTRIBUTES_SIZE),
308 DECL(ALC_ALL_ATTRIBUTES),
309 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
310 DECL(ALC_DEVICE_SPECIFIER),
311 DECL(ALC_ALL_DEVICES_SPECIFIER),
312 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
313 DECL(ALC_EXTENSIONS),
314 DECL(ALC_FREQUENCY),
315 DECL(ALC_REFRESH),
316 DECL(ALC_SYNC),
317 DECL(ALC_MONO_SOURCES),
318 DECL(ALC_STEREO_SOURCES),
319 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
320 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
321 DECL(ALC_CAPTURE_SAMPLES),
322 DECL(ALC_CONNECTED),
324 DECL(ALC_EFX_MAJOR_VERSION),
325 DECL(ALC_EFX_MINOR_VERSION),
326 DECL(ALC_MAX_AUXILIARY_SENDS),
328 DECL(ALC_FORMAT_CHANNELS_SOFT),
329 DECL(ALC_FORMAT_TYPE_SOFT),
331 DECL(ALC_MONO_SOFT),
332 DECL(ALC_STEREO_SOFT),
333 DECL(ALC_QUAD_SOFT),
334 DECL(ALC_5POINT1_SOFT),
335 DECL(ALC_6POINT1_SOFT),
336 DECL(ALC_7POINT1_SOFT),
338 DECL(ALC_BYTE_SOFT),
339 DECL(ALC_UNSIGNED_BYTE_SOFT),
340 DECL(ALC_SHORT_SOFT),
341 DECL(ALC_UNSIGNED_SHORT_SOFT),
342 DECL(ALC_INT_SOFT),
343 DECL(ALC_UNSIGNED_INT_SOFT),
344 DECL(ALC_FLOAT_SOFT),
346 DECL(ALC_HRTF_SOFT),
347 DECL(ALC_DONT_CARE_SOFT),
348 DECL(ALC_HRTF_STATUS_SOFT),
349 DECL(ALC_HRTF_DISABLED_SOFT),
350 DECL(ALC_HRTF_ENABLED_SOFT),
351 DECL(ALC_HRTF_DENIED_SOFT),
352 DECL(ALC_HRTF_REQUIRED_SOFT),
353 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
354 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
355 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
356 DECL(ALC_HRTF_SPECIFIER_SOFT),
357 DECL(ALC_HRTF_ID_SOFT),
359 DECL(ALC_NO_ERROR),
360 DECL(ALC_INVALID_DEVICE),
361 DECL(ALC_INVALID_CONTEXT),
362 DECL(ALC_INVALID_ENUM),
363 DECL(ALC_INVALID_VALUE),
364 DECL(ALC_OUT_OF_MEMORY),
367 DECL(AL_INVALID),
368 DECL(AL_NONE),
369 DECL(AL_FALSE),
370 DECL(AL_TRUE),
372 DECL(AL_SOURCE_RELATIVE),
373 DECL(AL_CONE_INNER_ANGLE),
374 DECL(AL_CONE_OUTER_ANGLE),
375 DECL(AL_PITCH),
376 DECL(AL_POSITION),
377 DECL(AL_DIRECTION),
378 DECL(AL_VELOCITY),
379 DECL(AL_LOOPING),
380 DECL(AL_BUFFER),
381 DECL(AL_GAIN),
382 DECL(AL_MIN_GAIN),
383 DECL(AL_MAX_GAIN),
384 DECL(AL_ORIENTATION),
385 DECL(AL_REFERENCE_DISTANCE),
386 DECL(AL_ROLLOFF_FACTOR),
387 DECL(AL_CONE_OUTER_GAIN),
388 DECL(AL_MAX_DISTANCE),
389 DECL(AL_SEC_OFFSET),
390 DECL(AL_SAMPLE_OFFSET),
391 DECL(AL_BYTE_OFFSET),
392 DECL(AL_SOURCE_TYPE),
393 DECL(AL_STATIC),
394 DECL(AL_STREAMING),
395 DECL(AL_UNDETERMINED),
396 DECL(AL_METERS_PER_UNIT),
397 DECL(AL_LOOP_POINTS_SOFT),
398 DECL(AL_DIRECT_CHANNELS_SOFT),
400 DECL(AL_DIRECT_FILTER),
401 DECL(AL_AUXILIARY_SEND_FILTER),
402 DECL(AL_AIR_ABSORPTION_FACTOR),
403 DECL(AL_ROOM_ROLLOFF_FACTOR),
404 DECL(AL_CONE_OUTER_GAINHF),
405 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
406 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
407 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
409 DECL(AL_SOURCE_STATE),
410 DECL(AL_INITIAL),
411 DECL(AL_PLAYING),
412 DECL(AL_PAUSED),
413 DECL(AL_STOPPED),
415 DECL(AL_BUFFERS_QUEUED),
416 DECL(AL_BUFFERS_PROCESSED),
418 DECL(AL_FORMAT_MONO8),
419 DECL(AL_FORMAT_MONO16),
420 DECL(AL_FORMAT_MONO_FLOAT32),
421 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
422 DECL(AL_FORMAT_STEREO8),
423 DECL(AL_FORMAT_STEREO16),
424 DECL(AL_FORMAT_STEREO_FLOAT32),
425 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
426 DECL(AL_FORMAT_MONO_IMA4),
427 DECL(AL_FORMAT_STEREO_IMA4),
428 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
429 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
430 DECL(AL_FORMAT_QUAD8_LOKI),
431 DECL(AL_FORMAT_QUAD16_LOKI),
432 DECL(AL_FORMAT_QUAD8),
433 DECL(AL_FORMAT_QUAD16),
434 DECL(AL_FORMAT_QUAD32),
435 DECL(AL_FORMAT_51CHN8),
436 DECL(AL_FORMAT_51CHN16),
437 DECL(AL_FORMAT_51CHN32),
438 DECL(AL_FORMAT_61CHN8),
439 DECL(AL_FORMAT_61CHN16),
440 DECL(AL_FORMAT_61CHN32),
441 DECL(AL_FORMAT_71CHN8),
442 DECL(AL_FORMAT_71CHN16),
443 DECL(AL_FORMAT_71CHN32),
444 DECL(AL_FORMAT_REAR8),
445 DECL(AL_FORMAT_REAR16),
446 DECL(AL_FORMAT_REAR32),
447 DECL(AL_FORMAT_MONO_MULAW),
448 DECL(AL_FORMAT_MONO_MULAW_EXT),
449 DECL(AL_FORMAT_STEREO_MULAW),
450 DECL(AL_FORMAT_STEREO_MULAW_EXT),
451 DECL(AL_FORMAT_QUAD_MULAW),
452 DECL(AL_FORMAT_51CHN_MULAW),
453 DECL(AL_FORMAT_61CHN_MULAW),
454 DECL(AL_FORMAT_71CHN_MULAW),
455 DECL(AL_FORMAT_REAR_MULAW),
456 DECL(AL_FORMAT_MONO_ALAW_EXT),
457 DECL(AL_FORMAT_STEREO_ALAW_EXT),
459 DECL(AL_FORMAT_BFORMAT2D_8),
460 DECL(AL_FORMAT_BFORMAT2D_16),
461 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
462 DECL(AL_FORMAT_BFORMAT2D_MULAW),
463 DECL(AL_FORMAT_BFORMAT3D_8),
464 DECL(AL_FORMAT_BFORMAT3D_16),
465 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
466 DECL(AL_FORMAT_BFORMAT3D_MULAW),
468 DECL(AL_MONO8_SOFT),
469 DECL(AL_MONO16_SOFT),
470 DECL(AL_MONO32F_SOFT),
471 DECL(AL_STEREO8_SOFT),
472 DECL(AL_STEREO16_SOFT),
473 DECL(AL_STEREO32F_SOFT),
474 DECL(AL_QUAD8_SOFT),
475 DECL(AL_QUAD16_SOFT),
476 DECL(AL_QUAD32F_SOFT),
477 DECL(AL_REAR8_SOFT),
478 DECL(AL_REAR16_SOFT),
479 DECL(AL_REAR32F_SOFT),
480 DECL(AL_5POINT1_8_SOFT),
481 DECL(AL_5POINT1_16_SOFT),
482 DECL(AL_5POINT1_32F_SOFT),
483 DECL(AL_6POINT1_8_SOFT),
484 DECL(AL_6POINT1_16_SOFT),
485 DECL(AL_6POINT1_32F_SOFT),
486 DECL(AL_7POINT1_8_SOFT),
487 DECL(AL_7POINT1_16_SOFT),
488 DECL(AL_7POINT1_32F_SOFT),
489 DECL(AL_BFORMAT2D_8_SOFT),
490 DECL(AL_BFORMAT2D_16_SOFT),
491 DECL(AL_BFORMAT2D_32F_SOFT),
492 DECL(AL_BFORMAT3D_8_SOFT),
493 DECL(AL_BFORMAT3D_16_SOFT),
494 DECL(AL_BFORMAT3D_32F_SOFT),
496 DECL(AL_MONO_SOFT),
497 DECL(AL_STEREO_SOFT),
498 DECL(AL_QUAD_SOFT),
499 DECL(AL_REAR_SOFT),
500 DECL(AL_5POINT1_SOFT),
501 DECL(AL_6POINT1_SOFT),
502 DECL(AL_7POINT1_SOFT),
503 DECL(AL_BFORMAT2D_SOFT),
504 DECL(AL_BFORMAT3D_SOFT),
506 DECL(AL_BYTE_SOFT),
507 DECL(AL_UNSIGNED_BYTE_SOFT),
508 DECL(AL_SHORT_SOFT),
509 DECL(AL_UNSIGNED_SHORT_SOFT),
510 DECL(AL_INT_SOFT),
511 DECL(AL_UNSIGNED_INT_SOFT),
512 DECL(AL_FLOAT_SOFT),
513 DECL(AL_DOUBLE_SOFT),
514 DECL(AL_BYTE3_SOFT),
515 DECL(AL_UNSIGNED_BYTE3_SOFT),
516 DECL(AL_MULAW_SOFT),
518 DECL(AL_FREQUENCY),
519 DECL(AL_BITS),
520 DECL(AL_CHANNELS),
521 DECL(AL_SIZE),
522 DECL(AL_INTERNAL_FORMAT_SOFT),
523 DECL(AL_BYTE_LENGTH_SOFT),
524 DECL(AL_SAMPLE_LENGTH_SOFT),
525 DECL(AL_SEC_LENGTH_SOFT),
526 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
527 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_SOURCE_RADIUS),
531 DECL(AL_STEREO_ANGLES),
533 DECL(AL_UNUSED),
534 DECL(AL_PENDING),
535 DECL(AL_PROCESSED),
537 DECL(AL_NO_ERROR),
538 DECL(AL_INVALID_NAME),
539 DECL(AL_INVALID_ENUM),
540 DECL(AL_INVALID_VALUE),
541 DECL(AL_INVALID_OPERATION),
542 DECL(AL_OUT_OF_MEMORY),
544 DECL(AL_VENDOR),
545 DECL(AL_VERSION),
546 DECL(AL_RENDERER),
547 DECL(AL_EXTENSIONS),
549 DECL(AL_DOPPLER_FACTOR),
550 DECL(AL_DOPPLER_VELOCITY),
551 DECL(AL_DISTANCE_MODEL),
552 DECL(AL_SPEED_OF_SOUND),
553 DECL(AL_SOURCE_DISTANCE_MODEL),
554 DECL(AL_DEFERRED_UPDATES_SOFT),
555 DECL(AL_GAIN_LIMIT_SOFT),
557 DECL(AL_INVERSE_DISTANCE),
558 DECL(AL_INVERSE_DISTANCE_CLAMPED),
559 DECL(AL_LINEAR_DISTANCE),
560 DECL(AL_LINEAR_DISTANCE_CLAMPED),
561 DECL(AL_EXPONENT_DISTANCE),
562 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
564 DECL(AL_FILTER_TYPE),
565 DECL(AL_FILTER_NULL),
566 DECL(AL_FILTER_LOWPASS),
567 DECL(AL_FILTER_HIGHPASS),
568 DECL(AL_FILTER_BANDPASS),
570 DECL(AL_LOWPASS_GAIN),
571 DECL(AL_LOWPASS_GAINHF),
573 DECL(AL_HIGHPASS_GAIN),
574 DECL(AL_HIGHPASS_GAINLF),
576 DECL(AL_BANDPASS_GAIN),
577 DECL(AL_BANDPASS_GAINHF),
578 DECL(AL_BANDPASS_GAINLF),
580 DECL(AL_EFFECT_TYPE),
581 DECL(AL_EFFECT_NULL),
582 DECL(AL_EFFECT_REVERB),
583 DECL(AL_EFFECT_EAXREVERB),
584 DECL(AL_EFFECT_CHORUS),
585 DECL(AL_EFFECT_DISTORTION),
586 DECL(AL_EFFECT_ECHO),
587 DECL(AL_EFFECT_FLANGER),
588 #if 0
589 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
590 DECL(AL_EFFECT_VOCAL_MORPHER),
591 DECL(AL_EFFECT_PITCH_SHIFTER),
592 #endif
593 DECL(AL_EFFECT_RING_MODULATOR),
594 #if 0
595 DECL(AL_EFFECT_AUTOWAH),
596 #endif
597 DECL(AL_EFFECT_COMPRESSOR),
598 DECL(AL_EFFECT_EQUALIZER),
599 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
600 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
602 DECL(AL_EAXREVERB_DENSITY),
603 DECL(AL_EAXREVERB_DIFFUSION),
604 DECL(AL_EAXREVERB_GAIN),
605 DECL(AL_EAXREVERB_GAINHF),
606 DECL(AL_EAXREVERB_GAINLF),
607 DECL(AL_EAXREVERB_DECAY_TIME),
608 DECL(AL_EAXREVERB_DECAY_HFRATIO),
609 DECL(AL_EAXREVERB_DECAY_LFRATIO),
610 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
611 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
612 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
613 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
614 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
615 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
616 DECL(AL_EAXREVERB_ECHO_TIME),
617 DECL(AL_EAXREVERB_ECHO_DEPTH),
618 DECL(AL_EAXREVERB_MODULATION_TIME),
619 DECL(AL_EAXREVERB_MODULATION_DEPTH),
620 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
621 DECL(AL_EAXREVERB_HFREFERENCE),
622 DECL(AL_EAXREVERB_LFREFERENCE),
623 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
624 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
626 DECL(AL_REVERB_DENSITY),
627 DECL(AL_REVERB_DIFFUSION),
628 DECL(AL_REVERB_GAIN),
629 DECL(AL_REVERB_GAINHF),
630 DECL(AL_REVERB_DECAY_TIME),
631 DECL(AL_REVERB_DECAY_HFRATIO),
632 DECL(AL_REVERB_REFLECTIONS_GAIN),
633 DECL(AL_REVERB_REFLECTIONS_DELAY),
634 DECL(AL_REVERB_LATE_REVERB_GAIN),
635 DECL(AL_REVERB_LATE_REVERB_DELAY),
636 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
637 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
638 DECL(AL_REVERB_DECAY_HFLIMIT),
640 DECL(AL_CHORUS_WAVEFORM),
641 DECL(AL_CHORUS_PHASE),
642 DECL(AL_CHORUS_RATE),
643 DECL(AL_CHORUS_DEPTH),
644 DECL(AL_CHORUS_FEEDBACK),
645 DECL(AL_CHORUS_DELAY),
647 DECL(AL_DISTORTION_EDGE),
648 DECL(AL_DISTORTION_GAIN),
649 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
650 DECL(AL_DISTORTION_EQCENTER),
651 DECL(AL_DISTORTION_EQBANDWIDTH),
653 DECL(AL_ECHO_DELAY),
654 DECL(AL_ECHO_LRDELAY),
655 DECL(AL_ECHO_DAMPING),
656 DECL(AL_ECHO_FEEDBACK),
657 DECL(AL_ECHO_SPREAD),
659 DECL(AL_FLANGER_WAVEFORM),
660 DECL(AL_FLANGER_PHASE),
661 DECL(AL_FLANGER_RATE),
662 DECL(AL_FLANGER_DEPTH),
663 DECL(AL_FLANGER_FEEDBACK),
664 DECL(AL_FLANGER_DELAY),
666 DECL(AL_RING_MODULATOR_FREQUENCY),
667 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
668 DECL(AL_RING_MODULATOR_WAVEFORM),
670 DECL(AL_COMPRESSOR_ONOFF),
672 DECL(AL_EQUALIZER_LOW_GAIN),
673 DECL(AL_EQUALIZER_LOW_CUTOFF),
674 DECL(AL_EQUALIZER_MID1_GAIN),
675 DECL(AL_EQUALIZER_MID1_CENTER),
676 DECL(AL_EQUALIZER_MID1_WIDTH),
677 DECL(AL_EQUALIZER_MID2_GAIN),
678 DECL(AL_EQUALIZER_MID2_CENTER),
679 DECL(AL_EQUALIZER_MID2_WIDTH),
680 DECL(AL_EQUALIZER_HIGH_GAIN),
681 DECL(AL_EQUALIZER_HIGH_CUTOFF),
683 DECL(AL_DEDICATED_GAIN),
685 { NULL, (ALCenum)0 }
687 #undef DECL
689 static const ALCchar alcNoError[] = "No Error";
690 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
691 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
692 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
693 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
694 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
697 /************************************************
698 * Global variables
699 ************************************************/
701 /* Enumerated device names */
702 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
704 static al_string alcAllDevicesList;
705 static al_string alcCaptureDeviceList;
707 /* Default is always the first in the list */
708 static ALCchar *alcDefaultAllDevicesSpecifier;
709 static ALCchar *alcCaptureDefaultDeviceSpecifier;
711 /* Default context extensions */
712 static const ALchar alExtList[] =
713 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
714 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
715 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
716 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
717 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
718 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
719 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
721 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
723 /* Thread-local current context */
724 static altss_t LocalContext;
725 /* Process-wide current context */
726 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
728 /* Mixing thread piority level */
729 ALint RTPrioLevel;
731 FILE *LogFile;
732 #ifdef _DEBUG
733 enum LogLevel LogLevel = LogWarning;
734 #else
735 enum LogLevel LogLevel = LogError;
736 #endif
738 /* Flag to trap ALC device errors */
739 static ALCboolean TrapALCError = ALC_FALSE;
741 /* One-time configuration init control */
742 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
744 /* Default effect that applies to sources that don't have an effect on send 0 */
745 static ALeffect DefaultEffect;
747 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
748 * updates.
750 static ALCboolean SuspendDefers = ALC_TRUE;
753 /************************************************
754 * ALC information
755 ************************************************/
756 static const ALCchar alcNoDeviceExtList[] =
757 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
758 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
759 static const ALCchar alcExtensionList[] =
760 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
761 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
762 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
763 "ALC_SOFT_loopback ALC_SOFT_pause_device";
764 static const ALCint alcMajorVersion = 1;
765 static const ALCint alcMinorVersion = 1;
767 static const ALCint alcEFXMajorVersion = 1;
768 static const ALCint alcEFXMinorVersion = 0;
771 /************************************************
772 * Device lists
773 ************************************************/
774 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
776 static almtx_t ListLock;
777 static inline void LockLists(void)
779 int ret = almtx_lock(&ListLock);
780 assert(ret == althrd_success);
782 static inline void UnlockLists(void)
784 int ret = almtx_unlock(&ListLock);
785 assert(ret == althrd_success);
788 /************************************************
789 * Library initialization
790 ************************************************/
791 #if defined(_WIN32)
792 static void alc_init(void);
793 static void alc_deinit(void);
794 static void alc_deinit_safe(void);
796 #ifndef AL_LIBTYPE_STATIC
797 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
799 switch(reason)
801 case DLL_PROCESS_ATTACH:
802 /* Pin the DLL so we won't get unloaded until the process terminates */
803 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
804 (WCHAR*)hModule, &hModule);
805 alc_init();
806 break;
808 case DLL_THREAD_DETACH:
809 break;
811 case DLL_PROCESS_DETACH:
812 if(!lpReserved)
813 alc_deinit();
814 else
815 alc_deinit_safe();
816 break;
818 return TRUE;
820 #elif defined(_MSC_VER)
821 #pragma section(".CRT$XCU",read)
822 static void alc_constructor(void);
823 static void alc_destructor(void);
824 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
826 static void alc_constructor(void)
828 atexit(alc_destructor);
829 alc_init();
832 static void alc_destructor(void)
834 alc_deinit();
836 #elif defined(HAVE_GCC_DESTRUCTOR)
837 static void alc_init(void) __attribute__((constructor));
838 static void alc_deinit(void) __attribute__((destructor));
839 #else
840 #error "No static initialization available on this platform!"
841 #endif
843 #elif defined(HAVE_GCC_DESTRUCTOR)
845 static void alc_init(void) __attribute__((constructor));
846 static void alc_deinit(void) __attribute__((destructor));
848 #else
849 #error "No global initialization available on this platform!"
850 #endif
852 static void ReleaseThreadCtx(void *ptr);
853 static void alc_init(void)
855 const char *str;
856 int ret;
858 LogFile = stderr;
860 AL_STRING_INIT(alcAllDevicesList);
861 AL_STRING_INIT(alcCaptureDeviceList);
863 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
864 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
865 ConeScale *= 0.5f;
867 str = getenv("__ALSOFT_REVERSE_Z");
868 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
869 ZScale *= -1.0f;
871 ret = altss_create(&LocalContext, ReleaseThreadCtx);
872 assert(ret == althrd_success);
874 ret = almtx_init(&ListLock, almtx_recursive);
875 assert(ret == althrd_success);
877 ThunkInit();
880 static void alc_initconfig(void)
882 const char *devs, *str;
883 ALuint capfilter;
884 float valf;
885 int i, n;
887 str = getenv("ALSOFT_LOGLEVEL");
888 if(str)
890 long lvl = strtol(str, NULL, 0);
891 if(lvl >= NoLog && lvl <= LogRef)
892 LogLevel = lvl;
895 str = getenv("ALSOFT_LOGFILE");
896 if(str && str[0])
898 FILE *logfile = al_fopen(str, "wt");
899 if(logfile) LogFile = logfile;
900 else ERR("Failed to open log file '%s'\n", str);
904 char buf[1024] = "";
905 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
906 for(i = 1;BackendList[i].name;i++)
907 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
908 TRACE("Supported backends: %s\n", buf);
910 ReadALConfig();
912 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
913 if(str && *str)
915 if(strcasecmp(str, "ignore") == 0)
917 SuspendDefers = ALC_FALSE;
918 TRACE("Selected context suspend behavior, \"ignore\"\n");
920 else
921 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
924 capfilter = 0;
925 #if defined(HAVE_SSE4_1)
926 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
927 #elif defined(HAVE_SSE3)
928 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
929 #elif defined(HAVE_SSE2)
930 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
931 #elif defined(HAVE_SSE)
932 capfilter |= CPU_CAP_SSE;
933 #endif
934 #ifdef HAVE_NEON
935 capfilter |= CPU_CAP_NEON;
936 #endif
937 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
939 if(strcasecmp(str, "all") == 0)
940 capfilter = 0;
941 else
943 size_t len;
944 const char *next = str;
946 do {
947 str = next;
948 while(isspace(str[0]))
949 str++;
950 next = strchr(str, ',');
952 if(!str[0] || str[0] == ',')
953 continue;
955 len = (next ? ((size_t)(next-str)) : strlen(str));
956 while(len > 0 && isspace(str[len-1]))
957 len--;
958 if(len == 3 && strncasecmp(str, "sse", len) == 0)
959 capfilter &= ~CPU_CAP_SSE;
960 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
961 capfilter &= ~CPU_CAP_SSE2;
962 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
963 capfilter &= ~CPU_CAP_SSE3;
964 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
965 capfilter &= ~CPU_CAP_SSE4_1;
966 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
967 capfilter &= ~CPU_CAP_NEON;
968 else
969 WARN("Invalid CPU extension \"%s\"\n", str);
970 } while(next++);
973 FillCPUCaps(capfilter);
975 #ifdef _WIN32
976 RTPrioLevel = 1;
977 #else
978 RTPrioLevel = 0;
979 #endif
980 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
982 aluInitMixer();
984 str = getenv("ALSOFT_TRAP_ERROR");
985 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
987 TrapALError = AL_TRUE;
988 TrapALCError = AL_TRUE;
990 else
992 str = getenv("ALSOFT_TRAP_AL_ERROR");
993 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
994 TrapALError = AL_TRUE;
995 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
997 str = getenv("ALSOFT_TRAP_ALC_ERROR");
998 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
999 TrapALCError = ALC_TRUE;
1000 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1003 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1004 ReverbBoost *= powf(10.0f, valf / 20.0f);
1006 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1008 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1009 ConfigValueStr(NULL, NULL, "drivers", &devs))
1011 int n;
1012 size_t len;
1013 const char *next = devs;
1014 int endlist, delitem;
1016 i = 0;
1017 do {
1018 devs = next;
1019 while(isspace(devs[0]))
1020 devs++;
1021 next = strchr(devs, ',');
1023 delitem = (devs[0] == '-');
1024 if(devs[0] == '-') devs++;
1026 if(!devs[0] || devs[0] == ',')
1028 endlist = 0;
1029 continue;
1031 endlist = 1;
1033 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1034 while(len > 0 && isspace(devs[len-1]))
1035 len--;
1036 for(n = i;BackendList[n].name;n++)
1038 if(len == strlen(BackendList[n].name) &&
1039 strncmp(BackendList[n].name, devs, len) == 0)
1041 if(delitem)
1043 do {
1044 BackendList[n] = BackendList[n+1];
1045 ++n;
1046 } while(BackendList[n].name);
1048 else
1050 struct BackendInfo Bkp = BackendList[n];
1051 while(n > i)
1053 BackendList[n] = BackendList[n-1];
1054 --n;
1056 BackendList[n] = Bkp;
1058 i++;
1060 break;
1063 } while(next++);
1065 if(endlist)
1067 BackendList[i].name = NULL;
1068 BackendList[i].getFactory = NULL;
1069 BackendList[i].Init = NULL;
1070 BackendList[i].Deinit = NULL;
1071 BackendList[i].Probe = NULL;
1075 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1077 if(BackendList[i].getFactory)
1079 ALCbackendFactory *factory = BackendList[i].getFactory();
1080 if(!V0(factory,init)())
1082 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1083 continue;
1086 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1087 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1089 PlaybackBackend = BackendList[i];
1090 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1092 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1094 CaptureBackend = BackendList[i];
1095 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1098 continue;
1101 if(!BackendList[i].Init(&BackendList[i].Funcs))
1103 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1104 continue;
1107 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1108 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1110 PlaybackBackend = BackendList[i];
1111 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1113 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1115 CaptureBackend = BackendList[i];
1116 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1120 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1121 V0(factory,init)();
1124 if(!PlaybackBackend.name)
1125 WARN("No playback backend available!\n");
1126 if(!CaptureBackend.name)
1127 WARN("No capture backend available!\n");
1129 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1131 size_t len;
1132 const char *next = str;
1134 do {
1135 str = next;
1136 next = strchr(str, ',');
1138 if(!str[0] || next == str)
1139 continue;
1141 len = (next ? ((size_t)(next-str)) : strlen(str));
1142 for(n = 0;EffectList[n].name;n++)
1144 if(len == strlen(EffectList[n].name) &&
1145 strncmp(EffectList[n].name, str, len) == 0)
1146 DisabledEffects[EffectList[n].type] = AL_TRUE;
1148 } while(next++);
1151 InitEffectFactoryMap();
1153 InitEffect(&DefaultEffect);
1154 str = getenv("ALSOFT_DEFAULT_REVERB");
1155 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1156 LoadReverbPreset(str, &DefaultEffect);
1158 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1161 /************************************************
1162 * Library deinitialization
1163 ************************************************/
1164 static void alc_cleanup(void)
1166 ALCdevice *dev;
1168 AL_STRING_DEINIT(alcAllDevicesList);
1169 AL_STRING_DEINIT(alcCaptureDeviceList);
1171 free(alcDefaultAllDevicesSpecifier);
1172 alcDefaultAllDevicesSpecifier = NULL;
1173 free(alcCaptureDefaultDeviceSpecifier);
1174 alcCaptureDefaultDeviceSpecifier = NULL;
1176 if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL)
1178 ALCuint num = 0;
1179 do {
1180 num++;
1181 } while((dev=dev->next) != NULL);
1182 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1185 DeinitEffectFactoryMap();
1188 static void alc_deinit_safe(void)
1190 alc_cleanup();
1192 FreeHrtfs();
1193 FreeALConfig();
1195 ThunkExit();
1196 almtx_destroy(&ListLock);
1197 altss_delete(LocalContext);
1199 if(LogFile != stderr)
1200 fclose(LogFile);
1201 LogFile = NULL;
1204 static void alc_deinit(void)
1206 int i;
1208 alc_cleanup();
1210 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1211 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1213 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1215 if(!BackendList[i].getFactory)
1216 BackendList[i].Deinit();
1217 else
1219 ALCbackendFactory *factory = BackendList[i].getFactory();
1220 V0(factory,deinit)();
1224 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1225 V0(factory,deinit)();
1228 alc_deinit_safe();
1232 /************************************************
1233 * Device enumeration
1234 ************************************************/
1235 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1237 DO_INITCONFIG();
1239 LockLists();
1240 al_string_clear(list);
1242 if(backendinfo->Probe)
1243 backendinfo->Probe(type);
1244 else if(backendinfo->getFactory)
1246 ALCbackendFactory *factory = backendinfo->getFactory();
1247 V(factory,probe)(type);
1250 UnlockLists();
1252 static void ProbeAllDevicesList(void)
1253 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1254 static void ProbeCaptureDeviceList(void)
1255 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1257 static void AppendDevice(const ALCchar *name, al_string *devnames)
1259 size_t len = strlen(name);
1260 if(len > 0)
1261 al_string_append_range(devnames, name, name+len+1);
1263 void AppendAllDevicesList(const ALCchar *name)
1264 { AppendDevice(name, &alcAllDevicesList); }
1265 void AppendCaptureDeviceList(const ALCchar *name)
1266 { AppendDevice(name, &alcCaptureDeviceList); }
1269 /************************************************
1270 * Device format information
1271 ************************************************/
1272 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1274 switch(type)
1276 case DevFmtByte: return "Signed Byte";
1277 case DevFmtUByte: return "Unsigned Byte";
1278 case DevFmtShort: return "Signed Short";
1279 case DevFmtUShort: return "Unsigned Short";
1280 case DevFmtInt: return "Signed Int";
1281 case DevFmtUInt: return "Unsigned Int";
1282 case DevFmtFloat: return "Float";
1284 return "(unknown type)";
1286 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1288 switch(chans)
1290 case DevFmtMono: return "Mono";
1291 case DevFmtStereo: return "Stereo";
1292 case DevFmtQuad: return "Quadraphonic";
1293 case DevFmtX51: return "5.1 Surround";
1294 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1295 case DevFmtX61: return "6.1 Surround";
1296 case DevFmtX71: return "7.1 Surround";
1297 case DevFmtAmbi1: return "Ambisonic (1st Order)";
1298 case DevFmtAmbi2: return "Ambisonic (2nd Order)";
1299 case DevFmtAmbi3: return "Ambisonic (3rd Order)";
1301 return "(unknown channels)";
1304 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1305 ALuint BytesFromDevFmt(enum DevFmtType type)
1307 switch(type)
1309 case DevFmtByte: return sizeof(ALbyte);
1310 case DevFmtUByte: return sizeof(ALubyte);
1311 case DevFmtShort: return sizeof(ALshort);
1312 case DevFmtUShort: return sizeof(ALushort);
1313 case DevFmtInt: return sizeof(ALint);
1314 case DevFmtUInt: return sizeof(ALuint);
1315 case DevFmtFloat: return sizeof(ALfloat);
1317 return 0;
1319 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1321 switch(chans)
1323 case DevFmtMono: return 1;
1324 case DevFmtStereo: return 2;
1325 case DevFmtQuad: return 4;
1326 case DevFmtX51: return 6;
1327 case DevFmtX51Rear: return 6;
1328 case DevFmtX61: return 7;
1329 case DevFmtX71: return 8;
1330 case DevFmtAmbi1: return 4;
1331 case DevFmtAmbi2: return 9;
1332 case DevFmtAmbi3: return 16;
1334 return 0;
1337 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1338 enum DevFmtType *type)
1340 static const struct {
1341 ALenum format;
1342 enum DevFmtChannels channels;
1343 enum DevFmtType type;
1344 } list[] = {
1345 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1346 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1347 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1349 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1350 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1351 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1353 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1354 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1355 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1357 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1358 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1359 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1361 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1362 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1363 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1365 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1366 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1367 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1369 ALuint i;
1371 for(i = 0;i < COUNTOF(list);i++)
1373 if(list[i].format == format)
1375 *chans = list[i].channels;
1376 *type = list[i].type;
1377 return AL_TRUE;
1381 return AL_FALSE;
1384 static ALCboolean IsValidALCType(ALCenum type)
1386 switch(type)
1388 case ALC_BYTE_SOFT:
1389 case ALC_UNSIGNED_BYTE_SOFT:
1390 case ALC_SHORT_SOFT:
1391 case ALC_UNSIGNED_SHORT_SOFT:
1392 case ALC_INT_SOFT:
1393 case ALC_UNSIGNED_INT_SOFT:
1394 case ALC_FLOAT_SOFT:
1395 return ALC_TRUE;
1397 return ALC_FALSE;
1400 static ALCboolean IsValidALCChannels(ALCenum channels)
1402 switch(channels)
1404 case ALC_MONO_SOFT:
1405 case ALC_STEREO_SOFT:
1406 case ALC_QUAD_SOFT:
1407 case ALC_5POINT1_SOFT:
1408 case ALC_6POINT1_SOFT:
1409 case ALC_7POINT1_SOFT:
1410 return ALC_TRUE;
1412 return ALC_FALSE;
1416 /************************************************
1417 * Miscellaneous ALC helpers
1418 ************************************************/
1420 extern inline void LockContext(ALCcontext *context);
1421 extern inline void UnlockContext(ALCcontext *context);
1423 void ALCdevice_Lock(ALCdevice *device)
1425 V0(device->Backend,lock)();
1428 void ALCdevice_Unlock(ALCdevice *device)
1430 V0(device->Backend,unlock)();
1434 /* SetDefaultWFXChannelOrder
1436 * Sets the default channel order used by WaveFormatEx.
1438 void SetDefaultWFXChannelOrder(ALCdevice *device)
1440 ALuint i;
1442 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1443 device->RealOut.ChannelName[i] = InvalidChannel;
1445 switch(device->FmtChans)
1447 case DevFmtMono:
1448 device->RealOut.ChannelName[0] = FrontCenter;
1449 break;
1450 case DevFmtStereo:
1451 device->RealOut.ChannelName[0] = FrontLeft;
1452 device->RealOut.ChannelName[1] = FrontRight;
1453 break;
1454 case DevFmtQuad:
1455 device->RealOut.ChannelName[0] = FrontLeft;
1456 device->RealOut.ChannelName[1] = FrontRight;
1457 device->RealOut.ChannelName[2] = BackLeft;
1458 device->RealOut.ChannelName[3] = BackRight;
1459 break;
1460 case DevFmtX51:
1461 device->RealOut.ChannelName[0] = FrontLeft;
1462 device->RealOut.ChannelName[1] = FrontRight;
1463 device->RealOut.ChannelName[2] = FrontCenter;
1464 device->RealOut.ChannelName[3] = LFE;
1465 device->RealOut.ChannelName[4] = SideLeft;
1466 device->RealOut.ChannelName[5] = SideRight;
1467 break;
1468 case DevFmtX51Rear:
1469 device->RealOut.ChannelName[0] = FrontLeft;
1470 device->RealOut.ChannelName[1] = FrontRight;
1471 device->RealOut.ChannelName[2] = FrontCenter;
1472 device->RealOut.ChannelName[3] = LFE;
1473 device->RealOut.ChannelName[4] = BackLeft;
1474 device->RealOut.ChannelName[5] = BackRight;
1475 break;
1476 case DevFmtX61:
1477 device->RealOut.ChannelName[0] = FrontLeft;
1478 device->RealOut.ChannelName[1] = FrontRight;
1479 device->RealOut.ChannelName[2] = FrontCenter;
1480 device->RealOut.ChannelName[3] = LFE;
1481 device->RealOut.ChannelName[4] = BackCenter;
1482 device->RealOut.ChannelName[5] = SideLeft;
1483 device->RealOut.ChannelName[6] = SideRight;
1484 break;
1485 case DevFmtX71:
1486 device->RealOut.ChannelName[0] = FrontLeft;
1487 device->RealOut.ChannelName[1] = FrontRight;
1488 device->RealOut.ChannelName[2] = FrontCenter;
1489 device->RealOut.ChannelName[3] = LFE;
1490 device->RealOut.ChannelName[4] = BackLeft;
1491 device->RealOut.ChannelName[5] = BackRight;
1492 device->RealOut.ChannelName[6] = SideLeft;
1493 device->RealOut.ChannelName[7] = SideRight;
1494 break;
1495 case DevFmtAmbi1:
1496 device->RealOut.ChannelName[0] = Aux0;
1497 device->RealOut.ChannelName[1] = Aux1;
1498 device->RealOut.ChannelName[2] = Aux2;
1499 device->RealOut.ChannelName[3] = Aux3;
1500 break;
1501 case DevFmtAmbi2:
1502 device->RealOut.ChannelName[0] = Aux0;
1503 device->RealOut.ChannelName[1] = Aux1;
1504 device->RealOut.ChannelName[2] = Aux2;
1505 device->RealOut.ChannelName[3] = Aux3;
1506 device->RealOut.ChannelName[4] = Aux4;
1507 device->RealOut.ChannelName[5] = Aux5;
1508 device->RealOut.ChannelName[6] = Aux6;
1509 device->RealOut.ChannelName[7] = Aux7;
1510 device->RealOut.ChannelName[8] = Aux8;
1511 break;
1512 case DevFmtAmbi3:
1513 device->RealOut.ChannelName[0] = Aux0;
1514 device->RealOut.ChannelName[1] = Aux1;
1515 device->RealOut.ChannelName[2] = Aux2;
1516 device->RealOut.ChannelName[3] = Aux3;
1517 device->RealOut.ChannelName[4] = Aux4;
1518 device->RealOut.ChannelName[5] = Aux5;
1519 device->RealOut.ChannelName[6] = Aux6;
1520 device->RealOut.ChannelName[7] = Aux7;
1521 device->RealOut.ChannelName[8] = Aux8;
1522 device->RealOut.ChannelName[9] = Aux9;
1523 device->RealOut.ChannelName[10] = Aux10;
1524 device->RealOut.ChannelName[11] = Aux11;
1525 device->RealOut.ChannelName[12] = Aux12;
1526 device->RealOut.ChannelName[13] = Aux13;
1527 device->RealOut.ChannelName[14] = Aux14;
1528 device->RealOut.ChannelName[15] = Aux15;
1529 break;
1533 /* SetDefaultChannelOrder
1535 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1537 void SetDefaultChannelOrder(ALCdevice *device)
1539 ALuint i;
1541 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1542 device->RealOut.ChannelName[i] = InvalidChannel;
1544 switch(device->FmtChans)
1546 case DevFmtX51Rear:
1547 device->RealOut.ChannelName[0] = FrontLeft;
1548 device->RealOut.ChannelName[1] = FrontRight;
1549 device->RealOut.ChannelName[2] = BackLeft;
1550 device->RealOut.ChannelName[3] = BackRight;
1551 device->RealOut.ChannelName[4] = FrontCenter;
1552 device->RealOut.ChannelName[5] = LFE;
1553 return;
1554 case DevFmtX71:
1555 device->RealOut.ChannelName[0] = FrontLeft;
1556 device->RealOut.ChannelName[1] = FrontRight;
1557 device->RealOut.ChannelName[2] = BackLeft;
1558 device->RealOut.ChannelName[3] = BackRight;
1559 device->RealOut.ChannelName[4] = FrontCenter;
1560 device->RealOut.ChannelName[5] = LFE;
1561 device->RealOut.ChannelName[6] = SideLeft;
1562 device->RealOut.ChannelName[7] = SideRight;
1563 return;
1565 /* Same as WFX order */
1566 case DevFmtMono:
1567 case DevFmtStereo:
1568 case DevFmtQuad:
1569 case DevFmtX51:
1570 case DevFmtX61:
1571 case DevFmtAmbi1:
1572 case DevFmtAmbi2:
1573 case DevFmtAmbi3:
1574 SetDefaultWFXChannelOrder(device);
1575 break;
1579 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1582 /* ALCcontext_DeferUpdates
1584 * Defers/suspends updates for the given context's listener and sources. This
1585 * does *NOT* stop mixing, but rather prevents certain property changes from
1586 * taking effect.
1588 void ALCcontext_DeferUpdates(ALCcontext *context, ALenum type)
1590 ATOMIC_STORE_SEQ(&context->DeferUpdates, type);
1593 /* ALCcontext_ProcessUpdates
1595 * Resumes update processing after being deferred.
1597 void ALCcontext_ProcessUpdates(ALCcontext *context)
1599 ALCdevice *device = context->Device;
1601 ReadLock(&context->PropLock);
1602 if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE))
1604 ALsizei pos;
1605 uint updates;
1607 /* Tell the mixer to stop applying updates, then wait for any active
1608 * updating to finish, before providing updates.
1610 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1611 while(((updates=ReadRef(&context->UpdateCount))&1) != 0)
1612 althrd_yield();
1614 UpdateListenerProps(context);
1615 UpdateAllEffectSlotProps(context);
1617 LockUIntMapRead(&context->SourceMap);
1618 V0(device->Backend,lock)();
1619 for(pos = 0;pos < context->SourceMap.size;pos++)
1621 ALsource *Source = context->SourceMap.values[pos];
1622 ALenum new_state;
1624 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1625 Source->OffsetType != AL_NONE)
1627 WriteLock(&Source->queue_lock);
1628 ApplyOffset(Source);
1629 WriteUnlock(&Source->queue_lock);
1632 new_state = Source->new_state;
1633 Source->new_state = AL_NONE;
1634 if(new_state)
1635 SetSourceState(Source, context, new_state);
1637 V0(device->Backend,unlock)();
1638 UnlockUIntMapRead(&context->SourceMap);
1640 UpdateAllSourceProps(context);
1642 /* Now with all updates declared, let the mixer continue applying them
1643 * so they all happen at once.
1645 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1647 ReadUnlock(&context->PropLock);
1651 /* alcSetError
1653 * Stores the latest ALC device error
1655 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1657 if(TrapALCError)
1659 #ifdef _WIN32
1660 /* DebugBreak() will cause an exception if there is no debugger */
1661 if(IsDebuggerPresent())
1662 DebugBreak();
1663 #elif defined(SIGTRAP)
1664 raise(SIGTRAP);
1665 #endif
1668 if(device)
1669 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1670 else
1671 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1675 /* UpdateClockBase
1677 * Updates the device's base clock time with however many samples have been
1678 * done. This is used so frequency changes on the device don't cause the time
1679 * to jump forward or back.
1681 static inline void UpdateClockBase(ALCdevice *device)
1683 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1684 device->SamplesDone = 0;
1687 /* UpdateDeviceParams
1689 * Updates device parameters according to the attribute list (caller is
1690 * responsible for holding the list lock).
1692 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1694 ALCcontext *context;
1695 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1696 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1697 enum DevFmtChannels oldChans;
1698 enum DevFmtType oldType;
1699 ALCuint oldFreq;
1700 FPUCtl oldMode;
1701 ALCsizei hrtf_id = -1;
1702 size_t size;
1704 // Check for attributes
1705 if(device->Type == Loopback)
1707 enum {
1708 GotFreq = 1<<0,
1709 GotChans = 1<<1,
1710 GotType = 1<<2,
1711 GotAll = GotFreq|GotChans|GotType
1713 ALCuint freq, numMono, numStereo, numSends;
1714 enum DevFmtChannels schans;
1715 enum DevFmtType stype;
1716 ALCuint attrIdx = 0;
1717 ALCint gotFmt = 0;
1719 if(!attrList)
1721 WARN("Missing attributes for loopback device\n");
1722 return ALC_INVALID_VALUE;
1725 numMono = device->NumMonoSources;
1726 numStereo = device->NumStereoSources;
1727 numSends = device->NumAuxSends;
1728 schans = device->FmtChans;
1729 stype = device->FmtType;
1730 freq = device->Frequency;
1732 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1733 while(attrList[attrIdx])
1735 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1737 ALCint val = attrList[attrIdx + 1];
1738 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val);
1739 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1740 return ALC_INVALID_VALUE;
1741 schans = val;
1742 gotFmt |= GotChans;
1745 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1747 ALCint val = attrList[attrIdx + 1];
1748 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val);
1749 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1750 return ALC_INVALID_VALUE;
1751 stype = val;
1752 gotFmt |= GotType;
1755 if(attrList[attrIdx] == ALC_FREQUENCY)
1757 freq = attrList[attrIdx + 1];
1758 TRACE_ATTR(ALC_FREQUENCY, freq);
1759 if(freq < MIN_OUTPUT_RATE)
1760 return ALC_INVALID_VALUE;
1761 gotFmt |= GotFreq;
1764 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1766 numStereo = attrList[attrIdx + 1];
1767 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1768 if(numStereo > device->SourcesMax)
1769 numStereo = device->SourcesMax;
1771 numMono = device->SourcesMax - numStereo;
1774 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1776 numSends = attrList[attrIdx + 1];
1777 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1780 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1782 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1783 if(attrList[attrIdx + 1] == ALC_FALSE)
1784 hrtf_appreq = Hrtf_Disable;
1785 else if(attrList[attrIdx + 1] == ALC_TRUE)
1786 hrtf_appreq = Hrtf_Enable;
1787 else
1788 hrtf_appreq = Hrtf_Default;
1791 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1793 hrtf_id = attrList[attrIdx + 1];
1794 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1797 attrIdx += 2;
1799 #undef TRACE_ATTR
1801 if(gotFmt != GotAll)
1803 WARN("Missing format for loopback device\n");
1804 return ALC_INVALID_VALUE;
1807 ConfigValueUInt(NULL, NULL, "sends", &numSends);
1808 numSends = minu(MAX_SENDS, numSends);
1810 if((device->Flags&DEVICE_RUNNING))
1811 V0(device->Backend,stop)();
1812 device->Flags &= ~DEVICE_RUNNING;
1814 UpdateClockBase(device);
1816 device->Frequency = freq;
1817 device->FmtChans = schans;
1818 device->FmtType = stype;
1819 device->NumMonoSources = numMono;
1820 device->NumStereoSources = numStereo;
1821 device->NumAuxSends = numSends;
1823 else if(attrList && attrList[0])
1825 ALCuint freq, numMono, numStereo, numSends;
1826 ALCuint attrIdx = 0;
1828 /* If a context is already running on the device, stop playback so the
1829 * device attributes can be updated. */
1830 if((device->Flags&DEVICE_RUNNING))
1831 V0(device->Backend,stop)();
1832 device->Flags &= ~DEVICE_RUNNING;
1834 freq = device->Frequency;
1835 numMono = device->NumMonoSources;
1836 numStereo = device->NumStereoSources;
1837 numSends = device->NumAuxSends;
1839 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1840 while(attrList[attrIdx])
1842 if(attrList[attrIdx] == ALC_FREQUENCY)
1844 freq = attrList[attrIdx + 1];
1845 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1846 TRACE_ATTR(ALC_FREQUENCY, freq);
1849 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1851 numStereo = attrList[attrIdx + 1];
1852 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1853 if(numStereo > device->SourcesMax)
1854 numStereo = device->SourcesMax;
1856 numMono = device->SourcesMax - numStereo;
1859 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1861 numSends = attrList[attrIdx + 1];
1862 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1865 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1867 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1868 if(attrList[attrIdx + 1] == ALC_FALSE)
1869 hrtf_appreq = Hrtf_Disable;
1870 else if(attrList[attrIdx + 1] == ALC_TRUE)
1871 hrtf_appreq = Hrtf_Enable;
1872 else
1873 hrtf_appreq = Hrtf_Default;
1876 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1878 hrtf_id = attrList[attrIdx + 1];
1879 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1882 attrIdx += 2;
1884 #undef TRACE_ATTR
1886 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1887 freq = maxu(freq, MIN_OUTPUT_RATE);
1889 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
1890 numSends = minu(MAX_SENDS, numSends);
1892 UpdateClockBase(device);
1894 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1895 device->Frequency;
1896 /* SSE and Neon do best with the update size being a multiple of 4 */
1897 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1898 device->UpdateSize = (device->UpdateSize+3)&~3;
1900 device->Frequency = freq;
1901 device->NumMonoSources = numMono;
1902 device->NumStereoSources = numStereo;
1903 device->NumAuxSends = numSends;
1906 if((device->Flags&DEVICE_RUNNING))
1907 return ALC_NO_ERROR;
1909 al_free(device->Uhj_Encoder);
1910 device->Uhj_Encoder = NULL;
1912 al_free(device->Bs2b);
1913 device->Bs2b = NULL;
1915 al_free(device->Dry.Buffer);
1916 device->Dry.Buffer = NULL;
1917 device->Dry.NumChannels = 0;
1918 device->FOAOut.Buffer = NULL;
1919 device->FOAOut.NumChannels = 0;
1920 device->RealOut.Buffer = NULL;
1921 device->RealOut.NumChannels = 0;
1923 UpdateClockBase(device);
1925 /*************************************************************************
1926 * Update device format request if HRTF is requested
1928 device->Hrtf.Status = ALC_HRTF_DISABLED_SOFT;
1929 if(device->Type != Loopback)
1931 const char *hrtf;
1932 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
1934 if(strcasecmp(hrtf, "true") == 0)
1935 hrtf_userreq = Hrtf_Enable;
1936 else if(strcasecmp(hrtf, "false") == 0)
1937 hrtf_userreq = Hrtf_Disable;
1938 else if(strcasecmp(hrtf, "auto") != 0)
1939 ERR("Unexpected hrtf value: %s\n", hrtf);
1942 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
1944 if(VECTOR_SIZE(device->Hrtf.List) == 0)
1946 VECTOR_DEINIT(device->Hrtf.List);
1947 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
1949 if(VECTOR_SIZE(device->Hrtf.List) > 0)
1951 device->FmtChans = DevFmtStereo;
1952 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf.List))
1953 device->Frequency = VECTOR_ELEM(device->Hrtf.List, hrtf_id).hrtf->sampleRate;
1954 else
1955 device->Frequency = VECTOR_ELEM(device->Hrtf.List, 0).hrtf->sampleRate;
1956 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
1958 else
1960 hrtf_userreq = Hrtf_Default;
1961 hrtf_appreq = Hrtf_Disable;
1962 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1966 else if(hrtf_appreq == Hrtf_Enable)
1968 size_t i = VECTOR_SIZE(device->Hrtf.List);
1969 /* Loopback device. We don't need to match to a specific HRTF entry
1970 * here. If the requested ID matches, we'll pick that later, if not,
1971 * we'll try to auto-select one anyway. Just make sure one exists
1972 * that'll work.
1974 if(device->FmtChans == DevFmtStereo)
1976 if(VECTOR_SIZE(device->Hrtf.List) == 0)
1978 VECTOR_DEINIT(device->Hrtf.List);
1979 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
1981 for(i = 0;i < VECTOR_SIZE(device->Hrtf.List);i++)
1983 const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf.List, i).hrtf;
1984 if(hrtf->sampleRate == device->Frequency)
1985 break;
1988 if(i == VECTOR_SIZE(device->Hrtf.List))
1990 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1991 DevFmtChannelsString(device->FmtChans), device->Frequency);
1992 hrtf_appreq = Hrtf_Disable;
1993 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1997 oldFreq = device->Frequency;
1998 oldChans = device->FmtChans;
1999 oldType = device->FmtType;
2001 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2002 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2003 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2004 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2005 device->UpdateSize, device->NumUpdates
2008 if(V0(device->Backend,reset)() == ALC_FALSE)
2009 return ALC_INVALID_DEVICE;
2011 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2013 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2014 DevFmtChannelsString(device->FmtChans));
2015 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2017 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2019 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2020 DevFmtTypeString(device->FmtType));
2021 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2023 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2025 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2026 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2029 if((device->UpdateSize&3) != 0)
2031 if((CPUCapFlags&CPU_CAP_SSE))
2032 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2033 if((CPUCapFlags&CPU_CAP_NEON))
2034 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2037 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2038 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2039 device->Frequency, device->UpdateSize, device->NumUpdates
2042 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2044 /* Allocate extra channels for any post-filter output. */
2045 size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]);
2046 if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2))
2047 size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]);
2048 else if(device->Hrtf.Handle || device->Uhj_Encoder || device->AmbiDecoder)
2049 size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]);
2050 else if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
2051 size += 4 * sizeof(device->Dry.Buffer[0]);
2052 device->Dry.Buffer = al_calloc(16, size);
2053 if(!device->Dry.Buffer)
2055 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2056 return ALC_INVALID_DEVICE;
2059 if(device->Hrtf.Handle || device->Uhj_Encoder || device->AmbiDecoder)
2061 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2062 device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
2064 else
2066 device->RealOut.Buffer = device->Dry.Buffer;
2067 device->RealOut.NumChannels = device->Dry.NumChannels;
2070 if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) ||
2071 (device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3))
2073 /* Higher-order rendering requires upsampling first-order content, so
2074 * make sure to mix it separately.
2076 device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels;
2077 device->FOAOut.NumChannels = 4;
2079 else
2081 device->FOAOut.Buffer = device->Dry.Buffer;
2082 device->FOAOut.NumChannels = device->Dry.NumChannels;
2085 SetMixerFPUMode(&oldMode);
2086 if(device->DefaultSlot)
2088 ALeffectslot *slot = device->DefaultSlot;
2089 ALeffectState *state = slot->Effect.State;
2091 state->OutBuffer = device->Dry.Buffer;
2092 state->OutChannels = device->Dry.NumChannels;
2093 if(V(state,deviceUpdate)(device) == AL_FALSE)
2095 RestoreFPUMode(&oldMode);
2096 return ALC_INVALID_DEVICE;
2098 UpdateEffectSlotProps(slot);
2101 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2102 while(context)
2104 ALsizei pos;
2106 ReadLock(&context->PropLock);
2107 LockUIntMapRead(&context->EffectSlotMap);
2108 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2110 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2111 ALeffectState *state = slot->Effect.State;
2113 state->OutBuffer = device->Dry.Buffer;
2114 state->OutChannels = device->Dry.NumChannels;
2115 if(V(state,deviceUpdate)(device) == AL_FALSE)
2117 UnlockUIntMapRead(&context->EffectSlotMap);
2118 ReadUnlock(&context->PropLock);
2119 RestoreFPUMode(&oldMode);
2120 return ALC_INVALID_DEVICE;
2123 UpdateEffectSlotProps(slot);
2125 UnlockUIntMapRead(&context->EffectSlotMap);
2127 LockUIntMapRead(&context->SourceMap);
2128 for(pos = 0;pos < context->SourceMap.size;pos++)
2130 ALsource *source = context->SourceMap.values[pos];
2131 ALuint s = device->NumAuxSends;
2132 while(s < MAX_SENDS)
2134 if(source->Send[s].Slot)
2135 DecrementRef(&source->Send[s].Slot->ref);
2136 source->Send[s].Slot = NULL;
2137 source->Send[s].Gain = 1.0f;
2138 source->Send[s].GainHF = 1.0f;
2139 source->Send[s].HFReference = LOWPASSFREQREF;
2140 source->Send[s].GainLF = 1.0f;
2141 source->Send[s].LFReference = HIGHPASSFREQREF;
2142 s++;
2144 source->NeedsUpdate = AL_TRUE;
2146 UnlockUIntMapRead(&context->SourceMap);
2148 UpdateListenerProps(context);
2149 ReadUnlock(&context->PropLock);
2151 context = context->next;
2153 RestoreFPUMode(&oldMode);
2155 if(!(device->Flags&DEVICE_PAUSED))
2157 if(V0(device->Backend,start)() == ALC_FALSE)
2158 return ALC_INVALID_DEVICE;
2159 device->Flags |= DEVICE_RUNNING;
2162 return ALC_NO_ERROR;
2165 /* FreeDevice
2167 * Frees the device structure, and destroys any objects the app failed to
2168 * delete. Called once there's no more references on the device.
2170 static ALCvoid FreeDevice(ALCdevice *device)
2172 TRACE("%p\n", device);
2174 V0(device->Backend,close)();
2175 DELETE_OBJ(device->Backend);
2176 device->Backend = NULL;
2178 almtx_destroy(&device->BackendLock);
2180 if(device->DefaultSlot)
2182 DeinitEffectSlot(device->DefaultSlot);
2183 device->DefaultSlot = NULL;
2186 if(device->BufferMap.size > 0)
2188 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2189 (device->BufferMap.size==1)?"":"s");
2190 ReleaseALBuffers(device);
2192 ResetUIntMap(&device->BufferMap);
2194 if(device->EffectMap.size > 0)
2196 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2197 (device->EffectMap.size==1)?"":"s");
2198 ReleaseALEffects(device);
2200 ResetUIntMap(&device->EffectMap);
2202 if(device->FilterMap.size > 0)
2204 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2205 (device->FilterMap.size==1)?"":"s");
2206 ReleaseALFilters(device);
2208 ResetUIntMap(&device->FilterMap);
2210 AL_STRING_DEINIT(device->Hrtf.Name);
2211 FreeHrtfList(&device->Hrtf.List);
2213 al_free(device->Bs2b);
2214 device->Bs2b = NULL;
2216 al_free(device->Uhj_Encoder);
2217 device->Uhj_Encoder = NULL;
2219 bformatdec_free(device->AmbiDecoder);
2220 device->AmbiDecoder = NULL;
2222 ambiup_free(device->AmbiUp);
2223 device->AmbiUp = NULL;
2225 AL_STRING_DEINIT(device->DeviceName);
2227 al_free(device->Dry.Buffer);
2228 device->Dry.Buffer = NULL;
2229 device->Dry.NumChannels = 0;
2230 device->FOAOut.Buffer = NULL;
2231 device->FOAOut.NumChannels = 0;
2232 device->RealOut.Buffer = NULL;
2233 device->RealOut.NumChannels = 0;
2235 al_free(device);
2239 void ALCdevice_IncRef(ALCdevice *device)
2241 uint ref;
2242 ref = IncrementRef(&device->ref);
2243 TRACEREF("%p increasing refcount to %u\n", device, ref);
2246 void ALCdevice_DecRef(ALCdevice *device)
2248 uint ref;
2249 ref = DecrementRef(&device->ref);
2250 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2251 if(ref == 0) FreeDevice(device);
2254 /* VerifyDevice
2256 * Checks if the device handle is valid, and increments its ref count if so.
2258 static ALCboolean VerifyDevice(ALCdevice **device)
2260 ALCdevice *tmpDevice;
2262 LockLists();
2263 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2264 while(tmpDevice)
2266 if(tmpDevice == *device)
2268 ALCdevice_IncRef(tmpDevice);
2269 UnlockLists();
2270 return ALC_TRUE;
2272 tmpDevice = tmpDevice->next;
2274 UnlockLists();
2276 *device = NULL;
2277 return ALC_FALSE;
2281 /* InitContext
2283 * Initializes context fields
2285 static ALvoid InitContext(ALCcontext *Context)
2287 ALlistener *listener = Context->Listener;
2289 //Initialise listener
2290 listener->Gain = 1.0f;
2291 listener->MetersPerUnit = 1.0f;
2292 listener->Position[0] = 0.0f;
2293 listener->Position[1] = 0.0f;
2294 listener->Position[2] = 0.0f;
2295 listener->Velocity[0] = 0.0f;
2296 listener->Velocity[1] = 0.0f;
2297 listener->Velocity[2] = 0.0f;
2298 listener->Forward[0] = 0.0f;
2299 listener->Forward[1] = 0.0f;
2300 listener->Forward[2] = -1.0f;
2301 listener->Up[0] = 0.0f;
2302 listener->Up[1] = 1.0f;
2303 listener->Up[2] = 0.0f;
2305 aluMatrixfSet(&listener->Params.Matrix,
2306 1.0f, 0.0f, 0.0f, 0.0f,
2307 0.0f, 1.0f, 0.0f, 0.0f,
2308 0.0f, 0.0f, 1.0f, 0.0f,
2309 0.0f, 0.0f, 0.0f, 1.0f
2311 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2312 listener->Params.Gain = 1.0f;
2313 listener->Params.MetersPerUnit = 1.0f;
2314 listener->Params.DopplerFactor = 1.0f;
2315 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2317 ATOMIC_INIT(&listener->Update, NULL);
2318 ATOMIC_INIT(&listener->FreeList, NULL);
2320 //Validate Context
2321 InitRef(&Context->UpdateCount, 0);
2322 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2323 Context->GainBoost = 1.0f;
2324 RWLockInit(&Context->PropLock);
2325 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2326 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2327 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2329 //Set globals
2330 Context->DistanceModel = DefaultDistanceModel;
2331 Context->SourceDistanceModel = AL_FALSE;
2332 Context->DopplerFactor = 1.0f;
2333 Context->DopplerVelocity = 1.0f;
2334 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2335 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2337 Context->ExtensionList = alExtList;
2341 /* FreeContext
2343 * Cleans up the context, and destroys any remaining objects the app failed to
2344 * delete. Called once there's no more references on the context.
2346 static void FreeContext(ALCcontext *context)
2348 ALlistener *listener = context->Listener;
2349 struct ALlistenerProps *lprops;
2350 size_t count;
2352 TRACE("%p\n", context);
2354 if(context->SourceMap.size > 0)
2356 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2357 (context->SourceMap.size==1)?"":"s");
2358 ReleaseALSources(context);
2360 ResetUIntMap(&context->SourceMap);
2362 if(context->EffectSlotMap.size > 0)
2364 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2365 (context->EffectSlotMap.size==1)?"":"s");
2366 ReleaseALAuxiliaryEffectSlots(context);
2368 ResetUIntMap(&context->EffectSlotMap);
2370 al_free(context->Voices);
2371 context->Voices = NULL;
2372 context->VoiceCount = 0;
2373 context->MaxVoices = 0;
2375 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2377 TRACE("Freed unapplied listener update %p\n", lprops);
2378 al_free(lprops);
2380 count = 0;
2381 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2382 while(lprops)
2384 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2385 al_free(lprops);
2386 lprops = next;
2387 ++count;
2389 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2391 ALCdevice_DecRef(context->Device);
2392 context->Device = NULL;
2394 //Invalidate context
2395 memset(context, 0, sizeof(ALCcontext));
2396 al_free(context);
2399 /* ReleaseContext
2401 * Removes the context reference from the given device and removes it from
2402 * being current on the running thread or globally.
2404 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2406 ALCcontext *origctx;
2408 if(altss_get(LocalContext) == context)
2410 WARN("%p released while current on thread\n", context);
2411 altss_set(LocalContext, NULL);
2412 ALCcontext_DecRef(context);
2415 origctx = context;
2416 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2417 ALCcontext_DecRef(context);
2419 ALCdevice_Lock(device);
2420 origctx = context;
2421 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList,
2422 &origctx, context->next))
2424 ALCcontext *volatile*list = &origctx->next;
2425 while(*list)
2427 if(*list == context)
2429 *list = (*list)->next;
2430 break;
2432 list = &(*list)->next;
2435 ALCdevice_Unlock(device);
2437 ALCcontext_DecRef(context);
2440 void ALCcontext_IncRef(ALCcontext *context)
2442 uint ref = IncrementRef(&context->ref);
2443 TRACEREF("%p increasing refcount to %u\n", context, ref);
2446 void ALCcontext_DecRef(ALCcontext *context)
2448 uint ref = DecrementRef(&context->ref);
2449 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2450 if(ref == 0) FreeContext(context);
2453 static void ReleaseThreadCtx(void *ptr)
2455 ALCcontext *context = ptr;
2456 uint ref = DecrementRef(&context->ref);
2457 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2458 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2461 /* VerifyContext
2463 * Checks that the given context is valid, and increments its reference count.
2465 static ALCboolean VerifyContext(ALCcontext **context)
2467 ALCdevice *dev;
2469 LockLists();
2470 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2471 while(dev)
2473 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2474 while(ctx)
2476 if(ctx == *context)
2478 ALCcontext_IncRef(ctx);
2479 UnlockLists();
2480 return ALC_TRUE;
2482 ctx = ctx->next;
2484 dev = dev->next;
2486 UnlockLists();
2488 *context = NULL;
2489 return ALC_FALSE;
2493 /* GetContextRef
2495 * Returns the currently active context for this thread, and adds a reference
2496 * without locking it.
2498 ALCcontext *GetContextRef(void)
2500 ALCcontext *context;
2502 context = altss_get(LocalContext);
2503 if(context)
2504 ALCcontext_IncRef(context);
2505 else
2507 LockLists();
2508 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2509 if(context)
2510 ALCcontext_IncRef(context);
2511 UnlockLists();
2514 return context;
2518 /************************************************
2519 * Standard ALC functions
2520 ************************************************/
2522 /* alcGetError
2524 * Return last ALC generated error code for the given device
2526 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2528 ALCenum errorCode;
2530 if(VerifyDevice(&device))
2532 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2533 ALCdevice_DecRef(device);
2535 else
2536 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2538 return errorCode;
2542 /* alcSuspendContext
2544 * Suspends updates for the given context
2546 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2548 if(!SuspendDefers)
2549 return;
2551 if(!VerifyContext(&context))
2552 alcSetError(NULL, ALC_INVALID_CONTEXT);
2553 else
2555 ALCcontext_DeferUpdates(context, DeferAllowPlay);
2556 ALCcontext_DecRef(context);
2560 /* alcProcessContext
2562 * Resumes processing updates for the given context
2564 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2566 if(!SuspendDefers)
2567 return;
2569 if(!VerifyContext(&context))
2570 alcSetError(NULL, ALC_INVALID_CONTEXT);
2571 else
2573 ALCcontext_ProcessUpdates(context);
2574 ALCcontext_DecRef(context);
2579 /* alcGetString
2581 * Returns information about the device, and error strings
2583 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2585 const ALCchar *value = NULL;
2587 switch(param)
2589 case ALC_NO_ERROR:
2590 value = alcNoError;
2591 break;
2593 case ALC_INVALID_ENUM:
2594 value = alcErrInvalidEnum;
2595 break;
2597 case ALC_INVALID_VALUE:
2598 value = alcErrInvalidValue;
2599 break;
2601 case ALC_INVALID_DEVICE:
2602 value = alcErrInvalidDevice;
2603 break;
2605 case ALC_INVALID_CONTEXT:
2606 value = alcErrInvalidContext;
2607 break;
2609 case ALC_OUT_OF_MEMORY:
2610 value = alcErrOutOfMemory;
2611 break;
2613 case ALC_DEVICE_SPECIFIER:
2614 value = alcDefaultName;
2615 break;
2617 case ALC_ALL_DEVICES_SPECIFIER:
2618 if(VerifyDevice(&Device))
2620 value = al_string_get_cstr(Device->DeviceName);
2621 ALCdevice_DecRef(Device);
2623 else
2625 ProbeAllDevicesList();
2626 value = al_string_get_cstr(alcAllDevicesList);
2628 break;
2630 case ALC_CAPTURE_DEVICE_SPECIFIER:
2631 if(VerifyDevice(&Device))
2633 value = al_string_get_cstr(Device->DeviceName);
2634 ALCdevice_DecRef(Device);
2636 else
2638 ProbeCaptureDeviceList();
2639 value = al_string_get_cstr(alcCaptureDeviceList);
2641 break;
2643 /* Default devices are always first in the list */
2644 case ALC_DEFAULT_DEVICE_SPECIFIER:
2645 value = alcDefaultName;
2646 break;
2648 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2649 if(al_string_empty(alcAllDevicesList))
2650 ProbeAllDevicesList();
2652 VerifyDevice(&Device);
2654 free(alcDefaultAllDevicesSpecifier);
2655 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2656 if(!alcDefaultAllDevicesSpecifier)
2657 alcSetError(Device, ALC_OUT_OF_MEMORY);
2659 value = alcDefaultAllDevicesSpecifier;
2660 if(Device) ALCdevice_DecRef(Device);
2661 break;
2663 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2664 if(al_string_empty(alcCaptureDeviceList))
2665 ProbeCaptureDeviceList();
2667 VerifyDevice(&Device);
2669 free(alcCaptureDefaultDeviceSpecifier);
2670 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2671 if(!alcCaptureDefaultDeviceSpecifier)
2672 alcSetError(Device, ALC_OUT_OF_MEMORY);
2674 value = alcCaptureDefaultDeviceSpecifier;
2675 if(Device) ALCdevice_DecRef(Device);
2676 break;
2678 case ALC_EXTENSIONS:
2679 if(!VerifyDevice(&Device))
2680 value = alcNoDeviceExtList;
2681 else
2683 value = alcExtensionList;
2684 ALCdevice_DecRef(Device);
2686 break;
2688 case ALC_HRTF_SPECIFIER_SOFT:
2689 if(!VerifyDevice(&Device))
2690 alcSetError(NULL, ALC_INVALID_DEVICE);
2691 else
2693 almtx_lock(&Device->BackendLock);
2694 value = (Device->Hrtf.Handle ? al_string_get_cstr(Device->Hrtf.Name) : "");
2695 almtx_unlock(&Device->BackendLock);
2696 ALCdevice_DecRef(Device);
2698 break;
2700 default:
2701 VerifyDevice(&Device);
2702 alcSetError(Device, ALC_INVALID_ENUM);
2703 if(Device) ALCdevice_DecRef(Device);
2704 break;
2707 return value;
2711 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2713 ALCsizei i;
2715 if(size <= 0 || values == NULL)
2717 alcSetError(device, ALC_INVALID_VALUE);
2718 return 0;
2721 if(!device)
2723 switch(param)
2725 case ALC_MAJOR_VERSION:
2726 values[0] = alcMajorVersion;
2727 return 1;
2728 case ALC_MINOR_VERSION:
2729 values[0] = alcMinorVersion;
2730 return 1;
2732 case ALC_ATTRIBUTES_SIZE:
2733 case ALC_ALL_ATTRIBUTES:
2734 case ALC_FREQUENCY:
2735 case ALC_REFRESH:
2736 case ALC_SYNC:
2737 case ALC_MONO_SOURCES:
2738 case ALC_STEREO_SOURCES:
2739 case ALC_CAPTURE_SAMPLES:
2740 case ALC_FORMAT_CHANNELS_SOFT:
2741 case ALC_FORMAT_TYPE_SOFT:
2742 alcSetError(NULL, ALC_INVALID_DEVICE);
2743 return 0;
2745 default:
2746 alcSetError(NULL, ALC_INVALID_ENUM);
2747 return 0;
2749 return 0;
2752 if(device->Type == Capture)
2754 switch(param)
2756 case ALC_CAPTURE_SAMPLES:
2757 almtx_lock(&device->BackendLock);
2758 values[0] = V0(device->Backend,availableSamples)();
2759 almtx_unlock(&device->BackendLock);
2760 return 1;
2762 case ALC_CONNECTED:
2763 values[0] = device->Connected;
2764 return 1;
2766 default:
2767 alcSetError(device, ALC_INVALID_ENUM);
2768 return 0;
2770 return 0;
2773 /* render device */
2774 switch(param)
2776 case ALC_MAJOR_VERSION:
2777 values[0] = alcMajorVersion;
2778 return 1;
2780 case ALC_MINOR_VERSION:
2781 values[0] = alcMinorVersion;
2782 return 1;
2784 case ALC_EFX_MAJOR_VERSION:
2785 values[0] = alcEFXMajorVersion;
2786 return 1;
2788 case ALC_EFX_MINOR_VERSION:
2789 values[0] = alcEFXMinorVersion;
2790 return 1;
2792 case ALC_ATTRIBUTES_SIZE:
2793 values[0] = 17;
2794 return 1;
2796 case ALC_ALL_ATTRIBUTES:
2797 if(size < 17)
2799 alcSetError(device, ALC_INVALID_VALUE);
2800 return 0;
2803 i = 0;
2804 almtx_lock(&device->BackendLock);
2805 values[i++] = ALC_FREQUENCY;
2806 values[i++] = device->Frequency;
2808 if(device->Type != Loopback)
2810 values[i++] = ALC_REFRESH;
2811 values[i++] = device->Frequency / device->UpdateSize;
2813 values[i++] = ALC_SYNC;
2814 values[i++] = ALC_FALSE;
2816 else
2818 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2819 values[i++] = device->FmtChans;
2821 values[i++] = ALC_FORMAT_TYPE_SOFT;
2822 values[i++] = device->FmtType;
2825 values[i++] = ALC_MONO_SOURCES;
2826 values[i++] = device->NumMonoSources;
2828 values[i++] = ALC_STEREO_SOURCES;
2829 values[i++] = device->NumStereoSources;
2831 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2832 values[i++] = device->NumAuxSends;
2834 values[i++] = ALC_HRTF_SOFT;
2835 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
2837 values[i++] = ALC_HRTF_STATUS_SOFT;
2838 values[i++] = device->Hrtf.Status;
2839 almtx_unlock(&device->BackendLock);
2841 values[i++] = 0;
2842 return i;
2844 case ALC_FREQUENCY:
2845 values[0] = device->Frequency;
2846 return 1;
2848 case ALC_REFRESH:
2849 if(device->Type == Loopback)
2851 alcSetError(device, ALC_INVALID_DEVICE);
2852 return 0;
2854 almtx_lock(&device->BackendLock);
2855 values[0] = device->Frequency / device->UpdateSize;
2856 almtx_unlock(&device->BackendLock);
2857 return 1;
2859 case ALC_SYNC:
2860 if(device->Type == Loopback)
2862 alcSetError(device, ALC_INVALID_DEVICE);
2863 return 0;
2865 values[0] = ALC_FALSE;
2866 return 1;
2868 case ALC_FORMAT_CHANNELS_SOFT:
2869 if(device->Type != Loopback)
2871 alcSetError(device, ALC_INVALID_DEVICE);
2872 return 0;
2874 values[0] = device->FmtChans;
2875 return 1;
2877 case ALC_FORMAT_TYPE_SOFT:
2878 if(device->Type != Loopback)
2880 alcSetError(device, ALC_INVALID_DEVICE);
2881 return 0;
2883 values[0] = device->FmtType;
2884 return 1;
2886 case ALC_MONO_SOURCES:
2887 values[0] = device->NumMonoSources;
2888 return 1;
2890 case ALC_STEREO_SOURCES:
2891 values[0] = device->NumStereoSources;
2892 return 1;
2894 case ALC_MAX_AUXILIARY_SENDS:
2895 values[0] = device->NumAuxSends;
2896 return 1;
2898 case ALC_CONNECTED:
2899 values[0] = device->Connected;
2900 return 1;
2902 case ALC_HRTF_SOFT:
2903 values[0] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
2904 return 1;
2906 case ALC_HRTF_STATUS_SOFT:
2907 values[0] = device->Hrtf.Status;
2908 return 1;
2910 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
2911 almtx_lock(&device->BackendLock);
2912 FreeHrtfList(&device->Hrtf.List);
2913 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
2914 values[0] = (ALCint)VECTOR_SIZE(device->Hrtf.List);
2915 almtx_unlock(&device->BackendLock);
2916 return 1;
2918 default:
2919 alcSetError(device, ALC_INVALID_ENUM);
2920 return 0;
2922 return 0;
2925 /* alcGetIntegerv
2927 * Returns information about the device and the version of OpenAL
2929 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2931 VerifyDevice(&device);
2932 if(size <= 0 || values == NULL)
2933 alcSetError(device, ALC_INVALID_VALUE);
2934 else
2935 GetIntegerv(device, param, size, values);
2936 if(device) ALCdevice_DecRef(device);
2939 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2941 ALCint *ivals;
2942 ALsizei i;
2944 VerifyDevice(&device);
2945 if(size <= 0 || values == NULL)
2946 alcSetError(device, ALC_INVALID_VALUE);
2947 else if(!device || device->Type == Capture)
2949 ivals = malloc(size * sizeof(ALCint));
2950 size = GetIntegerv(device, pname, size, ivals);
2951 for(i = 0;i < size;i++)
2952 values[i] = ivals[i];
2953 free(ivals);
2955 else /* render device */
2957 ClockLatency clock;
2958 ALuint64 basecount;
2959 ALuint samplecount;
2960 ALuint refcount;
2962 switch(pname)
2964 case ALC_ATTRIBUTES_SIZE:
2965 *values = 21;
2966 break;
2968 case ALC_ALL_ATTRIBUTES:
2969 if(size < 21)
2970 alcSetError(device, ALC_INVALID_VALUE);
2971 else
2973 i = 0;
2974 almtx_lock(&device->BackendLock);
2975 values[i++] = ALC_FREQUENCY;
2976 values[i++] = device->Frequency;
2978 if(device->Type != Loopback)
2980 values[i++] = ALC_REFRESH;
2981 values[i++] = device->Frequency / device->UpdateSize;
2983 values[i++] = ALC_SYNC;
2984 values[i++] = ALC_FALSE;
2986 else
2988 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2989 values[i++] = device->FmtChans;
2991 values[i++] = ALC_FORMAT_TYPE_SOFT;
2992 values[i++] = device->FmtType;
2995 values[i++] = ALC_MONO_SOURCES;
2996 values[i++] = device->NumMonoSources;
2998 values[i++] = ALC_STEREO_SOURCES;
2999 values[i++] = device->NumStereoSources;
3001 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3002 values[i++] = device->NumAuxSends;
3004 values[i++] = ALC_HRTF_SOFT;
3005 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3007 values[i++] = ALC_HRTF_STATUS_SOFT;
3008 values[i++] = device->Hrtf.Status;
3010 clock = V0(device->Backend,getClockLatency)();
3011 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3012 values[i++] = clock.ClockTime;
3014 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3015 values[i++] = clock.Latency;
3016 almtx_unlock(&device->BackendLock);
3018 values[i++] = 0;
3020 break;
3022 case ALC_DEVICE_CLOCK_SOFT:
3023 almtx_lock(&device->BackendLock);
3024 do {
3025 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3026 althrd_yield();
3027 basecount = device->ClockBase;
3028 samplecount = device->SamplesDone;
3029 } while(refcount != ReadRef(&device->MixCount));
3030 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3031 almtx_unlock(&device->BackendLock);
3032 break;
3034 case ALC_DEVICE_LATENCY_SOFT:
3036 almtx_lock(&device->BackendLock);
3037 clock = V0(device->Backend,getClockLatency)();
3038 almtx_unlock(&device->BackendLock);
3039 *values = clock.Latency;
3041 break;
3043 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3044 if(size < 2)
3045 alcSetError(device, ALC_INVALID_VALUE);
3046 else
3048 ClockLatency clock;
3049 almtx_lock(&device->BackendLock);
3050 clock = V0(device->Backend,getClockLatency)();
3051 almtx_unlock(&device->BackendLock);
3052 values[0] = clock.ClockTime;
3053 values[1] = clock.Latency;
3055 break;
3057 default:
3058 ivals = malloc(size * sizeof(ALCint));
3059 size = GetIntegerv(device, pname, size, ivals);
3060 for(i = 0;i < size;i++)
3061 values[i] = ivals[i];
3062 free(ivals);
3063 break;
3066 if(device)
3067 ALCdevice_DecRef(device);
3071 /* alcIsExtensionPresent
3073 * Determines if there is support for a particular extension
3075 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3077 ALCboolean bResult = ALC_FALSE;
3079 VerifyDevice(&device);
3081 if(!extName)
3082 alcSetError(device, ALC_INVALID_VALUE);
3083 else
3085 size_t len = strlen(extName);
3086 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3087 while(ptr && *ptr)
3089 if(strncasecmp(ptr, extName, len) == 0 &&
3090 (ptr[len] == '\0' || isspace(ptr[len])))
3092 bResult = ALC_TRUE;
3093 break;
3095 if((ptr=strchr(ptr, ' ')) != NULL)
3097 do {
3098 ++ptr;
3099 } while(isspace(*ptr));
3103 if(device)
3104 ALCdevice_DecRef(device);
3105 return bResult;
3109 /* alcGetProcAddress
3111 * Retrieves the function address for a particular extension function
3113 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3115 ALCvoid *ptr = NULL;
3117 if(!funcName)
3119 VerifyDevice(&device);
3120 alcSetError(device, ALC_INVALID_VALUE);
3121 if(device) ALCdevice_DecRef(device);
3123 else
3125 ALsizei i = 0;
3126 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3127 i++;
3128 ptr = alcFunctions[i].address;
3131 return ptr;
3135 /* alcGetEnumValue
3137 * Get the value for a particular ALC enumeration name
3139 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3141 ALCenum val = 0;
3143 if(!enumName)
3145 VerifyDevice(&device);
3146 alcSetError(device, ALC_INVALID_VALUE);
3147 if(device) ALCdevice_DecRef(device);
3149 else
3151 ALsizei i = 0;
3152 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3153 i++;
3154 val = enumeration[i].value;
3157 return val;
3161 /* alcCreateContext
3163 * Create and attach a context to the given device.
3165 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3167 ALCcontext *ALContext;
3168 ALfloat valf;
3169 ALCenum err;
3171 LockLists();
3172 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3174 UnlockLists();
3175 alcSetError(device, ALC_INVALID_DEVICE);
3176 if(device) ALCdevice_DecRef(device);
3177 return NULL;
3179 almtx_lock(&device->BackendLock);
3180 UnlockLists();
3182 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3184 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3185 if(ALContext)
3187 InitRef(&ALContext->ref, 1);
3188 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3190 ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
3192 ALContext->VoiceCount = 0;
3193 ALContext->MaxVoices = 256;
3194 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3196 if(!ALContext || !ALContext->Voices)
3198 almtx_unlock(&device->BackendLock);
3200 if(ALContext)
3202 al_free(ALContext->Voices);
3203 ALContext->Voices = NULL;
3205 al_free(ALContext);
3206 ALContext = NULL;
3209 alcSetError(device, ALC_OUT_OF_MEMORY);
3210 ALCdevice_DecRef(device);
3211 return NULL;
3214 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3216 almtx_unlock(&device->BackendLock);
3218 al_free(ALContext->Voices);
3219 ALContext->Voices = NULL;
3221 al_free(ALContext);
3222 ALContext = NULL;
3224 alcSetError(device, err);
3225 if(err == ALC_INVALID_DEVICE)
3227 V0(device->Backend,lock)();
3228 aluHandleDisconnect(device);
3229 V0(device->Backend,unlock)();
3231 ALCdevice_DecRef(device);
3232 return NULL;
3235 ALContext->Device = device;
3236 ALCdevice_IncRef(device);
3237 InitContext(ALContext);
3239 if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3241 if(!isfinite(valf))
3242 ERR("volume-adjust must be finite: %f\n", valf);
3243 else
3245 ALfloat db = clampf(valf, -24.0f, 24.0f);
3246 if(db != valf)
3247 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3248 ALContext->GainBoost = powf(10.0f, db/20.0f);
3249 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3252 UpdateListenerProps(ALContext);
3255 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3256 do {
3257 ALContext->next = head;
3258 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3259 &device->ContextList, &head, ALContext) == 0);
3261 almtx_unlock(&device->BackendLock);
3263 ALCdevice_DecRef(device);
3265 TRACE("Created context %p\n", ALContext);
3266 return ALContext;
3269 /* alcDestroyContext
3271 * Remove a context from its device
3273 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3275 ALCdevice *Device;
3277 LockLists();
3278 /* alcGetContextsDevice sets an error for invalid contexts */
3279 Device = alcGetContextsDevice(context);
3280 if(Device)
3282 almtx_lock(&Device->BackendLock);
3283 ReleaseContext(context, Device);
3284 if(!ATOMIC_LOAD_SEQ(&Device->ContextList))
3286 V0(Device->Backend,stop)();
3287 Device->Flags &= ~DEVICE_RUNNING;
3289 almtx_unlock(&Device->BackendLock);
3291 UnlockLists();
3295 /* alcGetCurrentContext
3297 * Returns the currently active context on the calling thread
3299 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3301 ALCcontext *Context = altss_get(LocalContext);
3302 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3303 return Context;
3306 /* alcGetThreadContext
3308 * Returns the currently active thread-local context
3310 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3312 return altss_get(LocalContext);
3316 /* alcMakeContextCurrent
3318 * Makes the given context the active process-wide context, and removes the
3319 * thread-local context for the calling thread.
3321 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3323 /* context must be valid or NULL */
3324 if(context && !VerifyContext(&context))
3326 alcSetError(NULL, ALC_INVALID_CONTEXT);
3327 return ALC_FALSE;
3329 /* context's reference count is already incremented */
3330 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3331 if(context) ALCcontext_DecRef(context);
3333 if((context=altss_get(LocalContext)) != NULL)
3335 altss_set(LocalContext, NULL);
3336 ALCcontext_DecRef(context);
3339 return ALC_TRUE;
3342 /* alcSetThreadContext
3344 * Makes the given context the active context for the current thread
3346 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3348 ALCcontext *old;
3350 /* context must be valid or NULL */
3351 if(context && !VerifyContext(&context))
3353 alcSetError(NULL, ALC_INVALID_CONTEXT);
3354 return ALC_FALSE;
3356 /* context's reference count is already incremented */
3357 old = altss_get(LocalContext);
3358 altss_set(LocalContext, context);
3359 if(old) ALCcontext_DecRef(old);
3361 return ALC_TRUE;
3365 /* alcGetContextsDevice
3367 * Returns the device that a particular context is attached to
3369 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3371 ALCdevice *Device;
3373 if(!VerifyContext(&Context))
3375 alcSetError(NULL, ALC_INVALID_CONTEXT);
3376 return NULL;
3378 Device = Context->Device;
3379 ALCcontext_DecRef(Context);
3381 return Device;
3385 /* alcOpenDevice
3387 * Opens the named device.
3389 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3391 const ALCchar *fmt;
3392 ALCdevice *device;
3393 ALCenum err;
3395 DO_INITCONFIG();
3397 if(!PlaybackBackend.name)
3399 alcSetError(NULL, ALC_INVALID_VALUE);
3400 return NULL;
3403 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3404 #ifdef _WIN32
3405 /* Some old Windows apps hardcode these expecting OpenAL to use a
3406 * specific audio API, even when they're not enumerated. Creative's
3407 * router effectively ignores them too.
3409 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3410 || strcasecmp(deviceName, "MMSYSTEM") == 0
3411 #endif
3413 deviceName = NULL;
3415 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3416 if(!device)
3418 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3419 return NULL;
3422 //Validate device
3423 InitRef(&device->ref, 1);
3424 device->Connected = ALC_TRUE;
3425 device->Type = Playback;
3426 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3428 device->Flags = 0;
3429 device->Bs2b = NULL;
3430 device->Uhj_Encoder = NULL;
3431 VECTOR_INIT(device->Hrtf.List);
3432 AL_STRING_INIT(device->Hrtf.Name);
3433 device->Render_Mode = NormalRender;
3434 AL_STRING_INIT(device->DeviceName);
3435 device->Dry.Buffer = NULL;
3436 device->Dry.NumChannels = 0;
3437 device->FOAOut.Buffer = NULL;
3438 device->FOAOut.NumChannels = 0;
3439 device->RealOut.Buffer = NULL;
3440 device->RealOut.NumChannels = 0;
3442 ATOMIC_INIT(&device->ContextList, NULL);
3444 device->ClockBase = 0;
3445 device->SamplesDone = 0;
3447 device->SourcesMax = 256;
3448 device->AuxiliaryEffectSlotMax = 4;
3449 device->NumAuxSends = MAX_SENDS;
3451 InitUIntMap(&device->BufferMap, ~0);
3452 InitUIntMap(&device->EffectMap, ~0);
3453 InitUIntMap(&device->FilterMap, ~0);
3455 //Set output format
3456 device->FmtChans = DevFmtChannelsDefault;
3457 device->FmtType = DevFmtTypeDefault;
3458 device->Frequency = DEFAULT_OUTPUT_RATE;
3459 device->IsHeadphones = AL_FALSE;
3460 device->AmbiFmt = AmbiFormat_Default;
3461 device->NumUpdates = 4;
3462 device->UpdateSize = 1024;
3464 if(!PlaybackBackend.getFactory)
3465 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3466 ALCbackend_Playback);
3467 else
3469 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3470 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3472 if(!device->Backend)
3474 al_free(device);
3475 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3476 return NULL;
3480 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3482 static const struct {
3483 const char name[16];
3484 enum DevFmtChannels chans;
3485 } chanlist[] = {
3486 { "mono", DevFmtMono },
3487 { "stereo", DevFmtStereo },
3488 { "quad", DevFmtQuad },
3489 { "surround51", DevFmtX51 },
3490 { "surround61", DevFmtX61 },
3491 { "surround71", DevFmtX71 },
3492 { "surround51rear", DevFmtX51Rear },
3493 { "ambi1", DevFmtAmbi1 },
3494 { "ambi2", DevFmtAmbi2 },
3495 { "ambi3", DevFmtAmbi3 },
3497 size_t i;
3499 for(i = 0;i < COUNTOF(chanlist);i++)
3501 if(strcasecmp(chanlist[i].name, fmt) == 0)
3503 device->FmtChans = chanlist[i].chans;
3504 device->Flags |= DEVICE_CHANNELS_REQUEST;
3505 break;
3508 if(i == COUNTOF(chanlist))
3509 ERR("Unsupported channels: %s\n", fmt);
3511 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3513 static const struct {
3514 const char name[16];
3515 enum DevFmtType type;
3516 } typelist[] = {
3517 { "int8", DevFmtByte },
3518 { "uint8", DevFmtUByte },
3519 { "int16", DevFmtShort },
3520 { "uint16", DevFmtUShort },
3521 { "int32", DevFmtInt },
3522 { "uint32", DevFmtUInt },
3523 { "float32", DevFmtFloat },
3525 size_t i;
3527 for(i = 0;i < COUNTOF(typelist);i++)
3529 if(strcasecmp(typelist[i].name, fmt) == 0)
3531 device->FmtType = typelist[i].type;
3532 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3533 break;
3536 if(i == COUNTOF(typelist))
3537 ERR("Unsupported sample-type: %s\n", fmt);
3540 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3542 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3543 if(device->Frequency < MIN_OUTPUT_RATE)
3544 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3545 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3548 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3549 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3551 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3552 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3553 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3554 device->UpdateSize = (device->UpdateSize+3)&~3;
3556 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3557 if(device->SourcesMax == 0) device->SourcesMax = 256;
3559 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3560 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3562 ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends);
3563 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3565 device->NumStereoSources = 1;
3566 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3568 // Find a playback device to open
3569 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3571 DELETE_OBJ(device->Backend);
3572 al_free(device);
3573 alcSetError(NULL, err);
3574 return NULL;
3576 almtx_init(&device->BackendLock, almtx_plain);
3578 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3580 if(strcasecmp(fmt, "fuma") == 0)
3581 device->AmbiFmt = AmbiFormat_FuMa;
3582 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3583 device->AmbiFmt = AmbiFormat_ACN_SN3D;
3584 else if(strcasecmp(fmt, "acn+n3d") == 0)
3585 device->AmbiFmt = AmbiFormat_ACN_N3D;
3586 else
3587 ERR("Unsupported ambi-format: %s\n", fmt);
3590 if(DefaultEffect.type != AL_EFFECT_NULL)
3592 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3593 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3595 device->DefaultSlot = NULL;
3596 ERR("Failed to initialize the default effect slot\n");
3598 else
3600 aluInitEffectPanning(device->DefaultSlot);
3601 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3603 DeinitEffectSlot(device->DefaultSlot);
3604 device->DefaultSlot = NULL;
3605 ERR("Failed to initialize the default effect\n");
3611 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3612 do {
3613 device->next = head;
3614 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3617 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3618 return device;
3621 /* alcCloseDevice
3623 * Closes the given device.
3625 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3627 ALCdevice *iter, *origdev;
3628 ALCcontext *ctx;
3630 LockLists();
3631 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3632 do {
3633 if(iter == device)
3634 break;
3635 } while((iter=iter->next) != NULL);
3636 if(!iter || iter->Type == Capture)
3638 alcSetError(iter, ALC_INVALID_DEVICE);
3639 UnlockLists();
3640 return ALC_FALSE;
3642 almtx_lock(&device->BackendLock);
3644 origdev = device;
3645 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3647 ALCdevice *volatile*list = &origdev->next;
3648 while(*list)
3650 if(*list == device)
3652 *list = (*list)->next;
3653 break;
3655 list = &(*list)->next;
3658 UnlockLists();
3660 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
3661 while(ctx != NULL)
3663 ALCcontext *next = ctx->next;
3664 WARN("Releasing context %p\n", ctx);
3665 ReleaseContext(ctx, device);
3666 ctx = next;
3668 if((device->Flags&DEVICE_RUNNING))
3669 V0(device->Backend,stop)();
3670 device->Flags &= ~DEVICE_RUNNING;
3671 almtx_unlock(&device->BackendLock);
3673 ALCdevice_DecRef(device);
3675 return ALC_TRUE;
3679 /************************************************
3680 * ALC capture functions
3681 ************************************************/
3682 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3684 ALCdevice *device = NULL;
3685 ALCenum err;
3687 DO_INITCONFIG();
3689 if(!CaptureBackend.name)
3691 alcSetError(NULL, ALC_INVALID_VALUE);
3692 return NULL;
3695 if(samples <= 0)
3697 alcSetError(NULL, ALC_INVALID_VALUE);
3698 return NULL;
3701 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3702 deviceName = NULL;
3704 device = al_calloc(16, sizeof(ALCdevice));
3705 if(!device)
3707 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3708 return NULL;
3711 //Validate device
3712 InitRef(&device->ref, 1);
3713 device->Connected = ALC_TRUE;
3714 device->Type = Capture;
3716 VECTOR_INIT(device->Hrtf.List);
3717 AL_STRING_INIT(device->Hrtf.Name);
3719 AL_STRING_INIT(device->DeviceName);
3720 device->Dry.Buffer = NULL;
3721 device->Dry.NumChannels = 0;
3722 device->FOAOut.Buffer = NULL;
3723 device->FOAOut.NumChannels = 0;
3724 device->RealOut.Buffer = NULL;
3725 device->RealOut.NumChannels = 0;
3727 InitUIntMap(&device->BufferMap, ~0);
3728 InitUIntMap(&device->EffectMap, ~0);
3729 InitUIntMap(&device->FilterMap, ~0);
3731 if(!CaptureBackend.getFactory)
3732 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3733 ALCbackend_Capture);
3734 else
3736 ALCbackendFactory *factory = CaptureBackend.getFactory();
3737 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3739 if(!device->Backend)
3741 al_free(device);
3742 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3743 return NULL;
3746 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3747 device->Frequency = frequency;
3749 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3750 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3752 al_free(device);
3753 alcSetError(NULL, ALC_INVALID_ENUM);
3754 return NULL;
3756 device->IsHeadphones = AL_FALSE;
3757 device->AmbiFmt = AmbiFormat_Default;
3759 device->UpdateSize = samples;
3760 device->NumUpdates = 1;
3762 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3764 al_free(device);
3765 alcSetError(NULL, err);
3766 return NULL;
3768 almtx_init(&device->BackendLock, almtx_plain);
3771 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3772 do {
3773 device->next = head;
3774 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3777 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3778 return device;
3781 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3783 ALCdevice *iter, *origdev;
3785 LockLists();
3786 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3787 do {
3788 if(iter == device)
3789 break;
3790 } while((iter=iter->next) != NULL);
3791 if(!iter || iter->Type != Capture)
3793 alcSetError(iter, ALC_INVALID_DEVICE);
3794 UnlockLists();
3795 return ALC_FALSE;
3798 origdev = device;
3799 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3801 ALCdevice *volatile*list = &origdev->next;
3802 while(*list)
3804 if(*list == device)
3806 *list = (*list)->next;
3807 break;
3809 list = &(*list)->next;
3812 UnlockLists();
3814 ALCdevice_DecRef(device);
3816 return ALC_TRUE;
3819 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3821 if(!VerifyDevice(&device) || device->Type != Capture)
3822 alcSetError(device, ALC_INVALID_DEVICE);
3823 else
3825 almtx_lock(&device->BackendLock);
3826 if(!device->Connected)
3827 alcSetError(device, ALC_INVALID_DEVICE);
3828 else if(!(device->Flags&DEVICE_RUNNING))
3830 if(V0(device->Backend,start)())
3831 device->Flags |= DEVICE_RUNNING;
3832 else
3834 aluHandleDisconnect(device);
3835 alcSetError(device, ALC_INVALID_DEVICE);
3838 almtx_unlock(&device->BackendLock);
3841 if(device) ALCdevice_DecRef(device);
3844 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3846 if(!VerifyDevice(&device) || device->Type != Capture)
3847 alcSetError(device, ALC_INVALID_DEVICE);
3848 else
3850 almtx_lock(&device->BackendLock);
3851 if((device->Flags&DEVICE_RUNNING))
3852 V0(device->Backend,stop)();
3853 device->Flags &= ~DEVICE_RUNNING;
3854 almtx_unlock(&device->BackendLock);
3857 if(device) ALCdevice_DecRef(device);
3860 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3862 if(!VerifyDevice(&device) || device->Type != Capture)
3863 alcSetError(device, ALC_INVALID_DEVICE);
3864 else
3866 ALCenum err = ALC_INVALID_VALUE;
3868 almtx_lock(&device->BackendLock);
3869 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3870 err = V(device->Backend,captureSamples)(buffer, samples);
3871 almtx_unlock(&device->BackendLock);
3873 if(err != ALC_NO_ERROR)
3874 alcSetError(device, err);
3876 if(device) ALCdevice_DecRef(device);
3880 /************************************************
3881 * ALC loopback functions
3882 ************************************************/
3884 /* alcLoopbackOpenDeviceSOFT
3886 * Open a loopback device, for manual rendering.
3888 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3890 ALCbackendFactory *factory;
3891 ALCdevice *device;
3893 DO_INITCONFIG();
3895 /* Make sure the device name, if specified, is us. */
3896 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3898 alcSetError(NULL, ALC_INVALID_VALUE);
3899 return NULL;
3902 device = al_calloc(16, sizeof(ALCdevice));
3903 if(!device)
3905 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3906 return NULL;
3909 //Validate device
3910 InitRef(&device->ref, 1);
3911 device->Connected = ALC_TRUE;
3912 device->Type = Loopback;
3913 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3915 device->Flags = 0;
3916 VECTOR_INIT(device->Hrtf.List);
3917 AL_STRING_INIT(device->Hrtf.Name);
3918 device->Bs2b = NULL;
3919 device->Uhj_Encoder = NULL;
3920 device->Render_Mode = NormalRender;
3921 AL_STRING_INIT(device->DeviceName);
3922 device->Dry.Buffer = NULL;
3923 device->Dry.NumChannels = 0;
3924 device->FOAOut.Buffer = NULL;
3925 device->FOAOut.NumChannels = 0;
3926 device->RealOut.Buffer = NULL;
3927 device->RealOut.NumChannels = 0;
3929 ATOMIC_INIT(&device->ContextList, NULL);
3931 device->ClockBase = 0;
3932 device->SamplesDone = 0;
3934 device->SourcesMax = 256;
3935 device->AuxiliaryEffectSlotMax = 4;
3936 device->NumAuxSends = MAX_SENDS;
3938 InitUIntMap(&device->BufferMap, ~0);
3939 InitUIntMap(&device->EffectMap, ~0);
3940 InitUIntMap(&device->FilterMap, ~0);
3942 factory = ALCloopbackFactory_getFactory();
3943 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3944 if(!device->Backend)
3946 al_free(device);
3947 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3948 return NULL;
3950 almtx_init(&device->BackendLock, almtx_plain);
3952 //Set output format
3953 device->NumUpdates = 0;
3954 device->UpdateSize = 0;
3956 device->Frequency = DEFAULT_OUTPUT_RATE;
3957 device->FmtChans = DevFmtChannelsDefault;
3958 device->FmtType = DevFmtTypeDefault;
3959 device->IsHeadphones = AL_FALSE;
3960 device->AmbiFmt = AmbiFormat_Default;
3962 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
3963 if(device->SourcesMax == 0) device->SourcesMax = 256;
3965 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3966 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3968 ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends);
3969 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3971 device->NumStereoSources = 1;
3972 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3974 // Open the "backend"
3975 V(device->Backend,open)("Loopback");
3978 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3979 do {
3980 device->next = head;
3981 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3984 TRACE("Created device %p\n", device);
3985 return device;
3988 /* alcIsRenderFormatSupportedSOFT
3990 * Determines if the loopback device supports the given format for rendering.
3992 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3994 ALCboolean ret = ALC_FALSE;
3996 if(!VerifyDevice(&device) || device->Type != Loopback)
3997 alcSetError(device, ALC_INVALID_DEVICE);
3998 else if(freq <= 0)
3999 alcSetError(device, ALC_INVALID_VALUE);
4000 else
4002 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
4003 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
4004 freq >= MIN_OUTPUT_RATE)
4005 ret = ALC_TRUE;
4007 if(device) ALCdevice_DecRef(device);
4009 return ret;
4012 /* alcRenderSamplesSOFT
4014 * Renders some samples into a buffer, using the format last set by the
4015 * attributes given to alcCreateContext.
4017 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4019 if(!VerifyDevice(&device) || device->Type != Loopback)
4020 alcSetError(device, ALC_INVALID_DEVICE);
4021 else if(samples < 0 || (samples > 0 && buffer == NULL))
4022 alcSetError(device, ALC_INVALID_VALUE);
4023 else
4024 aluMixData(device, buffer, samples);
4025 if(device) ALCdevice_DecRef(device);
4029 /************************************************
4030 * ALC DSP pause/resume functions
4031 ************************************************/
4033 /* alcDevicePauseSOFT
4035 * Pause the DSP to stop audio processing.
4037 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4039 if(!VerifyDevice(&device) || device->Type != Playback)
4040 alcSetError(device, ALC_INVALID_DEVICE);
4041 else
4043 almtx_lock(&device->BackendLock);
4044 if((device->Flags&DEVICE_RUNNING))
4045 V0(device->Backend,stop)();
4046 device->Flags &= ~DEVICE_RUNNING;
4047 device->Flags |= DEVICE_PAUSED;
4048 almtx_unlock(&device->BackendLock);
4050 if(device) ALCdevice_DecRef(device);
4053 /* alcDeviceResumeSOFT
4055 * Resume the DSP to restart audio processing.
4057 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4059 if(!VerifyDevice(&device) || device->Type != Playback)
4060 alcSetError(device, ALC_INVALID_DEVICE);
4061 else
4063 almtx_lock(&device->BackendLock);
4064 if((device->Flags&DEVICE_PAUSED))
4066 device->Flags &= ~DEVICE_PAUSED;
4067 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4069 if(V0(device->Backend,start)() != ALC_FALSE)
4070 device->Flags |= DEVICE_RUNNING;
4071 else
4073 alcSetError(device, ALC_INVALID_DEVICE);
4074 V0(device->Backend,lock)();
4075 aluHandleDisconnect(device);
4076 V0(device->Backend,unlock)();
4080 almtx_unlock(&device->BackendLock);
4082 if(device) ALCdevice_DecRef(device);
4086 /************************************************
4087 * ALC HRTF functions
4088 ************************************************/
4090 /* alcGetStringiSOFT
4092 * Gets a string parameter at the given index.
4094 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4096 const ALCchar *str = NULL;
4098 if(!VerifyDevice(&device) || device->Type == Capture)
4099 alcSetError(device, ALC_INVALID_DEVICE);
4100 else switch(paramName)
4102 case ALC_HRTF_SPECIFIER_SOFT:
4103 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf.List))
4104 str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf.List, index).name);
4105 else
4106 alcSetError(device, ALC_INVALID_VALUE);
4107 break;
4109 default:
4110 alcSetError(device, ALC_INVALID_ENUM);
4111 break;
4113 if(device) ALCdevice_DecRef(device);
4115 return str;
4118 /* alcResetDeviceSOFT
4120 * Resets the given device output, using the specified attribute list.
4122 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4124 ALCenum err;
4126 LockLists();
4127 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4129 UnlockLists();
4130 alcSetError(device, ALC_INVALID_DEVICE);
4131 if(device) ALCdevice_DecRef(device);
4132 return ALC_FALSE;
4134 almtx_lock(&device->BackendLock);
4135 UnlockLists();
4137 err = UpdateDeviceParams(device, attribs);
4138 almtx_unlock(&device->BackendLock);
4140 if(err != ALC_NO_ERROR)
4142 alcSetError(device, err);
4143 if(err == ALC_INVALID_DEVICE)
4145 V0(device->Backend,lock)();
4146 aluHandleDisconnect(device);
4147 V0(device->Backend,unlock)();
4149 ALCdevice_DecRef(device);
4150 return ALC_FALSE;
4152 ALCdevice_DecRef(device);
4154 return ALC_TRUE;