Make the voices' Send[] array dynamically sized
[openal-soft.git] / Alc / ALc.c
blob5a382d6e1c2a97ce5f610ab4c156199be37e552d
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include <signal.h>
32 #include "alMain.h"
33 #include "alSource.h"
34 #include "alListener.h"
35 #include "alThunk.h"
36 #include "alSource.h"
37 #include "alBuffer.h"
38 #include "alAuxEffectSlot.h"
39 #include "alError.h"
40 #include "bformatdec.h"
41 #include "alu.h"
43 #include "compat.h"
44 #include "threads.h"
45 #include "alstring.h"
46 #include "almalloc.h"
48 #include "backends/base.h"
51 /************************************************
52 * Backends
53 ************************************************/
54 struct BackendInfo {
55 const char *name;
56 ALCbackendFactory* (*getFactory)(void);
57 ALCboolean (*Init)(BackendFuncs*);
58 void (*Deinit)(void);
59 void (*Probe)(enum DevProbe);
60 BackendFuncs Funcs;
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList[] = {
65 #ifdef HAVE_JACK
66 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
67 #endif
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
70 #endif
71 #ifdef HAVE_ALSA
72 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
73 #endif
74 #ifdef HAVE_COREAUDIO
75 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
76 #endif
77 #ifdef HAVE_OSS
78 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
79 #endif
80 #ifdef HAVE_SOLARIS
81 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
82 #endif
83 #ifdef HAVE_SNDIO
84 { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
85 #endif
86 #ifdef HAVE_QSA
87 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
88 #endif
89 #ifdef HAVE_MMDEVAPI
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
91 #endif
92 #ifdef HAVE_DSOUND
93 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
94 #endif
95 #ifdef HAVE_WINMM
96 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
97 #endif
98 #ifdef HAVE_PORTAUDIO
99 { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
100 #endif
101 #ifdef HAVE_OPENSL
102 { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
103 #endif
105 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
106 #ifdef HAVE_WAVE
107 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
108 #endif
110 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
112 #undef EmptyFuncs
114 static struct BackendInfo PlaybackBackend;
115 static struct BackendInfo CaptureBackend;
118 /************************************************
119 * Functions, enums, and errors
120 ************************************************/
121 typedef struct ALCfunction {
122 const ALCchar *funcName;
123 ALCvoid *address;
124 } ALCfunction;
126 typedef struct ALCenums {
127 const ALCchar *enumName;
128 ALCenum value;
129 } ALCenums;
131 #define DECL(x) { #x, (ALCvoid*)(x) }
132 static const ALCfunction alcFunctions[] = {
133 DECL(alcCreateContext),
134 DECL(alcMakeContextCurrent),
135 DECL(alcProcessContext),
136 DECL(alcSuspendContext),
137 DECL(alcDestroyContext),
138 DECL(alcGetCurrentContext),
139 DECL(alcGetContextsDevice),
140 DECL(alcOpenDevice),
141 DECL(alcCloseDevice),
142 DECL(alcGetError),
143 DECL(alcIsExtensionPresent),
144 DECL(alcGetProcAddress),
145 DECL(alcGetEnumValue),
146 DECL(alcGetString),
147 DECL(alcGetIntegerv),
148 DECL(alcCaptureOpenDevice),
149 DECL(alcCaptureCloseDevice),
150 DECL(alcCaptureStart),
151 DECL(alcCaptureStop),
152 DECL(alcCaptureSamples),
154 DECL(alcSetThreadContext),
155 DECL(alcGetThreadContext),
157 DECL(alcLoopbackOpenDeviceSOFT),
158 DECL(alcIsRenderFormatSupportedSOFT),
159 DECL(alcRenderSamplesSOFT),
161 DECL(alcDevicePauseSOFT),
162 DECL(alcDeviceResumeSOFT),
164 DECL(alcGetStringiSOFT),
165 DECL(alcResetDeviceSOFT),
167 DECL(alcGetInteger64vSOFT),
169 DECL(alEnable),
170 DECL(alDisable),
171 DECL(alIsEnabled),
172 DECL(alGetString),
173 DECL(alGetBooleanv),
174 DECL(alGetIntegerv),
175 DECL(alGetFloatv),
176 DECL(alGetDoublev),
177 DECL(alGetBoolean),
178 DECL(alGetInteger),
179 DECL(alGetFloat),
180 DECL(alGetDouble),
181 DECL(alGetError),
182 DECL(alIsExtensionPresent),
183 DECL(alGetProcAddress),
184 DECL(alGetEnumValue),
185 DECL(alListenerf),
186 DECL(alListener3f),
187 DECL(alListenerfv),
188 DECL(alListeneri),
189 DECL(alListener3i),
190 DECL(alListeneriv),
191 DECL(alGetListenerf),
192 DECL(alGetListener3f),
193 DECL(alGetListenerfv),
194 DECL(alGetListeneri),
195 DECL(alGetListener3i),
196 DECL(alGetListeneriv),
197 DECL(alGenSources),
198 DECL(alDeleteSources),
199 DECL(alIsSource),
200 DECL(alSourcef),
201 DECL(alSource3f),
202 DECL(alSourcefv),
203 DECL(alSourcei),
204 DECL(alSource3i),
205 DECL(alSourceiv),
206 DECL(alGetSourcef),
207 DECL(alGetSource3f),
208 DECL(alGetSourcefv),
209 DECL(alGetSourcei),
210 DECL(alGetSource3i),
211 DECL(alGetSourceiv),
212 DECL(alSourcePlayv),
213 DECL(alSourceStopv),
214 DECL(alSourceRewindv),
215 DECL(alSourcePausev),
216 DECL(alSourcePlay),
217 DECL(alSourceStop),
218 DECL(alSourceRewind),
219 DECL(alSourcePause),
220 DECL(alSourceQueueBuffers),
221 DECL(alSourceUnqueueBuffers),
222 DECL(alGenBuffers),
223 DECL(alDeleteBuffers),
224 DECL(alIsBuffer),
225 DECL(alBufferData),
226 DECL(alBufferf),
227 DECL(alBuffer3f),
228 DECL(alBufferfv),
229 DECL(alBufferi),
230 DECL(alBuffer3i),
231 DECL(alBufferiv),
232 DECL(alGetBufferf),
233 DECL(alGetBuffer3f),
234 DECL(alGetBufferfv),
235 DECL(alGetBufferi),
236 DECL(alGetBuffer3i),
237 DECL(alGetBufferiv),
238 DECL(alDopplerFactor),
239 DECL(alDopplerVelocity),
240 DECL(alSpeedOfSound),
241 DECL(alDistanceModel),
243 DECL(alGenFilters),
244 DECL(alDeleteFilters),
245 DECL(alIsFilter),
246 DECL(alFilteri),
247 DECL(alFilteriv),
248 DECL(alFilterf),
249 DECL(alFilterfv),
250 DECL(alGetFilteri),
251 DECL(alGetFilteriv),
252 DECL(alGetFilterf),
253 DECL(alGetFilterfv),
254 DECL(alGenEffects),
255 DECL(alDeleteEffects),
256 DECL(alIsEffect),
257 DECL(alEffecti),
258 DECL(alEffectiv),
259 DECL(alEffectf),
260 DECL(alEffectfv),
261 DECL(alGetEffecti),
262 DECL(alGetEffectiv),
263 DECL(alGetEffectf),
264 DECL(alGetEffectfv),
265 DECL(alGenAuxiliaryEffectSlots),
266 DECL(alDeleteAuxiliaryEffectSlots),
267 DECL(alIsAuxiliaryEffectSlot),
268 DECL(alAuxiliaryEffectSloti),
269 DECL(alAuxiliaryEffectSlotiv),
270 DECL(alAuxiliaryEffectSlotf),
271 DECL(alAuxiliaryEffectSlotfv),
272 DECL(alGetAuxiliaryEffectSloti),
273 DECL(alGetAuxiliaryEffectSlotiv),
274 DECL(alGetAuxiliaryEffectSlotf),
275 DECL(alGetAuxiliaryEffectSlotfv),
277 DECL(alDeferUpdatesSOFT),
278 DECL(alProcessUpdatesSOFT),
280 DECL(alSourcedSOFT),
281 DECL(alSource3dSOFT),
282 DECL(alSourcedvSOFT),
283 DECL(alGetSourcedSOFT),
284 DECL(alGetSource3dSOFT),
285 DECL(alGetSourcedvSOFT),
286 DECL(alSourcei64SOFT),
287 DECL(alSource3i64SOFT),
288 DECL(alSourcei64vSOFT),
289 DECL(alGetSourcei64SOFT),
290 DECL(alGetSource3i64SOFT),
291 DECL(alGetSourcei64vSOFT),
293 DECL(alBufferSamplesSOFT),
294 DECL(alGetBufferSamplesSOFT),
295 DECL(alIsBufferFormatSupportedSOFT),
297 { NULL, NULL }
299 #undef DECL
301 #define DECL(x) { #x, (x) }
302 static const ALCenums enumeration[] = {
303 DECL(ALC_INVALID),
304 DECL(ALC_FALSE),
305 DECL(ALC_TRUE),
307 DECL(ALC_MAJOR_VERSION),
308 DECL(ALC_MINOR_VERSION),
309 DECL(ALC_ATTRIBUTES_SIZE),
310 DECL(ALC_ALL_ATTRIBUTES),
311 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
312 DECL(ALC_DEVICE_SPECIFIER),
313 DECL(ALC_ALL_DEVICES_SPECIFIER),
314 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
315 DECL(ALC_EXTENSIONS),
316 DECL(ALC_FREQUENCY),
317 DECL(ALC_REFRESH),
318 DECL(ALC_SYNC),
319 DECL(ALC_MONO_SOURCES),
320 DECL(ALC_STEREO_SOURCES),
321 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
322 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
323 DECL(ALC_CAPTURE_SAMPLES),
324 DECL(ALC_CONNECTED),
326 DECL(ALC_EFX_MAJOR_VERSION),
327 DECL(ALC_EFX_MINOR_VERSION),
328 DECL(ALC_MAX_AUXILIARY_SENDS),
330 DECL(ALC_FORMAT_CHANNELS_SOFT),
331 DECL(ALC_FORMAT_TYPE_SOFT),
333 DECL(ALC_MONO_SOFT),
334 DECL(ALC_STEREO_SOFT),
335 DECL(ALC_QUAD_SOFT),
336 DECL(ALC_5POINT1_SOFT),
337 DECL(ALC_6POINT1_SOFT),
338 DECL(ALC_7POINT1_SOFT),
340 DECL(ALC_BYTE_SOFT),
341 DECL(ALC_UNSIGNED_BYTE_SOFT),
342 DECL(ALC_SHORT_SOFT),
343 DECL(ALC_UNSIGNED_SHORT_SOFT),
344 DECL(ALC_INT_SOFT),
345 DECL(ALC_UNSIGNED_INT_SOFT),
346 DECL(ALC_FLOAT_SOFT),
348 DECL(ALC_HRTF_SOFT),
349 DECL(ALC_DONT_CARE_SOFT),
350 DECL(ALC_HRTF_STATUS_SOFT),
351 DECL(ALC_HRTF_DISABLED_SOFT),
352 DECL(ALC_HRTF_ENABLED_SOFT),
353 DECL(ALC_HRTF_DENIED_SOFT),
354 DECL(ALC_HRTF_REQUIRED_SOFT),
355 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT),
356 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT),
357 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT),
358 DECL(ALC_HRTF_SPECIFIER_SOFT),
359 DECL(ALC_HRTF_ID_SOFT),
361 DECL(ALC_NO_ERROR),
362 DECL(ALC_INVALID_DEVICE),
363 DECL(ALC_INVALID_CONTEXT),
364 DECL(ALC_INVALID_ENUM),
365 DECL(ALC_INVALID_VALUE),
366 DECL(ALC_OUT_OF_MEMORY),
369 DECL(AL_INVALID),
370 DECL(AL_NONE),
371 DECL(AL_FALSE),
372 DECL(AL_TRUE),
374 DECL(AL_SOURCE_RELATIVE),
375 DECL(AL_CONE_INNER_ANGLE),
376 DECL(AL_CONE_OUTER_ANGLE),
377 DECL(AL_PITCH),
378 DECL(AL_POSITION),
379 DECL(AL_DIRECTION),
380 DECL(AL_VELOCITY),
381 DECL(AL_LOOPING),
382 DECL(AL_BUFFER),
383 DECL(AL_GAIN),
384 DECL(AL_MIN_GAIN),
385 DECL(AL_MAX_GAIN),
386 DECL(AL_ORIENTATION),
387 DECL(AL_REFERENCE_DISTANCE),
388 DECL(AL_ROLLOFF_FACTOR),
389 DECL(AL_CONE_OUTER_GAIN),
390 DECL(AL_MAX_DISTANCE),
391 DECL(AL_SEC_OFFSET),
392 DECL(AL_SAMPLE_OFFSET),
393 DECL(AL_BYTE_OFFSET),
394 DECL(AL_SOURCE_TYPE),
395 DECL(AL_STATIC),
396 DECL(AL_STREAMING),
397 DECL(AL_UNDETERMINED),
398 DECL(AL_METERS_PER_UNIT),
399 DECL(AL_LOOP_POINTS_SOFT),
400 DECL(AL_DIRECT_CHANNELS_SOFT),
402 DECL(AL_DIRECT_FILTER),
403 DECL(AL_AUXILIARY_SEND_FILTER),
404 DECL(AL_AIR_ABSORPTION_FACTOR),
405 DECL(AL_ROOM_ROLLOFF_FACTOR),
406 DECL(AL_CONE_OUTER_GAINHF),
407 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
408 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
409 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
411 DECL(AL_SOURCE_STATE),
412 DECL(AL_INITIAL),
413 DECL(AL_PLAYING),
414 DECL(AL_PAUSED),
415 DECL(AL_STOPPED),
417 DECL(AL_BUFFERS_QUEUED),
418 DECL(AL_BUFFERS_PROCESSED),
420 DECL(AL_FORMAT_MONO8),
421 DECL(AL_FORMAT_MONO16),
422 DECL(AL_FORMAT_MONO_FLOAT32),
423 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
424 DECL(AL_FORMAT_STEREO8),
425 DECL(AL_FORMAT_STEREO16),
426 DECL(AL_FORMAT_STEREO_FLOAT32),
427 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
428 DECL(AL_FORMAT_MONO_IMA4),
429 DECL(AL_FORMAT_STEREO_IMA4),
430 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
431 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
432 DECL(AL_FORMAT_QUAD8_LOKI),
433 DECL(AL_FORMAT_QUAD16_LOKI),
434 DECL(AL_FORMAT_QUAD8),
435 DECL(AL_FORMAT_QUAD16),
436 DECL(AL_FORMAT_QUAD32),
437 DECL(AL_FORMAT_51CHN8),
438 DECL(AL_FORMAT_51CHN16),
439 DECL(AL_FORMAT_51CHN32),
440 DECL(AL_FORMAT_61CHN8),
441 DECL(AL_FORMAT_61CHN16),
442 DECL(AL_FORMAT_61CHN32),
443 DECL(AL_FORMAT_71CHN8),
444 DECL(AL_FORMAT_71CHN16),
445 DECL(AL_FORMAT_71CHN32),
446 DECL(AL_FORMAT_REAR8),
447 DECL(AL_FORMAT_REAR16),
448 DECL(AL_FORMAT_REAR32),
449 DECL(AL_FORMAT_MONO_MULAW),
450 DECL(AL_FORMAT_MONO_MULAW_EXT),
451 DECL(AL_FORMAT_STEREO_MULAW),
452 DECL(AL_FORMAT_STEREO_MULAW_EXT),
453 DECL(AL_FORMAT_QUAD_MULAW),
454 DECL(AL_FORMAT_51CHN_MULAW),
455 DECL(AL_FORMAT_61CHN_MULAW),
456 DECL(AL_FORMAT_71CHN_MULAW),
457 DECL(AL_FORMAT_REAR_MULAW),
458 DECL(AL_FORMAT_MONO_ALAW_EXT),
459 DECL(AL_FORMAT_STEREO_ALAW_EXT),
461 DECL(AL_FORMAT_BFORMAT2D_8),
462 DECL(AL_FORMAT_BFORMAT2D_16),
463 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
464 DECL(AL_FORMAT_BFORMAT2D_MULAW),
465 DECL(AL_FORMAT_BFORMAT3D_8),
466 DECL(AL_FORMAT_BFORMAT3D_16),
467 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
468 DECL(AL_FORMAT_BFORMAT3D_MULAW),
470 DECL(AL_MONO8_SOFT),
471 DECL(AL_MONO16_SOFT),
472 DECL(AL_MONO32F_SOFT),
473 DECL(AL_STEREO8_SOFT),
474 DECL(AL_STEREO16_SOFT),
475 DECL(AL_STEREO32F_SOFT),
476 DECL(AL_QUAD8_SOFT),
477 DECL(AL_QUAD16_SOFT),
478 DECL(AL_QUAD32F_SOFT),
479 DECL(AL_REAR8_SOFT),
480 DECL(AL_REAR16_SOFT),
481 DECL(AL_REAR32F_SOFT),
482 DECL(AL_5POINT1_8_SOFT),
483 DECL(AL_5POINT1_16_SOFT),
484 DECL(AL_5POINT1_32F_SOFT),
485 DECL(AL_6POINT1_8_SOFT),
486 DECL(AL_6POINT1_16_SOFT),
487 DECL(AL_6POINT1_32F_SOFT),
488 DECL(AL_7POINT1_8_SOFT),
489 DECL(AL_7POINT1_16_SOFT),
490 DECL(AL_7POINT1_32F_SOFT),
491 DECL(AL_BFORMAT2D_8_SOFT),
492 DECL(AL_BFORMAT2D_16_SOFT),
493 DECL(AL_BFORMAT2D_32F_SOFT),
494 DECL(AL_BFORMAT3D_8_SOFT),
495 DECL(AL_BFORMAT3D_16_SOFT),
496 DECL(AL_BFORMAT3D_32F_SOFT),
498 DECL(AL_MONO_SOFT),
499 DECL(AL_STEREO_SOFT),
500 DECL(AL_QUAD_SOFT),
501 DECL(AL_REAR_SOFT),
502 DECL(AL_5POINT1_SOFT),
503 DECL(AL_6POINT1_SOFT),
504 DECL(AL_7POINT1_SOFT),
505 DECL(AL_BFORMAT2D_SOFT),
506 DECL(AL_BFORMAT3D_SOFT),
508 DECL(AL_BYTE_SOFT),
509 DECL(AL_UNSIGNED_BYTE_SOFT),
510 DECL(AL_SHORT_SOFT),
511 DECL(AL_UNSIGNED_SHORT_SOFT),
512 DECL(AL_INT_SOFT),
513 DECL(AL_UNSIGNED_INT_SOFT),
514 DECL(AL_FLOAT_SOFT),
515 DECL(AL_DOUBLE_SOFT),
516 DECL(AL_BYTE3_SOFT),
517 DECL(AL_UNSIGNED_BYTE3_SOFT),
518 DECL(AL_MULAW_SOFT),
520 DECL(AL_FREQUENCY),
521 DECL(AL_BITS),
522 DECL(AL_CHANNELS),
523 DECL(AL_SIZE),
524 DECL(AL_INTERNAL_FORMAT_SOFT),
525 DECL(AL_BYTE_LENGTH_SOFT),
526 DECL(AL_SAMPLE_LENGTH_SOFT),
527 DECL(AL_SEC_LENGTH_SOFT),
528 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
531 DECL(AL_SOURCE_RADIUS),
533 DECL(AL_STEREO_ANGLES),
535 DECL(AL_UNUSED),
536 DECL(AL_PENDING),
537 DECL(AL_PROCESSED),
539 DECL(AL_NO_ERROR),
540 DECL(AL_INVALID_NAME),
541 DECL(AL_INVALID_ENUM),
542 DECL(AL_INVALID_VALUE),
543 DECL(AL_INVALID_OPERATION),
544 DECL(AL_OUT_OF_MEMORY),
546 DECL(AL_VENDOR),
547 DECL(AL_VERSION),
548 DECL(AL_RENDERER),
549 DECL(AL_EXTENSIONS),
551 DECL(AL_DOPPLER_FACTOR),
552 DECL(AL_DOPPLER_VELOCITY),
553 DECL(AL_DISTANCE_MODEL),
554 DECL(AL_SPEED_OF_SOUND),
555 DECL(AL_SOURCE_DISTANCE_MODEL),
556 DECL(AL_DEFERRED_UPDATES_SOFT),
557 DECL(AL_GAIN_LIMIT_SOFT),
559 DECL(AL_INVERSE_DISTANCE),
560 DECL(AL_INVERSE_DISTANCE_CLAMPED),
561 DECL(AL_LINEAR_DISTANCE),
562 DECL(AL_LINEAR_DISTANCE_CLAMPED),
563 DECL(AL_EXPONENT_DISTANCE),
564 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
566 DECL(AL_FILTER_TYPE),
567 DECL(AL_FILTER_NULL),
568 DECL(AL_FILTER_LOWPASS),
569 DECL(AL_FILTER_HIGHPASS),
570 DECL(AL_FILTER_BANDPASS),
572 DECL(AL_LOWPASS_GAIN),
573 DECL(AL_LOWPASS_GAINHF),
575 DECL(AL_HIGHPASS_GAIN),
576 DECL(AL_HIGHPASS_GAINLF),
578 DECL(AL_BANDPASS_GAIN),
579 DECL(AL_BANDPASS_GAINHF),
580 DECL(AL_BANDPASS_GAINLF),
582 DECL(AL_EFFECT_TYPE),
583 DECL(AL_EFFECT_NULL),
584 DECL(AL_EFFECT_REVERB),
585 DECL(AL_EFFECT_EAXREVERB),
586 DECL(AL_EFFECT_CHORUS),
587 DECL(AL_EFFECT_DISTORTION),
588 DECL(AL_EFFECT_ECHO),
589 DECL(AL_EFFECT_FLANGER),
590 #if 0
591 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
592 DECL(AL_EFFECT_VOCAL_MORPHER),
593 DECL(AL_EFFECT_PITCH_SHIFTER),
594 #endif
595 DECL(AL_EFFECT_RING_MODULATOR),
596 #if 0
597 DECL(AL_EFFECT_AUTOWAH),
598 #endif
599 DECL(AL_EFFECT_COMPRESSOR),
600 DECL(AL_EFFECT_EQUALIZER),
601 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
602 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
604 DECL(AL_EFFECTSLOT_EFFECT),
605 DECL(AL_EFFECTSLOT_GAIN),
606 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO),
607 DECL(AL_EFFECTSLOT_NULL),
609 DECL(AL_EAXREVERB_DENSITY),
610 DECL(AL_EAXREVERB_DIFFUSION),
611 DECL(AL_EAXREVERB_GAIN),
612 DECL(AL_EAXREVERB_GAINHF),
613 DECL(AL_EAXREVERB_GAINLF),
614 DECL(AL_EAXREVERB_DECAY_TIME),
615 DECL(AL_EAXREVERB_DECAY_HFRATIO),
616 DECL(AL_EAXREVERB_DECAY_LFRATIO),
617 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
618 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
619 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
620 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
621 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
622 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
623 DECL(AL_EAXREVERB_ECHO_TIME),
624 DECL(AL_EAXREVERB_ECHO_DEPTH),
625 DECL(AL_EAXREVERB_MODULATION_TIME),
626 DECL(AL_EAXREVERB_MODULATION_DEPTH),
627 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
628 DECL(AL_EAXREVERB_HFREFERENCE),
629 DECL(AL_EAXREVERB_LFREFERENCE),
630 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
631 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
633 DECL(AL_REVERB_DENSITY),
634 DECL(AL_REVERB_DIFFUSION),
635 DECL(AL_REVERB_GAIN),
636 DECL(AL_REVERB_GAINHF),
637 DECL(AL_REVERB_DECAY_TIME),
638 DECL(AL_REVERB_DECAY_HFRATIO),
639 DECL(AL_REVERB_REFLECTIONS_GAIN),
640 DECL(AL_REVERB_REFLECTIONS_DELAY),
641 DECL(AL_REVERB_LATE_REVERB_GAIN),
642 DECL(AL_REVERB_LATE_REVERB_DELAY),
643 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
644 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
645 DECL(AL_REVERB_DECAY_HFLIMIT),
647 DECL(AL_CHORUS_WAVEFORM),
648 DECL(AL_CHORUS_PHASE),
649 DECL(AL_CHORUS_RATE),
650 DECL(AL_CHORUS_DEPTH),
651 DECL(AL_CHORUS_FEEDBACK),
652 DECL(AL_CHORUS_DELAY),
654 DECL(AL_DISTORTION_EDGE),
655 DECL(AL_DISTORTION_GAIN),
656 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
657 DECL(AL_DISTORTION_EQCENTER),
658 DECL(AL_DISTORTION_EQBANDWIDTH),
660 DECL(AL_ECHO_DELAY),
661 DECL(AL_ECHO_LRDELAY),
662 DECL(AL_ECHO_DAMPING),
663 DECL(AL_ECHO_FEEDBACK),
664 DECL(AL_ECHO_SPREAD),
666 DECL(AL_FLANGER_WAVEFORM),
667 DECL(AL_FLANGER_PHASE),
668 DECL(AL_FLANGER_RATE),
669 DECL(AL_FLANGER_DEPTH),
670 DECL(AL_FLANGER_FEEDBACK),
671 DECL(AL_FLANGER_DELAY),
673 DECL(AL_RING_MODULATOR_FREQUENCY),
674 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
675 DECL(AL_RING_MODULATOR_WAVEFORM),
677 DECL(AL_COMPRESSOR_ONOFF),
679 DECL(AL_EQUALIZER_LOW_GAIN),
680 DECL(AL_EQUALIZER_LOW_CUTOFF),
681 DECL(AL_EQUALIZER_MID1_GAIN),
682 DECL(AL_EQUALIZER_MID1_CENTER),
683 DECL(AL_EQUALIZER_MID1_WIDTH),
684 DECL(AL_EQUALIZER_MID2_GAIN),
685 DECL(AL_EQUALIZER_MID2_CENTER),
686 DECL(AL_EQUALIZER_MID2_WIDTH),
687 DECL(AL_EQUALIZER_HIGH_GAIN),
688 DECL(AL_EQUALIZER_HIGH_CUTOFF),
690 DECL(AL_DEDICATED_GAIN),
692 { NULL, (ALCenum)0 }
694 #undef DECL
696 static const ALCchar alcNoError[] = "No Error";
697 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
698 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
699 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
700 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
701 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
704 /************************************************
705 * Global variables
706 ************************************************/
708 /* Enumerated device names */
709 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
711 static al_string alcAllDevicesList;
712 static al_string alcCaptureDeviceList;
714 /* Default is always the first in the list */
715 static ALCchar *alcDefaultAllDevicesSpecifier;
716 static ALCchar *alcCaptureDefaultDeviceSpecifier;
718 /* Default context extensions */
719 static const ALchar alExtList[] =
720 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
721 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
722 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
723 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
724 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
725 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
726 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
728 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
730 /* Thread-local current context */
731 static altss_t LocalContext;
732 /* Process-wide current context */
733 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
735 /* Mixing thread piority level */
736 ALint RTPrioLevel;
738 FILE *LogFile;
739 #ifdef _DEBUG
740 enum LogLevel LogLevel = LogWarning;
741 #else
742 enum LogLevel LogLevel = LogError;
743 #endif
745 /* Flag to trap ALC device errors */
746 static ALCboolean TrapALCError = ALC_FALSE;
748 /* One-time configuration init control */
749 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
751 /* Default effect that applies to sources that don't have an effect on send 0 */
752 static ALeffect DefaultEffect;
754 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
755 * updates.
757 static ALCboolean SuspendDefers = ALC_TRUE;
760 /************************************************
761 * ALC information
762 ************************************************/
763 static const ALCchar alcNoDeviceExtList[] =
764 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
765 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
766 static const ALCchar alcExtensionList[] =
767 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
768 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
769 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
770 "ALC_SOFT_loopback ALC_SOFT_pause_device";
771 static const ALCint alcMajorVersion = 1;
772 static const ALCint alcMinorVersion = 1;
774 static const ALCint alcEFXMajorVersion = 1;
775 static const ALCint alcEFXMinorVersion = 0;
778 /************************************************
779 * Device lists
780 ************************************************/
781 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
783 static almtx_t ListLock;
784 static inline void LockLists(void)
786 int ret = almtx_lock(&ListLock);
787 assert(ret == althrd_success);
789 static inline void UnlockLists(void)
791 int ret = almtx_unlock(&ListLock);
792 assert(ret == althrd_success);
795 /************************************************
796 * Library initialization
797 ************************************************/
798 #if defined(_WIN32)
799 static void alc_init(void);
800 static void alc_deinit(void);
801 static void alc_deinit_safe(void);
803 #ifndef AL_LIBTYPE_STATIC
804 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
806 switch(reason)
808 case DLL_PROCESS_ATTACH:
809 /* Pin the DLL so we won't get unloaded until the process terminates */
810 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
811 (WCHAR*)hModule, &hModule);
812 alc_init();
813 break;
815 case DLL_THREAD_DETACH:
816 break;
818 case DLL_PROCESS_DETACH:
819 if(!lpReserved)
820 alc_deinit();
821 else
822 alc_deinit_safe();
823 break;
825 return TRUE;
827 #elif defined(_MSC_VER)
828 #pragma section(".CRT$XCU",read)
829 static void alc_constructor(void);
830 static void alc_destructor(void);
831 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
833 static void alc_constructor(void)
835 atexit(alc_destructor);
836 alc_init();
839 static void alc_destructor(void)
841 alc_deinit();
843 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
846 #else
847 #error "No static initialization available on this platform!"
848 #endif
850 #elif defined(HAVE_GCC_DESTRUCTOR)
852 static void alc_init(void) __attribute__((constructor));
853 static void alc_deinit(void) __attribute__((destructor));
855 #else
856 #error "No global initialization available on this platform!"
857 #endif
859 static void ReleaseThreadCtx(void *ptr);
860 static void alc_init(void)
862 const char *str;
863 int ret;
865 LogFile = stderr;
867 AL_STRING_INIT(alcAllDevicesList);
868 AL_STRING_INIT(alcCaptureDeviceList);
870 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
871 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
872 ConeScale *= 0.5f;
874 str = getenv("__ALSOFT_REVERSE_Z");
875 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
876 ZScale *= -1.0f;
878 ret = altss_create(&LocalContext, ReleaseThreadCtx);
879 assert(ret == althrd_success);
881 ret = almtx_init(&ListLock, almtx_recursive);
882 assert(ret == althrd_success);
884 ThunkInit();
887 static void alc_initconfig(void)
889 const char *devs, *str;
890 ALuint capfilter;
891 float valf;
892 int i, n;
894 str = getenv("ALSOFT_LOGLEVEL");
895 if(str)
897 long lvl = strtol(str, NULL, 0);
898 if(lvl >= NoLog && lvl <= LogRef)
899 LogLevel = lvl;
902 str = getenv("ALSOFT_LOGFILE");
903 if(str && str[0])
905 FILE *logfile = al_fopen(str, "wt");
906 if(logfile) LogFile = logfile;
907 else ERR("Failed to open log file '%s'\n", str);
910 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION,
911 ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
913 char buf[1024] = "";
914 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
915 for(i = 1;BackendList[i].name;i++)
916 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
917 TRACE("Supported backends: %s\n", buf);
919 ReadALConfig();
921 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
922 if(str && *str)
924 if(strcasecmp(str, "ignore") == 0)
926 SuspendDefers = ALC_FALSE;
927 TRACE("Selected context suspend behavior, \"ignore\"\n");
929 else
930 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
933 capfilter = 0;
934 #if defined(HAVE_SSE4_1)
935 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
936 #elif defined(HAVE_SSE3)
937 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
938 #elif defined(HAVE_SSE2)
939 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
940 #elif defined(HAVE_SSE)
941 capfilter |= CPU_CAP_SSE;
942 #endif
943 #ifdef HAVE_NEON
944 capfilter |= CPU_CAP_NEON;
945 #endif
946 if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str))
948 if(strcasecmp(str, "all") == 0)
949 capfilter = 0;
950 else
952 size_t len;
953 const char *next = str;
955 do {
956 str = next;
957 while(isspace(str[0]))
958 str++;
959 next = strchr(str, ',');
961 if(!str[0] || str[0] == ',')
962 continue;
964 len = (next ? ((size_t)(next-str)) : strlen(str));
965 while(len > 0 && isspace(str[len-1]))
966 len--;
967 if(len == 3 && strncasecmp(str, "sse", len) == 0)
968 capfilter &= ~CPU_CAP_SSE;
969 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
970 capfilter &= ~CPU_CAP_SSE2;
971 else if(len == 4 && strncasecmp(str, "sse3", len) == 0)
972 capfilter &= ~CPU_CAP_SSE3;
973 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
974 capfilter &= ~CPU_CAP_SSE4_1;
975 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
976 capfilter &= ~CPU_CAP_NEON;
977 else
978 WARN("Invalid CPU extension \"%s\"\n", str);
979 } while(next++);
982 FillCPUCaps(capfilter);
984 #ifdef _WIN32
985 RTPrioLevel = 1;
986 #else
987 RTPrioLevel = 0;
988 #endif
989 ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel);
991 aluInitMixer();
993 str = getenv("ALSOFT_TRAP_ERROR");
994 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
996 TrapALError = AL_TRUE;
997 TrapALCError = AL_TRUE;
999 else
1001 str = getenv("ALSOFT_TRAP_AL_ERROR");
1002 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1003 TrapALError = AL_TRUE;
1004 TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError);
1006 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1007 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1008 TrapALCError = ALC_TRUE;
1009 TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError);
1012 if(ConfigValueFloat(NULL, "reverb", "boost", &valf))
1013 ReverbBoost *= powf(10.0f, valf / 20.0f);
1015 EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE);
1017 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1018 ConfigValueStr(NULL, NULL, "drivers", &devs))
1020 int n;
1021 size_t len;
1022 const char *next = devs;
1023 int endlist, delitem;
1025 i = 0;
1026 do {
1027 devs = next;
1028 while(isspace(devs[0]))
1029 devs++;
1030 next = strchr(devs, ',');
1032 delitem = (devs[0] == '-');
1033 if(devs[0] == '-') devs++;
1035 if(!devs[0] || devs[0] == ',')
1037 endlist = 0;
1038 continue;
1040 endlist = 1;
1042 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1043 while(len > 0 && isspace(devs[len-1]))
1044 len--;
1045 for(n = i;BackendList[n].name;n++)
1047 if(len == strlen(BackendList[n].name) &&
1048 strncmp(BackendList[n].name, devs, len) == 0)
1050 if(delitem)
1052 do {
1053 BackendList[n] = BackendList[n+1];
1054 ++n;
1055 } while(BackendList[n].name);
1057 else
1059 struct BackendInfo Bkp = BackendList[n];
1060 while(n > i)
1062 BackendList[n] = BackendList[n-1];
1063 --n;
1065 BackendList[n] = Bkp;
1067 i++;
1069 break;
1072 } while(next++);
1074 if(endlist)
1076 BackendList[i].name = NULL;
1077 BackendList[i].getFactory = NULL;
1078 BackendList[i].Init = NULL;
1079 BackendList[i].Deinit = NULL;
1080 BackendList[i].Probe = NULL;
1084 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1086 if(BackendList[i].getFactory)
1088 ALCbackendFactory *factory = BackendList[i].getFactory();
1089 if(!V0(factory,init)())
1091 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1092 continue;
1095 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1096 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1098 PlaybackBackend = BackendList[i];
1099 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1101 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1103 CaptureBackend = BackendList[i];
1104 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1107 continue;
1110 if(!BackendList[i].Init(&BackendList[i].Funcs))
1112 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1113 continue;
1116 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1117 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1119 PlaybackBackend = BackendList[i];
1120 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1122 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1124 CaptureBackend = BackendList[i];
1125 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1129 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1130 V0(factory,init)();
1133 if(!PlaybackBackend.name)
1134 WARN("No playback backend available!\n");
1135 if(!CaptureBackend.name)
1136 WARN("No capture backend available!\n");
1138 if(ConfigValueStr(NULL, NULL, "excludefx", &str))
1140 size_t len;
1141 const char *next = str;
1143 do {
1144 str = next;
1145 next = strchr(str, ',');
1147 if(!str[0] || next == str)
1148 continue;
1150 len = (next ? ((size_t)(next-str)) : strlen(str));
1151 for(n = 0;EffectList[n].name;n++)
1153 if(len == strlen(EffectList[n].name) &&
1154 strncmp(EffectList[n].name, str, len) == 0)
1155 DisabledEffects[EffectList[n].type] = AL_TRUE;
1157 } while(next++);
1160 InitEffectFactoryMap();
1162 InitEffect(&DefaultEffect);
1163 str = getenv("ALSOFT_DEFAULT_REVERB");
1164 if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str))
1165 LoadReverbPreset(str, &DefaultEffect);
1167 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1169 #ifdef __ANDROID__
1170 #include <jni.h>
1172 static JavaVM *gJavaVM;
1173 static pthread_key_t gJVMThreadKey;
1175 static void CleanupJNIEnv(void* UNUSED(ptr))
1177 JCALL0(gJavaVM,DetachCurrentThread)();
1180 void *Android_GetJNIEnv(void)
1182 if(!gJavaVM)
1184 WARN("gJavaVM is NULL!\n");
1185 return NULL;
1188 /* http://developer.android.com/guide/practices/jni.html
1190 * All threads are Linux threads, scheduled by the kernel. They're usually
1191 * started from managed code (using Thread.start), but they can also be
1192 * created elsewhere and then attached to the JavaVM. For example, a thread
1193 * started with pthread_create can be attached with the JNI
1194 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1195 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1196 * Attaching a natively-created thread causes a java.lang.Thread object to
1197 * be constructed and added to the "main" ThreadGroup, making it visible to
1198 * the debugger. Calling AttachCurrentThread on an already-attached thread
1199 * is a no-op.
1201 JNIEnv *env = pthread_getspecific(gJVMThreadKey);
1202 if(!env)
1204 int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
1205 if(status < 0)
1207 ERR("Failed to attach current thread\n");
1208 return NULL;
1210 pthread_setspecific(gJVMThreadKey, env);
1212 return env;
1215 /* Automatically called by JNI. */
1216 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
1218 void *env;
1219 int err;
1221 gJavaVM = jvm;
1222 if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
1224 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1225 return JNI_ERR;
1228 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1229 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1231 if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
1232 ERR("pthread_key_create failed: %d\n", err);
1233 pthread_setspecific(gJVMThreadKey, env);
1234 return JNI_VERSION_1_4;
1237 #endif
1240 /************************************************
1241 * Library deinitialization
1242 ************************************************/
1243 static void alc_cleanup(void)
1245 ALCdevice *dev;
1247 AL_STRING_DEINIT(alcAllDevicesList);
1248 AL_STRING_DEINIT(alcCaptureDeviceList);
1250 free(alcDefaultAllDevicesSpecifier);
1251 alcDefaultAllDevicesSpecifier = NULL;
1252 free(alcCaptureDefaultDeviceSpecifier);
1253 alcCaptureDefaultDeviceSpecifier = NULL;
1255 if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL)
1257 ALCuint num = 0;
1258 do {
1259 num++;
1260 } while((dev=dev->next) != NULL);
1261 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1264 DeinitEffectFactoryMap();
1267 static void alc_deinit_safe(void)
1269 alc_cleanup();
1271 FreeHrtfs();
1272 FreeALConfig();
1274 ThunkExit();
1275 almtx_destroy(&ListLock);
1276 altss_delete(LocalContext);
1278 if(LogFile != stderr)
1279 fclose(LogFile);
1280 LogFile = NULL;
1283 static void alc_deinit(void)
1285 int i;
1287 alc_cleanup();
1289 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1290 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1292 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1294 if(!BackendList[i].getFactory)
1295 BackendList[i].Deinit();
1296 else
1298 ALCbackendFactory *factory = BackendList[i].getFactory();
1299 V0(factory,deinit)();
1303 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1304 V0(factory,deinit)();
1307 alc_deinit_safe();
1311 /************************************************
1312 * Device enumeration
1313 ************************************************/
1314 static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type)
1316 DO_INITCONFIG();
1318 LockLists();
1319 al_string_clear(list);
1321 if(backendinfo->Probe)
1322 backendinfo->Probe(type);
1323 else if(backendinfo->getFactory)
1325 ALCbackendFactory *factory = backendinfo->getFactory();
1326 V(factory,probe)(type);
1329 UnlockLists();
1331 static void ProbeAllDevicesList(void)
1332 { ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); }
1333 static void ProbeCaptureDeviceList(void)
1334 { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); }
1336 static void AppendDevice(const ALCchar *name, al_string *devnames)
1338 size_t len = strlen(name);
1339 if(len > 0)
1340 al_string_append_range(devnames, name, name+len+1);
1342 void AppendAllDevicesList(const ALCchar *name)
1343 { AppendDevice(name, &alcAllDevicesList); }
1344 void AppendCaptureDeviceList(const ALCchar *name)
1345 { AppendDevice(name, &alcCaptureDeviceList); }
1348 /************************************************
1349 * Device format information
1350 ************************************************/
1351 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1353 switch(type)
1355 case DevFmtByte: return "Signed Byte";
1356 case DevFmtUByte: return "Unsigned Byte";
1357 case DevFmtShort: return "Signed Short";
1358 case DevFmtUShort: return "Unsigned Short";
1359 case DevFmtInt: return "Signed Int";
1360 case DevFmtUInt: return "Unsigned Int";
1361 case DevFmtFloat: return "Float";
1363 return "(unknown type)";
1365 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1367 switch(chans)
1369 case DevFmtMono: return "Mono";
1370 case DevFmtStereo: return "Stereo";
1371 case DevFmtQuad: return "Quadraphonic";
1372 case DevFmtX51: return "5.1 Surround";
1373 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1374 case DevFmtX61: return "6.1 Surround";
1375 case DevFmtX71: return "7.1 Surround";
1376 case DevFmtAmbi1: return "Ambisonic (1st Order)";
1377 case DevFmtAmbi2: return "Ambisonic (2nd Order)";
1378 case DevFmtAmbi3: return "Ambisonic (3rd Order)";
1380 return "(unknown channels)";
1383 extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1384 ALsizei BytesFromDevFmt(enum DevFmtType type)
1386 switch(type)
1388 case DevFmtByte: return sizeof(ALbyte);
1389 case DevFmtUByte: return sizeof(ALubyte);
1390 case DevFmtShort: return sizeof(ALshort);
1391 case DevFmtUShort: return sizeof(ALushort);
1392 case DevFmtInt: return sizeof(ALint);
1393 case DevFmtUInt: return sizeof(ALuint);
1394 case DevFmtFloat: return sizeof(ALfloat);
1396 return 0;
1398 ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans)
1400 switch(chans)
1402 case DevFmtMono: return 1;
1403 case DevFmtStereo: return 2;
1404 case DevFmtQuad: return 4;
1405 case DevFmtX51: return 6;
1406 case DevFmtX51Rear: return 6;
1407 case DevFmtX61: return 7;
1408 case DevFmtX71: return 8;
1409 case DevFmtAmbi1: return 4;
1410 case DevFmtAmbi2: return 9;
1411 case DevFmtAmbi3: return 16;
1413 return 0;
1416 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1417 enum DevFmtType *type)
1419 static const struct {
1420 ALenum format;
1421 enum DevFmtChannels channels;
1422 enum DevFmtType type;
1423 } list[] = {
1424 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1425 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1426 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1428 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1429 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1430 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1432 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1433 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1434 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1436 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1437 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1438 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1440 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1441 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1442 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1444 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1445 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1446 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1448 ALuint i;
1450 for(i = 0;i < COUNTOF(list);i++)
1452 if(list[i].format == format)
1454 *chans = list[i].channels;
1455 *type = list[i].type;
1456 return AL_TRUE;
1460 return AL_FALSE;
1463 static ALCboolean IsValidALCType(ALCenum type)
1465 switch(type)
1467 case ALC_BYTE_SOFT:
1468 case ALC_UNSIGNED_BYTE_SOFT:
1469 case ALC_SHORT_SOFT:
1470 case ALC_UNSIGNED_SHORT_SOFT:
1471 case ALC_INT_SOFT:
1472 case ALC_UNSIGNED_INT_SOFT:
1473 case ALC_FLOAT_SOFT:
1474 return ALC_TRUE;
1476 return ALC_FALSE;
1479 static ALCboolean IsValidALCChannels(ALCenum channels)
1481 switch(channels)
1483 case ALC_MONO_SOFT:
1484 case ALC_STEREO_SOFT:
1485 case ALC_QUAD_SOFT:
1486 case ALC_5POINT1_SOFT:
1487 case ALC_6POINT1_SOFT:
1488 case ALC_7POINT1_SOFT:
1489 return ALC_TRUE;
1491 return ALC_FALSE;
1495 /************************************************
1496 * Miscellaneous ALC helpers
1497 ************************************************/
1499 void ALCdevice_Lock(ALCdevice *device)
1501 V0(device->Backend,lock)();
1504 void ALCdevice_Unlock(ALCdevice *device)
1506 V0(device->Backend,unlock)();
1510 /* SetDefaultWFXChannelOrder
1512 * Sets the default channel order used by WaveFormatEx.
1514 void SetDefaultWFXChannelOrder(ALCdevice *device)
1516 ALuint i;
1518 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1519 device->RealOut.ChannelName[i] = InvalidChannel;
1521 switch(device->FmtChans)
1523 case DevFmtMono:
1524 device->RealOut.ChannelName[0] = FrontCenter;
1525 break;
1526 case DevFmtStereo:
1527 device->RealOut.ChannelName[0] = FrontLeft;
1528 device->RealOut.ChannelName[1] = FrontRight;
1529 break;
1530 case DevFmtQuad:
1531 device->RealOut.ChannelName[0] = FrontLeft;
1532 device->RealOut.ChannelName[1] = FrontRight;
1533 device->RealOut.ChannelName[2] = BackLeft;
1534 device->RealOut.ChannelName[3] = BackRight;
1535 break;
1536 case DevFmtX51:
1537 device->RealOut.ChannelName[0] = FrontLeft;
1538 device->RealOut.ChannelName[1] = FrontRight;
1539 device->RealOut.ChannelName[2] = FrontCenter;
1540 device->RealOut.ChannelName[3] = LFE;
1541 device->RealOut.ChannelName[4] = SideLeft;
1542 device->RealOut.ChannelName[5] = SideRight;
1543 break;
1544 case DevFmtX51Rear:
1545 device->RealOut.ChannelName[0] = FrontLeft;
1546 device->RealOut.ChannelName[1] = FrontRight;
1547 device->RealOut.ChannelName[2] = FrontCenter;
1548 device->RealOut.ChannelName[3] = LFE;
1549 device->RealOut.ChannelName[4] = BackLeft;
1550 device->RealOut.ChannelName[5] = BackRight;
1551 break;
1552 case DevFmtX61:
1553 device->RealOut.ChannelName[0] = FrontLeft;
1554 device->RealOut.ChannelName[1] = FrontRight;
1555 device->RealOut.ChannelName[2] = FrontCenter;
1556 device->RealOut.ChannelName[3] = LFE;
1557 device->RealOut.ChannelName[4] = BackCenter;
1558 device->RealOut.ChannelName[5] = SideLeft;
1559 device->RealOut.ChannelName[6] = SideRight;
1560 break;
1561 case DevFmtX71:
1562 device->RealOut.ChannelName[0] = FrontLeft;
1563 device->RealOut.ChannelName[1] = FrontRight;
1564 device->RealOut.ChannelName[2] = FrontCenter;
1565 device->RealOut.ChannelName[3] = LFE;
1566 device->RealOut.ChannelName[4] = BackLeft;
1567 device->RealOut.ChannelName[5] = BackRight;
1568 device->RealOut.ChannelName[6] = SideLeft;
1569 device->RealOut.ChannelName[7] = SideRight;
1570 break;
1571 case DevFmtAmbi1:
1572 device->RealOut.ChannelName[0] = Aux0;
1573 device->RealOut.ChannelName[1] = Aux1;
1574 device->RealOut.ChannelName[2] = Aux2;
1575 device->RealOut.ChannelName[3] = Aux3;
1576 break;
1577 case DevFmtAmbi2:
1578 device->RealOut.ChannelName[0] = Aux0;
1579 device->RealOut.ChannelName[1] = Aux1;
1580 device->RealOut.ChannelName[2] = Aux2;
1581 device->RealOut.ChannelName[3] = Aux3;
1582 device->RealOut.ChannelName[4] = Aux4;
1583 device->RealOut.ChannelName[5] = Aux5;
1584 device->RealOut.ChannelName[6] = Aux6;
1585 device->RealOut.ChannelName[7] = Aux7;
1586 device->RealOut.ChannelName[8] = Aux8;
1587 break;
1588 case DevFmtAmbi3:
1589 device->RealOut.ChannelName[0] = Aux0;
1590 device->RealOut.ChannelName[1] = Aux1;
1591 device->RealOut.ChannelName[2] = Aux2;
1592 device->RealOut.ChannelName[3] = Aux3;
1593 device->RealOut.ChannelName[4] = Aux4;
1594 device->RealOut.ChannelName[5] = Aux5;
1595 device->RealOut.ChannelName[6] = Aux6;
1596 device->RealOut.ChannelName[7] = Aux7;
1597 device->RealOut.ChannelName[8] = Aux8;
1598 device->RealOut.ChannelName[9] = Aux9;
1599 device->RealOut.ChannelName[10] = Aux10;
1600 device->RealOut.ChannelName[11] = Aux11;
1601 device->RealOut.ChannelName[12] = Aux12;
1602 device->RealOut.ChannelName[13] = Aux13;
1603 device->RealOut.ChannelName[14] = Aux14;
1604 device->RealOut.ChannelName[15] = Aux15;
1605 break;
1609 /* SetDefaultChannelOrder
1611 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1613 void SetDefaultChannelOrder(ALCdevice *device)
1615 ALuint i;
1617 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1618 device->RealOut.ChannelName[i] = InvalidChannel;
1620 switch(device->FmtChans)
1622 case DevFmtX51Rear:
1623 device->RealOut.ChannelName[0] = FrontLeft;
1624 device->RealOut.ChannelName[1] = FrontRight;
1625 device->RealOut.ChannelName[2] = BackLeft;
1626 device->RealOut.ChannelName[3] = BackRight;
1627 device->RealOut.ChannelName[4] = FrontCenter;
1628 device->RealOut.ChannelName[5] = LFE;
1629 return;
1630 case DevFmtX71:
1631 device->RealOut.ChannelName[0] = FrontLeft;
1632 device->RealOut.ChannelName[1] = FrontRight;
1633 device->RealOut.ChannelName[2] = BackLeft;
1634 device->RealOut.ChannelName[3] = BackRight;
1635 device->RealOut.ChannelName[4] = FrontCenter;
1636 device->RealOut.ChannelName[5] = LFE;
1637 device->RealOut.ChannelName[6] = SideLeft;
1638 device->RealOut.ChannelName[7] = SideRight;
1639 return;
1641 /* Same as WFX order */
1642 case DevFmtMono:
1643 case DevFmtStereo:
1644 case DevFmtQuad:
1645 case DevFmtX51:
1646 case DevFmtX61:
1647 case DevFmtAmbi1:
1648 case DevFmtAmbi2:
1649 case DevFmtAmbi3:
1650 SetDefaultWFXChannelOrder(device);
1651 break;
1655 extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
1658 /* ALCcontext_DeferUpdates
1660 * Defers/suspends updates for the given context's listener and sources. This
1661 * does *NOT* stop mixing, but rather prevents certain property changes from
1662 * taking effect.
1664 void ALCcontext_DeferUpdates(ALCcontext *context, ALenum type)
1666 ATOMIC_STORE_SEQ(&context->DeferUpdates, type);
1669 /* ALCcontext_ProcessUpdates
1671 * Resumes update processing after being deferred.
1673 void ALCcontext_ProcessUpdates(ALCcontext *context)
1675 ALCdevice *device = context->Device;
1677 ReadLock(&context->PropLock);
1678 if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE))
1680 ALsizei pos;
1681 uint updates;
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(((updates=ReadRef(&context->UpdateCount))&1) != 0)
1688 althrd_yield();
1690 UpdateListenerProps(context);
1691 UpdateAllEffectSlotProps(context);
1693 LockUIntMapRead(&context->SourceMap);
1694 V0(device->Backend,lock)();
1695 for(pos = 0;pos < context->SourceMap.size;pos++)
1697 ALsource *Source = context->SourceMap.values[pos];
1698 ALenum new_state;
1700 if(Source->OffsetType != AL_NONE && IsPlayingOrPaused(Source))
1702 WriteLock(&Source->queue_lock);
1703 ApplyOffset(Source);
1704 WriteUnlock(&Source->queue_lock);
1707 new_state = Source->new_state;
1708 Source->new_state = AL_NONE;
1709 if(new_state)
1710 SetSourceState(Source, context, new_state);
1712 V0(device->Backend,unlock)();
1713 UnlockUIntMapRead(&context->SourceMap);
1715 UpdateAllSourceProps(context);
1717 /* Now with all updates declared, let the mixer continue applying them
1718 * so they all happen at once.
1720 ATOMIC_STORE_SEQ(&context->HoldUpdates, AL_FALSE);
1722 ReadUnlock(&context->PropLock);
1726 /* alcSetError
1728 * Stores the latest ALC device error
1730 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1732 if(TrapALCError)
1734 #ifdef _WIN32
1735 /* DebugBreak() will cause an exception if there is no debugger */
1736 if(IsDebuggerPresent())
1737 DebugBreak();
1738 #elif defined(SIGTRAP)
1739 raise(SIGTRAP);
1740 #endif
1743 if(device)
1744 ATOMIC_STORE_SEQ(&device->LastError, errorCode);
1745 else
1746 ATOMIC_STORE_SEQ(&LastNullDeviceError, errorCode);
1750 /* UpdateClockBase
1752 * Updates the device's base clock time with however many samples have been
1753 * done. This is used so frequency changes on the device don't cause the time
1754 * to jump forward or back.
1756 static inline void UpdateClockBase(ALCdevice *device)
1758 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1759 device->SamplesDone = 0;
1762 /* UpdateDeviceParams
1764 * Updates device parameters according to the attribute list (caller is
1765 * responsible for holding the list lock).
1767 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1769 ALCcontext *context;
1770 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1771 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1772 ALsizei old_sends = device->NumAuxSends;
1773 enum DevFmtChannels oldChans;
1774 enum DevFmtType oldType;
1775 ALCuint oldFreq;
1776 FPUCtl oldMode;
1777 ALCsizei hrtf_id = -1;
1778 size_t size;
1780 // Check for attributes
1781 if(device->Type == Loopback)
1783 enum {
1784 GotFreq = 1<<0,
1785 GotChans = 1<<1,
1786 GotType = 1<<2,
1787 GotAll = GotFreq|GotChans|GotType
1789 ALCuint freq, numMono, numStereo, numSends;
1790 enum DevFmtChannels schans;
1791 enum DevFmtType stype;
1792 ALCuint attrIdx = 0;
1793 ALCint gotFmt = 0;
1795 if(!attrList)
1797 WARN("Missing attributes for loopback device\n");
1798 return ALC_INVALID_VALUE;
1801 numMono = device->NumMonoSources;
1802 numStereo = device->NumStereoSources;
1803 numSends = device->NumAuxSends;
1804 schans = device->FmtChans;
1805 stype = device->FmtType;
1806 freq = device->Frequency;
1808 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1809 while(attrList[attrIdx])
1811 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1813 ALCint val = attrList[attrIdx + 1];
1814 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val);
1815 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1816 return ALC_INVALID_VALUE;
1817 schans = val;
1818 gotFmt |= GotChans;
1821 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1823 ALCint val = attrList[attrIdx + 1];
1824 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val);
1825 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1826 return ALC_INVALID_VALUE;
1827 stype = val;
1828 gotFmt |= GotType;
1831 if(attrList[attrIdx] == ALC_FREQUENCY)
1833 freq = attrList[attrIdx + 1];
1834 TRACE_ATTR(ALC_FREQUENCY, freq);
1835 if(freq < MIN_OUTPUT_RATE)
1836 return ALC_INVALID_VALUE;
1837 gotFmt |= GotFreq;
1840 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1842 numStereo = attrList[attrIdx + 1];
1843 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1844 if(numStereo > device->SourcesMax)
1845 numStereo = device->SourcesMax;
1847 numMono = device->SourcesMax - numStereo;
1850 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1852 numSends = attrList[attrIdx + 1];
1853 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1856 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1858 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1859 if(attrList[attrIdx + 1] == ALC_FALSE)
1860 hrtf_appreq = Hrtf_Disable;
1861 else if(attrList[attrIdx + 1] == ALC_TRUE)
1862 hrtf_appreq = Hrtf_Enable;
1863 else
1864 hrtf_appreq = Hrtf_Default;
1867 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1869 hrtf_id = attrList[attrIdx + 1];
1870 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1873 attrIdx += 2;
1875 #undef TRACE_ATTR
1877 if(gotFmt != GotAll)
1879 WARN("Missing format for loopback device\n");
1880 return ALC_INVALID_VALUE;
1883 ConfigValueUInt(NULL, NULL, "sends", &numSends);
1884 numSends = minu(MAX_SENDS, numSends);
1886 if((device->Flags&DEVICE_RUNNING))
1887 V0(device->Backend,stop)();
1888 device->Flags &= ~DEVICE_RUNNING;
1890 UpdateClockBase(device);
1892 device->Frequency = freq;
1893 device->FmtChans = schans;
1894 device->FmtType = stype;
1895 device->NumMonoSources = numMono;
1896 device->NumStereoSources = numStereo;
1897 device->NumAuxSends = numSends;
1899 else if(attrList && attrList[0])
1901 ALCuint freq, numMono, numStereo, numSends;
1902 ALCuint attrIdx = 0;
1904 /* If a context is already running on the device, stop playback so the
1905 * device attributes can be updated. */
1906 if((device->Flags&DEVICE_RUNNING))
1907 V0(device->Backend,stop)();
1908 device->Flags &= ~DEVICE_RUNNING;
1910 freq = device->Frequency;
1911 numMono = device->NumMonoSources;
1912 numStereo = device->NumStereoSources;
1913 numSends = device->NumAuxSends;
1915 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1916 while(attrList[attrIdx])
1918 if(attrList[attrIdx] == ALC_FREQUENCY)
1920 freq = attrList[attrIdx + 1];
1921 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1922 TRACE_ATTR(ALC_FREQUENCY, freq);
1925 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1927 numStereo = attrList[attrIdx + 1];
1928 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1929 if(numStereo > device->SourcesMax)
1930 numStereo = device->SourcesMax;
1932 numMono = device->SourcesMax - numStereo;
1935 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1937 numSends = attrList[attrIdx + 1];
1938 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1941 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1943 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1944 if(attrList[attrIdx + 1] == ALC_FALSE)
1945 hrtf_appreq = Hrtf_Disable;
1946 else if(attrList[attrIdx + 1] == ALC_TRUE)
1947 hrtf_appreq = Hrtf_Enable;
1948 else
1949 hrtf_appreq = Hrtf_Default;
1952 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1954 hrtf_id = attrList[attrIdx + 1];
1955 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1958 attrIdx += 2;
1960 #undef TRACE_ATTR
1962 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1963 freq = maxu(freq, MIN_OUTPUT_RATE);
1965 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
1966 numSends = minu(MAX_SENDS, numSends);
1968 UpdateClockBase(device);
1970 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1971 device->Frequency;
1972 /* SSE and Neon do best with the update size being a multiple of 4 */
1973 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1974 device->UpdateSize = (device->UpdateSize+3)&~3;
1976 device->Frequency = freq;
1977 device->NumMonoSources = numMono;
1978 device->NumStereoSources = numStereo;
1979 device->NumAuxSends = numSends;
1982 if((device->Flags&DEVICE_RUNNING))
1983 return ALC_NO_ERROR;
1985 al_free(device->Uhj_Encoder);
1986 device->Uhj_Encoder = NULL;
1988 al_free(device->Bs2b);
1989 device->Bs2b = NULL;
1991 al_free(device->Dry.Buffer);
1992 device->Dry.Buffer = NULL;
1993 device->Dry.NumChannels = 0;
1994 device->FOAOut.Buffer = NULL;
1995 device->FOAOut.NumChannels = 0;
1996 device->RealOut.Buffer = NULL;
1997 device->RealOut.NumChannels = 0;
1999 UpdateClockBase(device);
2001 /*************************************************************************
2002 * Update device format request if HRTF is requested
2004 device->Hrtf.Status = ALC_HRTF_DISABLED_SOFT;
2005 if(device->Type != Loopback)
2007 const char *hrtf;
2008 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2010 if(strcasecmp(hrtf, "true") == 0)
2011 hrtf_userreq = Hrtf_Enable;
2012 else if(strcasecmp(hrtf, "false") == 0)
2013 hrtf_userreq = Hrtf_Disable;
2014 else if(strcasecmp(hrtf, "auto") != 0)
2015 ERR("Unexpected hrtf value: %s\n", hrtf);
2018 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2020 if(VECTOR_SIZE(device->Hrtf.List) == 0)
2022 VECTOR_DEINIT(device->Hrtf.List);
2023 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
2025 if(VECTOR_SIZE(device->Hrtf.List) > 0)
2027 device->FmtChans = DevFmtStereo;
2028 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf.List))
2029 device->Frequency = VECTOR_ELEM(device->Hrtf.List, hrtf_id).hrtf->sampleRate;
2030 else
2031 device->Frequency = VECTOR_ELEM(device->Hrtf.List, 0).hrtf->sampleRate;
2032 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2034 else
2036 hrtf_userreq = Hrtf_Default;
2037 hrtf_appreq = Hrtf_Disable;
2038 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2042 else if(hrtf_appreq == Hrtf_Enable)
2044 size_t i = VECTOR_SIZE(device->Hrtf.List);
2045 /* Loopback device. We don't need to match to a specific HRTF entry
2046 * here. If the requested ID matches, we'll pick that later, if not,
2047 * we'll try to auto-select one anyway. Just make sure one exists
2048 * that'll work.
2050 if(device->FmtChans == DevFmtStereo)
2052 if(VECTOR_SIZE(device->Hrtf.List) == 0)
2054 VECTOR_DEINIT(device->Hrtf.List);
2055 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
2057 for(i = 0;i < VECTOR_SIZE(device->Hrtf.List);i++)
2059 const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf.List, i).hrtf;
2060 if(hrtf->sampleRate == device->Frequency)
2061 break;
2064 if(i == VECTOR_SIZE(device->Hrtf.List))
2066 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2067 DevFmtChannelsString(device->FmtChans), device->Frequency);
2068 hrtf_appreq = Hrtf_Disable;
2069 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2073 oldFreq = device->Frequency;
2074 oldChans = device->FmtChans;
2075 oldType = device->FmtType;
2077 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2078 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2079 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2080 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2081 device->UpdateSize, device->NumUpdates
2084 if(V0(device->Backend,reset)() == ALC_FALSE)
2085 return ALC_INVALID_DEVICE;
2087 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2089 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2090 DevFmtChannelsString(device->FmtChans));
2091 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2093 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2095 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2096 DevFmtTypeString(device->FmtType));
2097 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2099 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2101 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2102 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2105 if((device->UpdateSize&3) != 0)
2107 if((CPUCapFlags&CPU_CAP_SSE))
2108 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2109 if((CPUCapFlags&CPU_CAP_NEON))
2110 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2113 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2114 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2115 device->Frequency, device->UpdateSize, device->NumUpdates
2118 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2119 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2120 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2122 /* Allocate extra channels for any post-filter output. */
2123 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2124 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2126 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2127 device->Dry.Buffer = al_calloc(16, size);
2128 if(!device->Dry.Buffer)
2130 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2131 return ALC_INVALID_DEVICE;
2134 if(device->RealOut.NumChannels != 0)
2135 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2136 device->FOAOut.NumChannels;
2137 else
2139 device->RealOut.Buffer = device->Dry.Buffer;
2140 device->RealOut.NumChannels = device->Dry.NumChannels;
2143 if(device->FOAOut.NumChannels != 0)
2144 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2145 else
2147 device->FOAOut.Buffer = device->Dry.Buffer;
2148 device->FOAOut.NumChannels = device->Dry.NumChannels;
2151 SetMixerFPUMode(&oldMode);
2152 if(device->DefaultSlot)
2154 ALeffectslot *slot = device->DefaultSlot;
2155 ALeffectState *state = slot->Effect.State;
2157 state->OutBuffer = device->Dry.Buffer;
2158 state->OutChannels = device->Dry.NumChannels;
2159 if(V(state,deviceUpdate)(device) == AL_FALSE)
2161 RestoreFPUMode(&oldMode);
2162 return ALC_INVALID_DEVICE;
2164 UpdateEffectSlotProps(slot);
2167 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2168 while(context)
2170 ALsizei pos;
2172 WriteLock(&context->PropLock);
2173 LockUIntMapRead(&context->EffectSlotMap);
2174 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2176 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2177 ALeffectState *state = slot->Effect.State;
2179 state->OutBuffer = device->Dry.Buffer;
2180 state->OutChannels = device->Dry.NumChannels;
2181 if(V(state,deviceUpdate)(device) == AL_FALSE)
2183 UnlockUIntMapRead(&context->EffectSlotMap);
2184 ReadUnlock(&context->PropLock);
2185 RestoreFPUMode(&oldMode);
2186 return ALC_INVALID_DEVICE;
2189 UpdateEffectSlotProps(slot);
2191 UnlockUIntMapRead(&context->EffectSlotMap);
2193 LockUIntMapRead(&context->SourceMap);
2194 for(pos = 0;pos < context->SourceMap.size;pos++)
2196 ALsource *source = context->SourceMap.values[pos];
2197 struct ALsourceProps *props;
2198 ALsizei s;
2200 for(s = device->NumAuxSends;s < MAX_SENDS;s++)
2202 if(source->Send[s].Slot)
2203 DecrementRef(&source->Send[s].Slot->ref);
2204 source->Send[s].Slot = NULL;
2205 source->Send[s].Gain = 1.0f;
2206 source->Send[s].GainHF = 1.0f;
2207 source->Send[s].HFReference = LOWPASSFREQREF;
2208 source->Send[s].GainLF = 1.0f;
2209 source->Send[s].LFReference = HIGHPASSFREQREF;
2212 source->NeedsUpdate = AL_TRUE;
2214 /* Clear any pre-existing source property structs, in case the
2215 * number of auxiliary sends changed. Playing (or paused) sources
2216 * will have updates specified.
2218 props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
2219 al_free(props);
2221 props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
2222 almemory_order_relaxed);
2223 while(props)
2225 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2226 al_free(props);
2227 props = next;
2230 AllocateVoices(context, context->MaxVoices, old_sends);
2231 UnlockUIntMapRead(&context->SourceMap);
2233 UpdateListenerProps(context);
2234 UpdateAllSourceProps(context);
2235 WriteUnlock(&context->PropLock);
2237 context = context->next;
2239 RestoreFPUMode(&oldMode);
2241 if(!(device->Flags&DEVICE_PAUSED))
2243 if(V0(device->Backend,start)() == ALC_FALSE)
2244 return ALC_INVALID_DEVICE;
2245 device->Flags |= DEVICE_RUNNING;
2248 return ALC_NO_ERROR;
2251 /* FreeDevice
2253 * Frees the device structure, and destroys any objects the app failed to
2254 * delete. Called once there's no more references on the device.
2256 static ALCvoid FreeDevice(ALCdevice *device)
2258 TRACE("%p\n", device);
2260 V0(device->Backend,close)();
2261 DELETE_OBJ(device->Backend);
2262 device->Backend = NULL;
2264 almtx_destroy(&device->BackendLock);
2266 if(device->DefaultSlot)
2268 DeinitEffectSlot(device->DefaultSlot);
2269 device->DefaultSlot = NULL;
2272 if(device->BufferMap.size > 0)
2274 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2275 (device->BufferMap.size==1)?"":"s");
2276 ReleaseALBuffers(device);
2278 ResetUIntMap(&device->BufferMap);
2280 if(device->EffectMap.size > 0)
2282 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2283 (device->EffectMap.size==1)?"":"s");
2284 ReleaseALEffects(device);
2286 ResetUIntMap(&device->EffectMap);
2288 if(device->FilterMap.size > 0)
2290 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2291 (device->FilterMap.size==1)?"":"s");
2292 ReleaseALFilters(device);
2294 ResetUIntMap(&device->FilterMap);
2296 AL_STRING_DEINIT(device->Hrtf.Name);
2297 FreeHrtfList(&device->Hrtf.List);
2299 al_free(device->Bs2b);
2300 device->Bs2b = NULL;
2302 al_free(device->Uhj_Encoder);
2303 device->Uhj_Encoder = NULL;
2305 bformatdec_free(device->AmbiDecoder);
2306 device->AmbiDecoder = NULL;
2308 ambiup_free(device->AmbiUp);
2309 device->AmbiUp = NULL;
2311 AL_STRING_DEINIT(device->DeviceName);
2313 al_free(device->Dry.Buffer);
2314 device->Dry.Buffer = NULL;
2315 device->Dry.NumChannels = 0;
2316 device->FOAOut.Buffer = NULL;
2317 device->FOAOut.NumChannels = 0;
2318 device->RealOut.Buffer = NULL;
2319 device->RealOut.NumChannels = 0;
2321 al_free(device);
2325 void ALCdevice_IncRef(ALCdevice *device)
2327 uint ref;
2328 ref = IncrementRef(&device->ref);
2329 TRACEREF("%p increasing refcount to %u\n", device, ref);
2332 void ALCdevice_DecRef(ALCdevice *device)
2334 uint ref;
2335 ref = DecrementRef(&device->ref);
2336 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2337 if(ref == 0) FreeDevice(device);
2340 /* VerifyDevice
2342 * Checks if the device handle is valid, and increments its ref count if so.
2344 static ALCboolean VerifyDevice(ALCdevice **device)
2346 ALCdevice *tmpDevice;
2348 LockLists();
2349 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2350 while(tmpDevice)
2352 if(tmpDevice == *device)
2354 ALCdevice_IncRef(tmpDevice);
2355 UnlockLists();
2356 return ALC_TRUE;
2358 tmpDevice = tmpDevice->next;
2360 UnlockLists();
2362 *device = NULL;
2363 return ALC_FALSE;
2367 /* InitContext
2369 * Initializes context fields
2371 static ALvoid InitContext(ALCcontext *Context)
2373 ALlistener *listener = Context->Listener;
2375 //Initialise listener
2376 listener->Gain = 1.0f;
2377 listener->MetersPerUnit = 1.0f;
2378 listener->Position[0] = 0.0f;
2379 listener->Position[1] = 0.0f;
2380 listener->Position[2] = 0.0f;
2381 listener->Velocity[0] = 0.0f;
2382 listener->Velocity[1] = 0.0f;
2383 listener->Velocity[2] = 0.0f;
2384 listener->Forward[0] = 0.0f;
2385 listener->Forward[1] = 0.0f;
2386 listener->Forward[2] = -1.0f;
2387 listener->Up[0] = 0.0f;
2388 listener->Up[1] = 1.0f;
2389 listener->Up[2] = 0.0f;
2391 aluMatrixfSet(&listener->Params.Matrix,
2392 1.0f, 0.0f, 0.0f, 0.0f,
2393 0.0f, 1.0f, 0.0f, 0.0f,
2394 0.0f, 0.0f, 1.0f, 0.0f,
2395 0.0f, 0.0f, 0.0f, 1.0f
2397 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2398 listener->Params.Gain = 1.0f;
2399 listener->Params.MetersPerUnit = 1.0f;
2400 listener->Params.DopplerFactor = 1.0f;
2401 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2403 ATOMIC_INIT(&listener->Update, NULL);
2404 ATOMIC_INIT(&listener->FreeList, NULL);
2406 //Validate Context
2407 InitRef(&Context->UpdateCount, 0);
2408 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2409 Context->GainBoost = 1.0f;
2410 RWLockInit(&Context->PropLock);
2411 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2412 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2413 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2415 //Set globals
2416 Context->DistanceModel = DefaultDistanceModel;
2417 Context->SourceDistanceModel = AL_FALSE;
2418 Context->DopplerFactor = 1.0f;
2419 Context->DopplerVelocity = 1.0f;
2420 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2421 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2423 Context->ExtensionList = alExtList;
2427 /* FreeContext
2429 * Cleans up the context, and destroys any remaining objects the app failed to
2430 * delete. Called once there's no more references on the context.
2432 static void FreeContext(ALCcontext *context)
2434 ALlistener *listener = context->Listener;
2435 struct ALlistenerProps *lprops;
2436 size_t count;
2438 TRACE("%p\n", context);
2440 if(context->SourceMap.size > 0)
2442 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2443 (context->SourceMap.size==1)?"":"s");
2444 ReleaseALSources(context);
2446 ResetUIntMap(&context->SourceMap);
2448 if(context->EffectSlotMap.size > 0)
2450 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2451 (context->EffectSlotMap.size==1)?"":"s");
2452 ReleaseALAuxiliaryEffectSlots(context);
2454 ResetUIntMap(&context->EffectSlotMap);
2456 al_free(context->Voices);
2457 context->Voices = NULL;
2458 context->VoiceCount = 0;
2459 context->MaxVoices = 0;
2461 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2463 TRACE("Freed unapplied listener update %p\n", lprops);
2464 al_free(lprops);
2466 count = 0;
2467 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2468 while(lprops)
2470 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2471 al_free(lprops);
2472 lprops = next;
2473 ++count;
2475 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2477 ALCdevice_DecRef(context->Device);
2478 context->Device = NULL;
2480 //Invalidate context
2481 memset(context, 0, sizeof(ALCcontext));
2482 al_free(context);
2485 /* ReleaseContext
2487 * Removes the context reference from the given device and removes it from
2488 * being current on the running thread or globally.
2490 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2492 ALCcontext *origctx;
2494 if(altss_get(LocalContext) == context)
2496 WARN("%p released while current on thread\n", context);
2497 altss_set(LocalContext, NULL);
2498 ALCcontext_DecRef(context);
2501 origctx = context;
2502 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2503 ALCcontext_DecRef(context);
2505 ALCdevice_Lock(device);
2506 origctx = context;
2507 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList,
2508 &origctx, context->next))
2510 ALCcontext *volatile*list = &origctx->next;
2511 while(*list)
2513 if(*list == context)
2515 *list = (*list)->next;
2516 break;
2518 list = &(*list)->next;
2521 ALCdevice_Unlock(device);
2523 ALCcontext_DecRef(context);
2526 void ALCcontext_IncRef(ALCcontext *context)
2528 uint ref = IncrementRef(&context->ref);
2529 TRACEREF("%p increasing refcount to %u\n", context, ref);
2532 void ALCcontext_DecRef(ALCcontext *context)
2534 uint ref = DecrementRef(&context->ref);
2535 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2536 if(ref == 0) FreeContext(context);
2539 static void ReleaseThreadCtx(void *ptr)
2541 ALCcontext *context = ptr;
2542 uint ref = DecrementRef(&context->ref);
2543 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2544 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2547 /* VerifyContext
2549 * Checks that the given context is valid, and increments its reference count.
2551 static ALCboolean VerifyContext(ALCcontext **context)
2553 ALCdevice *dev;
2555 LockLists();
2556 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2557 while(dev)
2559 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2560 while(ctx)
2562 if(ctx == *context)
2564 ALCcontext_IncRef(ctx);
2565 UnlockLists();
2566 return ALC_TRUE;
2568 ctx = ctx->next;
2570 dev = dev->next;
2572 UnlockLists();
2574 *context = NULL;
2575 return ALC_FALSE;
2579 /* GetContextRef
2581 * Returns the currently active context for this thread, and adds a reference
2582 * without locking it.
2584 ALCcontext *GetContextRef(void)
2586 ALCcontext *context;
2588 context = altss_get(LocalContext);
2589 if(context)
2590 ALCcontext_IncRef(context);
2591 else
2593 LockLists();
2594 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2595 if(context)
2596 ALCcontext_IncRef(context);
2597 UnlockLists();
2600 return context;
2604 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2606 ALCdevice *device = context->Device;
2607 ALsizei num_sends = device->NumAuxSends;
2608 struct ALsourceProps *props;
2609 size_t sizeof_props;
2610 size_t sizeof_voice;
2611 ALvoice **voices;
2612 ALvoice *voice;
2613 ALsizei v = 0;
2614 size_t size;
2616 if(num_voices == context->MaxVoices && num_sends == old_sends)
2617 return;
2619 /* Allocate the voice pointers, voices, and the voices' stored source
2620 * property set (including the dynamically-sized Send[] array) in one
2621 * chunk.
2623 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2624 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2625 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2627 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2628 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2629 props = (struct ALsourceProps*)((char*)voice + num_voices*sizeof_voice);
2631 if(context->Voices)
2633 ALsizei v_count = mini(context->VoiceCount, num_voices);
2634 for(;v < v_count;v++)
2636 ALsizei s_count = mini(old_sends, num_sends);
2637 ALsizei i;
2639 /* Copy the old voice data and source property set to the new
2640 * storage.
2642 *voice = *(context->Voices[v]);
2643 for(i = 0;i < s_count;i++)
2644 voice->Send[i] = context->Voices[v]->Send[i];
2645 *props = *(context->Voices[v]->Props);
2646 for(i = 0;i < s_count;i++)
2647 props->Send[i] = context->Voices[v]->Props->Send[i];
2649 /* Set this voice's property set pointer and increment 'props' to
2650 * the next property storage space.
2652 voice->Props = props;
2653 props = (struct ALsourceProps*)((char*)props + sizeof_props);
2655 /* Set this voice's reference and increment 'voice' to the next
2656 * voice storage space.
2658 voices[v] = voice;
2659 voice = (ALvoice*)((char*)voice + sizeof_voice);
2662 /* Finish setting the voices' property set pointers and references. */
2663 for(;v < num_voices;v++)
2665 voice->Props = props;
2666 props = (struct ALsourceProps*)((char*)props + sizeof_props);
2668 voices[v] = voice;
2669 voice = (ALvoice*)((char*)voice + sizeof_voice);
2672 al_free(context->Voices);
2673 context->Voices = voices;
2674 context->MaxVoices = num_voices;
2675 context->VoiceCount = mini(context->VoiceCount, num_voices);
2679 /************************************************
2680 * Standard ALC functions
2681 ************************************************/
2683 /* alcGetError
2685 * Return last ALC generated error code for the given device
2687 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2689 ALCenum errorCode;
2691 if(VerifyDevice(&device))
2693 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2694 ALCdevice_DecRef(device);
2696 else
2697 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2699 return errorCode;
2703 /* alcSuspendContext
2705 * Suspends updates for the given context
2707 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2709 if(!SuspendDefers)
2710 return;
2712 if(!VerifyContext(&context))
2713 alcSetError(NULL, ALC_INVALID_CONTEXT);
2714 else
2716 ALCcontext_DeferUpdates(context, DeferAllowPlay);
2717 ALCcontext_DecRef(context);
2721 /* alcProcessContext
2723 * Resumes processing updates for the given context
2725 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2727 if(!SuspendDefers)
2728 return;
2730 if(!VerifyContext(&context))
2731 alcSetError(NULL, ALC_INVALID_CONTEXT);
2732 else
2734 ALCcontext_ProcessUpdates(context);
2735 ALCcontext_DecRef(context);
2740 /* alcGetString
2742 * Returns information about the device, and error strings
2744 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2746 const ALCchar *value = NULL;
2748 switch(param)
2750 case ALC_NO_ERROR:
2751 value = alcNoError;
2752 break;
2754 case ALC_INVALID_ENUM:
2755 value = alcErrInvalidEnum;
2756 break;
2758 case ALC_INVALID_VALUE:
2759 value = alcErrInvalidValue;
2760 break;
2762 case ALC_INVALID_DEVICE:
2763 value = alcErrInvalidDevice;
2764 break;
2766 case ALC_INVALID_CONTEXT:
2767 value = alcErrInvalidContext;
2768 break;
2770 case ALC_OUT_OF_MEMORY:
2771 value = alcErrOutOfMemory;
2772 break;
2774 case ALC_DEVICE_SPECIFIER:
2775 value = alcDefaultName;
2776 break;
2778 case ALC_ALL_DEVICES_SPECIFIER:
2779 if(VerifyDevice(&Device))
2781 value = al_string_get_cstr(Device->DeviceName);
2782 ALCdevice_DecRef(Device);
2784 else
2786 ProbeAllDevicesList();
2787 value = al_string_get_cstr(alcAllDevicesList);
2789 break;
2791 case ALC_CAPTURE_DEVICE_SPECIFIER:
2792 if(VerifyDevice(&Device))
2794 value = al_string_get_cstr(Device->DeviceName);
2795 ALCdevice_DecRef(Device);
2797 else
2799 ProbeCaptureDeviceList();
2800 value = al_string_get_cstr(alcCaptureDeviceList);
2802 break;
2804 /* Default devices are always first in the list */
2805 case ALC_DEFAULT_DEVICE_SPECIFIER:
2806 value = alcDefaultName;
2807 break;
2809 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2810 if(al_string_empty(alcAllDevicesList))
2811 ProbeAllDevicesList();
2813 VerifyDevice(&Device);
2815 free(alcDefaultAllDevicesSpecifier);
2816 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2817 if(!alcDefaultAllDevicesSpecifier)
2818 alcSetError(Device, ALC_OUT_OF_MEMORY);
2820 value = alcDefaultAllDevicesSpecifier;
2821 if(Device) ALCdevice_DecRef(Device);
2822 break;
2824 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2825 if(al_string_empty(alcCaptureDeviceList))
2826 ProbeCaptureDeviceList();
2828 VerifyDevice(&Device);
2830 free(alcCaptureDefaultDeviceSpecifier);
2831 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2832 if(!alcCaptureDefaultDeviceSpecifier)
2833 alcSetError(Device, ALC_OUT_OF_MEMORY);
2835 value = alcCaptureDefaultDeviceSpecifier;
2836 if(Device) ALCdevice_DecRef(Device);
2837 break;
2839 case ALC_EXTENSIONS:
2840 if(!VerifyDevice(&Device))
2841 value = alcNoDeviceExtList;
2842 else
2844 value = alcExtensionList;
2845 ALCdevice_DecRef(Device);
2847 break;
2849 case ALC_HRTF_SPECIFIER_SOFT:
2850 if(!VerifyDevice(&Device))
2851 alcSetError(NULL, ALC_INVALID_DEVICE);
2852 else
2854 almtx_lock(&Device->BackendLock);
2855 value = (Device->Hrtf.Handle ? al_string_get_cstr(Device->Hrtf.Name) : "");
2856 almtx_unlock(&Device->BackendLock);
2857 ALCdevice_DecRef(Device);
2859 break;
2861 default:
2862 VerifyDevice(&Device);
2863 alcSetError(Device, ALC_INVALID_ENUM);
2864 if(Device) ALCdevice_DecRef(Device);
2865 break;
2868 return value;
2872 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2874 ALCsizei i;
2876 if(size <= 0 || values == NULL)
2878 alcSetError(device, ALC_INVALID_VALUE);
2879 return 0;
2882 if(!device)
2884 switch(param)
2886 case ALC_MAJOR_VERSION:
2887 values[0] = alcMajorVersion;
2888 return 1;
2889 case ALC_MINOR_VERSION:
2890 values[0] = alcMinorVersion;
2891 return 1;
2893 case ALC_ATTRIBUTES_SIZE:
2894 case ALC_ALL_ATTRIBUTES:
2895 case ALC_FREQUENCY:
2896 case ALC_REFRESH:
2897 case ALC_SYNC:
2898 case ALC_MONO_SOURCES:
2899 case ALC_STEREO_SOURCES:
2900 case ALC_CAPTURE_SAMPLES:
2901 case ALC_FORMAT_CHANNELS_SOFT:
2902 case ALC_FORMAT_TYPE_SOFT:
2903 alcSetError(NULL, ALC_INVALID_DEVICE);
2904 return 0;
2906 default:
2907 alcSetError(NULL, ALC_INVALID_ENUM);
2908 return 0;
2910 return 0;
2913 if(device->Type == Capture)
2915 switch(param)
2917 case ALC_CAPTURE_SAMPLES:
2918 almtx_lock(&device->BackendLock);
2919 values[0] = V0(device->Backend,availableSamples)();
2920 almtx_unlock(&device->BackendLock);
2921 return 1;
2923 case ALC_CONNECTED:
2924 values[0] = device->Connected;
2925 return 1;
2927 default:
2928 alcSetError(device, ALC_INVALID_ENUM);
2929 return 0;
2931 return 0;
2934 /* render device */
2935 switch(param)
2937 case ALC_MAJOR_VERSION:
2938 values[0] = alcMajorVersion;
2939 return 1;
2941 case ALC_MINOR_VERSION:
2942 values[0] = alcMinorVersion;
2943 return 1;
2945 case ALC_EFX_MAJOR_VERSION:
2946 values[0] = alcEFXMajorVersion;
2947 return 1;
2949 case ALC_EFX_MINOR_VERSION:
2950 values[0] = alcEFXMinorVersion;
2951 return 1;
2953 case ALC_ATTRIBUTES_SIZE:
2954 values[0] = 17;
2955 return 1;
2957 case ALC_ALL_ATTRIBUTES:
2958 if(size < 17)
2960 alcSetError(device, ALC_INVALID_VALUE);
2961 return 0;
2964 i = 0;
2965 almtx_lock(&device->BackendLock);
2966 values[i++] = ALC_FREQUENCY;
2967 values[i++] = device->Frequency;
2969 if(device->Type != Loopback)
2971 values[i++] = ALC_REFRESH;
2972 values[i++] = device->Frequency / device->UpdateSize;
2974 values[i++] = ALC_SYNC;
2975 values[i++] = ALC_FALSE;
2977 else
2979 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2980 values[i++] = device->FmtChans;
2982 values[i++] = ALC_FORMAT_TYPE_SOFT;
2983 values[i++] = device->FmtType;
2986 values[i++] = ALC_MONO_SOURCES;
2987 values[i++] = device->NumMonoSources;
2989 values[i++] = ALC_STEREO_SOURCES;
2990 values[i++] = device->NumStereoSources;
2992 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2993 values[i++] = device->NumAuxSends;
2995 values[i++] = ALC_HRTF_SOFT;
2996 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
2998 values[i++] = ALC_HRTF_STATUS_SOFT;
2999 values[i++] = device->Hrtf.Status;
3000 almtx_unlock(&device->BackendLock);
3002 values[i++] = 0;
3003 return i;
3005 case ALC_FREQUENCY:
3006 values[0] = device->Frequency;
3007 return 1;
3009 case ALC_REFRESH:
3010 if(device->Type == Loopback)
3012 alcSetError(device, ALC_INVALID_DEVICE);
3013 return 0;
3015 almtx_lock(&device->BackendLock);
3016 values[0] = device->Frequency / device->UpdateSize;
3017 almtx_unlock(&device->BackendLock);
3018 return 1;
3020 case ALC_SYNC:
3021 if(device->Type == Loopback)
3023 alcSetError(device, ALC_INVALID_DEVICE);
3024 return 0;
3026 values[0] = ALC_FALSE;
3027 return 1;
3029 case ALC_FORMAT_CHANNELS_SOFT:
3030 if(device->Type != Loopback)
3032 alcSetError(device, ALC_INVALID_DEVICE);
3033 return 0;
3035 values[0] = device->FmtChans;
3036 return 1;
3038 case ALC_FORMAT_TYPE_SOFT:
3039 if(device->Type != Loopback)
3041 alcSetError(device, ALC_INVALID_DEVICE);
3042 return 0;
3044 values[0] = device->FmtType;
3045 return 1;
3047 case ALC_MONO_SOURCES:
3048 values[0] = device->NumMonoSources;
3049 return 1;
3051 case ALC_STEREO_SOURCES:
3052 values[0] = device->NumStereoSources;
3053 return 1;
3055 case ALC_MAX_AUXILIARY_SENDS:
3056 values[0] = device->NumAuxSends;
3057 return 1;
3059 case ALC_CONNECTED:
3060 values[0] = device->Connected;
3061 return 1;
3063 case ALC_HRTF_SOFT:
3064 values[0] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3065 return 1;
3067 case ALC_HRTF_STATUS_SOFT:
3068 values[0] = device->Hrtf.Status;
3069 return 1;
3071 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3072 almtx_lock(&device->BackendLock);
3073 FreeHrtfList(&device->Hrtf.List);
3074 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
3075 values[0] = (ALCint)VECTOR_SIZE(device->Hrtf.List);
3076 almtx_unlock(&device->BackendLock);
3077 return 1;
3079 default:
3080 alcSetError(device, ALC_INVALID_ENUM);
3081 return 0;
3083 return 0;
3086 /* alcGetIntegerv
3088 * Returns information about the device and the version of OpenAL
3090 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3092 VerifyDevice(&device);
3093 if(size <= 0 || values == NULL)
3094 alcSetError(device, ALC_INVALID_VALUE);
3095 else
3096 GetIntegerv(device, param, size, values);
3097 if(device) ALCdevice_DecRef(device);
3100 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3102 ALCint *ivals;
3103 ALsizei i;
3105 VerifyDevice(&device);
3106 if(size <= 0 || values == NULL)
3107 alcSetError(device, ALC_INVALID_VALUE);
3108 else if(!device || device->Type == Capture)
3110 ivals = malloc(size * sizeof(ALCint));
3111 size = GetIntegerv(device, pname, size, ivals);
3112 for(i = 0;i < size;i++)
3113 values[i] = ivals[i];
3114 free(ivals);
3116 else /* render device */
3118 ClockLatency clock;
3119 ALuint64 basecount;
3120 ALuint samplecount;
3121 ALuint refcount;
3123 switch(pname)
3125 case ALC_ATTRIBUTES_SIZE:
3126 *values = 21;
3127 break;
3129 case ALC_ALL_ATTRIBUTES:
3130 if(size < 21)
3131 alcSetError(device, ALC_INVALID_VALUE);
3132 else
3134 i = 0;
3135 almtx_lock(&device->BackendLock);
3136 values[i++] = ALC_FREQUENCY;
3137 values[i++] = device->Frequency;
3139 if(device->Type != Loopback)
3141 values[i++] = ALC_REFRESH;
3142 values[i++] = device->Frequency / device->UpdateSize;
3144 values[i++] = ALC_SYNC;
3145 values[i++] = ALC_FALSE;
3147 else
3149 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3150 values[i++] = device->FmtChans;
3152 values[i++] = ALC_FORMAT_TYPE_SOFT;
3153 values[i++] = device->FmtType;
3156 values[i++] = ALC_MONO_SOURCES;
3157 values[i++] = device->NumMonoSources;
3159 values[i++] = ALC_STEREO_SOURCES;
3160 values[i++] = device->NumStereoSources;
3162 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3163 values[i++] = device->NumAuxSends;
3165 values[i++] = ALC_HRTF_SOFT;
3166 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3168 values[i++] = ALC_HRTF_STATUS_SOFT;
3169 values[i++] = device->Hrtf.Status;
3171 clock = V0(device->Backend,getClockLatency)();
3172 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3173 values[i++] = clock.ClockTime;
3175 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3176 values[i++] = clock.Latency;
3177 almtx_unlock(&device->BackendLock);
3179 values[i++] = 0;
3181 break;
3183 case ALC_DEVICE_CLOCK_SOFT:
3184 almtx_lock(&device->BackendLock);
3185 do {
3186 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3187 althrd_yield();
3188 basecount = device->ClockBase;
3189 samplecount = device->SamplesDone;
3190 } while(refcount != ReadRef(&device->MixCount));
3191 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3192 almtx_unlock(&device->BackendLock);
3193 break;
3195 case ALC_DEVICE_LATENCY_SOFT:
3197 almtx_lock(&device->BackendLock);
3198 clock = V0(device->Backend,getClockLatency)();
3199 almtx_unlock(&device->BackendLock);
3200 *values = clock.Latency;
3202 break;
3204 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3205 if(size < 2)
3206 alcSetError(device, ALC_INVALID_VALUE);
3207 else
3209 ClockLatency clock;
3210 almtx_lock(&device->BackendLock);
3211 clock = V0(device->Backend,getClockLatency)();
3212 almtx_unlock(&device->BackendLock);
3213 values[0] = clock.ClockTime;
3214 values[1] = clock.Latency;
3216 break;
3218 default:
3219 ivals = malloc(size * sizeof(ALCint));
3220 size = GetIntegerv(device, pname, size, ivals);
3221 for(i = 0;i < size;i++)
3222 values[i] = ivals[i];
3223 free(ivals);
3224 break;
3227 if(device)
3228 ALCdevice_DecRef(device);
3232 /* alcIsExtensionPresent
3234 * Determines if there is support for a particular extension
3236 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3238 ALCboolean bResult = ALC_FALSE;
3240 VerifyDevice(&device);
3242 if(!extName)
3243 alcSetError(device, ALC_INVALID_VALUE);
3244 else
3246 size_t len = strlen(extName);
3247 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3248 while(ptr && *ptr)
3250 if(strncasecmp(ptr, extName, len) == 0 &&
3251 (ptr[len] == '\0' || isspace(ptr[len])))
3253 bResult = ALC_TRUE;
3254 break;
3256 if((ptr=strchr(ptr, ' ')) != NULL)
3258 do {
3259 ++ptr;
3260 } while(isspace(*ptr));
3264 if(device)
3265 ALCdevice_DecRef(device);
3266 return bResult;
3270 /* alcGetProcAddress
3272 * Retrieves the function address for a particular extension function
3274 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3276 ALCvoid *ptr = NULL;
3278 if(!funcName)
3280 VerifyDevice(&device);
3281 alcSetError(device, ALC_INVALID_VALUE);
3282 if(device) ALCdevice_DecRef(device);
3284 else
3286 ALsizei i = 0;
3287 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3288 i++;
3289 ptr = alcFunctions[i].address;
3292 return ptr;
3296 /* alcGetEnumValue
3298 * Get the value for a particular ALC enumeration name
3300 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3302 ALCenum val = 0;
3304 if(!enumName)
3306 VerifyDevice(&device);
3307 alcSetError(device, ALC_INVALID_VALUE);
3308 if(device) ALCdevice_DecRef(device);
3310 else
3312 ALsizei i = 0;
3313 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3314 i++;
3315 val = enumeration[i].value;
3318 return val;
3322 /* alcCreateContext
3324 * Create and attach a context to the given device.
3326 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3328 ALCcontext *ALContext;
3329 ALfloat valf;
3330 ALCenum err;
3332 LockLists();
3333 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3335 UnlockLists();
3336 alcSetError(device, ALC_INVALID_DEVICE);
3337 if(device) ALCdevice_DecRef(device);
3338 return NULL;
3340 almtx_lock(&device->BackendLock);
3341 UnlockLists();
3343 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3345 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3346 if(ALContext)
3348 InitRef(&ALContext->ref, 1);
3349 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3351 ALContext->Device = device;
3352 ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
3354 ALContext->Voices = NULL;
3355 ALContext->MaxVoices = 0;
3356 ALContext->VoiceCount = 0;
3357 AllocateVoices(ALContext, 256, device->NumAuxSends);
3359 if(!ALContext || !ALContext->Voices)
3361 almtx_unlock(&device->BackendLock);
3363 if(ALContext)
3365 al_free(ALContext->Voices);
3366 ALContext->Voices = NULL;
3368 al_free(ALContext);
3369 ALContext = NULL;
3372 alcSetError(device, ALC_OUT_OF_MEMORY);
3373 ALCdevice_DecRef(device);
3374 return NULL;
3377 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3379 almtx_unlock(&device->BackendLock);
3381 al_free(ALContext->Voices);
3382 ALContext->Voices = NULL;
3384 al_free(ALContext);
3385 ALContext = NULL;
3387 alcSetError(device, err);
3388 if(err == ALC_INVALID_DEVICE)
3390 V0(device->Backend,lock)();
3391 aluHandleDisconnect(device);
3392 V0(device->Backend,unlock)();
3394 ALCdevice_DecRef(device);
3395 return NULL;
3398 ALCdevice_IncRef(ALContext->Device);
3399 InitContext(ALContext);
3401 if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3403 if(!isfinite(valf))
3404 ERR("volume-adjust must be finite: %f\n", valf);
3405 else
3407 ALfloat db = clampf(valf, -24.0f, 24.0f);
3408 if(db != valf)
3409 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3410 ALContext->GainBoost = powf(10.0f, db/20.0f);
3411 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3414 UpdateListenerProps(ALContext);
3417 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3418 do {
3419 ALContext->next = head;
3420 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3421 &device->ContextList, &head, ALContext) == 0);
3423 almtx_unlock(&device->BackendLock);
3425 ALCdevice_DecRef(device);
3427 TRACE("Created context %p\n", ALContext);
3428 return ALContext;
3431 /* alcDestroyContext
3433 * Remove a context from its device
3435 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3437 ALCdevice *Device;
3439 LockLists();
3440 /* alcGetContextsDevice sets an error for invalid contexts */
3441 Device = alcGetContextsDevice(context);
3442 if(Device)
3444 almtx_lock(&Device->BackendLock);
3445 ReleaseContext(context, Device);
3446 if(!ATOMIC_LOAD_SEQ(&Device->ContextList))
3448 V0(Device->Backend,stop)();
3449 Device->Flags &= ~DEVICE_RUNNING;
3451 almtx_unlock(&Device->BackendLock);
3453 UnlockLists();
3457 /* alcGetCurrentContext
3459 * Returns the currently active context on the calling thread
3461 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3463 ALCcontext *Context = altss_get(LocalContext);
3464 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3465 return Context;
3468 /* alcGetThreadContext
3470 * Returns the currently active thread-local context
3472 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3474 return altss_get(LocalContext);
3478 /* alcMakeContextCurrent
3480 * Makes the given context the active process-wide context, and removes the
3481 * thread-local context for the calling thread.
3483 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3485 /* context must be valid or NULL */
3486 if(context && !VerifyContext(&context))
3488 alcSetError(NULL, ALC_INVALID_CONTEXT);
3489 return ALC_FALSE;
3491 /* context's reference count is already incremented */
3492 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3493 if(context) ALCcontext_DecRef(context);
3495 if((context=altss_get(LocalContext)) != NULL)
3497 altss_set(LocalContext, NULL);
3498 ALCcontext_DecRef(context);
3501 return ALC_TRUE;
3504 /* alcSetThreadContext
3506 * Makes the given context the active context for the current thread
3508 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3510 ALCcontext *old;
3512 /* context must be valid or NULL */
3513 if(context && !VerifyContext(&context))
3515 alcSetError(NULL, ALC_INVALID_CONTEXT);
3516 return ALC_FALSE;
3518 /* context's reference count is already incremented */
3519 old = altss_get(LocalContext);
3520 altss_set(LocalContext, context);
3521 if(old) ALCcontext_DecRef(old);
3523 return ALC_TRUE;
3527 /* alcGetContextsDevice
3529 * Returns the device that a particular context is attached to
3531 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3533 ALCdevice *Device;
3535 if(!VerifyContext(&Context))
3537 alcSetError(NULL, ALC_INVALID_CONTEXT);
3538 return NULL;
3540 Device = Context->Device;
3541 ALCcontext_DecRef(Context);
3543 return Device;
3547 /* alcOpenDevice
3549 * Opens the named device.
3551 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3553 const ALCchar *fmt;
3554 ALCdevice *device;
3555 ALCenum err;
3557 DO_INITCONFIG();
3559 if(!PlaybackBackend.name)
3561 alcSetError(NULL, ALC_INVALID_VALUE);
3562 return NULL;
3565 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3566 #ifdef _WIN32
3567 /* Some old Windows apps hardcode these expecting OpenAL to use a
3568 * specific audio API, even when they're not enumerated. Creative's
3569 * router effectively ignores them too.
3571 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3572 || strcasecmp(deviceName, "MMSYSTEM") == 0
3573 #endif
3575 deviceName = NULL;
3577 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3578 if(!device)
3580 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3581 return NULL;
3584 //Validate device
3585 InitRef(&device->ref, 1);
3586 device->Connected = ALC_TRUE;
3587 device->Type = Playback;
3588 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3590 device->Flags = 0;
3591 device->Bs2b = NULL;
3592 device->Uhj_Encoder = NULL;
3593 VECTOR_INIT(device->Hrtf.List);
3594 AL_STRING_INIT(device->Hrtf.Name);
3595 device->Render_Mode = NormalRender;
3596 AL_STRING_INIT(device->DeviceName);
3597 device->Dry.Buffer = NULL;
3598 device->Dry.NumChannels = 0;
3599 device->FOAOut.Buffer = NULL;
3600 device->FOAOut.NumChannels = 0;
3601 device->RealOut.Buffer = NULL;
3602 device->RealOut.NumChannels = 0;
3604 ATOMIC_INIT(&device->ContextList, NULL);
3606 device->ClockBase = 0;
3607 device->SamplesDone = 0;
3609 device->SourcesMax = 256;
3610 device->AuxiliaryEffectSlotMax = 4;
3611 device->NumAuxSends = MAX_SENDS;
3613 InitUIntMap(&device->BufferMap, ~0);
3614 InitUIntMap(&device->EffectMap, ~0);
3615 InitUIntMap(&device->FilterMap, ~0);
3617 //Set output format
3618 device->FmtChans = DevFmtChannelsDefault;
3619 device->FmtType = DevFmtTypeDefault;
3620 device->Frequency = DEFAULT_OUTPUT_RATE;
3621 device->IsHeadphones = AL_FALSE;
3622 device->AmbiFmt = AmbiFormat_Default;
3623 device->NumUpdates = 4;
3624 device->UpdateSize = 1024;
3626 if(!PlaybackBackend.getFactory)
3627 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3628 ALCbackend_Playback);
3629 else
3631 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3632 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3634 if(!device->Backend)
3636 al_free(device);
3637 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3638 return NULL;
3642 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3644 static const struct {
3645 const char name[16];
3646 enum DevFmtChannels chans;
3647 } chanlist[] = {
3648 { "mono", DevFmtMono },
3649 { "stereo", DevFmtStereo },
3650 { "quad", DevFmtQuad },
3651 { "surround51", DevFmtX51 },
3652 { "surround61", DevFmtX61 },
3653 { "surround71", DevFmtX71 },
3654 { "surround51rear", DevFmtX51Rear },
3655 { "ambi1", DevFmtAmbi1 },
3656 { "ambi2", DevFmtAmbi2 },
3657 { "ambi3", DevFmtAmbi3 },
3659 size_t i;
3661 for(i = 0;i < COUNTOF(chanlist);i++)
3663 if(strcasecmp(chanlist[i].name, fmt) == 0)
3665 device->FmtChans = chanlist[i].chans;
3666 device->Flags |= DEVICE_CHANNELS_REQUEST;
3667 break;
3670 if(i == COUNTOF(chanlist))
3671 ERR("Unsupported channels: %s\n", fmt);
3673 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3675 static const struct {
3676 const char name[16];
3677 enum DevFmtType type;
3678 } typelist[] = {
3679 { "int8", DevFmtByte },
3680 { "uint8", DevFmtUByte },
3681 { "int16", DevFmtShort },
3682 { "uint16", DevFmtUShort },
3683 { "int32", DevFmtInt },
3684 { "uint32", DevFmtUInt },
3685 { "float32", DevFmtFloat },
3687 size_t i;
3689 for(i = 0;i < COUNTOF(typelist);i++)
3691 if(strcasecmp(typelist[i].name, fmt) == 0)
3693 device->FmtType = typelist[i].type;
3694 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3695 break;
3698 if(i == COUNTOF(typelist))
3699 ERR("Unsupported sample-type: %s\n", fmt);
3702 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3704 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3705 if(device->Frequency < MIN_OUTPUT_RATE)
3706 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3707 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3710 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3711 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3713 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3714 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3715 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3716 device->UpdateSize = (device->UpdateSize+3)&~3;
3718 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3719 if(device->SourcesMax == 0) device->SourcesMax = 256;
3721 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3722 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3724 ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends);
3725 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3727 device->NumStereoSources = 1;
3728 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3730 // Find a playback device to open
3731 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3733 DELETE_OBJ(device->Backend);
3734 al_free(device);
3735 alcSetError(NULL, err);
3736 return NULL;
3738 almtx_init(&device->BackendLock, almtx_plain);
3740 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3742 if(strcasecmp(fmt, "fuma") == 0)
3743 device->AmbiFmt = AmbiFormat_FuMa;
3744 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3745 device->AmbiFmt = AmbiFormat_ACN_SN3D;
3746 else if(strcasecmp(fmt, "acn+n3d") == 0)
3747 device->AmbiFmt = AmbiFormat_ACN_N3D;
3748 else
3749 ERR("Unsupported ambi-format: %s\n", fmt);
3752 if(DefaultEffect.type != AL_EFFECT_NULL)
3754 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3755 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3757 device->DefaultSlot = NULL;
3758 ERR("Failed to initialize the default effect slot\n");
3760 else
3762 aluInitEffectPanning(device->DefaultSlot);
3763 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3765 DeinitEffectSlot(device->DefaultSlot);
3766 device->DefaultSlot = NULL;
3767 ERR("Failed to initialize the default effect\n");
3773 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3774 do {
3775 device->next = head;
3776 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3779 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3780 return device;
3783 /* alcCloseDevice
3785 * Closes the given device.
3787 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3789 ALCdevice *iter, *origdev;
3790 ALCcontext *ctx;
3792 LockLists();
3793 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3794 do {
3795 if(iter == device)
3796 break;
3797 } while((iter=iter->next) != NULL);
3798 if(!iter || iter->Type == Capture)
3800 alcSetError(iter, ALC_INVALID_DEVICE);
3801 UnlockLists();
3802 return ALC_FALSE;
3804 almtx_lock(&device->BackendLock);
3806 origdev = device;
3807 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3809 ALCdevice *volatile*list = &origdev->next;
3810 while(*list)
3812 if(*list == device)
3814 *list = (*list)->next;
3815 break;
3817 list = &(*list)->next;
3820 UnlockLists();
3822 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
3823 while(ctx != NULL)
3825 ALCcontext *next = ctx->next;
3826 WARN("Releasing context %p\n", ctx);
3827 ReleaseContext(ctx, device);
3828 ctx = next;
3830 if((device->Flags&DEVICE_RUNNING))
3831 V0(device->Backend,stop)();
3832 device->Flags &= ~DEVICE_RUNNING;
3833 almtx_unlock(&device->BackendLock);
3835 ALCdevice_DecRef(device);
3837 return ALC_TRUE;
3841 /************************************************
3842 * ALC capture functions
3843 ************************************************/
3844 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3846 ALCdevice *device = NULL;
3847 ALCenum err;
3849 DO_INITCONFIG();
3851 if(!CaptureBackend.name)
3853 alcSetError(NULL, ALC_INVALID_VALUE);
3854 return NULL;
3857 if(samples <= 0)
3859 alcSetError(NULL, ALC_INVALID_VALUE);
3860 return NULL;
3863 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3864 deviceName = NULL;
3866 device = al_calloc(16, sizeof(ALCdevice));
3867 if(!device)
3869 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3870 return NULL;
3873 //Validate device
3874 InitRef(&device->ref, 1);
3875 device->Connected = ALC_TRUE;
3876 device->Type = Capture;
3878 VECTOR_INIT(device->Hrtf.List);
3879 AL_STRING_INIT(device->Hrtf.Name);
3881 AL_STRING_INIT(device->DeviceName);
3882 device->Dry.Buffer = NULL;
3883 device->Dry.NumChannels = 0;
3884 device->FOAOut.Buffer = NULL;
3885 device->FOAOut.NumChannels = 0;
3886 device->RealOut.Buffer = NULL;
3887 device->RealOut.NumChannels = 0;
3889 InitUIntMap(&device->BufferMap, ~0);
3890 InitUIntMap(&device->EffectMap, ~0);
3891 InitUIntMap(&device->FilterMap, ~0);
3893 if(!CaptureBackend.getFactory)
3894 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3895 ALCbackend_Capture);
3896 else
3898 ALCbackendFactory *factory = CaptureBackend.getFactory();
3899 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3901 if(!device->Backend)
3903 al_free(device);
3904 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3905 return NULL;
3908 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3909 device->Frequency = frequency;
3911 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3912 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3914 al_free(device);
3915 alcSetError(NULL, ALC_INVALID_ENUM);
3916 return NULL;
3918 device->IsHeadphones = AL_FALSE;
3919 device->AmbiFmt = AmbiFormat_Default;
3921 device->UpdateSize = samples;
3922 device->NumUpdates = 1;
3924 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3926 al_free(device);
3927 alcSetError(NULL, err);
3928 return NULL;
3930 almtx_init(&device->BackendLock, almtx_plain);
3933 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3934 do {
3935 device->next = head;
3936 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3939 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3940 return device;
3943 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3945 ALCdevice *iter, *origdev;
3947 LockLists();
3948 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3949 do {
3950 if(iter == device)
3951 break;
3952 } while((iter=iter->next) != NULL);
3953 if(!iter || iter->Type != Capture)
3955 alcSetError(iter, ALC_INVALID_DEVICE);
3956 UnlockLists();
3957 return ALC_FALSE;
3960 origdev = device;
3961 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3963 ALCdevice *volatile*list = &origdev->next;
3964 while(*list)
3966 if(*list == device)
3968 *list = (*list)->next;
3969 break;
3971 list = &(*list)->next;
3974 UnlockLists();
3976 ALCdevice_DecRef(device);
3978 return ALC_TRUE;
3981 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3983 if(!VerifyDevice(&device) || device->Type != Capture)
3984 alcSetError(device, ALC_INVALID_DEVICE);
3985 else
3987 almtx_lock(&device->BackendLock);
3988 if(!device->Connected)
3989 alcSetError(device, ALC_INVALID_DEVICE);
3990 else if(!(device->Flags&DEVICE_RUNNING))
3992 if(V0(device->Backend,start)())
3993 device->Flags |= DEVICE_RUNNING;
3994 else
3996 aluHandleDisconnect(device);
3997 alcSetError(device, ALC_INVALID_DEVICE);
4000 almtx_unlock(&device->BackendLock);
4003 if(device) ALCdevice_DecRef(device);
4006 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4008 if(!VerifyDevice(&device) || device->Type != Capture)
4009 alcSetError(device, ALC_INVALID_DEVICE);
4010 else
4012 almtx_lock(&device->BackendLock);
4013 if((device->Flags&DEVICE_RUNNING))
4014 V0(device->Backend,stop)();
4015 device->Flags &= ~DEVICE_RUNNING;
4016 almtx_unlock(&device->BackendLock);
4019 if(device) ALCdevice_DecRef(device);
4022 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4024 if(!VerifyDevice(&device) || device->Type != Capture)
4025 alcSetError(device, ALC_INVALID_DEVICE);
4026 else
4028 ALCenum err = ALC_INVALID_VALUE;
4030 almtx_lock(&device->BackendLock);
4031 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4032 err = V(device->Backend,captureSamples)(buffer, samples);
4033 almtx_unlock(&device->BackendLock);
4035 if(err != ALC_NO_ERROR)
4036 alcSetError(device, err);
4038 if(device) ALCdevice_DecRef(device);
4042 /************************************************
4043 * ALC loopback functions
4044 ************************************************/
4046 /* alcLoopbackOpenDeviceSOFT
4048 * Open a loopback device, for manual rendering.
4050 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4052 ALCbackendFactory *factory;
4053 ALCdevice *device;
4055 DO_INITCONFIG();
4057 /* Make sure the device name, if specified, is us. */
4058 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4060 alcSetError(NULL, ALC_INVALID_VALUE);
4061 return NULL;
4064 device = al_calloc(16, sizeof(ALCdevice));
4065 if(!device)
4067 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4068 return NULL;
4071 //Validate device
4072 InitRef(&device->ref, 1);
4073 device->Connected = ALC_TRUE;
4074 device->Type = Loopback;
4075 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4077 device->Flags = 0;
4078 VECTOR_INIT(device->Hrtf.List);
4079 AL_STRING_INIT(device->Hrtf.Name);
4080 device->Bs2b = NULL;
4081 device->Uhj_Encoder = NULL;
4082 device->Render_Mode = NormalRender;
4083 AL_STRING_INIT(device->DeviceName);
4084 device->Dry.Buffer = NULL;
4085 device->Dry.NumChannels = 0;
4086 device->FOAOut.Buffer = NULL;
4087 device->FOAOut.NumChannels = 0;
4088 device->RealOut.Buffer = NULL;
4089 device->RealOut.NumChannels = 0;
4091 ATOMIC_INIT(&device->ContextList, NULL);
4093 device->ClockBase = 0;
4094 device->SamplesDone = 0;
4096 device->SourcesMax = 256;
4097 device->AuxiliaryEffectSlotMax = 4;
4098 device->NumAuxSends = MAX_SENDS;
4100 InitUIntMap(&device->BufferMap, ~0);
4101 InitUIntMap(&device->EffectMap, ~0);
4102 InitUIntMap(&device->FilterMap, ~0);
4104 factory = ALCloopbackFactory_getFactory();
4105 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4106 if(!device->Backend)
4108 al_free(device);
4109 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4110 return NULL;
4112 almtx_init(&device->BackendLock, almtx_plain);
4114 //Set output format
4115 device->NumUpdates = 0;
4116 device->UpdateSize = 0;
4118 device->Frequency = DEFAULT_OUTPUT_RATE;
4119 device->FmtChans = DevFmtChannelsDefault;
4120 device->FmtType = DevFmtTypeDefault;
4121 device->IsHeadphones = AL_FALSE;
4122 device->AmbiFmt = AmbiFormat_Default;
4124 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4125 if(device->SourcesMax == 0) device->SourcesMax = 256;
4127 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4128 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
4130 ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends);
4131 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
4133 device->NumStereoSources = 1;
4134 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4136 // Open the "backend"
4137 V(device->Backend,open)("Loopback");
4140 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4141 do {
4142 device->next = head;
4143 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4146 TRACE("Created device %p\n", device);
4147 return device;
4150 /* alcIsRenderFormatSupportedSOFT
4152 * Determines if the loopback device supports the given format for rendering.
4154 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4156 ALCboolean ret = ALC_FALSE;
4158 if(!VerifyDevice(&device) || device->Type != Loopback)
4159 alcSetError(device, ALC_INVALID_DEVICE);
4160 else if(freq <= 0)
4161 alcSetError(device, ALC_INVALID_VALUE);
4162 else
4164 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
4165 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
4166 freq >= MIN_OUTPUT_RATE)
4167 ret = ALC_TRUE;
4169 if(device) ALCdevice_DecRef(device);
4171 return ret;
4174 /* alcRenderSamplesSOFT
4176 * Renders some samples into a buffer, using the format last set by the
4177 * attributes given to alcCreateContext.
4179 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4181 if(!VerifyDevice(&device) || device->Type != Loopback)
4182 alcSetError(device, ALC_INVALID_DEVICE);
4183 else if(samples < 0 || (samples > 0 && buffer == NULL))
4184 alcSetError(device, ALC_INVALID_VALUE);
4185 else
4187 V0(device->Backend,lock)();
4188 aluMixData(device, buffer, samples);
4189 V0(device->Backend,unlock)();
4191 if(device) ALCdevice_DecRef(device);
4195 /************************************************
4196 * ALC DSP pause/resume functions
4197 ************************************************/
4199 /* alcDevicePauseSOFT
4201 * Pause the DSP to stop audio processing.
4203 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4205 if(!VerifyDevice(&device) || device->Type != Playback)
4206 alcSetError(device, ALC_INVALID_DEVICE);
4207 else
4209 almtx_lock(&device->BackendLock);
4210 if((device->Flags&DEVICE_RUNNING))
4211 V0(device->Backend,stop)();
4212 device->Flags &= ~DEVICE_RUNNING;
4213 device->Flags |= DEVICE_PAUSED;
4214 almtx_unlock(&device->BackendLock);
4216 if(device) ALCdevice_DecRef(device);
4219 /* alcDeviceResumeSOFT
4221 * Resume the DSP to restart audio processing.
4223 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4225 if(!VerifyDevice(&device) || device->Type != Playback)
4226 alcSetError(device, ALC_INVALID_DEVICE);
4227 else
4229 almtx_lock(&device->BackendLock);
4230 if((device->Flags&DEVICE_PAUSED))
4232 device->Flags &= ~DEVICE_PAUSED;
4233 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4235 if(V0(device->Backend,start)() != ALC_FALSE)
4236 device->Flags |= DEVICE_RUNNING;
4237 else
4239 alcSetError(device, ALC_INVALID_DEVICE);
4240 V0(device->Backend,lock)();
4241 aluHandleDisconnect(device);
4242 V0(device->Backend,unlock)();
4246 almtx_unlock(&device->BackendLock);
4248 if(device) ALCdevice_DecRef(device);
4252 /************************************************
4253 * ALC HRTF functions
4254 ************************************************/
4256 /* alcGetStringiSOFT
4258 * Gets a string parameter at the given index.
4260 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4262 const ALCchar *str = NULL;
4264 if(!VerifyDevice(&device) || device->Type == Capture)
4265 alcSetError(device, ALC_INVALID_DEVICE);
4266 else switch(paramName)
4268 case ALC_HRTF_SPECIFIER_SOFT:
4269 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf.List))
4270 str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf.List, index).name);
4271 else
4272 alcSetError(device, ALC_INVALID_VALUE);
4273 break;
4275 default:
4276 alcSetError(device, ALC_INVALID_ENUM);
4277 break;
4279 if(device) ALCdevice_DecRef(device);
4281 return str;
4284 /* alcResetDeviceSOFT
4286 * Resets the given device output, using the specified attribute list.
4288 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4290 ALCenum err;
4292 LockLists();
4293 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4295 UnlockLists();
4296 alcSetError(device, ALC_INVALID_DEVICE);
4297 if(device) ALCdevice_DecRef(device);
4298 return ALC_FALSE;
4300 almtx_lock(&device->BackendLock);
4301 UnlockLists();
4303 err = UpdateDeviceParams(device, attribs);
4304 almtx_unlock(&device->BackendLock);
4306 if(err != ALC_NO_ERROR)
4308 alcSetError(device, err);
4309 if(err == ALC_INVALID_DEVICE)
4311 V0(device->Backend,lock)();
4312 aluHandleDisconnect(device);
4313 V0(device->Backend,unlock)();
4315 ALCdevice_DecRef(device);
4316 return ALC_FALSE;
4318 ALCdevice_DecRef(device);
4320 return ALC_TRUE;