Rename al_string_* functions to alstr_*
[openal-soft.git] / Alc / ALc.c
blobf248a998aedf1c36110279c4da86912b15a27cdc
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", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, 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 if(VECTOR_SIZE(device->HrtfList) == 0)
2054 VECTOR_DEINIT(device->HrtfList);
2055 device->HrtfList = EnumerateHrtf(device->DeviceName);
2057 if(VECTOR_SIZE(device->HrtfList) > 0)
2059 device->FmtChans = DevFmtStereo;
2060 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2061 device->Frequency = VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf->sampleRate;
2062 else
2063 device->Frequency = VECTOR_ELEM(device->HrtfList, 0).hrtf->sampleRate;
2064 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2066 else
2068 hrtf_userreq = Hrtf_Default;
2069 hrtf_appreq = Hrtf_Disable;
2070 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2074 else if(hrtf_appreq == Hrtf_Enable)
2076 size_t i = VECTOR_SIZE(device->HrtfList);
2077 /* Loopback device. We don't need to match to a specific HRTF entry
2078 * here. If the requested ID matches, we'll pick that later, if not,
2079 * we'll try to auto-select one anyway. Just make sure one exists
2080 * that'll work.
2082 if(device->FmtChans == DevFmtStereo)
2084 if(VECTOR_SIZE(device->HrtfList) == 0)
2086 VECTOR_DEINIT(device->HrtfList);
2087 device->HrtfList = EnumerateHrtf(device->DeviceName);
2089 for(i = 0;i < VECTOR_SIZE(device->HrtfList);i++)
2091 const struct Hrtf *hrtf = VECTOR_ELEM(device->HrtfList, i).hrtf;
2092 if(hrtf->sampleRate == device->Frequency)
2093 break;
2096 if(i == VECTOR_SIZE(device->HrtfList))
2098 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2099 DevFmtChannelsString(device->FmtChans), device->Frequency);
2100 hrtf_appreq = Hrtf_Disable;
2101 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2105 oldFreq = device->Frequency;
2106 oldChans = device->FmtChans;
2107 oldType = device->FmtType;
2109 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2110 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2111 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2112 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2113 device->UpdateSize, device->NumUpdates
2116 if(V0(device->Backend,reset)() == ALC_FALSE)
2117 return ALC_INVALID_DEVICE;
2119 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2121 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2122 DevFmtChannelsString(device->FmtChans));
2123 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2125 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2128 DevFmtTypeString(device->FmtType));
2129 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2131 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2133 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2134 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2137 if((device->UpdateSize&3) != 0)
2139 if((CPUCapFlags&CPU_CAP_SSE))
2140 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2141 if((CPUCapFlags&CPU_CAP_NEON))
2142 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2145 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2146 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2147 device->Frequency, device->UpdateSize, device->NumUpdates
2150 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2151 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2152 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2154 /* Allocate extra channels for any post-filter output. */
2155 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2156 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2158 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2159 device->Dry.Buffer = al_calloc(16, size);
2160 if(!device->Dry.Buffer)
2162 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2163 return ALC_INVALID_DEVICE;
2166 if(device->RealOut.NumChannels != 0)
2167 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2168 device->FOAOut.NumChannels;
2169 else
2171 device->RealOut.Buffer = device->Dry.Buffer;
2172 device->RealOut.NumChannels = device->Dry.NumChannels;
2175 if(device->FOAOut.NumChannels != 0)
2176 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2177 else
2179 device->FOAOut.Buffer = device->Dry.Buffer;
2180 device->FOAOut.NumChannels = device->Dry.NumChannels;
2183 /* Need to delay returning failure until replacement Send arrays have been
2184 * allocated with the appropriate size.
2186 device->NumAuxSends = new_sends;
2187 update_failed = AL_FALSE;
2188 SetMixerFPUMode(&oldMode);
2189 if(device->DefaultSlot)
2191 ALeffectslot *slot = device->DefaultSlot;
2192 ALeffectState *state = slot->Effect.State;
2194 state->OutBuffer = device->Dry.Buffer;
2195 state->OutChannels = device->Dry.NumChannels;
2196 if(V(state,deviceUpdate)(device) == AL_FALSE)
2197 update_failed = AL_TRUE;
2198 else
2199 UpdateEffectSlotProps(slot);
2202 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2203 while(context)
2205 ALsizei pos;
2207 WriteLock(&context->PropLock);
2208 LockUIntMapRead(&context->EffectSlotMap);
2209 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2211 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2212 ALeffectState *state = slot->Effect.State;
2214 state->OutBuffer = device->Dry.Buffer;
2215 state->OutChannels = device->Dry.NumChannels;
2216 if(V(state,deviceUpdate)(device) == AL_FALSE)
2217 update_failed = AL_TRUE;
2218 else
2219 UpdateEffectSlotProps(slot);
2221 UnlockUIntMapRead(&context->EffectSlotMap);
2223 LockUIntMapRead(&context->SourceMap);
2224 for(pos = 0;pos < context->SourceMap.size;pos++)
2226 ALsource *source = context->SourceMap.values[pos];
2227 struct ALsourceProps *props;
2229 if(old_sends != device->NumAuxSends)
2231 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2232 ALsizei s;
2234 memcpy(sends, source->Send,
2235 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2237 for(s = device->NumAuxSends;s < old_sends;s++)
2239 if(source->Send[s].Slot)
2240 DecrementRef(&source->Send[s].Slot->ref);
2241 source->Send[s].Slot = NULL;
2243 al_free(source->Send);
2244 source->Send = sends;
2245 for(s = old_sends;s < device->NumAuxSends;s++)
2247 source->Send[s].Slot = NULL;
2248 source->Send[s].Gain = 1.0f;
2249 source->Send[s].GainHF = 1.0f;
2250 source->Send[s].HFReference = LOWPASSFREQREF;
2251 source->Send[s].GainLF = 1.0f;
2252 source->Send[s].LFReference = HIGHPASSFREQREF;
2256 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2258 /* Clear any pre-existing source property structs, in case the
2259 * number of auxiliary sends changed. Playing (or paused) sources
2260 * will have updates respecified in UpdateAllSourceProps.
2262 props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
2263 al_free(props);
2265 props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
2266 almemory_order_relaxed);
2267 while(props)
2269 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2270 al_free(props);
2271 props = next;
2274 AllocateVoices(context, context->MaxVoices, old_sends);
2275 for(pos = 0;pos < context->VoiceCount;pos++)
2277 ALvoice *voice = context->Voices[pos];
2278 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2279 continue;
2281 if(device->AvgSpeakerDist > 0.0f)
2283 /* Reinitialize the NFC filters for new parameters. */
2284 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2285 (device->AvgSpeakerDist * device->Frequency);
2286 for(i = 0;i < voice->NumChannels;i++)
2288 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2289 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2290 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2294 UnlockUIntMapRead(&context->SourceMap);
2296 UpdateListenerProps(context);
2297 UpdateAllSourceProps(context);
2298 WriteUnlock(&context->PropLock);
2300 context = context->next;
2302 RestoreFPUMode(&oldMode);
2303 if(update_failed)
2304 return ALC_INVALID_DEVICE;
2306 if(!(device->Flags&DEVICE_PAUSED))
2308 if(V0(device->Backend,start)() == ALC_FALSE)
2309 return ALC_INVALID_DEVICE;
2310 device->Flags |= DEVICE_RUNNING;
2313 return ALC_NO_ERROR;
2316 /* FreeDevice
2318 * Frees the device structure, and destroys any objects the app failed to
2319 * delete. Called once there's no more references on the device.
2321 static ALCvoid FreeDevice(ALCdevice *device)
2323 ALsizei i;
2325 TRACE("%p\n", device);
2327 V0(device->Backend,close)();
2328 DELETE_OBJ(device->Backend);
2329 device->Backend = NULL;
2331 almtx_destroy(&device->BackendLock);
2333 if(device->DefaultSlot)
2335 DeinitEffectSlot(device->DefaultSlot);
2336 device->DefaultSlot = NULL;
2339 if(device->BufferMap.size > 0)
2341 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2342 (device->BufferMap.size==1)?"":"s");
2343 ReleaseALBuffers(device);
2345 ResetUIntMap(&device->BufferMap);
2347 if(device->EffectMap.size > 0)
2349 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2350 (device->EffectMap.size==1)?"":"s");
2351 ReleaseALEffects(device);
2353 ResetUIntMap(&device->EffectMap);
2355 if(device->FilterMap.size > 0)
2357 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2358 (device->FilterMap.size==1)?"":"s");
2359 ReleaseALFilters(device);
2361 ResetUIntMap(&device->FilterMap);
2363 AL_STRING_DEINIT(device->HrtfName);
2364 FreeHrtfList(&device->HrtfList);
2365 al_free(device->Hrtf);
2366 device->Hrtf = NULL;
2368 al_free(device->Bs2b);
2369 device->Bs2b = NULL;
2371 al_free(device->Uhj_Encoder);
2372 device->Uhj_Encoder = NULL;
2374 bformatdec_free(device->AmbiDecoder);
2375 device->AmbiDecoder = NULL;
2377 ambiup_free(device->AmbiUp);
2378 device->AmbiUp = NULL;
2380 al_free(device->ChannelDelay[0].Buffer);
2381 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2383 device->ChannelDelay[i].Gain = 1.0f;
2384 device->ChannelDelay[i].Length = 0;
2385 device->ChannelDelay[i].Buffer = NULL;
2388 AL_STRING_DEINIT(device->DeviceName);
2390 al_free(device->Dry.Buffer);
2391 device->Dry.Buffer = NULL;
2392 device->Dry.NumChannels = 0;
2393 device->FOAOut.Buffer = NULL;
2394 device->FOAOut.NumChannels = 0;
2395 device->RealOut.Buffer = NULL;
2396 device->RealOut.NumChannels = 0;
2398 al_free(device);
2402 void ALCdevice_IncRef(ALCdevice *device)
2404 uint ref;
2405 ref = IncrementRef(&device->ref);
2406 TRACEREF("%p increasing refcount to %u\n", device, ref);
2409 void ALCdevice_DecRef(ALCdevice *device)
2411 uint ref;
2412 ref = DecrementRef(&device->ref);
2413 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2414 if(ref == 0) FreeDevice(device);
2417 /* VerifyDevice
2419 * Checks if the device handle is valid, and increments its ref count if so.
2421 static ALCboolean VerifyDevice(ALCdevice **device)
2423 ALCdevice *tmpDevice;
2425 LockLists();
2426 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2427 while(tmpDevice)
2429 if(tmpDevice == *device)
2431 ALCdevice_IncRef(tmpDevice);
2432 UnlockLists();
2433 return ALC_TRUE;
2435 tmpDevice = tmpDevice->next;
2437 UnlockLists();
2439 *device = NULL;
2440 return ALC_FALSE;
2444 /* InitContext
2446 * Initializes context fields
2448 static ALvoid InitContext(ALCcontext *Context)
2450 ALlistener *listener = Context->Listener;
2451 struct ALeffectslotArray *auxslots;
2453 //Initialise listener
2454 listener->Gain = 1.0f;
2455 listener->MetersPerUnit = 1.0f;
2456 listener->Position[0] = 0.0f;
2457 listener->Position[1] = 0.0f;
2458 listener->Position[2] = 0.0f;
2459 listener->Velocity[0] = 0.0f;
2460 listener->Velocity[1] = 0.0f;
2461 listener->Velocity[2] = 0.0f;
2462 listener->Forward[0] = 0.0f;
2463 listener->Forward[1] = 0.0f;
2464 listener->Forward[2] = -1.0f;
2465 listener->Up[0] = 0.0f;
2466 listener->Up[1] = 1.0f;
2467 listener->Up[2] = 0.0f;
2469 aluMatrixfSet(&listener->Params.Matrix,
2470 1.0f, 0.0f, 0.0f, 0.0f,
2471 0.0f, 1.0f, 0.0f, 0.0f,
2472 0.0f, 0.0f, 1.0f, 0.0f,
2473 0.0f, 0.0f, 0.0f, 1.0f
2475 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2476 listener->Params.Gain = 1.0f;
2477 listener->Params.MetersPerUnit = 1.0f;
2478 listener->Params.DopplerFactor = 1.0f;
2479 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2481 ATOMIC_INIT(&listener->Update, NULL);
2482 ATOMIC_INIT(&listener->FreeList, NULL);
2484 //Validate Context
2485 InitRef(&Context->UpdateCount, 0);
2486 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2487 Context->GainBoost = 1.0f;
2488 RWLockInit(&Context->PropLock);
2489 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2490 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2491 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2493 auxslots = al_calloc(DEF_ALIGN, offsetof(struct ALeffectslotArray, slot[0]));
2494 auxslots->count = 0;
2495 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2497 //Set globals
2498 Context->DistanceModel = DefaultDistanceModel;
2499 Context->SourceDistanceModel = AL_FALSE;
2500 Context->DopplerFactor = 1.0f;
2501 Context->DopplerVelocity = 1.0f;
2502 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2503 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2505 Context->ExtensionList = alExtList;
2509 /* FreeContext
2511 * Cleans up the context, and destroys any remaining objects the app failed to
2512 * delete. Called once there's no more references on the context.
2514 static void FreeContext(ALCcontext *context)
2516 ALlistener *listener = context->Listener;
2517 struct ALeffectslotArray *auxslots;
2518 struct ALlistenerProps *lprops;
2519 size_t count;
2521 TRACE("%p\n", context);
2523 auxslots = ATOMIC_EXCHANGE(struct ALeffectslotArray*, &context->ActiveAuxSlots,
2524 NULL, almemory_order_relaxed);
2525 al_free(auxslots);
2527 if(context->SourceMap.size > 0)
2529 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2530 (context->SourceMap.size==1)?"":"s");
2531 ReleaseALSources(context);
2533 ResetUIntMap(&context->SourceMap);
2535 if(context->EffectSlotMap.size > 0)
2537 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2538 (context->EffectSlotMap.size==1)?"":"s");
2539 ReleaseALAuxiliaryEffectSlots(context);
2541 ResetUIntMap(&context->EffectSlotMap);
2543 al_free(context->Voices);
2544 context->Voices = NULL;
2545 context->VoiceCount = 0;
2546 context->MaxVoices = 0;
2548 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2550 TRACE("Freed unapplied listener update %p\n", lprops);
2551 al_free(lprops);
2553 count = 0;
2554 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2555 while(lprops)
2557 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2558 al_free(lprops);
2559 lprops = next;
2560 ++count;
2562 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2564 ALCdevice_DecRef(context->Device);
2565 context->Device = NULL;
2567 //Invalidate context
2568 memset(context, 0, sizeof(ALCcontext));
2569 al_free(context);
2572 /* ReleaseContext
2574 * Removes the context reference from the given device and removes it from
2575 * being current on the running thread or globally. Returns true if other
2576 * contexts still exist on the device.
2578 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2580 ALCcontext *origctx, *newhead;
2581 bool ret = true;
2583 if(altss_get(LocalContext) == context)
2585 WARN("%p released while current on thread\n", context);
2586 altss_set(LocalContext, NULL);
2587 ALCcontext_DecRef(context);
2590 origctx = context;
2591 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2592 ALCcontext_DecRef(context);
2594 ALCdevice_Lock(device);
2595 origctx = context;
2596 newhead = context->next;
2597 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList, &origctx, newhead))
2599 ALCcontext *volatile*list = &origctx->next;
2600 while(*list)
2602 if(*list == context)
2604 *list = (*list)->next;
2605 break;
2607 list = &(*list)->next;
2610 else
2611 ret = !!newhead;
2612 ALCdevice_Unlock(device);
2614 ALCcontext_DecRef(context);
2615 return ret;
2618 void ALCcontext_IncRef(ALCcontext *context)
2620 uint ref = IncrementRef(&context->ref);
2621 TRACEREF("%p increasing refcount to %u\n", context, ref);
2624 void ALCcontext_DecRef(ALCcontext *context)
2626 uint ref = DecrementRef(&context->ref);
2627 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2628 if(ref == 0) FreeContext(context);
2631 static void ReleaseThreadCtx(void *ptr)
2633 ALCcontext *context = ptr;
2634 uint ref = DecrementRef(&context->ref);
2635 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2636 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2639 /* VerifyContext
2641 * Checks that the given context is valid, and increments its reference count.
2643 static ALCboolean VerifyContext(ALCcontext **context)
2645 ALCdevice *dev;
2647 LockLists();
2648 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2649 while(dev)
2651 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2652 while(ctx)
2654 if(ctx == *context)
2656 ALCcontext_IncRef(ctx);
2657 UnlockLists();
2658 return ALC_TRUE;
2660 ctx = ctx->next;
2662 dev = dev->next;
2664 UnlockLists();
2666 *context = NULL;
2667 return ALC_FALSE;
2671 /* GetContextRef
2673 * Returns the currently active context for this thread, and adds a reference
2674 * without locking it.
2676 ALCcontext *GetContextRef(void)
2678 ALCcontext *context;
2680 context = altss_get(LocalContext);
2681 if(context)
2682 ALCcontext_IncRef(context);
2683 else
2685 LockLists();
2686 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2687 if(context)
2688 ALCcontext_IncRef(context);
2689 UnlockLists();
2692 return context;
2696 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2698 ALCdevice *device = context->Device;
2699 ALsizei num_sends = device->NumAuxSends;
2700 struct ALsourceProps *props;
2701 size_t sizeof_props;
2702 size_t sizeof_voice;
2703 ALvoice **voices;
2704 ALvoice *voice;
2705 ALsizei v = 0;
2706 size_t size;
2708 if(num_voices == context->MaxVoices && num_sends == old_sends)
2709 return;
2711 /* Allocate the voice pointers, voices, and the voices' stored source
2712 * property set (including the dynamically-sized Send[] array) in one
2713 * chunk.
2715 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2716 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2717 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2719 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2720 /* The voice and property objects are stored interleaved since they're
2721 * paired together.
2723 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2724 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2726 if(context->Voices)
2728 ALsizei v_count = mini(context->VoiceCount, num_voices);
2729 for(;v < v_count;v++)
2731 ALsizei s_count = mini(old_sends, num_sends);
2732 ALsizei i;
2734 /* Copy the old voice data and source property set to the new
2735 * storage.
2737 *voice = *(context->Voices[v]);
2738 for(i = 0;i < s_count;i++)
2739 voice->Send[i] = context->Voices[v]->Send[i];
2740 *props = *(context->Voices[v]->Props);
2741 for(i = 0;i < s_count;i++)
2742 props->Send[i] = context->Voices[v]->Props->Send[i];
2744 /* Set this voice's property set pointer and voice reference. */
2745 voice->Props = props;
2746 voices[v] = voice;
2748 /* Increment pointers to the next storage space. */
2749 voice = (ALvoice*)((char*)props + sizeof_props);
2750 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2753 /* Finish setting the voices' property set pointers and references. */
2754 for(;v < num_voices;v++)
2756 voice->Props = props;
2757 voices[v] = voice;
2759 voice = (ALvoice*)((char*)props + sizeof_props);
2760 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2763 al_free(context->Voices);
2764 context->Voices = voices;
2765 context->MaxVoices = num_voices;
2766 context->VoiceCount = mini(context->VoiceCount, num_voices);
2770 /************************************************
2771 * Standard ALC functions
2772 ************************************************/
2774 /* alcGetError
2776 * Return last ALC generated error code for the given device
2778 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2780 ALCenum errorCode;
2782 if(VerifyDevice(&device))
2784 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2785 ALCdevice_DecRef(device);
2787 else
2788 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2790 return errorCode;
2794 /* alcSuspendContext
2796 * Suspends updates for the given context
2798 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2800 if(!SuspendDefers)
2801 return;
2803 if(!VerifyContext(&context))
2804 alcSetError(NULL, ALC_INVALID_CONTEXT);
2805 else
2807 ALCcontext_DeferUpdates(context);
2808 ALCcontext_DecRef(context);
2812 /* alcProcessContext
2814 * Resumes processing updates for the given context
2816 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2818 if(!SuspendDefers)
2819 return;
2821 if(!VerifyContext(&context))
2822 alcSetError(NULL, ALC_INVALID_CONTEXT);
2823 else
2825 ALCcontext_ProcessUpdates(context);
2826 ALCcontext_DecRef(context);
2831 /* alcGetString
2833 * Returns information about the device, and error strings
2835 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2837 const ALCchar *value = NULL;
2839 switch(param)
2841 case ALC_NO_ERROR:
2842 value = alcNoError;
2843 break;
2845 case ALC_INVALID_ENUM:
2846 value = alcErrInvalidEnum;
2847 break;
2849 case ALC_INVALID_VALUE:
2850 value = alcErrInvalidValue;
2851 break;
2853 case ALC_INVALID_DEVICE:
2854 value = alcErrInvalidDevice;
2855 break;
2857 case ALC_INVALID_CONTEXT:
2858 value = alcErrInvalidContext;
2859 break;
2861 case ALC_OUT_OF_MEMORY:
2862 value = alcErrOutOfMemory;
2863 break;
2865 case ALC_DEVICE_SPECIFIER:
2866 value = alcDefaultName;
2867 break;
2869 case ALC_ALL_DEVICES_SPECIFIER:
2870 if(VerifyDevice(&Device))
2872 value = alstr_get_cstr(Device->DeviceName);
2873 ALCdevice_DecRef(Device);
2875 else
2877 ProbeAllDevicesList();
2878 value = alstr_get_cstr(alcAllDevicesList);
2880 break;
2882 case ALC_CAPTURE_DEVICE_SPECIFIER:
2883 if(VerifyDevice(&Device))
2885 value = alstr_get_cstr(Device->DeviceName);
2886 ALCdevice_DecRef(Device);
2888 else
2890 ProbeCaptureDeviceList();
2891 value = alstr_get_cstr(alcCaptureDeviceList);
2893 break;
2895 /* Default devices are always first in the list */
2896 case ALC_DEFAULT_DEVICE_SPECIFIER:
2897 value = alcDefaultName;
2898 break;
2900 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2901 if(alstr_empty(alcAllDevicesList))
2902 ProbeAllDevicesList();
2904 VerifyDevice(&Device);
2906 free(alcDefaultAllDevicesSpecifier);
2907 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
2908 if(!alcDefaultAllDevicesSpecifier)
2909 alcSetError(Device, ALC_OUT_OF_MEMORY);
2911 value = alcDefaultAllDevicesSpecifier;
2912 if(Device) ALCdevice_DecRef(Device);
2913 break;
2915 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2916 if(alstr_empty(alcCaptureDeviceList))
2917 ProbeCaptureDeviceList();
2919 VerifyDevice(&Device);
2921 free(alcCaptureDefaultDeviceSpecifier);
2922 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
2923 if(!alcCaptureDefaultDeviceSpecifier)
2924 alcSetError(Device, ALC_OUT_OF_MEMORY);
2926 value = alcCaptureDefaultDeviceSpecifier;
2927 if(Device) ALCdevice_DecRef(Device);
2928 break;
2930 case ALC_EXTENSIONS:
2931 if(!VerifyDevice(&Device))
2932 value = alcNoDeviceExtList;
2933 else
2935 value = alcExtensionList;
2936 ALCdevice_DecRef(Device);
2938 break;
2940 case ALC_HRTF_SPECIFIER_SOFT:
2941 if(!VerifyDevice(&Device))
2942 alcSetError(NULL, ALC_INVALID_DEVICE);
2943 else
2945 almtx_lock(&Device->BackendLock);
2946 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
2947 almtx_unlock(&Device->BackendLock);
2948 ALCdevice_DecRef(Device);
2950 break;
2952 default:
2953 VerifyDevice(&Device);
2954 alcSetError(Device, ALC_INVALID_ENUM);
2955 if(Device) ALCdevice_DecRef(Device);
2956 break;
2959 return value;
2963 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2965 if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 &&
2966 device->FmtChans <= DevFmtAmbi3)
2967 return 23;
2968 return 17;
2971 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2973 ALCsizei i;
2975 if(size <= 0 || values == NULL)
2977 alcSetError(device, ALC_INVALID_VALUE);
2978 return 0;
2981 if(!device)
2983 switch(param)
2985 case ALC_MAJOR_VERSION:
2986 values[0] = alcMajorVersion;
2987 return 1;
2988 case ALC_MINOR_VERSION:
2989 values[0] = alcMinorVersion;
2990 return 1;
2992 case ALC_ATTRIBUTES_SIZE:
2993 case ALC_ALL_ATTRIBUTES:
2994 case ALC_FREQUENCY:
2995 case ALC_REFRESH:
2996 case ALC_SYNC:
2997 case ALC_MONO_SOURCES:
2998 case ALC_STEREO_SOURCES:
2999 case ALC_CAPTURE_SAMPLES:
3000 case ALC_FORMAT_CHANNELS_SOFT:
3001 case ALC_FORMAT_TYPE_SOFT:
3002 case ALC_AMBISONIC_LAYOUT_SOFT:
3003 case ALC_AMBISONIC_SCALING_SOFT:
3004 case ALC_AMBISONIC_ORDER_SOFT:
3005 alcSetError(NULL, ALC_INVALID_DEVICE);
3006 return 0;
3008 default:
3009 alcSetError(NULL, ALC_INVALID_ENUM);
3010 return 0;
3012 return 0;
3015 if(device->Type == Capture)
3017 switch(param)
3019 case ALC_CAPTURE_SAMPLES:
3020 almtx_lock(&device->BackendLock);
3021 values[0] = V0(device->Backend,availableSamples)();
3022 almtx_unlock(&device->BackendLock);
3023 return 1;
3025 case ALC_CONNECTED:
3026 values[0] = device->Connected;
3027 return 1;
3029 default:
3030 alcSetError(device, ALC_INVALID_ENUM);
3031 return 0;
3033 return 0;
3036 /* render device */
3037 switch(param)
3039 case ALC_MAJOR_VERSION:
3040 values[0] = alcMajorVersion;
3041 return 1;
3043 case ALC_MINOR_VERSION:
3044 values[0] = alcMinorVersion;
3045 return 1;
3047 case ALC_EFX_MAJOR_VERSION:
3048 values[0] = alcEFXMajorVersion;
3049 return 1;
3051 case ALC_EFX_MINOR_VERSION:
3052 values[0] = alcEFXMinorVersion;
3053 return 1;
3055 case ALC_ATTRIBUTES_SIZE:
3056 values[0] = NumAttrsForDevice(device);
3057 return 1;
3059 case ALC_ALL_ATTRIBUTES:
3060 if(size < NumAttrsForDevice(device))
3062 alcSetError(device, ALC_INVALID_VALUE);
3063 return 0;
3066 i = 0;
3067 almtx_lock(&device->BackendLock);
3068 values[i++] = ALC_FREQUENCY;
3069 values[i++] = device->Frequency;
3071 if(device->Type != Loopback)
3073 values[i++] = ALC_REFRESH;
3074 values[i++] = device->Frequency / device->UpdateSize;
3076 values[i++] = ALC_SYNC;
3077 values[i++] = ALC_FALSE;
3079 else
3081 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3083 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3084 values[i++] = device->AmbiLayout;
3086 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3087 values[i++] = device->AmbiScale;
3089 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3090 values[i++] = device->FmtChans-DevFmtAmbi1+1;
3092 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3093 values[i++] = ALC_BFORMAT3D_SOFT;
3095 else
3097 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3098 values[i++] = device->FmtChans;
3101 values[i++] = ALC_FORMAT_TYPE_SOFT;
3102 values[i++] = device->FmtType;
3105 values[i++] = ALC_MONO_SOURCES;
3106 values[i++] = device->NumMonoSources;
3108 values[i++] = ALC_STEREO_SOURCES;
3109 values[i++] = device->NumStereoSources;
3111 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3112 values[i++] = device->NumAuxSends;
3114 values[i++] = ALC_HRTF_SOFT;
3115 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3117 values[i++] = ALC_HRTF_STATUS_SOFT;
3118 values[i++] = device->HrtfStatus;
3119 almtx_unlock(&device->BackendLock);
3121 values[i++] = 0;
3122 return i;
3124 case ALC_FREQUENCY:
3125 values[0] = device->Frequency;
3126 return 1;
3128 case ALC_REFRESH:
3129 if(device->Type == Loopback)
3131 alcSetError(device, ALC_INVALID_DEVICE);
3132 return 0;
3134 almtx_lock(&device->BackendLock);
3135 values[0] = device->Frequency / device->UpdateSize;
3136 almtx_unlock(&device->BackendLock);
3137 return 1;
3139 case ALC_SYNC:
3140 if(device->Type == Loopback)
3142 alcSetError(device, ALC_INVALID_DEVICE);
3143 return 0;
3145 values[0] = ALC_FALSE;
3146 return 1;
3148 case ALC_FORMAT_CHANNELS_SOFT:
3149 if(device->Type != Loopback)
3151 alcSetError(device, ALC_INVALID_DEVICE);
3152 return 0;
3154 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3155 values[0] = ALC_BFORMAT3D_SOFT;
3156 else
3157 values[0] = device->FmtChans;
3158 return 1;
3160 case ALC_FORMAT_TYPE_SOFT:
3161 if(device->Type != Loopback)
3163 alcSetError(device, ALC_INVALID_DEVICE);
3164 return 0;
3166 values[0] = device->FmtType;
3167 return 1;
3169 case ALC_AMBISONIC_LAYOUT_SOFT:
3170 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3171 device->FmtChans <= DevFmtAmbi3))
3173 alcSetError(device, ALC_INVALID_DEVICE);
3174 return 0;
3176 values[0] = device->AmbiLayout;
3177 return 1;
3179 case ALC_AMBISONIC_SCALING_SOFT:
3180 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3181 device->FmtChans <= DevFmtAmbi3))
3183 alcSetError(device, ALC_INVALID_DEVICE);
3184 return 0;
3186 values[0] = device->AmbiScale;
3187 return 1;
3189 case ALC_AMBISONIC_ORDER_SOFT:
3190 if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
3191 device->FmtChans <= DevFmtAmbi3))
3193 alcSetError(device, ALC_INVALID_DEVICE);
3194 return 0;
3196 values[0] = device->FmtChans - DevFmtAmbi1 + 1;
3197 return 1;
3199 case ALC_MONO_SOURCES:
3200 values[0] = device->NumMonoSources;
3201 return 1;
3203 case ALC_STEREO_SOURCES:
3204 values[0] = device->NumStereoSources;
3205 return 1;
3207 case ALC_MAX_AUXILIARY_SENDS:
3208 values[0] = device->NumAuxSends;
3209 return 1;
3211 case ALC_CONNECTED:
3212 values[0] = device->Connected;
3213 return 1;
3215 case ALC_HRTF_SOFT:
3216 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3217 return 1;
3219 case ALC_HRTF_STATUS_SOFT:
3220 values[0] = device->HrtfStatus;
3221 return 1;
3223 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3224 almtx_lock(&device->BackendLock);
3225 FreeHrtfList(&device->HrtfList);
3226 device->HrtfList = EnumerateHrtf(device->DeviceName);
3227 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3228 almtx_unlock(&device->BackendLock);
3229 return 1;
3231 default:
3232 alcSetError(device, ALC_INVALID_ENUM);
3233 return 0;
3235 return 0;
3238 /* alcGetIntegerv
3240 * Returns information about the device and the version of OpenAL
3242 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3244 VerifyDevice(&device);
3245 if(size <= 0 || values == NULL)
3246 alcSetError(device, ALC_INVALID_VALUE);
3247 else
3248 GetIntegerv(device, param, size, values);
3249 if(device) ALCdevice_DecRef(device);
3252 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3254 ALCint *ivals;
3255 ALsizei i;
3257 VerifyDevice(&device);
3258 if(size <= 0 || values == NULL)
3259 alcSetError(device, ALC_INVALID_VALUE);
3260 else if(!device || device->Type == Capture)
3262 ivals = malloc(size * sizeof(ALCint));
3263 size = GetIntegerv(device, pname, size, ivals);
3264 for(i = 0;i < size;i++)
3265 values[i] = ivals[i];
3266 free(ivals);
3268 else /* render device */
3270 ClockLatency clock;
3271 ALuint64 basecount;
3272 ALuint samplecount;
3273 ALuint refcount;
3275 switch(pname)
3277 case ALC_ATTRIBUTES_SIZE:
3278 *values = NumAttrsForDevice(device)+2;
3279 break;
3281 case ALC_ALL_ATTRIBUTES:
3282 if(size < NumAttrsForDevice(device)+2)
3283 alcSetError(device, ALC_INVALID_VALUE);
3284 else
3286 i = 0;
3287 almtx_lock(&device->BackendLock);
3288 values[i++] = ALC_FREQUENCY;
3289 values[i++] = device->Frequency;
3291 if(device->Type != Loopback)
3293 values[i++] = ALC_REFRESH;
3294 values[i++] = device->Frequency / device->UpdateSize;
3296 values[i++] = ALC_SYNC;
3297 values[i++] = ALC_FALSE;
3299 else
3301 if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
3303 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3304 values[i++] = device->AmbiLayout;
3306 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3307 values[i++] = device->AmbiScale;
3309 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3310 values[i++] = device->FmtChans-DevFmtAmbi1+1;
3312 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3313 values[i++] = ALC_BFORMAT3D_SOFT;
3315 else
3317 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3318 values[i++] = device->FmtChans;
3321 values[i++] = ALC_FORMAT_TYPE_SOFT;
3322 values[i++] = device->FmtType;
3325 values[i++] = ALC_MONO_SOURCES;
3326 values[i++] = device->NumMonoSources;
3328 values[i++] = ALC_STEREO_SOURCES;
3329 values[i++] = device->NumStereoSources;
3331 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3332 values[i++] = device->NumAuxSends;
3334 values[i++] = ALC_HRTF_SOFT;
3335 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3337 values[i++] = ALC_HRTF_STATUS_SOFT;
3338 values[i++] = device->HrtfStatus;
3340 clock = V0(device->Backend,getClockLatency)();
3341 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3342 values[i++] = clock.ClockTime;
3344 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3345 values[i++] = clock.Latency;
3346 almtx_unlock(&device->BackendLock);
3348 values[i++] = 0;
3350 break;
3352 case ALC_DEVICE_CLOCK_SOFT:
3353 almtx_lock(&device->BackendLock);
3354 do {
3355 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3356 althrd_yield();
3357 basecount = device->ClockBase;
3358 samplecount = device->SamplesDone;
3359 } while(refcount != ReadRef(&device->MixCount));
3360 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3361 almtx_unlock(&device->BackendLock);
3362 break;
3364 case ALC_DEVICE_LATENCY_SOFT:
3365 almtx_lock(&device->BackendLock);
3366 clock = V0(device->Backend,getClockLatency)();
3367 almtx_unlock(&device->BackendLock);
3368 *values = clock.Latency;
3369 break;
3371 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3372 if(size < 2)
3373 alcSetError(device, ALC_INVALID_VALUE);
3374 else
3376 almtx_lock(&device->BackendLock);
3377 clock = V0(device->Backend,getClockLatency)();
3378 almtx_unlock(&device->BackendLock);
3379 values[0] = clock.ClockTime;
3380 values[1] = clock.Latency;
3382 break;
3384 default:
3385 ivals = malloc(size * sizeof(ALCint));
3386 size = GetIntegerv(device, pname, size, ivals);
3387 for(i = 0;i < size;i++)
3388 values[i] = ivals[i];
3389 free(ivals);
3390 break;
3393 if(device)
3394 ALCdevice_DecRef(device);
3398 /* alcIsExtensionPresent
3400 * Determines if there is support for a particular extension
3402 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3404 ALCboolean bResult = ALC_FALSE;
3406 VerifyDevice(&device);
3408 if(!extName)
3409 alcSetError(device, ALC_INVALID_VALUE);
3410 else
3412 size_t len = strlen(extName);
3413 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3414 while(ptr && *ptr)
3416 if(strncasecmp(ptr, extName, len) == 0 &&
3417 (ptr[len] == '\0' || isspace(ptr[len])))
3419 bResult = ALC_TRUE;
3420 break;
3422 if((ptr=strchr(ptr, ' ')) != NULL)
3424 do {
3425 ++ptr;
3426 } while(isspace(*ptr));
3430 if(device)
3431 ALCdevice_DecRef(device);
3432 return bResult;
3436 /* alcGetProcAddress
3438 * Retrieves the function address for a particular extension function
3440 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3442 ALCvoid *ptr = NULL;
3444 if(!funcName)
3446 VerifyDevice(&device);
3447 alcSetError(device, ALC_INVALID_VALUE);
3448 if(device) ALCdevice_DecRef(device);
3450 else
3452 size_t i = 0;
3453 for(i = 0;i < COUNTOF(alcFunctions);i++)
3455 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3457 ptr = alcFunctions[i].address;
3458 break;
3463 return ptr;
3467 /* alcGetEnumValue
3469 * Get the value for a particular ALC enumeration name
3471 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3473 ALCenum val = 0;
3475 if(!enumName)
3477 VerifyDevice(&device);
3478 alcSetError(device, ALC_INVALID_VALUE);
3479 if(device) ALCdevice_DecRef(device);
3481 else
3483 size_t i = 0;
3484 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3486 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3488 val = alcEnumerations[i].value;
3489 break;
3494 return val;
3498 /* alcCreateContext
3500 * Create and attach a context to the given device.
3502 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3504 ALCcontext *ALContext;
3505 ALfloat valf;
3506 ALCenum err;
3508 /* Explicitly hold the list lock while taking the BackendLock in case the
3509 * device is asynchronously destropyed, to ensure this new context is
3510 * properly cleaned up after being made.
3512 LockLists();
3513 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3515 UnlockLists();
3516 alcSetError(device, ALC_INVALID_DEVICE);
3517 if(device) ALCdevice_DecRef(device);
3518 return NULL;
3520 almtx_lock(&device->BackendLock);
3521 UnlockLists();
3523 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3525 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3526 if(ALContext)
3528 InitRef(&ALContext->ref, 1);
3529 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3531 ALContext->Device = device;
3532 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3534 ALContext->Voices = NULL;
3535 ALContext->MaxVoices = 0;
3536 ALContext->VoiceCount = 0;
3537 AllocateVoices(ALContext, 256, device->NumAuxSends);
3539 if(!ALContext || !ALContext->Voices)
3541 almtx_unlock(&device->BackendLock);
3543 if(ALContext)
3545 al_free(ALContext->Voices);
3546 ALContext->Voices = NULL;
3548 al_free(ALContext);
3549 ALContext = NULL;
3552 alcSetError(device, ALC_OUT_OF_MEMORY);
3553 ALCdevice_DecRef(device);
3554 return NULL;
3557 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3559 almtx_unlock(&device->BackendLock);
3561 al_free(ALContext->Voices);
3562 ALContext->Voices = NULL;
3564 al_free(ALContext);
3565 ALContext = NULL;
3567 alcSetError(device, err);
3568 if(err == ALC_INVALID_DEVICE)
3570 V0(device->Backend,lock)();
3571 aluHandleDisconnect(device);
3572 V0(device->Backend,unlock)();
3574 ALCdevice_DecRef(device);
3575 return NULL;
3578 ALCdevice_IncRef(ALContext->Device);
3579 InitContext(ALContext);
3581 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3583 if(!isfinite(valf))
3584 ERR("volume-adjust must be finite: %f\n", valf);
3585 else
3587 ALfloat db = clampf(valf, -24.0f, 24.0f);
3588 if(db != valf)
3589 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3590 ALContext->GainBoost = powf(10.0f, db/20.0f);
3591 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3594 UpdateListenerProps(ALContext);
3597 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3598 do {
3599 ALContext->next = head;
3600 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3601 &device->ContextList, &head, ALContext) == 0);
3603 almtx_unlock(&device->BackendLock);
3605 ALCdevice_DecRef(device);
3607 TRACE("Created context %p\n", ALContext);
3608 return ALContext;
3611 /* alcDestroyContext
3613 * Remove a context from its device
3615 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3617 ALCdevice *Device;
3619 LockLists();
3620 if(!VerifyContext(&context))
3622 UnlockLists();
3623 alcSetError(NULL, ALC_INVALID_CONTEXT);
3624 return;
3627 Device = context->Device;
3628 if(Device)
3630 almtx_lock(&Device->BackendLock);
3631 if(!ReleaseContext(context, Device))
3633 V0(Device->Backend,stop)();
3634 Device->Flags &= ~DEVICE_RUNNING;
3636 almtx_unlock(&Device->BackendLock);
3638 UnlockLists();
3640 ALCcontext_DecRef(context);
3644 /* alcGetCurrentContext
3646 * Returns the currently active context on the calling thread
3648 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3650 ALCcontext *Context = altss_get(LocalContext);
3651 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3652 return Context;
3655 /* alcGetThreadContext
3657 * Returns the currently active thread-local context
3659 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3661 return altss_get(LocalContext);
3665 /* alcMakeContextCurrent
3667 * Makes the given context the active process-wide context, and removes the
3668 * thread-local context for the calling thread.
3670 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3672 /* context must be valid or NULL */
3673 if(context && !VerifyContext(&context))
3675 alcSetError(NULL, ALC_INVALID_CONTEXT);
3676 return ALC_FALSE;
3678 /* context's reference count is already incremented */
3679 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3680 if(context) ALCcontext_DecRef(context);
3682 if((context=altss_get(LocalContext)) != NULL)
3684 altss_set(LocalContext, NULL);
3685 ALCcontext_DecRef(context);
3688 return ALC_TRUE;
3691 /* alcSetThreadContext
3693 * Makes the given context the active context for the current thread
3695 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3697 ALCcontext *old;
3699 /* context must be valid or NULL */
3700 if(context && !VerifyContext(&context))
3702 alcSetError(NULL, ALC_INVALID_CONTEXT);
3703 return ALC_FALSE;
3705 /* context's reference count is already incremented */
3706 old = altss_get(LocalContext);
3707 altss_set(LocalContext, context);
3708 if(old) ALCcontext_DecRef(old);
3710 return ALC_TRUE;
3714 /* alcGetContextsDevice
3716 * Returns the device that a particular context is attached to
3718 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3720 ALCdevice *Device;
3722 if(!VerifyContext(&Context))
3724 alcSetError(NULL, ALC_INVALID_CONTEXT);
3725 return NULL;
3727 Device = Context->Device;
3728 ALCcontext_DecRef(Context);
3730 return Device;
3734 /* alcOpenDevice
3736 * Opens the named device.
3738 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3740 const ALCchar *fmt;
3741 ALCdevice *device;
3742 ALCenum err;
3743 ALCsizei i;
3745 DO_INITCONFIG();
3747 if(!PlaybackBackend.name)
3749 alcSetError(NULL, ALC_INVALID_VALUE);
3750 return NULL;
3753 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3754 #ifdef _WIN32
3755 /* Some old Windows apps hardcode these expecting OpenAL to use a
3756 * specific audio API, even when they're not enumerated. Creative's
3757 * router effectively ignores them too.
3759 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3760 || strcasecmp(deviceName, "MMSYSTEM") == 0
3761 #endif
3763 deviceName = NULL;
3765 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3766 if(!device)
3768 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3769 return NULL;
3772 //Validate device
3773 InitRef(&device->ref, 1);
3774 device->Connected = ALC_TRUE;
3775 device->Type = Playback;
3776 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3778 device->Flags = 0;
3779 device->Bs2b = NULL;
3780 device->Uhj_Encoder = NULL;
3781 device->Hrtf = NULL;
3782 VECTOR_INIT(device->HrtfList);
3783 AL_STRING_INIT(device->HrtfName);
3784 device->Render_Mode = NormalRender;
3785 AL_STRING_INIT(device->DeviceName);
3786 device->Dry.Buffer = NULL;
3787 device->Dry.NumChannels = 0;
3788 device->FOAOut.Buffer = NULL;
3789 device->FOAOut.NumChannels = 0;
3790 device->RealOut.Buffer = NULL;
3791 device->RealOut.NumChannels = 0;
3792 device->AvgSpeakerDist = 0.0f;
3794 ATOMIC_INIT(&device->ContextList, NULL);
3796 device->ClockBase = 0;
3797 device->SamplesDone = 0;
3799 device->SourcesMax = 256;
3800 device->AuxiliaryEffectSlotMax = 64;
3801 device->NumAuxSends = DEFAULT_SENDS;
3803 InitUIntMap(&device->BufferMap, ~0);
3804 InitUIntMap(&device->EffectMap, ~0);
3805 InitUIntMap(&device->FilterMap, ~0);
3807 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
3809 device->ChannelDelay[i].Gain = 1.0f;
3810 device->ChannelDelay[i].Length = 0;
3811 device->ChannelDelay[i].Buffer = NULL;
3814 //Set output format
3815 device->FmtChans = DevFmtChannelsDefault;
3816 device->FmtType = DevFmtTypeDefault;
3817 device->Frequency = DEFAULT_OUTPUT_RATE;
3818 device->IsHeadphones = AL_FALSE;
3819 device->AmbiLayout = AmbiLayout_Default;
3820 device->AmbiScale = AmbiNorm_Default;
3821 device->NumUpdates = 3;
3822 device->UpdateSize = 1024;
3824 if(!PlaybackBackend.getFactory)
3825 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3826 ALCbackend_Playback);
3827 else
3829 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3830 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3832 if(!device->Backend)
3834 al_free(device);
3835 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3836 return NULL;
3840 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3842 static const struct {
3843 const char name[16];
3844 enum DevFmtChannels chans;
3845 } chanlist[] = {
3846 { "mono", DevFmtMono },
3847 { "stereo", DevFmtStereo },
3848 { "quad", DevFmtQuad },
3849 { "surround51", DevFmtX51 },
3850 { "surround61", DevFmtX61 },
3851 { "surround71", DevFmtX71 },
3852 { "surround51rear", DevFmtX51Rear },
3853 { "ambi1", DevFmtAmbi1 },
3854 { "ambi2", DevFmtAmbi2 },
3855 { "ambi3", DevFmtAmbi3 },
3857 size_t i;
3859 for(i = 0;i < COUNTOF(chanlist);i++)
3861 if(strcasecmp(chanlist[i].name, fmt) == 0)
3863 device->FmtChans = chanlist[i].chans;
3864 device->Flags |= DEVICE_CHANNELS_REQUEST;
3865 break;
3868 if(i == COUNTOF(chanlist))
3869 ERR("Unsupported channels: %s\n", fmt);
3871 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3873 static const struct {
3874 const char name[16];
3875 enum DevFmtType type;
3876 } typelist[] = {
3877 { "int8", DevFmtByte },
3878 { "uint8", DevFmtUByte },
3879 { "int16", DevFmtShort },
3880 { "uint16", DevFmtUShort },
3881 { "int32", DevFmtInt },
3882 { "uint32", DevFmtUInt },
3883 { "float32", DevFmtFloat },
3885 size_t i;
3887 for(i = 0;i < COUNTOF(typelist);i++)
3889 if(strcasecmp(typelist[i].name, fmt) == 0)
3891 device->FmtType = typelist[i].type;
3892 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3893 break;
3896 if(i == COUNTOF(typelist))
3897 ERR("Unsupported sample-type: %s\n", fmt);
3900 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3902 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3903 if(device->Frequency < MIN_OUTPUT_RATE)
3904 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3905 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3908 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3909 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3911 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3912 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3913 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3914 device->UpdateSize = (device->UpdateSize+3)&~3;
3916 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3917 if(device->SourcesMax == 0) device->SourcesMax = 256;
3919 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3920 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3922 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
3923 device->NumAuxSends = clampi(
3924 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3927 device->NumStereoSources = 1;
3928 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3930 // Find a playback device to open
3931 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3933 DELETE_OBJ(device->Backend);
3934 al_free(device);
3935 alcSetError(NULL, err);
3936 return NULL;
3938 almtx_init(&device->BackendLock, almtx_plain);
3940 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3942 if(strcasecmp(fmt, "fuma") == 0)
3944 device->AmbiLayout = AmbiLayout_FuMa;
3945 device->AmbiScale = AmbiNorm_FuMa;
3947 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3949 device->AmbiLayout = AmbiLayout_ACN;
3950 device->AmbiScale = AmbiNorm_SN3D;
3952 else if(strcasecmp(fmt, "acn+n3d") == 0)
3954 device->AmbiLayout = AmbiLayout_ACN;
3955 device->AmbiScale = AmbiNorm_N3D;
3957 else
3958 ERR("Unsupported ambi-format: %s\n", fmt);
3961 if(DefaultEffect.type != AL_EFFECT_NULL)
3963 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3964 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3966 device->DefaultSlot = NULL;
3967 ERR("Failed to initialize the default effect slot\n");
3969 else
3971 aluInitEffectPanning(device->DefaultSlot);
3972 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3974 DeinitEffectSlot(device->DefaultSlot);
3975 device->DefaultSlot = NULL;
3976 ERR("Failed to initialize the default effect\n");
3982 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3983 do {
3984 device->next = head;
3985 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3988 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
3989 return device;
3992 /* alcCloseDevice
3994 * Closes the given device.
3996 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3998 ALCdevice *iter, *origdev;
3999 ALCcontext *ctx;
4001 LockLists();
4002 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4003 do {
4004 if(iter == device)
4005 break;
4006 } while((iter=iter->next) != NULL);
4007 if(!iter || iter->Type == Capture)
4009 alcSetError(iter, ALC_INVALID_DEVICE);
4010 UnlockLists();
4011 return ALC_FALSE;
4013 almtx_lock(&device->BackendLock);
4015 origdev = device;
4016 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4018 ALCdevice *volatile*list = &origdev->next;
4019 while(*list)
4021 if(*list == device)
4023 *list = (*list)->next;
4024 break;
4026 list = &(*list)->next;
4029 UnlockLists();
4031 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4032 while(ctx != NULL)
4034 ALCcontext *next = ctx->next;
4035 WARN("Releasing context %p\n", ctx);
4036 ReleaseContext(ctx, device);
4037 ctx = next;
4039 if((device->Flags&DEVICE_RUNNING))
4040 V0(device->Backend,stop)();
4041 device->Flags &= ~DEVICE_RUNNING;
4042 almtx_unlock(&device->BackendLock);
4044 ALCdevice_DecRef(device);
4046 return ALC_TRUE;
4050 /************************************************
4051 * ALC capture functions
4052 ************************************************/
4053 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4055 ALCdevice *device = NULL;
4056 ALCenum err;
4057 ALCsizei i;
4059 DO_INITCONFIG();
4061 if(!CaptureBackend.name)
4063 alcSetError(NULL, ALC_INVALID_VALUE);
4064 return NULL;
4067 if(samples <= 0)
4069 alcSetError(NULL, ALC_INVALID_VALUE);
4070 return NULL;
4073 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4074 deviceName = NULL;
4076 device = al_calloc(16, sizeof(ALCdevice));
4077 if(!device)
4079 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4080 return NULL;
4083 //Validate device
4084 InitRef(&device->ref, 1);
4085 device->Connected = ALC_TRUE;
4086 device->Type = Capture;
4088 device->Hrtf = NULL;
4089 VECTOR_INIT(device->HrtfList);
4090 AL_STRING_INIT(device->HrtfName);
4092 AL_STRING_INIT(device->DeviceName);
4093 device->Dry.Buffer = NULL;
4094 device->Dry.NumChannels = 0;
4095 device->FOAOut.Buffer = NULL;
4096 device->FOAOut.NumChannels = 0;
4097 device->RealOut.Buffer = NULL;
4098 device->RealOut.NumChannels = 0;
4100 InitUIntMap(&device->BufferMap, ~0);
4101 InitUIntMap(&device->EffectMap, ~0);
4102 InitUIntMap(&device->FilterMap, ~0);
4104 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4106 device->ChannelDelay[i].Gain = 1.0f;
4107 device->ChannelDelay[i].Length = 0;
4108 device->ChannelDelay[i].Buffer = NULL;
4111 if(!CaptureBackend.getFactory)
4112 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
4113 ALCbackend_Capture);
4114 else
4116 ALCbackendFactory *factory = CaptureBackend.getFactory();
4117 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4119 if(!device->Backend)
4121 al_free(device);
4122 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4123 return NULL;
4126 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4127 device->Frequency = frequency;
4129 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4130 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4132 al_free(device);
4133 alcSetError(NULL, ALC_INVALID_ENUM);
4134 return NULL;
4136 device->IsHeadphones = AL_FALSE;
4137 device->AmbiLayout = AmbiLayout_Default;
4138 device->AmbiScale = AmbiNorm_Default;
4140 device->UpdateSize = samples;
4141 device->NumUpdates = 1;
4143 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4145 al_free(device);
4146 alcSetError(NULL, err);
4147 return NULL;
4149 almtx_init(&device->BackendLock, almtx_plain);
4152 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4153 do {
4154 device->next = head;
4155 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4158 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4159 return device;
4162 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4164 ALCdevice *iter, *origdev;
4166 LockLists();
4167 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4168 do {
4169 if(iter == device)
4170 break;
4171 } while((iter=iter->next) != NULL);
4172 if(!iter || iter->Type != Capture)
4174 alcSetError(iter, ALC_INVALID_DEVICE);
4175 UnlockLists();
4176 return ALC_FALSE;
4179 origdev = device;
4180 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
4182 ALCdevice *volatile*list = &origdev->next;
4183 while(*list)
4185 if(*list == device)
4187 *list = (*list)->next;
4188 break;
4190 list = &(*list)->next;
4193 UnlockLists();
4195 ALCdevice_DecRef(device);
4197 return ALC_TRUE;
4200 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4202 if(!VerifyDevice(&device) || device->Type != Capture)
4203 alcSetError(device, ALC_INVALID_DEVICE);
4204 else
4206 almtx_lock(&device->BackendLock);
4207 if(!device->Connected)
4208 alcSetError(device, ALC_INVALID_DEVICE);
4209 else if(!(device->Flags&DEVICE_RUNNING))
4211 if(V0(device->Backend,start)())
4212 device->Flags |= DEVICE_RUNNING;
4213 else
4215 aluHandleDisconnect(device);
4216 alcSetError(device, ALC_INVALID_DEVICE);
4219 almtx_unlock(&device->BackendLock);
4222 if(device) ALCdevice_DecRef(device);
4225 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4227 if(!VerifyDevice(&device) || device->Type != Capture)
4228 alcSetError(device, ALC_INVALID_DEVICE);
4229 else
4231 almtx_lock(&device->BackendLock);
4232 if((device->Flags&DEVICE_RUNNING))
4233 V0(device->Backend,stop)();
4234 device->Flags &= ~DEVICE_RUNNING;
4235 almtx_unlock(&device->BackendLock);
4238 if(device) ALCdevice_DecRef(device);
4241 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4243 if(!VerifyDevice(&device) || device->Type != Capture)
4244 alcSetError(device, ALC_INVALID_DEVICE);
4245 else
4247 ALCenum err = ALC_INVALID_VALUE;
4249 almtx_lock(&device->BackendLock);
4250 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4251 err = V(device->Backend,captureSamples)(buffer, samples);
4252 almtx_unlock(&device->BackendLock);
4254 if(err != ALC_NO_ERROR)
4255 alcSetError(device, err);
4257 if(device) ALCdevice_DecRef(device);
4261 /************************************************
4262 * ALC loopback functions
4263 ************************************************/
4265 /* alcLoopbackOpenDeviceSOFT
4267 * Open a loopback device, for manual rendering.
4269 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4271 ALCbackendFactory *factory;
4272 ALCdevice *device;
4273 ALCsizei i;
4275 DO_INITCONFIG();
4277 /* Make sure the device name, if specified, is us. */
4278 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4280 alcSetError(NULL, ALC_INVALID_VALUE);
4281 return NULL;
4284 device = al_calloc(16, sizeof(ALCdevice));
4285 if(!device)
4287 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4288 return NULL;
4291 //Validate device
4292 InitRef(&device->ref, 1);
4293 device->Connected = ALC_TRUE;
4294 device->Type = Loopback;
4295 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4297 device->Flags = 0;
4298 device->Hrtf = NULL;
4299 VECTOR_INIT(device->HrtfList);
4300 AL_STRING_INIT(device->HrtfName);
4301 device->Bs2b = NULL;
4302 device->Uhj_Encoder = NULL;
4303 device->Render_Mode = NormalRender;
4304 AL_STRING_INIT(device->DeviceName);
4305 device->Dry.Buffer = NULL;
4306 device->Dry.NumChannels = 0;
4307 device->FOAOut.Buffer = NULL;
4308 device->FOAOut.NumChannels = 0;
4309 device->RealOut.Buffer = NULL;
4310 device->RealOut.NumChannels = 0;
4311 device->AvgSpeakerDist = 0.0f;
4313 ATOMIC_INIT(&device->ContextList, NULL);
4315 device->ClockBase = 0;
4316 device->SamplesDone = 0;
4318 device->SourcesMax = 256;
4319 device->AuxiliaryEffectSlotMax = 64;
4320 device->NumAuxSends = DEFAULT_SENDS;
4322 InitUIntMap(&device->BufferMap, ~0);
4323 InitUIntMap(&device->EffectMap, ~0);
4324 InitUIntMap(&device->FilterMap, ~0);
4326 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4328 device->ChannelDelay[i].Gain = 1.0f;
4329 device->ChannelDelay[i].Length = 0;
4330 device->ChannelDelay[i].Buffer = NULL;
4333 factory = ALCloopbackFactory_getFactory();
4334 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4335 if(!device->Backend)
4337 al_free(device);
4338 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4339 return NULL;
4341 almtx_init(&device->BackendLock, almtx_plain);
4343 //Set output format
4344 device->NumUpdates = 0;
4345 device->UpdateSize = 0;
4347 device->Frequency = DEFAULT_OUTPUT_RATE;
4348 device->FmtChans = DevFmtChannelsDefault;
4349 device->FmtType = DevFmtTypeDefault;
4350 device->IsHeadphones = AL_FALSE;
4351 device->AmbiLayout = AmbiLayout_Default;
4352 device->AmbiScale = AmbiNorm_Default;
4354 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4355 if(device->SourcesMax == 0) device->SourcesMax = 256;
4357 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4358 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4360 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4361 device->NumAuxSends = clampi(
4362 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4365 device->NumStereoSources = 1;
4366 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4368 // Open the "backend"
4369 V(device->Backend,open)("Loopback");
4372 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4373 do {
4374 device->next = head;
4375 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4378 TRACE("Created device %p\n", device);
4379 return device;
4382 /* alcIsRenderFormatSupportedSOFT
4384 * Determines if the loopback device supports the given format for rendering.
4386 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4388 ALCboolean ret = ALC_FALSE;
4390 if(!VerifyDevice(&device) || device->Type != Loopback)
4391 alcSetError(device, ALC_INVALID_DEVICE);
4392 else if(freq <= 0)
4393 alcSetError(device, ALC_INVALID_VALUE);
4394 else
4396 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4397 ret = ALC_TRUE;
4399 if(device) ALCdevice_DecRef(device);
4401 return ret;
4404 /* alcRenderSamplesSOFT
4406 * Renders some samples into a buffer, using the format last set by the
4407 * attributes given to alcCreateContext.
4409 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4411 if(!VerifyDevice(&device) || device->Type != Loopback)
4412 alcSetError(device, ALC_INVALID_DEVICE);
4413 else if(samples < 0 || (samples > 0 && buffer == NULL))
4414 alcSetError(device, ALC_INVALID_VALUE);
4415 else
4417 V0(device->Backend,lock)();
4418 aluMixData(device, buffer, samples);
4419 V0(device->Backend,unlock)();
4421 if(device) ALCdevice_DecRef(device);
4425 /************************************************
4426 * ALC loopback2 functions
4427 ************************************************/
4429 ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order)
4431 ALCboolean ret = ALC_FALSE;
4433 if(!VerifyDevice(&device) || device->Type != Loopback)
4434 alcSetError(device, ALC_INVALID_DEVICE);
4435 else if(order <= 0)
4436 alcSetError(device, ALC_INVALID_VALUE);
4437 else
4439 if(IsValidAmbiLayout(layout) && IsValidAmbiScaling(scaling) && order <= MAX_AMBI_ORDER)
4440 ret = ALC_TRUE;
4442 if(device) ALCdevice_DecRef(device);
4444 return ret;
4447 /************************************************
4448 * ALC DSP pause/resume functions
4449 ************************************************/
4451 /* alcDevicePauseSOFT
4453 * Pause the DSP to stop audio processing.
4455 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4457 if(!VerifyDevice(&device) || device->Type != Playback)
4458 alcSetError(device, ALC_INVALID_DEVICE);
4459 else
4461 almtx_lock(&device->BackendLock);
4462 if((device->Flags&DEVICE_RUNNING))
4463 V0(device->Backend,stop)();
4464 device->Flags &= ~DEVICE_RUNNING;
4465 device->Flags |= DEVICE_PAUSED;
4466 almtx_unlock(&device->BackendLock);
4468 if(device) ALCdevice_DecRef(device);
4471 /* alcDeviceResumeSOFT
4473 * Resume the DSP to restart audio processing.
4475 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4477 if(!VerifyDevice(&device) || device->Type != Playback)
4478 alcSetError(device, ALC_INVALID_DEVICE);
4479 else
4481 almtx_lock(&device->BackendLock);
4482 if((device->Flags&DEVICE_PAUSED))
4484 device->Flags &= ~DEVICE_PAUSED;
4485 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4487 if(V0(device->Backend,start)() != ALC_FALSE)
4488 device->Flags |= DEVICE_RUNNING;
4489 else
4491 alcSetError(device, ALC_INVALID_DEVICE);
4492 V0(device->Backend,lock)();
4493 aluHandleDisconnect(device);
4494 V0(device->Backend,unlock)();
4498 almtx_unlock(&device->BackendLock);
4500 if(device) ALCdevice_DecRef(device);
4504 /************************************************
4505 * ALC HRTF functions
4506 ************************************************/
4508 /* alcGetStringiSOFT
4510 * Gets a string parameter at the given index.
4512 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4514 const ALCchar *str = NULL;
4516 if(!VerifyDevice(&device) || device->Type == Capture)
4517 alcSetError(device, ALC_INVALID_DEVICE);
4518 else switch(paramName)
4520 case ALC_HRTF_SPECIFIER_SOFT:
4521 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4522 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4523 else
4524 alcSetError(device, ALC_INVALID_VALUE);
4525 break;
4527 default:
4528 alcSetError(device, ALC_INVALID_ENUM);
4529 break;
4531 if(device) ALCdevice_DecRef(device);
4533 return str;
4536 /* alcResetDeviceSOFT
4538 * Resets the given device output, using the specified attribute list.
4540 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4542 ALCenum err;
4544 LockLists();
4545 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4547 UnlockLists();
4548 alcSetError(device, ALC_INVALID_DEVICE);
4549 if(device) ALCdevice_DecRef(device);
4550 return ALC_FALSE;
4552 almtx_lock(&device->BackendLock);
4553 UnlockLists();
4555 err = UpdateDeviceParams(device, attribs);
4556 almtx_unlock(&device->BackendLock);
4558 if(err != ALC_NO_ERROR)
4560 alcSetError(device, err);
4561 if(err == ALC_INVALID_DEVICE)
4563 V0(device->Backend,lock)();
4564 aluHandleDisconnect(device);
4565 V0(device->Backend,unlock)();
4567 ALCdevice_DecRef(device);
4568 return ALC_FALSE;
4570 ALCdevice_DecRef(device);
4572 return ALC_TRUE;