Correctly handle the attribute array size for alcGetInteger64vSOFT
[openal-soft.git] / Alc / ALc.c
blobe11a2a4e8954f7e67600846129a58f9fb49e6008
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alThunk.h"
36 #include "alSource.h"
37 #include "alBuffer.h"
38 #include "alAuxEffectSlot.h"
39 #include "alError.h"
40 #include "bformatdec.h"
41 #include "alu.h"
43 #include "compat.h"
44 #include "threads.h"
45 #include "alstring.h"
46 #include "almalloc.h"
48 #include "backends/base.h"
51 /************************************************
52 * Backends
53 ************************************************/
54 struct BackendInfo {
55 const char *name;
56 ALCbackendFactory* (*getFactory)(void);
57 ALCboolean (*Init)(BackendFuncs*);
58 void (*Deinit)(void);
59 void (*Probe)(enum DevProbe);
60 BackendFuncs Funcs;
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList[] = {
65 #ifdef HAVE_JACK
66 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
67 #endif
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
70 #endif
71 #ifdef HAVE_ALSA
72 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
73 #endif
74 #ifdef HAVE_COREAUDIO
75 { "core", ALCcoreAudioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
76 #endif
77 #ifdef HAVE_OSS
78 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
79 #endif
80 #ifdef HAVE_SOLARIS
81 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
82 #endif
83 #ifdef HAVE_SNDIO
84 { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
85 #endif
86 #ifdef HAVE_QSA
87 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
88 #endif
89 #ifdef HAVE_MMDEVAPI
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
91 #endif
92 #ifdef HAVE_DSOUND
93 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
94 #endif
95 #ifdef HAVE_WINMM
96 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
97 #endif
98 #ifdef HAVE_PORTAUDIO
99 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
100 #endif
101 #ifdef HAVE_OPENSL
102 { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
103 #endif
105 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #ifdef HAVE_WAVE
107 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
108 #endif
110 static ALsizei BackendListSize = COUNTOF(BackendList);
111 #undef EmptyFuncs
113 static struct BackendInfo PlaybackBackend;
114 static struct BackendInfo CaptureBackend;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar *funcName;
123 ALCvoid *address;
124 } alcFunctions[] = {
125 DECL(alcCreateContext),
126 DECL(alcMakeContextCurrent),
127 DECL(alcProcessContext),
128 DECL(alcSuspendContext),
129 DECL(alcDestroyContext),
130 DECL(alcGetCurrentContext),
131 DECL(alcGetContextsDevice),
132 DECL(alcOpenDevice),
133 DECL(alcCloseDevice),
134 DECL(alcGetError),
135 DECL(alcIsExtensionPresent),
136 DECL(alcGetProcAddress),
137 DECL(alcGetEnumValue),
138 DECL(alcGetString),
139 DECL(alcGetIntegerv),
140 DECL(alcCaptureOpenDevice),
141 DECL(alcCaptureCloseDevice),
142 DECL(alcCaptureStart),
143 DECL(alcCaptureStop),
144 DECL(alcCaptureSamples),
146 DECL(alcSetThreadContext),
147 DECL(alcGetThreadContext),
149 DECL(alcLoopbackOpenDeviceSOFT),
150 DECL(alcIsRenderFormatSupportedSOFT),
151 DECL(alcRenderSamplesSOFT),
153 DECL(alcIsAmbisonicFormatSupportedSOFT),
155 DECL(alcDevicePauseSOFT),
156 DECL(alcDeviceResumeSOFT),
158 DECL(alcGetStringiSOFT),
159 DECL(alcResetDeviceSOFT),
161 DECL(alcGetInteger64vSOFT),
163 DECL(alEnable),
164 DECL(alDisable),
165 DECL(alIsEnabled),
166 DECL(alGetString),
167 DECL(alGetBooleanv),
168 DECL(alGetIntegerv),
169 DECL(alGetFloatv),
170 DECL(alGetDoublev),
171 DECL(alGetBoolean),
172 DECL(alGetInteger),
173 DECL(alGetFloat),
174 DECL(alGetDouble),
175 DECL(alGetError),
176 DECL(alIsExtensionPresent),
177 DECL(alGetProcAddress),
178 DECL(alGetEnumValue),
179 DECL(alListenerf),
180 DECL(alListener3f),
181 DECL(alListenerfv),
182 DECL(alListeneri),
183 DECL(alListener3i),
184 DECL(alListeneriv),
185 DECL(alGetListenerf),
186 DECL(alGetListener3f),
187 DECL(alGetListenerfv),
188 DECL(alGetListeneri),
189 DECL(alGetListener3i),
190 DECL(alGetListeneriv),
191 DECL(alGenSources),
192 DECL(alDeleteSources),
193 DECL(alIsSource),
194 DECL(alSourcef),
195 DECL(alSource3f),
196 DECL(alSourcefv),
197 DECL(alSourcei),
198 DECL(alSource3i),
199 DECL(alSourceiv),
200 DECL(alGetSourcef),
201 DECL(alGetSource3f),
202 DECL(alGetSourcefv),
203 DECL(alGetSourcei),
204 DECL(alGetSource3i),
205 DECL(alGetSourceiv),
206 DECL(alSourcePlayv),
207 DECL(alSourceStopv),
208 DECL(alSourceRewindv),
209 DECL(alSourcePausev),
210 DECL(alSourcePlay),
211 DECL(alSourceStop),
212 DECL(alSourceRewind),
213 DECL(alSourcePause),
214 DECL(alSourceQueueBuffers),
215 DECL(alSourceUnqueueBuffers),
216 DECL(alGenBuffers),
217 DECL(alDeleteBuffers),
218 DECL(alIsBuffer),
219 DECL(alBufferData),
220 DECL(alBufferf),
221 DECL(alBuffer3f),
222 DECL(alBufferfv),
223 DECL(alBufferi),
224 DECL(alBuffer3i),
225 DECL(alBufferiv),
226 DECL(alGetBufferf),
227 DECL(alGetBuffer3f),
228 DECL(alGetBufferfv),
229 DECL(alGetBufferi),
230 DECL(alGetBuffer3i),
231 DECL(alGetBufferiv),
232 DECL(alDopplerFactor),
233 DECL(alDopplerVelocity),
234 DECL(alSpeedOfSound),
235 DECL(alDistanceModel),
237 DECL(alGenFilters),
238 DECL(alDeleteFilters),
239 DECL(alIsFilter),
240 DECL(alFilteri),
241 DECL(alFilteriv),
242 DECL(alFilterf),
243 DECL(alFilterfv),
244 DECL(alGetFilteri),
245 DECL(alGetFilteriv),
246 DECL(alGetFilterf),
247 DECL(alGetFilterfv),
248 DECL(alGenEffects),
249 DECL(alDeleteEffects),
250 DECL(alIsEffect),
251 DECL(alEffecti),
252 DECL(alEffectiv),
253 DECL(alEffectf),
254 DECL(alEffectfv),
255 DECL(alGetEffecti),
256 DECL(alGetEffectiv),
257 DECL(alGetEffectf),
258 DECL(alGetEffectfv),
259 DECL(alGenAuxiliaryEffectSlots),
260 DECL(alDeleteAuxiliaryEffectSlots),
261 DECL(alIsAuxiliaryEffectSlot),
262 DECL(alAuxiliaryEffectSloti),
263 DECL(alAuxiliaryEffectSlotiv),
264 DECL(alAuxiliaryEffectSlotf),
265 DECL(alAuxiliaryEffectSlotfv),
266 DECL(alGetAuxiliaryEffectSloti),
267 DECL(alGetAuxiliaryEffectSlotiv),
268 DECL(alGetAuxiliaryEffectSlotf),
269 DECL(alGetAuxiliaryEffectSlotfv),
271 DECL(alDeferUpdatesSOFT),
272 DECL(alProcessUpdatesSOFT),
274 DECL(alSourcedSOFT),
275 DECL(alSource3dSOFT),
276 DECL(alSourcedvSOFT),
277 DECL(alGetSourcedSOFT),
278 DECL(alGetSource3dSOFT),
279 DECL(alGetSourcedvSOFT),
280 DECL(alSourcei64SOFT),
281 DECL(alSource3i64SOFT),
282 DECL(alSourcei64vSOFT),
283 DECL(alGetSourcei64SOFT),
284 DECL(alGetSource3i64SOFT),
285 DECL(alGetSourcei64vSOFT),
287 DECL(alBufferSamplesSOFT),
288 DECL(alGetBufferSamplesSOFT),
289 DECL(alIsBufferFormatSupportedSOFT),
291 #undef DECL
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar *enumName;
296 ALCenum value;
297 } alcEnumerations[] = {
298 DECL(ALC_INVALID),
299 DECL(ALC_FALSE),
300 DECL(ALC_TRUE),
302 DECL(ALC_MAJOR_VERSION),
303 DECL(ALC_MINOR_VERSION),
304 DECL(ALC_ATTRIBUTES_SIZE),
305 DECL(ALC_ALL_ATTRIBUTES),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
307 DECL(ALC_DEVICE_SPECIFIER),
308 DECL(ALC_ALL_DEVICES_SPECIFIER),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
310 DECL(ALC_EXTENSIONS),
311 DECL(ALC_FREQUENCY),
312 DECL(ALC_REFRESH),
313 DECL(ALC_SYNC),
314 DECL(ALC_MONO_SOURCES),
315 DECL(ALC_STEREO_SOURCES),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
318 DECL(ALC_CAPTURE_SAMPLES),
319 DECL(ALC_CONNECTED),
321 DECL(ALC_EFX_MAJOR_VERSION),
322 DECL(ALC_EFX_MINOR_VERSION),
323 DECL(ALC_MAX_AUXILIARY_SENDS),
325 DECL(ALC_FORMAT_CHANNELS_SOFT),
326 DECL(ALC_FORMAT_TYPE_SOFT),
328 DECL(ALC_MONO_SOFT),
329 DECL(ALC_STEREO_SOFT),
330 DECL(ALC_QUAD_SOFT),
331 DECL(ALC_5POINT1_SOFT),
332 DECL(ALC_6POINT1_SOFT),
333 DECL(ALC_7POINT1_SOFT),
334 DECL(ALC_BFORMAT3D_SOFT),
336 DECL(ALC_BYTE_SOFT),
337 DECL(ALC_UNSIGNED_BYTE_SOFT),
338 DECL(ALC_SHORT_SOFT),
339 DECL(ALC_UNSIGNED_SHORT_SOFT),
340 DECL(ALC_INT_SOFT),
341 DECL(ALC_UNSIGNED_INT_SOFT),
342 DECL(ALC_FLOAT_SOFT),
344 DECL(ALC_HRTF_SOFT),
345 DECL(ALC_DONT_CARE_SOFT),
346 DECL(ALC_HRTF_STATUS_SOFT),
347 DECL(ALC_HRTF_DISABLED_SOFT),
348 DECL(ALC_HRTF_ENABLED_SOFT),
349 DECL(ALC_HRTF_DENIED_SOFT),
350 DECL(ALC_HRTF_REQUIRED_SOFT),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
354 DECL(ALC_HRTF_SPECIFIER_SOFT),
355 DECL(ALC_HRTF_ID_SOFT),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT),
358 DECL(ALC_AMBISONIC_SCALING_SOFT),
359 DECL(ALC_AMBISONIC_ORDER_SOFT),
360 DECL(ALC_ACN_SOFT),
361 DECL(ALC_FUMA_SOFT),
362 DECL(ALC_N3D_SOFT),
363 DECL(ALC_SN3D_SOFT),
365 DECL(ALC_NO_ERROR),
366 DECL(ALC_INVALID_DEVICE),
367 DECL(ALC_INVALID_CONTEXT),
368 DECL(ALC_INVALID_ENUM),
369 DECL(ALC_INVALID_VALUE),
370 DECL(ALC_OUT_OF_MEMORY),
373 DECL(AL_INVALID),
374 DECL(AL_NONE),
375 DECL(AL_FALSE),
376 DECL(AL_TRUE),
378 DECL(AL_SOURCE_RELATIVE),
379 DECL(AL_CONE_INNER_ANGLE),
380 DECL(AL_CONE_OUTER_ANGLE),
381 DECL(AL_PITCH),
382 DECL(AL_POSITION),
383 DECL(AL_DIRECTION),
384 DECL(AL_VELOCITY),
385 DECL(AL_LOOPING),
386 DECL(AL_BUFFER),
387 DECL(AL_GAIN),
388 DECL(AL_MIN_GAIN),
389 DECL(AL_MAX_GAIN),
390 DECL(AL_ORIENTATION),
391 DECL(AL_REFERENCE_DISTANCE),
392 DECL(AL_ROLLOFF_FACTOR),
393 DECL(AL_CONE_OUTER_GAIN),
394 DECL(AL_MAX_DISTANCE),
395 DECL(AL_SEC_OFFSET),
396 DECL(AL_SAMPLE_OFFSET),
397 DECL(AL_BYTE_OFFSET),
398 DECL(AL_SOURCE_TYPE),
399 DECL(AL_STATIC),
400 DECL(AL_STREAMING),
401 DECL(AL_UNDETERMINED),
402 DECL(AL_METERS_PER_UNIT),
403 DECL(AL_LOOP_POINTS_SOFT),
404 DECL(AL_DIRECT_CHANNELS_SOFT),
406 DECL(AL_DIRECT_FILTER),
407 DECL(AL_AUXILIARY_SEND_FILTER),
408 DECL(AL_AIR_ABSORPTION_FACTOR),
409 DECL(AL_ROOM_ROLLOFF_FACTOR),
410 DECL(AL_CONE_OUTER_GAINHF),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
415 DECL(AL_SOURCE_STATE),
416 DECL(AL_INITIAL),
417 DECL(AL_PLAYING),
418 DECL(AL_PAUSED),
419 DECL(AL_STOPPED),
421 DECL(AL_BUFFERS_QUEUED),
422 DECL(AL_BUFFERS_PROCESSED),
424 DECL(AL_FORMAT_MONO8),
425 DECL(AL_FORMAT_MONO16),
426 DECL(AL_FORMAT_MONO_FLOAT32),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
428 DECL(AL_FORMAT_STEREO8),
429 DECL(AL_FORMAT_STEREO16),
430 DECL(AL_FORMAT_STEREO_FLOAT32),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
432 DECL(AL_FORMAT_MONO_IMA4),
433 DECL(AL_FORMAT_STEREO_IMA4),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
436 DECL(AL_FORMAT_QUAD8_LOKI),
437 DECL(AL_FORMAT_QUAD16_LOKI),
438 DECL(AL_FORMAT_QUAD8),
439 DECL(AL_FORMAT_QUAD16),
440 DECL(AL_FORMAT_QUAD32),
441 DECL(AL_FORMAT_51CHN8),
442 DECL(AL_FORMAT_51CHN16),
443 DECL(AL_FORMAT_51CHN32),
444 DECL(AL_FORMAT_61CHN8),
445 DECL(AL_FORMAT_61CHN16),
446 DECL(AL_FORMAT_61CHN32),
447 DECL(AL_FORMAT_71CHN8),
448 DECL(AL_FORMAT_71CHN16),
449 DECL(AL_FORMAT_71CHN32),
450 DECL(AL_FORMAT_REAR8),
451 DECL(AL_FORMAT_REAR16),
452 DECL(AL_FORMAT_REAR32),
453 DECL(AL_FORMAT_MONO_MULAW),
454 DECL(AL_FORMAT_MONO_MULAW_EXT),
455 DECL(AL_FORMAT_STEREO_MULAW),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT),
457 DECL(AL_FORMAT_QUAD_MULAW),
458 DECL(AL_FORMAT_51CHN_MULAW),
459 DECL(AL_FORMAT_61CHN_MULAW),
460 DECL(AL_FORMAT_71CHN_MULAW),
461 DECL(AL_FORMAT_REAR_MULAW),
462 DECL(AL_FORMAT_MONO_ALAW_EXT),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT),
465 DECL(AL_FORMAT_BFORMAT2D_8),
466 DECL(AL_FORMAT_BFORMAT2D_16),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW),
469 DECL(AL_FORMAT_BFORMAT3D_8),
470 DECL(AL_FORMAT_BFORMAT3D_16),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW),
474 DECL(AL_MONO8_SOFT),
475 DECL(AL_MONO16_SOFT),
476 DECL(AL_MONO32F_SOFT),
477 DECL(AL_STEREO8_SOFT),
478 DECL(AL_STEREO16_SOFT),
479 DECL(AL_STEREO32F_SOFT),
480 DECL(AL_QUAD8_SOFT),
481 DECL(AL_QUAD16_SOFT),
482 DECL(AL_QUAD32F_SOFT),
483 DECL(AL_REAR8_SOFT),
484 DECL(AL_REAR16_SOFT),
485 DECL(AL_REAR32F_SOFT),
486 DECL(AL_5POINT1_8_SOFT),
487 DECL(AL_5POINT1_16_SOFT),
488 DECL(AL_5POINT1_32F_SOFT),
489 DECL(AL_6POINT1_8_SOFT),
490 DECL(AL_6POINT1_16_SOFT),
491 DECL(AL_6POINT1_32F_SOFT),
492 DECL(AL_7POINT1_8_SOFT),
493 DECL(AL_7POINT1_16_SOFT),
494 DECL(AL_7POINT1_32F_SOFT),
495 DECL(AL_BFORMAT2D_8_SOFT),
496 DECL(AL_BFORMAT2D_16_SOFT),
497 DECL(AL_BFORMAT2D_32F_SOFT),
498 DECL(AL_BFORMAT3D_8_SOFT),
499 DECL(AL_BFORMAT3D_16_SOFT),
500 DECL(AL_BFORMAT3D_32F_SOFT),
502 DECL(AL_MONO_SOFT),
503 DECL(AL_STEREO_SOFT),
504 DECL(AL_QUAD_SOFT),
505 DECL(AL_REAR_SOFT),
506 DECL(AL_5POINT1_SOFT),
507 DECL(AL_6POINT1_SOFT),
508 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BFORMAT2D_SOFT),
510 DECL(AL_BFORMAT3D_SOFT),
512 DECL(AL_BYTE_SOFT),
513 DECL(AL_UNSIGNED_BYTE_SOFT),
514 DECL(AL_SHORT_SOFT),
515 DECL(AL_UNSIGNED_SHORT_SOFT),
516 DECL(AL_INT_SOFT),
517 DECL(AL_UNSIGNED_INT_SOFT),
518 DECL(AL_FLOAT_SOFT),
519 DECL(AL_DOUBLE_SOFT),
520 DECL(AL_BYTE3_SOFT),
521 DECL(AL_UNSIGNED_BYTE3_SOFT),
522 DECL(AL_MULAW_SOFT),
524 DECL(AL_FREQUENCY),
525 DECL(AL_BITS),
526 DECL(AL_CHANNELS),
527 DECL(AL_SIZE),
528 DECL(AL_INTERNAL_FORMAT_SOFT),
529 DECL(AL_BYTE_LENGTH_SOFT),
530 DECL(AL_SAMPLE_LENGTH_SOFT),
531 DECL(AL_SEC_LENGTH_SOFT),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
535 DECL(AL_SOURCE_RADIUS),
537 DECL(AL_STEREO_ANGLES),
539 DECL(AL_UNUSED),
540 DECL(AL_PENDING),
541 DECL(AL_PROCESSED),
543 DECL(AL_NO_ERROR),
544 DECL(AL_INVALID_NAME),
545 DECL(AL_INVALID_ENUM),
546 DECL(AL_INVALID_VALUE),
547 DECL(AL_INVALID_OPERATION),
548 DECL(AL_OUT_OF_MEMORY),
550 DECL(AL_VENDOR),
551 DECL(AL_VERSION),
552 DECL(AL_RENDERER),
553 DECL(AL_EXTENSIONS),
555 DECL(AL_DOPPLER_FACTOR),
556 DECL(AL_DOPPLER_VELOCITY),
557 DECL(AL_DISTANCE_MODEL),
558 DECL(AL_SPEED_OF_SOUND),
559 DECL(AL_SOURCE_DISTANCE_MODEL),
560 DECL(AL_DEFERRED_UPDATES_SOFT),
561 DECL(AL_GAIN_LIMIT_SOFT),
563 DECL(AL_INVERSE_DISTANCE),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED),
565 DECL(AL_LINEAR_DISTANCE),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED),
567 DECL(AL_EXPONENT_DISTANCE),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
570 DECL(AL_FILTER_TYPE),
571 DECL(AL_FILTER_NULL),
572 DECL(AL_FILTER_LOWPASS),
573 DECL(AL_FILTER_HIGHPASS),
574 DECL(AL_FILTER_BANDPASS),
576 DECL(AL_LOWPASS_GAIN),
577 DECL(AL_LOWPASS_GAINHF),
579 DECL(AL_HIGHPASS_GAIN),
580 DECL(AL_HIGHPASS_GAINLF),
582 DECL(AL_BANDPASS_GAIN),
583 DECL(AL_BANDPASS_GAINHF),
584 DECL(AL_BANDPASS_GAINLF),
586 DECL(AL_EFFECT_TYPE),
587 DECL(AL_EFFECT_NULL),
588 DECL(AL_EFFECT_REVERB),
589 DECL(AL_EFFECT_EAXREVERB),
590 DECL(AL_EFFECT_CHORUS),
591 DECL(AL_EFFECT_DISTORTION),
592 DECL(AL_EFFECT_ECHO),
593 DECL(AL_EFFECT_FLANGER),
594 #if 0
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
596 DECL(AL_EFFECT_VOCAL_MORPHER),
597 DECL(AL_EFFECT_PITCH_SHIFTER),
598 #endif
599 DECL(AL_EFFECT_RING_MODULATOR),
600 #if 0
601 DECL(AL_EFFECT_AUTOWAH),
602 #endif
603 DECL(AL_EFFECT_COMPRESSOR),
604 DECL(AL_EFFECT_EQUALIZER),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
608 DECL(AL_EFFECTSLOT_EFFECT),
609 DECL(AL_EFFECTSLOT_GAIN),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
611 DECL(AL_EFFECTSLOT_NULL),
613 DECL(AL_EAXREVERB_DENSITY),
614 DECL(AL_EAXREVERB_DIFFUSION),
615 DECL(AL_EAXREVERB_GAIN),
616 DECL(AL_EAXREVERB_GAINHF),
617 DECL(AL_EAXREVERB_GAINLF),
618 DECL(AL_EAXREVERB_DECAY_TIME),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
627 DECL(AL_EAXREVERB_ECHO_TIME),
628 DECL(AL_EAXREVERB_ECHO_DEPTH),
629 DECL(AL_EAXREVERB_MODULATION_TIME),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
632 DECL(AL_EAXREVERB_HFREFERENCE),
633 DECL(AL_EAXREVERB_LFREFERENCE),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
637 DECL(AL_REVERB_DENSITY),
638 DECL(AL_REVERB_DIFFUSION),
639 DECL(AL_REVERB_GAIN),
640 DECL(AL_REVERB_GAINHF),
641 DECL(AL_REVERB_DECAY_TIME),
642 DECL(AL_REVERB_DECAY_HFRATIO),
643 DECL(AL_REVERB_REFLECTIONS_GAIN),
644 DECL(AL_REVERB_REFLECTIONS_DELAY),
645 DECL(AL_REVERB_LATE_REVERB_GAIN),
646 DECL(AL_REVERB_LATE_REVERB_DELAY),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
649 DECL(AL_REVERB_DECAY_HFLIMIT),
651 DECL(AL_CHORUS_WAVEFORM),
652 DECL(AL_CHORUS_PHASE),
653 DECL(AL_CHORUS_RATE),
654 DECL(AL_CHORUS_DEPTH),
655 DECL(AL_CHORUS_FEEDBACK),
656 DECL(AL_CHORUS_DELAY),
658 DECL(AL_DISTORTION_EDGE),
659 DECL(AL_DISTORTION_GAIN),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
661 DECL(AL_DISTORTION_EQCENTER),
662 DECL(AL_DISTORTION_EQBANDWIDTH),
664 DECL(AL_ECHO_DELAY),
665 DECL(AL_ECHO_LRDELAY),
666 DECL(AL_ECHO_DAMPING),
667 DECL(AL_ECHO_FEEDBACK),
668 DECL(AL_ECHO_SPREAD),
670 DECL(AL_FLANGER_WAVEFORM),
671 DECL(AL_FLANGER_PHASE),
672 DECL(AL_FLANGER_RATE),
673 DECL(AL_FLANGER_DEPTH),
674 DECL(AL_FLANGER_FEEDBACK),
675 DECL(AL_FLANGER_DELAY),
677 DECL(AL_RING_MODULATOR_FREQUENCY),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
679 DECL(AL_RING_MODULATOR_WAVEFORM),
681 DECL(AL_COMPRESSOR_ONOFF),
683 DECL(AL_EQUALIZER_LOW_GAIN),
684 DECL(AL_EQUALIZER_LOW_CUTOFF),
685 DECL(AL_EQUALIZER_MID1_GAIN),
686 DECL(AL_EQUALIZER_MID1_CENTER),
687 DECL(AL_EQUALIZER_MID1_WIDTH),
688 DECL(AL_EQUALIZER_MID2_GAIN),
689 DECL(AL_EQUALIZER_MID2_CENTER),
690 DECL(AL_EQUALIZER_MID2_WIDTH),
691 DECL(AL_EQUALIZER_HIGH_GAIN),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF),
694 DECL(AL_DEDICATED_GAIN),
696 #undef DECL
698 static const ALCchar alcNoError[] = "No Error";
699 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
706 /************************************************
707 * Global variables
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList;
714 static al_string alcCaptureDeviceList;
716 /* Default is always the first in the list */
717 static ALCchar *alcDefaultAllDevicesSpecifier;
718 static ALCchar *alcCaptureDefaultDeviceSpecifier;
720 /* Default context extensions */
721 static const ALchar alExtList[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
732 /* Thread-local current context */
733 static altss_t LocalContext;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
737 /* Mixing thread piority level */
738 ALint RTPrioLevel;
740 FILE *LogFile;
741 #ifdef _DEBUG
742 enum LogLevel LogLevel = LogWarning;
743 #else
744 enum LogLevel LogLevel = LogError;
745 #endif
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError = ALC_FALSE;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
757 * updates.
759 static ALCboolean SuspendDefers = ALC_TRUE;
762 /************************************************
763 * ALC information
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion = 1;
774 static const ALCint alcMinorVersion = 1;
776 static const ALCint alcEFXMajorVersion = 1;
777 static const ALCint alcEFXMinorVersion = 0;
780 /************************************************
781 * Device lists
782 ************************************************/
783 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
785 static almtx_t ListLock;
786 static inline void LockLists(void)
788 int ret = almtx_lock(&ListLock);
789 assert(ret == althrd_success);
791 static inline void UnlockLists(void)
793 int ret = almtx_unlock(&ListLock);
794 assert(ret == althrd_success);
797 /************************************************
798 * Library initialization
799 ************************************************/
800 #if defined(_WIN32)
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
808 switch(reason)
810 case DLL_PROCESS_ATTACH:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
813 (WCHAR*)hModule, &hModule);
814 alc_init();
815 break;
817 case DLL_THREAD_DETACH:
818 break;
820 case DLL_PROCESS_DETACH:
821 if(!lpReserved)
822 alc_deinit();
823 else
824 alc_deinit_safe();
825 break;
827 return TRUE;
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
835 static void alc_constructor(void)
837 atexit(alc_destructor);
838 alc_init();
841 static void alc_destructor(void)
843 alc_deinit();
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor));
847 static void alc_deinit(void) __attribute__((destructor));
848 #else
849 #error "No static initialization available on this platform!"
850 #endif
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor));
855 static void alc_deinit(void) __attribute__((destructor));
857 #else
858 #error "No global initialization available on this platform!"
859 #endif
861 static void ReleaseThreadCtx(void *ptr);
862 static void alc_init(void)
864 const char *str;
865 int ret;
867 LogFile = stderr;
869 AL_STRING_INIT(alcAllDevicesList);
870 AL_STRING_INIT(alcCaptureDeviceList);
872 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
874 ConeScale *= 0.5f;
876 str = getenv("__ALSOFT_REVERSE_Z");
877 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
878 ZScale *= -1.0f;
880 ret = altss_create(&LocalContext, ReleaseThreadCtx);
881 assert(ret == althrd_success);
883 ret = almtx_init(&ListLock, almtx_recursive);
884 assert(ret == althrd_success);
886 ThunkInit();
889 static void alc_initconfig(void)
891 const char *devs, *str;
892 ALuint capfilter;
893 float valf;
894 int i, n;
896 str = getenv("ALSOFT_LOGLEVEL");
897 if(str)
899 long lvl = strtol(str, NULL, 0);
900 if(lvl >= NoLog && lvl <= LogRef)
901 LogLevel = lvl;
904 str = getenv("ALSOFT_LOGFILE");
905 if(str && str[0])
907 FILE *logfile = al_fopen(str, "wt");
908 if(logfile) LogFile = logfile;
909 else ERR("Failed to open log file '%s'\n", str);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
913 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
915 char buf[1024] = "";
916 int len = 0;
918 if(BackendListSize > 0)
919 len += snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
920 for(i = 1;i < BackendListSize;i++)
921 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
922 TRACE("Supported backends: %s\n", buf);
924 ReadALConfig();
926 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
927 if(str && *str)
929 if(strcasecmp(str, "ignore") == 0)
931 SuspendDefers = ALC_FALSE;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
934 else
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
938 capfilter = 0;
939 #if defined(HAVE_SSE4_1)
940 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
941 #elif defined(HAVE_SSE3)
942 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
943 #elif defined(HAVE_SSE2)
944 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
945 #elif defined(HAVE_SSE)
946 capfilter |= CPU_CAP_SSE;
947 #endif
948 #ifdef HAVE_NEON
949 capfilter |= CPU_CAP_NEON;
950 #endif
951 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
953 if(strcasecmp(str, "all") == 0)
954 capfilter = 0;
955 else
957 size_t len;
958 const char *next = str;
960 do {
961 str = next;
962 while(isspace(str[0]))
963 str++;
964 next = strchr(str, ',');
966 if(!str[0] || str[0] == ',')
967 continue;
969 len = (next ? ((size_t)(next-str)) : strlen(str));
970 while(len > 0 && isspace(str[len-1]))
971 len--;
972 if(len == 3 && strncasecmp(str, "sse", len) == 0)
973 capfilter &= ~CPU_CAP_SSE;
974 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
975 capfilter &= ~CPU_CAP_SSE2;
976 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
977 capfilter &= ~CPU_CAP_SSE3;
978 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
979 capfilter &= ~CPU_CAP_SSE4_1;
980 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
981 capfilter &= ~CPU_CAP_NEON;
982 else
983 WARN("Invalid CPU extension \"%s\"\n", str);
984 } while(next++);
987 FillCPUCaps(capfilter);
989 #ifdef _WIN32
990 RTPrioLevel = 1;
991 #else
992 RTPrioLevel = 0;
993 #endif
994 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
996 aluInitMixer();
998 str = getenv("ALSOFT_TRAP_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1001 TrapALError = AL_TRUE;
1002 TrapALCError = AL_TRUE;
1004 else
1006 str = getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1008 TrapALError = AL_TRUE;
1009 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1011 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1013 TrapALCError = ALC_TRUE;
1014 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1017 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1018 ReverbBoost *= powf(10.0f, valf / 20.0f);
1020 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1022 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1023 ConfigValueStr(NULL, NULL, "drivers", &devs))
1025 int n;
1026 size_t len;
1027 const char *next = devs;
1028 int endlist, delitem;
1030 i = 0;
1031 do {
1032 devs = next;
1033 while(isspace(devs[0]))
1034 devs++;
1035 next = strchr(devs, ',');
1037 delitem = (devs[0] == '-');
1038 if(devs[0] == '-') devs++;
1040 if(!devs[0] || devs[0] == ',')
1042 endlist = 0;
1043 continue;
1045 endlist = 1;
1047 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1048 while(len > 0 && isspace(devs[len-1]))
1049 len--;
1050 for(n = i;n < BackendListSize;n++)
1052 if(len == strlen(BackendList[n].name) &&
1053 strncmp(BackendList[n].name, devs, len) == 0)
1055 if(delitem)
1057 for(;n+1 < BackendListSize;n++)
1058 BackendList[n] = BackendList[n+1];
1059 BackendListSize--;
1061 else
1063 struct BackendInfo Bkp = BackendList[n];
1064 for(;n > i;n--)
1065 BackendList[n] = BackendList[n-1];
1066 BackendList[n] = Bkp;
1068 i++;
1070 break;
1073 } while(next++);
1075 if(endlist)
1076 BackendListSize = i;
1079 for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1081 if(BackendList[i].getFactory)
1083 ALCbackendFactory *factory = BackendList[i].getFactory();
1084 if(!V0(factory,init)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1087 continue;
1090 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1091 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1093 PlaybackBackend = BackendList[i];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1096 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1098 CaptureBackend = BackendList[i];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1102 continue;
1105 if(!BackendList[i].Init(&BackendList[i].Funcs))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1108 continue;
1111 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1112 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1114 PlaybackBackend = BackendList[i];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1117 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1119 CaptureBackend = BackendList[i];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1124 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1125 V0(factory,init)();
1128 if(!PlaybackBackend.name)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend.name)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1135 size_t len;
1136 const char *next = str;
1138 do {
1139 str = next;
1140 next = strchr(str, ',');
1142 if(!str[0] || next == str)
1143 continue;
1145 len = (next ? ((size_t)(next-str)) : strlen(str));
1146 for(n = 0;EffectList[n].name;n++)
1148 if(len == strlen(EffectList[n].name) &&
1149 strncmp(EffectList[n].name, str, len) == 0)
1150 DisabledEffects[EffectList[n].type] = AL_TRUE;
1152 } while(next++);
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect);
1158 str = getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1160 LoadReverbPreset(str, &DefaultEffect);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1164 #ifdef __ANDROID__
1165 #include <jni.h>
1167 static JavaVM *gJavaVM;
1168 static pthread_key_t gJVMThreadKey;
1170 static void CleanupJNIEnv(void* UNUSED(ptr))
1172 JCALL0(gJavaVM,DetachCurrentThread)();
1175 void *Android_GetJNIEnv(void)
1177 if(!gJavaVM)
1179 WARN("gJavaVM is NULL!\n");
1180 return NULL;
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1194 * is a no-op.
1196 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1197 if(!env)
1199 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1200 if(status < 0)
1202 ERR("Failed to attach current thread\n");
1203 return NULL;
1205 pthread_setspecific(gJVMThreadKey, env);
1207 return env;
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1213 void *env;
1214 int err;
1216 gJavaVM = jvm;
1217 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1220 return JNI_ERR;
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err);
1228 pthread_setspecific(gJVMThreadKey, env);
1229 return JNI_VERSION_1_4;
1232 #endif
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1240 ALCdevice *dev;
1242 AL_STRING_DEINIT(alcAllDevicesList);
1243 AL_STRING_DEINIT(alcCaptureDeviceList);
1245 free(alcDefaultAllDevicesSpecifier);
1246 alcDefaultAllDevicesSpecifier = NULL;
1247 free(alcCaptureDefaultDeviceSpecifier);
1248 alcCaptureDefaultDeviceSpecifier = NULL;
1250 if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&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 DevFmtAmbi3D: return "Ambisonic 3D";
1372 return "(unknown channels)";
1375 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
1376 ALsizei BytesFromDevFmt(enum DevFmtType type)
1378 switch(type)
1380 case DevFmtByte: return sizeof(ALbyte);
1381 case DevFmtUByte: return sizeof(ALubyte);
1382 case DevFmtShort: return sizeof(ALshort);
1383 case DevFmtUShort: return sizeof(ALushort);
1384 case DevFmtInt: return sizeof(ALint);
1385 case DevFmtUInt: return sizeof(ALuint);
1386 case DevFmtFloat: return sizeof(ALfloat);
1388 return 0;
1390 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
1392 switch(chans)
1394 case DevFmtMono: return 1;
1395 case DevFmtStereo: return 2;
1396 case DevFmtQuad: return 4;
1397 case DevFmtX51: return 6;
1398 case DevFmtX51Rear: return 6;
1399 case DevFmtX61: return 7;
1400 case DevFmtX71: return 8;
1401 case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
1402 (ambiorder == 2) ? 9 :
1403 (ambiorder == 1) ? 4 : 1;
1405 return 0;
1408 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1409 enum DevFmtType *type)
1411 static const struct {
1412 ALenum format;
1413 enum DevFmtChannels channels;
1414 enum DevFmtType type;
1415 } list[] = {
1416 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1417 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1418 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1420 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1421 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1422 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1424 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1425 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1426 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1428 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1429 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1430 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1432 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1433 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1434 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1436 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1437 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1438 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1440 ALuint i;
1442 for(i = 0;i < COUNTOF(list);i++)
1444 if(list[i].format == format)
1446 *chans = list[i].channels;
1447 *type = list[i].type;
1448 return AL_TRUE;
1452 return AL_FALSE;
1455 static ALCboolean IsValidALCType(ALCenum type)
1457 switch(type)
1459 case ALC_BYTE_SOFT:
1460 case ALC_UNSIGNED_BYTE_SOFT:
1461 case ALC_SHORT_SOFT:
1462 case ALC_UNSIGNED_SHORT_SOFT:
1463 case ALC_INT_SOFT:
1464 case ALC_UNSIGNED_INT_SOFT:
1465 case ALC_FLOAT_SOFT:
1466 return ALC_TRUE;
1468 return ALC_FALSE;
1471 static ALCboolean IsValidALCChannels(ALCenum channels)
1473 switch(channels)
1475 case ALC_MONO_SOFT:
1476 case ALC_STEREO_SOFT:
1477 case ALC_QUAD_SOFT:
1478 case ALC_5POINT1_SOFT:
1479 case ALC_6POINT1_SOFT:
1480 case ALC_7POINT1_SOFT:
1481 case ALC_BFORMAT3D_SOFT:
1482 return ALC_TRUE;
1484 return ALC_FALSE;
1487 static ALCboolean IsValidAmbiLayout(ALCenum layout)
1489 switch(layout)
1491 case ALC_ACN_SOFT:
1492 case ALC_FUMA_SOFT:
1493 return ALC_TRUE;
1495 return ALC_FALSE;
1498 static ALCboolean IsValidAmbiScaling(ALCenum scaling)
1500 switch(scaling)
1502 case ALC_N3D_SOFT:
1503 case ALC_SN3D_SOFT:
1504 case ALC_FUMA_SOFT:
1505 return ALC_TRUE;
1507 return ALC_FALSE;
1510 /************************************************
1511 * Miscellaneous ALC helpers
1512 ************************************************/
1514 void ALCdevice_Lock(ALCdevice *device)
1516 V0(device->Backend,lock)();
1519 void ALCdevice_Unlock(ALCdevice *device)
1521 V0(device->Backend,unlock)();
1525 /* SetDefaultWFXChannelOrder
1527 * Sets the default channel order used by WaveFormatEx.
1529 void SetDefaultWFXChannelOrder(ALCdevice *device)
1531 ALsizei i;
1533 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1534 device->RealOut.ChannelName[i] = InvalidChannel;
1536 switch(device->FmtChans)
1538 case DevFmtMono:
1539 device->RealOut.ChannelName[0] = FrontCenter;
1540 break;
1541 case DevFmtStereo:
1542 device->RealOut.ChannelName[0] = FrontLeft;
1543 device->RealOut.ChannelName[1] = FrontRight;
1544 break;
1545 case DevFmtQuad:
1546 device->RealOut.ChannelName[0] = FrontLeft;
1547 device->RealOut.ChannelName[1] = FrontRight;
1548 device->RealOut.ChannelName[2] = BackLeft;
1549 device->RealOut.ChannelName[3] = BackRight;
1550 break;
1551 case DevFmtX51:
1552 device->RealOut.ChannelName[0] = FrontLeft;
1553 device->RealOut.ChannelName[1] = FrontRight;
1554 device->RealOut.ChannelName[2] = FrontCenter;
1555 device->RealOut.ChannelName[3] = LFE;
1556 device->RealOut.ChannelName[4] = SideLeft;
1557 device->RealOut.ChannelName[5] = SideRight;
1558 break;
1559 case DevFmtX51Rear:
1560 device->RealOut.ChannelName[0] = FrontLeft;
1561 device->RealOut.ChannelName[1] = FrontRight;
1562 device->RealOut.ChannelName[2] = FrontCenter;
1563 device->RealOut.ChannelName[3] = LFE;
1564 device->RealOut.ChannelName[4] = BackLeft;
1565 device->RealOut.ChannelName[5] = BackRight;
1566 break;
1567 case DevFmtX61:
1568 device->RealOut.ChannelName[0] = FrontLeft;
1569 device->RealOut.ChannelName[1] = FrontRight;
1570 device->RealOut.ChannelName[2] = FrontCenter;
1571 device->RealOut.ChannelName[3] = LFE;
1572 device->RealOut.ChannelName[4] = BackCenter;
1573 device->RealOut.ChannelName[5] = SideLeft;
1574 device->RealOut.ChannelName[6] = SideRight;
1575 break;
1576 case DevFmtX71:
1577 device->RealOut.ChannelName[0] = FrontLeft;
1578 device->RealOut.ChannelName[1] = FrontRight;
1579 device->RealOut.ChannelName[2] = FrontCenter;
1580 device->RealOut.ChannelName[3] = LFE;
1581 device->RealOut.ChannelName[4] = BackLeft;
1582 device->RealOut.ChannelName[5] = BackRight;
1583 device->RealOut.ChannelName[6] = SideLeft;
1584 device->RealOut.ChannelName[7] = SideRight;
1585 break;
1586 case DevFmtAmbi3D:
1587 device->RealOut.ChannelName[0] = Aux0;
1588 if(device->AmbiOrder > 0)
1590 device->RealOut.ChannelName[1] = Aux1;
1591 device->RealOut.ChannelName[2] = Aux2;
1592 device->RealOut.ChannelName[3] = Aux3;
1594 if(device->AmbiOrder > 1)
1596 device->RealOut.ChannelName[4] = Aux4;
1597 device->RealOut.ChannelName[5] = Aux5;
1598 device->RealOut.ChannelName[6] = Aux6;
1599 device->RealOut.ChannelName[7] = Aux7;
1600 device->RealOut.ChannelName[8] = Aux8;
1602 if(device->AmbiOrder > 2)
1604 device->RealOut.ChannelName[9] = Aux9;
1605 device->RealOut.ChannelName[10] = Aux10;
1606 device->RealOut.ChannelName[11] = Aux11;
1607 device->RealOut.ChannelName[12] = Aux12;
1608 device->RealOut.ChannelName[13] = Aux13;
1609 device->RealOut.ChannelName[14] = Aux14;
1610 device->RealOut.ChannelName[15] = Aux15;
1612 break;
1616 /* SetDefaultChannelOrder
1618 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1620 void SetDefaultChannelOrder(ALCdevice *device)
1622 ALsizei i;
1624 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1625 device->RealOut.ChannelName[i] = InvalidChannel;
1627 switch(device->FmtChans)
1629 case DevFmtX51Rear:
1630 device->RealOut.ChannelName[0] = FrontLeft;
1631 device->RealOut.ChannelName[1] = FrontRight;
1632 device->RealOut.ChannelName[2] = BackLeft;
1633 device->RealOut.ChannelName[3] = BackRight;
1634 device->RealOut.ChannelName[4] = FrontCenter;
1635 device->RealOut.ChannelName[5] = LFE;
1636 return;
1637 case DevFmtX71:
1638 device->RealOut.ChannelName[0] = FrontLeft;
1639 device->RealOut.ChannelName[1] = FrontRight;
1640 device->RealOut.ChannelName[2] = BackLeft;
1641 device->RealOut.ChannelName[3] = BackRight;
1642 device->RealOut.ChannelName[4] = FrontCenter;
1643 device->RealOut.ChannelName[5] = LFE;
1644 device->RealOut.ChannelName[6] = SideLeft;
1645 device->RealOut.ChannelName[7] = SideRight;
1646 return;
1648 /* Same as WFX order */
1649 case DevFmtMono:
1650 case DevFmtStereo:
1651 case DevFmtQuad:
1652 case DevFmtX51:
1653 case DevFmtX61:
1654 case DevFmtAmbi3D:
1655 SetDefaultWFXChannelOrder(device);
1656 break;
1660 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1663 /* ALCcontext_DeferUpdates
1665 * Defers/suspends updates for the given context's listener and sources. This
1666 * does *NOT* stop mixing, but rather prevents certain property changes from
1667 * taking effect.
1669 void ALCcontext_DeferUpdates(ALCcontext *context)
1671 ATOMIC_STORE_SEQ(&context->DeferUpdates, AL_TRUE);
1674 /* ALCcontext_ProcessUpdates
1676 * Resumes update processing after being deferred.
1678 void ALCcontext_ProcessUpdates(ALCcontext *context)
1680 ReadLock(&context->PropLock);
1681 if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE))
1683 /* Tell the mixer to stop applying updates, then wait for any active
1684 * updating to finish, before providing updates.
1686 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_TRUE);
1687 while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
1688 althrd_yield();
1690 UpdateListenerProps(context);
1691 UpdateAllEffectSlotProps(context);
1692 UpdateAllSourceProps(context);
1694 /* Now with all updates declared, let the mixer continue applying them
1695 * so they all happen at once.
1697 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1699 ReadUnlock(&context->PropLock);
1703 /* alcSetError
1705 * Stores the latest ALC device error
1707 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1709 WARN("Error generated on device %p, code 0x%04x\n", device, errorCode);
1710 if(TrapALCError)
1712 #ifdef _WIN32
1713 /* DebugBreak() will cause an exception if there is no debugger */
1714 if(IsDebuggerPresent())
1715 DebugBreak();
1716 #elif defined(SIGTRAP)
1717 raise(SIGTRAP);
1718 #endif
1721 if(device)
1722 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1723 else
1724 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1728 /* UpdateClockBase
1730 * Updates the device's base clock time with however many samples have been
1731 * done. This is used so frequency changes on the device don't cause the time
1732 * to jump forward or back. Must not be called while the device is running/
1733 * mixing.
1735 static inline void UpdateClockBase(ALCdevice *device)
1737 IncrementRef(&device->MixCount);
1738 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1739 device->SamplesDone = 0;
1740 IncrementRef(&device->MixCount);
1743 /* UpdateDeviceParams
1745 * Updates device parameters according to the attribute list (caller is
1746 * responsible for holding the list lock).
1748 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1750 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1751 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1752 const ALsizei old_sends = device->NumAuxSends;
1753 ALsizei new_sends = device->NumAuxSends;
1754 enum DevFmtChannels oldChans;
1755 enum DevFmtType oldType;
1756 ALboolean update_failed;
1757 ALCsizei hrtf_id = -1;
1758 ALCcontext *context;
1759 ALCuint oldFreq;
1760 FPUCtl oldMode;
1761 size_t size;
1762 ALCsizei i;
1764 // Check for attributes
1765 if(device->Type == Loopback)
1767 ALCsizei numMono, numStereo, numSends;
1768 ALCenum alayout = AL_NONE;
1769 ALCenum ascale = AL_NONE;
1770 ALCenum schans = AL_NONE;
1771 ALCenum stype = AL_NONE;
1772 ALCsizei attrIdx = 0;
1773 ALCsizei aorder = 0;
1774 ALCuint freq = 0;
1776 if(!attrList)
1778 WARN("Missing attributes for loopback device\n");
1779 return ALC_INVALID_VALUE;
1782 numMono = device->NumMonoSources;
1783 numStereo = device->NumStereoSources;
1784 numSends = old_sends;
1786 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1787 while(attrList[attrIdx])
1789 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1791 schans = attrList[attrIdx + 1];
1792 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans);
1793 if(!IsValidALCChannels(schans))
1794 return ALC_INVALID_VALUE;
1797 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1799 stype = attrList[attrIdx + 1];
1800 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype);
1801 if(!IsValidALCType(stype))
1802 return ALC_INVALID_VALUE;
1805 if(attrList[attrIdx] == ALC_FREQUENCY)
1807 freq = attrList[attrIdx + 1];
1808 TRACE_ATTR(ALC_FREQUENCY, freq);
1809 if(freq < MIN_OUTPUT_RATE)
1810 return ALC_INVALID_VALUE;
1813 if(attrList[attrIdx] == ALC_AMBISONIC_LAYOUT_SOFT)
1815 alayout = attrList[attrIdx + 1];
1816 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout);
1817 if(!IsValidAmbiLayout(alayout))
1818 return ALC_INVALID_VALUE;
1821 if(attrList[attrIdx] == ALC_AMBISONIC_SCALING_SOFT)
1823 ascale = attrList[attrIdx + 1];
1824 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale);
1825 if(!IsValidAmbiScaling(ascale))
1826 return ALC_INVALID_VALUE;
1829 if(attrList[attrIdx] == ALC_AMBISONIC_ORDER_SOFT)
1831 aorder = attrList[attrIdx + 1];
1832 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder);
1833 if(aorder < 1 || aorder > MAX_AMBI_ORDER)
1834 return ALC_INVALID_VALUE;
1837 if(attrList[attrIdx] == ALC_MONO_SOURCES)
1839 numMono = attrList[attrIdx + 1];
1840 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1841 numMono = maxi(numMono, 0);
1844 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1846 numStereo = attrList[attrIdx + 1];
1847 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1848 numStereo = maxi(numStereo, 0);
1851 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1853 numSends = attrList[attrIdx + 1];
1854 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1855 numSends = clampi(numSends, 0, MAX_SENDS);
1858 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1860 ALCint val = attrList[attrIdx + 1];
1861 TRACE_ATTR(ALC_HRTF_SOFT, val);
1862 if(val == ALC_FALSE)
1863 hrtf_appreq = Hrtf_Disable;
1864 else if(val == ALC_TRUE)
1865 hrtf_appreq = Hrtf_Enable;
1866 else
1867 hrtf_appreq = Hrtf_Default;
1870 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1872 hrtf_id = attrList[attrIdx + 1];
1873 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1876 attrIdx += 2;
1878 #undef TRACE_ATTR
1880 if(!schans || !stype || !freq)
1882 WARN("Missing format for loopback device\n");
1883 return ALC_INVALID_VALUE;
1885 if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder))
1887 WARN("Missing ambisonic info for loopback device\n");
1888 return ALC_INVALID_VALUE;
1891 if((device->Flags&DEVICE_RUNNING))
1892 V0(device->Backend,stop)();
1893 device->Flags &= ~DEVICE_RUNNING;
1895 UpdateClockBase(device);
1897 device->Frequency = freq;
1898 device->FmtChans = schans;
1899 device->FmtType = stype;
1900 if(schans == ALC_BFORMAT3D_SOFT)
1902 device->AmbiOrder = aorder;
1903 device->AmbiLayout = alayout;
1904 device->AmbiScale = ascale;
1907 if(numMono > INT_MAX-numStereo)
1908 numMono = INT_MAX-numStereo;
1909 numMono += numStereo;
1910 if(ConfigValueInt(NULL, NULL, "sources", &numMono))
1912 if(numMono <= 0)
1913 numMono = 256;
1915 else
1916 numMono = maxi(numMono, 256);
1917 numStereo = mini(numStereo, numMono);
1918 numMono -= numStereo;
1919 device->SourcesMax = numMono + numStereo;
1921 device->NumMonoSources = numMono;
1922 device->NumStereoSources = numStereo;
1924 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1925 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
1926 else
1927 new_sends = numSends;
1929 else if(attrList && attrList[0])
1931 ALCsizei numMono, numStereo, numSends;
1932 ALCsizei attrIdx = 0;
1933 ALCuint freq;
1935 /* If a context is already running on the device, stop playback so the
1936 * device attributes can be updated. */
1937 if((device->Flags&DEVICE_RUNNING))
1938 V0(device->Backend,stop)();
1939 device->Flags &= ~DEVICE_RUNNING;
1941 UpdateClockBase(device);
1943 freq = device->Frequency;
1944 numMono = device->NumMonoSources;
1945 numStereo = device->NumStereoSources;
1946 numSends = old_sends;
1948 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1949 while(attrList[attrIdx])
1951 if(attrList[attrIdx] == ALC_FREQUENCY)
1953 freq = attrList[attrIdx + 1];
1954 TRACE_ATTR(ALC_FREQUENCY, freq);
1955 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1958 if(attrList[attrIdx] == ALC_MONO_SOURCES)
1960 numMono = attrList[attrIdx + 1];
1961 TRACE_ATTR(ALC_MONO_SOURCES, numMono);
1962 numMono = maxi(numMono, 0);
1965 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1967 numStereo = attrList[attrIdx + 1];
1968 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1969 numStereo = maxi(numStereo, 0);
1972 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1974 numSends = attrList[attrIdx + 1];
1975 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1976 numSends = clampi(numSends, 0, MAX_SENDS);
1979 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1981 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1982 if(attrList[attrIdx + 1] == ALC_FALSE)
1983 hrtf_appreq = Hrtf_Disable;
1984 else if(attrList[attrIdx + 1] == ALC_TRUE)
1985 hrtf_appreq = Hrtf_Enable;
1986 else
1987 hrtf_appreq = Hrtf_Default;
1990 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1992 hrtf_id = attrList[attrIdx + 1];
1993 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1996 attrIdx += 2;
1998 #undef TRACE_ATTR
2000 ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq);
2001 freq = maxu(freq, MIN_OUTPUT_RATE);
2003 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
2004 device->Frequency;
2005 /* SSE and Neon do best with the update size being a multiple of 4 */
2006 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
2007 device->UpdateSize = (device->UpdateSize+3)&~3;
2009 device->Frequency = freq;
2011 if(numMono > INT_MAX-numStereo)
2012 numMono = INT_MAX-numStereo;
2013 numMono += numStereo;
2014 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sources", &numMono))
2016 if(numMono <= 0)
2017 numMono = 256;
2019 else
2020 numMono = maxi(numMono, 256);
2021 numStereo = mini(numStereo, numMono);
2022 numMono -= numStereo;
2023 device->SourcesMax = numMono + numStereo;
2025 device->NumMonoSources = numMono;
2026 device->NumStereoSources = numStereo;
2028 if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
2029 new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS));
2030 else
2031 new_sends = numSends;
2034 if((device->Flags&DEVICE_RUNNING))
2035 return ALC_NO_ERROR;
2037 al_free(device->Uhj_Encoder);
2038 device->Uhj_Encoder = NULL;
2040 al_free(device->Bs2b);
2041 device->Bs2b = NULL;
2043 al_free(device->ChannelDelay[0].Buffer);
2044 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2046 device->ChannelDelay[i].Length = 0;
2047 device->ChannelDelay[i].Buffer = NULL;
2050 al_free(device->Dry.Buffer);
2051 device->Dry.Buffer = NULL;
2052 device->Dry.NumChannels = 0;
2053 device->FOAOut.Buffer = NULL;
2054 device->FOAOut.NumChannels = 0;
2055 device->RealOut.Buffer = NULL;
2056 device->RealOut.NumChannels = 0;
2058 UpdateClockBase(device);
2060 /*************************************************************************
2061 * Update device format request if HRTF is requested
2063 device->HrtfStatus = ALC_HRTF_DISABLED_SOFT;
2064 if(device->Type != Loopback)
2066 const char *hrtf;
2067 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2069 if(strcasecmp(hrtf, "true") == 0)
2070 hrtf_userreq = Hrtf_Enable;
2071 else if(strcasecmp(hrtf, "false") == 0)
2072 hrtf_userreq = Hrtf_Disable;
2073 else if(strcasecmp(hrtf, "auto") != 0)
2074 ERR("Unexpected hrtf value: %s\n", hrtf);
2077 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2079 struct Hrtf *hrtf = NULL;
2080 if(VECTOR_SIZE(device->HrtfList) == 0)
2082 VECTOR_DEINIT(device->HrtfList);
2083 device->HrtfList = EnumerateHrtf(device->DeviceName);
2085 if(VECTOR_SIZE(device->HrtfList) > 0)
2087 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
2088 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
2089 else
2090 hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
2093 if(hrtf)
2095 device->FmtChans = DevFmtStereo;
2096 device->Frequency = hrtf->sampleRate;
2097 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2098 if(device->HrtfHandle)
2099 Hrtf_DecRef(device->HrtfHandle);
2100 device->HrtfHandle = hrtf;
2102 else
2104 hrtf_userreq = Hrtf_Default;
2105 hrtf_appreq = Hrtf_Disable;
2106 device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2111 oldFreq = device->Frequency;
2112 oldChans = device->FmtChans;
2113 oldType = device->FmtType;
2115 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2116 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2117 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2118 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2119 device->UpdateSize, device->NumUpdates
2122 if(V0(device->Backend,reset)() == ALC_FALSE)
2123 return ALC_INVALID_DEVICE;
2125 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2128 DevFmtChannelsString(device->FmtChans));
2129 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2131 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2133 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2134 DevFmtTypeString(device->FmtType));
2135 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2137 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2139 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2140 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2143 if((device->UpdateSize&3) != 0)
2145 if((CPUCapFlags&CPU_CAP_SSE))
2146 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2147 if((CPUCapFlags&CPU_CAP_NEON))
2148 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2151 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2152 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2153 device->Frequency, device->UpdateSize, device->NumUpdates
2156 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2157 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2158 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2160 /* Allocate extra channels for any post-filter output. */
2161 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2162 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2164 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2165 device->Dry.Buffer = al_calloc(16, size);
2166 if(!device->Dry.Buffer)
2168 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2169 return ALC_INVALID_DEVICE;
2172 if(device->RealOut.NumChannels != 0)
2173 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2174 device->FOAOut.NumChannels;
2175 else
2177 device->RealOut.Buffer = device->Dry.Buffer;
2178 device->RealOut.NumChannels = device->Dry.NumChannels;
2181 if(device->FOAOut.NumChannels != 0)
2182 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2183 else
2185 device->FOAOut.Buffer = device->Dry.Buffer;
2186 device->FOAOut.NumChannels = device->Dry.NumChannels;
2189 /* Need to delay returning failure until replacement Send arrays have been
2190 * allocated with the appropriate size.
2192 device->NumAuxSends = new_sends;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device->SourcesMax, device->NumMonoSources, device->NumStereoSources,
2195 device->AuxiliaryEffectSlotMax, device->NumAuxSends);
2196 update_failed = AL_FALSE;
2197 SetMixerFPUMode(&oldMode);
2198 if(device->DefaultSlot)
2200 ALeffectslot *slot = device->DefaultSlot;
2201 ALeffectState *state = slot->Effect.State;
2203 state->OutBuffer = device->Dry.Buffer;
2204 state->OutChannels = device->Dry.NumChannels;
2205 if(V(state,deviceUpdate)(device) == AL_FALSE)
2206 update_failed = AL_TRUE;
2207 else
2208 UpdateEffectSlotProps(slot);
2211 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2212 while(context)
2214 ALsizei pos;
2216 WriteLock(&context->PropLock);
2217 LockUIntMapRead(&context->EffectSlotMap);
2218 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2220 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2221 ALeffectState *state = slot->Effect.State;
2223 state->OutBuffer = device->Dry.Buffer;
2224 state->OutChannels = device->Dry.NumChannels;
2225 if(V(state,deviceUpdate)(device) == AL_FALSE)
2226 update_failed = AL_TRUE;
2227 else
2228 UpdateEffectSlotProps(slot);
2230 UnlockUIntMapRead(&context->EffectSlotMap);
2232 LockUIntMapRead(&context->SourceMap);
2233 RelimitUIntMapNoLock(&context->SourceMap, device->SourcesMax);
2234 for(pos = 0;pos < context->SourceMap.size;pos++)
2236 ALsource *source = context->SourceMap.values[pos];
2237 struct ALsourceProps *props;
2239 if(old_sends != device->NumAuxSends)
2241 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2242 ALsizei s;
2244 memcpy(sends, source->Send,
2245 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2247 for(s = device->NumAuxSends;s < old_sends;s++)
2249 if(source->Send[s].Slot)
2250 DecrementRef(&source->Send[s].Slot->ref);
2251 source->Send[s].Slot = NULL;
2253 al_free(source->Send);
2254 source->Send = sends;
2255 for(s = old_sends;s < device->NumAuxSends;s++)
2257 source->Send[s].Slot = NULL;
2258 source->Send[s].Gain = 1.0f;
2259 source->Send[s].GainHF = 1.0f;
2260 source->Send[s].HFReference = LOWPASSFREQREF;
2261 source->Send[s].GainLF = 1.0f;
2262 source->Send[s].LFReference = HIGHPASSFREQREF;
2266 ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release);
2268 /* Clear any pre-existing source property structs, in case the
2269 * number of auxiliary sends changed. Playing (or paused) sources
2270 * will have updates respecified in UpdateAllSourceProps.
2272 props = ATOMIC_EXCHANGE_PTR_SEQ(&source->Update, NULL);
2273 al_free(props);
2275 props = ATOMIC_EXCHANGE_PTR(&source->FreeList, NULL, almemory_order_relaxed);
2276 while(props)
2278 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2279 al_free(props);
2280 props = next;
2283 AllocateVoices(context, context->MaxVoices, old_sends);
2284 for(pos = 0;pos < context->VoiceCount;pos++)
2286 ALvoice *voice = context->Voices[pos];
2287 if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL)
2288 continue;
2290 if(device->AvgSpeakerDist > 0.0f)
2292 /* Reinitialize the NFC filters for new parameters. */
2293 ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
2294 (device->AvgSpeakerDist * device->Frequency);
2295 for(i = 0;i < voice->NumChannels;i++)
2297 NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
2298 NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
2299 NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
2303 UnlockUIntMapRead(&context->SourceMap);
2305 UpdateListenerProps(context);
2306 UpdateAllSourceProps(context);
2307 WriteUnlock(&context->PropLock);
2309 context = context->next;
2311 RestoreFPUMode(&oldMode);
2312 if(update_failed)
2313 return ALC_INVALID_DEVICE;
2315 if(!(device->Flags&DEVICE_PAUSED))
2317 if(V0(device->Backend,start)() == ALC_FALSE)
2318 return ALC_INVALID_DEVICE;
2319 device->Flags |= DEVICE_RUNNING;
2322 return ALC_NO_ERROR;
2325 /* FreeDevice
2327 * Frees the device structure, and destroys any objects the app failed to
2328 * delete. Called once there's no more references on the device.
2330 static ALCvoid FreeDevice(ALCdevice *device)
2332 ALsizei i;
2334 TRACE("%p\n", device);
2336 V0(device->Backend,close)();
2337 DELETE_OBJ(device->Backend);
2338 device->Backend = NULL;
2340 almtx_destroy(&device->BackendLock);
2342 if(device->DefaultSlot)
2344 DeinitEffectSlot(device->DefaultSlot);
2345 device->DefaultSlot = NULL;
2348 if(device->BufferMap.size > 0)
2350 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2351 (device->BufferMap.size==1)?"":"s");
2352 ReleaseALBuffers(device);
2354 ResetUIntMap(&device->BufferMap);
2356 if(device->EffectMap.size > 0)
2358 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2359 (device->EffectMap.size==1)?"":"s");
2360 ReleaseALEffects(device);
2362 ResetUIntMap(&device->EffectMap);
2364 if(device->FilterMap.size > 0)
2366 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2367 (device->FilterMap.size==1)?"":"s");
2368 ReleaseALFilters(device);
2370 ResetUIntMap(&device->FilterMap);
2372 AL_STRING_DEINIT(device->HrtfName);
2373 FreeHrtfList(&device->HrtfList);
2374 if(device->HrtfHandle)
2375 Hrtf_DecRef(device->HrtfHandle);
2376 device->HrtfHandle = NULL;
2377 al_free(device->Hrtf);
2378 device->Hrtf = NULL;
2380 al_free(device->Bs2b);
2381 device->Bs2b = NULL;
2383 al_free(device->Uhj_Encoder);
2384 device->Uhj_Encoder = NULL;
2386 bformatdec_free(device->AmbiDecoder);
2387 device->AmbiDecoder = NULL;
2389 ambiup_free(device->AmbiUp);
2390 device->AmbiUp = NULL;
2392 al_free(device->ChannelDelay[0].Buffer);
2393 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
2395 device->ChannelDelay[i].Gain = 1.0f;
2396 device->ChannelDelay[i].Length = 0;
2397 device->ChannelDelay[i].Buffer = NULL;
2400 AL_STRING_DEINIT(device->DeviceName);
2402 al_free(device->Dry.Buffer);
2403 device->Dry.Buffer = NULL;
2404 device->Dry.NumChannels = 0;
2405 device->FOAOut.Buffer = NULL;
2406 device->FOAOut.NumChannels = 0;
2407 device->RealOut.Buffer = NULL;
2408 device->RealOut.NumChannels = 0;
2410 al_free(device);
2414 void ALCdevice_IncRef(ALCdevice *device)
2416 uint ref;
2417 ref = IncrementRef(&device->ref);
2418 TRACEREF("%p increasing refcount to %u\n", device, ref);
2421 void ALCdevice_DecRef(ALCdevice *device)
2423 uint ref;
2424 ref = DecrementRef(&device->ref);
2425 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2426 if(ref == 0) FreeDevice(device);
2429 /* VerifyDevice
2431 * Checks if the device handle is valid, and increments its ref count if so.
2433 static ALCboolean VerifyDevice(ALCdevice **device)
2435 ALCdevice *tmpDevice;
2437 LockLists();
2438 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2439 while(tmpDevice)
2441 if(tmpDevice == *device)
2443 ALCdevice_IncRef(tmpDevice);
2444 UnlockLists();
2445 return ALC_TRUE;
2447 tmpDevice = tmpDevice->next;
2449 UnlockLists();
2451 *device = NULL;
2452 return ALC_FALSE;
2456 /* InitContext
2458 * Initializes context fields
2460 static ALvoid InitContext(ALCcontext *Context)
2462 ALlistener *listener = Context->Listener;
2463 struct ALeffectslotArray *auxslots;
2465 //Initialise listener
2466 listener->Gain = 1.0f;
2467 listener->MetersPerUnit = 1.0f;
2468 listener->Position[0] = 0.0f;
2469 listener->Position[1] = 0.0f;
2470 listener->Position[2] = 0.0f;
2471 listener->Velocity[0] = 0.0f;
2472 listener->Velocity[1] = 0.0f;
2473 listener->Velocity[2] = 0.0f;
2474 listener->Forward[0] = 0.0f;
2475 listener->Forward[1] = 0.0f;
2476 listener->Forward[2] = -1.0f;
2477 listener->Up[0] = 0.0f;
2478 listener->Up[1] = 1.0f;
2479 listener->Up[2] = 0.0f;
2481 aluMatrixfSet(&listener->Params.Matrix,
2482 1.0f, 0.0f, 0.0f, 0.0f,
2483 0.0f, 1.0f, 0.0f, 0.0f,
2484 0.0f, 0.0f, 1.0f, 0.0f,
2485 0.0f, 0.0f, 0.0f, 1.0f
2487 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2488 listener->Params.Gain = 1.0f;
2489 listener->Params.MetersPerUnit = 1.0f;
2490 listener->Params.DopplerFactor = 1.0f;
2491 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2493 ATOMIC_INIT(&listener->Update, NULL);
2494 ATOMIC_INIT(&listener->FreeList, NULL);
2496 //Validate Context
2497 InitRef(&Context->UpdateCount, 0);
2498 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2499 Context->GainBoost = 1.0f;
2500 RWLockInit(&Context->PropLock);
2501 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2502 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2503 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2505 auxslots = al_calloc(DEF_ALIGN, offsetof(struct ALeffectslotArray, slot[0]));
2506 auxslots->count = 0;
2507 ATOMIC_INIT(&Context->ActiveAuxSlots, auxslots);
2509 //Set globals
2510 Context->DistanceModel = DefaultDistanceModel;
2511 Context->SourceDistanceModel = AL_FALSE;
2512 Context->DopplerFactor = 1.0f;
2513 Context->DopplerVelocity = 1.0f;
2514 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2515 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2517 Context->ExtensionList = alExtList;
2521 /* FreeContext
2523 * Cleans up the context, and destroys any remaining objects the app failed to
2524 * delete. Called once there's no more references on the context.
2526 static void FreeContext(ALCcontext *context)
2528 ALlistener *listener = context->Listener;
2529 struct ALeffectslotArray *auxslots;
2530 struct ALlistenerProps *lprops;
2531 size_t count;
2533 TRACE("%p\n", context);
2535 auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed);
2536 al_free(auxslots);
2538 if(context->SourceMap.size > 0)
2540 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2541 (context->SourceMap.size==1)?"":"s");
2542 ReleaseALSources(context);
2544 ResetUIntMap(&context->SourceMap);
2546 if(context->EffectSlotMap.size > 0)
2548 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2549 (context->EffectSlotMap.size==1)?"":"s");
2550 ReleaseALAuxiliaryEffectSlots(context);
2552 ResetUIntMap(&context->EffectSlotMap);
2554 al_free(context->Voices);
2555 context->Voices = NULL;
2556 context->VoiceCount = 0;
2557 context->MaxVoices = 0;
2559 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2561 TRACE("Freed unapplied listener update %p\n", lprops);
2562 al_free(lprops);
2564 count = 0;
2565 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2566 while(lprops)
2568 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2569 al_free(lprops);
2570 lprops = next;
2571 ++count;
2573 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2575 ALCdevice_DecRef(context->Device);
2576 context->Device = NULL;
2578 //Invalidate context
2579 memset(context, 0, sizeof(ALCcontext));
2580 al_free(context);
2583 /* ReleaseContext
2585 * Removes the context reference from the given device and removes it from
2586 * being current on the running thread or globally. Returns true if other
2587 * contexts still exist on the device.
2589 static bool ReleaseContext(ALCcontext *context, ALCdevice *device)
2591 ALCcontext *origctx, *newhead;
2592 bool ret = true;
2594 if(altss_get(LocalContext) == context)
2596 WARN("%p released while current on thread\n", context);
2597 altss_set(LocalContext, NULL);
2598 ALCcontext_DecRef(context);
2601 origctx = context;
2602 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL))
2603 ALCcontext_DecRef(context);
2605 ALCdevice_Lock(device);
2606 origctx = context;
2607 newhead = context->next;
2608 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead))
2610 ALCcontext *volatile*list = &origctx->next;
2611 while(*list)
2613 if(*list == context)
2615 *list = (*list)->next;
2616 break;
2618 list = &(*list)->next;
2621 else
2622 ret = !!newhead;
2623 ALCdevice_Unlock(device);
2625 ALCcontext_DecRef(context);
2626 return ret;
2629 void ALCcontext_IncRef(ALCcontext *context)
2631 uint ref = IncrementRef(&context->ref);
2632 TRACEREF("%p increasing refcount to %u\n", context, ref);
2635 void ALCcontext_DecRef(ALCcontext *context)
2637 uint ref = DecrementRef(&context->ref);
2638 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2639 if(ref == 0) FreeContext(context);
2642 static void ReleaseThreadCtx(void *ptr)
2644 ALCcontext *context = ptr;
2645 uint ref = DecrementRef(&context->ref);
2646 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2647 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2650 /* VerifyContext
2652 * Checks that the given context is valid, and increments its reference count.
2654 static ALCboolean VerifyContext(ALCcontext **context)
2656 ALCdevice *dev;
2658 LockLists();
2659 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2660 while(dev)
2662 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2663 while(ctx)
2665 if(ctx == *context)
2667 ALCcontext_IncRef(ctx);
2668 UnlockLists();
2669 return ALC_TRUE;
2671 ctx = ctx->next;
2673 dev = dev->next;
2675 UnlockLists();
2677 *context = NULL;
2678 return ALC_FALSE;
2682 /* GetContextRef
2684 * Returns the currently active context for this thread, and adds a reference
2685 * without locking it.
2687 ALCcontext *GetContextRef(void)
2689 ALCcontext *context;
2691 context = altss_get(LocalContext);
2692 if(context)
2693 ALCcontext_IncRef(context);
2694 else
2696 LockLists();
2697 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2698 if(context)
2699 ALCcontext_IncRef(context);
2700 UnlockLists();
2703 return context;
2707 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2709 ALCdevice *device = context->Device;
2710 ALsizei num_sends = device->NumAuxSends;
2711 struct ALsourceProps *props;
2712 size_t sizeof_props;
2713 size_t sizeof_voice;
2714 ALvoice **voices;
2715 ALvoice *voice;
2716 ALsizei v = 0;
2717 size_t size;
2719 if(num_voices == context->MaxVoices && num_sends == old_sends)
2720 return;
2722 /* Allocate the voice pointers, voices, and the voices' stored source
2723 * property set (including the dynamically-sized Send[] array) in one
2724 * chunk.
2726 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2727 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2728 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2730 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2731 /* The voice and property objects are stored interleaved since they're
2732 * paired together.
2734 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2735 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2737 if(context->Voices)
2739 ALsizei v_count = mini(context->VoiceCount, num_voices);
2740 for(;v < v_count;v++)
2742 ALsizei s_count = mini(old_sends, num_sends);
2743 ALsizei i;
2745 /* Copy the old voice data and source property set to the new
2746 * storage.
2748 *voice = *(context->Voices[v]);
2749 for(i = 0;i < s_count;i++)
2750 voice->Send[i] = context->Voices[v]->Send[i];
2751 *props = *(context->Voices[v]->Props);
2752 for(i = 0;i < s_count;i++)
2753 props->Send[i] = context->Voices[v]->Props->Send[i];
2755 /* Set this voice's property set pointer and voice reference. */
2756 voice->Props = props;
2757 voices[v] = voice;
2759 /* Increment pointers to the next storage space. */
2760 voice = (ALvoice*)((char*)props + sizeof_props);
2761 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2764 /* Finish setting the voices' property set pointers and references. */
2765 for(;v < num_voices;v++)
2767 voice->Props = props;
2768 voices[v] = voice;
2770 voice = (ALvoice*)((char*)props + sizeof_props);
2771 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2774 al_free(context->Voices);
2775 context->Voices = voices;
2776 context->MaxVoices = num_voices;
2777 context->VoiceCount = mini(context->VoiceCount, num_voices);
2781 /************************************************
2782 * Standard ALC functions
2783 ************************************************/
2785 /* alcGetError
2787 * Return last ALC generated error code for the given device
2789 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2791 ALCenum errorCode;
2793 if(VerifyDevice(&device))
2795 errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR);
2796 ALCdevice_DecRef(device);
2798 else
2799 errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR);
2801 return errorCode;
2805 /* alcSuspendContext
2807 * Suspends updates for the given context
2809 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2811 if(!SuspendDefers)
2812 return;
2814 if(!VerifyContext(&context))
2815 alcSetError(NULL, ALC_INVALID_CONTEXT);
2816 else
2818 ALCcontext_DeferUpdates(context);
2819 ALCcontext_DecRef(context);
2823 /* alcProcessContext
2825 * Resumes processing updates for the given context
2827 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2829 if(!SuspendDefers)
2830 return;
2832 if(!VerifyContext(&context))
2833 alcSetError(NULL, ALC_INVALID_CONTEXT);
2834 else
2836 ALCcontext_ProcessUpdates(context);
2837 ALCcontext_DecRef(context);
2842 /* alcGetString
2844 * Returns information about the device, and error strings
2846 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2848 const ALCchar *value = NULL;
2850 switch(param)
2852 case ALC_NO_ERROR:
2853 value = alcNoError;
2854 break;
2856 case ALC_INVALID_ENUM:
2857 value = alcErrInvalidEnum;
2858 break;
2860 case ALC_INVALID_VALUE:
2861 value = alcErrInvalidValue;
2862 break;
2864 case ALC_INVALID_DEVICE:
2865 value = alcErrInvalidDevice;
2866 break;
2868 case ALC_INVALID_CONTEXT:
2869 value = alcErrInvalidContext;
2870 break;
2872 case ALC_OUT_OF_MEMORY:
2873 value = alcErrOutOfMemory;
2874 break;
2876 case ALC_DEVICE_SPECIFIER:
2877 value = alcDefaultName;
2878 break;
2880 case ALC_ALL_DEVICES_SPECIFIER:
2881 if(VerifyDevice(&Device))
2883 value = alstr_get_cstr(Device->DeviceName);
2884 ALCdevice_DecRef(Device);
2886 else
2888 ProbeAllDevicesList();
2889 value = alstr_get_cstr(alcAllDevicesList);
2891 break;
2893 case ALC_CAPTURE_DEVICE_SPECIFIER:
2894 if(VerifyDevice(&Device))
2896 value = alstr_get_cstr(Device->DeviceName);
2897 ALCdevice_DecRef(Device);
2899 else
2901 ProbeCaptureDeviceList();
2902 value = alstr_get_cstr(alcCaptureDeviceList);
2904 break;
2906 /* Default devices are always first in the list */
2907 case ALC_DEFAULT_DEVICE_SPECIFIER:
2908 value = alcDefaultName;
2909 break;
2911 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2912 if(alstr_empty(alcAllDevicesList))
2913 ProbeAllDevicesList();
2915 VerifyDevice(&Device);
2917 free(alcDefaultAllDevicesSpecifier);
2918 alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList));
2919 if(!alcDefaultAllDevicesSpecifier)
2920 alcSetError(Device, ALC_OUT_OF_MEMORY);
2922 value = alcDefaultAllDevicesSpecifier;
2923 if(Device) ALCdevice_DecRef(Device);
2924 break;
2926 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2927 if(alstr_empty(alcCaptureDeviceList))
2928 ProbeCaptureDeviceList();
2930 VerifyDevice(&Device);
2932 free(alcCaptureDefaultDeviceSpecifier);
2933 alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList));
2934 if(!alcCaptureDefaultDeviceSpecifier)
2935 alcSetError(Device, ALC_OUT_OF_MEMORY);
2937 value = alcCaptureDefaultDeviceSpecifier;
2938 if(Device) ALCdevice_DecRef(Device);
2939 break;
2941 case ALC_EXTENSIONS:
2942 if(!VerifyDevice(&Device))
2943 value = alcNoDeviceExtList;
2944 else
2946 value = alcExtensionList;
2947 ALCdevice_DecRef(Device);
2949 break;
2951 case ALC_HRTF_SPECIFIER_SOFT:
2952 if(!VerifyDevice(&Device))
2953 alcSetError(NULL, ALC_INVALID_DEVICE);
2954 else
2956 almtx_lock(&Device->BackendLock);
2957 value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : "");
2958 almtx_unlock(&Device->BackendLock);
2959 ALCdevice_DecRef(Device);
2961 break;
2963 default:
2964 VerifyDevice(&Device);
2965 alcSetError(Device, ALC_INVALID_ENUM);
2966 if(Device) ALCdevice_DecRef(Device);
2967 break;
2970 return value;
2974 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
2976 if(device->Type == Loopback && device->FmtChans == DevFmtAmbi3D)
2977 return 23;
2978 return 17;
2981 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2983 ALCsizei i;
2985 if(size <= 0 || values == NULL)
2987 alcSetError(device, ALC_INVALID_VALUE);
2988 return 0;
2991 if(!device)
2993 switch(param)
2995 case ALC_MAJOR_VERSION:
2996 values[0] = alcMajorVersion;
2997 return 1;
2998 case ALC_MINOR_VERSION:
2999 values[0] = alcMinorVersion;
3000 return 1;
3002 case ALC_ATTRIBUTES_SIZE:
3003 case ALC_ALL_ATTRIBUTES:
3004 case ALC_FREQUENCY:
3005 case ALC_REFRESH:
3006 case ALC_SYNC:
3007 case ALC_MONO_SOURCES:
3008 case ALC_STEREO_SOURCES:
3009 case ALC_CAPTURE_SAMPLES:
3010 case ALC_FORMAT_CHANNELS_SOFT:
3011 case ALC_FORMAT_TYPE_SOFT:
3012 case ALC_AMBISONIC_LAYOUT_SOFT:
3013 case ALC_AMBISONIC_SCALING_SOFT:
3014 case ALC_AMBISONIC_ORDER_SOFT:
3015 alcSetError(NULL, ALC_INVALID_DEVICE);
3016 return 0;
3018 default:
3019 alcSetError(NULL, ALC_INVALID_ENUM);
3020 return 0;
3022 return 0;
3025 if(device->Type == Capture)
3027 switch(param)
3029 case ALC_CAPTURE_SAMPLES:
3030 almtx_lock(&device->BackendLock);
3031 values[0] = V0(device->Backend,availableSamples)();
3032 almtx_unlock(&device->BackendLock);
3033 return 1;
3035 case ALC_CONNECTED:
3036 values[0] = device->Connected;
3037 return 1;
3039 default:
3040 alcSetError(device, ALC_INVALID_ENUM);
3041 return 0;
3043 return 0;
3046 /* render device */
3047 switch(param)
3049 case ALC_MAJOR_VERSION:
3050 values[0] = alcMajorVersion;
3051 return 1;
3053 case ALC_MINOR_VERSION:
3054 values[0] = alcMinorVersion;
3055 return 1;
3057 case ALC_EFX_MAJOR_VERSION:
3058 values[0] = alcEFXMajorVersion;
3059 return 1;
3061 case ALC_EFX_MINOR_VERSION:
3062 values[0] = alcEFXMinorVersion;
3063 return 1;
3065 case ALC_ATTRIBUTES_SIZE:
3066 values[0] = NumAttrsForDevice(device);
3067 return 1;
3069 case ALC_ALL_ATTRIBUTES:
3070 if(size < NumAttrsForDevice(device))
3072 alcSetError(device, ALC_INVALID_VALUE);
3073 return 0;
3076 i = 0;
3077 almtx_lock(&device->BackendLock);
3078 values[i++] = ALC_FREQUENCY;
3079 values[i++] = device->Frequency;
3081 if(device->Type != Loopback)
3083 values[i++] = ALC_REFRESH;
3084 values[i++] = device->Frequency / device->UpdateSize;
3086 values[i++] = ALC_SYNC;
3087 values[i++] = ALC_FALSE;
3089 else
3091 if(device->FmtChans == DevFmtAmbi3D)
3093 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3094 values[i++] = device->AmbiLayout;
3096 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3097 values[i++] = device->AmbiScale;
3099 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3100 values[i++] = device->AmbiOrder;
3103 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3104 values[i++] = device->FmtChans;
3106 values[i++] = ALC_FORMAT_TYPE_SOFT;
3107 values[i++] = device->FmtType;
3110 values[i++] = ALC_MONO_SOURCES;
3111 values[i++] = device->NumMonoSources;
3113 values[i++] = ALC_STEREO_SOURCES;
3114 values[i++] = device->NumStereoSources;
3116 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3117 values[i++] = device->NumAuxSends;
3119 values[i++] = ALC_HRTF_SOFT;
3120 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3122 values[i++] = ALC_HRTF_STATUS_SOFT;
3123 values[i++] = device->HrtfStatus;
3124 almtx_unlock(&device->BackendLock);
3126 values[i++] = 0;
3127 return i;
3129 case ALC_FREQUENCY:
3130 values[0] = device->Frequency;
3131 return 1;
3133 case ALC_REFRESH:
3134 if(device->Type == Loopback)
3136 alcSetError(device, ALC_INVALID_DEVICE);
3137 return 0;
3139 almtx_lock(&device->BackendLock);
3140 values[0] = device->Frequency / device->UpdateSize;
3141 almtx_unlock(&device->BackendLock);
3142 return 1;
3144 case ALC_SYNC:
3145 if(device->Type == Loopback)
3147 alcSetError(device, ALC_INVALID_DEVICE);
3148 return 0;
3150 values[0] = ALC_FALSE;
3151 return 1;
3153 case ALC_FORMAT_CHANNELS_SOFT:
3154 if(device->Type != Loopback)
3156 alcSetError(device, ALC_INVALID_DEVICE);
3157 return 0;
3159 values[0] = device->FmtChans;
3160 return 1;
3162 case ALC_FORMAT_TYPE_SOFT:
3163 if(device->Type != Loopback)
3165 alcSetError(device, ALC_INVALID_DEVICE);
3166 return 0;
3168 values[0] = device->FmtType;
3169 return 1;
3171 case ALC_AMBISONIC_LAYOUT_SOFT:
3172 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
3174 alcSetError(device, ALC_INVALID_DEVICE);
3175 return 0;
3177 values[0] = device->AmbiLayout;
3178 return 1;
3180 case ALC_AMBISONIC_SCALING_SOFT:
3181 if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
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 != DevFmtAmbi3D)
3192 alcSetError(device, ALC_INVALID_DEVICE);
3193 return 0;
3195 values[0] = device->AmbiOrder;
3196 return 1;
3198 case ALC_MONO_SOURCES:
3199 values[0] = device->NumMonoSources;
3200 return 1;
3202 case ALC_STEREO_SOURCES:
3203 values[0] = device->NumStereoSources;
3204 return 1;
3206 case ALC_MAX_AUXILIARY_SENDS:
3207 values[0] = device->NumAuxSends;
3208 return 1;
3210 case ALC_CONNECTED:
3211 values[0] = device->Connected;
3212 return 1;
3214 case ALC_HRTF_SOFT:
3215 values[0] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3216 return 1;
3218 case ALC_HRTF_STATUS_SOFT:
3219 values[0] = device->HrtfStatus;
3220 return 1;
3222 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3223 almtx_lock(&device->BackendLock);
3224 FreeHrtfList(&device->HrtfList);
3225 device->HrtfList = EnumerateHrtf(device->DeviceName);
3226 values[0] = (ALCint)VECTOR_SIZE(device->HrtfList);
3227 almtx_unlock(&device->BackendLock);
3228 return 1;
3230 default:
3231 alcSetError(device, ALC_INVALID_ENUM);
3232 return 0;
3234 return 0;
3237 /* alcGetIntegerv
3239 * Returns information about the device and the version of OpenAL
3241 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3243 VerifyDevice(&device);
3244 if(size <= 0 || values == NULL)
3245 alcSetError(device, ALC_INVALID_VALUE);
3246 else
3247 GetIntegerv(device, param, size, values);
3248 if(device) ALCdevice_DecRef(device);
3251 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3253 ALCint *ivals;
3254 ALsizei i;
3256 VerifyDevice(&device);
3257 if(size <= 0 || values == NULL)
3258 alcSetError(device, ALC_INVALID_VALUE);
3259 else if(!device || device->Type == Capture)
3261 ivals = malloc(size * sizeof(ALCint));
3262 size = GetIntegerv(device, pname, size, ivals);
3263 for(i = 0;i < size;i++)
3264 values[i] = ivals[i];
3265 free(ivals);
3267 else /* render device */
3269 ClockLatency clock;
3270 ALuint64 basecount;
3271 ALuint samplecount;
3272 ALuint refcount;
3274 switch(pname)
3276 case ALC_ATTRIBUTES_SIZE:
3277 *values = NumAttrsForDevice(device)+4;
3278 break;
3280 case ALC_ALL_ATTRIBUTES:
3281 if(size < NumAttrsForDevice(device)+4)
3282 alcSetError(device, ALC_INVALID_VALUE);
3283 else
3285 i = 0;
3286 almtx_lock(&device->BackendLock);
3287 values[i++] = ALC_FREQUENCY;
3288 values[i++] = device->Frequency;
3290 if(device->Type != Loopback)
3292 values[i++] = ALC_REFRESH;
3293 values[i++] = device->Frequency / device->UpdateSize;
3295 values[i++] = ALC_SYNC;
3296 values[i++] = ALC_FALSE;
3298 else
3300 if(device->FmtChans == DevFmtAmbi3D)
3302 values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
3303 values[i++] = device->AmbiLayout;
3305 values[i++] = ALC_AMBISONIC_SCALING_SOFT;
3306 values[i++] = device->AmbiScale;
3308 values[i++] = ALC_AMBISONIC_ORDER_SOFT;
3309 values[i++] = device->AmbiOrder;
3312 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3313 values[i++] = device->FmtChans;
3315 values[i++] = ALC_FORMAT_TYPE_SOFT;
3316 values[i++] = device->FmtType;
3319 values[i++] = ALC_MONO_SOURCES;
3320 values[i++] = device->NumMonoSources;
3322 values[i++] = ALC_STEREO_SOURCES;
3323 values[i++] = device->NumStereoSources;
3325 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3326 values[i++] = device->NumAuxSends;
3328 values[i++] = ALC_HRTF_SOFT;
3329 values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
3331 values[i++] = ALC_HRTF_STATUS_SOFT;
3332 values[i++] = device->HrtfStatus;
3334 clock = V0(device->Backend,getClockLatency)();
3335 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3336 values[i++] = clock.ClockTime;
3338 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3339 values[i++] = clock.Latency;
3340 almtx_unlock(&device->BackendLock);
3342 values[i++] = 0;
3344 break;
3346 case ALC_DEVICE_CLOCK_SOFT:
3347 almtx_lock(&device->BackendLock);
3348 do {
3349 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3350 althrd_yield();
3351 basecount = device->ClockBase;
3352 samplecount = device->SamplesDone;
3353 } while(refcount != ReadRef(&device->MixCount));
3354 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3355 almtx_unlock(&device->BackendLock);
3356 break;
3358 case ALC_DEVICE_LATENCY_SOFT:
3359 almtx_lock(&device->BackendLock);
3360 clock = V0(device->Backend,getClockLatency)();
3361 almtx_unlock(&device->BackendLock);
3362 *values = clock.Latency;
3363 break;
3365 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3366 if(size < 2)
3367 alcSetError(device, ALC_INVALID_VALUE);
3368 else
3370 almtx_lock(&device->BackendLock);
3371 clock = V0(device->Backend,getClockLatency)();
3372 almtx_unlock(&device->BackendLock);
3373 values[0] = clock.ClockTime;
3374 values[1] = clock.Latency;
3376 break;
3378 default:
3379 ivals = malloc(size * sizeof(ALCint));
3380 size = GetIntegerv(device, pname, size, ivals);
3381 for(i = 0;i < size;i++)
3382 values[i] = ivals[i];
3383 free(ivals);
3384 break;
3387 if(device)
3388 ALCdevice_DecRef(device);
3392 /* alcIsExtensionPresent
3394 * Determines if there is support for a particular extension
3396 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3398 ALCboolean bResult = ALC_FALSE;
3400 VerifyDevice(&device);
3402 if(!extName)
3403 alcSetError(device, ALC_INVALID_VALUE);
3404 else
3406 size_t len = strlen(extName);
3407 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3408 while(ptr && *ptr)
3410 if(strncasecmp(ptr, extName, len) == 0 &&
3411 (ptr[len] == '\0' || isspace(ptr[len])))
3413 bResult = ALC_TRUE;
3414 break;
3416 if((ptr=strchr(ptr, ' ')) != NULL)
3418 do {
3419 ++ptr;
3420 } while(isspace(*ptr));
3424 if(device)
3425 ALCdevice_DecRef(device);
3426 return bResult;
3430 /* alcGetProcAddress
3432 * Retrieves the function address for a particular extension function
3434 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3436 ALCvoid *ptr = NULL;
3438 if(!funcName)
3440 VerifyDevice(&device);
3441 alcSetError(device, ALC_INVALID_VALUE);
3442 if(device) ALCdevice_DecRef(device);
3444 else
3446 size_t i = 0;
3447 for(i = 0;i < COUNTOF(alcFunctions);i++)
3449 if(strcmp(alcFunctions[i].funcName, funcName) == 0)
3451 ptr = alcFunctions[i].address;
3452 break;
3457 return ptr;
3461 /* alcGetEnumValue
3463 * Get the value for a particular ALC enumeration name
3465 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3467 ALCenum val = 0;
3469 if(!enumName)
3471 VerifyDevice(&device);
3472 alcSetError(device, ALC_INVALID_VALUE);
3473 if(device) ALCdevice_DecRef(device);
3475 else
3477 size_t i = 0;
3478 for(i = 0;i < COUNTOF(alcEnumerations);i++)
3480 if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
3482 val = alcEnumerations[i].value;
3483 break;
3488 return val;
3492 /* alcCreateContext
3494 * Create and attach a context to the given device.
3496 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3498 ALCcontext *ALContext;
3499 ALfloat valf;
3500 ALCenum err;
3502 /* Explicitly hold the list lock while taking the BackendLock in case the
3503 * device is asynchronously destropyed, to ensure this new context is
3504 * properly cleaned up after being made.
3506 LockLists();
3507 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3509 UnlockLists();
3510 alcSetError(device, ALC_INVALID_DEVICE);
3511 if(device) ALCdevice_DecRef(device);
3512 return NULL;
3514 almtx_lock(&device->BackendLock);
3515 UnlockLists();
3517 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3519 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3520 if(ALContext)
3522 InitRef(&ALContext->ref, 1);
3523 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3525 ALContext->Device = device;
3526 ATOMIC_INIT(&ALContext->ActiveAuxSlots, NULL);
3528 ALContext->Voices = NULL;
3529 ALContext->MaxVoices = 0;
3530 ALContext->VoiceCount = 0;
3531 AllocateVoices(ALContext, 256, device->NumAuxSends);
3533 if(!ALContext || !ALContext->Voices)
3535 almtx_unlock(&device->BackendLock);
3537 if(ALContext)
3539 al_free(ALContext->Voices);
3540 ALContext->Voices = NULL;
3542 al_free(ALContext);
3543 ALContext = NULL;
3546 alcSetError(device, ALC_OUT_OF_MEMORY);
3547 ALCdevice_DecRef(device);
3548 return NULL;
3551 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3553 almtx_unlock(&device->BackendLock);
3555 al_free(ALContext->Voices);
3556 ALContext->Voices = NULL;
3558 al_free(ALContext);
3559 ALContext = NULL;
3561 alcSetError(device, err);
3562 if(err == ALC_INVALID_DEVICE)
3564 V0(device->Backend,lock)();
3565 aluHandleDisconnect(device);
3566 V0(device->Backend,unlock)();
3568 ALCdevice_DecRef(device);
3569 return NULL;
3572 ALCdevice_IncRef(ALContext->Device);
3573 InitContext(ALContext);
3575 if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3577 if(!isfinite(valf))
3578 ERR("volume-adjust must be finite: %f\n", valf);
3579 else
3581 ALfloat db = clampf(valf, -24.0f, 24.0f);
3582 if(db != valf)
3583 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3584 ALContext->GainBoost = powf(10.0f, db/20.0f);
3585 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3588 UpdateListenerProps(ALContext);
3591 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3592 do {
3593 ALContext->next = head;
3594 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head,
3595 ALContext) == 0);
3597 almtx_unlock(&device->BackendLock);
3599 ALCdevice_DecRef(device);
3601 TRACE("Created context %p\n", ALContext);
3602 return ALContext;
3605 /* alcDestroyContext
3607 * Remove a context from its device
3609 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3611 ALCdevice *Device;
3613 LockLists();
3614 if(!VerifyContext(&context))
3616 UnlockLists();
3617 alcSetError(NULL, ALC_INVALID_CONTEXT);
3618 return;
3621 Device = context->Device;
3622 if(Device)
3624 almtx_lock(&Device->BackendLock);
3625 if(!ReleaseContext(context, Device))
3627 V0(Device->Backend,stop)();
3628 Device->Flags &= ~DEVICE_RUNNING;
3630 almtx_unlock(&Device->BackendLock);
3632 UnlockLists();
3634 ALCcontext_DecRef(context);
3638 /* alcGetCurrentContext
3640 * Returns the currently active context on the calling thread
3642 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3644 ALCcontext *Context = altss_get(LocalContext);
3645 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3646 return Context;
3649 /* alcGetThreadContext
3651 * Returns the currently active thread-local context
3653 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3655 return altss_get(LocalContext);
3659 /* alcMakeContextCurrent
3661 * Makes the given context the active process-wide context, and removes the
3662 * thread-local context for the calling thread.
3664 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3666 /* context must be valid or NULL */
3667 if(context && !VerifyContext(&context))
3669 alcSetError(NULL, ALC_INVALID_CONTEXT);
3670 return ALC_FALSE;
3672 /* context's reference count is already incremented */
3673 context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context);
3674 if(context) ALCcontext_DecRef(context);
3676 if((context=altss_get(LocalContext)) != NULL)
3678 altss_set(LocalContext, NULL);
3679 ALCcontext_DecRef(context);
3682 return ALC_TRUE;
3685 /* alcSetThreadContext
3687 * Makes the given context the active context for the current thread
3689 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3691 ALCcontext *old;
3693 /* context must be valid or NULL */
3694 if(context && !VerifyContext(&context))
3696 alcSetError(NULL, ALC_INVALID_CONTEXT);
3697 return ALC_FALSE;
3699 /* context's reference count is already incremented */
3700 old = altss_get(LocalContext);
3701 altss_set(LocalContext, context);
3702 if(old) ALCcontext_DecRef(old);
3704 return ALC_TRUE;
3708 /* alcGetContextsDevice
3710 * Returns the device that a particular context is attached to
3712 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3714 ALCdevice *Device;
3716 if(!VerifyContext(&Context))
3718 alcSetError(NULL, ALC_INVALID_CONTEXT);
3719 return NULL;
3721 Device = Context->Device;
3722 ALCcontext_DecRef(Context);
3724 return Device;
3728 /* alcOpenDevice
3730 * Opens the named device.
3732 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3734 const ALCchar *fmt;
3735 ALCdevice *device;
3736 ALCenum err;
3737 ALCsizei i;
3739 DO_INITCONFIG();
3741 if(!PlaybackBackend.name)
3743 alcSetError(NULL, ALC_INVALID_VALUE);
3744 return NULL;
3747 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3748 #ifdef _WIN32
3749 /* Some old Windows apps hardcode these expecting OpenAL to use a
3750 * specific audio API, even when they're not enumerated. Creative's
3751 * router effectively ignores them too.
3753 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3754 || strcasecmp(deviceName, "MMSYSTEM") == 0
3755 #endif
3757 deviceName = NULL;
3759 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3760 if(!device)
3762 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3763 return NULL;
3766 //Validate device
3767 InitRef(&device->ref, 1);
3768 device->Connected = ALC_TRUE;
3769 device->Type = Playback;
3770 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3772 device->Flags = 0;
3773 device->Bs2b = NULL;
3774 device->Uhj_Encoder = NULL;
3775 device->Hrtf = NULL;
3776 device->HrtfHandle = NULL;
3777 VECTOR_INIT(device->HrtfList);
3778 AL_STRING_INIT(device->HrtfName);
3779 device->Render_Mode = NormalRender;
3780 AL_STRING_INIT(device->DeviceName);
3781 device->Dry.Buffer = NULL;
3782 device->Dry.NumChannels = 0;
3783 device->FOAOut.Buffer = NULL;
3784 device->FOAOut.NumChannels = 0;
3785 device->RealOut.Buffer = NULL;
3786 device->RealOut.NumChannels = 0;
3787 device->AvgSpeakerDist = 0.0f;
3789 ATOMIC_INIT(&device->ContextList, NULL);
3791 device->ClockBase = 0;
3792 device->SamplesDone = 0;
3794 device->SourcesMax = 256;
3795 device->AuxiliaryEffectSlotMax = 64;
3796 device->NumAuxSends = DEFAULT_SENDS;
3798 InitUIntMap(&device->BufferMap, INT_MAX);
3799 InitUIntMap(&device->EffectMap, INT_MAX);
3800 InitUIntMap(&device->FilterMap, INT_MAX);
3802 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
3804 device->ChannelDelay[i].Gain = 1.0f;
3805 device->ChannelDelay[i].Length = 0;
3806 device->ChannelDelay[i].Buffer = NULL;
3809 //Set output format
3810 device->FmtChans = DevFmtChannelsDefault;
3811 device->FmtType = DevFmtTypeDefault;
3812 device->Frequency = DEFAULT_OUTPUT_RATE;
3813 device->IsHeadphones = AL_FALSE;
3814 device->AmbiLayout = AmbiLayout_Default;
3815 device->AmbiScale = AmbiNorm_Default;
3816 device->NumUpdates = 3;
3817 device->UpdateSize = 1024;
3819 if(!PlaybackBackend.getFactory)
3820 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3821 ALCbackend_Playback);
3822 else
3824 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3825 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3827 if(!device->Backend)
3829 al_free(device);
3830 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3831 return NULL;
3835 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3837 static const struct {
3838 const char name[16];
3839 enum DevFmtChannels chans;
3840 ALsizei order;
3841 } chanlist[] = {
3842 { "mono", DevFmtMono, 0 },
3843 { "stereo", DevFmtStereo, 0 },
3844 { "quad", DevFmtQuad, 0 },
3845 { "surround51", DevFmtX51, 0 },
3846 { "surround61", DevFmtX61, 0 },
3847 { "surround71", DevFmtX71, 0 },
3848 { "surround51rear", DevFmtX51Rear, 0 },
3849 { "ambi1", DevFmtAmbi3D, 1 },
3850 { "ambi2", DevFmtAmbi3D, 2 },
3851 { "ambi3", DevFmtAmbi3D, 3 },
3853 size_t i;
3855 for(i = 0;i < COUNTOF(chanlist);i++)
3857 if(strcasecmp(chanlist[i].name, fmt) == 0)
3859 device->FmtChans = chanlist[i].chans;
3860 device->AmbiOrder = chanlist[i].order;
3861 device->Flags |= DEVICE_CHANNELS_REQUEST;
3862 break;
3865 if(i == COUNTOF(chanlist))
3866 ERR("Unsupported channels: %s\n", fmt);
3868 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3870 static const struct {
3871 const char name[16];
3872 enum DevFmtType type;
3873 } typelist[] = {
3874 { "int8", DevFmtByte },
3875 { "uint8", DevFmtUByte },
3876 { "int16", DevFmtShort },
3877 { "uint16", DevFmtUShort },
3878 { "int32", DevFmtInt },
3879 { "uint32", DevFmtUInt },
3880 { "float32", DevFmtFloat },
3882 size_t i;
3884 for(i = 0;i < COUNTOF(typelist);i++)
3886 if(strcasecmp(typelist[i].name, fmt) == 0)
3888 device->FmtType = typelist[i].type;
3889 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3890 break;
3893 if(i == COUNTOF(typelist))
3894 ERR("Unsupported sample-type: %s\n", fmt);
3897 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3899 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3900 if(device->Frequency < MIN_OUTPUT_RATE)
3901 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3902 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3905 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3906 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3908 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3909 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3910 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3911 device->UpdateSize = (device->UpdateSize+3)&~3;
3913 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3914 if(device->SourcesMax == 0) device->SourcesMax = 256;
3916 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3917 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3919 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
3920 device->NumAuxSends = clampi(
3921 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3924 device->NumStereoSources = 1;
3925 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3927 // Find a playback device to open
3928 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3930 DELETE_OBJ(device->Backend);
3931 al_free(device);
3932 alcSetError(NULL, err);
3933 return NULL;
3935 almtx_init(&device->BackendLock, almtx_plain);
3937 if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3939 if(strcasecmp(fmt, "fuma") == 0)
3941 device->AmbiLayout = AmbiLayout_FuMa;
3942 device->AmbiScale = AmbiNorm_FuMa;
3944 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3946 device->AmbiLayout = AmbiLayout_ACN;
3947 device->AmbiScale = AmbiNorm_SN3D;
3949 else if(strcasecmp(fmt, "acn+n3d") == 0)
3951 device->AmbiLayout = AmbiLayout_ACN;
3952 device->AmbiScale = AmbiNorm_N3D;
3954 else
3955 ERR("Unsupported ambi-format: %s\n", fmt);
3958 if(DefaultEffect.type != AL_EFFECT_NULL)
3960 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3961 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3963 device->DefaultSlot = NULL;
3964 ERR("Failed to initialize the default effect slot\n");
3966 else
3968 aluInitEffectPanning(device->DefaultSlot);
3969 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3971 DeinitEffectSlot(device->DefaultSlot);
3972 device->DefaultSlot = NULL;
3973 ERR("Failed to initialize the default effect\n");
3979 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3980 do {
3981 device->next = head;
3982 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
3985 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
3986 return device;
3989 /* alcCloseDevice
3991 * Closes the given device.
3993 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3995 ALCdevice *iter, *origdev;
3996 ALCcontext *ctx;
3998 LockLists();
3999 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4000 do {
4001 if(iter == device)
4002 break;
4003 } while((iter=iter->next) != NULL);
4004 if(!iter || iter->Type == Capture)
4006 alcSetError(iter, ALC_INVALID_DEVICE);
4007 UnlockLists();
4008 return ALC_FALSE;
4010 almtx_lock(&device->BackendLock);
4012 origdev = device;
4013 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4015 ALCdevice *volatile*list = &origdev->next;
4016 while(*list)
4018 if(*list == device)
4020 *list = (*list)->next;
4021 break;
4023 list = &(*list)->next;
4026 UnlockLists();
4028 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
4029 while(ctx != NULL)
4031 ALCcontext *next = ctx->next;
4032 WARN("Releasing context %p\n", ctx);
4033 ReleaseContext(ctx, device);
4034 ctx = next;
4036 if((device->Flags&DEVICE_RUNNING))
4037 V0(device->Backend,stop)();
4038 device->Flags &= ~DEVICE_RUNNING;
4039 almtx_unlock(&device->BackendLock);
4041 ALCdevice_DecRef(device);
4043 return ALC_TRUE;
4047 /************************************************
4048 * ALC capture functions
4049 ************************************************/
4050 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
4052 ALCdevice *device = NULL;
4053 ALCenum err;
4054 ALCsizei i;
4056 DO_INITCONFIG();
4058 if(!CaptureBackend.name)
4060 alcSetError(NULL, ALC_INVALID_VALUE);
4061 return NULL;
4064 if(samples <= 0)
4066 alcSetError(NULL, ALC_INVALID_VALUE);
4067 return NULL;
4070 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
4071 deviceName = NULL;
4073 device = al_calloc(16, sizeof(ALCdevice));
4074 if(!device)
4076 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4077 return NULL;
4080 //Validate device
4081 InitRef(&device->ref, 1);
4082 device->Connected = ALC_TRUE;
4083 device->Type = Capture;
4085 device->Hrtf = NULL;
4086 device->HrtfHandle = NULL;
4087 VECTOR_INIT(device->HrtfList);
4088 AL_STRING_INIT(device->HrtfName);
4090 AL_STRING_INIT(device->DeviceName);
4091 device->Dry.Buffer = NULL;
4092 device->Dry.NumChannels = 0;
4093 device->FOAOut.Buffer = NULL;
4094 device->FOAOut.NumChannels = 0;
4095 device->RealOut.Buffer = NULL;
4096 device->RealOut.NumChannels = 0;
4098 InitUIntMap(&device->BufferMap, INT_MAX);
4099 InitUIntMap(&device->EffectMap, INT_MAX);
4100 InitUIntMap(&device->FilterMap, INT_MAX);
4102 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4104 device->ChannelDelay[i].Gain = 1.0f;
4105 device->ChannelDelay[i].Length = 0;
4106 device->ChannelDelay[i].Buffer = NULL;
4109 if(!CaptureBackend.getFactory)
4110 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
4111 ALCbackend_Capture);
4112 else
4114 ALCbackendFactory *factory = CaptureBackend.getFactory();
4115 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
4117 if(!device->Backend)
4119 al_free(device);
4120 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4121 return NULL;
4124 device->Flags |= DEVICE_FREQUENCY_REQUEST;
4125 device->Frequency = frequency;
4127 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
4128 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
4130 al_free(device);
4131 alcSetError(NULL, ALC_INVALID_ENUM);
4132 return NULL;
4134 device->IsHeadphones = AL_FALSE;
4135 device->AmbiOrder = 0;
4136 device->AmbiLayout = AmbiLayout_Default;
4137 device->AmbiScale = AmbiNorm_Default;
4139 device->UpdateSize = samples;
4140 device->NumUpdates = 1;
4142 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4143 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
4144 device->Frequency, device->UpdateSize, device->NumUpdates
4146 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
4148 al_free(device);
4149 alcSetError(NULL, err);
4150 return NULL;
4152 almtx_init(&device->BackendLock, almtx_plain);
4155 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4156 do {
4157 device->next = head;
4158 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4161 TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName));
4162 return device;
4165 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
4167 ALCdevice *iter, *origdev;
4169 LockLists();
4170 iter = ATOMIC_LOAD_SEQ(&DeviceList);
4171 do {
4172 if(iter == device)
4173 break;
4174 } while((iter=iter->next) != NULL);
4175 if(!iter || iter->Type != Capture)
4177 alcSetError(iter, ALC_INVALID_DEVICE);
4178 UnlockLists();
4179 return ALC_FALSE;
4182 origdev = device;
4183 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next))
4185 ALCdevice *volatile*list = &origdev->next;
4186 while(*list)
4188 if(*list == device)
4190 *list = (*list)->next;
4191 break;
4193 list = &(*list)->next;
4196 UnlockLists();
4198 ALCdevice_DecRef(device);
4200 return ALC_TRUE;
4203 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4205 if(!VerifyDevice(&device) || device->Type != Capture)
4206 alcSetError(device, ALC_INVALID_DEVICE);
4207 else
4209 almtx_lock(&device->BackendLock);
4210 if(!device->Connected)
4211 alcSetError(device, ALC_INVALID_DEVICE);
4212 else if(!(device->Flags&DEVICE_RUNNING))
4214 if(V0(device->Backend,start)())
4215 device->Flags |= DEVICE_RUNNING;
4216 else
4218 aluHandleDisconnect(device);
4219 alcSetError(device, ALC_INVALID_DEVICE);
4222 almtx_unlock(&device->BackendLock);
4225 if(device) ALCdevice_DecRef(device);
4228 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4230 if(!VerifyDevice(&device) || device->Type != Capture)
4231 alcSetError(device, ALC_INVALID_DEVICE);
4232 else
4234 almtx_lock(&device->BackendLock);
4235 if((device->Flags&DEVICE_RUNNING))
4236 V0(device->Backend,stop)();
4237 device->Flags &= ~DEVICE_RUNNING;
4238 almtx_unlock(&device->BackendLock);
4241 if(device) ALCdevice_DecRef(device);
4244 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4246 if(!VerifyDevice(&device) || device->Type != Capture)
4247 alcSetError(device, ALC_INVALID_DEVICE);
4248 else
4250 ALCenum err = ALC_INVALID_VALUE;
4252 almtx_lock(&device->BackendLock);
4253 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4254 err = V(device->Backend,captureSamples)(buffer, samples);
4255 almtx_unlock(&device->BackendLock);
4257 if(err != ALC_NO_ERROR)
4258 alcSetError(device, err);
4260 if(device) ALCdevice_DecRef(device);
4264 /************************************************
4265 * ALC loopback functions
4266 ************************************************/
4268 /* alcLoopbackOpenDeviceSOFT
4270 * Open a loopback device, for manual rendering.
4272 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4274 ALCbackendFactory *factory;
4275 ALCdevice *device;
4276 ALCsizei i;
4278 DO_INITCONFIG();
4280 /* Make sure the device name, if specified, is us. */
4281 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4283 alcSetError(NULL, ALC_INVALID_VALUE);
4284 return NULL;
4287 device = al_calloc(16, sizeof(ALCdevice));
4288 if(!device)
4290 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4291 return NULL;
4294 //Validate device
4295 InitRef(&device->ref, 1);
4296 device->Connected = ALC_TRUE;
4297 device->Type = Loopback;
4298 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4300 device->Flags = 0;
4301 device->Hrtf = NULL;
4302 device->HrtfHandle = NULL;
4303 VECTOR_INIT(device->HrtfList);
4304 AL_STRING_INIT(device->HrtfName);
4305 device->Bs2b = NULL;
4306 device->Uhj_Encoder = NULL;
4307 device->Render_Mode = NormalRender;
4308 AL_STRING_INIT(device->DeviceName);
4309 device->Dry.Buffer = NULL;
4310 device->Dry.NumChannels = 0;
4311 device->FOAOut.Buffer = NULL;
4312 device->FOAOut.NumChannels = 0;
4313 device->RealOut.Buffer = NULL;
4314 device->RealOut.NumChannels = 0;
4315 device->AvgSpeakerDist = 0.0f;
4317 ATOMIC_INIT(&device->ContextList, NULL);
4319 device->ClockBase = 0;
4320 device->SamplesDone = 0;
4322 device->SourcesMax = 256;
4323 device->AuxiliaryEffectSlotMax = 64;
4324 device->NumAuxSends = DEFAULT_SENDS;
4326 InitUIntMap(&device->BufferMap, INT_MAX);
4327 InitUIntMap(&device->EffectMap, INT_MAX);
4328 InitUIntMap(&device->FilterMap, INT_MAX);
4330 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
4332 device->ChannelDelay[i].Gain = 1.0f;
4333 device->ChannelDelay[i].Length = 0;
4334 device->ChannelDelay[i].Buffer = NULL;
4337 factory = ALCloopbackFactory_getFactory();
4338 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4339 if(!device->Backend)
4341 al_free(device);
4342 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4343 return NULL;
4345 almtx_init(&device->BackendLock, almtx_plain);
4347 //Set output format
4348 device->NumUpdates = 0;
4349 device->UpdateSize = 0;
4351 device->Frequency = DEFAULT_OUTPUT_RATE;
4352 device->FmtChans = DevFmtChannelsDefault;
4353 device->FmtType = DevFmtTypeDefault;
4354 device->IsHeadphones = AL_FALSE;
4355 device->AmbiLayout = AmbiLayout_Default;
4356 device->AmbiScale = AmbiNorm_Default;
4358 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4359 if(device->SourcesMax == 0) device->SourcesMax = 256;
4361 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4362 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4364 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4365 device->NumAuxSends = clampi(
4366 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4369 device->NumStereoSources = 1;
4370 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4372 // Open the "backend"
4373 V(device->Backend,open)("Loopback");
4376 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4377 do {
4378 device->next = head;
4379 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device));
4382 TRACE("Created device %p\n", device);
4383 return device;
4386 /* alcIsRenderFormatSupportedSOFT
4388 * Determines if the loopback device supports the given format for rendering.
4390 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4392 ALCboolean ret = ALC_FALSE;
4394 if(!VerifyDevice(&device) || device->Type != Loopback)
4395 alcSetError(device, ALC_INVALID_DEVICE);
4396 else if(freq <= 0)
4397 alcSetError(device, ALC_INVALID_VALUE);
4398 else
4400 if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
4401 ret = ALC_TRUE;
4403 if(device) ALCdevice_DecRef(device);
4405 return ret;
4408 /* alcRenderSamplesSOFT
4410 * Renders some samples into a buffer, using the format last set by the
4411 * attributes given to alcCreateContext.
4413 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4415 if(!VerifyDevice(&device) || device->Type != Loopback)
4416 alcSetError(device, ALC_INVALID_DEVICE);
4417 else if(samples < 0 || (samples > 0 && buffer == NULL))
4418 alcSetError(device, ALC_INVALID_VALUE);
4419 else
4421 V0(device->Backend,lock)();
4422 aluMixData(device, buffer, samples);
4423 V0(device->Backend,unlock)();
4425 if(device) ALCdevice_DecRef(device);
4429 /************************************************
4430 * ALC loopback2 functions
4431 ************************************************/
4433 ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order)
4435 ALCboolean ret = ALC_FALSE;
4437 if(!VerifyDevice(&device) || device->Type != Loopback)
4438 alcSetError(device, ALC_INVALID_DEVICE);
4439 else if(order <= 0)
4440 alcSetError(device, ALC_INVALID_VALUE);
4441 else
4443 if(IsValidAmbiLayout(layout) && IsValidAmbiScaling(scaling) && order <= MAX_AMBI_ORDER)
4444 ret = ALC_TRUE;
4446 if(device) ALCdevice_DecRef(device);
4448 return ret;
4451 /************************************************
4452 * ALC DSP pause/resume functions
4453 ************************************************/
4455 /* alcDevicePauseSOFT
4457 * Pause the DSP to stop audio processing.
4459 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4461 if(!VerifyDevice(&device) || device->Type != Playback)
4462 alcSetError(device, ALC_INVALID_DEVICE);
4463 else
4465 almtx_lock(&device->BackendLock);
4466 if((device->Flags&DEVICE_RUNNING))
4467 V0(device->Backend,stop)();
4468 device->Flags &= ~DEVICE_RUNNING;
4469 device->Flags |= DEVICE_PAUSED;
4470 almtx_unlock(&device->BackendLock);
4472 if(device) ALCdevice_DecRef(device);
4475 /* alcDeviceResumeSOFT
4477 * Resume the DSP to restart audio processing.
4479 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4481 if(!VerifyDevice(&device) || device->Type != Playback)
4482 alcSetError(device, ALC_INVALID_DEVICE);
4483 else
4485 almtx_lock(&device->BackendLock);
4486 if((device->Flags&DEVICE_PAUSED))
4488 device->Flags &= ~DEVICE_PAUSED;
4489 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4491 if(V0(device->Backend,start)() != ALC_FALSE)
4492 device->Flags |= DEVICE_RUNNING;
4493 else
4495 alcSetError(device, ALC_INVALID_DEVICE);
4496 V0(device->Backend,lock)();
4497 aluHandleDisconnect(device);
4498 V0(device->Backend,unlock)();
4502 almtx_unlock(&device->BackendLock);
4504 if(device) ALCdevice_DecRef(device);
4508 /************************************************
4509 * ALC HRTF functions
4510 ************************************************/
4512 /* alcGetStringiSOFT
4514 * Gets a string parameter at the given index.
4516 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4518 const ALCchar *str = NULL;
4520 if(!VerifyDevice(&device) || device->Type == Capture)
4521 alcSetError(device, ALC_INVALID_DEVICE);
4522 else switch(paramName)
4524 case ALC_HRTF_SPECIFIER_SOFT:
4525 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList))
4526 str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name);
4527 else
4528 alcSetError(device, ALC_INVALID_VALUE);
4529 break;
4531 default:
4532 alcSetError(device, ALC_INVALID_ENUM);
4533 break;
4535 if(device) ALCdevice_DecRef(device);
4537 return str;
4540 /* alcResetDeviceSOFT
4542 * Resets the given device output, using the specified attribute list.
4544 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4546 ALCenum err;
4548 LockLists();
4549 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4551 UnlockLists();
4552 alcSetError(device, ALC_INVALID_DEVICE);
4553 if(device) ALCdevice_DecRef(device);
4554 return ALC_FALSE;
4556 almtx_lock(&device->BackendLock);
4557 UnlockLists();
4559 err = UpdateDeviceParams(device, attribs);
4560 almtx_unlock(&device->BackendLock);
4562 if(err != ALC_NO_ERROR)
4564 alcSetError(device, err);
4565 if(err == ALC_INVALID_DEVICE)
4567 V0(device->Backend,lock)();
4568 aluHandleDisconnect(device);
4569 V0(device->Backend,unlock)();
4571 ALCdevice_DecRef(device);
4572 return ALC_FALSE;
4574 ALCdevice_DecRef(device);
4576 return ALC_TRUE;