Move the config function declarations to their own header
[openal-soft.git] / Alc / ALc.c
blob5297af30d5a734f8286a64164c4a107399fdaa35
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alThunk.h"
36 #include "alSource.h"
37 #include "alBuffer.h"
38 #include "alAuxEffectSlot.h"
39 #include "alError.h"
40 #include "mastering.h"
41 #include "bformatdec.h"
42 #include "alu.h"
43 #include "alconfig.h"
45 #include "cpu_caps.h"
46 #include "compat.h"
47 #include "threads.h"
48 #include "alstring.h"
49 #include "almalloc.h"
51 #include "backends/base.h"
54 /************************************************
55 * Backends
56 ************************************************/
57 struct BackendInfo {
58 const char *name;
59 ALCbackendFactory* (*getFactory)(void);
62 static struct BackendInfo BackendList[] = {
63 #ifdef HAVE_JACK
64 { "jack", ALCjackBackendFactory_getFactory },
65 #endif
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", ALCpulseBackendFactory_getFactory },
68 #endif
69 #ifdef HAVE_ALSA
70 { "alsa", ALCalsaBackendFactory_getFactory },
71 #endif
72 #ifdef HAVE_COREAUDIO
73 { "core", ALCcoreAudioBackendFactory_getFactory },
74 #endif
75 #ifdef HAVE_OSS
76 { "oss", ALCossBackendFactory_getFactory },
77 #endif
78 #ifdef HAVE_SOLARIS
79 { "solaris", ALCsolarisBackendFactory_getFactory },
80 #endif
81 #ifdef HAVE_SNDIO
82 { "sndio", ALCsndioBackendFactory_getFactory },
83 #endif
84 #ifdef HAVE_QSA
85 { "qsa", ALCqsaBackendFactory_getFactory },
86 #endif
87 #ifdef HAVE_MMDEVAPI
88 { "mmdevapi", ALCmmdevBackendFactory_getFactory },
89 #endif
90 #ifdef HAVE_DSOUND
91 { "dsound", ALCdsoundBackendFactory_getFactory },
92 #endif
93 #ifdef HAVE_WINMM
94 { "winmm", ALCwinmmBackendFactory_getFactory },
95 #endif
96 #ifdef HAVE_PORTAUDIO
97 { "port", ALCportBackendFactory_getFactory },
98 #endif
99 #ifdef HAVE_OPENSL
100 { "opensl", ALCopenslBackendFactory_getFactory },
101 #endif
103 { "null", ALCnullBackendFactory_getFactory },
104 #ifdef HAVE_WAVE
105 { "wave", ALCwaveBackendFactory_getFactory },
106 #endif
108 static ALsizei BackendListSize = COUNTOF(BackendList);
109 #undef EmptyFuncs
111 static struct BackendInfo PlaybackBackend;
112 static struct BackendInfo CaptureBackend;
115 /************************************************
116 * Functions, enums, and errors
117 ************************************************/
118 #define DECL(x) { #x, (ALCvoid*)(x) }
119 static const struct {
120 const ALCchar *funcName;
121 ALCvoid *address;
122 } alcFunctions[] = {
123 DECL(alcCreateContext),
124 DECL(alcMakeContextCurrent),
125 DECL(alcProcessContext),
126 DECL(alcSuspendContext),
127 DECL(alcDestroyContext),
128 DECL(alcGetCurrentContext),
129 DECL(alcGetContextsDevice),
130 DECL(alcOpenDevice),
131 DECL(alcCloseDevice),
132 DECL(alcGetError),
133 DECL(alcIsExtensionPresent),
134 DECL(alcGetProcAddress),
135 DECL(alcGetEnumValue),
136 DECL(alcGetString),
137 DECL(alcGetIntegerv),
138 DECL(alcCaptureOpenDevice),
139 DECL(alcCaptureCloseDevice),
140 DECL(alcCaptureStart),
141 DECL(alcCaptureStop),
142 DECL(alcCaptureSamples),
144 DECL(alcSetThreadContext),
145 DECL(alcGetThreadContext),
147 DECL(alcLoopbackOpenDeviceSOFT),
148 DECL(alcIsRenderFormatSupportedSOFT),
149 DECL(alcRenderSamplesSOFT),
151 DECL(alcDevicePauseSOFT),
152 DECL(alcDeviceResumeSOFT),
154 DECL(alcGetStringiSOFT),
155 DECL(alcResetDeviceSOFT),
157 DECL(alcGetInteger64vSOFT),
159 DECL(alEnable),
160 DECL(alDisable),
161 DECL(alIsEnabled),
162 DECL(alGetString),
163 DECL(alGetBooleanv),
164 DECL(alGetIntegerv),
165 DECL(alGetFloatv),
166 DECL(alGetDoublev),
167 DECL(alGetBoolean),
168 DECL(alGetInteger),
169 DECL(alGetFloat),
170 DECL(alGetDouble),
171 DECL(alGetError),
172 DECL(alIsExtensionPresent),
173 DECL(alGetProcAddress),
174 DECL(alGetEnumValue),
175 DECL(alListenerf),
176 DECL(alListener3f),
177 DECL(alListenerfv),
178 DECL(alListeneri),
179 DECL(alListener3i),
180 DECL(alListeneriv),
181 DECL(alGetListenerf),
182 DECL(alGetListener3f),
183 DECL(alGetListenerfv),
184 DECL(alGetListeneri),
185 DECL(alGetListener3i),
186 DECL(alGetListeneriv),
187 DECL(alGenSources),
188 DECL(alDeleteSources),
189 DECL(alIsSource),
190 DECL(alSourcef),
191 DECL(alSource3f),
192 DECL(alSourcefv),
193 DECL(alSourcei),
194 DECL(alSource3i),
195 DECL(alSourceiv),
196 DECL(alGetSourcef),
197 DECL(alGetSource3f),
198 DECL(alGetSourcefv),
199 DECL(alGetSourcei),
200 DECL(alGetSource3i),
201 DECL(alGetSourceiv),
202 DECL(alSourcePlayv),
203 DECL(alSourceStopv),
204 DECL(alSourceRewindv),
205 DECL(alSourcePausev),
206 DECL(alSourcePlay),
207 DECL(alSourceStop),
208 DECL(alSourceRewind),
209 DECL(alSourcePause),
210 DECL(alSourceQueueBuffers),
211 DECL(alSourceUnqueueBuffers),
212 DECL(alGenBuffers),
213 DECL(alDeleteBuffers),
214 DECL(alIsBuffer),
215 DECL(alBufferData),
216 DECL(alBufferf),
217 DECL(alBuffer3f),
218 DECL(alBufferfv),
219 DECL(alBufferi),
220 DECL(alBuffer3i),
221 DECL(alBufferiv),
222 DECL(alGetBufferf),
223 DECL(alGetBuffer3f),
224 DECL(alGetBufferfv),
225 DECL(alGetBufferi),
226 DECL(alGetBuffer3i),
227 DECL(alGetBufferiv),
228 DECL(alDopplerFactor),
229 DECL(alDopplerVelocity),
230 DECL(alSpeedOfSound),
231 DECL(alDistanceModel),
233 DECL(alGenFilters),
234 DECL(alDeleteFilters),
235 DECL(alIsFilter),
236 DECL(alFilteri),
237 DECL(alFilteriv),
238 DECL(alFilterf),
239 DECL(alFilterfv),
240 DECL(alGetFilteri),
241 DECL(alGetFilteriv),
242 DECL(alGetFilterf),
243 DECL(alGetFilterfv),
244 DECL(alGenEffects),
245 DECL(alDeleteEffects),
246 DECL(alIsEffect),
247 DECL(alEffecti),
248 DECL(alEffectiv),
249 DECL(alEffectf),
250 DECL(alEffectfv),
251 DECL(alGetEffecti),
252 DECL(alGetEffectiv),
253 DECL(alGetEffectf),
254 DECL(alGetEffectfv),
255 DECL(alGenAuxiliaryEffectSlots),
256 DECL(alDeleteAuxiliaryEffectSlots),
257 DECL(alIsAuxiliaryEffectSlot),
258 DECL(alAuxiliaryEffectSloti),
259 DECL(alAuxiliaryEffectSlotiv),
260 DECL(alAuxiliaryEffectSlotf),
261 DECL(alAuxiliaryEffectSlotfv),
262 DECL(alGetAuxiliaryEffectSloti),
263 DECL(alGetAuxiliaryEffectSlotiv),
264 DECL(alGetAuxiliaryEffectSlotf),
265 DECL(alGetAuxiliaryEffectSlotfv),
267 DECL(alDeferUpdatesSOFT),
268 DECL(alProcessUpdatesSOFT),
270 DECL(alSourcedSOFT),
271 DECL(alSource3dSOFT),
272 DECL(alSourcedvSOFT),
273 DECL(alGetSourcedSOFT),
274 DECL(alGetSource3dSOFT),
275 DECL(alGetSourcedvSOFT),
276 DECL(alSourcei64SOFT),
277 DECL(alSource3i64SOFT),
278 DECL(alSourcei64vSOFT),
279 DECL(alGetSourcei64SOFT),
280 DECL(alGetSource3i64SOFT),
281 DECL(alGetSourcei64vSOFT),
283 DECL(alBufferSamplesSOFT),
284 DECL(alGetBufferSamplesSOFT),
285 DECL(alIsBufferFormatSupportedSOFT),
287 DECL(alGetStringiSOFT),
289 #undef DECL
291 #define DECL(x) { #x, (x) }
292 static const struct {
293 const ALCchar *enumName;
294 ALCenum value;
295 } alcEnumerations[] = {
296 DECL(ALC_INVALID),
297 DECL(ALC_FALSE),
298 DECL(ALC_TRUE),
300 DECL(ALC_MAJOR_VERSION),
301 DECL(ALC_MINOR_VERSION),
302 DECL(ALC_ATTRIBUTES_SIZE),
303 DECL(ALC_ALL_ATTRIBUTES),
304 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
305 DECL(ALC_DEVICE_SPECIFIER),
306 DECL(ALC_ALL_DEVICES_SPECIFIER),
307 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
308 DECL(ALC_EXTENSIONS),
309 DECL(ALC_FREQUENCY),
310 DECL(ALC_REFRESH),
311 DECL(ALC_SYNC),
312 DECL(ALC_MONO_SOURCES),
313 DECL(ALC_STEREO_SOURCES),
314 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
315 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
316 DECL(ALC_CAPTURE_SAMPLES),
317 DECL(ALC_CONNECTED),
319 DECL(ALC_EFX_MAJOR_VERSION),
320 DECL(ALC_EFX_MINOR_VERSION),
321 DECL(ALC_MAX_AUXILIARY_SENDS),
323 DECL(ALC_FORMAT_CHANNELS_SOFT),
324 DECL(ALC_FORMAT_TYPE_SOFT),
326 DECL(ALC_MONO_SOFT),
327 DECL(ALC_STEREO_SOFT),
328 DECL(ALC_QUAD_SOFT),
329 DECL(ALC_5POINT1_SOFT),
330 DECL(ALC_6POINT1_SOFT),
331 DECL(ALC_7POINT1_SOFT),
332 DECL(ALC_BFORMAT3D_SOFT),
334 DECL(ALC_BYTE_SOFT),
335 DECL(ALC_UNSIGNED_BYTE_SOFT),
336 DECL(ALC_SHORT_SOFT),
337 DECL(ALC_UNSIGNED_SHORT_SOFT),
338 DECL(ALC_INT_SOFT),
339 DECL(ALC_UNSIGNED_INT_SOFT),
340 DECL(ALC_FLOAT_SOFT),
342 DECL(ALC_HRTF_SOFT),
343 DECL(ALC_DONT_CARE_SOFT),
344 DECL(ALC_HRTF_STATUS_SOFT),
345 DECL(ALC_HRTF_DISABLED_SOFT),
346 DECL(ALC_HRTF_ENABLED_SOFT),
347 DECL(ALC_HRTF_DENIED_SOFT),
348 DECL(ALC_HRTF_REQUIRED_SOFT),
349 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
350 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
351 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
352 DECL(ALC_HRTF_SPECIFIER_SOFT),
353 DECL(ALC_HRTF_ID_SOFT),
355 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
356 DECL(ALC_AMBISONIC_SCALING_SOFT),
357 DECL(ALC_AMBISONIC_ORDER_SOFT),
358 DECL(ALC_ACN_SOFT),
359 DECL(ALC_FUMA_SOFT),
360 DECL(ALC_N3D_SOFT),
361 DECL(ALC_SN3D_SOFT),
363 DECL(ALC_OUTPUT_LIMITER_SOFT),
365 DECL(ALC_NO_ERROR),
366 DECL(ALC_INVALID_DEVICE),
367 DECL(ALC_INVALID_CONTEXT),
368 DECL(ALC_INVALID_ENUM),
369 DECL(ALC_INVALID_VALUE),
370 DECL(ALC_OUT_OF_MEMORY),
373 DECL(AL_INVALID),
374 DECL(AL_NONE),
375 DECL(AL_FALSE),
376 DECL(AL_TRUE),
378 DECL(AL_SOURCE_RELATIVE),
379 DECL(AL_CONE_INNER_ANGLE),
380 DECL(AL_CONE_OUTER_ANGLE),
381 DECL(AL_PITCH),
382 DECL(AL_POSITION),
383 DECL(AL_DIRECTION),
384 DECL(AL_VELOCITY),
385 DECL(AL_LOOPING),
386 DECL(AL_BUFFER),
387 DECL(AL_GAIN),
388 DECL(AL_MIN_GAIN),
389 DECL(AL_MAX_GAIN),
390 DECL(AL_ORIENTATION),
391 DECL(AL_REFERENCE_DISTANCE),
392 DECL(AL_ROLLOFF_FACTOR),
393 DECL(AL_CONE_OUTER_GAIN),
394 DECL(AL_MAX_DISTANCE),
395 DECL(AL_SEC_OFFSET),
396 DECL(AL_SAMPLE_OFFSET),
397 DECL(AL_BYTE_OFFSET),
398 DECL(AL_SOURCE_TYPE),
399 DECL(AL_STATIC),
400 DECL(AL_STREAMING),
401 DECL(AL_UNDETERMINED),
402 DECL(AL_METERS_PER_UNIT),
403 DECL(AL_LOOP_POINTS_SOFT),
404 DECL(AL_DIRECT_CHANNELS_SOFT),
406 DECL(AL_DIRECT_FILTER),
407 DECL(AL_AUXILIARY_SEND_FILTER),
408 DECL(AL_AIR_ABSORPTION_FACTOR),
409 DECL(AL_ROOM_ROLLOFF_FACTOR),
410 DECL(AL_CONE_OUTER_GAINHF),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
415 DECL(AL_SOURCE_STATE),
416 DECL(AL_INITIAL),
417 DECL(AL_PLAYING),
418 DECL(AL_PAUSED),
419 DECL(AL_STOPPED),
421 DECL(AL_BUFFERS_QUEUED),
422 DECL(AL_BUFFERS_PROCESSED),
424 DECL(AL_FORMAT_MONO8),
425 DECL(AL_FORMAT_MONO16),
426 DECL(AL_FORMAT_MONO_FLOAT32),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
428 DECL(AL_FORMAT_STEREO8),
429 DECL(AL_FORMAT_STEREO16),
430 DECL(AL_FORMAT_STEREO_FLOAT32),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
432 DECL(AL_FORMAT_MONO_IMA4),
433 DECL(AL_FORMAT_STEREO_IMA4),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
436 DECL(AL_FORMAT_QUAD8_LOKI),
437 DECL(AL_FORMAT_QUAD16_LOKI),
438 DECL(AL_FORMAT_QUAD8),
439 DECL(AL_FORMAT_QUAD16),
440 DECL(AL_FORMAT_QUAD32),
441 DECL(AL_FORMAT_51CHN8),
442 DECL(AL_FORMAT_51CHN16),
443 DECL(AL_FORMAT_51CHN32),
444 DECL(AL_FORMAT_61CHN8),
445 DECL(AL_FORMAT_61CHN16),
446 DECL(AL_FORMAT_61CHN32),
447 DECL(AL_FORMAT_71CHN8),
448 DECL(AL_FORMAT_71CHN16),
449 DECL(AL_FORMAT_71CHN32),
450 DECL(AL_FORMAT_REAR8),
451 DECL(AL_FORMAT_REAR16),
452 DECL(AL_FORMAT_REAR32),
453 DECL(AL_FORMAT_MONO_MULAW),
454 DECL(AL_FORMAT_MONO_MULAW_EXT),
455 DECL(AL_FORMAT_STEREO_MULAW),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT),
457 DECL(AL_FORMAT_QUAD_MULAW),
458 DECL(AL_FORMAT_51CHN_MULAW),
459 DECL(AL_FORMAT_61CHN_MULAW),
460 DECL(AL_FORMAT_71CHN_MULAW),
461 DECL(AL_FORMAT_REAR_MULAW),
462 DECL(AL_FORMAT_MONO_ALAW_EXT),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT),
465 DECL(AL_FORMAT_BFORMAT2D_8),
466 DECL(AL_FORMAT_BFORMAT2D_16),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW),
469 DECL(AL_FORMAT_BFORMAT3D_8),
470 DECL(AL_FORMAT_BFORMAT3D_16),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW),
474 DECL(AL_MONO8_SOFT),
475 DECL(AL_MONO16_SOFT),
476 DECL(AL_MONO32F_SOFT),
477 DECL(AL_STEREO8_SOFT),
478 DECL(AL_STEREO16_SOFT),
479 DECL(AL_STEREO32F_SOFT),
480 DECL(AL_QUAD8_SOFT),
481 DECL(AL_QUAD16_SOFT),
482 DECL(AL_QUAD32F_SOFT),
483 DECL(AL_REAR8_SOFT),
484 DECL(AL_REAR16_SOFT),
485 DECL(AL_REAR32F_SOFT),
486 DECL(AL_5POINT1_8_SOFT),
487 DECL(AL_5POINT1_16_SOFT),
488 DECL(AL_5POINT1_32F_SOFT),
489 DECL(AL_6POINT1_8_SOFT),
490 DECL(AL_6POINT1_16_SOFT),
491 DECL(AL_6POINT1_32F_SOFT),
492 DECL(AL_7POINT1_8_SOFT),
493 DECL(AL_7POINT1_16_SOFT),
494 DECL(AL_7POINT1_32F_SOFT),
495 DECL(AL_BFORMAT2D_8_SOFT),
496 DECL(AL_BFORMAT2D_16_SOFT),
497 DECL(AL_BFORMAT2D_32F_SOFT),
498 DECL(AL_BFORMAT3D_8_SOFT),
499 DECL(AL_BFORMAT3D_16_SOFT),
500 DECL(AL_BFORMAT3D_32F_SOFT),
502 DECL(AL_MONO_SOFT),
503 DECL(AL_STEREO_SOFT),
504 DECL(AL_QUAD_SOFT),
505 DECL(AL_REAR_SOFT),
506 DECL(AL_5POINT1_SOFT),
507 DECL(AL_6POINT1_SOFT),
508 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BFORMAT2D_SOFT),
510 DECL(AL_BFORMAT3D_SOFT),
512 DECL(AL_BYTE_SOFT),
513 DECL(AL_UNSIGNED_BYTE_SOFT),
514 DECL(AL_SHORT_SOFT),
515 DECL(AL_UNSIGNED_SHORT_SOFT),
516 DECL(AL_INT_SOFT),
517 DECL(AL_UNSIGNED_INT_SOFT),
518 DECL(AL_FLOAT_SOFT),
519 DECL(AL_DOUBLE_SOFT),
520 DECL(AL_BYTE3_SOFT),
521 DECL(AL_UNSIGNED_BYTE3_SOFT),
522 DECL(AL_MULAW_SOFT),
524 DECL(AL_FREQUENCY),
525 DECL(AL_BITS),
526 DECL(AL_CHANNELS),
527 DECL(AL_SIZE),
528 DECL(AL_INTERNAL_FORMAT_SOFT),
529 DECL(AL_BYTE_LENGTH_SOFT),
530 DECL(AL_SAMPLE_LENGTH_SOFT),
531 DECL(AL_SEC_LENGTH_SOFT),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
535 DECL(AL_SOURCE_RADIUS),
537 DECL(AL_STEREO_ANGLES),
539 DECL(AL_UNUSED),
540 DECL(AL_PENDING),
541 DECL(AL_PROCESSED),
543 DECL(AL_NO_ERROR),
544 DECL(AL_INVALID_NAME),
545 DECL(AL_INVALID_ENUM),
546 DECL(AL_INVALID_VALUE),
547 DECL(AL_INVALID_OPERATION),
548 DECL(AL_OUT_OF_MEMORY),
550 DECL(AL_VENDOR),
551 DECL(AL_VERSION),
552 DECL(AL_RENDERER),
553 DECL(AL_EXTENSIONS),
555 DECL(AL_DOPPLER_FACTOR),
556 DECL(AL_DOPPLER_VELOCITY),
557 DECL(AL_DISTANCE_MODEL),
558 DECL(AL_SPEED_OF_SOUND),
559 DECL(AL_SOURCE_DISTANCE_MODEL),
560 DECL(AL_DEFERRED_UPDATES_SOFT),
561 DECL(AL_GAIN_LIMIT_SOFT),
563 DECL(AL_INVERSE_DISTANCE),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED),
565 DECL(AL_LINEAR_DISTANCE),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED),
567 DECL(AL_EXPONENT_DISTANCE),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
570 DECL(AL_FILTER_TYPE),
571 DECL(AL_FILTER_NULL),
572 DECL(AL_FILTER_LOWPASS),
573 DECL(AL_FILTER_HIGHPASS),
574 DECL(AL_FILTER_BANDPASS),
576 DECL(AL_LOWPASS_GAIN),
577 DECL(AL_LOWPASS_GAINHF),
579 DECL(AL_HIGHPASS_GAIN),
580 DECL(AL_HIGHPASS_GAINLF),
582 DECL(AL_BANDPASS_GAIN),
583 DECL(AL_BANDPASS_GAINHF),
584 DECL(AL_BANDPASS_GAINLF),
586 DECL(AL_EFFECT_TYPE),
587 DECL(AL_EFFECT_NULL),
588 DECL(AL_EFFECT_REVERB),
589 DECL(AL_EFFECT_EAXREVERB),
590 DECL(AL_EFFECT_CHORUS),
591 DECL(AL_EFFECT_DISTORTION),
592 DECL(AL_EFFECT_ECHO),
593 DECL(AL_EFFECT_FLANGER),
594 #if 0
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
596 DECL(AL_EFFECT_VOCAL_MORPHER),
597 DECL(AL_EFFECT_PITCH_SHIFTER),
598 #endif
599 DECL(AL_EFFECT_RING_MODULATOR),
600 #if 0
601 DECL(AL_EFFECT_AUTOWAH),
602 #endif
603 DECL(AL_EFFECT_COMPRESSOR),
604 DECL(AL_EFFECT_EQUALIZER),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
608 DECL(AL_EFFECTSLOT_EFFECT),
609 DECL(AL_EFFECTSLOT_GAIN),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
611 DECL(AL_EFFECTSLOT_NULL),
613 DECL(AL_EAXREVERB_DENSITY),
614 DECL(AL_EAXREVERB_DIFFUSION),
615 DECL(AL_EAXREVERB_GAIN),
616 DECL(AL_EAXREVERB_GAINHF),
617 DECL(AL_EAXREVERB_GAINLF),
618 DECL(AL_EAXREVERB_DECAY_TIME),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
627 DECL(AL_EAXREVERB_ECHO_TIME),
628 DECL(AL_EAXREVERB_ECHO_DEPTH),
629 DECL(AL_EAXREVERB_MODULATION_TIME),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
632 DECL(AL_EAXREVERB_HFREFERENCE),
633 DECL(AL_EAXREVERB_LFREFERENCE),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
637 DECL(AL_REVERB_DENSITY),
638 DECL(AL_REVERB_DIFFUSION),
639 DECL(AL_REVERB_GAIN),
640 DECL(AL_REVERB_GAINHF),
641 DECL(AL_REVERB_DECAY_TIME),
642 DECL(AL_REVERB_DECAY_HFRATIO),
643 DECL(AL_REVERB_REFLECTIONS_GAIN),
644 DECL(AL_REVERB_REFLECTIONS_DELAY),
645 DECL(AL_REVERB_LATE_REVERB_GAIN),
646 DECL(AL_REVERB_LATE_REVERB_DELAY),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
649 DECL(AL_REVERB_DECAY_HFLIMIT),
651 DECL(AL_CHORUS_WAVEFORM),
652 DECL(AL_CHORUS_PHASE),
653 DECL(AL_CHORUS_RATE),
654 DECL(AL_CHORUS_DEPTH),
655 DECL(AL_CHORUS_FEEDBACK),
656 DECL(AL_CHORUS_DELAY),
658 DECL(AL_DISTORTION_EDGE),
659 DECL(AL_DISTORTION_GAIN),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
661 DECL(AL_DISTORTION_EQCENTER),
662 DECL(AL_DISTORTION_EQBANDWIDTH),
664 DECL(AL_ECHO_DELAY),
665 DECL(AL_ECHO_LRDELAY),
666 DECL(AL_ECHO_DAMPING),
667 DECL(AL_ECHO_FEEDBACK),
668 DECL(AL_ECHO_SPREAD),
670 DECL(AL_FLANGER_WAVEFORM),
671 DECL(AL_FLANGER_PHASE),
672 DECL(AL_FLANGER_RATE),
673 DECL(AL_FLANGER_DEPTH),
674 DECL(AL_FLANGER_FEEDBACK),
675 DECL(AL_FLANGER_DELAY),
677 DECL(AL_RING_MODULATOR_FREQUENCY),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
679 DECL(AL_RING_MODULATOR_WAVEFORM),
681 DECL(AL_COMPRESSOR_ONOFF),
683 DECL(AL_EQUALIZER_LOW_GAIN),
684 DECL(AL_EQUALIZER_LOW_CUTOFF),
685 DECL(AL_EQUALIZER_MID1_GAIN),
686 DECL(AL_EQUALIZER_MID1_CENTER),
687 DECL(AL_EQUALIZER_MID1_WIDTH),
688 DECL(AL_EQUALIZER_MID2_GAIN),
689 DECL(AL_EQUALIZER_MID2_CENTER),
690 DECL(AL_EQUALIZER_MID2_WIDTH),
691 DECL(AL_EQUALIZER_HIGH_GAIN),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF),
694 DECL(AL_DEDICATED_GAIN),
696 DECL(AL_NUM_RESAMPLERS_SOFT),
697 DECL(AL_DEFAULT_RESAMPLER_SOFT),
698 DECL(AL_SOURCE_RESAMPLER_SOFT),
699 DECL(AL_RESAMPLER_NAME_SOFT),
701 DECL(AL_SOURCE_SPATIALIZE_SOFT),
702 DECL(AL_AUTO_SOFT),
704 #undef DECL
706 static const ALCchar alcNoError[] = "No Error";
707 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
708 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
709 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
710 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
711 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
714 /************************************************
715 * Global variables
716 ************************************************/
718 /* Enumerated device names */
719 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
721 static al_string alcAllDevicesList;
722 static al_string alcCaptureDeviceList;
724 /* Default is always the first in the list */
725 static ALCchar *alcDefaultAllDevicesSpecifier;
726 static ALCchar *alcCaptureDefaultDeviceSpecifier;
728 /* Default context extensions */
729 static const ALchar alExtList[] =
730 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
731 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
732 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
733 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
734 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
735 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
736 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length "
737 "AL_SOFT_source_resampler AL_SOFT_source_spatialize";
739 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
741 /* Thread-local current context */
742 static altss_t LocalContext;
743 /* Process-wide current context */
744 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
746 /* Mixing thread piority level */
747 ALint RTPrioLevel;
749 FILE *LogFile;
750 #ifdef _DEBUG
751 enum LogLevel LogLevel = LogWarning;
752 #else
753 enum LogLevel LogLevel = LogError;
754 #endif
756 /* Flag to trap ALC device errors */
757 static ALCboolean TrapALCError = ALC_FALSE;
759 /* One-time configuration init control */
760 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
762 /* Default effect that applies to sources that don't have an effect on send 0 */
763 static ALeffect DefaultEffect;
765 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
766 * updates.
768 static ALCboolean SuspendDefers = ALC_TRUE;
771 /************************************************
772 * ALC information
773 ************************************************/
774 static const ALCchar alcNoDeviceExtList[] =
775 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
776 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
777 static const ALCchar alcExtensionList[] =
778 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
779 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
780 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
781 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
782 static const ALCint alcMajorVersion = 1;
783 static const ALCint alcMinorVersion = 1;
785 static const ALCint alcEFXMajorVersion = 1;
786 static const ALCint alcEFXMinorVersion = 0;
789 /************************************************
790 * Device lists
791 ************************************************/
792 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
794 static almtx_t ListLock;
795 static inline void LockLists(void)
797 int ret = almtx_lock(&ListLock);
798 assert(ret == althrd_success);
800 static inline void UnlockLists(void)
802 int ret = almtx_unlock(&ListLock);
803 assert(ret == althrd_success);
806 /************************************************
807 * Library initialization
808 ************************************************/
809 #if defined(_WIN32)
810 static void alc_init(void);
811 static void alc_deinit(void);
812 static void alc_deinit_safe(void);
814 #ifndef AL_LIBTYPE_STATIC
815 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
817 switch(reason)
819 case DLL_PROCESS_ATTACH:
820 /* Pin the DLL so we won't get unloaded until the process terminates */
821 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
822 (WCHAR*)hModule, &hModule);
823 alc_init();
824 break;
826 case DLL_THREAD_DETACH:
827 break;
829 case DLL_PROCESS_DETACH:
830 if(!lpReserved)
831 alc_deinit();
832 else
833 alc_deinit_safe();
834 break;
836 return TRUE;
838 #elif defined(_MSC_VER)
839 #pragma section(".CRT$XCU",read)
840 static void alc_constructor(void);
841 static void alc_destructor(void);
842 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
844 static void alc_constructor(void)
846 atexit(alc_destructor);
847 alc_init();
850 static void alc_destructor(void)
852 alc_deinit();
854 #elif defined(HAVE_GCC_DESTRUCTOR)
855 static void alc_init(void) __attribute__((constructor));
856 static void alc_deinit(void) __attribute__((destructor));
857 #else
858 #error "No static initialization available on this platform!"
859 #endif
861 #elif defined(HAVE_GCC_DESTRUCTOR)
863 static void alc_init(void) __attribute__((constructor));
864 static void alc_deinit(void) __attribute__((destructor));
866 #else
867 #error "No global initialization available on this platform!"
868 #endif
870 static void ReleaseThreadCtx(void *ptr);
871 static void alc_init(void)
873 const char *str;
874 int ret;
876 LogFile = stderr;
878 AL_STRING_INIT(alcAllDevicesList);
879 AL_STRING_INIT(alcCaptureDeviceList);
881 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
882 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
883 ConeScale *= 0.5f;
885 str = getenv("__ALSOFT_REVERSE_Z");
886 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
887 ZScale *= -1.0f;
889 str = getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
890 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
891 OverrideReverbSpeedOfSound = AL_TRUE;
893 ret = altss_create(&LocalContext, ReleaseThreadCtx);
894 assert(ret == althrd_success);
896 ret = almtx_init(&ListLock, almtx_recursive);
897 assert(ret == althrd_success);
899 ThunkInit();
902 static void alc_initconfig(void)
904 const char *devs, *str;
905 int capfilter;
906 float valf;
907 int i, n;
909 str = getenv("ALSOFT_LOGLEVEL");
910 if(str)
912 long lvl = strtol(str, NULL, 0);
913 if(lvl >= NoLog && lvl <= LogRef)
914 LogLevel = lvl;
917 str = getenv("ALSOFT_LOGFILE");
918 if(str && str[0])
920 FILE *logfile = al_fopen(str, "wt");
921 if(logfile) LogFile = logfile;
922 else ERR("Failed to open log file '%s'\n", str);
925 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
926 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
928 char buf[1024] = "";
929 int len = 0;
931 if(BackendListSize > 0)
932 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
933 for(i = 1;i < BackendListSize;i++)
934 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
935 TRACE("Supported backends: %s\n", buf);
937 ReadALConfig();
939 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
940 if(str && *str)
942 if(strcasecmp(str, "ignore") == 0)
944 SuspendDefers = ALC_FALSE;
945 TRACE("Selected context suspend behavior, \"ignore\"\n");
947 else
948 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
951 capfilter = 0;
952 #if defined(HAVE_SSE4_1)
953 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
954 #elif defined(HAVE_SSE3)
955 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
956 #elif defined(HAVE_SSE2)
957 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
958 #elif defined(HAVE_SSE)
959 capfilter |= CPU_CAP_SSE;
960 #endif
961 #ifdef HAVE_NEON
962 capfilter |= CPU_CAP_NEON;
963 #endif
964 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
966 if(strcasecmp(str, "all") == 0)
967 capfilter = 0;
968 else
970 size_t len;
971 const char *next = str;
973 do {
974 str = next;
975 while(isspace(str[0]))
976 str++;
977 next = strchr(str, ',');
979 if(!str[0] || str[0] == ',')
980 continue;
982 len = (next ? ((size_t)(next-str)) : strlen(str));
983 while(len > 0 && isspace(str[len-1]))
984 len--;
985 if(len == 3 && strncasecmp(str, "sse", len) == 0)
986 capfilter &= ~CPU_CAP_SSE;
987 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
988 capfilter &= ~CPU_CAP_SSE2;
989 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
990 capfilter &= ~CPU_CAP_SSE3;
991 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
992 capfilter &= ~CPU_CAP_SSE4_1;
993 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
994 capfilter &= ~CPU_CAP_NEON;
995 else
996 WARN("Invalid CPU extension \"%s\"\n", str);
997 } while(next++);
1000 FillCPUCaps(capfilter);
1002 #ifdef _WIN32
1003 RTPrioLevel = 1;
1004 #else
1005 RTPrioLevel = 0;
1006 #endif
1007 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
1009 aluInit();
1010 aluInitMixer();
1012 str = getenv("ALSOFT_TRAP_ERROR");
1013 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1015 TrapALError = AL_TRUE;
1016 TrapALCError = AL_TRUE;
1018 else
1020 str = getenv("ALSOFT_TRAP_AL_ERROR");
1021 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1022 TrapALError = AL_TRUE;
1023 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1025 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1026 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1027 TrapALCError = ALC_TRUE;
1028 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1031 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1032 ReverbBoost *= powf(10.0f, valf / 20.0f);
1034 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1035 ConfigValueStr(NULL, NULL, "drivers", &devs))
1037 int n;
1038 size_t len;
1039 const char *next = devs;
1040 int endlist, delitem;
1042 i = 0;
1043 do {
1044 devs = next;
1045 while(isspace(devs[0]))
1046 devs++;
1047 next = strchr(devs, ',');
1049 delitem = (devs[0] == '-');
1050 if(devs[0] == '-') devs++;
1052 if(!devs[0] || devs[0] == ',')
1054 endlist = 0;
1055 continue;
1057 endlist = 1;
1059 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1060 while(len > 0 && isspace(devs[len-1]))
1061 len--;
1062 for(n = i;n < BackendListSize;n++)
1064 if(len == strlen(BackendList[n].name) &&
1065 strncmp(BackendList[n].name, devs, len) == 0)
1067 if(delitem)
1069 for(;n+1 < BackendListSize;n++)
1070 BackendList[n] = BackendList[n+1];
1071 BackendListSize--;
1073 else
1075 struct BackendInfo Bkp = BackendList[n];
1076 for(;n > i;n--)
1077 BackendList[n] = BackendList[n-1];
1078 BackendList[n] = Bkp;
1080 i++;
1082 break;
1085 } while(next++);
1087 if(endlist)
1088 BackendListSize = i;
1091 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1093 ALCbackendFactory *factory = BackendList[i].getFactory();
1094 if(!V0(factory,init)())
1096 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1097 continue;
1100 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1101 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1103 PlaybackBackend = BackendList[i];
1104 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1106 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1108 CaptureBackend = BackendList[i];
1109 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1113 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1114 V0(factory,init)();
1117 if(!PlaybackBackend.name)
1118 WARN("No playback backend available!\n");
1119 if(!CaptureBackend.name)
1120 WARN("No capture backend available!\n");
1122 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1124 size_t len;
1125 const char *next = str;
1127 do {
1128 str = next;
1129 next = strchr(str, ',');
1131 if(!str[0] || next == str)
1132 continue;
1134 len = (next ? ((size_t)(next-str)) : strlen(str));
1135 for(n = 0;EffectList[n].name;n++)
1137 if(len == strlen(EffectList[n].name) &&
1138 strncmp(EffectList[n].name, str, len) == 0)
1139 DisabledEffects[EffectList[n].type] = AL_TRUE;
1141 } while(next++);
1144 InitEffectFactoryMap();
1146 InitEffect(&DefaultEffect);
1147 str = getenv("ALSOFT_DEFAULT_REVERB");
1148 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1149 LoadReverbPreset(str, &DefaultEffect);
1151 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1153 #ifdef __ANDROID__
1154 #include <jni.h>
1156 static JavaVM *gJavaVM;
1157 static pthread_key_t gJVMThreadKey;
1159 static void CleanupJNIEnv(void* UNUSED(ptr))
1161 JCALL0(gJavaVM,DetachCurrentThread)();
1164 void *Android_GetJNIEnv(void)
1166 if(!gJavaVM)
1168 WARN("gJavaVM is NULL!\n");
1169 return NULL;
1172 /* http://developer.android.com/guide/practices/jni.html
1174 * All threads are Linux threads, scheduled by the kernel. They're usually
1175 * started from managed code (using Thread.start), but they can also be
1176 * created elsewhere and then attached to the JavaVM. For example, a thread
1177 * started with pthread_create can be attached with the JNI
1178 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1179 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1180 * Attaching a natively-created thread causes a java.lang.Thread object to
1181 * be constructed and added to the "main" ThreadGroup, making it visible to
1182 * the debugger. Calling AttachCurrentThread on an already-attached thread
1183 * is a no-op.
1185 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1186 if(!env)
1188 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1189 if(status < 0)
1191 ERR("Failed to attach current thread\n");
1192 return NULL;
1194 pthread_setspecific(gJVMThreadKey, env);
1196 return env;
1199 /* Automatically called by JNI. */
1200 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1202 void *env;
1203 int err;
1205 gJavaVM = jvm;
1206 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1208 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1209 return JNI_ERR;
1212 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1213 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1215 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1216 ERR("pthread_key_create failed: %d\n", err);
1217 pthread_setspecific(gJVMThreadKey, env);
1218 return JNI_VERSION_1_4;
1220 #endif
1223 /************************************************
1224 * Library deinitialization
1225 ************************************************/
1226 static void alc_cleanup(void)
1228 ALCdevice *dev;
1230 AL_STRING_DEINIT(alcAllDevicesList);
1231 AL_STRING_DEINIT(alcCaptureDeviceList);
1233 free(alcDefaultAllDevicesSpecifier);
1234 alcDefaultAllDevicesSpecifier = NULL;
1235 free(alcCaptureDefaultDeviceSpecifier);
1236 alcCaptureDefaultDeviceSpecifier = NULL;
1238 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL)
1240 ALCuint num = 0;
1241 do {
1242 num++;
1243 } while((dev=dev->next) != NULL);
1244 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1247 DeinitEffectFactoryMap();
1250 static void alc_deinit_safe(void)
1252 alc_cleanup();
1254 FreeHrtfs();
1255 FreeALConfig();
1257 ThunkExit();
1258 almtx_destroy(&ListLock);
1259 altss_delete(LocalContext);
1261 if(LogFile != stderr)
1262 fclose(LogFile);
1263 LogFile = NULL;
1266 static void alc_deinit(void)
1268 int i;
1270 alc_cleanup();
1272 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1273 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1275 for(i = 0;i < BackendListSize;i++)
1277 ALCbackendFactory *factory = BackendList[i].getFactory();
1278 V0(factory,deinit)();
1281 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1282 V0(factory,deinit)();
1285 alc_deinit_safe();
1289 /************************************************
1290 * Device enumeration
1291 ************************************************/
1292 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1294 DO_INITCONFIG();
1296 LockLists();
1297 alstr_clear(list);
1299 if(backendinfo->getFactory)
1301 ALCbackendFactory *factory = backendinfo->getFactory();
1302 V(factory,probe)(type);
1305 UnlockLists();
1307 static void ProbeAllDevicesList(void)
1308 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1309 static void ProbeCaptureDeviceList(void)
1310 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1312 static void AppendDevice(const ALCchar *name, al_string *devnames)
1314 size_t len = strlen(name);
1315 if(len > 0)
1316 alstr_append_range(devnames, name, name+len+1);
1318 void AppendAllDevicesList(const ALCchar *name)
1319 { AppendDevice(name, &alcAllDevicesList); }
1320 void AppendCaptureDeviceList(const ALCchar *name)
1321 { AppendDevice(name, &alcCaptureDeviceList); }
1324 /************************************************
1325 * Device format information
1326 ************************************************/
1327 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1329 switch(type)
1331 case DevFmtByte: return "Signed Byte";
1332 case DevFmtUByte: return "Unsigned Byte";
1333 case DevFmtShort: return "Signed Short";
1334 case DevFmtUShort: return "Unsigned Short";
1335 case DevFmtInt: return "Signed Int";
1336 case DevFmtUInt: return "Unsigned Int";
1337 case DevFmtFloat: return "Float";
1339 return "(unknown type)";
1341 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1343 switch(chans)
1345 case DevFmtMono: return "Mono";
1346 case DevFmtStereo: return "Stereo";
1347 case DevFmtQuad: return "Quadraphonic";
1348 case DevFmtX51: return "5.1 Surround";
1349 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1350 case DevFmtX61: return "6.1 Surround";
1351 case DevFmtX71: return "7.1 Surround";
1352 case DevFmtAmbi3D: return "Ambisonic 3D";
1354 return "(unknown channels)";
1357 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1358 ALsizei BytesFromDevFmt(enum DevFmtType type)
1360 switch(type)
1362 case DevFmtByte: return sizeof(ALbyte);
1363 case DevFmtUByte: return sizeof(ALubyte);
1364 case DevFmtShort: return sizeof(ALshort);
1365 case DevFmtUShort: return sizeof(ALushort);
1366 case DevFmtInt: return sizeof(ALint);
1367 case DevFmtUInt: return sizeof(ALuint);
1368 case DevFmtFloat: return sizeof(ALfloat);
1370 return 0;
1372 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1374 switch(chans)
1376 case DevFmtMono: return 1;
1377 case DevFmtStereo: return 2;
1378 case DevFmtQuad: return 4;
1379 case DevFmtX51: return 6;
1380 case DevFmtX51Rear: return 6;
1381 case DevFmtX61: return 7;
1382 case DevFmtX71: return 8;
1383 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1384 (ambiorder == 2) ? 9 :
1385 (ambiorder == 1) ? 4 : 1;
1387 return 0;
1390 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1391 enum DevFmtType *type)
1393 static const struct {
1394 ALenum format;
1395 enum DevFmtChannels channels;
1396 enum DevFmtType type;
1397 } list[] = {
1398 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1399 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1400 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1402 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1403 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1404 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1406 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1407 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1408 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1410 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1411 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1412 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1414 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1415 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1416 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1418 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1419 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1420 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1422 ALuint i;
1424 for(i = 0;i < COUNTOF(list);i++)
1426 if(list[i].format == format)
1428 *chans = list[i].channels;
1429 *type = list[i].type;
1430 return AL_TRUE;
1434 return AL_FALSE;
1437 static ALCboolean IsValidALCType(ALCenum type)
1439 switch(type)
1441 case ALC_BYTE_SOFT:
1442 case ALC_UNSIGNED_BYTE_SOFT:
1443 case ALC_SHORT_SOFT:
1444 case ALC_UNSIGNED_SHORT_SOFT:
1445 case ALC_INT_SOFT:
1446 case ALC_UNSIGNED_INT_SOFT:
1447 case ALC_FLOAT_SOFT:
1448 return ALC_TRUE;
1450 return ALC_FALSE;
1453 static ALCboolean IsValidALCChannels(ALCenum channels)
1455 switch(channels)
1457 case ALC_MONO_SOFT:
1458 case ALC_STEREO_SOFT:
1459 case ALC_QUAD_SOFT:
1460 case ALC_5POINT1_SOFT:
1461 case ALC_6POINT1_SOFT:
1462 case ALC_7POINT1_SOFT:
1463 case ALC_BFORMAT3D_SOFT:
1464 return ALC_TRUE;
1466 return ALC_FALSE;
1469 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1471 switch(layout)
1473 case ALC_ACN_SOFT:
1474 case ALC_FUMA_SOFT:
1475 return ALC_TRUE;
1477 return ALC_FALSE;
1480 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1482 switch(scaling)
1484 case ALC_N3D_SOFT:
1485 case ALC_SN3D_SOFT:
1486 case ALC_FUMA_SOFT:
1487 return ALC_TRUE;
1489 return ALC_FALSE;
1492 /************************************************
1493 * Miscellaneous ALC helpers
1494 ************************************************/
1496 void ALCdevice_Lock(ALCdevice *device)
1498 V0(device->Backend,lock)();
1501 void ALCdevice_Unlock(ALCdevice *device)
1503 V0(device->Backend,unlock)();
1507 /* SetDefaultWFXChannelOrder
1509 * Sets the default channel order used by WaveFormatEx.
1511 void SetDefaultWFXChannelOrder(ALCdevice *device)
1513 ALsizei i;
1515 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1516 device->RealOut.ChannelName[i] = InvalidChannel;
1518 switch(device->FmtChans)
1520 case DevFmtMono:
1521 device->RealOut.ChannelName[0] = FrontCenter;
1522 break;
1523 case DevFmtStereo:
1524 device->RealOut.ChannelName[0] = FrontLeft;
1525 device->RealOut.ChannelName[1] = FrontRight;
1526 break;
1527 case DevFmtQuad:
1528 device->RealOut.ChannelName[0] = FrontLeft;
1529 device->RealOut.ChannelName[1] = FrontRight;
1530 device->RealOut.ChannelName[2] = BackLeft;
1531 device->RealOut.ChannelName[3] = BackRight;
1532 break;
1533 case DevFmtX51:
1534 device->RealOut.ChannelName[0] = FrontLeft;
1535 device->RealOut.ChannelName[1] = FrontRight;
1536 device->RealOut.ChannelName[2] = FrontCenter;
1537 device->RealOut.ChannelName[3] = LFE;
1538 device->RealOut.ChannelName[4] = SideLeft;
1539 device->RealOut.ChannelName[5] = SideRight;
1540 break;
1541 case DevFmtX51Rear:
1542 device->RealOut.ChannelName[0] = FrontLeft;
1543 device->RealOut.ChannelName[1] = FrontRight;
1544 device->RealOut.ChannelName[2] = FrontCenter;
1545 device->RealOut.ChannelName[3] = LFE;
1546 device->RealOut.ChannelName[4] = BackLeft;
1547 device->RealOut.ChannelName[5] = BackRight;
1548 break;
1549 case DevFmtX61:
1550 device->RealOut.ChannelName[0] = FrontLeft;
1551 device->RealOut.ChannelName[1] = FrontRight;
1552 device->RealOut.ChannelName[2] = FrontCenter;
1553 device->RealOut.ChannelName[3] = LFE;
1554 device->RealOut.ChannelName[4] = BackCenter;
1555 device->RealOut.ChannelName[5] = SideLeft;
1556 device->RealOut.ChannelName[6] = SideRight;
1557 break;
1558 case DevFmtX71:
1559 device->RealOut.ChannelName[0] = FrontLeft;
1560 device->RealOut.ChannelName[1] = FrontRight;
1561 device->RealOut.ChannelName[2] = FrontCenter;
1562 device->RealOut.ChannelName[3] = LFE;
1563 device->RealOut.ChannelName[4] = BackLeft;
1564 device->RealOut.ChannelName[5] = BackRight;
1565 device->RealOut.ChannelName[6] = SideLeft;
1566 device->RealOut.ChannelName[7] = SideRight;
1567 break;
1568 case DevFmtAmbi3D:
1569 device->RealOut.ChannelName[0] = Aux0;
1570 if(device->AmbiOrder > 0)
1572 device->RealOut.ChannelName[1] = Aux1;
1573 device->RealOut.ChannelName[2] = Aux2;
1574 device->RealOut.ChannelName[3] = Aux3;
1576 if(device->AmbiOrder > 1)
1578 device->RealOut.ChannelName[4] = Aux4;
1579 device->RealOut.ChannelName[5] = Aux5;
1580 device->RealOut.ChannelName[6] = Aux6;
1581 device->RealOut.ChannelName[7] = Aux7;
1582 device->RealOut.ChannelName[8] = Aux8;
1584 if(device->AmbiOrder > 2)
1586 device->RealOut.ChannelName[9] = Aux9;
1587 device->RealOut.ChannelName[10] = Aux10;
1588 device->RealOut.ChannelName[11] = Aux11;
1589 device->RealOut.ChannelName[12] = Aux12;
1590 device->RealOut.ChannelName[13] = Aux13;
1591 device->RealOut.ChannelName[14] = Aux14;
1592 device->RealOut.ChannelName[15] = Aux15;
1594 break;
1598 /* SetDefaultChannelOrder
1600 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1602 void SetDefaultChannelOrder(ALCdevice *device)
1604 ALsizei i;
1606 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1607 device->RealOut.ChannelName[i] = InvalidChannel;
1609 switch(device->FmtChans)
1611 case DevFmtX51Rear:
1612 device->RealOut.ChannelName[0] = FrontLeft;
1613 device->RealOut.ChannelName[1] = FrontRight;
1614 device->RealOut.ChannelName[2] = BackLeft;
1615 device->RealOut.ChannelName[3] = BackRight;
1616 device->RealOut.ChannelName[4] = FrontCenter;
1617 device->RealOut.ChannelName[5] = LFE;
1618 return;
1619 case DevFmtX71:
1620 device->RealOut.ChannelName[0] = FrontLeft;
1621 device->RealOut.ChannelName[1] = FrontRight;
1622 device->RealOut.ChannelName[2] = BackLeft;
1623 device->RealOut.ChannelName[3] = BackRight;
1624 device->RealOut.ChannelName[4] = FrontCenter;
1625 device->RealOut.ChannelName[5] = LFE;
1626 device->RealOut.ChannelName[6] = SideLeft;
1627 device->RealOut.ChannelName[7] = SideRight;
1628 return;
1630 /* Same as WFX order */
1631 case DevFmtMono:
1632 case DevFmtStereo:
1633 case DevFmtQuad:
1634 case DevFmtX51:
1635 case DevFmtX61:
1636 case DevFmtAmbi3D:
1637 SetDefaultWFXChannelOrder(device);
1638 break;
1642 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1643 extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
1646 /* ALCcontext_DeferUpdates
1648 * Defers/suspends updates for the given context's listener and sources. This
1649 * does *NOT* stop mixing, but rather prevents certain property changes from
1650 * taking effect.
1652 void ALCcontext_DeferUpdates(ALCcontext *context)
1654 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1657 /* ALCcontext_ProcessUpdates
1659 * Resumes update processing after being deferred.
1661 void ALCcontext_ProcessUpdates(ALCcontext *context)
1663 ReadLock(&context->PropLock);
1664 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1666 /* Tell the mixer to stop applying updates, then wait for any active
1667 * updating to finish, before providing updates.
1669 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1670 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1671 althrd_yield();
1673 if(!ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_acq_rel))
1674 UpdateContextProps(context);
1675 if(!ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_acq_rel))
1676 UpdateListenerProps(context);
1677 UpdateAllEffectSlotProps(context);
1678 UpdateAllSourceProps(context);
1680 /* Now with all updates declared, let the mixer continue applying them
1681 * so they all happen at once.
1683 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1685 ReadUnlock(&context->PropLock);
1689 /* alcSetError
1691 * Stores the latest ALC device error
1693 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1695 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1696 if(TrapALCError)
1698 #ifdef _WIN32
1699 /* DebugBreak() will cause an exception if there is no debugger */
1700 if(IsDebuggerPresent())
1701 DebugBreak();
1702 #elif defined(SIGTRAP)
1703 raise(SIGTRAP);
1704 #endif
1707 if(device)
1708 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1709 else
1710 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1714 struct Compressor *CreateDeviceLimiter(const ALCdevice *device)
1716 return CompressorInit(0.0f, 0.0f, AL_FALSE, AL_TRUE, 0.0f, 0.0f, 0.5f, 2.0f,
1717 0.0f, -3.0f, 3.0f, device->Frequency);
1720 /* UpdateClockBase
1722 * Updates the device's base clock time with however many samples have been
1723 * done. This is used so frequency changes on the device don't cause the time
1724 * to jump forward or back. Must not be called while the device is running/
1725 * mixing.
1727 static inline void UpdateClockBase(ALCdevice *device)
1729 IncrementRef(&device->MixCount);
1730 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1731 device->SamplesDone = 0;
1732 IncrementRef(&device->MixCount);
1735 /* UpdateDeviceParams
1737 * Updates device parameters according to the attribute list (caller is
1738 * responsible for holding the list lock).
1740 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1742 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1743 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1744 ALCenum gainLimiter = device->Limiter ? ALC_TRUE : ALC_FALSE;
1745 const ALsizei old_sends = device->NumAuxSends;
1746 ALsizei new_sends = device->NumAuxSends;
1747 enum DevFmtChannels oldChans;
1748 enum DevFmtType oldType;
1749 ALboolean update_failed;
1750 ALCsizei hrtf_id = -1;
1751 ALCcontext *context;
1752 ALCuint oldFreq;
1753 size_t size;
1754 ALCsizei i;
1755 int val;
1757 // Check for attributes
1758 if(device->Type == Loopback)
1760 ALCsizei numMono, numStereo, numSends;
1761 ALCenum alayout = AL_NONE;
1762 ALCenum ascale = AL_NONE;
1763 ALCenum schans = AL_NONE;
1764 ALCenum stype = AL_NONE;
1765 ALCsizei attrIdx = 0;
1766 ALCsizei aorder = 0;
1767 ALCuint freq = 0;
1769 if(!attrList)
1771 WARN("Missing attributes for loopback device\n");
1772 return ALC_INVALID_VALUE;
1775 numMono = device->NumMonoSources;
1776 numStereo = device->NumStereoSources;
1777 numSends = old_sends;
1779 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1780 while(attrList[attrIdx])
1782 switch(attrList[attrIdx])
1784 case ALC_FORMAT_CHANNELS_SOFT:
1785 schans = attrList[attrIdx + 1];
1786 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1787 if(!IsValidALCChannels(schans))
1788 return ALC_INVALID_VALUE;
1789 break;
1791 case ALC_FORMAT_TYPE_SOFT:
1792 stype = attrList[attrIdx + 1];
1793 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1794 if(!IsValidALCType(stype))
1795 return ALC_INVALID_VALUE;
1796 break;
1798 case ALC_FREQUENCY:
1799 freq = attrList[attrIdx + 1];
1800 TRACE_ATTR(ALC_FREQUENCY, freq);
1801 if(freq < MIN_OUTPUT_RATE)
1802 return ALC_INVALID_VALUE;
1803 break;
1805 case ALC_AMBISONIC_LAYOUT_SOFT:
1806 alayout = attrList[attrIdx + 1];
1807 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1808 if(!IsValidAmbiLayout(alayout))
1809 return ALC_INVALID_VALUE;
1810 break;
1812 case ALC_AMBISONIC_SCALING_SOFT:
1813 ascale = attrList[attrIdx + 1];
1814 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1815 if(!IsValidAmbiScaling(ascale))
1816 return ALC_INVALID_VALUE;
1817 break;
1819 case ALC_AMBISONIC_ORDER_SOFT:
1820 aorder = attrList[attrIdx + 1];
1821 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1822 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1823 return ALC_INVALID_VALUE;
1824 break;
1826 case ALC_MONO_SOURCES:
1827 numMono = attrList[attrIdx + 1];
1828 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1829 numMono = maxi(numMono, 0);
1830 break;
1832 case ALC_STEREO_SOURCES:
1833 numStereo = attrList[attrIdx + 1];
1834 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1835 numStereo = maxi(numStereo, 0);
1836 break;
1838 case ALC_MAX_AUXILIARY_SENDS:
1839 numSends = attrList[attrIdx + 1];
1840 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1841 numSends = clampi(numSends, 0, MAX_SENDS);
1842 break;
1844 case ALC_HRTF_SOFT:
1845 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1846 if(attrList[attrIdx + 1] == ALC_FALSE)
1847 hrtf_appreq = Hrtf_Disable;
1848 else if(attrList[attrIdx + 1] == ALC_TRUE)
1849 hrtf_appreq = Hrtf_Enable;
1850 else
1851 hrtf_appreq = Hrtf_Default;
1852 break;
1854 case ALC_HRTF_ID_SOFT:
1855 hrtf_id = attrList[attrIdx + 1];
1856 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1857 break;
1859 case ALC_OUTPUT_LIMITER_SOFT:
1860 gainLimiter = attrList[attrIdx + 1];
1861 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1862 break;
1864 default:
1865 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx],
1866 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1867 break;
1870 attrIdx += 2;
1872 #undef TRACE_ATTR
1874 if(!schans || !stype || !freq)
1876 WARN("Missing format for loopback device\n");
1877 return ALC_INVALID_VALUE;
1879 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1881 WARN("Missing ambisonic info for loopback device\n");
1882 return ALC_INVALID_VALUE;
1885 if((device->Flags&DEVICE_RUNNING))
1886 V0(device->Backend,stop)();
1887 device->Flags &= ~DEVICE_RUNNING;
1889 UpdateClockBase(device);
1891 device->Frequency = freq;
1892 device->FmtChans = schans;
1893 device->FmtType = stype;
1894 if(schans == ALC_BFORMAT3D_SOFT)
1896 device->AmbiOrder = aorder;
1897 device->AmbiLayout = alayout;
1898 device->AmbiScale = ascale;
1901 if(numMono > INT_MAX-numStereo)
1902 numMono = INT_MAX-numStereo;
1903 numMono += numStereo;
1904 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1906 if(numMono <= 0)
1907 numMono = 256;
1909 else
1910 numMono = maxi(numMono, 256);
1911 numStereo = mini(numStereo, numMono);
1912 numMono -= numStereo;
1913 device->SourcesMax = numMono + numStereo;
1915 device->NumMonoSources = numMono;
1916 device->NumStereoSources = numStereo;
1918 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1919 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1920 else
1921 new_sends = numSends;
1923 else if(attrList && attrList[0])
1925 ALCsizei numMono, numStereo, numSends;
1926 ALCsizei attrIdx = 0;
1927 ALCuint freq;
1929 /* If a context is already running on the device, stop playback so the
1930 * device attributes can be updated. */
1931 if((device->Flags&DEVICE_RUNNING))
1932 V0(device->Backend,stop)();
1933 device->Flags &= ~DEVICE_RUNNING;
1935 UpdateClockBase(device);
1937 freq = device->Frequency;
1938 numMono = device->NumMonoSources;
1939 numStereo = device->NumStereoSources;
1940 numSends = old_sends;
1942 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1943 while(attrList[attrIdx])
1945 switch(attrList[attrIdx])
1947 case ALC_FREQUENCY:
1948 freq = attrList[attrIdx + 1];
1949 TRACE_ATTR(ALC_FREQUENCY, freq);
1950 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1951 break;
1953 case ALC_MONO_SOURCES:
1954 numMono = attrList[attrIdx + 1];
1955 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1956 numMono = maxi(numMono, 0);
1957 break;
1959 case ALC_STEREO_SOURCES:
1960 numStereo = attrList[attrIdx + 1];
1961 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1962 numStereo = maxi(numStereo, 0);
1963 break;
1965 case ALC_MAX_AUXILIARY_SENDS:
1966 numSends = attrList[attrIdx + 1];
1967 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1968 numSends = clampi(numSends, 0, MAX_SENDS);
1969 break;
1971 case ALC_HRTF_SOFT:
1972 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1973 if(attrList[attrIdx + 1] == ALC_FALSE)
1974 hrtf_appreq = Hrtf_Disable;
1975 else if(attrList[attrIdx + 1] == ALC_TRUE)
1976 hrtf_appreq = Hrtf_Enable;
1977 else
1978 hrtf_appreq = Hrtf_Default;
1979 break;
1981 case ALC_HRTF_ID_SOFT:
1982 hrtf_id = attrList[attrIdx + 1];
1983 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1984 break;
1986 case ALC_OUTPUT_LIMITER_SOFT:
1987 gainLimiter = attrList[attrIdx + 1];
1988 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter);
1989 break;
1991 default:
1992 TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx],
1993 attrList[attrIdx + 1], attrList[attrIdx + 1]);
1994 break;
1997 attrIdx += 2;
1999 #undef TRACE_ATTR
2001 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
2002 freq = maxu(freq, MIN_OUTPUT_RATE);
2004 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
2005 device->Frequency;
2006 /* SSE and Neon do best with the update size being a multiple of 4 */
2007 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
2008 device->UpdateSize = (device->UpdateSize+3)&~3;
2010 device->Frequency = freq;
2012 if(numMono > INT_MAX-numStereo)
2013 numMono = INT_MAX-numStereo;
2014 numMono += numStereo;
2015 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
2017 if(numMono <= 0)
2018 numMono = 256;
2020 else
2021 numMono = maxi(numMono, 256);
2022 numStereo = mini(numStereo, numMono);
2023 numMono -= numStereo;
2024 device->SourcesMax = numMono + numStereo;
2026 device->NumMonoSources = numMono;
2027 device->NumStereoSources = numStereo;
2029 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2030 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2031 else
2032 new_sends = numSends;
2035 if((device->Flags&DEVICE_RUNNING))
2036 return ALC_NO_ERROR;
2038 al_free(device->Uhj_Encoder);
2039 device->Uhj_Encoder = NULL;
2041 al_free(device->Bs2b);
2042 device->Bs2b = NULL;
2044 al_free(device->ChannelDelay[0].Buffer);
2045 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2047 device->ChannelDelay[i].Length = 0;
2048 device->ChannelDelay[i].Buffer = NULL;
2051 al_free(device->Dry.Buffer);
2052 device->Dry.Buffer = NULL;
2053 device->Dry.NumChannels = 0;
2054 device->FOAOut.Buffer = NULL;
2055 device->FOAOut.NumChannels = 0;
2056 device->RealOut.Buffer = NULL;
2057 device->RealOut.NumChannels = 0;
2059 UpdateClockBase(device);
2061 device->DitherSeed = DITHER_RNG_SEED;
2063 /*************************************************************************
2064 * Update device format request if HRTF is requested
2066 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2067 if(device->Type != Loopback)
2069 const char *hrtf;
2070 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2072 if(strcasecmp(hrtf, "true") == 0)
2073 hrtf_userreq = Hrtf_Enable;
2074 else if(strcasecmp(hrtf, "false") == 0)
2075 hrtf_userreq = Hrtf_Disable;
2076 else if(strcasecmp(hrtf, "auto") != 0)
2077 ERR("Unexpected hrtf value: %s\n", hrtf);
2080 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2082 struct Hrtf *hrtf = NULL;
2083 if(VECTOR_SIZE(device->HrtfList) == 0)
2085 VECTOR_DEINIT(device->HrtfList);
2086 device->HrtfList = EnumerateHrtf(device->DeviceName);
2088 if(VECTOR_SIZE(device->HrtfList) > 0)
2090 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2091 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2092 else
2093 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2096 if(hrtf)
2098 device->FmtChans = DevFmtStereo;
2099 device->Frequency = hrtf->sampleRate;
2100 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2101 if(device->HrtfHandle)
2102 Hrtf_DecRef(device->HrtfHandle);
2103 device->HrtfHandle = hrtf;
2105 else
2107 hrtf_userreq = Hrtf_Default;
2108 hrtf_appreq = Hrtf_Disable;
2109 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2114 oldFreq = device->Frequency;
2115 oldChans = device->FmtChans;
2116 oldType = device->FmtType;
2118 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2119 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2120 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2121 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2122 device->UpdateSize, device->NumUpdates
2125 if(V0(device->Backend,reset)() == ALC_FALSE)
2126 return ALC_INVALID_DEVICE;
2128 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2130 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2131 DevFmtChannelsString(device->FmtChans));
2132 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2134 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2136 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2137 DevFmtTypeString(device->FmtType));
2138 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2140 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2142 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2143 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2146 if((device->UpdateSize&3) != 0)
2148 if((CPUCapFlags&CPU_CAP_SSE))
2149 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2150 if((CPUCapFlags&CPU_CAP_NEON))
2151 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2154 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2155 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2156 device->Frequency, device->UpdateSize, device->NumUpdates
2159 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2160 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2161 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2163 /* Allocate extra channels for any post-filter output. */
2164 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2165 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2167 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2168 device->Dry.Buffer = al_calloc(16, size);
2169 if(!device->Dry.Buffer)
2171 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2172 return ALC_INVALID_DEVICE;
2175 if(device->RealOut.NumChannels != 0)
2176 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2177 device->FOAOut.NumChannels;
2178 else
2180 device->RealOut.Buffer = device->Dry.Buffer;
2181 device->RealOut.NumChannels = device->Dry.NumChannels;
2184 if(device->FOAOut.NumChannels != 0)
2185 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2186 else
2188 device->FOAOut.Buffer = device->Dry.Buffer;
2189 device->FOAOut.NumChannels = device->Dry.NumChannels;
2192 device->NumAuxSends = new_sends;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2195 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2197 device->DitherDepth = 0.0f;
2198 if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "dither", 1))
2200 ALint depth = 0;
2201 ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "dither-depth", &depth);
2202 if(depth <= 0)
2204 switch(device->FmtType)
2206 case DevFmtByte:
2207 case DevFmtUByte:
2208 depth = 8;
2209 break;
2210 case DevFmtShort:
2211 case DevFmtUShort:
2212 depth = 16;
2213 break;
2214 case DevFmtInt:
2215 case DevFmtUInt:
2216 case DevFmtFloat:
2217 break;
2220 else if(depth > 24)
2221 depth = 24;
2222 device->DitherDepth = (depth > 0) ? powf(2.0f, (ALfloat)(depth-1)) : 0.0f;
2224 if(!(device->DitherDepth > 0.0f))
2225 TRACE("Dithering disabled\n");
2226 else
2227 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device->DitherDepth)+1.0f,
2228 device->DitherDepth);
2230 if(ConfigValueBool(alstr_get_cstr(device->DeviceName), NULL, "output-limiter", &val))
2231 gainLimiter = val ? ALC_TRUE : ALC_FALSE;
2232 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2233 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2234 * ALC_TRUE.
2236 if(gainLimiter != ALC_FALSE)
2238 if(!device->Limiter || device->Frequency != GetCompressorSampleRate(device->Limiter))
2240 al_free(device->Limiter);
2241 device->Limiter = CreateDeviceLimiter(device);
2244 else
2246 al_free(device->Limiter);
2247 device->Limiter = NULL;
2249 TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
2251 /* Need to delay returning failure until replacement Send arrays have been
2252 * allocated with the appropriate size.
2254 update_failed = AL_FALSE;
2255 START_MIXER_MODE();
2256 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2257 while(context)
2259 struct ALvoiceProps *vprops;
2260 ALsizei pos;
2262 if(context->DefaultSlot)
2264 ALeffectslot *slot = context->DefaultSlot;
2265 ALeffectState *state = slot->Effect.State;
2267 state->OutBuffer = device->Dry.Buffer;
2268 state->OutChannels = device->Dry.NumChannels;
2269 if(V(state,deviceUpdate)(device) == AL_FALSE)
2270 update_failed = AL_TRUE;
2271 else
2272 UpdateEffectSlotProps(slot, context);
2275 WriteLock(&context->PropLock);
2276 LockUIntMapRead(&context->EffectSlotMap);
2277 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2279 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2280 ALeffectState *state = slot->Effect.State;
2282 state->OutBuffer = device->Dry.Buffer;
2283 state->OutChannels = device->Dry.NumChannels;
2284 if(V(state,deviceUpdate)(device) == AL_FALSE)
2285 update_failed = AL_TRUE;
2286 else
2287 UpdateEffectSlotProps(slot, context);
2289 UnlockUIntMapRead(&context->EffectSlotMap);
2291 LockUIntMapRead(&context->SourceMap);
2292 RelimitUIntMapNoLock(&context->SourceMap, device->SourcesMax);
2293 for(pos = 0;pos < context->SourceMap.size;pos++)
2295 ALsource *source = context->SourceMap.values[pos];
2297 if(old_sends != device->NumAuxSends)
2299 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2300 ALsizei s;
2302 memcpy(sends, source->Send,
2303 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2305 for(s = device->NumAuxSends;s < old_sends;s++)
2307 if(source->Send[s].Slot)
2308 DecrementRef(&source->Send[s].Slot->ref);
2309 source->Send[s].Slot = NULL;
2311 al_free(source->Send);
2312 source->Send = sends;
2313 for(s = old_sends;s < device->NumAuxSends;s++)
2315 source->Send[s].Slot = NULL;
2316 source->Send[s].Gain = 1.0f;
2317 source->Send[s].GainHF = 1.0f;
2318 source->Send[s].HFReference = LOWPASSFREQREF;
2319 source->Send[s].GainLF = 1.0f;
2320 source->Send[s].LFReference = HIGHPASSFREQREF;
2324 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2327 /* Clear any pre-existing voice property structs, in case the number of
2328 * auxiliary sends is changing. Active sources will have updates
2329 * respecified in UpdateAllSourceProps.
2331 vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel);
2332 while(vprops)
2334 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2335 al_free(vprops);
2336 vprops = next;
2339 AllocateVoices(context, context->MaxVoices, old_sends);
2340 for(pos = 0;pos < context->VoiceCount;pos++)
2342 ALvoice *voice = context->Voices[pos];
2344 al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel));
2346 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2347 continue;
2349 if(device->AvgSpeakerDist > 0.0f)
2351 /* Reinitialize the NFC filters for new parameters. */
2352 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2353 (device->AvgSpeakerDist * device->Frequency);
2354 for(i = 0;i < voice->NumChannels;i++)
2356 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2357 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2358 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2362 UnlockUIntMapRead(&context->SourceMap);
2364 ATOMIC_FLAG_TEST_AND_SET(&context->PropsClean, almemory_order_release);
2365 UpdateContextProps(context);
2366 ATOMIC_FLAG_TEST_AND_SET(&context->Listener->PropsClean, almemory_order_release);
2367 UpdateListenerProps(context);
2368 UpdateAllSourceProps(context);
2369 WriteUnlock(&context->PropLock);
2371 context = context->next;
2373 END_MIXER_MODE();
2374 if(update_failed)
2375 return ALC_INVALID_DEVICE;
2377 if(!(device->Flags&DEVICE_PAUSED))
2379 if(V0(device->Backend,start)() == ALC_FALSE)
2380 return ALC_INVALID_DEVICE;
2381 device->Flags |= DEVICE_RUNNING;
2384 return ALC_NO_ERROR;
2387 /* FreeDevice
2389 * Frees the device structure, and destroys any objects the app failed to
2390 * delete. Called once there's no more references on the device.
2392 static ALCvoid FreeDevice(ALCdevice *device)
2394 ALsizei i;
2396 TRACE("%p\n", device);
2398 V0(device->Backend,close)();
2399 DELETE_OBJ(device->Backend);
2400 device->Backend = NULL;
2402 almtx_destroy(&device->BackendLock);
2404 if(device->BufferMap.size > 0)
2406 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2407 (device->BufferMap.size==1)?"":"s");
2408 ReleaseALBuffers(device);
2410 ResetUIntMap(&device->BufferMap);
2412 if(device->EffectMap.size > 0)
2414 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2415 (device->EffectMap.size==1)?"":"s");
2416 ReleaseALEffects(device);
2418 ResetUIntMap(&device->EffectMap);
2420 if(device->FilterMap.size > 0)
2422 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2423 (device->FilterMap.size==1)?"":"s");
2424 ReleaseALFilters(device);
2426 ResetUIntMap(&device->FilterMap);
2428 AL_STRING_DEINIT(device->HrtfName);
2429 FreeHrtfList(&device->HrtfList);
2430 if(device->HrtfHandle)
2431 Hrtf_DecRef(device->HrtfHandle);
2432 device->HrtfHandle = NULL;
2433 al_free(device->Hrtf);
2434 device->Hrtf = NULL;
2436 al_free(device->Bs2b);
2437 device->Bs2b = NULL;
2439 al_free(device->Uhj_Encoder);
2440 device->Uhj_Encoder = NULL;
2442 bformatdec_free(device->AmbiDecoder);
2443 device->AmbiDecoder = NULL;
2445 ambiup_free(device->AmbiUp);
2446 device->AmbiUp = NULL;
2448 al_free(device->Stablizer);
2449 device->Stablizer = NULL;
2451 al_free(device->Limiter);
2452 device->Limiter = NULL;
2454 al_free(device->ChannelDelay[0].Buffer);
2455 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2457 device->ChannelDelay[i].Gain = 1.0f;
2458 device->ChannelDelay[i].Length = 0;
2459 device->ChannelDelay[i].Buffer = NULL;
2462 AL_STRING_DEINIT(device->DeviceName);
2464 al_free(device->Dry.Buffer);
2465 device->Dry.Buffer = NULL;
2466 device->Dry.NumChannels = 0;
2467 device->FOAOut.Buffer = NULL;
2468 device->FOAOut.NumChannels = 0;
2469 device->RealOut.Buffer = NULL;
2470 device->RealOut.NumChannels = 0;
2472 al_free(device);
2476 void ALCdevice_IncRef(ALCdevice *device)
2478 uint ref;
2479 ref = IncrementRef(&device->ref);
2480 TRACEREF("%p increasing refcount to %u\n", device, ref);
2483 void ALCdevice_DecRef(ALCdevice *device)
2485 uint ref;
2486 ref = DecrementRef(&device->ref);
2487 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2488 if(ref == 0) FreeDevice(device);
2491 /* VerifyDevice
2493 * Checks if the device handle is valid, and increments its ref count if so.
2495 static ALCboolean VerifyDevice(ALCdevice **device)
2497 ALCdevice *tmpDevice;
2499 LockLists();
2500 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2501 while(tmpDevice)
2503 if(tmpDevice == *device)
2505 ALCdevice_IncRef(tmpDevice);
2506 UnlockLists();
2507 return ALC_TRUE;
2509 tmpDevice = tmpDevice->next;
2511 UnlockLists();
2513 *device = NULL;
2514 return ALC_FALSE;
2518 /* InitContext
2520 * Initializes context fields
2522 static ALvoid InitContext(ALCcontext *Context)
2524 ALlistener *listener = Context->Listener;
2525 struct ALeffectslotArray *auxslots;
2527 //Initialise listener
2528 listener->Gain = 1.0f;
2529 listener->Position[0] = 0.0f;
2530 listener->Position[1] = 0.0f;
2531 listener->Position[2] = 0.0f;
2532 listener->Velocity[0] = 0.0f;
2533 listener->Velocity[1] = 0.0f;
2534 listener->Velocity[2] = 0.0f;
2535 listener->Forward[0] = 0.0f;
2536 listener->Forward[1] = 0.0f;
2537 listener->Forward[2] = -1.0f;
2538 listener->Up[0] = 0.0f;
2539 listener->Up[1] = 1.0f;
2540 listener->Up[2] = 0.0f;
2541 ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed);
2543 ATOMIC_INIT(&listener->Update, NULL);
2545 //Validate Context
2546 InitRef(&Context->UpdateCount, 0);
2547 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2548 Context->GainBoost = 1.0f;
2549 RWLockInit(&Context->PropLock);
2550 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2551 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2552 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2554 if(Context->DefaultSlot)
2556 auxslots = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, 1));
2557 auxslots->count = 1;
2558 auxslots->slot[0] = Context->DefaultSlot;
2560 else
2562 auxslots = al_calloc(DEF_ALIGN, sizeof(struct ALeffectslotArray));
2563 auxslots->count = 0;
2565 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2567 //Set globals
2568 Context->DistanceModel = DefaultDistanceModel;
2569 Context->SourceDistanceModel = AL_FALSE;
2570 Context->DopplerFactor = 1.0f;
2571 Context->DopplerVelocity = 1.0f;
2572 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2573 Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
2574 ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed);
2575 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2577 ATOMIC_INIT(&Context->Update, NULL);
2578 ATOMIC_INIT(&Context->FreeContextProps, NULL);
2579 ATOMIC_INIT(&Context->FreeListenerProps, NULL);
2580 ATOMIC_INIT(&Context->FreeVoiceProps, NULL);
2581 ATOMIC_INIT(&Context->FreeEffectslotProps, NULL);
2583 Context->ExtensionList = alExtList;
2586 listener->Params.Matrix = IdentityMatrixf;
2587 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2588 listener->Params.Gain = listener->Gain;
2589 listener->Params.MetersPerUnit = Context->MetersPerUnit;
2590 listener->Params.DopplerFactor = Context->DopplerFactor;
2591 listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
2592 listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
2593 listener->Params.MetersPerUnit;
2594 listener->Params.SourceDistanceModel = Context->SourceDistanceModel;
2595 listener->Params.DistanceModel = Context->DistanceModel;
2599 /* FreeContext
2601 * Cleans up the context, and destroys any remaining objects the app failed to
2602 * delete. Called once there's no more references on the context.
2604 static void FreeContext(ALCcontext *context)
2606 ALlistener *listener = context->Listener;
2607 struct ALeffectslotArray *auxslots;
2608 struct ALeffectslotProps *eprops;
2609 struct ALlistenerProps *lprops;
2610 struct ALcontextProps *cprops;
2611 struct ALvoiceProps *vprops;
2612 size_t count;
2613 ALsizei i;
2615 TRACE("%p\n", context);
2617 if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
2619 TRACE("Freed unapplied context update %p\n", cprops);
2620 al_free(cprops);
2623 count = 0;
2624 cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
2625 while(cprops)
2627 struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
2628 al_free(cprops);
2629 cprops = next;
2630 ++count;
2632 TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
2634 if(context->DefaultSlot)
2636 DeinitEffectSlot(context->DefaultSlot);
2637 context->DefaultSlot = NULL;
2640 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2641 al_free(auxslots);
2643 if(context->SourceMap.size > 0)
2645 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2646 (context->SourceMap.size==1)?"":"s");
2647 ReleaseALSources(context);
2649 ResetUIntMap(&context->SourceMap);
2651 count = 0;
2652 eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
2653 while(eprops)
2655 struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed);
2656 if(eprops->State) ALeffectState_DecRef(eprops->State);
2657 al_free(eprops);
2658 eprops = next;
2659 ++count;
2661 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
2662 if(context->EffectSlotMap.size > 0)
2664 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2665 (context->EffectSlotMap.size==1)?"":"s");
2666 ReleaseALAuxiliaryEffectSlots(context);
2668 ResetUIntMap(&context->EffectSlotMap);
2670 count = 0;
2671 vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed);
2672 while(vprops)
2674 struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed);
2675 al_free(vprops);
2676 vprops = next;
2677 ++count;
2679 TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s");
2681 for(i = 0;i < context->VoiceCount;i++)
2682 DeinitVoice(context->Voices[i]);
2683 al_free(context->Voices);
2684 context->Voices = NULL;
2685 context->VoiceCount = 0;
2686 context->MaxVoices = 0;
2688 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2690 TRACE("Freed unapplied listener update %p\n", lprops);
2691 al_free(lprops);
2693 count = 0;
2694 lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
2695 while(lprops)
2697 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2698 al_free(lprops);
2699 lprops = next;
2700 ++count;
2702 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2704 ALCdevice_DecRef(context->Device);
2705 context->Device = NULL;
2707 //Invalidate context
2708 memset(context, 0, sizeof(ALCcontext));
2709 al_free(context);
2712 /* ReleaseContext
2714 * Removes the context reference from the given device and removes it from
2715 * being current on the running thread or globally. Returns true if other
2716 * contexts still exist on the device.
2718 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2720 ALCcontext *origctx, *newhead;
2721 bool ret = true;
2723 if(altss_get(LocalContext) == context)
2725 WARN("%p released while current on thread\n", context);
2726 altss_set(LocalContext, NULL);
2727 ALCcontext_DecRef(context);
2730 origctx = context;
2731 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2732 ALCcontext_DecRef(context);
2734 ALCdevice_Lock(device);
2735 origctx = context;
2736 newhead = context->next;
2737 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2739 ALCcontext *volatile*list = &origctx->next;
2740 while(*list)
2742 if(*list == context)
2744 *list = (*list)->next;
2745 break;
2747 list = &(*list)->next;
2750 else
2751 ret = !!newhead;
2752 ALCdevice_Unlock(device);
2754 ALCcontext_DecRef(context);
2755 return ret;
2758 void ALCcontext_IncRef(ALCcontext *context)
2760 uint ref = IncrementRef(&context->ref);
2761 TRACEREF("%p increasing refcount to %u\n", context, ref);
2764 void ALCcontext_DecRef(ALCcontext *context)
2766 uint ref = DecrementRef(&context->ref);
2767 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2768 if(ref == 0) FreeContext(context);
2771 static void ReleaseThreadCtx(void *ptr)
2773 ALCcontext *context = ptr;
2774 uint ref = DecrementRef(&context->ref);
2775 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2776 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2779 /* VerifyContext
2781 * Checks that the given context is valid, and increments its reference count.
2783 static ALCboolean VerifyContext(ALCcontext **context)
2785 ALCdevice *dev;
2787 LockLists();
2788 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2789 while(dev)
2791 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2792 while(ctx)
2794 if(ctx == *context)
2796 ALCcontext_IncRef(ctx);
2797 UnlockLists();
2798 return ALC_TRUE;
2800 ctx = ctx->next;
2802 dev = dev->next;
2804 UnlockLists();
2806 *context = NULL;
2807 return ALC_FALSE;
2811 /* GetContextRef
2813 * Returns the currently active context for this thread, and adds a reference
2814 * without locking it.
2816 ALCcontext *GetContextRef(void)
2818 ALCcontext *context;
2820 context = altss_get(LocalContext);
2821 if(context)
2822 ALCcontext_IncRef(context);
2823 else
2825 LockLists();
2826 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2827 if(context)
2828 ALCcontext_IncRef(context);
2829 UnlockLists();
2832 return context;
2836 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2838 ALCdevice *device = context->Device;
2839 ALsizei num_sends = device->NumAuxSends;
2840 struct ALvoiceProps *props;
2841 size_t sizeof_props;
2842 size_t sizeof_voice;
2843 ALvoice **voices;
2844 ALvoice *voice;
2845 ALsizei v = 0;
2846 size_t size;
2848 if(num_voices == context->MaxVoices && num_sends == old_sends)
2849 return;
2851 /* Allocate the voice pointers, voices, and the voices' stored source
2852 * property set (including the dynamically-sized Send[] array) in one
2853 * chunk.
2855 sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16);
2856 sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16);
2857 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2859 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2860 /* The voice and property objects are stored interleaved since they're
2861 * paired together.
2863 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2864 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2866 if(context->Voices)
2868 const ALsizei v_count = mini(context->VoiceCount, num_voices);
2869 const ALsizei s_count = mini(old_sends, num_sends);
2871 for(;v < v_count;v++)
2873 ALvoice *old_voice = context->Voices[v];
2874 ALsizei i;
2876 /* Copy the old voice data and source property set to the new
2877 * storage.
2879 *voice = *old_voice;
2880 for(i = 0;i < s_count;i++)
2881 voice->Send[i] = old_voice->Send[i];
2882 *props = *(old_voice->Props);
2883 for(i = 0;i < s_count;i++)
2884 props->Send[i] = old_voice->Props->Send[i];
2886 /* Set this voice's property set pointer and voice reference. */
2887 voice->Props = props;
2888 voices[v] = voice;
2890 /* Increment pointers to the next storage space. */
2891 voice = (ALvoice*)((char*)props + sizeof_props);
2892 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2894 /* Deinit any left over voices that weren't copied over to the new
2895 * array. NOTE: If this does anything, v equals num_voices and
2896 * num_voices is less than VoiceCount, so the following loop won't do
2897 * anything.
2899 for(;v < context->VoiceCount;v++)
2900 DeinitVoice(context->Voices[v]);
2902 /* Finish setting the voices' property set pointers and references. */
2903 for(;v < num_voices;v++)
2905 ATOMIC_INIT(&voice->Update, NULL);
2907 voice->Props = props;
2908 voices[v] = voice;
2910 voice = (ALvoice*)((char*)props + sizeof_props);
2911 props = (struct ALvoiceProps*)((char*)voice + sizeof_voice);
2914 al_free(context->Voices);
2915 context->Voices = voices;
2916 context->MaxVoices = num_voices;
2917 context->VoiceCount = mini(context->VoiceCount, num_voices);
2921 /************************************************
2922 * Standard ALC functions
2923 ************************************************/
2925 /* alcGetError
2927 * Return last ALC generated error code for the given device
2929 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2931 ALCenum errorCode;
2933 if(VerifyDevice(&device))
2935 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2936 ALCdevice_DecRef(device);
2938 else
2939 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
2941 return errorCode;
2945 /* alcSuspendContext
2947 * Suspends updates for the given context
2949 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2951 if(!SuspendDefers)
2952 return;
2954 if(!VerifyContext(&context))
2955 alcSetError(NULL, ALC_INVALID_CONTEXT);
2956 else
2958 ALCcontext_DeferUpdates(context);
2959 ALCcontext_DecRef(context);
2963 /* alcProcessContext
2965 * Resumes processing updates for the given context
2967 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2969 if(!SuspendDefers)
2970 return;
2972 if(!VerifyContext(&context))
2973 alcSetError(NULL, ALC_INVALID_CONTEXT);
2974 else
2976 ALCcontext_ProcessUpdates(context);
2977 ALCcontext_DecRef(context);
2982 /* alcGetString
2984 * Returns information about the device, and error strings
2986 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2988 const ALCchar *value = NULL;
2990 switch(param)
2992 case ALC_NO_ERROR:
2993 value = alcNoError;
2994 break;
2996 case ALC_INVALID_ENUM:
2997 value = alcErrInvalidEnum;
2998 break;
3000 case ALC_INVALID_VALUE:
3001 value = alcErrInvalidValue;
3002 break;
3004 case ALC_INVALID_DEVICE:
3005 value = alcErrInvalidDevice;
3006 break;
3008 case ALC_INVALID_CONTEXT:
3009 value = alcErrInvalidContext;
3010 break;
3012 case ALC_OUT_OF_MEMORY:
3013 value = alcErrOutOfMemory;
3014 break;
3016 case ALC_DEVICE_SPECIFIER:
3017 value = alcDefaultName;
3018 break;
3020 case ALC_ALL_DEVICES_SPECIFIER:
3021 if(VerifyDevice(&Device))
3023 value = alstr_get_cstr(Device->DeviceName);
3024 ALCdevice_DecRef(Device);
3026 else
3028 ProbeAllDevicesList();
3029 value = alstr_get_cstr(alcAllDevicesList);
3031 break;
3033 case ALC_CAPTURE_DEVICE_SPECIFIER:
3034 if(VerifyDevice(&Device))
3036 value = alstr_get_cstr(Device->DeviceName);
3037 ALCdevice_DecRef(Device);
3039 else
3041 ProbeCaptureDeviceList();
3042 value = alstr_get_cstr(alcCaptureDeviceList);
3044 break;
3046 /* Default devices are always first in the list */
3047 case ALC_DEFAULT_DEVICE_SPECIFIER:
3048 value = alcDefaultName;
3049 break;
3051 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
3052 if(alstr_empty(alcAllDevicesList))
3053 ProbeAllDevicesList();
3055 VerifyDevice(&Device);
3057 free(alcDefaultAllDevicesSpecifier);
3058 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
3059 if(!alcDefaultAllDevicesSpecifier)
3060 alcSetError(Device, ALC_OUT_OF_MEMORY);
3062 value = alcDefaultAllDevicesSpecifier;
3063 if(Device) ALCdevice_DecRef(Device);
3064 break;
3066 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
3067 if(alstr_empty(alcCaptureDeviceList))
3068 ProbeCaptureDeviceList();
3070 VerifyDevice(&Device);
3072 free(alcCaptureDefaultDeviceSpecifier);
3073 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
3074 if(!alcCaptureDefaultDeviceSpecifier)
3075 alcSetError(Device, ALC_OUT_OF_MEMORY);
3077 value = alcCaptureDefaultDeviceSpecifier;
3078 if(Device) ALCdevice_DecRef(Device);
3079 break;
3081 case ALC_EXTENSIONS:
3082 if(!VerifyDevice(&Device))
3083 value = alcNoDeviceExtList;
3084 else
3086 value = alcExtensionList;
3087 ALCdevice_DecRef(Device);
3089 break;
3091 case ALC_HRTF_SPECIFIER_SOFT:
3092 if(!VerifyDevice(&Device))
3093 alcSetError(NULL, ALC_INVALID_DEVICE);
3094 else
3096 almtx_lock(&Device->BackendLock);
3097 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
3098 almtx_unlock(&Device->BackendLock);
3099 ALCdevice_DecRef(Device);
3101 break;
3103 default:
3104 VerifyDevice(&Device);
3105 alcSetError(Device, ALC_INVALID_ENUM);
3106 if(Device) ALCdevice_DecRef(Device);
3107 break;
3110 return value;
3114 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
3116 if(device->Type == Capture) return 9;
3117 if(device->Type == Loopback && device->FmtChans == DevFmtAmbi3D)
3118 return 35;
3119 return 29;
3122 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3124 ALCsizei i;
3126 if(size <= 0 || values == NULL)
3128 alcSetError(device, ALC_INVALID_VALUE);
3129 return 0;
3132 if(!device)
3134 switch(param)
3136 case ALC_MAJOR_VERSION:
3137 values[0] = alcMajorVersion;
3138 return 1;
3139 case ALC_MINOR_VERSION:
3140 values[0] = alcMinorVersion;
3141 return 1;
3143 case ALC_ATTRIBUTES_SIZE:
3144 case ALC_ALL_ATTRIBUTES:
3145 case ALC_FREQUENCY:
3146 case ALC_REFRESH:
3147 case ALC_SYNC:
3148 case ALC_MONO_SOURCES:
3149 case ALC_STEREO_SOURCES:
3150 case ALC_CAPTURE_SAMPLES:
3151 case ALC_FORMAT_CHANNELS_SOFT:
3152 case ALC_FORMAT_TYPE_SOFT:
3153 case ALC_AMBISONIC_LAYOUT_SOFT:
3154 case ALC_AMBISONIC_SCALING_SOFT:
3155 case ALC_AMBISONIC_ORDER_SOFT:
3156 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3157 alcSetError(NULL, ALC_INVALID_DEVICE);
3158 return 0;
3160 default:
3161 alcSetError(NULL, ALC_INVALID_ENUM);
3162 return 0;
3164 return 0;
3167 if(device->Type == Capture)
3169 switch(param)
3171 case ALC_ATTRIBUTES_SIZE:
3172 values[0] = NumAttrsForDevice(device);
3173 return 1;
3175 case ALC_ALL_ATTRIBUTES:
3176 if(size < NumAttrsForDevice(device))
3178 alcSetError(device, ALC_INVALID_VALUE);
3179 return 0;
3182 i = 0;
3183 almtx_lock(&device->BackendLock);
3184 values[i++] = ALC_MAJOR_VERSION;
3185 values[i++] = alcMajorVersion;
3186 values[i++] = ALC_MINOR_VERSION;
3187 values[i++] = alcMinorVersion;
3188 values[i++] = ALC_CAPTURE_SAMPLES;
3189 values[i++] = V0(device->Backend,availableSamples)();
3190 values[i++] = ALC_CONNECTED;
3191 values[i++] = device->Connected;
3192 almtx_unlock(&device->BackendLock);
3194 values[i++] = 0;
3195 return i;
3197 case ALC_MAJOR_VERSION:
3198 values[0] = alcMajorVersion;
3199 return 1;
3200 case ALC_MINOR_VERSION:
3201 values[0] = alcMinorVersion;
3202 return 1;
3204 case ALC_CAPTURE_SAMPLES:
3205 almtx_lock(&device->BackendLock);
3206 values[0] = V0(device->Backend,availableSamples)();
3207 almtx_unlock(&device->BackendLock);
3208 return 1;
3210 case ALC_CONNECTED:
3211 values[0] = device->Connected;
3212 return 1;
3214 default:
3215 alcSetError(device, ALC_INVALID_ENUM);
3216 return 0;
3218 return 0;
3221 /* render device */
3222 switch(param)
3224 case ALC_ATTRIBUTES_SIZE:
3225 values[0] = NumAttrsForDevice(device);
3226 return 1;
3228 case ALC_ALL_ATTRIBUTES:
3229 if(size < NumAttrsForDevice(device))
3231 alcSetError(device, ALC_INVALID_VALUE);
3232 return 0;
3235 i = 0;
3236 almtx_lock(&device->BackendLock);
3237 values[i++] = ALC_MAJOR_VERSION;
3238 values[i++] = alcMajorVersion;
3239 values[i++] = ALC_MINOR_VERSION;
3240 values[i++] = alcMinorVersion;
3241 values[i++] = ALC_EFX_MAJOR_VERSION;
3242 values[i++] = alcEFXMajorVersion;
3243 values[i++] = ALC_EFX_MINOR_VERSION;
3244 values[i++] = alcEFXMinorVersion;
3246 values[i++] = ALC_FREQUENCY;
3247 values[i++] = device->Frequency;
3248 if(device->Type != Loopback)
3250 values[i++] = ALC_REFRESH;
3251 values[i++] = device->Frequency / device->UpdateSize;
3253 values[i++] = ALC_SYNC;
3254 values[i++] = ALC_FALSE;
3256 else
3258 if(device->FmtChans == DevFmtAmbi3D)
3260 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3261 values[i++] = device->AmbiLayout;
3263 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3264 values[i++] = device->AmbiScale;
3266 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3267 values[i++] = device->AmbiOrder;
3270 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3271 values[i++] = device->FmtChans;
3273 values[i++] = ALC_FORMAT_TYPE_SOFT;
3274 values[i++] = device->FmtType;
3277 values[i++] = ALC_MONO_SOURCES;
3278 values[i++] = device->NumMonoSources;
3280 values[i++] = ALC_STEREO_SOURCES;
3281 values[i++] = device->NumStereoSources;
3283 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3284 values[i++] = device->NumAuxSends;
3286 values[i++] = ALC_HRTF_SOFT;
3287 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3289 values[i++] = ALC_HRTF_STATUS_SOFT;
3290 values[i++] = device->HrtfStatus;
3292 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3293 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3295 values[i++] = ALC_MAX_AMBISONIC_ORDER_SOFT;
3296 values[i++] = MAX_AMBI_ORDER;
3297 almtx_unlock(&device->BackendLock);
3299 values[i++] = 0;
3300 return i;
3302 case ALC_MAJOR_VERSION:
3303 values[0] = alcMajorVersion;
3304 return 1;
3306 case ALC_MINOR_VERSION:
3307 values[0] = alcMinorVersion;
3308 return 1;
3310 case ALC_EFX_MAJOR_VERSION:
3311 values[0] = alcEFXMajorVersion;
3312 return 1;
3314 case ALC_EFX_MINOR_VERSION:
3315 values[0] = alcEFXMinorVersion;
3316 return 1;
3318 case ALC_FREQUENCY:
3319 values[0] = device->Frequency;
3320 return 1;
3322 case ALC_REFRESH:
3323 if(device->Type == Loopback)
3325 alcSetError(device, ALC_INVALID_DEVICE);
3326 return 0;
3328 almtx_lock(&device->BackendLock);
3329 values[0] = device->Frequency / device->UpdateSize;
3330 almtx_unlock(&device->BackendLock);
3331 return 1;
3333 case ALC_SYNC:
3334 if(device->Type == Loopback)
3336 alcSetError(device, ALC_INVALID_DEVICE);
3337 return 0;
3339 values[0] = ALC_FALSE;
3340 return 1;
3342 case ALC_FORMAT_CHANNELS_SOFT:
3343 if(device->Type != Loopback)
3345 alcSetError(device, ALC_INVALID_DEVICE);
3346 return 0;
3348 values[0] = device->FmtChans;
3349 return 1;
3351 case ALC_FORMAT_TYPE_SOFT:
3352 if(device->Type != Loopback)
3354 alcSetError(device, ALC_INVALID_DEVICE);
3355 return 0;
3357 values[0] = device->FmtType;
3358 return 1;
3360 case ALC_AMBISONIC_LAYOUT_SOFT:
3361 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3363 alcSetError(device, ALC_INVALID_DEVICE);
3364 return 0;
3366 values[0] = device->AmbiLayout;
3367 return 1;
3369 case ALC_AMBISONIC_SCALING_SOFT:
3370 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3372 alcSetError(device, ALC_INVALID_DEVICE);
3373 return 0;
3375 values[0] = device->AmbiScale;
3376 return 1;
3378 case ALC_AMBISONIC_ORDER_SOFT:
3379 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3381 alcSetError(device, ALC_INVALID_DEVICE);
3382 return 0;
3384 values[0] = device->AmbiOrder;
3385 return 1;
3387 case ALC_MONO_SOURCES:
3388 values[0] = device->NumMonoSources;
3389 return 1;
3391 case ALC_STEREO_SOURCES:
3392 values[0] = device->NumStereoSources;
3393 return 1;
3395 case ALC_MAX_AUXILIARY_SENDS:
3396 values[0] = device->NumAuxSends;
3397 return 1;
3399 case ALC_CONNECTED:
3400 values[0] = device->Connected;
3401 return 1;
3403 case ALC_HRTF_SOFT:
3404 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3405 return 1;
3407 case ALC_HRTF_STATUS_SOFT:
3408 values[0] = device->HrtfStatus;
3409 return 1;
3411 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3412 almtx_lock(&device->BackendLock);
3413 FreeHrtfList(&device->HrtfList);
3414 device->HrtfList = EnumerateHrtf(device->DeviceName);
3415 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3416 almtx_unlock(&device->BackendLock);
3417 return 1;
3419 case ALC_OUTPUT_LIMITER_SOFT:
3420 values[0] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3421 return 1;
3423 case ALC_MAX_AMBISONIC_ORDER_SOFT:
3424 values[0] = MAX_AMBI_ORDER;
3425 return 1;
3427 default:
3428 alcSetError(device, ALC_INVALID_ENUM);
3429 return 0;
3431 return 0;
3434 /* alcGetIntegerv
3436 * Returns information about the device and the version of OpenAL
3438 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3440 VerifyDevice(&device);
3441 if(size <= 0 || values == NULL)
3442 alcSetError(device, ALC_INVALID_VALUE);
3443 else
3444 GetIntegerv(device, param, size, values);
3445 if(device) ALCdevice_DecRef(device);
3448 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3450 ALCint *ivals;
3451 ALsizei i;
3453 VerifyDevice(&device);
3454 if(size <= 0 || values == NULL)
3455 alcSetError(device, ALC_INVALID_VALUE);
3456 else if(!device || device->Type == Capture)
3458 ivals = malloc(size * sizeof(ALCint));
3459 size = GetIntegerv(device, pname, size, ivals);
3460 for(i = 0;i < size;i++)
3461 values[i] = ivals[i];
3462 free(ivals);
3464 else /* render device */
3466 ClockLatency clock;
3467 ALuint64 basecount;
3468 ALuint samplecount;
3469 ALuint refcount;
3471 switch(pname)
3473 case ALC_ATTRIBUTES_SIZE:
3474 *values = NumAttrsForDevice(device)+4;
3475 break;
3477 case ALC_ALL_ATTRIBUTES:
3478 if(size < NumAttrsForDevice(device)+4)
3479 alcSetError(device, ALC_INVALID_VALUE);
3480 else
3482 i = 0;
3483 almtx_lock(&device->BackendLock);
3484 values[i++] = ALC_FREQUENCY;
3485 values[i++] = device->Frequency;
3487 if(device->Type != Loopback)
3489 values[i++] = ALC_REFRESH;
3490 values[i++] = device->Frequency / device->UpdateSize;
3492 values[i++] = ALC_SYNC;
3493 values[i++] = ALC_FALSE;
3495 else
3497 if(device->FmtChans == DevFmtAmbi3D)
3499 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3500 values[i++] = device->AmbiLayout;
3502 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3503 values[i++] = device->AmbiScale;
3505 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3506 values[i++] = device->AmbiOrder;
3509 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3510 values[i++] = device->FmtChans;
3512 values[i++] = ALC_FORMAT_TYPE_SOFT;
3513 values[i++] = device->FmtType;
3516 values[i++] = ALC_MONO_SOURCES;
3517 values[i++] = device->NumMonoSources;
3519 values[i++] = ALC_STEREO_SOURCES;
3520 values[i++] = device->NumStereoSources;
3522 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3523 values[i++] = device->NumAuxSends;
3525 values[i++] = ALC_HRTF_SOFT;
3526 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3528 values[i++] = ALC_HRTF_STATUS_SOFT;
3529 values[i++] = device->HrtfStatus;
3531 values[i++] = ALC_OUTPUT_LIMITER_SOFT;
3532 values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
3534 clock = V0(device->Backend,getClockLatency)();
3535 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3536 values[i++] = clock.ClockTime;
3538 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3539 values[i++] = clock.Latency;
3540 almtx_unlock(&device->BackendLock);
3542 values[i++] = 0;
3544 break;
3546 case ALC_DEVICE_CLOCK_SOFT:
3547 almtx_lock(&device->BackendLock);
3548 do {
3549 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3550 althrd_yield();
3551 basecount = device->ClockBase;
3552 samplecount = device->SamplesDone;
3553 } while(refcount != ReadRef(&device->MixCount));
3554 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3555 almtx_unlock(&device->BackendLock);
3556 break;
3558 case ALC_DEVICE_LATENCY_SOFT:
3559 almtx_lock(&device->BackendLock);
3560 clock = V0(device->Backend,getClockLatency)();
3561 almtx_unlock(&device->BackendLock);
3562 *values = clock.Latency;
3563 break;
3565 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3566 if(size < 2)
3567 alcSetError(device, ALC_INVALID_VALUE);
3568 else
3570 almtx_lock(&device->BackendLock);
3571 clock = V0(device->Backend,getClockLatency)();
3572 almtx_unlock(&device->BackendLock);
3573 values[0] = clock.ClockTime;
3574 values[1] = clock.Latency;
3576 break;
3578 default:
3579 ivals = malloc(size * sizeof(ALCint));
3580 size = GetIntegerv(device, pname, size, ivals);
3581 for(i = 0;i < size;i++)
3582 values[i] = ivals[i];
3583 free(ivals);
3584 break;
3587 if(device)
3588 ALCdevice_DecRef(device);
3592 /* alcIsExtensionPresent
3594 * Determines if there is support for a particular extension
3596 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3598 ALCboolean bResult = ALC_FALSE;
3600 VerifyDevice(&device);
3602 if(!extName)
3603 alcSetError(device, ALC_INVALID_VALUE);
3604 else
3606 size_t len = strlen(extName);
3607 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3608 while(ptr && *ptr)
3610 if(strncasecmp(ptr, extName, len) == 0 &&
3611 (ptr[len] == '\0' || isspace(ptr[len])))
3613 bResult = ALC_TRUE;
3614 break;
3616 if((ptr=strchr(ptr, ' ')) != NULL)
3618 do {
3619 ++ptr;
3620 } while(isspace(*ptr));
3624 if(device)
3625 ALCdevice_DecRef(device);
3626 return bResult;
3630 /* alcGetProcAddress
3632 * Retrieves the function address for a particular extension function
3634 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3636 ALCvoid *ptr = NULL;
3638 if(!funcName)
3640 VerifyDevice(&device);
3641 alcSetError(device, ALC_INVALID_VALUE);
3642 if(device) ALCdevice_DecRef(device);
3644 else
3646 size_t i = 0;
3647 for(i = 0;i < COUNTOF(alcFunctions);i++)
3649 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3651 ptr = alcFunctions[i].address;
3652 break;
3657 return ptr;
3661 /* alcGetEnumValue
3663 * Get the value for a particular ALC enumeration name
3665 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3667 ALCenum val = 0;
3669 if(!enumName)
3671 VerifyDevice(&device);
3672 alcSetError(device, ALC_INVALID_VALUE);
3673 if(device) ALCdevice_DecRef(device);
3675 else
3677 size_t i = 0;
3678 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3680 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3682 val = alcEnumerations[i].value;
3683 break;
3688 return val;
3692 /* alcCreateContext
3694 * Create and attach a context to the given device.
3696 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3698 ALCcontext *ALContext;
3699 ALfloat valf;
3700 ALCenum err;
3702 /* Explicitly hold the list lock while taking the BackendLock in case the
3703 * device is asynchronously destropyed, to ensure this new context is
3704 * properly cleaned up after being made.
3706 LockLists();
3707 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3709 UnlockLists();
3710 alcSetError(device, ALC_INVALID_DEVICE);
3711 if(device) ALCdevice_DecRef(device);
3712 return NULL;
3714 almtx_lock(&device->BackendLock);
3715 UnlockLists();
3717 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3719 if(device->Type == Playback && DefaultEffect.type != AL_EFFECT_NULL)
3720 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)+sizeof(ALeffectslot));
3721 else
3722 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3723 if(!ALContext)
3725 almtx_unlock(&device->BackendLock);
3727 alcSetError(device, ALC_OUT_OF_MEMORY);
3728 ALCdevice_DecRef(device);
3729 return NULL;
3732 InitRef(&ALContext->ref, 1);
3733 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3734 ALContext->DefaultSlot = NULL;
3736 ALContext->Voices = NULL;
3737 ALContext->VoiceCount = 0;
3738 ALContext->MaxVoices = 0;
3739 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3740 ALContext->Device = device;
3742 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3744 almtx_unlock(&device->BackendLock);
3746 al_free(ALContext);
3747 ALContext = NULL;
3749 alcSetError(device, err);
3750 if(err == ALC_INVALID_DEVICE)
3752 V0(device->Backend,lock)();
3753 aluHandleDisconnect(device);
3754 V0(device->Backend,unlock)();
3756 ALCdevice_DecRef(device);
3757 return NULL;
3759 AllocateVoices(ALContext, 256, device->NumAuxSends);
3761 if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
3763 ALContext->DefaultSlot = (ALeffectslot*)(ALContext->_listener_mem + sizeof(ALlistener));
3764 if(InitEffectSlot(ALContext->DefaultSlot) == AL_NO_ERROR)
3765 aluInitEffectPanning(ALContext->DefaultSlot);
3766 else
3768 ALContext->DefaultSlot = NULL;
3769 ERR("Failed to initialize the default effect slot\n");
3773 ALCdevice_IncRef(ALContext->Device);
3774 InitContext(ALContext);
3776 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3778 if(!isfinite(valf))
3779 ERR("volume-adjust must be finite: %f\n", valf);
3780 else
3782 ALfloat db = clampf(valf, -24.0f, 24.0f);
3783 if(db != valf)
3784 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3785 ALContext->GainBoost = powf(10.0f, db/20.0f);
3786 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3789 UpdateListenerProps(ALContext);
3792 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3793 do {
3794 ALContext->next = head;
3795 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3796 ALContext) == 0);
3798 almtx_unlock(&device->BackendLock);
3800 if(ALContext->DefaultSlot)
3802 if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR)
3803 UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext);
3804 else
3805 ERR("Failed to initialize the default effect\n");
3808 ALCdevice_DecRef(device);
3810 TRACE("Created context %p\n", ALContext);
3811 return ALContext;
3814 /* alcDestroyContext
3816 * Remove a context from its device
3818 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3820 ALCdevice *Device;
3822 LockLists();
3823 if(!VerifyContext(&context))
3825 UnlockLists();
3826 alcSetError(NULL, ALC_INVALID_CONTEXT);
3827 return;
3830 Device = context->Device;
3831 if(Device)
3833 almtx_lock(&Device->BackendLock);
3834 if(!ReleaseContext(context, Device))
3836 V0(Device->Backend,stop)();
3837 Device->Flags &= ~DEVICE_RUNNING;
3839 almtx_unlock(&Device->BackendLock);
3841 UnlockLists();
3843 ALCcontext_DecRef(context);
3847 /* alcGetCurrentContext
3849 * Returns the currently active context on the calling thread
3851 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3853 ALCcontext *Context = altss_get(LocalContext);
3854 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3855 return Context;
3858 /* alcGetThreadContext
3860 * Returns the currently active thread-local context
3862 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3864 return altss_get(LocalContext);
3868 /* alcMakeContextCurrent
3870 * Makes the given context the active process-wide context, and removes the
3871 * thread-local context for the calling thread.
3873 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3875 /* context must be valid or NULL */
3876 if(context && !VerifyContext(&context))
3878 alcSetError(NULL, ALC_INVALID_CONTEXT);
3879 return ALC_FALSE;
3881 /* context's reference count is already incremented */
3882 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3883 if(context) ALCcontext_DecRef(context);
3885 if((context=altss_get(LocalContext)) != NULL)
3887 altss_set(LocalContext, NULL);
3888 ALCcontext_DecRef(context);
3891 return ALC_TRUE;
3894 /* alcSetThreadContext
3896 * Makes the given context the active context for the current thread
3898 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3900 ALCcontext *old;
3902 /* context must be valid or NULL */
3903 if(context && !VerifyContext(&context))
3905 alcSetError(NULL, ALC_INVALID_CONTEXT);
3906 return ALC_FALSE;
3908 /* context's reference count is already incremented */
3909 old = altss_get(LocalContext);
3910 altss_set(LocalContext, context);
3911 if(old) ALCcontext_DecRef(old);
3913 return ALC_TRUE;
3917 /* alcGetContextsDevice
3919 * Returns the device that a particular context is attached to
3921 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3923 ALCdevice *Device;
3925 if(!VerifyContext(&Context))
3927 alcSetError(NULL, ALC_INVALID_CONTEXT);
3928 return NULL;
3930 Device = Context->Device;
3931 ALCcontext_DecRef(Context);
3933 return Device;
3937 /* alcOpenDevice
3939 * Opens the named device.
3941 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3943 ALCbackendFactory *factory;
3944 const ALCchar *fmt;
3945 ALCdevice *device;
3946 ALCenum err;
3947 ALCsizei i;
3949 DO_INITCONFIG();
3951 if(!PlaybackBackend.name)
3953 alcSetError(NULL, ALC_INVALID_VALUE);
3954 return NULL;
3957 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3958 #ifdef _WIN32
3959 /* Some old Windows apps hardcode these expecting OpenAL to use a
3960 * specific audio API, even when they're not enumerated. Creative's
3961 * router effectively ignores them too.
3963 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3964 || strcasecmp(deviceName, "MMSYSTEM") == 0
3965 #endif
3967 deviceName = NULL;
3969 device = al_calloc(16, sizeof(ALCdevice));
3970 if(!device)
3972 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3973 return NULL;
3976 //Validate device
3977 InitRef(&device->ref, 1);
3978 device->Connected = ALC_TRUE;
3979 device->Type = Playback;
3980 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3982 device->Flags = 0;
3983 device->Bs2b = NULL;
3984 device->Uhj_Encoder = NULL;
3985 device->Hrtf = NULL;
3986 device->HrtfHandle = NULL;
3987 VECTOR_INIT(device->HrtfList);
3988 AL_STRING_INIT(device->HrtfName);
3989 device->Render_Mode = NormalRender;
3990 AL_STRING_INIT(device->DeviceName);
3991 device->Dry.Buffer = NULL;
3992 device->Dry.NumChannels = 0;
3993 device->FOAOut.Buffer = NULL;
3994 device->FOAOut.NumChannels = 0;
3995 device->RealOut.Buffer = NULL;
3996 device->RealOut.NumChannels = 0;
3997 device->Limiter = NULL;
3998 device->AvgSpeakerDist = 0.0f;
4000 ATOMIC_INIT(&device->ContextList, NULL);
4002 device->ClockBase = 0;
4003 device->SamplesDone = 0;
4005 device->SourcesMax = 256;
4006 device->AuxiliaryEffectSlotMax = 64;
4007 device->NumAuxSends = DEFAULT_SENDS;
4009 InitUIntMap(&device->BufferMap, INT_MAX);
4010 InitUIntMap(&device->EffectMap, INT_MAX);
4011 InitUIntMap(&device->FilterMap, INT_MAX);
4013 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4015 device->ChannelDelay[i].Gain = 1.0f;
4016 device->ChannelDelay[i].Length = 0;
4017 device->ChannelDelay[i].Buffer = NULL;
4020 //Set output format
4021 device->FmtChans = DevFmtChannelsDefault;
4022 device->FmtType = DevFmtTypeDefault;
4023 device->Frequency = DEFAULT_OUTPUT_RATE;
4024 device->IsHeadphones = AL_FALSE;
4025 device->AmbiLayout = AmbiLayout_Default;
4026 device->AmbiScale = AmbiNorm_Default;
4027 device->NumUpdates = 3;
4028 device->UpdateSize = 1024;
4030 factory = PlaybackBackend.getFactory();
4031 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
4032 if(!device->Backend)
4034 al_free(device);
4035 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4036 return NULL;
4040 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
4042 static const struct {
4043 const char name[16];
4044 enum DevFmtChannels chans;
4045 ALsizei order;
4046 } chanlist[] = {
4047 { "mono", DevFmtMono, 0 },
4048 { "stereo", DevFmtStereo, 0 },
4049 { "quad", DevFmtQuad, 0 },
4050 { "surround51", DevFmtX51, 0 },
4051 { "surround61", DevFmtX61, 0 },
4052 { "surround71", DevFmtX71, 0 },
4053 { "surround51rear", DevFmtX51Rear, 0 },
4054 { "ambi1", DevFmtAmbi3D, 1 },
4055 { "ambi2", DevFmtAmbi3D, 2 },
4056 { "ambi3", DevFmtAmbi3D, 3 },
4058 size_t i;
4060 for(i = 0;i < COUNTOF(chanlist);i++)
4062 if(strcasecmp(chanlist[i].name, fmt) == 0)
4064 device->FmtChans = chanlist[i].chans;
4065 device->AmbiOrder = chanlist[i].order;
4066 device->Flags |= DEVICE_CHANNELS_REQUEST;
4067 break;
4070 if(i == COUNTOF(chanlist))
4071 ERR("Unsupported channels: %s\n", fmt);
4073 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
4075 static const struct {
4076 const char name[16];
4077 enum DevFmtType type;
4078 } typelist[] = {
4079 { "int8", DevFmtByte },
4080 { "uint8", DevFmtUByte },
4081 { "int16", DevFmtShort },
4082 { "uint16", DevFmtUShort },
4083 { "int32", DevFmtInt },
4084 { "uint32", DevFmtUInt },
4085 { "float32", DevFmtFloat },
4087 size_t i;
4089 for(i = 0;i < COUNTOF(typelist);i++)
4091 if(strcasecmp(typelist[i].name, fmt) == 0)
4093 device->FmtType = typelist[i].type;
4094 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
4095 break;
4098 if(i == COUNTOF(typelist))
4099 ERR("Unsupported sample-type: %s\n", fmt);
4102 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
4104 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4105 if(device->Frequency < MIN_OUTPUT_RATE)
4106 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
4107 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
4110 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
4111 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
4113 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
4114 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
4115 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
4116 device->UpdateSize = (device->UpdateSize+3)&~3;
4118 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
4119 if(device->SourcesMax == 0) device->SourcesMax = 256;
4121 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4122 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4124 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
4125 device->NumAuxSends = clampi(
4126 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4129 device->NumStereoSources = 1;
4130 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4132 // Find a playback device to open
4133 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4135 DELETE_OBJ(device->Backend);
4136 al_free(device);
4137 alcSetError(NULL, err);
4138 return NULL;
4140 almtx_init(&device->BackendLock, almtx_plain);
4142 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
4144 if(strcasecmp(fmt, "fuma") == 0)
4146 device->AmbiLayout = AmbiLayout_FuMa;
4147 device->AmbiScale = AmbiNorm_FuMa;
4149 else if(strcasecmp(fmt, "acn+sn3d") == 0)
4151 device->AmbiLayout = AmbiLayout_ACN;
4152 device->AmbiScale = AmbiNorm_SN3D;
4154 else if(strcasecmp(fmt, "acn+n3d") == 0)
4156 device->AmbiLayout = AmbiLayout_ACN;
4157 device->AmbiScale = AmbiNorm_N3D;
4159 else
4160 ERR("Unsupported ambi-format: %s\n", fmt);
4163 device->Limiter = CreateDeviceLimiter(device);
4166 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4167 do {
4168 device->next = head;
4169 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4172 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4173 return device;
4176 /* alcCloseDevice
4178 * Closes the given device.
4180 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
4182 ALCdevice *iter, *origdev;
4183 ALCcontext *ctx;
4185 LockLists();
4186 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4187 do {
4188 if(iter == device)
4189 break;
4190 } while((iter=iter->next) != NULL);
4191 if(!iter || iter->Type == Capture)
4193 alcSetError(iter, ALC_INVALID_DEVICE);
4194 UnlockLists();
4195 return ALC_FALSE;
4197 almtx_lock(&device->BackendLock);
4199 origdev = device;
4200 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4202 ALCdevice *volatile*list = &origdev->next;
4203 while(*list)
4205 if(*list == device)
4207 *list = (*list)->next;
4208 break;
4210 list = &(*list)->next;
4213 UnlockLists();
4215 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4216 while(ctx != NULL)
4218 ALCcontext *next = ctx->next;
4219 WARN("Releasing context %p\n", ctx);
4220 ReleaseContext(ctx, device);
4221 ctx = next;
4223 if((device->Flags&DEVICE_RUNNING))
4224 V0(device->Backend,stop)();
4225 device->Flags &= ~DEVICE_RUNNING;
4226 almtx_unlock(&device->BackendLock);
4228 ALCdevice_DecRef(device);
4230 return ALC_TRUE;
4234 /************************************************
4235 * ALC capture functions
4236 ************************************************/
4237 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4239 ALCbackendFactory *factory;
4240 ALCdevice *device = NULL;
4241 ALCenum err;
4242 ALCsizei i;
4244 DO_INITCONFIG();
4246 if(!CaptureBackend.name)
4248 alcSetError(NULL, ALC_INVALID_VALUE);
4249 return NULL;
4252 if(samples <= 0)
4254 alcSetError(NULL, ALC_INVALID_VALUE);
4255 return NULL;
4258 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4259 deviceName = NULL;
4261 device = al_calloc(16, sizeof(ALCdevice));
4262 if(!device)
4264 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4265 return NULL;
4268 //Validate device
4269 InitRef(&device->ref, 1);
4270 device->Connected = ALC_TRUE;
4271 device->Type = Capture;
4273 device->Hrtf = NULL;
4274 device->HrtfHandle = NULL;
4275 VECTOR_INIT(device->HrtfList);
4276 AL_STRING_INIT(device->HrtfName);
4278 AL_STRING_INIT(device->DeviceName);
4279 device->Dry.Buffer = NULL;
4280 device->Dry.NumChannels = 0;
4281 device->FOAOut.Buffer = NULL;
4282 device->FOAOut.NumChannels = 0;
4283 device->RealOut.Buffer = NULL;
4284 device->RealOut.NumChannels = 0;
4286 InitUIntMap(&device->BufferMap, INT_MAX);
4287 InitUIntMap(&device->EffectMap, INT_MAX);
4288 InitUIntMap(&device->FilterMap, INT_MAX);
4290 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4292 device->ChannelDelay[i].Gain = 1.0f;
4293 device->ChannelDelay[i].Length = 0;
4294 device->ChannelDelay[i].Buffer = NULL;
4297 factory = CaptureBackend.getFactory();
4298 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4299 if(!device->Backend)
4301 al_free(device);
4302 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4303 return NULL;
4306 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4307 device->Frequency = frequency;
4309 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4310 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4312 al_free(device);
4313 alcSetError(NULL, ALC_INVALID_ENUM);
4314 return NULL;
4316 device->IsHeadphones = AL_FALSE;
4317 device->AmbiOrder = 0;
4318 device->AmbiLayout = AmbiLayout_Default;
4319 device->AmbiScale = AmbiNorm_Default;
4321 device->UpdateSize = samples;
4322 device->NumUpdates = 1;
4324 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4325 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4326 device->Frequency, device->UpdateSize, device->NumUpdates
4328 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4330 al_free(device);
4331 alcSetError(NULL, err);
4332 return NULL;
4334 almtx_init(&device->BackendLock, almtx_plain);
4337 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4338 do {
4339 device->next = head;
4340 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4343 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4344 return device;
4347 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4349 ALCdevice *iter, *origdev;
4351 LockLists();
4352 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4353 do {
4354 if(iter == device)
4355 break;
4356 } while((iter=iter->next) != NULL);
4357 if(!iter || iter->Type != Capture)
4359 alcSetError(iter, ALC_INVALID_DEVICE);
4360 UnlockLists();
4361 return ALC_FALSE;
4364 origdev = device;
4365 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4367 ALCdevice *volatile*list = &origdev->next;
4368 while(*list)
4370 if(*list == device)
4372 *list = (*list)->next;
4373 break;
4375 list = &(*list)->next;
4378 UnlockLists();
4380 ALCdevice_DecRef(device);
4382 return ALC_TRUE;
4385 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4387 if(!VerifyDevice(&device) || device->Type != Capture)
4388 alcSetError(device, ALC_INVALID_DEVICE);
4389 else
4391 almtx_lock(&device->BackendLock);
4392 if(!device->Connected)
4393 alcSetError(device, ALC_INVALID_DEVICE);
4394 else if(!(device->Flags&DEVICE_RUNNING))
4396 if(V0(device->Backend,start)())
4397 device->Flags |= DEVICE_RUNNING;
4398 else
4400 aluHandleDisconnect(device);
4401 alcSetError(device, ALC_INVALID_DEVICE);
4404 almtx_unlock(&device->BackendLock);
4407 if(device) ALCdevice_DecRef(device);
4410 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4412 if(!VerifyDevice(&device) || device->Type != Capture)
4413 alcSetError(device, ALC_INVALID_DEVICE);
4414 else
4416 almtx_lock(&device->BackendLock);
4417 if((device->Flags&DEVICE_RUNNING))
4418 V0(device->Backend,stop)();
4419 device->Flags &= ~DEVICE_RUNNING;
4420 almtx_unlock(&device->BackendLock);
4423 if(device) ALCdevice_DecRef(device);
4426 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4428 if(!VerifyDevice(&device) || device->Type != Capture)
4429 alcSetError(device, ALC_INVALID_DEVICE);
4430 else
4432 ALCenum err = ALC_INVALID_VALUE;
4434 almtx_lock(&device->BackendLock);
4435 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4436 err = V(device->Backend,captureSamples)(buffer, samples);
4437 almtx_unlock(&device->BackendLock);
4439 if(err != ALC_NO_ERROR)
4440 alcSetError(device, err);
4442 if(device) ALCdevice_DecRef(device);
4446 /************************************************
4447 * ALC loopback functions
4448 ************************************************/
4450 /* alcLoopbackOpenDeviceSOFT
4452 * Open a loopback device, for manual rendering.
4454 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4456 ALCbackendFactory *factory;
4457 ALCdevice *device;
4458 ALCsizei i;
4460 DO_INITCONFIG();
4462 /* Make sure the device name, if specified, is us. */
4463 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4465 alcSetError(NULL, ALC_INVALID_VALUE);
4466 return NULL;
4469 device = al_calloc(16, sizeof(ALCdevice));
4470 if(!device)
4472 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4473 return NULL;
4476 //Validate device
4477 InitRef(&device->ref, 1);
4478 device->Connected = ALC_TRUE;
4479 device->Type = Loopback;
4480 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4482 device->Flags = 0;
4483 device->Hrtf = NULL;
4484 device->HrtfHandle = NULL;
4485 VECTOR_INIT(device->HrtfList);
4486 AL_STRING_INIT(device->HrtfName);
4487 device->Bs2b = NULL;
4488 device->Uhj_Encoder = NULL;
4489 device->Render_Mode = NormalRender;
4490 AL_STRING_INIT(device->DeviceName);
4491 device->Dry.Buffer = NULL;
4492 device->Dry.NumChannels = 0;
4493 device->FOAOut.Buffer = NULL;
4494 device->FOAOut.NumChannels = 0;
4495 device->RealOut.Buffer = NULL;
4496 device->RealOut.NumChannels = 0;
4497 device->Limiter = NULL;
4498 device->AvgSpeakerDist = 0.0f;
4500 ATOMIC_INIT(&device->ContextList, NULL);
4502 device->ClockBase = 0;
4503 device->SamplesDone = 0;
4505 device->SourcesMax = 256;
4506 device->AuxiliaryEffectSlotMax = 64;
4507 device->NumAuxSends = DEFAULT_SENDS;
4509 InitUIntMap(&device->BufferMap, INT_MAX);
4510 InitUIntMap(&device->EffectMap, INT_MAX);
4511 InitUIntMap(&device->FilterMap, INT_MAX);
4513 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4515 device->ChannelDelay[i].Gain = 1.0f;
4516 device->ChannelDelay[i].Length = 0;
4517 device->ChannelDelay[i].Buffer = NULL;
4520 factory = ALCloopbackFactory_getFactory();
4521 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4522 if(!device->Backend)
4524 al_free(device);
4525 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4526 return NULL;
4528 almtx_init(&device->BackendLock, almtx_plain);
4530 //Set output format
4531 device->NumUpdates = 0;
4532 device->UpdateSize = 0;
4534 device->Frequency = DEFAULT_OUTPUT_RATE;
4535 device->FmtChans = DevFmtChannelsDefault;
4536 device->FmtType = DevFmtTypeDefault;
4537 device->IsHeadphones = AL_FALSE;
4538 device->AmbiLayout = AmbiLayout_Default;
4539 device->AmbiScale = AmbiNorm_Default;
4541 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4542 if(device->SourcesMax == 0) device->SourcesMax = 256;
4544 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4545 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4547 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4548 device->NumAuxSends = clampi(
4549 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4552 device->NumStereoSources = 1;
4553 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4555 // Open the "backend"
4556 V(device->Backend,open)("Loopback");
4558 device->Limiter = CreateDeviceLimiter(device);
4561 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4562 do {
4563 device->next = head;
4564 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4567 TRACE("Created device %p\n", device);
4568 return device;
4571 /* alcIsRenderFormatSupportedSOFT
4573 * Determines if the loopback device supports the given format for rendering.
4575 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4577 ALCboolean ret = ALC_FALSE;
4579 if(!VerifyDevice(&device) || device->Type != Loopback)
4580 alcSetError(device, ALC_INVALID_DEVICE);
4581 else if(freq <= 0)
4582 alcSetError(device, ALC_INVALID_VALUE);
4583 else
4585 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4586 ret = ALC_TRUE;
4588 if(device) ALCdevice_DecRef(device);
4590 return ret;
4593 /* alcRenderSamplesSOFT
4595 * Renders some samples into a buffer, using the format last set by the
4596 * attributes given to alcCreateContext.
4598 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4600 if(!VerifyDevice(&device) || device->Type != Loopback)
4601 alcSetError(device, ALC_INVALID_DEVICE);
4602 else if(samples < 0 || (samples > 0 && buffer == NULL))
4603 alcSetError(device, ALC_INVALID_VALUE);
4604 else
4606 V0(device->Backend,lock)();
4607 aluMixData(device, buffer, samples);
4608 V0(device->Backend,unlock)();
4610 if(device) ALCdevice_DecRef(device);
4614 /************************************************
4615 * ALC DSP pause/resume functions
4616 ************************************************/
4618 /* alcDevicePauseSOFT
4620 * Pause the DSP to stop audio processing.
4622 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4624 if(!VerifyDevice(&device) || device->Type != Playback)
4625 alcSetError(device, ALC_INVALID_DEVICE);
4626 else
4628 almtx_lock(&device->BackendLock);
4629 if((device->Flags&DEVICE_RUNNING))
4630 V0(device->Backend,stop)();
4631 device->Flags &= ~DEVICE_RUNNING;
4632 device->Flags |= DEVICE_PAUSED;
4633 almtx_unlock(&device->BackendLock);
4635 if(device) ALCdevice_DecRef(device);
4638 /* alcDeviceResumeSOFT
4640 * Resume the DSP to restart audio processing.
4642 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4644 if(!VerifyDevice(&device) || device->Type != Playback)
4645 alcSetError(device, ALC_INVALID_DEVICE);
4646 else
4648 almtx_lock(&device->BackendLock);
4649 if((device->Flags&DEVICE_PAUSED))
4651 device->Flags &= ~DEVICE_PAUSED;
4652 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4654 if(V0(device->Backend,start)() != ALC_FALSE)
4655 device->Flags |= DEVICE_RUNNING;
4656 else
4658 alcSetError(device, ALC_INVALID_DEVICE);
4659 V0(device->Backend,lock)();
4660 aluHandleDisconnect(device);
4661 V0(device->Backend,unlock)();
4665 almtx_unlock(&device->BackendLock);
4667 if(device) ALCdevice_DecRef(device);
4671 /************************************************
4672 * ALC HRTF functions
4673 ************************************************/
4675 /* alcGetStringiSOFT
4677 * Gets a string parameter at the given index.
4679 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4681 const ALCchar *str = NULL;
4683 if(!VerifyDevice(&device) || device->Type == Capture)
4684 alcSetError(device, ALC_INVALID_DEVICE);
4685 else switch(paramName)
4687 case ALC_HRTF_SPECIFIER_SOFT:
4688 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4689 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4690 else
4691 alcSetError(device, ALC_INVALID_VALUE);
4692 break;
4694 default:
4695 alcSetError(device, ALC_INVALID_ENUM);
4696 break;
4698 if(device) ALCdevice_DecRef(device);
4700 return str;
4703 /* alcResetDeviceSOFT
4705 * Resets the given device output, using the specified attribute list.
4707 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4709 ALCenum err;
4711 LockLists();
4712 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4714 UnlockLists();
4715 alcSetError(device, ALC_INVALID_DEVICE);
4716 if(device) ALCdevice_DecRef(device);
4717 return ALC_FALSE;
4719 almtx_lock(&device->BackendLock);
4720 UnlockLists();
4722 err = UpdateDeviceParams(device, attribs);
4723 almtx_unlock(&device->BackendLock);
4725 if(err != ALC_NO_ERROR)
4727 alcSetError(device, err);
4728 if(err == ALC_INVALID_DEVICE)
4730 V0(device->Backend,lock)();
4731 aluHandleDisconnect(device);
4732 V0(device->Backend,unlock)();
4734 ALCdevice_DecRef(device);
4735 return ALC_FALSE;
4737 ALCdevice_DecRef(device);
4739 return ALC_TRUE;