Trace the capture device format
[openal-soft.git] / Alc / ALc.c
blob47bd19e47b5dcb2c3c3520b155f983744e74aabc
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 "bformatdec.h"
41 #include "alu.h"
43 #include "compat.h"
44 #include "threads.h"
45 #include "alstring.h"
46 #include "almalloc.h"
48 #include "backends/base.h"
51 /************************************************
52 * Backends
53 ************************************************/
54 struct BackendInfo {
55 const char *name;
56 ALCbackendFactory* (*getFactory)(void);
57 ALCboolean (*Init)(BackendFuncs*);
58 void (*Deinit)(void);
59 void (*Probe)(enum DevProbe);
60 BackendFuncs Funcs;
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList[] = {
65 #ifdef HAVE_JACK
66 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
67 #endif
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
70 #endif
71 #ifdef HAVE_ALSA
72 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
73 #endif
74 #ifdef HAVE_COREAUDIO
75 { "core", ALCcoreAudioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
76 #endif
77 #ifdef HAVE_OSS
78 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
79 #endif
80 #ifdef HAVE_SOLARIS
81 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
82 #endif
83 #ifdef HAVE_SNDIO
84 { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
85 #endif
86 #ifdef HAVE_QSA
87 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
88 #endif
89 #ifdef HAVE_MMDEVAPI
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
91 #endif
92 #ifdef HAVE_DSOUND
93 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
94 #endif
95 #ifdef HAVE_WINMM
96 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
97 #endif
98 #ifdef HAVE_PORTAUDIO
99 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
100 #endif
101 #ifdef HAVE_OPENSL
102 { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
103 #endif
105 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #ifdef HAVE_WAVE
107 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
108 #endif
110 static ALsizei BackendListSize = COUNTOF(BackendList);
111 #undef EmptyFuncs
113 static struct BackendInfo PlaybackBackend;
114 static struct BackendInfo CaptureBackend;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar *funcName;
123 ALCvoid *address;
124 } alcFunctions[] = {
125 DECL(alcCreateContext),
126 DECL(alcMakeContextCurrent),
127 DECL(alcProcessContext),
128 DECL(alcSuspendContext),
129 DECL(alcDestroyContext),
130 DECL(alcGetCurrentContext),
131 DECL(alcGetContextsDevice),
132 DECL(alcOpenDevice),
133 DECL(alcCloseDevice),
134 DECL(alcGetError),
135 DECL(alcIsExtensionPresent),
136 DECL(alcGetProcAddress),
137 DECL(alcGetEnumValue),
138 DECL(alcGetString),
139 DECL(alcGetIntegerv),
140 DECL(alcCaptureOpenDevice),
141 DECL(alcCaptureCloseDevice),
142 DECL(alcCaptureStart),
143 DECL(alcCaptureStop),
144 DECL(alcCaptureSamples),
146 DECL(alcSetThreadContext),
147 DECL(alcGetThreadContext),
149 DECL(alcLoopbackOpenDeviceSOFT),
150 DECL(alcIsRenderFormatSupportedSOFT),
151 DECL(alcRenderSamplesSOFT),
153 DECL(alcIsAmbisonicFormatSupportedSOFT),
155 DECL(alcDevicePauseSOFT),
156 DECL(alcDeviceResumeSOFT),
158 DECL(alcGetStringiSOFT),
159 DECL(alcResetDeviceSOFT),
161 DECL(alcGetInteger64vSOFT),
163 DECL(alEnable),
164 DECL(alDisable),
165 DECL(alIsEnabled),
166 DECL(alGetString),
167 DECL(alGetBooleanv),
168 DECL(alGetIntegerv),
169 DECL(alGetFloatv),
170 DECL(alGetDoublev),
171 DECL(alGetBoolean),
172 DECL(alGetInteger),
173 DECL(alGetFloat),
174 DECL(alGetDouble),
175 DECL(alGetError),
176 DECL(alIsExtensionPresent),
177 DECL(alGetProcAddress),
178 DECL(alGetEnumValue),
179 DECL(alListenerf),
180 DECL(alListener3f),
181 DECL(alListenerfv),
182 DECL(alListeneri),
183 DECL(alListener3i),
184 DECL(alListeneriv),
185 DECL(alGetListenerf),
186 DECL(alGetListener3f),
187 DECL(alGetListenerfv),
188 DECL(alGetListeneri),
189 DECL(alGetListener3i),
190 DECL(alGetListeneriv),
191 DECL(alGenSources),
192 DECL(alDeleteSources),
193 DECL(alIsSource),
194 DECL(alSourcef),
195 DECL(alSource3f),
196 DECL(alSourcefv),
197 DECL(alSourcei),
198 DECL(alSource3i),
199 DECL(alSourceiv),
200 DECL(alGetSourcef),
201 DECL(alGetSource3f),
202 DECL(alGetSourcefv),
203 DECL(alGetSourcei),
204 DECL(alGetSource3i),
205 DECL(alGetSourceiv),
206 DECL(alSourcePlayv),
207 DECL(alSourceStopv),
208 DECL(alSourceRewindv),
209 DECL(alSourcePausev),
210 DECL(alSourcePlay),
211 DECL(alSourceStop),
212 DECL(alSourceRewind),
213 DECL(alSourcePause),
214 DECL(alSourceQueueBuffers),
215 DECL(alSourceUnqueueBuffers),
216 DECL(alGenBuffers),
217 DECL(alDeleteBuffers),
218 DECL(alIsBuffer),
219 DECL(alBufferData),
220 DECL(alBufferf),
221 DECL(alBuffer3f),
222 DECL(alBufferfv),
223 DECL(alBufferi),
224 DECL(alBuffer3i),
225 DECL(alBufferiv),
226 DECL(alGetBufferf),
227 DECL(alGetBuffer3f),
228 DECL(alGetBufferfv),
229 DECL(alGetBufferi),
230 DECL(alGetBuffer3i),
231 DECL(alGetBufferiv),
232 DECL(alDopplerFactor),
233 DECL(alDopplerVelocity),
234 DECL(alSpeedOfSound),
235 DECL(alDistanceModel),
237 DECL(alGenFilters),
238 DECL(alDeleteFilters),
239 DECL(alIsFilter),
240 DECL(alFilteri),
241 DECL(alFilteriv),
242 DECL(alFilterf),
243 DECL(alFilterfv),
244 DECL(alGetFilteri),
245 DECL(alGetFilteriv),
246 DECL(alGetFilterf),
247 DECL(alGetFilterfv),
248 DECL(alGenEffects),
249 DECL(alDeleteEffects),
250 DECL(alIsEffect),
251 DECL(alEffecti),
252 DECL(alEffectiv),
253 DECL(alEffectf),
254 DECL(alEffectfv),
255 DECL(alGetEffecti),
256 DECL(alGetEffectiv),
257 DECL(alGetEffectf),
258 DECL(alGetEffectfv),
259 DECL(alGenAuxiliaryEffectSlots),
260 DECL(alDeleteAuxiliaryEffectSlots),
261 DECL(alIsAuxiliaryEffectSlot),
262 DECL(alAuxiliaryEffectSloti),
263 DECL(alAuxiliaryEffectSlotiv),
264 DECL(alAuxiliaryEffectSlotf),
265 DECL(alAuxiliaryEffectSlotfv),
266 DECL(alGetAuxiliaryEffectSloti),
267 DECL(alGetAuxiliaryEffectSlotiv),
268 DECL(alGetAuxiliaryEffectSlotf),
269 DECL(alGetAuxiliaryEffectSlotfv),
271 DECL(alDeferUpdatesSOFT),
272 DECL(alProcessUpdatesSOFT),
274 DECL(alSourcedSOFT),
275 DECL(alSource3dSOFT),
276 DECL(alSourcedvSOFT),
277 DECL(alGetSourcedSOFT),
278 DECL(alGetSource3dSOFT),
279 DECL(alGetSourcedvSOFT),
280 DECL(alSourcei64SOFT),
281 DECL(alSource3i64SOFT),
282 DECL(alSourcei64vSOFT),
283 DECL(alGetSourcei64SOFT),
284 DECL(alGetSource3i64SOFT),
285 DECL(alGetSourcei64vSOFT),
287 DECL(alBufferSamplesSOFT),
288 DECL(alGetBufferSamplesSOFT),
289 DECL(alIsBufferFormatSupportedSOFT),
291 #undef DECL
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar *enumName;
296 ALCenum value;
297 } alcEnumerations[] = {
298 DECL(ALC_INVALID),
299 DECL(ALC_FALSE),
300 DECL(ALC_TRUE),
302 DECL(ALC_MAJOR_VERSION),
303 DECL(ALC_MINOR_VERSION),
304 DECL(ALC_ATTRIBUTES_SIZE),
305 DECL(ALC_ALL_ATTRIBUTES),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
307 DECL(ALC_DEVICE_SPECIFIER),
308 DECL(ALC_ALL_DEVICES_SPECIFIER),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
310 DECL(ALC_EXTENSIONS),
311 DECL(ALC_FREQUENCY),
312 DECL(ALC_REFRESH),
313 DECL(ALC_SYNC),
314 DECL(ALC_MONO_SOURCES),
315 DECL(ALC_STEREO_SOURCES),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
318 DECL(ALC_CAPTURE_SAMPLES),
319 DECL(ALC_CONNECTED),
321 DECL(ALC_EFX_MAJOR_VERSION),
322 DECL(ALC_EFX_MINOR_VERSION),
323 DECL(ALC_MAX_AUXILIARY_SENDS),
325 DECL(ALC_FORMAT_CHANNELS_SOFT),
326 DECL(ALC_FORMAT_TYPE_SOFT),
328 DECL(ALC_MONO_SOFT),
329 DECL(ALC_STEREO_SOFT),
330 DECL(ALC_QUAD_SOFT),
331 DECL(ALC_5POINT1_SOFT),
332 DECL(ALC_6POINT1_SOFT),
333 DECL(ALC_7POINT1_SOFT),
334 DECL(ALC_BFORMAT3D_SOFT),
336 DECL(ALC_BYTE_SOFT),
337 DECL(ALC_UNSIGNED_BYTE_SOFT),
338 DECL(ALC_SHORT_SOFT),
339 DECL(ALC_UNSIGNED_SHORT_SOFT),
340 DECL(ALC_INT_SOFT),
341 DECL(ALC_UNSIGNED_INT_SOFT),
342 DECL(ALC_FLOAT_SOFT),
344 DECL(ALC_HRTF_SOFT),
345 DECL(ALC_DONT_CARE_SOFT),
346 DECL(ALC_HRTF_STATUS_SOFT),
347 DECL(ALC_HRTF_DISABLED_SOFT),
348 DECL(ALC_HRTF_ENABLED_SOFT),
349 DECL(ALC_HRTF_DENIED_SOFT),
350 DECL(ALC_HRTF_REQUIRED_SOFT),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
354 DECL(ALC_HRTF_SPECIFIER_SOFT),
355 DECL(ALC_HRTF_ID_SOFT),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
358 DECL(ALC_AMBISONIC_SCALING_SOFT),
359 DECL(ALC_AMBISONIC_ORDER_SOFT),
360 DECL(ALC_ACN_SOFT),
361 DECL(ALC_FUMA_SOFT),
362 DECL(ALC_N3D_SOFT),
363 DECL(ALC_SN3D_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 #undef DECL
698 static const ALCchar alcNoError[] = "No Error";
699 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
706 /************************************************
707 * Global variables
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList;
714 static al_string alcCaptureDeviceList;
716 /* Default is always the first in the list */
717 static ALCchar *alcDefaultAllDevicesSpecifier;
718 static ALCchar *alcCaptureDefaultDeviceSpecifier;
720 /* Default context extensions */
721 static const ALchar alExtList[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
732 /* Thread-local current context */
733 static altss_t LocalContext;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
737 /* Mixing thread piority level */
738 ALint RTPrioLevel;
740 FILE *LogFile;
741 #ifdef _DEBUG
742 enum LogLevel LogLevel = LogWarning;
743 #else
744 enum LogLevel LogLevel = LogError;
745 #endif
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError = ALC_FALSE;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
757 * updates.
759 static ALCboolean SuspendDefers = ALC_TRUE;
762 /************************************************
763 * ALC information
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion = 1;
774 static const ALCint alcMinorVersion = 1;
776 static const ALCint alcEFXMajorVersion = 1;
777 static const ALCint alcEFXMinorVersion = 0;
780 /************************************************
781 * Device lists
782 ************************************************/
783 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
785 static almtx_t ListLock;
786 static inline void LockLists(void)
788 int ret = almtx_lock(&ListLock);
789 assert(ret == althrd_success);
791 static inline void UnlockLists(void)
793 int ret = almtx_unlock(&ListLock);
794 assert(ret == althrd_success);
797 /************************************************
798 * Library initialization
799 ************************************************/
800 #if defined(_WIN32)
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
808 switch(reason)
810 case DLL_PROCESS_ATTACH:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
813 (WCHAR*)hModule, &hModule);
814 alc_init();
815 break;
817 case DLL_THREAD_DETACH:
818 break;
820 case DLL_PROCESS_DETACH:
821 if(!lpReserved)
822 alc_deinit();
823 else
824 alc_deinit_safe();
825 break;
827 return TRUE;
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
835 static void alc_constructor(void)
837 atexit(alc_destructor);
838 alc_init();
841 static void alc_destructor(void)
843 alc_deinit();
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor));
847 static void alc_deinit(void) __attribute__((destructor));
848 #else
849 #error "No static initialization available on this platform!"
850 #endif
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor));
855 static void alc_deinit(void) __attribute__((destructor));
857 #else
858 #error "No global initialization available on this platform!"
859 #endif
861 static void ReleaseThreadCtx(void *ptr);
862 static void alc_init(void)
864 const char *str;
865 int ret;
867 LogFile = stderr;
869 AL_STRING_INIT(alcAllDevicesList);
870 AL_STRING_INIT(alcCaptureDeviceList);
872 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
874 ConeScale *= 0.5f;
876 str = getenv("__ALSOFT_REVERSE_Z");
877 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
878 ZScale *= -1.0f;
880 ret = altss_create(&LocalContext, ReleaseThreadCtx);
881 assert(ret == althrd_success);
883 ret = almtx_init(&ListLock, almtx_recursive);
884 assert(ret == althrd_success);
886 ThunkInit();
889 static void alc_initconfig(void)
891 const char *devs, *str;
892 ALuint capfilter;
893 float valf;
894 int i, n;
896 str = getenv("ALSOFT_LOGLEVEL");
897 if(str)
899 long lvl = strtol(str, NULL, 0);
900 if(lvl >= NoLog && lvl <= LogRef)
901 LogLevel = lvl;
904 str = getenv("ALSOFT_LOGFILE");
905 if(str && str[0])
907 FILE *logfile = al_fopen(str, "wt");
908 if(logfile) LogFile = logfile;
909 else ERR("Failed to open log file '%s'\n", str);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
913 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
915 char buf[1024] = "";
916 int len = 0;
918 if(BackendListSize > 0)
919 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
920 for(i = 1;i < BackendListSize;i++)
921 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
922 TRACE("Supported backends: %s\n", buf);
924 ReadALConfig();
926 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
927 if(str && *str)
929 if(strcasecmp(str, "ignore") == 0)
931 SuspendDefers = ALC_FALSE;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
934 else
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
938 capfilter = 0;
939 #if defined(HAVE_SSE4_1)
940 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
941 #elif defined(HAVE_SSE3)
942 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
943 #elif defined(HAVE_SSE2)
944 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
945 #elif defined(HAVE_SSE)
946 capfilter |= CPU_CAP_SSE;
947 #endif
948 #ifdef HAVE_NEON
949 capfilter |= CPU_CAP_NEON;
950 #endif
951 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
953 if(strcasecmp(str, "all") == 0)
954 capfilter = 0;
955 else
957 size_t len;
958 const char *next = str;
960 do {
961 str = next;
962 while(isspace(str[0]))
963 str++;
964 next = strchr(str, ',');
966 if(!str[0] || str[0] == ',')
967 continue;
969 len = (next ? ((size_t)(next-str)) : strlen(str));
970 while(len > 0 && isspace(str[len-1]))
971 len--;
972 if(len == 3 && strncasecmp(str, "sse", len) == 0)
973 capfilter &= ~CPU_CAP_SSE;
974 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
975 capfilter &= ~CPU_CAP_SSE2;
976 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
977 capfilter &= ~CPU_CAP_SSE3;
978 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
979 capfilter &= ~CPU_CAP_SSE4_1;
980 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
981 capfilter &= ~CPU_CAP_NEON;
982 else
983 WARN("Invalid CPU extension \"%s\"\n", str);
984 } while(next++);
987 FillCPUCaps(capfilter);
989 #ifdef _WIN32
990 RTPrioLevel = 1;
991 #else
992 RTPrioLevel = 0;
993 #endif
994 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
996 aluInitMixer();
998 str = getenv("ALSOFT_TRAP_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1001 TrapALError = AL_TRUE;
1002 TrapALCError = AL_TRUE;
1004 else
1006 str = getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1008 TrapALError = AL_TRUE;
1009 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1011 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1013 TrapALCError = ALC_TRUE;
1014 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1017 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1018 ReverbBoost *= powf(10.0f, valf / 20.0f);
1020 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1022 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1023 ConfigValueStr(NULL, NULL, "drivers", &devs))
1025 int n;
1026 size_t len;
1027 const char *next = devs;
1028 int endlist, delitem;
1030 i = 0;
1031 do {
1032 devs = next;
1033 while(isspace(devs[0]))
1034 devs++;
1035 next = strchr(devs, ',');
1037 delitem = (devs[0] == '-');
1038 if(devs[0] == '-') devs++;
1040 if(!devs[0] || devs[0] == ',')
1042 endlist = 0;
1043 continue;
1045 endlist = 1;
1047 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1048 while(len > 0 && isspace(devs[len-1]))
1049 len--;
1050 for(n = i;n < BackendListSize;n++)
1052 if(len == strlen(BackendList[n].name) &&
1053 strncmp(BackendList[n].name, devs, len) == 0)
1055 if(delitem)
1057 for(;n+1 < BackendListSize;n++)
1058 BackendList[n] = BackendList[n+1];
1059 BackendListSize--;
1061 else
1063 struct BackendInfo Bkp = BackendList[n];
1064 for(;n > i;n--)
1065 BackendList[n] = BackendList[n-1];
1066 BackendList[n] = Bkp;
1068 i++;
1070 break;
1073 } while(next++);
1075 if(endlist)
1076 BackendListSize = i;
1079 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1081 if(BackendList[i].getFactory)
1083 ALCbackendFactory *factory = BackendList[i].getFactory();
1084 if(!V0(factory,init)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1087 continue;
1090 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1091 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1093 PlaybackBackend = BackendList[i];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1096 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1098 CaptureBackend = BackendList[i];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1102 continue;
1105 if(!BackendList[i].Init(&BackendList[i].Funcs))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1108 continue;
1111 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1112 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1114 PlaybackBackend = BackendList[i];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1117 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1119 CaptureBackend = BackendList[i];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1124 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1125 V0(factory,init)();
1128 if(!PlaybackBackend.name)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend.name)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1135 size_t len;
1136 const char *next = str;
1138 do {
1139 str = next;
1140 next = strchr(str, ',');
1142 if(!str[0] || next == str)
1143 continue;
1145 len = (next ? ((size_t)(next-str)) : strlen(str));
1146 for(n = 0;EffectList[n].name;n++)
1148 if(len == strlen(EffectList[n].name) &&
1149 strncmp(EffectList[n].name, str, len) == 0)
1150 DisabledEffects[EffectList[n].type] = AL_TRUE;
1152 } while(next++);
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect);
1158 str = getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1160 LoadReverbPreset(str, &DefaultEffect);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1164 #ifdef __ANDROID__
1165 #include <jni.h>
1167 static JavaVM *gJavaVM;
1168 static pthread_key_t gJVMThreadKey;
1170 static void CleanupJNIEnv(void* UNUSED(ptr))
1172 JCALL0(gJavaVM,DetachCurrentThread)();
1175 void *Android_GetJNIEnv(void)
1177 if(!gJavaVM)
1179 WARN("gJavaVM is NULL!\n");
1180 return NULL;
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1194 * is a no-op.
1196 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1197 if(!env)
1199 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1200 if(status < 0)
1202 ERR("Failed to attach current thread\n");
1203 return NULL;
1205 pthread_setspecific(gJVMThreadKey, env);
1207 return env;
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1213 void *env;
1214 int err;
1216 gJavaVM = jvm;
1217 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1220 return JNI_ERR;
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err);
1228 pthread_setspecific(gJVMThreadKey, env);
1229 return JNI_VERSION_1_4;
1232 #endif
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1240 ALCdevice *dev;
1242 AL_STRING_DEINIT(alcAllDevicesList);
1243 AL_STRING_DEINIT(alcCaptureDeviceList);
1245 free(alcDefaultAllDevicesSpecifier);
1246 alcDefaultAllDevicesSpecifier = NULL;
1247 free(alcCaptureDefaultDeviceSpecifier);
1248 alcCaptureDefaultDeviceSpecifier = NULL;
1250 if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL)
1252 ALCuint num = 0;
1253 do {
1254 num++;
1255 } while((dev=dev->next) != NULL);
1256 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1259 DeinitEffectFactoryMap();
1262 static void alc_deinit_safe(void)
1264 alc_cleanup();
1266 FreeHrtfs();
1267 FreeALConfig();
1269 ThunkExit();
1270 almtx_destroy(&ListLock);
1271 altss_delete(LocalContext);
1273 if(LogFile != stderr)
1274 fclose(LogFile);
1275 LogFile = NULL;
1278 static void alc_deinit(void)
1280 int i;
1282 alc_cleanup();
1284 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1285 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1287 for(i = 0;i < BackendListSize;i++)
1289 if(!BackendList[i].getFactory)
1290 BackendList[i].Deinit();
1291 else
1293 ALCbackendFactory *factory = BackendList[i].getFactory();
1294 V0(factory,deinit)();
1298 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1299 V0(factory,deinit)();
1302 alc_deinit_safe();
1306 /************************************************
1307 * Device enumeration
1308 ************************************************/
1309 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1311 DO_INITCONFIG();
1313 LockLists();
1314 alstr_clear(list);
1316 if(backendinfo->Probe)
1317 backendinfo->Probe(type);
1318 else if(backendinfo->getFactory)
1320 ALCbackendFactory *factory = backendinfo->getFactory();
1321 V(factory,probe)(type);
1323 UnlockLists();
1325 static void ProbeAllDevicesList(void)
1326 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1327 static void ProbeCaptureDeviceList(void)
1328 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1330 static void AppendDevice(const ALCchar *name, al_string *devnames)
1332 size_t len = strlen(name);
1333 if(len > 0)
1334 alstr_append_range(devnames, name, name+len+1);
1336 void AppendAllDevicesList(const ALCchar *name)
1337 { AppendDevice(name, &alcAllDevicesList); }
1338 void AppendCaptureDeviceList(const ALCchar *name)
1339 { AppendDevice(name, &alcCaptureDeviceList); }
1342 /************************************************
1343 * Device format information
1344 ************************************************/
1345 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1347 switch(type)
1349 case DevFmtByte: return "Signed Byte";
1350 case DevFmtUByte: return "Unsigned Byte";
1351 case DevFmtShort: return "Signed Short";
1352 case DevFmtUShort: return "Unsigned Short";
1353 case DevFmtInt: return "Signed Int";
1354 case DevFmtUInt: return "Unsigned Int";
1355 case DevFmtFloat: return "Float";
1357 return "(unknown type)";
1359 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1361 switch(chans)
1363 case DevFmtMono: return "Mono";
1364 case DevFmtStereo: return "Stereo";
1365 case DevFmtQuad: return "Quadraphonic";
1366 case DevFmtX51: return "5.1 Surround";
1367 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1368 case DevFmtX61: return "6.1 Surround";
1369 case DevFmtX71: return "7.1 Surround";
1370 case DevFmtAmbi1: return "Ambisonic (1st Order)";
1371 case DevFmtAmbi2: return "Ambisonic (2nd Order)";
1372 case DevFmtAmbi3: return "Ambisonic (3rd Order)";
1374 return "(unknown channels)";
1377 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1378 ALsizei BytesFromDevFmt(enum DevFmtType type)
1380 switch(type)
1382 case DevFmtByte: return sizeof(ALbyte);
1383 case DevFmtUByte: return sizeof(ALubyte);
1384 case DevFmtShort: return sizeof(ALshort);
1385 case DevFmtUShort: return sizeof(ALushort);
1386 case DevFmtInt: return sizeof(ALint);
1387 case DevFmtUInt: return sizeof(ALuint);
1388 case DevFmtFloat: return sizeof(ALfloat);
1390 return 0;
1392 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans)
1394 switch(chans)
1396 case DevFmtMono: return 1;
1397 case DevFmtStereo: return 2;
1398 case DevFmtQuad: return 4;
1399 case DevFmtX51: return 6;
1400 case DevFmtX51Rear: return 6;
1401 case DevFmtX61: return 7;
1402 case DevFmtX71: return 8;
1403 case DevFmtAmbi1: return 4;
1404 case DevFmtAmbi2: return 9;
1405 case DevFmtAmbi3: return 16;
1407 return 0;
1410 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1411 enum DevFmtType *type)
1413 static const struct {
1414 ALenum format;
1415 enum DevFmtChannels channels;
1416 enum DevFmtType type;
1417 } list[] = {
1418 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1419 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1420 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1422 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1423 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1424 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1426 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1427 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1428 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1430 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1431 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1432 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1434 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1435 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1436 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1438 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1439 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1440 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1442 ALuint i;
1444 for(i = 0;i < COUNTOF(list);i++)
1446 if(list[i].format == format)
1448 *chans = list[i].channels;
1449 *type = list[i].type;
1450 return AL_TRUE;
1454 return AL_FALSE;
1457 static ALCboolean IsValidALCType(ALCenum type)
1459 switch(type)
1461 case ALC_BYTE_SOFT:
1462 case ALC_UNSIGNED_BYTE_SOFT:
1463 case ALC_SHORT_SOFT:
1464 case ALC_UNSIGNED_SHORT_SOFT:
1465 case ALC_INT_SOFT:
1466 case ALC_UNSIGNED_INT_SOFT:
1467 case ALC_FLOAT_SOFT:
1468 return ALC_TRUE;
1470 return ALC_FALSE;
1473 static ALCboolean IsValidALCChannels(ALCenum channels)
1475 switch(channels)
1477 case ALC_MONO_SOFT:
1478 case ALC_STEREO_SOFT:
1479 case ALC_QUAD_SOFT:
1480 case ALC_5POINT1_SOFT:
1481 case ALC_6POINT1_SOFT:
1482 case ALC_7POINT1_SOFT:
1483 case ALC_BFORMAT3D_SOFT:
1484 return ALC_TRUE;
1486 return ALC_FALSE;
1489 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1491 switch(layout)
1493 case ALC_ACN_SOFT:
1494 case ALC_FUMA_SOFT:
1495 return ALC_TRUE;
1497 return ALC_FALSE;
1500 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1502 switch(scaling)
1504 case ALC_N3D_SOFT:
1505 case ALC_SN3D_SOFT:
1506 case ALC_FUMA_SOFT:
1507 return ALC_TRUE;
1509 return ALC_FALSE;
1512 /************************************************
1513 * Miscellaneous ALC helpers
1514 ************************************************/
1516 void ALCdevice_Lock(ALCdevice *device)
1518 V0(device->Backend,lock)();
1521 void ALCdevice_Unlock(ALCdevice *device)
1523 V0(device->Backend,unlock)();
1527 /* SetDefaultWFXChannelOrder
1529 * Sets the default channel order used by WaveFormatEx.
1531 void SetDefaultWFXChannelOrder(ALCdevice *device)
1533 ALsizei i;
1535 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1536 device->RealOut.ChannelName[i] = InvalidChannel;
1538 switch(device->FmtChans)
1540 case DevFmtMono:
1541 device->RealOut.ChannelName[0] = FrontCenter;
1542 break;
1543 case DevFmtStereo:
1544 device->RealOut.ChannelName[0] = FrontLeft;
1545 device->RealOut.ChannelName[1] = FrontRight;
1546 break;
1547 case DevFmtQuad:
1548 device->RealOut.ChannelName[0] = FrontLeft;
1549 device->RealOut.ChannelName[1] = FrontRight;
1550 device->RealOut.ChannelName[2] = BackLeft;
1551 device->RealOut.ChannelName[3] = BackRight;
1552 break;
1553 case DevFmtX51:
1554 device->RealOut.ChannelName[0] = FrontLeft;
1555 device->RealOut.ChannelName[1] = FrontRight;
1556 device->RealOut.ChannelName[2] = FrontCenter;
1557 device->RealOut.ChannelName[3] = LFE;
1558 device->RealOut.ChannelName[4] = SideLeft;
1559 device->RealOut.ChannelName[5] = SideRight;
1560 break;
1561 case DevFmtX51Rear:
1562 device->RealOut.ChannelName[0] = FrontLeft;
1563 device->RealOut.ChannelName[1] = FrontRight;
1564 device->RealOut.ChannelName[2] = FrontCenter;
1565 device->RealOut.ChannelName[3] = LFE;
1566 device->RealOut.ChannelName[4] = BackLeft;
1567 device->RealOut.ChannelName[5] = BackRight;
1568 break;
1569 case DevFmtX61:
1570 device->RealOut.ChannelName[0] = FrontLeft;
1571 device->RealOut.ChannelName[1] = FrontRight;
1572 device->RealOut.ChannelName[2] = FrontCenter;
1573 device->RealOut.ChannelName[3] = LFE;
1574 device->RealOut.ChannelName[4] = BackCenter;
1575 device->RealOut.ChannelName[5] = SideLeft;
1576 device->RealOut.ChannelName[6] = SideRight;
1577 break;
1578 case DevFmtX71:
1579 device->RealOut.ChannelName[0] = FrontLeft;
1580 device->RealOut.ChannelName[1] = FrontRight;
1581 device->RealOut.ChannelName[2] = FrontCenter;
1582 device->RealOut.ChannelName[3] = LFE;
1583 device->RealOut.ChannelName[4] = BackLeft;
1584 device->RealOut.ChannelName[5] = BackRight;
1585 device->RealOut.ChannelName[6] = SideLeft;
1586 device->RealOut.ChannelName[7] = SideRight;
1587 break;
1588 case DevFmtAmbi1:
1589 device->RealOut.ChannelName[0] = Aux0;
1590 device->RealOut.ChannelName[1] = Aux1;
1591 device->RealOut.ChannelName[2] = Aux2;
1592 device->RealOut.ChannelName[3] = Aux3;
1593 break;
1594 case DevFmtAmbi2:
1595 device->RealOut.ChannelName[0] = Aux0;
1596 device->RealOut.ChannelName[1] = Aux1;
1597 device->RealOut.ChannelName[2] = Aux2;
1598 device->RealOut.ChannelName[3] = Aux3;
1599 device->RealOut.ChannelName[4] = Aux4;
1600 device->RealOut.ChannelName[5] = Aux5;
1601 device->RealOut.ChannelName[6] = Aux6;
1602 device->RealOut.ChannelName[7] = Aux7;
1603 device->RealOut.ChannelName[8] = Aux8;
1604 break;
1605 case DevFmtAmbi3:
1606 device->RealOut.ChannelName[0] = Aux0;
1607 device->RealOut.ChannelName[1] = Aux1;
1608 device->RealOut.ChannelName[2] = Aux2;
1609 device->RealOut.ChannelName[3] = Aux3;
1610 device->RealOut.ChannelName[4] = Aux4;
1611 device->RealOut.ChannelName[5] = Aux5;
1612 device->RealOut.ChannelName[6] = Aux6;
1613 device->RealOut.ChannelName[7] = Aux7;
1614 device->RealOut.ChannelName[8] = Aux8;
1615 device->RealOut.ChannelName[9] = Aux9;
1616 device->RealOut.ChannelName[10] = Aux10;
1617 device->RealOut.ChannelName[11] = Aux11;
1618 device->RealOut.ChannelName[12] = Aux12;
1619 device->RealOut.ChannelName[13] = Aux13;
1620 device->RealOut.ChannelName[14] = Aux14;
1621 device->RealOut.ChannelName[15] = Aux15;
1622 break;
1626 /* SetDefaultChannelOrder
1628 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1630 void SetDefaultChannelOrder(ALCdevice *device)
1632 ALsizei i;
1634 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1635 device->RealOut.ChannelName[i] = InvalidChannel;
1637 switch(device->FmtChans)
1639 case DevFmtX51Rear:
1640 device->RealOut.ChannelName[0] = FrontLeft;
1641 device->RealOut.ChannelName[1] = FrontRight;
1642 device->RealOut.ChannelName[2] = BackLeft;
1643 device->RealOut.ChannelName[3] = BackRight;
1644 device->RealOut.ChannelName[4] = FrontCenter;
1645 device->RealOut.ChannelName[5] = LFE;
1646 return;
1647 case DevFmtX71:
1648 device->RealOut.ChannelName[0] = FrontLeft;
1649 device->RealOut.ChannelName[1] = FrontRight;
1650 device->RealOut.ChannelName[2] = BackLeft;
1651 device->RealOut.ChannelName[3] = BackRight;
1652 device->RealOut.ChannelName[4] = FrontCenter;
1653 device->RealOut.ChannelName[5] = LFE;
1654 device->RealOut.ChannelName[6] = SideLeft;
1655 device->RealOut.ChannelName[7] = SideRight;
1656 return;
1658 /* Same as WFX order */
1659 case DevFmtMono:
1660 case DevFmtStereo:
1661 case DevFmtQuad:
1662 case DevFmtX51:
1663 case DevFmtX61:
1664 case DevFmtAmbi1:
1665 case DevFmtAmbi2:
1666 case DevFmtAmbi3:
1667 SetDefaultWFXChannelOrder(device);
1668 break;
1672 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1675 /* ALCcontext_DeferUpdates
1677 * Defers/suspends updates for the given context's listener and sources. This
1678 * does *NOT* stop mixing, but rather prevents certain property changes from
1679 * taking effect.
1681 void ALCcontext_DeferUpdates(ALCcontext *context)
1683 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1686 /* ALCcontext_ProcessUpdates
1688 * Resumes update processing after being deferred.
1690 void ALCcontext_ProcessUpdates(ALCcontext *context)
1692 ReadLock(&context->PropLock);
1693 if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE))
1695 /* Tell the mixer to stop applying updates, then wait for any active
1696 * updating to finish, before providing updates.
1698 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1699 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1700 althrd_yield();
1702 UpdateListenerProps(context);
1703 UpdateAllEffectSlotProps(context);
1704 UpdateAllSourceProps(context);
1706 /* Now with all updates declared, let the mixer continue applying them
1707 * so they all happen at once.
1709 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1711 ReadUnlock(&context->PropLock);
1715 /* alcSetError
1717 * Stores the latest ALC device error
1719 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1721 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1722 if(TrapALCError)
1724 #ifdef _WIN32
1725 /* DebugBreak() will cause an exception if there is no debugger */
1726 if(IsDebuggerPresent())
1727 DebugBreak();
1728 #elif defined(SIGTRAP)
1729 raise(SIGTRAP);
1730 #endif
1733 if(device)
1734 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1735 else
1736 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1740 /* UpdateClockBase
1742 * Updates the device's base clock time with however many samples have been
1743 * done. This is used so frequency changes on the device don't cause the time
1744 * to jump forward or back. Must not be called while the device is running/
1745 * mixing.
1747 static inline void UpdateClockBase(ALCdevice *device)
1749 IncrementRef(&device->MixCount);
1750 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1751 device->SamplesDone = 0;
1752 IncrementRef(&device->MixCount);
1755 /* UpdateDeviceParams
1757 * Updates device parameters according to the attribute list (caller is
1758 * responsible for holding the list lock).
1760 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1762 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1763 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1764 const ALsizei old_sends = device->NumAuxSends;
1765 ALsizei new_sends = device->NumAuxSends;
1766 enum DevFmtChannels oldChans;
1767 enum DevFmtType oldType;
1768 ALboolean update_failed;
1769 ALCsizei hrtf_id = -1;
1770 ALCcontext *context;
1771 ALCuint oldFreq;
1772 FPUCtl oldMode;
1773 size_t size;
1774 ALCsizei i;
1776 // Check for attributes
1777 if(device->Type == Loopback)
1779 ALCsizei numMono, numStereo, numSends;
1780 ALCenum alayout = AL_NONE;
1781 ALCenum ascale = AL_NONE;
1782 ALCenum schans = AL_NONE;
1783 ALCenum stype = AL_NONE;
1784 ALCsizei attrIdx = 0;
1785 ALCsizei aorder = 0;
1786 ALCuint freq = 0;
1788 if(!attrList)
1790 WARN("Missing attributes for loopback device\n");
1791 return ALC_INVALID_VALUE;
1794 numMono = device->NumMonoSources;
1795 numStereo = device->NumStereoSources;
1796 numSends = old_sends;
1798 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1799 while(attrList[attrIdx])
1801 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1803 schans = attrList[attrIdx + 1];
1804 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1805 if(!IsValidALCChannels(schans))
1806 return ALC_INVALID_VALUE;
1809 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1811 stype = attrList[attrIdx + 1];
1812 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1813 if(!IsValidALCType(stype))
1814 return ALC_INVALID_VALUE;
1817 if(attrList[attrIdx] == ALC_FREQUENCY)
1819 freq = attrList[attrIdx + 1];
1820 TRACE_ATTR(ALC_FREQUENCY, freq);
1821 if(freq < MIN_OUTPUT_RATE)
1822 return ALC_INVALID_VALUE;
1825 if(attrList[attrIdx] == ALC_AMBISONIC_LAYOUT_SOFT)
1827 alayout = attrList[attrIdx + 1];
1828 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1829 if(!IsValidAmbiLayout(alayout))
1830 return ALC_INVALID_VALUE;
1833 if(attrList[attrIdx] == ALC_AMBISONIC_SCALING_SOFT)
1835 ascale = attrList[attrIdx + 1];
1836 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1837 if(!IsValidAmbiScaling(ascale))
1838 return ALC_INVALID_VALUE;
1841 if(attrList[attrIdx] == ALC_AMBISONIC_ORDER_SOFT)
1843 aorder = attrList[attrIdx + 1];
1844 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1845 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1846 return ALC_INVALID_VALUE;
1849 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1851 numStereo = attrList[attrIdx + 1];
1852 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1854 numStereo = clampi(numStereo, 0, device->SourcesMax);
1855 numMono = device->SourcesMax - numStereo;
1858 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1860 numSends = attrList[attrIdx + 1];
1861 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1862 numSends = clampi(numSends, 0, MAX_SENDS);
1865 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1867 ALCint val = attrList[attrIdx + 1];
1868 TRACE_ATTR(ALC_HRTF_SOFT, val);
1869 if(val == ALC_FALSE)
1870 hrtf_appreq = Hrtf_Disable;
1871 else if(val == ALC_TRUE)
1872 hrtf_appreq = Hrtf_Enable;
1873 else
1874 hrtf_appreq = Hrtf_Default;
1877 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1879 hrtf_id = attrList[attrIdx + 1];
1880 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1883 attrIdx += 2;
1885 #undef TRACE_ATTR
1887 if(!schans || !stype || !freq)
1889 WARN("Missing format for loopback device\n");
1890 return ALC_INVALID_VALUE;
1892 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1894 WARN("Missing ambisonic info for loopback device\n");
1895 return ALC_INVALID_VALUE;
1898 if((device->Flags&DEVICE_RUNNING))
1899 V0(device->Backend,stop)();
1900 device->Flags &= ~DEVICE_RUNNING;
1902 UpdateClockBase(device);
1904 if(schans == ALC_BFORMAT3D_SOFT)
1906 device->FmtChans = DevFmtAmbi1 + (aorder-1);
1907 device->AmbiLayout = alayout;
1908 device->AmbiScale = ascale;
1910 else
1911 device->FmtChans = schans;
1912 device->Frequency = freq;
1913 device->FmtType = stype;
1914 device->NumMonoSources = numMono;
1915 device->NumStereoSources = numStereo;
1917 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1918 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1919 else
1920 new_sends = numSends;
1922 else if(attrList && attrList[0])
1924 ALCsizei numMono, numStereo, numSends;
1925 ALCsizei attrIdx = 0;
1926 ALCuint freq;
1928 /* If a context is already running on the device, stop playback so the
1929 * device attributes can be updated. */
1930 if((device->Flags&DEVICE_RUNNING))
1931 V0(device->Backend,stop)();
1932 device->Flags &= ~DEVICE_RUNNING;
1934 UpdateClockBase(device);
1936 freq = device->Frequency;
1937 numMono = device->NumMonoSources;
1938 numStereo = device->NumStereoSources;
1939 numSends = old_sends;
1941 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1942 while(attrList[attrIdx])
1944 if(attrList[attrIdx] == ALC_FREQUENCY)
1946 freq = attrList[attrIdx + 1];
1947 TRACE_ATTR(ALC_FREQUENCY, freq);
1948 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1951 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1953 numStereo = attrList[attrIdx + 1];
1954 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1956 numStereo = clampi(numStereo, 0, device->SourcesMax);
1957 numMono = device->SourcesMax - numStereo;
1960 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1962 numSends = attrList[attrIdx + 1];
1963 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1964 numSends = clampi(numSends, 0, MAX_SENDS);
1967 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1969 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1970 if(attrList[attrIdx + 1] == ALC_FALSE)
1971 hrtf_appreq = Hrtf_Disable;
1972 else if(attrList[attrIdx + 1] == ALC_TRUE)
1973 hrtf_appreq = Hrtf_Enable;
1974 else
1975 hrtf_appreq = Hrtf_Default;
1978 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1980 hrtf_id = attrList[attrIdx + 1];
1981 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1984 attrIdx += 2;
1986 #undef TRACE_ATTR
1988 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1989 freq = maxu(freq, MIN_OUTPUT_RATE);
1991 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1992 device->Frequency;
1993 /* SSE and Neon do best with the update size being a multiple of 4 */
1994 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1995 device->UpdateSize = (device->UpdateSize+3)&~3;
1997 device->Frequency = freq;
1998 device->NumMonoSources = numMono;
1999 device->NumStereoSources = numStereo;
2001 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2002 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2003 else
2004 new_sends = numSends;
2007 if((device->Flags&DEVICE_RUNNING))
2008 return ALC_NO_ERROR;
2010 al_free(device->Uhj_Encoder);
2011 device->Uhj_Encoder = NULL;
2013 al_free(device->Bs2b);
2014 device->Bs2b = NULL;
2016 al_free(device->ChannelDelay[0].Buffer);
2017 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2019 device->ChannelDelay[i].Length = 0;
2020 device->ChannelDelay[i].Buffer = NULL;
2023 al_free(device->Dry.Buffer);
2024 device->Dry.Buffer = NULL;
2025 device->Dry.NumChannels = 0;
2026 device->FOAOut.Buffer = NULL;
2027 device->FOAOut.NumChannels = 0;
2028 device->RealOut.Buffer = NULL;
2029 device->RealOut.NumChannels = 0;
2031 UpdateClockBase(device);
2033 /*************************************************************************
2034 * Update device format request if HRTF is requested
2036 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2037 if(device->Type != Loopback)
2039 const char *hrtf;
2040 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2042 if(strcasecmp(hrtf, "true") == 0)
2043 hrtf_userreq = Hrtf_Enable;
2044 else if(strcasecmp(hrtf, "false") == 0)
2045 hrtf_userreq = Hrtf_Disable;
2046 else if(strcasecmp(hrtf, "auto") != 0)
2047 ERR("Unexpected hrtf value: %s\n", hrtf);
2050 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2052 struct Hrtf *hrtf = NULL;
2053 if(VECTOR_SIZE(device->HrtfList) == 0)
2055 VECTOR_DEINIT(device->HrtfList);
2056 device->HrtfList = EnumerateHrtf(device->DeviceName);
2058 if(VECTOR_SIZE(device->HrtfList) > 0)
2060 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2061 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2062 else
2063 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2066 if(hrtf)
2068 device->FmtChans = DevFmtStereo;
2069 device->Frequency = hrtf->sampleRate;
2070 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2071 if(device->HrtfHandle)
2072 Hrtf_DecRef(device->HrtfHandle);
2073 device->HrtfHandle = hrtf;
2075 else
2077 hrtf_userreq = Hrtf_Default;
2078 hrtf_appreq = Hrtf_Disable;
2079 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2084 oldFreq = device->Frequency;
2085 oldChans = device->FmtChans;
2086 oldType = device->FmtType;
2088 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2089 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2090 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2091 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2092 device->UpdateSize, device->NumUpdates
2095 if(V0(device->Backend,reset)() == ALC_FALSE)
2096 return ALC_INVALID_DEVICE;
2098 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2100 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2101 DevFmtChannelsString(device->FmtChans));
2102 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2104 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2106 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2107 DevFmtTypeString(device->FmtType));
2108 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2110 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2112 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2113 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2116 if((device->UpdateSize&3) != 0)
2118 if((CPUCapFlags&CPU_CAP_SSE))
2119 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2120 if((CPUCapFlags&CPU_CAP_NEON))
2121 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2124 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2125 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2126 device->Frequency, device->UpdateSize, device->NumUpdates
2129 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2130 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2131 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2133 /* Allocate extra channels for any post-filter output. */
2134 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2135 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2137 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2138 device->Dry.Buffer = al_calloc(16, size);
2139 if(!device->Dry.Buffer)
2141 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2142 return ALC_INVALID_DEVICE;
2145 if(device->RealOut.NumChannels != 0)
2146 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2147 device->FOAOut.NumChannels;
2148 else
2150 device->RealOut.Buffer = device->Dry.Buffer;
2151 device->RealOut.NumChannels = device->Dry.NumChannels;
2154 if(device->FOAOut.NumChannels != 0)
2155 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2156 else
2158 device->FOAOut.Buffer = device->Dry.Buffer;
2159 device->FOAOut.NumChannels = device->Dry.NumChannels;
2162 /* Need to delay returning failure until replacement Send arrays have been
2163 * allocated with the appropriate size.
2165 device->NumAuxSends = new_sends;
2166 update_failed = AL_FALSE;
2167 SetMixerFPUMode(&oldMode);
2168 if(device->DefaultSlot)
2170 ALeffectslot *slot = device->DefaultSlot;
2171 ALeffectState *state = slot->Effect.State;
2173 state->OutBuffer = device->Dry.Buffer;
2174 state->OutChannels = device->Dry.NumChannels;
2175 if(V(state,deviceUpdate)(device) == AL_FALSE)
2176 update_failed = AL_TRUE;
2177 else
2178 UpdateEffectSlotProps(slot);
2181 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2182 while(context)
2184 ALsizei pos;
2186 WriteLock(&context->PropLock);
2187 LockUIntMapRead(&context->EffectSlotMap);
2188 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2190 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2191 ALeffectState *state = slot->Effect.State;
2193 state->OutBuffer = device->Dry.Buffer;
2194 state->OutChannels = device->Dry.NumChannels;
2195 if(V(state,deviceUpdate)(device) == AL_FALSE)
2196 update_failed = AL_TRUE;
2197 else
2198 UpdateEffectSlotProps(slot);
2200 UnlockUIntMapRead(&context->EffectSlotMap);
2202 LockUIntMapRead(&context->SourceMap);
2203 for(pos = 0;pos < context->SourceMap.size;pos++)
2205 ALsource *source = context->SourceMap.values[pos];
2206 struct ALsourceProps *props;
2208 if(old_sends != device->NumAuxSends)
2210 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2211 ALsizei s;
2213 memcpy(sends, source->Send,
2214 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2216 for(s = device->NumAuxSends;s < old_sends;s++)
2218 if(source->Send[s].Slot)
2219 DecrementRef(&source->Send[s].Slot->ref);
2220 source->Send[s].Slot = NULL;
2222 al_free(source->Send);
2223 source->Send = sends;
2224 for(s = old_sends;s < device->NumAuxSends;s++)
2226 source->Send[s].Slot = NULL;
2227 source->Send[s].Gain = 1.0f;
2228 source->Send[s].GainHF = 1.0f;
2229 source->Send[s].HFReference = LOWPASSFREQREF;
2230 source->Send[s].GainLF = 1.0f;
2231 source->Send[s].LFReference = HIGHPASSFREQREF;
2235 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2237 /* Clear any pre-existing source property structs, in case the
2238 * number of auxiliary sends changed. Playing (or paused) sources
2239 * will have updates respecified in UpdateAllSourceProps.
2241 props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
2242 al_free(props);
2244 props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
2245 almemory_order_relaxed);
2246 while(props)
2248 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2249 al_free(props);
2250 props = next;
2253 AllocateVoices(context, context->MaxVoices, old_sends);
2254 for(pos = 0;pos < context->VoiceCount;pos++)
2256 ALvoice *voice = context->Voices[pos];
2257 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2258 continue;
2260 if(device->AvgSpeakerDist > 0.0f)
2262 /* Reinitialize the NFC filters for new parameters. */
2263 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2264 (device->AvgSpeakerDist * device->Frequency);
2265 for(i = 0;i < voice->NumChannels;i++)
2267 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2268 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2269 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2273 UnlockUIntMapRead(&context->SourceMap);
2275 UpdateListenerProps(context);
2276 UpdateAllSourceProps(context);
2277 WriteUnlock(&context->PropLock);
2279 context = context->next;
2281 RestoreFPUMode(&oldMode);
2282 if(update_failed)
2283 return ALC_INVALID_DEVICE;
2285 if(!(device->Flags&DEVICE_PAUSED))
2287 if(V0(device->Backend,start)() == ALC_FALSE)
2288 return ALC_INVALID_DEVICE;
2289 device->Flags |= DEVICE_RUNNING;
2292 return ALC_NO_ERROR;
2295 /* FreeDevice
2297 * Frees the device structure, and destroys any objects the app failed to
2298 * delete. Called once there's no more references on the device.
2300 static ALCvoid FreeDevice(ALCdevice *device)
2302 ALsizei i;
2304 TRACE("%p\n", device);
2306 V0(device->Backend,close)();
2307 DELETE_OBJ(device->Backend);
2308 device->Backend = NULL;
2310 almtx_destroy(&device->BackendLock);
2312 if(device->DefaultSlot)
2314 DeinitEffectSlot(device->DefaultSlot);
2315 device->DefaultSlot = NULL;
2318 if(device->BufferMap.size > 0)
2320 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2321 (device->BufferMap.size==1)?"":"s");
2322 ReleaseALBuffers(device);
2324 ResetUIntMap(&device->BufferMap);
2326 if(device->EffectMap.size > 0)
2328 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2329 (device->EffectMap.size==1)?"":"s");
2330 ReleaseALEffects(device);
2332 ResetUIntMap(&device->EffectMap);
2334 if(device->FilterMap.size > 0)
2336 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2337 (device->FilterMap.size==1)?"":"s");
2338 ReleaseALFilters(device);
2340 ResetUIntMap(&device->FilterMap);
2342 AL_STRING_DEINIT(device->HrtfName);
2343 FreeHrtfList(&device->HrtfList);
2344 if(device->HrtfHandle)
2345 Hrtf_DecRef(device->HrtfHandle);
2346 device->HrtfHandle = NULL;
2347 al_free(device->Hrtf);
2348 device->Hrtf = NULL;
2350 al_free(device->Bs2b);
2351 device->Bs2b = NULL;
2353 al_free(device->Uhj_Encoder);
2354 device->Uhj_Encoder = NULL;
2356 bformatdec_free(device->AmbiDecoder);
2357 device->AmbiDecoder = NULL;
2359 ambiup_free(device->AmbiUp);
2360 device->AmbiUp = NULL;
2362 al_free(device->ChannelDelay[0].Buffer);
2363 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2365 device->ChannelDelay[i].Gain = 1.0f;
2366 device->ChannelDelay[i].Length = 0;
2367 device->ChannelDelay[i].Buffer = NULL;
2370 AL_STRING_DEINIT(device->DeviceName);
2372 al_free(device->Dry.Buffer);
2373 device->Dry.Buffer = NULL;
2374 device->Dry.NumChannels = 0;
2375 device->FOAOut.Buffer = NULL;
2376 device->FOAOut.NumChannels = 0;
2377 device->RealOut.Buffer = NULL;
2378 device->RealOut.NumChannels = 0;
2380 al_free(device);
2384 void ALCdevice_IncRef(ALCdevice *device)
2386 uint ref;
2387 ref = IncrementRef(&device->ref);
2388 TRACEREF("%p increasing refcount to %u\n", device, ref);
2391 void ALCdevice_DecRef(ALCdevice *device)
2393 uint ref;
2394 ref = DecrementRef(&device->ref);
2395 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2396 if(ref == 0) FreeDevice(device);
2399 /* VerifyDevice
2401 * Checks if the device handle is valid, and increments its ref count if so.
2403 static ALCboolean VerifyDevice(ALCdevice **device)
2405 ALCdevice *tmpDevice;
2407 LockLists();
2408 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2409 while(tmpDevice)
2411 if(tmpDevice == *device)
2413 ALCdevice_IncRef(tmpDevice);
2414 UnlockLists();
2415 return ALC_TRUE;
2417 tmpDevice = tmpDevice->next;
2419 UnlockLists();
2421 *device = NULL;
2422 return ALC_FALSE;
2426 /* InitContext
2428 * Initializes context fields
2430 static ALvoid InitContext(ALCcontext *Context)
2432 ALlistener *listener = Context->Listener;
2433 struct ALeffectslotArray *auxslots;
2435 //Initialise listener
2436 listener->Gain = 1.0f;
2437 listener->MetersPerUnit = 1.0f;
2438 listener->Position[0] = 0.0f;
2439 listener->Position[1] = 0.0f;
2440 listener->Position[2] = 0.0f;
2441 listener->Velocity[0] = 0.0f;
2442 listener->Velocity[1] = 0.0f;
2443 listener->Velocity[2] = 0.0f;
2444 listener->Forward[0] = 0.0f;
2445 listener->Forward[1] = 0.0f;
2446 listener->Forward[2] = -1.0f;
2447 listener->Up[0] = 0.0f;
2448 listener->Up[1] = 1.0f;
2449 listener->Up[2] = 0.0f;
2451 aluMatrixfSet(&listener->Params.Matrix,
2452 1.0f, 0.0f, 0.0f, 0.0f,
2453 0.0f, 1.0f, 0.0f, 0.0f,
2454 0.0f, 0.0f, 1.0f, 0.0f,
2455 0.0f, 0.0f, 0.0f, 1.0f
2457 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2458 listener->Params.Gain = 1.0f;
2459 listener->Params.MetersPerUnit = 1.0f;
2460 listener->Params.DopplerFactor = 1.0f;
2461 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2463 ATOMIC_INIT(&listener->Update, NULL);
2464 ATOMIC_INIT(&listener->FreeList, NULL);
2466 //Validate Context
2467 InitRef(&Context->UpdateCount, 0);
2468 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2469 Context->GainBoost = 1.0f;
2470 RWLockInit(&Context->PropLock);
2471 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2472 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2473 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2475 auxslots = al_calloc(DEF_ALIGN, offsetof(struct ALeffectslotArray, slot[0]));
2476 auxslots->count = 0;
2477 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2479 //Set globals
2480 Context->DistanceModel = DefaultDistanceModel;
2481 Context->SourceDistanceModel = AL_FALSE;
2482 Context->DopplerFactor = 1.0f;
2483 Context->DopplerVelocity = 1.0f;
2484 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2485 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2487 Context->ExtensionList = alExtList;
2491 /* FreeContext
2493 * Cleans up the context, and destroys any remaining objects the app failed to
2494 * delete. Called once there's no more references on the context.
2496 static void FreeContext(ALCcontext *context)
2498 ALlistener *listener = context->Listener;
2499 struct ALeffectslotArray *auxslots;
2500 struct ALlistenerProps *lprops;
2501 size_t count;
2503 TRACE("%p\n", context);
2505 auxslots = ATOMIC_EXCHANGE(struct ALeffectslotArray*, &context->ActiveAuxSlots,
2506 NULL, almemory_order_relaxed);
2507 al_free(auxslots);
2509 if(context->SourceMap.size > 0)
2511 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2512 (context->SourceMap.size==1)?"":"s");
2513 ReleaseALSources(context);
2515 ResetUIntMap(&context->SourceMap);
2517 if(context->EffectSlotMap.size > 0)
2519 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2520 (context->EffectSlotMap.size==1)?"":"s");
2521 ReleaseALAuxiliaryEffectSlots(context);
2523 ResetUIntMap(&context->EffectSlotMap);
2525 al_free(context->Voices);
2526 context->Voices = NULL;
2527 context->VoiceCount = 0;
2528 context->MaxVoices = 0;
2530 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2532 TRACE("Freed unapplied listener update %p\n", lprops);
2533 al_free(lprops);
2535 count = 0;
2536 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2537 while(lprops)
2539 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2540 al_free(lprops);
2541 lprops = next;
2542 ++count;
2544 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2546 ALCdevice_DecRef(context->Device);
2547 context->Device = NULL;
2549 //Invalidate context
2550 memset(context, 0, sizeof(ALCcontext));
2551 al_free(context);
2554 /* ReleaseContext
2556 * Removes the context reference from the given device and removes it from
2557 * being current on the running thread or globally. Returns true if other
2558 * contexts still exist on the device.
2560 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2562 ALCcontext *origctx, *newhead;
2563 bool ret = true;
2565 if(altss_get(LocalContext) == context)
2567 WARN("%p released while current on thread\n", context);
2568 altss_set(LocalContext, NULL);
2569 ALCcontext_DecRef(context);
2572 origctx = context;
2573 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2574 ALCcontext_DecRef(context);
2576 ALCdevice_Lock(device);
2577 origctx = context;
2578 newhead = context->next;
2579 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList, &origctx, newhead))
2581 ALCcontext *volatile*list = &origctx->next;
2582 while(*list)
2584 if(*list == context)
2586 *list = (*list)->next;
2587 break;
2589 list = &(*list)->next;
2592 else
2593 ret = !!newhead;
2594 ALCdevice_Unlock(device);
2596 ALCcontext_DecRef(context);
2597 return ret;
2600 void ALCcontext_IncRef(ALCcontext *context)
2602 uint ref = IncrementRef(&context->ref);
2603 TRACEREF("%p increasing refcount to %u\n", context, ref);
2606 void ALCcontext_DecRef(ALCcontext *context)
2608 uint ref = DecrementRef(&context->ref);
2609 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2610 if(ref == 0) FreeContext(context);
2613 static void ReleaseThreadCtx(void *ptr)
2615 ALCcontext *context = ptr;
2616 uint ref = DecrementRef(&context->ref);
2617 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2618 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2621 /* VerifyContext
2623 * Checks that the given context is valid, and increments its reference count.
2625 static ALCboolean VerifyContext(ALCcontext **context)
2627 ALCdevice *dev;
2629 LockLists();
2630 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2631 while(dev)
2633 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2634 while(ctx)
2636 if(ctx == *context)
2638 ALCcontext_IncRef(ctx);
2639 UnlockLists();
2640 return ALC_TRUE;
2642 ctx = ctx->next;
2644 dev = dev->next;
2646 UnlockLists();
2648 *context = NULL;
2649 return ALC_FALSE;
2653 /* GetContextRef
2655 * Returns the currently active context for this thread, and adds a reference
2656 * without locking it.
2658 ALCcontext *GetContextRef(void)
2660 ALCcontext *context;
2662 context = altss_get(LocalContext);
2663 if(context)
2664 ALCcontext_IncRef(context);
2665 else
2667 LockLists();
2668 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2669 if(context)
2670 ALCcontext_IncRef(context);
2671 UnlockLists();
2674 return context;
2678 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2680 ALCdevice *device = context->Device;
2681 ALsizei num_sends = device->NumAuxSends;
2682 struct ALsourceProps *props;
2683 size_t sizeof_props;
2684 size_t sizeof_voice;
2685 ALvoice **voices;
2686 ALvoice *voice;
2687 ALsizei v = 0;
2688 size_t size;
2690 if(num_voices == context->MaxVoices && num_sends == old_sends)
2691 return;
2693 /* Allocate the voice pointers, voices, and the voices' stored source
2694 * property set (including the dynamically-sized Send[] array) in one
2695 * chunk.
2697 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2698 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2699 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2701 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2702 /* The voice and property objects are stored interleaved since they're
2703 * paired together.
2705 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2706 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2708 if(context->Voices)
2710 ALsizei v_count = mini(context->VoiceCount, num_voices);
2711 for(;v < v_count;v++)
2713 ALsizei s_count = mini(old_sends, num_sends);
2714 ALsizei i;
2716 /* Copy the old voice data and source property set to the new
2717 * storage.
2719 *voice = *(context->Voices[v]);
2720 for(i = 0;i < s_count;i++)
2721 voice->Send[i] = context->Voices[v]->Send[i];
2722 *props = *(context->Voices[v]->Props);
2723 for(i = 0;i < s_count;i++)
2724 props->Send[i] = context->Voices[v]->Props->Send[i];
2726 /* Set this voice's property set pointer and voice reference. */
2727 voice->Props = props;
2728 voices[v] = voice;
2730 /* Increment pointers to the next storage space. */
2731 voice = (ALvoice*)((char*)props + sizeof_props);
2732 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2735 /* Finish setting the voices' property set pointers and references. */
2736 for(;v < num_voices;v++)
2738 voice->Props = props;
2739 voices[v] = voice;
2741 voice = (ALvoice*)((char*)props + sizeof_props);
2742 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2745 al_free(context->Voices);
2746 context->Voices = voices;
2747 context->MaxVoices = num_voices;
2748 context->VoiceCount = mini(context->VoiceCount, num_voices);
2752 /************************************************
2753 * Standard ALC functions
2754 ************************************************/
2756 /* alcGetError
2758 * Return last ALC generated error code for the given device
2760 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2762 ALCenum errorCode;
2764 if(VerifyDevice(&device))
2766 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2767 ALCdevice_DecRef(device);
2769 else
2770 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2772 return errorCode;
2776 /* alcSuspendContext
2778 * Suspends updates for the given context
2780 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2782 if(!SuspendDefers)
2783 return;
2785 if(!VerifyContext(&context))
2786 alcSetError(NULL, ALC_INVALID_CONTEXT);
2787 else
2789 ALCcontext_DeferUpdates(context);
2790 ALCcontext_DecRef(context);
2794 /* alcProcessContext
2796 * Resumes processing updates for the given context
2798 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2800 if(!SuspendDefers)
2801 return;
2803 if(!VerifyContext(&context))
2804 alcSetError(NULL, ALC_INVALID_CONTEXT);
2805 else
2807 ALCcontext_ProcessUpdates(context);
2808 ALCcontext_DecRef(context);
2813 /* alcGetString
2815 * Returns information about the device, and error strings
2817 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2819 const ALCchar *value = NULL;
2821 switch(param)
2823 case ALC_NO_ERROR:
2824 value = alcNoError;
2825 break;
2827 case ALC_INVALID_ENUM:
2828 value = alcErrInvalidEnum;
2829 break;
2831 case ALC_INVALID_VALUE:
2832 value = alcErrInvalidValue;
2833 break;
2835 case ALC_INVALID_DEVICE:
2836 value = alcErrInvalidDevice;
2837 break;
2839 case ALC_INVALID_CONTEXT:
2840 value = alcErrInvalidContext;
2841 break;
2843 case ALC_OUT_OF_MEMORY:
2844 value = alcErrOutOfMemory;
2845 break;
2847 case ALC_DEVICE_SPECIFIER:
2848 value = alcDefaultName;
2849 break;
2851 case ALC_ALL_DEVICES_SPECIFIER:
2852 if(VerifyDevice(&Device))
2854 value = alstr_get_cstr(Device->DeviceName);
2855 ALCdevice_DecRef(Device);
2857 else
2859 ProbeAllDevicesList();
2860 value = alstr_get_cstr(alcAllDevicesList);
2862 break;
2864 case ALC_CAPTURE_DEVICE_SPECIFIER:
2865 if(VerifyDevice(&Device))
2867 value = alstr_get_cstr(Device->DeviceName);
2868 ALCdevice_DecRef(Device);
2870 else
2872 ProbeCaptureDeviceList();
2873 value = alstr_get_cstr(alcCaptureDeviceList);
2875 break;
2877 /* Default devices are always first in the list */
2878 case ALC_DEFAULT_DEVICE_SPECIFIER:
2879 value = alcDefaultName;
2880 break;
2882 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2883 if(alstr_empty(alcAllDevicesList))
2884 ProbeAllDevicesList();
2886 VerifyDevice(&Device);
2888 free(alcDefaultAllDevicesSpecifier);
2889 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
2890 if(!alcDefaultAllDevicesSpecifier)
2891 alcSetError(Device, ALC_OUT_OF_MEMORY);
2893 value = alcDefaultAllDevicesSpecifier;
2894 if(Device) ALCdevice_DecRef(Device);
2895 break;
2897 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2898 if(alstr_empty(alcCaptureDeviceList))
2899 ProbeCaptureDeviceList();
2901 VerifyDevice(&Device);
2903 free(alcCaptureDefaultDeviceSpecifier);
2904 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
2905 if(!alcCaptureDefaultDeviceSpecifier)
2906 alcSetError(Device, ALC_OUT_OF_MEMORY);
2908 value = alcCaptureDefaultDeviceSpecifier;
2909 if(Device) ALCdevice_DecRef(Device);
2910 break;
2912 case ALC_EXTENSIONS:
2913 if(!VerifyDevice(&Device))
2914 value = alcNoDeviceExtList;
2915 else
2917 value = alcExtensionList;
2918 ALCdevice_DecRef(Device);
2920 break;
2922 case ALC_HRTF_SPECIFIER_SOFT:
2923 if(!VerifyDevice(&Device))
2924 alcSetError(NULL, ALC_INVALID_DEVICE);
2925 else
2927 almtx_lock(&Device->BackendLock);
2928 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
2929 almtx_unlock(&Device->BackendLock);
2930 ALCdevice_DecRef(Device);
2932 break;
2934 default:
2935 VerifyDevice(&Device);
2936 alcSetError(Device, ALC_INVALID_ENUM);
2937 if(Device) ALCdevice_DecRef(Device);
2938 break;
2941 return value;
2945 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2947 if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 &&
2948 device->FmtChans <= DevFmtAmbi3)
2949 return 23;
2950 return 17;
2953 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2955 ALCsizei i;
2957 if(size <= 0 || values == NULL)
2959 alcSetError(device, ALC_INVALID_VALUE);
2960 return 0;
2963 if(!device)
2965 switch(param)
2967 case ALC_MAJOR_VERSION:
2968 values[0] = alcMajorVersion;
2969 return 1;
2970 case ALC_MINOR_VERSION:
2971 values[0] = alcMinorVersion;
2972 return 1;
2974 case ALC_ATTRIBUTES_SIZE:
2975 case ALC_ALL_ATTRIBUTES:
2976 case ALC_FREQUENCY:
2977 case ALC_REFRESH:
2978 case ALC_SYNC:
2979 case ALC_MONO_SOURCES:
2980 case ALC_STEREO_SOURCES:
2981 case ALC_CAPTURE_SAMPLES:
2982 case ALC_FORMAT_CHANNELS_SOFT:
2983 case ALC_FORMAT_TYPE_SOFT:
2984 case ALC_AMBISONIC_LAYOUT_SOFT:
2985 case ALC_AMBISONIC_SCALING_SOFT:
2986 case ALC_AMBISONIC_ORDER_SOFT:
2987 alcSetError(NULL, ALC_INVALID_DEVICE);
2988 return 0;
2990 default:
2991 alcSetError(NULL, ALC_INVALID_ENUM);
2992 return 0;
2994 return 0;
2997 if(device->Type == Capture)
2999 switch(param)
3001 case ALC_CAPTURE_SAMPLES:
3002 almtx_lock(&device->BackendLock);
3003 values[0] = V0(device->Backend,availableSamples)();
3004 almtx_unlock(&device->BackendLock);
3005 return 1;
3007 case ALC_CONNECTED:
3008 values[0] = device->Connected;
3009 return 1;
3011 default:
3012 alcSetError(device, ALC_INVALID_ENUM);
3013 return 0;
3015 return 0;
3018 /* render device */
3019 switch(param)
3021 case ALC_MAJOR_VERSION:
3022 values[0] = alcMajorVersion;
3023 return 1;
3025 case ALC_MINOR_VERSION:
3026 values[0] = alcMinorVersion;
3027 return 1;
3029 case ALC_EFX_MAJOR_VERSION:
3030 values[0] = alcEFXMajorVersion;
3031 return 1;
3033 case ALC_EFX_MINOR_VERSION:
3034 values[0] = alcEFXMinorVersion;
3035 return 1;
3037 case ALC_ATTRIBUTES_SIZE:
3038 values[0] = NumAttrsForDevice(device);
3039 return 1;
3041 case ALC_ALL_ATTRIBUTES:
3042 if(size < NumAttrsForDevice(device))
3044 alcSetError(device, ALC_INVALID_VALUE);
3045 return 0;
3048 i = 0;
3049 almtx_lock(&device->BackendLock);
3050 values[i++] = ALC_FREQUENCY;
3051 values[i++] = device->Frequency;
3053 if(device->Type != Loopback)
3055 values[i++] = ALC_REFRESH;
3056 values[i++] = device->Frequency / device->UpdateSize;
3058 values[i++] = ALC_SYNC;
3059 values[i++] = ALC_FALSE;
3061 else
3063 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3065 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3066 values[i++] = device->AmbiLayout;
3068 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3069 values[i++] = device->AmbiScale;
3071 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3072 values[i++] = device->FmtChans-DevFmtAmbi1+1;
3074 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3075 values[i++] = ALC_BFORMAT3D_SOFT;
3077 else
3079 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3080 values[i++] = device->FmtChans;
3083 values[i++] = ALC_FORMAT_TYPE_SOFT;
3084 values[i++] = device->FmtType;
3087 values[i++] = ALC_MONO_SOURCES;
3088 values[i++] = device->NumMonoSources;
3090 values[i++] = ALC_STEREO_SOURCES;
3091 values[i++] = device->NumStereoSources;
3093 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3094 values[i++] = device->NumAuxSends;
3096 values[i++] = ALC_HRTF_SOFT;
3097 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3099 values[i++] = ALC_HRTF_STATUS_SOFT;
3100 values[i++] = device->HrtfStatus;
3101 almtx_unlock(&device->BackendLock);
3103 values[i++] = 0;
3104 return i;
3106 case ALC_FREQUENCY:
3107 values[0] = device->Frequency;
3108 return 1;
3110 case ALC_REFRESH:
3111 if(device->Type == Loopback)
3113 alcSetError(device, ALC_INVALID_DEVICE);
3114 return 0;
3116 almtx_lock(&device->BackendLock);
3117 values[0] = device->Frequency / device->UpdateSize;
3118 almtx_unlock(&device->BackendLock);
3119 return 1;
3121 case ALC_SYNC:
3122 if(device->Type == Loopback)
3124 alcSetError(device, ALC_INVALID_DEVICE);
3125 return 0;
3127 values[0] = ALC_FALSE;
3128 return 1;
3130 case ALC_FORMAT_CHANNELS_SOFT:
3131 if(device->Type != Loopback)
3133 alcSetError(device, ALC_INVALID_DEVICE);
3134 return 0;
3136 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3137 values[0] = ALC_BFORMAT3D_SOFT;
3138 else
3139 values[0] = device->FmtChans;
3140 return 1;
3142 case ALC_FORMAT_TYPE_SOFT:
3143 if(device->Type != Loopback)
3145 alcSetError(device, ALC_INVALID_DEVICE);
3146 return 0;
3148 values[0] = device->FmtType;
3149 return 1;
3151 case ALC_AMBISONIC_LAYOUT_SOFT:
3152 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3153 device->FmtChans <= DevFmtAmbi3))
3155 alcSetError(device, ALC_INVALID_DEVICE);
3156 return 0;
3158 values[0] = device->AmbiLayout;
3159 return 1;
3161 case ALC_AMBISONIC_SCALING_SOFT:
3162 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3163 device->FmtChans <= DevFmtAmbi3))
3165 alcSetError(device, ALC_INVALID_DEVICE);
3166 return 0;
3168 values[0] = device->AmbiScale;
3169 return 1;
3171 case ALC_AMBISONIC_ORDER_SOFT:
3172 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3173 device->FmtChans <= DevFmtAmbi3))
3175 alcSetError(device, ALC_INVALID_DEVICE);
3176 return 0;
3178 values[0] = device->FmtChans - DevFmtAmbi1 + 1;
3179 return 1;
3181 case ALC_MONO_SOURCES:
3182 values[0] = device->NumMonoSources;
3183 return 1;
3185 case ALC_STEREO_SOURCES:
3186 values[0] = device->NumStereoSources;
3187 return 1;
3189 case ALC_MAX_AUXILIARY_SENDS:
3190 values[0] = device->NumAuxSends;
3191 return 1;
3193 case ALC_CONNECTED:
3194 values[0] = device->Connected;
3195 return 1;
3197 case ALC_HRTF_SOFT:
3198 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3199 return 1;
3201 case ALC_HRTF_STATUS_SOFT:
3202 values[0] = device->HrtfStatus;
3203 return 1;
3205 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3206 almtx_lock(&device->BackendLock);
3207 FreeHrtfList(&device->HrtfList);
3208 device->HrtfList = EnumerateHrtf(device->DeviceName);
3209 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3210 almtx_unlock(&device->BackendLock);
3211 return 1;
3213 default:
3214 alcSetError(device, ALC_INVALID_ENUM);
3215 return 0;
3217 return 0;
3220 /* alcGetIntegerv
3222 * Returns information about the device and the version of OpenAL
3224 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3226 VerifyDevice(&device);
3227 if(size <= 0 || values == NULL)
3228 alcSetError(device, ALC_INVALID_VALUE);
3229 else
3230 GetIntegerv(device, param, size, values);
3231 if(device) ALCdevice_DecRef(device);
3234 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3236 ALCint *ivals;
3237 ALsizei i;
3239 VerifyDevice(&device);
3240 if(size <= 0 || values == NULL)
3241 alcSetError(device, ALC_INVALID_VALUE);
3242 else if(!device || device->Type == Capture)
3244 ivals = malloc(size * sizeof(ALCint));
3245 size = GetIntegerv(device, pname, size, ivals);
3246 for(i = 0;i < size;i++)
3247 values[i] = ivals[i];
3248 free(ivals);
3250 else /* render device */
3252 ClockLatency clock;
3253 ALuint64 basecount;
3254 ALuint samplecount;
3255 ALuint refcount;
3257 switch(pname)
3259 case ALC_ATTRIBUTES_SIZE:
3260 *values = NumAttrsForDevice(device)+2;
3261 break;
3263 case ALC_ALL_ATTRIBUTES:
3264 if(size < NumAttrsForDevice(device)+2)
3265 alcSetError(device, ALC_INVALID_VALUE);
3266 else
3268 i = 0;
3269 almtx_lock(&device->BackendLock);
3270 values[i++] = ALC_FREQUENCY;
3271 values[i++] = device->Frequency;
3273 if(device->Type != Loopback)
3275 values[i++] = ALC_REFRESH;
3276 values[i++] = device->Frequency / device->UpdateSize;
3278 values[i++] = ALC_SYNC;
3279 values[i++] = ALC_FALSE;
3281 else
3283 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3285 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3286 values[i++] = device->AmbiLayout;
3288 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3289 values[i++] = device->AmbiScale;
3291 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3292 values[i++] = device->FmtChans-DevFmtAmbi1+1;
3294 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3295 values[i++] = ALC_BFORMAT3D_SOFT;
3297 else
3299 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3300 values[i++] = device->FmtChans;
3303 values[i++] = ALC_FORMAT_TYPE_SOFT;
3304 values[i++] = device->FmtType;
3307 values[i++] = ALC_MONO_SOURCES;
3308 values[i++] = device->NumMonoSources;
3310 values[i++] = ALC_STEREO_SOURCES;
3311 values[i++] = device->NumStereoSources;
3313 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3314 values[i++] = device->NumAuxSends;
3316 values[i++] = ALC_HRTF_SOFT;
3317 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3319 values[i++] = ALC_HRTF_STATUS_SOFT;
3320 values[i++] = device->HrtfStatus;
3322 clock = V0(device->Backend,getClockLatency)();
3323 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3324 values[i++] = clock.ClockTime;
3326 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3327 values[i++] = clock.Latency;
3328 almtx_unlock(&device->BackendLock);
3330 values[i++] = 0;
3332 break;
3334 case ALC_DEVICE_CLOCK_SOFT:
3335 almtx_lock(&device->BackendLock);
3336 do {
3337 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3338 althrd_yield();
3339 basecount = device->ClockBase;
3340 samplecount = device->SamplesDone;
3341 } while(refcount != ReadRef(&device->MixCount));
3342 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3343 almtx_unlock(&device->BackendLock);
3344 break;
3346 case ALC_DEVICE_LATENCY_SOFT:
3347 almtx_lock(&device->BackendLock);
3348 clock = V0(device->Backend,getClockLatency)();
3349 almtx_unlock(&device->BackendLock);
3350 *values = clock.Latency;
3351 break;
3353 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3354 if(size < 2)
3355 alcSetError(device, ALC_INVALID_VALUE);
3356 else
3358 almtx_lock(&device->BackendLock);
3359 clock = V0(device->Backend,getClockLatency)();
3360 almtx_unlock(&device->BackendLock);
3361 values[0] = clock.ClockTime;
3362 values[1] = clock.Latency;
3364 break;
3366 default:
3367 ivals = malloc(size * sizeof(ALCint));
3368 size = GetIntegerv(device, pname, size, ivals);
3369 for(i = 0;i < size;i++)
3370 values[i] = ivals[i];
3371 free(ivals);
3372 break;
3375 if(device)
3376 ALCdevice_DecRef(device);
3380 /* alcIsExtensionPresent
3382 * Determines if there is support for a particular extension
3384 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3386 ALCboolean bResult = ALC_FALSE;
3388 VerifyDevice(&device);
3390 if(!extName)
3391 alcSetError(device, ALC_INVALID_VALUE);
3392 else
3394 size_t len = strlen(extName);
3395 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3396 while(ptr && *ptr)
3398 if(strncasecmp(ptr, extName, len) == 0 &&
3399 (ptr[len] == '\0' || isspace(ptr[len])))
3401 bResult = ALC_TRUE;
3402 break;
3404 if((ptr=strchr(ptr, ' ')) != NULL)
3406 do {
3407 ++ptr;
3408 } while(isspace(*ptr));
3412 if(device)
3413 ALCdevice_DecRef(device);
3414 return bResult;
3418 /* alcGetProcAddress
3420 * Retrieves the function address for a particular extension function
3422 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3424 ALCvoid *ptr = NULL;
3426 if(!funcName)
3428 VerifyDevice(&device);
3429 alcSetError(device, ALC_INVALID_VALUE);
3430 if(device) ALCdevice_DecRef(device);
3432 else
3434 size_t i = 0;
3435 for(i = 0;i < COUNTOF(alcFunctions);i++)
3437 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3439 ptr = alcFunctions[i].address;
3440 break;
3445 return ptr;
3449 /* alcGetEnumValue
3451 * Get the value for a particular ALC enumeration name
3453 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3455 ALCenum val = 0;
3457 if(!enumName)
3459 VerifyDevice(&device);
3460 alcSetError(device, ALC_INVALID_VALUE);
3461 if(device) ALCdevice_DecRef(device);
3463 else
3465 size_t i = 0;
3466 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3468 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3470 val = alcEnumerations[i].value;
3471 break;
3476 return val;
3480 /* alcCreateContext
3482 * Create and attach a context to the given device.
3484 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3486 ALCcontext *ALContext;
3487 ALfloat valf;
3488 ALCenum err;
3490 /* Explicitly hold the list lock while taking the BackendLock in case the
3491 * device is asynchronously destropyed, to ensure this new context is
3492 * properly cleaned up after being made.
3494 LockLists();
3495 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3497 UnlockLists();
3498 alcSetError(device, ALC_INVALID_DEVICE);
3499 if(device) ALCdevice_DecRef(device);
3500 return NULL;
3502 almtx_lock(&device->BackendLock);
3503 UnlockLists();
3505 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3507 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3508 if(ALContext)
3510 InitRef(&ALContext->ref, 1);
3511 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3513 ALContext->Device = device;
3514 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3516 ALContext->Voices = NULL;
3517 ALContext->MaxVoices = 0;
3518 ALContext->VoiceCount = 0;
3519 AllocateVoices(ALContext, 256, device->NumAuxSends);
3521 if(!ALContext || !ALContext->Voices)
3523 almtx_unlock(&device->BackendLock);
3525 if(ALContext)
3527 al_free(ALContext->Voices);
3528 ALContext->Voices = NULL;
3530 al_free(ALContext);
3531 ALContext = NULL;
3534 alcSetError(device, ALC_OUT_OF_MEMORY);
3535 ALCdevice_DecRef(device);
3536 return NULL;
3539 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3541 almtx_unlock(&device->BackendLock);
3543 al_free(ALContext->Voices);
3544 ALContext->Voices = NULL;
3546 al_free(ALContext);
3547 ALContext = NULL;
3549 alcSetError(device, err);
3550 if(err == ALC_INVALID_DEVICE)
3552 V0(device->Backend,lock)();
3553 aluHandleDisconnect(device);
3554 V0(device->Backend,unlock)();
3556 ALCdevice_DecRef(device);
3557 return NULL;
3560 ALCdevice_IncRef(ALContext->Device);
3561 InitContext(ALContext);
3563 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3565 if(!isfinite(valf))
3566 ERR("volume-adjust must be finite: %f\n", valf);
3567 else
3569 ALfloat db = clampf(valf, -24.0f, 24.0f);
3570 if(db != valf)
3571 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3572 ALContext->GainBoost = powf(10.0f, db/20.0f);
3573 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3576 UpdateListenerProps(ALContext);
3579 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3580 do {
3581 ALContext->next = head;
3582 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3583 &device->ContextList, &head, ALContext) == 0);
3585 almtx_unlock(&device->BackendLock);
3587 ALCdevice_DecRef(device);
3589 TRACE("Created context %p\n", ALContext);
3590 return ALContext;
3593 /* alcDestroyContext
3595 * Remove a context from its device
3597 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3599 ALCdevice *Device;
3601 LockLists();
3602 if(!VerifyContext(&context))
3604 UnlockLists();
3605 alcSetError(NULL, ALC_INVALID_CONTEXT);
3606 return;
3609 Device = context->Device;
3610 if(Device)
3612 almtx_lock(&Device->BackendLock);
3613 if(!ReleaseContext(context, Device))
3615 V0(Device->Backend,stop)();
3616 Device->Flags &= ~DEVICE_RUNNING;
3618 almtx_unlock(&Device->BackendLock);
3620 UnlockLists();
3622 ALCcontext_DecRef(context);
3626 /* alcGetCurrentContext
3628 * Returns the currently active context on the calling thread
3630 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3632 ALCcontext *Context = altss_get(LocalContext);
3633 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3634 return Context;
3637 /* alcGetThreadContext
3639 * Returns the currently active thread-local context
3641 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3643 return altss_get(LocalContext);
3647 /* alcMakeContextCurrent
3649 * Makes the given context the active process-wide context, and removes the
3650 * thread-local context for the calling thread.
3652 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3654 /* context must be valid or NULL */
3655 if(context && !VerifyContext(&context))
3657 alcSetError(NULL, ALC_INVALID_CONTEXT);
3658 return ALC_FALSE;
3660 /* context's reference count is already incremented */
3661 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3662 if(context) ALCcontext_DecRef(context);
3664 if((context=altss_get(LocalContext)) != NULL)
3666 altss_set(LocalContext, NULL);
3667 ALCcontext_DecRef(context);
3670 return ALC_TRUE;
3673 /* alcSetThreadContext
3675 * Makes the given context the active context for the current thread
3677 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3679 ALCcontext *old;
3681 /* context must be valid or NULL */
3682 if(context && !VerifyContext(&context))
3684 alcSetError(NULL, ALC_INVALID_CONTEXT);
3685 return ALC_FALSE;
3687 /* context's reference count is already incremented */
3688 old = altss_get(LocalContext);
3689 altss_set(LocalContext, context);
3690 if(old) ALCcontext_DecRef(old);
3692 return ALC_TRUE;
3696 /* alcGetContextsDevice
3698 * Returns the device that a particular context is attached to
3700 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3702 ALCdevice *Device;
3704 if(!VerifyContext(&Context))
3706 alcSetError(NULL, ALC_INVALID_CONTEXT);
3707 return NULL;
3709 Device = Context->Device;
3710 ALCcontext_DecRef(Context);
3712 return Device;
3716 /* alcOpenDevice
3718 * Opens the named device.
3720 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3722 const ALCchar *fmt;
3723 ALCdevice *device;
3724 ALCenum err;
3725 ALCsizei i;
3727 DO_INITCONFIG();
3729 if(!PlaybackBackend.name)
3731 alcSetError(NULL, ALC_INVALID_VALUE);
3732 return NULL;
3735 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3736 #ifdef _WIN32
3737 /* Some old Windows apps hardcode these expecting OpenAL to use a
3738 * specific audio API, even when they're not enumerated. Creative's
3739 * router effectively ignores them too.
3741 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3742 || strcasecmp(deviceName, "MMSYSTEM") == 0
3743 #endif
3745 deviceName = NULL;
3747 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3748 if(!device)
3750 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3751 return NULL;
3754 //Validate device
3755 InitRef(&device->ref, 1);
3756 device->Connected = ALC_TRUE;
3757 device->Type = Playback;
3758 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3760 device->Flags = 0;
3761 device->Bs2b = NULL;
3762 device->Uhj_Encoder = NULL;
3763 device->Hrtf = NULL;
3764 device->HrtfHandle = NULL;
3765 VECTOR_INIT(device->HrtfList);
3766 AL_STRING_INIT(device->HrtfName);
3767 device->Render_Mode = NormalRender;
3768 AL_STRING_INIT(device->DeviceName);
3769 device->Dry.Buffer = NULL;
3770 device->Dry.NumChannels = 0;
3771 device->FOAOut.Buffer = NULL;
3772 device->FOAOut.NumChannels = 0;
3773 device->RealOut.Buffer = NULL;
3774 device->RealOut.NumChannels = 0;
3775 device->AvgSpeakerDist = 0.0f;
3777 ATOMIC_INIT(&device->ContextList, NULL);
3779 device->ClockBase = 0;
3780 device->SamplesDone = 0;
3782 device->SourcesMax = 256;
3783 device->AuxiliaryEffectSlotMax = 64;
3784 device->NumAuxSends = DEFAULT_SENDS;
3786 InitUIntMap(&device->BufferMap, ~0);
3787 InitUIntMap(&device->EffectMap, ~0);
3788 InitUIntMap(&device->FilterMap, ~0);
3790 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
3792 device->ChannelDelay[i].Gain = 1.0f;
3793 device->ChannelDelay[i].Length = 0;
3794 device->ChannelDelay[i].Buffer = NULL;
3797 //Set output format
3798 device->FmtChans = DevFmtChannelsDefault;
3799 device->FmtType = DevFmtTypeDefault;
3800 device->Frequency = DEFAULT_OUTPUT_RATE;
3801 device->IsHeadphones = AL_FALSE;
3802 device->AmbiLayout = AmbiLayout_Default;
3803 device->AmbiScale = AmbiNorm_Default;
3804 device->NumUpdates = 3;
3805 device->UpdateSize = 1024;
3807 if(!PlaybackBackend.getFactory)
3808 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3809 ALCbackend_Playback);
3810 else
3812 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3813 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3815 if(!device->Backend)
3817 al_free(device);
3818 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3819 return NULL;
3823 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3825 static const struct {
3826 const char name[16];
3827 enum DevFmtChannels chans;
3828 } chanlist[] = {
3829 { "mono", DevFmtMono },
3830 { "stereo", DevFmtStereo },
3831 { "quad", DevFmtQuad },
3832 { "surround51", DevFmtX51 },
3833 { "surround61", DevFmtX61 },
3834 { "surround71", DevFmtX71 },
3835 { "surround51rear", DevFmtX51Rear },
3836 { "ambi1", DevFmtAmbi1 },
3837 { "ambi2", DevFmtAmbi2 },
3838 { "ambi3", DevFmtAmbi3 },
3840 size_t i;
3842 for(i = 0;i < COUNTOF(chanlist);i++)
3844 if(strcasecmp(chanlist[i].name, fmt) == 0)
3846 device->FmtChans = chanlist[i].chans;
3847 device->Flags |= DEVICE_CHANNELS_REQUEST;
3848 break;
3851 if(i == COUNTOF(chanlist))
3852 ERR("Unsupported channels: %s\n", fmt);
3854 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3856 static const struct {
3857 const char name[16];
3858 enum DevFmtType type;
3859 } typelist[] = {
3860 { "int8", DevFmtByte },
3861 { "uint8", DevFmtUByte },
3862 { "int16", DevFmtShort },
3863 { "uint16", DevFmtUShort },
3864 { "int32", DevFmtInt },
3865 { "uint32", DevFmtUInt },
3866 { "float32", DevFmtFloat },
3868 size_t i;
3870 for(i = 0;i < COUNTOF(typelist);i++)
3872 if(strcasecmp(typelist[i].name, fmt) == 0)
3874 device->FmtType = typelist[i].type;
3875 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3876 break;
3879 if(i == COUNTOF(typelist))
3880 ERR("Unsupported sample-type: %s\n", fmt);
3883 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3885 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3886 if(device->Frequency < MIN_OUTPUT_RATE)
3887 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3888 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3891 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3892 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3894 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3895 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3896 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3897 device->UpdateSize = (device->UpdateSize+3)&~3;
3899 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3900 if(device->SourcesMax == 0) device->SourcesMax = 256;
3902 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3903 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3905 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
3906 device->NumAuxSends = clampi(
3907 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3910 device->NumStereoSources = 1;
3911 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3913 // Find a playback device to open
3914 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3916 DELETE_OBJ(device->Backend);
3917 al_free(device);
3918 alcSetError(NULL, err);
3919 return NULL;
3921 almtx_init(&device->BackendLock, almtx_plain);
3923 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3925 if(strcasecmp(fmt, "fuma") == 0)
3927 device->AmbiLayout = AmbiLayout_FuMa;
3928 device->AmbiScale = AmbiNorm_FuMa;
3930 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3932 device->AmbiLayout = AmbiLayout_ACN;
3933 device->AmbiScale = AmbiNorm_SN3D;
3935 else if(strcasecmp(fmt, "acn+n3d") == 0)
3937 device->AmbiLayout = AmbiLayout_ACN;
3938 device->AmbiScale = AmbiNorm_N3D;
3940 else
3941 ERR("Unsupported ambi-format: %s\n", fmt);
3944 if(DefaultEffect.type != AL_EFFECT_NULL)
3946 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3947 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3949 device->DefaultSlot = NULL;
3950 ERR("Failed to initialize the default effect slot\n");
3952 else
3954 aluInitEffectPanning(device->DefaultSlot);
3955 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3957 DeinitEffectSlot(device->DefaultSlot);
3958 device->DefaultSlot = NULL;
3959 ERR("Failed to initialize the default effect\n");
3965 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3966 do {
3967 device->next = head;
3968 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3971 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
3972 return device;
3975 /* alcCloseDevice
3977 * Closes the given device.
3979 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3981 ALCdevice *iter, *origdev;
3982 ALCcontext *ctx;
3984 LockLists();
3985 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3986 do {
3987 if(iter == device)
3988 break;
3989 } while((iter=iter->next) != NULL);
3990 if(!iter || iter->Type == Capture)
3992 alcSetError(iter, ALC_INVALID_DEVICE);
3993 UnlockLists();
3994 return ALC_FALSE;
3996 almtx_lock(&device->BackendLock);
3998 origdev = device;
3999 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4001 ALCdevice *volatile*list = &origdev->next;
4002 while(*list)
4004 if(*list == device)
4006 *list = (*list)->next;
4007 break;
4009 list = &(*list)->next;
4012 UnlockLists();
4014 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4015 while(ctx != NULL)
4017 ALCcontext *next = ctx->next;
4018 WARN("Releasing context %p\n", ctx);
4019 ReleaseContext(ctx, device);
4020 ctx = next;
4022 if((device->Flags&DEVICE_RUNNING))
4023 V0(device->Backend,stop)();
4024 device->Flags &= ~DEVICE_RUNNING;
4025 almtx_unlock(&device->BackendLock);
4027 ALCdevice_DecRef(device);
4029 return ALC_TRUE;
4033 /************************************************
4034 * ALC capture functions
4035 ************************************************/
4036 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4038 ALCdevice *device = NULL;
4039 ALCenum err;
4040 ALCsizei i;
4042 DO_INITCONFIG();
4044 if(!CaptureBackend.name)
4046 alcSetError(NULL, ALC_INVALID_VALUE);
4047 return NULL;
4050 if(samples <= 0)
4052 alcSetError(NULL, ALC_INVALID_VALUE);
4053 return NULL;
4056 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4057 deviceName = NULL;
4059 device = al_calloc(16, sizeof(ALCdevice));
4060 if(!device)
4062 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4063 return NULL;
4066 //Validate device
4067 InitRef(&device->ref, 1);
4068 device->Connected = ALC_TRUE;
4069 device->Type = Capture;
4071 device->Hrtf = NULL;
4072 device->HrtfHandle = NULL;
4073 VECTOR_INIT(device->HrtfList);
4074 AL_STRING_INIT(device->HrtfName);
4076 AL_STRING_INIT(device->DeviceName);
4077 device->Dry.Buffer = NULL;
4078 device->Dry.NumChannels = 0;
4079 device->FOAOut.Buffer = NULL;
4080 device->FOAOut.NumChannels = 0;
4081 device->RealOut.Buffer = NULL;
4082 device->RealOut.NumChannels = 0;
4084 InitUIntMap(&device->BufferMap, ~0);
4085 InitUIntMap(&device->EffectMap, ~0);
4086 InitUIntMap(&device->FilterMap, ~0);
4088 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4090 device->ChannelDelay[i].Gain = 1.0f;
4091 device->ChannelDelay[i].Length = 0;
4092 device->ChannelDelay[i].Buffer = NULL;
4095 if(!CaptureBackend.getFactory)
4096 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
4097 ALCbackend_Capture);
4098 else
4100 ALCbackendFactory *factory = CaptureBackend.getFactory();
4101 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4103 if(!device->Backend)
4105 al_free(device);
4106 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4107 return NULL;
4110 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4111 device->Frequency = frequency;
4113 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4114 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4116 al_free(device);
4117 alcSetError(NULL, ALC_INVALID_ENUM);
4118 return NULL;
4120 device->IsHeadphones = AL_FALSE;
4121 device->AmbiLayout = AmbiLayout_Default;
4122 device->AmbiScale = AmbiNorm_Default;
4124 device->UpdateSize = samples;
4125 device->NumUpdates = 1;
4127 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4128 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4129 device->Frequency, device->UpdateSize, device->NumUpdates
4131 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4133 al_free(device);
4134 alcSetError(NULL, err);
4135 return NULL;
4137 almtx_init(&device->BackendLock, almtx_plain);
4140 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4141 do {
4142 device->next = head;
4143 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4146 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4147 return device;
4150 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4152 ALCdevice *iter, *origdev;
4154 LockLists();
4155 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4156 do {
4157 if(iter == device)
4158 break;
4159 } while((iter=iter->next) != NULL);
4160 if(!iter || iter->Type != Capture)
4162 alcSetError(iter, ALC_INVALID_DEVICE);
4163 UnlockLists();
4164 return ALC_FALSE;
4167 origdev = device;
4168 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4170 ALCdevice *volatile*list = &origdev->next;
4171 while(*list)
4173 if(*list == device)
4175 *list = (*list)->next;
4176 break;
4178 list = &(*list)->next;
4181 UnlockLists();
4183 ALCdevice_DecRef(device);
4185 return ALC_TRUE;
4188 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4190 if(!VerifyDevice(&device) || device->Type != Capture)
4191 alcSetError(device, ALC_INVALID_DEVICE);
4192 else
4194 almtx_lock(&device->BackendLock);
4195 if(!device->Connected)
4196 alcSetError(device, ALC_INVALID_DEVICE);
4197 else if(!(device->Flags&DEVICE_RUNNING))
4199 if(V0(device->Backend,start)())
4200 device->Flags |= DEVICE_RUNNING;
4201 else
4203 aluHandleDisconnect(device);
4204 alcSetError(device, ALC_INVALID_DEVICE);
4207 almtx_unlock(&device->BackendLock);
4210 if(device) ALCdevice_DecRef(device);
4213 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4215 if(!VerifyDevice(&device) || device->Type != Capture)
4216 alcSetError(device, ALC_INVALID_DEVICE);
4217 else
4219 almtx_lock(&device->BackendLock);
4220 if((device->Flags&DEVICE_RUNNING))
4221 V0(device->Backend,stop)();
4222 device->Flags &= ~DEVICE_RUNNING;
4223 almtx_unlock(&device->BackendLock);
4226 if(device) ALCdevice_DecRef(device);
4229 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4231 if(!VerifyDevice(&device) || device->Type != Capture)
4232 alcSetError(device, ALC_INVALID_DEVICE);
4233 else
4235 ALCenum err = ALC_INVALID_VALUE;
4237 almtx_lock(&device->BackendLock);
4238 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4239 err = V(device->Backend,captureSamples)(buffer, samples);
4240 almtx_unlock(&device->BackendLock);
4242 if(err != ALC_NO_ERROR)
4243 alcSetError(device, err);
4245 if(device) ALCdevice_DecRef(device);
4249 /************************************************
4250 * ALC loopback functions
4251 ************************************************/
4253 /* alcLoopbackOpenDeviceSOFT
4255 * Open a loopback device, for manual rendering.
4257 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4259 ALCbackendFactory *factory;
4260 ALCdevice *device;
4261 ALCsizei i;
4263 DO_INITCONFIG();
4265 /* Make sure the device name, if specified, is us. */
4266 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4268 alcSetError(NULL, ALC_INVALID_VALUE);
4269 return NULL;
4272 device = al_calloc(16, sizeof(ALCdevice));
4273 if(!device)
4275 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4276 return NULL;
4279 //Validate device
4280 InitRef(&device->ref, 1);
4281 device->Connected = ALC_TRUE;
4282 device->Type = Loopback;
4283 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4285 device->Flags = 0;
4286 device->Hrtf = NULL;
4287 device->HrtfHandle = NULL;
4288 VECTOR_INIT(device->HrtfList);
4289 AL_STRING_INIT(device->HrtfName);
4290 device->Bs2b = NULL;
4291 device->Uhj_Encoder = NULL;
4292 device->Render_Mode = NormalRender;
4293 AL_STRING_INIT(device->DeviceName);
4294 device->Dry.Buffer = NULL;
4295 device->Dry.NumChannels = 0;
4296 device->FOAOut.Buffer = NULL;
4297 device->FOAOut.NumChannels = 0;
4298 device->RealOut.Buffer = NULL;
4299 device->RealOut.NumChannels = 0;
4300 device->AvgSpeakerDist = 0.0f;
4302 ATOMIC_INIT(&device->ContextList, NULL);
4304 device->ClockBase = 0;
4305 device->SamplesDone = 0;
4307 device->SourcesMax = 256;
4308 device->AuxiliaryEffectSlotMax = 64;
4309 device->NumAuxSends = DEFAULT_SENDS;
4311 InitUIntMap(&device->BufferMap, ~0);
4312 InitUIntMap(&device->EffectMap, ~0);
4313 InitUIntMap(&device->FilterMap, ~0);
4315 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4317 device->ChannelDelay[i].Gain = 1.0f;
4318 device->ChannelDelay[i].Length = 0;
4319 device->ChannelDelay[i].Buffer = NULL;
4322 factory = ALCloopbackFactory_getFactory();
4323 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4324 if(!device->Backend)
4326 al_free(device);
4327 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4328 return NULL;
4330 almtx_init(&device->BackendLock, almtx_plain);
4332 //Set output format
4333 device->NumUpdates = 0;
4334 device->UpdateSize = 0;
4336 device->Frequency = DEFAULT_OUTPUT_RATE;
4337 device->FmtChans = DevFmtChannelsDefault;
4338 device->FmtType = DevFmtTypeDefault;
4339 device->IsHeadphones = AL_FALSE;
4340 device->AmbiLayout = AmbiLayout_Default;
4341 device->AmbiScale = AmbiNorm_Default;
4343 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4344 if(device->SourcesMax == 0) device->SourcesMax = 256;
4346 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4347 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4349 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4350 device->NumAuxSends = clampi(
4351 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4354 device->NumStereoSources = 1;
4355 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4357 // Open the "backend"
4358 V(device->Backend,open)("Loopback");
4361 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4362 do {
4363 device->next = head;
4364 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4367 TRACE("Created device %p\n", device);
4368 return device;
4371 /* alcIsRenderFormatSupportedSOFT
4373 * Determines if the loopback device supports the given format for rendering.
4375 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4377 ALCboolean ret = ALC_FALSE;
4379 if(!VerifyDevice(&device) || device->Type != Loopback)
4380 alcSetError(device, ALC_INVALID_DEVICE);
4381 else if(freq <= 0)
4382 alcSetError(device, ALC_INVALID_VALUE);
4383 else
4385 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4386 ret = ALC_TRUE;
4388 if(device) ALCdevice_DecRef(device);
4390 return ret;
4393 /* alcRenderSamplesSOFT
4395 * Renders some samples into a buffer, using the format last set by the
4396 * attributes given to alcCreateContext.
4398 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4400 if(!VerifyDevice(&device) || device->Type != Loopback)
4401 alcSetError(device, ALC_INVALID_DEVICE);
4402 else if(samples < 0 || (samples > 0 && buffer == NULL))
4403 alcSetError(device, ALC_INVALID_VALUE);
4404 else
4406 V0(device->Backend,lock)();
4407 aluMixData(device, buffer, samples);
4408 V0(device->Backend,unlock)();
4410 if(device) ALCdevice_DecRef(device);
4414 /************************************************
4415 * ALC loopback2 functions
4416 ************************************************/
4418 ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order)
4420 ALCboolean ret = ALC_FALSE;
4422 if(!VerifyDevice(&device) || device->Type != Loopback)
4423 alcSetError(device, ALC_INVALID_DEVICE);
4424 else if(order <= 0)
4425 alcSetError(device, ALC_INVALID_VALUE);
4426 else
4428 if(IsValidAmbiLayout(layout) && IsValidAmbiScaling(scaling) && order <= MAX_AMBI_ORDER)
4429 ret = ALC_TRUE;
4431 if(device) ALCdevice_DecRef(device);
4433 return ret;
4436 /************************************************
4437 * ALC DSP pause/resume functions
4438 ************************************************/
4440 /* alcDevicePauseSOFT
4442 * Pause the DSP to stop audio processing.
4444 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4446 if(!VerifyDevice(&device) || device->Type != Playback)
4447 alcSetError(device, ALC_INVALID_DEVICE);
4448 else
4450 almtx_lock(&device->BackendLock);
4451 if((device->Flags&DEVICE_RUNNING))
4452 V0(device->Backend,stop)();
4453 device->Flags &= ~DEVICE_RUNNING;
4454 device->Flags |= DEVICE_PAUSED;
4455 almtx_unlock(&device->BackendLock);
4457 if(device) ALCdevice_DecRef(device);
4460 /* alcDeviceResumeSOFT
4462 * Resume the DSP to restart audio processing.
4464 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4466 if(!VerifyDevice(&device) || device->Type != Playback)
4467 alcSetError(device, ALC_INVALID_DEVICE);
4468 else
4470 almtx_lock(&device->BackendLock);
4471 if((device->Flags&DEVICE_PAUSED))
4473 device->Flags &= ~DEVICE_PAUSED;
4474 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4476 if(V0(device->Backend,start)() != ALC_FALSE)
4477 device->Flags |= DEVICE_RUNNING;
4478 else
4480 alcSetError(device, ALC_INVALID_DEVICE);
4481 V0(device->Backend,lock)();
4482 aluHandleDisconnect(device);
4483 V0(device->Backend,unlock)();
4487 almtx_unlock(&device->BackendLock);
4489 if(device) ALCdevice_DecRef(device);
4493 /************************************************
4494 * ALC HRTF functions
4495 ************************************************/
4497 /* alcGetStringiSOFT
4499 * Gets a string parameter at the given index.
4501 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4503 const ALCchar *str = NULL;
4505 if(!VerifyDevice(&device) || device->Type == Capture)
4506 alcSetError(device, ALC_INVALID_DEVICE);
4507 else switch(paramName)
4509 case ALC_HRTF_SPECIFIER_SOFT:
4510 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4511 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4512 else
4513 alcSetError(device, ALC_INVALID_VALUE);
4514 break;
4516 default:
4517 alcSetError(device, ALC_INVALID_ENUM);
4518 break;
4520 if(device) ALCdevice_DecRef(device);
4522 return str;
4525 /* alcResetDeviceSOFT
4527 * Resets the given device output, using the specified attribute list.
4529 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4531 ALCenum err;
4533 LockLists();
4534 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4536 UnlockLists();
4537 alcSetError(device, ALC_INVALID_DEVICE);
4538 if(device) ALCdevice_DecRef(device);
4539 return ALC_FALSE;
4541 almtx_lock(&device->BackendLock);
4542 UnlockLists();
4544 err = UpdateDeviceParams(device, attribs);
4545 almtx_unlock(&device->BackendLock);
4547 if(err != ALC_NO_ERROR)
4549 alcSetError(device, err);
4550 if(err == ALC_INVALID_DEVICE)
4552 V0(device->Backend,lock)();
4553 aluHandleDisconnect(device);
4554 V0(device->Backend,unlock)();
4556 ALCdevice_DecRef(device);
4557 return ALC_FALSE;
4559 ALCdevice_DecRef(device);
4561 return ALC_TRUE;