Reduce the default period count to 3
[openal-soft.git] / Alc / ALc.c
blobc829d8e7ec9013ab6966062998cde8836b132d15
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 enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
1770 enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
1771 const ALsizei old_sends = device->NumAuxSends;
1772 ALsizei new_sends = device->NumAuxSends;
1773 enum DevFmtChannels oldChans;
1774 enum DevFmtType oldType;
1775 ALboolean update_failed;
1776 ALCsizei hrtf_id = -1;
1777 ALCcontext *context;
1778 ALCuint oldFreq;
1779 FPUCtl oldMode;
1780 size_t size;
1782 // Check for attributes
1783 if(device->Type == Loopback)
1785 enum {
1786 GotFreq = 1<<0,
1787 GotChans = 1<<1,
1788 GotType = 1<<2,
1789 GotAll = GotFreq|GotChans|GotType
1791 ALCuint freq, numMono, numStereo;
1792 enum DevFmtChannels schans;
1793 enum DevFmtType stype;
1794 ALCuint attrIdx = 0;
1795 ALCint gotFmt = 0;
1796 ALCsizei numSends;
1798 if(!attrList)
1800 WARN("Missing attributes for loopback device\n");
1801 return ALC_INVALID_VALUE;
1804 numMono = device->NumMonoSources;
1805 numStereo = device->NumStereoSources;
1806 schans = device->FmtChans;
1807 stype = device->FmtType;
1808 freq = device->Frequency;
1809 numSends = old_sends;
1811 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1812 while(attrList[attrIdx])
1814 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1816 ALCint val = attrList[attrIdx + 1];
1817 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val);
1818 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1819 return ALC_INVALID_VALUE;
1820 schans = val;
1821 gotFmt |= GotChans;
1824 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1826 ALCint val = attrList[attrIdx + 1];
1827 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val);
1828 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1829 return ALC_INVALID_VALUE;
1830 stype = val;
1831 gotFmt |= GotType;
1834 if(attrList[attrIdx] == ALC_FREQUENCY)
1836 freq = attrList[attrIdx + 1];
1837 TRACE_ATTR(ALC_FREQUENCY, freq);
1838 if(freq < MIN_OUTPUT_RATE)
1839 return ALC_INVALID_VALUE;
1840 gotFmt |= GotFreq;
1843 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1845 numStereo = attrList[attrIdx + 1];
1846 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1847 if(numStereo > device->SourcesMax)
1848 numStereo = device->SourcesMax;
1850 numMono = device->SourcesMax - numStereo;
1853 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1855 numSends = attrList[attrIdx + 1];
1856 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1859 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1861 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1862 if(attrList[attrIdx + 1] == ALC_FALSE)
1863 hrtf_appreq = Hrtf_Disable;
1864 else if(attrList[attrIdx + 1] == ALC_TRUE)
1865 hrtf_appreq = Hrtf_Enable;
1866 else
1867 hrtf_appreq = Hrtf_Default;
1870 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1872 hrtf_id = attrList[attrIdx + 1];
1873 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1876 attrIdx += 2;
1878 #undef TRACE_ATTR
1880 if(gotFmt != GotAll)
1882 WARN("Missing format for loopback device\n");
1883 return ALC_INVALID_VALUE;
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;
1898 if(ConfigValueInt(NULL, NULL, "sends", &new_sends))
1899 new_sends = clampi(numSends, 0, clampi(new_sends, 0, MAX_SENDS));
1900 else
1901 new_sends = clampi(numSends, 0, MAX_SENDS);
1903 else if(attrList && attrList[0])
1905 ALCuint freq, numMono, numStereo;
1906 ALCuint attrIdx = 0;
1907 ALCsizei numSends;
1909 /* If a context is already running on the device, stop playback so the
1910 * device attributes can be updated. */
1911 if((device->Flags&DEVICE_RUNNING))
1912 V0(device->Backend,stop)();
1913 device->Flags &= ~DEVICE_RUNNING;
1915 UpdateClockBase(device);
1917 freq = device->Frequency;
1918 numMono = device->NumMonoSources;
1919 numStereo = device->NumStereoSources;
1920 numSends = old_sends;
1922 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1923 while(attrList[attrIdx])
1925 if(attrList[attrIdx] == ALC_FREQUENCY)
1927 freq = attrList[attrIdx + 1];
1928 TRACE_ATTR(ALC_FREQUENCY, freq);
1929 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1932 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1934 numStereo = attrList[attrIdx + 1];
1935 TRACE_ATTR(ALC_STEREO_SOURCES, numStereo);
1936 if(numStereo > device->SourcesMax)
1937 numStereo = device->SourcesMax;
1939 numMono = device->SourcesMax - numStereo;
1942 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1944 numSends = attrList[attrIdx + 1];
1945 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends);
1948 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1950 TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]);
1951 if(attrList[attrIdx + 1] == ALC_FALSE)
1952 hrtf_appreq = Hrtf_Disable;
1953 else if(attrList[attrIdx + 1] == ALC_TRUE)
1954 hrtf_appreq = Hrtf_Enable;
1955 else
1956 hrtf_appreq = Hrtf_Default;
1959 if(attrList[attrIdx] == ALC_HRTF_ID_SOFT)
1961 hrtf_id = attrList[attrIdx + 1];
1962 TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id);
1965 attrIdx += 2;
1967 #undef TRACE_ATTR
1969 ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
1970 freq = maxu(freq, MIN_OUTPUT_RATE);
1972 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1973 device->Frequency;
1974 /* SSE and Neon do best with the update size being a multiple of 4 */
1975 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1976 device->UpdateSize = (device->UpdateSize+3)&~3;
1978 device->Frequency = freq;
1979 device->NumMonoSources = numMono;
1980 device->NumStereoSources = numStereo;
1982 if(ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &new_sends))
1983 new_sends = clampi(numSends, 0, clampi(new_sends, 0, MAX_SENDS));
1984 else
1985 new_sends = clampi(numSends, 0, MAX_SENDS);
1988 if((device->Flags&DEVICE_RUNNING))
1989 return ALC_NO_ERROR;
1991 al_free(device->Uhj_Encoder);
1992 device->Uhj_Encoder = NULL;
1994 al_free(device->Bs2b);
1995 device->Bs2b = NULL;
1997 al_free(device->Dry.Buffer);
1998 device->Dry.Buffer = NULL;
1999 device->Dry.NumChannels = 0;
2000 device->FOAOut.Buffer = NULL;
2001 device->FOAOut.NumChannels = 0;
2002 device->RealOut.Buffer = NULL;
2003 device->RealOut.NumChannels = 0;
2005 UpdateClockBase(device);
2007 /*************************************************************************
2008 * Update device format request if HRTF is requested
2010 device->Hrtf.Status = ALC_HRTF_DISABLED_SOFT;
2011 if(device->Type != Loopback)
2013 const char *hrtf;
2014 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf))
2016 if(strcasecmp(hrtf, "true") == 0)
2017 hrtf_userreq = Hrtf_Enable;
2018 else if(strcasecmp(hrtf, "false") == 0)
2019 hrtf_userreq = Hrtf_Disable;
2020 else if(strcasecmp(hrtf, "auto") != 0)
2021 ERR("Unexpected hrtf value: %s\n", hrtf);
2024 if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
2026 if(VECTOR_SIZE(device->Hrtf.List) == 0)
2028 VECTOR_DEINIT(device->Hrtf.List);
2029 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
2031 if(VECTOR_SIZE(device->Hrtf.List) > 0)
2033 device->FmtChans = DevFmtStereo;
2034 if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf.List))
2035 device->Frequency = VECTOR_ELEM(device->Hrtf.List, hrtf_id).hrtf->sampleRate;
2036 else
2037 device->Frequency = VECTOR_ELEM(device->Hrtf.List, 0).hrtf->sampleRate;
2038 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
2040 else
2042 hrtf_userreq = Hrtf_Default;
2043 hrtf_appreq = Hrtf_Disable;
2044 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2048 else if(hrtf_appreq == Hrtf_Enable)
2050 size_t i = VECTOR_SIZE(device->Hrtf.List);
2051 /* Loopback device. We don't need to match to a specific HRTF entry
2052 * here. If the requested ID matches, we'll pick that later, if not,
2053 * we'll try to auto-select one anyway. Just make sure one exists
2054 * that'll work.
2056 if(device->FmtChans == DevFmtStereo)
2058 if(VECTOR_SIZE(device->Hrtf.List) == 0)
2060 VECTOR_DEINIT(device->Hrtf.List);
2061 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
2063 for(i = 0;i < VECTOR_SIZE(device->Hrtf.List);i++)
2065 const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf.List, i).hrtf;
2066 if(hrtf->sampleRate == device->Frequency)
2067 break;
2070 if(i == VECTOR_SIZE(device->Hrtf.List))
2072 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2073 DevFmtChannelsString(device->FmtChans), device->Frequency);
2074 hrtf_appreq = Hrtf_Disable;
2075 device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2079 oldFreq = device->Frequency;
2080 oldChans = device->FmtChans;
2081 oldType = device->FmtType;
2083 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2084 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
2085 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
2086 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
2087 device->UpdateSize, device->NumUpdates
2090 if(V0(device->Backend,reset)() == ALC_FALSE)
2091 return ALC_INVALID_DEVICE;
2093 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
2095 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
2096 DevFmtChannelsString(device->FmtChans));
2097 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
2099 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2101 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
2102 DevFmtTypeString(device->FmtType));
2103 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
2105 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
2107 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
2108 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
2111 if((device->UpdateSize&3) != 0)
2113 if((CPUCapFlags&CPU_CAP_SSE))
2114 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2115 if((CPUCapFlags&CPU_CAP_NEON))
2116 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
2119 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2120 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
2121 device->Frequency, device->UpdateSize, device->NumUpdates
2124 aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
2125 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels,
2126 device->FOAOut.NumChannels, device->RealOut.NumChannels);
2128 /* Allocate extra channels for any post-filter output. */
2129 size = (device->Dry.NumChannels + device->FOAOut.NumChannels +
2130 device->RealOut.NumChannels)*sizeof(device->Dry.Buffer[0]);
2132 TRACE("Allocating "SZFMT" channels, "SZFMT" bytes\n", size/sizeof(device->Dry.Buffer[0]), size);
2133 device->Dry.Buffer = al_calloc(16, size);
2134 if(!device->Dry.Buffer)
2136 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2137 return ALC_INVALID_DEVICE;
2140 if(device->RealOut.NumChannels != 0)
2141 device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels +
2142 device->FOAOut.NumChannels;
2143 else
2145 device->RealOut.Buffer = device->Dry.Buffer;
2146 device->RealOut.NumChannels = device->Dry.NumChannels;
2149 if(device->FOAOut.NumChannels != 0)
2150 device->FOAOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels;
2151 else
2153 device->FOAOut.Buffer = device->Dry.Buffer;
2154 device->FOAOut.NumChannels = device->Dry.NumChannels;
2157 /* Need to delay returning failure until replacement Send arrays have been
2158 * allocated with the appropriate size.
2160 device->NumAuxSends = new_sends;
2161 update_failed = AL_FALSE;
2162 SetMixerFPUMode(&oldMode);
2163 if(device->DefaultSlot)
2165 ALeffectslot *slot = device->DefaultSlot;
2166 ALeffectState *state = slot->Effect.State;
2168 state->OutBuffer = device->Dry.Buffer;
2169 state->OutChannels = device->Dry.NumChannels;
2170 if(V(state,deviceUpdate)(device) == AL_FALSE)
2171 update_failed = AL_TRUE;
2172 else
2173 UpdateEffectSlotProps(slot);
2176 context = ATOMIC_LOAD_SEQ(&device->ContextList);
2177 while(context)
2179 ALsizei pos;
2181 WriteLock(&context->PropLock);
2182 LockUIntMapRead(&context->EffectSlotMap);
2183 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2185 ALeffectslot *slot = context->EffectSlotMap.values[pos];
2186 ALeffectState *state = slot->Effect.State;
2188 state->OutBuffer = device->Dry.Buffer;
2189 state->OutChannels = device->Dry.NumChannels;
2190 if(V(state,deviceUpdate)(device) == AL_FALSE)
2191 update_failed = AL_TRUE;
2192 else
2193 UpdateEffectSlotProps(slot);
2195 UnlockUIntMapRead(&context->EffectSlotMap);
2197 LockUIntMapRead(&context->SourceMap);
2198 for(pos = 0;pos < context->SourceMap.size;pos++)
2200 ALsource *source = context->SourceMap.values[pos];
2201 struct ALsourceProps *props;
2203 if(old_sends != device->NumAuxSends)
2205 ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
2206 ALsizei s;
2208 memcpy(sends, source->Send,
2209 mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
2211 for(s = device->NumAuxSends;s < old_sends;s++)
2213 if(source->Send[s].Slot)
2214 DecrementRef(&source->Send[s].Slot->ref);
2215 source->Send[s].Slot = NULL;
2217 al_free(source->Send);
2218 source->Send = sends;
2219 for(s = old_sends;s < device->NumAuxSends;s++)
2221 source->Send[s].Slot = NULL;
2222 source->Send[s].Gain = 1.0f;
2223 source->Send[s].GainHF = 1.0f;
2224 source->Send[s].HFReference = LOWPASSFREQREF;
2225 source->Send[s].GainLF = 1.0f;
2226 source->Send[s].LFReference = HIGHPASSFREQREF;
2230 source->NeedsUpdate = AL_TRUE;
2232 /* Clear any pre-existing source property structs, in case the
2233 * number of auxiliary sends changed. Playing (or paused) sources
2234 * will have updates respecified in UpdateAllSourceProps.
2236 props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
2237 al_free(props);
2239 props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
2240 almemory_order_relaxed);
2241 while(props)
2243 struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
2244 al_free(props);
2245 props = next;
2248 AllocateVoices(context, context->MaxVoices, old_sends);
2249 UnlockUIntMapRead(&context->SourceMap);
2251 UpdateListenerProps(context);
2252 UpdateAllSourceProps(context);
2253 WriteUnlock(&context->PropLock);
2255 context = context->next;
2257 RestoreFPUMode(&oldMode);
2258 if(update_failed)
2259 return ALC_INVALID_DEVICE;
2261 if(!(device->Flags&DEVICE_PAUSED))
2263 if(V0(device->Backend,start)() == ALC_FALSE)
2264 return ALC_INVALID_DEVICE;
2265 device->Flags |= DEVICE_RUNNING;
2268 return ALC_NO_ERROR;
2271 /* FreeDevice
2273 * Frees the device structure, and destroys any objects the app failed to
2274 * delete. Called once there's no more references on the device.
2276 static ALCvoid FreeDevice(ALCdevice *device)
2278 TRACE("%p\n", device);
2280 V0(device->Backend,close)();
2281 DELETE_OBJ(device->Backend);
2282 device->Backend = NULL;
2284 almtx_destroy(&device->BackendLock);
2286 if(device->DefaultSlot)
2288 DeinitEffectSlot(device->DefaultSlot);
2289 device->DefaultSlot = NULL;
2292 if(device->BufferMap.size > 0)
2294 WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size,
2295 (device->BufferMap.size==1)?"":"s");
2296 ReleaseALBuffers(device);
2298 ResetUIntMap(&device->BufferMap);
2300 if(device->EffectMap.size > 0)
2302 WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size,
2303 (device->EffectMap.size==1)?"":"s");
2304 ReleaseALEffects(device);
2306 ResetUIntMap(&device->EffectMap);
2308 if(device->FilterMap.size > 0)
2310 WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size,
2311 (device->FilterMap.size==1)?"":"s");
2312 ReleaseALFilters(device);
2314 ResetUIntMap(&device->FilterMap);
2316 AL_STRING_DEINIT(device->Hrtf.Name);
2317 FreeHrtfList(&device->Hrtf.List);
2319 al_free(device->Bs2b);
2320 device->Bs2b = NULL;
2322 al_free(device->Uhj_Encoder);
2323 device->Uhj_Encoder = NULL;
2325 bformatdec_free(device->AmbiDecoder);
2326 device->AmbiDecoder = NULL;
2328 ambiup_free(device->AmbiUp);
2329 device->AmbiUp = NULL;
2331 AL_STRING_DEINIT(device->DeviceName);
2333 al_free(device->Dry.Buffer);
2334 device->Dry.Buffer = NULL;
2335 device->Dry.NumChannels = 0;
2336 device->FOAOut.Buffer = NULL;
2337 device->FOAOut.NumChannels = 0;
2338 device->RealOut.Buffer = NULL;
2339 device->RealOut.NumChannels = 0;
2341 al_free(device);
2345 void ALCdevice_IncRef(ALCdevice *device)
2347 uint ref;
2348 ref = IncrementRef(&device->ref);
2349 TRACEREF("%p increasing refcount to %u\n", device, ref);
2352 void ALCdevice_DecRef(ALCdevice *device)
2354 uint ref;
2355 ref = DecrementRef(&device->ref);
2356 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2357 if(ref == 0) FreeDevice(device);
2360 /* VerifyDevice
2362 * Checks if the device handle is valid, and increments its ref count if so.
2364 static ALCboolean VerifyDevice(ALCdevice **device)
2366 ALCdevice *tmpDevice;
2368 LockLists();
2369 tmpDevice = ATOMIC_LOAD_SEQ(&DeviceList);
2370 while(tmpDevice)
2372 if(tmpDevice == *device)
2374 ALCdevice_IncRef(tmpDevice);
2375 UnlockLists();
2376 return ALC_TRUE;
2378 tmpDevice = tmpDevice->next;
2380 UnlockLists();
2382 *device = NULL;
2383 return ALC_FALSE;
2387 /* InitContext
2389 * Initializes context fields
2391 static ALvoid InitContext(ALCcontext *Context)
2393 ALlistener *listener = Context->Listener;
2395 //Initialise listener
2396 listener->Gain = 1.0f;
2397 listener->MetersPerUnit = 1.0f;
2398 listener->Position[0] = 0.0f;
2399 listener->Position[1] = 0.0f;
2400 listener->Position[2] = 0.0f;
2401 listener->Velocity[0] = 0.0f;
2402 listener->Velocity[1] = 0.0f;
2403 listener->Velocity[2] = 0.0f;
2404 listener->Forward[0] = 0.0f;
2405 listener->Forward[1] = 0.0f;
2406 listener->Forward[2] = -1.0f;
2407 listener->Up[0] = 0.0f;
2408 listener->Up[1] = 1.0f;
2409 listener->Up[2] = 0.0f;
2411 aluMatrixfSet(&listener->Params.Matrix,
2412 1.0f, 0.0f, 0.0f, 0.0f,
2413 0.0f, 1.0f, 0.0f, 0.0f,
2414 0.0f, 0.0f, 1.0f, 0.0f,
2415 0.0f, 0.0f, 0.0f, 1.0f
2417 aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2418 listener->Params.Gain = 1.0f;
2419 listener->Params.MetersPerUnit = 1.0f;
2420 listener->Params.DopplerFactor = 1.0f;
2421 listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2423 ATOMIC_INIT(&listener->Update, NULL);
2424 ATOMIC_INIT(&listener->FreeList, NULL);
2426 //Validate Context
2427 InitRef(&Context->UpdateCount, 0);
2428 ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE);
2429 Context->GainBoost = 1.0f;
2430 RWLockInit(&Context->PropLock);
2431 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2432 InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax);
2433 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2435 //Set globals
2436 Context->DistanceModel = DefaultDistanceModel;
2437 Context->SourceDistanceModel = AL_FALSE;
2438 Context->DopplerFactor = 1.0f;
2439 Context->DopplerVelocity = 1.0f;
2440 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2441 ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
2443 Context->ExtensionList = alExtList;
2447 /* FreeContext
2449 * Cleans up the context, and destroys any remaining objects the app failed to
2450 * delete. Called once there's no more references on the context.
2452 static void FreeContext(ALCcontext *context)
2454 ALlistener *listener = context->Listener;
2455 struct ALlistenerProps *lprops;
2456 size_t count;
2458 TRACE("%p\n", context);
2460 if(context->SourceMap.size > 0)
2462 WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size,
2463 (context->SourceMap.size==1)?"":"s");
2464 ReleaseALSources(context);
2466 ResetUIntMap(&context->SourceMap);
2468 if(context->EffectSlotMap.size > 0)
2470 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size,
2471 (context->EffectSlotMap.size==1)?"":"s");
2472 ReleaseALAuxiliaryEffectSlots(context);
2474 ResetUIntMap(&context->EffectSlotMap);
2476 al_free(context->Voices);
2477 context->Voices = NULL;
2478 context->VoiceCount = 0;
2479 context->MaxVoices = 0;
2481 if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
2483 TRACE("Freed unapplied listener update %p\n", lprops);
2484 al_free(lprops);
2486 count = 0;
2487 lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
2488 while(lprops)
2490 struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire);
2491 al_free(lprops);
2492 lprops = next;
2493 ++count;
2495 TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
2497 ALCdevice_DecRef(context->Device);
2498 context->Device = NULL;
2500 //Invalidate context
2501 memset(context, 0, sizeof(ALCcontext));
2502 al_free(context);
2505 /* ReleaseContext
2507 * Removes the context reference from the given device and removes it from
2508 * being current on the running thread or globally.
2510 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2512 ALCcontext *origctx;
2514 if(altss_get(LocalContext) == context)
2516 WARN("%p released while current on thread\n", context);
2517 altss_set(LocalContext, NULL);
2518 ALCcontext_DecRef(context);
2521 origctx = context;
2522 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL))
2523 ALCcontext_DecRef(context);
2525 ALCdevice_Lock(device);
2526 origctx = context;
2527 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList,
2528 &origctx, context->next))
2530 ALCcontext *volatile*list = &origctx->next;
2531 while(*list)
2533 if(*list == context)
2535 *list = (*list)->next;
2536 break;
2538 list = &(*list)->next;
2541 ALCdevice_Unlock(device);
2543 ALCcontext_DecRef(context);
2546 void ALCcontext_IncRef(ALCcontext *context)
2548 uint ref = IncrementRef(&context->ref);
2549 TRACEREF("%p increasing refcount to %u\n", context, ref);
2552 void ALCcontext_DecRef(ALCcontext *context)
2554 uint ref = DecrementRef(&context->ref);
2555 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2556 if(ref == 0) FreeContext(context);
2559 static void ReleaseThreadCtx(void *ptr)
2561 ALCcontext *context = ptr;
2562 uint ref = DecrementRef(&context->ref);
2563 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2564 ERR("Context %p current for thread being destroyed, possible leak!\n", context);
2567 /* VerifyContext
2569 * Checks that the given context is valid, and increments its reference count.
2571 static ALCboolean VerifyContext(ALCcontext **context)
2573 ALCdevice *dev;
2575 LockLists();
2576 dev = ATOMIC_LOAD_SEQ(&DeviceList);
2577 while(dev)
2579 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList, almemory_order_acquire);
2580 while(ctx)
2582 if(ctx == *context)
2584 ALCcontext_IncRef(ctx);
2585 UnlockLists();
2586 return ALC_TRUE;
2588 ctx = ctx->next;
2590 dev = dev->next;
2592 UnlockLists();
2594 *context = NULL;
2595 return ALC_FALSE;
2599 /* GetContextRef
2601 * Returns the currently active context for this thread, and adds a reference
2602 * without locking it.
2604 ALCcontext *GetContextRef(void)
2606 ALCcontext *context;
2608 context = altss_get(LocalContext);
2609 if(context)
2610 ALCcontext_IncRef(context);
2611 else
2613 LockLists();
2614 context = ATOMIC_LOAD_SEQ(&GlobalContext);
2615 if(context)
2616 ALCcontext_IncRef(context);
2617 UnlockLists();
2620 return context;
2624 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
2626 ALCdevice *device = context->Device;
2627 ALsizei num_sends = device->NumAuxSends;
2628 struct ALsourceProps *props;
2629 size_t sizeof_props;
2630 size_t sizeof_voice;
2631 ALvoice **voices;
2632 ALvoice *voice;
2633 ALsizei v = 0;
2634 size_t size;
2636 if(num_voices == context->MaxVoices && num_sends == old_sends)
2637 return;
2639 /* Allocate the voice pointers, voices, and the voices' stored source
2640 * property set (including the dynamically-sized Send[] array) in one
2641 * chunk.
2643 sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
2644 sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
2645 size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
2647 voices = al_calloc(16, RoundUp(size*num_voices, 16));
2648 /* The voice and property objects are stored interleaved since they're
2649 * paired together.
2651 voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
2652 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2654 if(context->Voices)
2656 ALsizei v_count = mini(context->VoiceCount, num_voices);
2657 for(;v < v_count;v++)
2659 ALsizei s_count = mini(old_sends, num_sends);
2660 ALsizei i;
2662 /* Copy the old voice data and source property set to the new
2663 * storage.
2665 *voice = *(context->Voices[v]);
2666 for(i = 0;i < s_count;i++)
2667 voice->Send[i] = context->Voices[v]->Send[i];
2668 *props = *(context->Voices[v]->Props);
2669 for(i = 0;i < s_count;i++)
2670 props->Send[i] = context->Voices[v]->Props->Send[i];
2672 /* Set this voice's property set pointer and voice reference. */
2673 voice->Props = props;
2674 voices[v] = voice;
2676 /* Increment pointers to the next storage space. */
2677 voice = (ALvoice*)((char*)props + sizeof_props);
2678 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2681 /* Finish setting the voices' property set pointers and references. */
2682 for(;v < num_voices;v++)
2684 voice->Props = props;
2685 voices[v] = voice;
2687 voice = (ALvoice*)((char*)props + sizeof_props);
2688 props = (struct ALsourceProps*)((char*)voice + sizeof_voice);
2691 al_free(context->Voices);
2692 context->Voices = voices;
2693 context->MaxVoices = num_voices;
2694 context->VoiceCount = mini(context->VoiceCount, num_voices);
2698 /************************************************
2699 * Standard ALC functions
2700 ************************************************/
2702 /* alcGetError
2704 * Return last ALC generated error code for the given device
2706 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2708 ALCenum errorCode;
2710 if(VerifyDevice(&device))
2712 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR);
2713 ALCdevice_DecRef(device);
2715 else
2716 errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2718 return errorCode;
2722 /* alcSuspendContext
2724 * Suspends updates for the given context
2726 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2728 if(!SuspendDefers)
2729 return;
2731 if(!VerifyContext(&context))
2732 alcSetError(NULL, ALC_INVALID_CONTEXT);
2733 else
2735 ALCcontext_DeferUpdates(context, DeferAllowPlay);
2736 ALCcontext_DecRef(context);
2740 /* alcProcessContext
2742 * Resumes processing updates for the given context
2744 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2746 if(!SuspendDefers)
2747 return;
2749 if(!VerifyContext(&context))
2750 alcSetError(NULL, ALC_INVALID_CONTEXT);
2751 else
2753 ALCcontext_ProcessUpdates(context);
2754 ALCcontext_DecRef(context);
2759 /* alcGetString
2761 * Returns information about the device, and error strings
2763 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2765 const ALCchar *value = NULL;
2767 switch(param)
2769 case ALC_NO_ERROR:
2770 value = alcNoError;
2771 break;
2773 case ALC_INVALID_ENUM:
2774 value = alcErrInvalidEnum;
2775 break;
2777 case ALC_INVALID_VALUE:
2778 value = alcErrInvalidValue;
2779 break;
2781 case ALC_INVALID_DEVICE:
2782 value = alcErrInvalidDevice;
2783 break;
2785 case ALC_INVALID_CONTEXT:
2786 value = alcErrInvalidContext;
2787 break;
2789 case ALC_OUT_OF_MEMORY:
2790 value = alcErrOutOfMemory;
2791 break;
2793 case ALC_DEVICE_SPECIFIER:
2794 value = alcDefaultName;
2795 break;
2797 case ALC_ALL_DEVICES_SPECIFIER:
2798 if(VerifyDevice(&Device))
2800 value = al_string_get_cstr(Device->DeviceName);
2801 ALCdevice_DecRef(Device);
2803 else
2805 ProbeAllDevicesList();
2806 value = al_string_get_cstr(alcAllDevicesList);
2808 break;
2810 case ALC_CAPTURE_DEVICE_SPECIFIER:
2811 if(VerifyDevice(&Device))
2813 value = al_string_get_cstr(Device->DeviceName);
2814 ALCdevice_DecRef(Device);
2816 else
2818 ProbeCaptureDeviceList();
2819 value = al_string_get_cstr(alcCaptureDeviceList);
2821 break;
2823 /* Default devices are always first in the list */
2824 case ALC_DEFAULT_DEVICE_SPECIFIER:
2825 value = alcDefaultName;
2826 break;
2828 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2829 if(al_string_empty(alcAllDevicesList))
2830 ProbeAllDevicesList();
2832 VerifyDevice(&Device);
2834 free(alcDefaultAllDevicesSpecifier);
2835 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2836 if(!alcDefaultAllDevicesSpecifier)
2837 alcSetError(Device, ALC_OUT_OF_MEMORY);
2839 value = alcDefaultAllDevicesSpecifier;
2840 if(Device) ALCdevice_DecRef(Device);
2841 break;
2843 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2844 if(al_string_empty(alcCaptureDeviceList))
2845 ProbeCaptureDeviceList();
2847 VerifyDevice(&Device);
2849 free(alcCaptureDefaultDeviceSpecifier);
2850 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2851 if(!alcCaptureDefaultDeviceSpecifier)
2852 alcSetError(Device, ALC_OUT_OF_MEMORY);
2854 value = alcCaptureDefaultDeviceSpecifier;
2855 if(Device) ALCdevice_DecRef(Device);
2856 break;
2858 case ALC_EXTENSIONS:
2859 if(!VerifyDevice(&Device))
2860 value = alcNoDeviceExtList;
2861 else
2863 value = alcExtensionList;
2864 ALCdevice_DecRef(Device);
2866 break;
2868 case ALC_HRTF_SPECIFIER_SOFT:
2869 if(!VerifyDevice(&Device))
2870 alcSetError(NULL, ALC_INVALID_DEVICE);
2871 else
2873 almtx_lock(&Device->BackendLock);
2874 value = (Device->Hrtf.Handle ? al_string_get_cstr(Device->Hrtf.Name) : "");
2875 almtx_unlock(&Device->BackendLock);
2876 ALCdevice_DecRef(Device);
2878 break;
2880 default:
2881 VerifyDevice(&Device);
2882 alcSetError(Device, ALC_INVALID_ENUM);
2883 if(Device) ALCdevice_DecRef(Device);
2884 break;
2887 return value;
2891 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2893 ALCsizei i;
2895 if(size <= 0 || values == NULL)
2897 alcSetError(device, ALC_INVALID_VALUE);
2898 return 0;
2901 if(!device)
2903 switch(param)
2905 case ALC_MAJOR_VERSION:
2906 values[0] = alcMajorVersion;
2907 return 1;
2908 case ALC_MINOR_VERSION:
2909 values[0] = alcMinorVersion;
2910 return 1;
2912 case ALC_ATTRIBUTES_SIZE:
2913 case ALC_ALL_ATTRIBUTES:
2914 case ALC_FREQUENCY:
2915 case ALC_REFRESH:
2916 case ALC_SYNC:
2917 case ALC_MONO_SOURCES:
2918 case ALC_STEREO_SOURCES:
2919 case ALC_CAPTURE_SAMPLES:
2920 case ALC_FORMAT_CHANNELS_SOFT:
2921 case ALC_FORMAT_TYPE_SOFT:
2922 alcSetError(NULL, ALC_INVALID_DEVICE);
2923 return 0;
2925 default:
2926 alcSetError(NULL, ALC_INVALID_ENUM);
2927 return 0;
2929 return 0;
2932 if(device->Type == Capture)
2934 switch(param)
2936 case ALC_CAPTURE_SAMPLES:
2937 almtx_lock(&device->BackendLock);
2938 values[0] = V0(device->Backend,availableSamples)();
2939 almtx_unlock(&device->BackendLock);
2940 return 1;
2942 case ALC_CONNECTED:
2943 values[0] = device->Connected;
2944 return 1;
2946 default:
2947 alcSetError(device, ALC_INVALID_ENUM);
2948 return 0;
2950 return 0;
2953 /* render device */
2954 switch(param)
2956 case ALC_MAJOR_VERSION:
2957 values[0] = alcMajorVersion;
2958 return 1;
2960 case ALC_MINOR_VERSION:
2961 values[0] = alcMinorVersion;
2962 return 1;
2964 case ALC_EFX_MAJOR_VERSION:
2965 values[0] = alcEFXMajorVersion;
2966 return 1;
2968 case ALC_EFX_MINOR_VERSION:
2969 values[0] = alcEFXMinorVersion;
2970 return 1;
2972 case ALC_ATTRIBUTES_SIZE:
2973 values[0] = 17;
2974 return 1;
2976 case ALC_ALL_ATTRIBUTES:
2977 if(size < 17)
2979 alcSetError(device, ALC_INVALID_VALUE);
2980 return 0;
2983 i = 0;
2984 almtx_lock(&device->BackendLock);
2985 values[i++] = ALC_FREQUENCY;
2986 values[i++] = device->Frequency;
2988 if(device->Type != Loopback)
2990 values[i++] = ALC_REFRESH;
2991 values[i++] = device->Frequency / device->UpdateSize;
2993 values[i++] = ALC_SYNC;
2994 values[i++] = ALC_FALSE;
2996 else
2998 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2999 values[i++] = device->FmtChans;
3001 values[i++] = ALC_FORMAT_TYPE_SOFT;
3002 values[i++] = device->FmtType;
3005 values[i++] = ALC_MONO_SOURCES;
3006 values[i++] = device->NumMonoSources;
3008 values[i++] = ALC_STEREO_SOURCES;
3009 values[i++] = device->NumStereoSources;
3011 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3012 values[i++] = device->NumAuxSends;
3014 values[i++] = ALC_HRTF_SOFT;
3015 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3017 values[i++] = ALC_HRTF_STATUS_SOFT;
3018 values[i++] = device->Hrtf.Status;
3019 almtx_unlock(&device->BackendLock);
3021 values[i++] = 0;
3022 return i;
3024 case ALC_FREQUENCY:
3025 values[0] = device->Frequency;
3026 return 1;
3028 case ALC_REFRESH:
3029 if(device->Type == Loopback)
3031 alcSetError(device, ALC_INVALID_DEVICE);
3032 return 0;
3034 almtx_lock(&device->BackendLock);
3035 values[0] = device->Frequency / device->UpdateSize;
3036 almtx_unlock(&device->BackendLock);
3037 return 1;
3039 case ALC_SYNC:
3040 if(device->Type == Loopback)
3042 alcSetError(device, ALC_INVALID_DEVICE);
3043 return 0;
3045 values[0] = ALC_FALSE;
3046 return 1;
3048 case ALC_FORMAT_CHANNELS_SOFT:
3049 if(device->Type != Loopback)
3051 alcSetError(device, ALC_INVALID_DEVICE);
3052 return 0;
3054 values[0] = device->FmtChans;
3055 return 1;
3057 case ALC_FORMAT_TYPE_SOFT:
3058 if(device->Type != Loopback)
3060 alcSetError(device, ALC_INVALID_DEVICE);
3061 return 0;
3063 values[0] = device->FmtType;
3064 return 1;
3066 case ALC_MONO_SOURCES:
3067 values[0] = device->NumMonoSources;
3068 return 1;
3070 case ALC_STEREO_SOURCES:
3071 values[0] = device->NumStereoSources;
3072 return 1;
3074 case ALC_MAX_AUXILIARY_SENDS:
3075 values[0] = device->NumAuxSends;
3076 return 1;
3078 case ALC_CONNECTED:
3079 values[0] = device->Connected;
3080 return 1;
3082 case ALC_HRTF_SOFT:
3083 values[0] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3084 return 1;
3086 case ALC_HRTF_STATUS_SOFT:
3087 values[0] = device->Hrtf.Status;
3088 return 1;
3090 case ALC_NUM_HRTF_SPECIFIERS_SOFT:
3091 almtx_lock(&device->BackendLock);
3092 FreeHrtfList(&device->Hrtf.List);
3093 device->Hrtf.List = EnumerateHrtf(device->DeviceName);
3094 values[0] = (ALCint)VECTOR_SIZE(device->Hrtf.List);
3095 almtx_unlock(&device->BackendLock);
3096 return 1;
3098 default:
3099 alcSetError(device, ALC_INVALID_ENUM);
3100 return 0;
3102 return 0;
3105 /* alcGetIntegerv
3107 * Returns information about the device and the version of OpenAL
3109 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
3111 VerifyDevice(&device);
3112 if(size <= 0 || values == NULL)
3113 alcSetError(device, ALC_INVALID_VALUE);
3114 else
3115 GetIntegerv(device, param, size, values);
3116 if(device) ALCdevice_DecRef(device);
3119 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
3121 ALCint *ivals;
3122 ALsizei i;
3124 VerifyDevice(&device);
3125 if(size <= 0 || values == NULL)
3126 alcSetError(device, ALC_INVALID_VALUE);
3127 else if(!device || device->Type == Capture)
3129 ivals = malloc(size * sizeof(ALCint));
3130 size = GetIntegerv(device, pname, size, ivals);
3131 for(i = 0;i < size;i++)
3132 values[i] = ivals[i];
3133 free(ivals);
3135 else /* render device */
3137 ClockLatency clock;
3138 ALuint64 basecount;
3139 ALuint samplecount;
3140 ALuint refcount;
3142 switch(pname)
3144 case ALC_ATTRIBUTES_SIZE:
3145 *values = 21;
3146 break;
3148 case ALC_ALL_ATTRIBUTES:
3149 if(size < 21)
3150 alcSetError(device, ALC_INVALID_VALUE);
3151 else
3153 i = 0;
3154 almtx_lock(&device->BackendLock);
3155 values[i++] = ALC_FREQUENCY;
3156 values[i++] = device->Frequency;
3158 if(device->Type != Loopback)
3160 values[i++] = ALC_REFRESH;
3161 values[i++] = device->Frequency / device->UpdateSize;
3163 values[i++] = ALC_SYNC;
3164 values[i++] = ALC_FALSE;
3166 else
3168 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
3169 values[i++] = device->FmtChans;
3171 values[i++] = ALC_FORMAT_TYPE_SOFT;
3172 values[i++] = device->FmtType;
3175 values[i++] = ALC_MONO_SOURCES;
3176 values[i++] = device->NumMonoSources;
3178 values[i++] = ALC_STEREO_SOURCES;
3179 values[i++] = device->NumStereoSources;
3181 values[i++] = ALC_MAX_AUXILIARY_SENDS;
3182 values[i++] = device->NumAuxSends;
3184 values[i++] = ALC_HRTF_SOFT;
3185 values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE);
3187 values[i++] = ALC_HRTF_STATUS_SOFT;
3188 values[i++] = device->Hrtf.Status;
3190 clock = V0(device->Backend,getClockLatency)();
3191 values[i++] = ALC_DEVICE_CLOCK_SOFT;
3192 values[i++] = clock.ClockTime;
3194 values[i++] = ALC_DEVICE_LATENCY_SOFT;
3195 values[i++] = clock.Latency;
3196 almtx_unlock(&device->BackendLock);
3198 values[i++] = 0;
3200 break;
3202 case ALC_DEVICE_CLOCK_SOFT:
3203 almtx_lock(&device->BackendLock);
3204 do {
3205 while(((refcount=ReadRef(&device->MixCount))&1) != 0)
3206 althrd_yield();
3207 basecount = device->ClockBase;
3208 samplecount = device->SamplesDone;
3209 } while(refcount != ReadRef(&device->MixCount));
3210 *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency);
3211 almtx_unlock(&device->BackendLock);
3212 break;
3214 case ALC_DEVICE_LATENCY_SOFT:
3216 almtx_lock(&device->BackendLock);
3217 clock = V0(device->Backend,getClockLatency)();
3218 almtx_unlock(&device->BackendLock);
3219 *values = clock.Latency;
3221 break;
3223 case ALC_DEVICE_CLOCK_LATENCY_SOFT:
3224 if(size < 2)
3225 alcSetError(device, ALC_INVALID_VALUE);
3226 else
3228 ClockLatency clock;
3229 almtx_lock(&device->BackendLock);
3230 clock = V0(device->Backend,getClockLatency)();
3231 almtx_unlock(&device->BackendLock);
3232 values[0] = clock.ClockTime;
3233 values[1] = clock.Latency;
3235 break;
3237 default:
3238 ivals = malloc(size * sizeof(ALCint));
3239 size = GetIntegerv(device, pname, size, ivals);
3240 for(i = 0;i < size;i++)
3241 values[i] = ivals[i];
3242 free(ivals);
3243 break;
3246 if(device)
3247 ALCdevice_DecRef(device);
3251 /* alcIsExtensionPresent
3253 * Determines if there is support for a particular extension
3255 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3257 ALCboolean bResult = ALC_FALSE;
3259 VerifyDevice(&device);
3261 if(!extName)
3262 alcSetError(device, ALC_INVALID_VALUE);
3263 else
3265 size_t len = strlen(extName);
3266 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3267 while(ptr && *ptr)
3269 if(strncasecmp(ptr, extName, len) == 0 &&
3270 (ptr[len] == '\0' || isspace(ptr[len])))
3272 bResult = ALC_TRUE;
3273 break;
3275 if((ptr=strchr(ptr, ' ')) != NULL)
3277 do {
3278 ++ptr;
3279 } while(isspace(*ptr));
3283 if(device)
3284 ALCdevice_DecRef(device);
3285 return bResult;
3289 /* alcGetProcAddress
3291 * Retrieves the function address for a particular extension function
3293 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3295 ALCvoid *ptr = NULL;
3297 if(!funcName)
3299 VerifyDevice(&device);
3300 alcSetError(device, ALC_INVALID_VALUE);
3301 if(device) ALCdevice_DecRef(device);
3303 else
3305 ALsizei i = 0;
3306 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3307 i++;
3308 ptr = alcFunctions[i].address;
3311 return ptr;
3315 /* alcGetEnumValue
3317 * Get the value for a particular ALC enumeration name
3319 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3321 ALCenum val = 0;
3323 if(!enumName)
3325 VerifyDevice(&device);
3326 alcSetError(device, ALC_INVALID_VALUE);
3327 if(device) ALCdevice_DecRef(device);
3329 else
3331 ALsizei i = 0;
3332 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3333 i++;
3334 val = enumeration[i].value;
3337 return val;
3341 /* alcCreateContext
3343 * Create and attach a context to the given device.
3345 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3347 ALCcontext *ALContext;
3348 ALfloat valf;
3349 ALCenum err;
3351 LockLists();
3352 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
3354 UnlockLists();
3355 alcSetError(device, ALC_INVALID_DEVICE);
3356 if(device) ALCdevice_DecRef(device);
3357 return NULL;
3359 almtx_lock(&device->BackendLock);
3360 UnlockLists();
3362 ATOMIC_STORE_SEQ(&device->LastError, ALC_NO_ERROR);
3364 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3365 if(ALContext)
3367 InitRef(&ALContext->ref, 1);
3368 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3370 ALContext->Device = device;
3371 ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
3373 ALContext->Voices = NULL;
3374 ALContext->MaxVoices = 0;
3375 ALContext->VoiceCount = 0;
3376 AllocateVoices(ALContext, 256, device->NumAuxSends);
3378 if(!ALContext || !ALContext->Voices)
3380 almtx_unlock(&device->BackendLock);
3382 if(ALContext)
3384 al_free(ALContext->Voices);
3385 ALContext->Voices = NULL;
3387 al_free(ALContext);
3388 ALContext = NULL;
3391 alcSetError(device, ALC_OUT_OF_MEMORY);
3392 ALCdevice_DecRef(device);
3393 return NULL;
3396 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3398 almtx_unlock(&device->BackendLock);
3400 al_free(ALContext->Voices);
3401 ALContext->Voices = NULL;
3403 al_free(ALContext);
3404 ALContext = NULL;
3406 alcSetError(device, err);
3407 if(err == ALC_INVALID_DEVICE)
3409 V0(device->Backend,lock)();
3410 aluHandleDisconnect(device);
3411 V0(device->Backend,unlock)();
3413 ALCdevice_DecRef(device);
3414 return NULL;
3417 ALCdevice_IncRef(ALContext->Device);
3418 InitContext(ALContext);
3420 if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))
3422 if(!isfinite(valf))
3423 ERR("volume-adjust must be finite: %f\n", valf);
3424 else
3426 ALfloat db = clampf(valf, -24.0f, 24.0f);
3427 if(db != valf)
3428 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f);
3429 ALContext->GainBoost = powf(10.0f, db/20.0f);
3430 TRACE("volume-adjust gain: %f\n", ALContext->GainBoost);
3433 UpdateListenerProps(ALContext);
3436 ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList);
3437 do {
3438 ALContext->next = head;
3439 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*,
3440 &device->ContextList, &head, ALContext) == 0);
3442 almtx_unlock(&device->BackendLock);
3444 ALCdevice_DecRef(device);
3446 TRACE("Created context %p\n", ALContext);
3447 return ALContext;
3450 /* alcDestroyContext
3452 * Remove a context from its device
3454 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3456 ALCdevice *Device;
3458 LockLists();
3459 /* alcGetContextsDevice sets an error for invalid contexts */
3460 Device = alcGetContextsDevice(context);
3461 if(Device)
3463 almtx_lock(&Device->BackendLock);
3464 ReleaseContext(context, Device);
3465 if(!ATOMIC_LOAD_SEQ(&Device->ContextList))
3467 V0(Device->Backend,stop)();
3468 Device->Flags &= ~DEVICE_RUNNING;
3470 almtx_unlock(&Device->BackendLock);
3472 UnlockLists();
3476 /* alcGetCurrentContext
3478 * Returns the currently active context on the calling thread
3480 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3482 ALCcontext *Context = altss_get(LocalContext);
3483 if(!Context) Context = ATOMIC_LOAD_SEQ(&GlobalContext);
3484 return Context;
3487 /* alcGetThreadContext
3489 * Returns the currently active thread-local context
3491 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3493 return altss_get(LocalContext);
3497 /* alcMakeContextCurrent
3499 * Makes the given context the active process-wide context, and removes the
3500 * thread-local context for the calling thread.
3502 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3504 /* context must be valid or NULL */
3505 if(context && !VerifyContext(&context))
3507 alcSetError(NULL, ALC_INVALID_CONTEXT);
3508 return ALC_FALSE;
3510 /* context's reference count is already incremented */
3511 context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context);
3512 if(context) ALCcontext_DecRef(context);
3514 if((context=altss_get(LocalContext)) != NULL)
3516 altss_set(LocalContext, NULL);
3517 ALCcontext_DecRef(context);
3520 return ALC_TRUE;
3523 /* alcSetThreadContext
3525 * Makes the given context the active context for the current thread
3527 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3529 ALCcontext *old;
3531 /* context must be valid or NULL */
3532 if(context && !VerifyContext(&context))
3534 alcSetError(NULL, ALC_INVALID_CONTEXT);
3535 return ALC_FALSE;
3537 /* context's reference count is already incremented */
3538 old = altss_get(LocalContext);
3539 altss_set(LocalContext, context);
3540 if(old) ALCcontext_DecRef(old);
3542 return ALC_TRUE;
3546 /* alcGetContextsDevice
3548 * Returns the device that a particular context is attached to
3550 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3552 ALCdevice *Device;
3554 if(!VerifyContext(&Context))
3556 alcSetError(NULL, ALC_INVALID_CONTEXT);
3557 return NULL;
3559 Device = Context->Device;
3560 ALCcontext_DecRef(Context);
3562 return Device;
3566 /* alcOpenDevice
3568 * Opens the named device.
3570 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3572 const ALCchar *fmt;
3573 ALCdevice *device;
3574 ALCenum err;
3576 DO_INITCONFIG();
3578 if(!PlaybackBackend.name)
3580 alcSetError(NULL, ALC_INVALID_VALUE);
3581 return NULL;
3584 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0
3585 #ifdef _WIN32
3586 /* Some old Windows apps hardcode these expecting OpenAL to use a
3587 * specific audio API, even when they're not enumerated. Creative's
3588 * router effectively ignores them too.
3590 || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0
3591 || strcasecmp(deviceName, "MMSYSTEM") == 0
3592 #endif
3594 deviceName = NULL;
3596 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3597 if(!device)
3599 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3600 return NULL;
3603 //Validate device
3604 InitRef(&device->ref, 1);
3605 device->Connected = ALC_TRUE;
3606 device->Type = Playback;
3607 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3609 device->Flags = 0;
3610 device->Bs2b = NULL;
3611 device->Uhj_Encoder = NULL;
3612 VECTOR_INIT(device->Hrtf.List);
3613 AL_STRING_INIT(device->Hrtf.Name);
3614 device->Render_Mode = NormalRender;
3615 AL_STRING_INIT(device->DeviceName);
3616 device->Dry.Buffer = NULL;
3617 device->Dry.NumChannels = 0;
3618 device->FOAOut.Buffer = NULL;
3619 device->FOAOut.NumChannels = 0;
3620 device->RealOut.Buffer = NULL;
3621 device->RealOut.NumChannels = 0;
3623 ATOMIC_INIT(&device->ContextList, NULL);
3625 device->ClockBase = 0;
3626 device->SamplesDone = 0;
3628 device->SourcesMax = 256;
3629 device->AuxiliaryEffectSlotMax = 64;
3630 device->NumAuxSends = DEFAULT_SENDS;
3632 InitUIntMap(&device->BufferMap, ~0);
3633 InitUIntMap(&device->EffectMap, ~0);
3634 InitUIntMap(&device->FilterMap, ~0);
3636 //Set output format
3637 device->FmtChans = DevFmtChannelsDefault;
3638 device->FmtType = DevFmtTypeDefault;
3639 device->Frequency = DEFAULT_OUTPUT_RATE;
3640 device->IsHeadphones = AL_FALSE;
3641 device->AmbiFmt = AmbiFormat_Default;
3642 device->NumUpdates = 3;
3643 device->UpdateSize = 1024;
3645 if(!PlaybackBackend.getFactory)
3646 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3647 ALCbackend_Playback);
3648 else
3650 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3651 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3653 if(!device->Backend)
3655 al_free(device);
3656 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3657 return NULL;
3661 if(ConfigValueStr(deviceName, NULL, "channels", &fmt))
3663 static const struct {
3664 const char name[16];
3665 enum DevFmtChannels chans;
3666 } chanlist[] = {
3667 { "mono", DevFmtMono },
3668 { "stereo", DevFmtStereo },
3669 { "quad", DevFmtQuad },
3670 { "surround51", DevFmtX51 },
3671 { "surround61", DevFmtX61 },
3672 { "surround71", DevFmtX71 },
3673 { "surround51rear", DevFmtX51Rear },
3674 { "ambi1", DevFmtAmbi1 },
3675 { "ambi2", DevFmtAmbi2 },
3676 { "ambi3", DevFmtAmbi3 },
3678 size_t i;
3680 for(i = 0;i < COUNTOF(chanlist);i++)
3682 if(strcasecmp(chanlist[i].name, fmt) == 0)
3684 device->FmtChans = chanlist[i].chans;
3685 device->Flags |= DEVICE_CHANNELS_REQUEST;
3686 break;
3689 if(i == COUNTOF(chanlist))
3690 ERR("Unsupported channels: %s\n", fmt);
3692 if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt))
3694 static const struct {
3695 const char name[16];
3696 enum DevFmtType type;
3697 } typelist[] = {
3698 { "int8", DevFmtByte },
3699 { "uint8", DevFmtUByte },
3700 { "int16", DevFmtShort },
3701 { "uint16", DevFmtUShort },
3702 { "int32", DevFmtInt },
3703 { "uint32", DevFmtUInt },
3704 { "float32", DevFmtFloat },
3706 size_t i;
3708 for(i = 0;i < COUNTOF(typelist);i++)
3710 if(strcasecmp(typelist[i].name, fmt) == 0)
3712 device->FmtType = typelist[i].type;
3713 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3714 break;
3717 if(i == COUNTOF(typelist))
3718 ERR("Unsupported sample-type: %s\n", fmt);
3721 if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency))
3723 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3724 if(device->Frequency < MIN_OUTPUT_RATE)
3725 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3726 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3729 ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates);
3730 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3732 ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize);
3733 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3734 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3735 device->UpdateSize = (device->UpdateSize+3)&~3;
3737 ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax);
3738 if(device->SourcesMax == 0) device->SourcesMax = 256;
3740 ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
3741 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
3743 if(ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends))
3744 device->NumAuxSends = clampi(
3745 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
3748 device->NumStereoSources = 1;
3749 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
3751 // Find a playback device to open
3752 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3754 DELETE_OBJ(device->Backend);
3755 al_free(device);
3756 alcSetError(NULL, err);
3757 return NULL;
3759 almtx_init(&device->BackendLock, almtx_plain);
3761 if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt))
3763 if(strcasecmp(fmt, "fuma") == 0)
3764 device->AmbiFmt = AmbiFormat_FuMa;
3765 else if(strcasecmp(fmt, "acn+sn3d") == 0)
3766 device->AmbiFmt = AmbiFormat_ACN_SN3D;
3767 else if(strcasecmp(fmt, "acn+n3d") == 0)
3768 device->AmbiFmt = AmbiFormat_ACN_N3D;
3769 else
3770 ERR("Unsupported ambi-format: %s\n", fmt);
3773 if(DefaultEffect.type != AL_EFFECT_NULL)
3775 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3776 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3778 device->DefaultSlot = NULL;
3779 ERR("Failed to initialize the default effect slot\n");
3781 else
3783 aluInitEffectPanning(device->DefaultSlot);
3784 if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3786 DeinitEffectSlot(device->DefaultSlot);
3787 device->DefaultSlot = NULL;
3788 ERR("Failed to initialize the default effect\n");
3794 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3795 do {
3796 device->next = head;
3797 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3800 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3801 return device;
3804 /* alcCloseDevice
3806 * Closes the given device.
3808 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3810 ALCdevice *iter, *origdev;
3811 ALCcontext *ctx;
3813 LockLists();
3814 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3815 do {
3816 if(iter == device)
3817 break;
3818 } while((iter=iter->next) != NULL);
3819 if(!iter || iter->Type == Capture)
3821 alcSetError(iter, ALC_INVALID_DEVICE);
3822 UnlockLists();
3823 return ALC_FALSE;
3825 almtx_lock(&device->BackendLock);
3827 origdev = device;
3828 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3830 ALCdevice *volatile*list = &origdev->next;
3831 while(*list)
3833 if(*list == device)
3835 *list = (*list)->next;
3836 break;
3838 list = &(*list)->next;
3841 UnlockLists();
3843 ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
3844 while(ctx != NULL)
3846 ALCcontext *next = ctx->next;
3847 WARN("Releasing context %p\n", ctx);
3848 ReleaseContext(ctx, device);
3849 ctx = next;
3851 if((device->Flags&DEVICE_RUNNING))
3852 V0(device->Backend,stop)();
3853 device->Flags &= ~DEVICE_RUNNING;
3854 almtx_unlock(&device->BackendLock);
3856 ALCdevice_DecRef(device);
3858 return ALC_TRUE;
3862 /************************************************
3863 * ALC capture functions
3864 ************************************************/
3865 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3867 ALCdevice *device = NULL;
3868 ALCenum err;
3870 DO_INITCONFIG();
3872 if(!CaptureBackend.name)
3874 alcSetError(NULL, ALC_INVALID_VALUE);
3875 return NULL;
3878 if(samples <= 0)
3880 alcSetError(NULL, ALC_INVALID_VALUE);
3881 return NULL;
3884 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3885 deviceName = NULL;
3887 device = al_calloc(16, sizeof(ALCdevice));
3888 if(!device)
3890 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3891 return NULL;
3894 //Validate device
3895 InitRef(&device->ref, 1);
3896 device->Connected = ALC_TRUE;
3897 device->Type = Capture;
3899 VECTOR_INIT(device->Hrtf.List);
3900 AL_STRING_INIT(device->Hrtf.Name);
3902 AL_STRING_INIT(device->DeviceName);
3903 device->Dry.Buffer = NULL;
3904 device->Dry.NumChannels = 0;
3905 device->FOAOut.Buffer = NULL;
3906 device->FOAOut.NumChannels = 0;
3907 device->RealOut.Buffer = NULL;
3908 device->RealOut.NumChannels = 0;
3910 InitUIntMap(&device->BufferMap, ~0);
3911 InitUIntMap(&device->EffectMap, ~0);
3912 InitUIntMap(&device->FilterMap, ~0);
3914 if(!CaptureBackend.getFactory)
3915 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3916 ALCbackend_Capture);
3917 else
3919 ALCbackendFactory *factory = CaptureBackend.getFactory();
3920 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3922 if(!device->Backend)
3924 al_free(device);
3925 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3926 return NULL;
3929 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3930 device->Frequency = frequency;
3932 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3933 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3935 al_free(device);
3936 alcSetError(NULL, ALC_INVALID_ENUM);
3937 return NULL;
3939 device->IsHeadphones = AL_FALSE;
3940 device->AmbiFmt = AmbiFormat_Default;
3942 device->UpdateSize = samples;
3943 device->NumUpdates = 1;
3945 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3947 al_free(device);
3948 alcSetError(NULL, err);
3949 return NULL;
3951 almtx_init(&device->BackendLock, almtx_plain);
3954 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
3955 do {
3956 device->next = head;
3957 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
3960 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3961 return device;
3964 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3966 ALCdevice *iter, *origdev;
3968 LockLists();
3969 iter = ATOMIC_LOAD_SEQ(&DeviceList);
3970 do {
3971 if(iter == device)
3972 break;
3973 } while((iter=iter->next) != NULL);
3974 if(!iter || iter->Type != Capture)
3976 alcSetError(iter, ALC_INVALID_DEVICE);
3977 UnlockLists();
3978 return ALC_FALSE;
3981 origdev = device;
3982 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next))
3984 ALCdevice *volatile*list = &origdev->next;
3985 while(*list)
3987 if(*list == device)
3989 *list = (*list)->next;
3990 break;
3992 list = &(*list)->next;
3995 UnlockLists();
3997 ALCdevice_DecRef(device);
3999 return ALC_TRUE;
4002 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
4004 if(!VerifyDevice(&device) || device->Type != Capture)
4005 alcSetError(device, ALC_INVALID_DEVICE);
4006 else
4008 almtx_lock(&device->BackendLock);
4009 if(!device->Connected)
4010 alcSetError(device, ALC_INVALID_DEVICE);
4011 else if(!(device->Flags&DEVICE_RUNNING))
4013 if(V0(device->Backend,start)())
4014 device->Flags |= DEVICE_RUNNING;
4015 else
4017 aluHandleDisconnect(device);
4018 alcSetError(device, ALC_INVALID_DEVICE);
4021 almtx_unlock(&device->BackendLock);
4024 if(device) ALCdevice_DecRef(device);
4027 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
4029 if(!VerifyDevice(&device) || device->Type != Capture)
4030 alcSetError(device, ALC_INVALID_DEVICE);
4031 else
4033 almtx_lock(&device->BackendLock);
4034 if((device->Flags&DEVICE_RUNNING))
4035 V0(device->Backend,stop)();
4036 device->Flags &= ~DEVICE_RUNNING;
4037 almtx_unlock(&device->BackendLock);
4040 if(device) ALCdevice_DecRef(device);
4043 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4045 if(!VerifyDevice(&device) || device->Type != Capture)
4046 alcSetError(device, ALC_INVALID_DEVICE);
4047 else
4049 ALCenum err = ALC_INVALID_VALUE;
4051 almtx_lock(&device->BackendLock);
4052 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
4053 err = V(device->Backend,captureSamples)(buffer, samples);
4054 almtx_unlock(&device->BackendLock);
4056 if(err != ALC_NO_ERROR)
4057 alcSetError(device, err);
4059 if(device) ALCdevice_DecRef(device);
4063 /************************************************
4064 * ALC loopback functions
4065 ************************************************/
4067 /* alcLoopbackOpenDeviceSOFT
4069 * Open a loopback device, for manual rendering.
4071 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
4073 ALCbackendFactory *factory;
4074 ALCdevice *device;
4076 DO_INITCONFIG();
4078 /* Make sure the device name, if specified, is us. */
4079 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
4081 alcSetError(NULL, ALC_INVALID_VALUE);
4082 return NULL;
4085 device = al_calloc(16, sizeof(ALCdevice));
4086 if(!device)
4088 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4089 return NULL;
4092 //Validate device
4093 InitRef(&device->ref, 1);
4094 device->Connected = ALC_TRUE;
4095 device->Type = Loopback;
4096 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
4098 device->Flags = 0;
4099 VECTOR_INIT(device->Hrtf.List);
4100 AL_STRING_INIT(device->Hrtf.Name);
4101 device->Bs2b = NULL;
4102 device->Uhj_Encoder = NULL;
4103 device->Render_Mode = NormalRender;
4104 AL_STRING_INIT(device->DeviceName);
4105 device->Dry.Buffer = NULL;
4106 device->Dry.NumChannels = 0;
4107 device->FOAOut.Buffer = NULL;
4108 device->FOAOut.NumChannels = 0;
4109 device->RealOut.Buffer = NULL;
4110 device->RealOut.NumChannels = 0;
4112 ATOMIC_INIT(&device->ContextList, NULL);
4114 device->ClockBase = 0;
4115 device->SamplesDone = 0;
4117 device->SourcesMax = 256;
4118 device->AuxiliaryEffectSlotMax = 64;
4119 device->NumAuxSends = DEFAULT_SENDS;
4121 InitUIntMap(&device->BufferMap, ~0);
4122 InitUIntMap(&device->EffectMap, ~0);
4123 InitUIntMap(&device->FilterMap, ~0);
4125 factory = ALCloopbackFactory_getFactory();
4126 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
4127 if(!device->Backend)
4129 al_free(device);
4130 alcSetError(NULL, ALC_OUT_OF_MEMORY);
4131 return NULL;
4133 almtx_init(&device->BackendLock, almtx_plain);
4135 //Set output format
4136 device->NumUpdates = 0;
4137 device->UpdateSize = 0;
4139 device->Frequency = DEFAULT_OUTPUT_RATE;
4140 device->FmtChans = DevFmtChannelsDefault;
4141 device->FmtType = DevFmtTypeDefault;
4142 device->IsHeadphones = AL_FALSE;
4143 device->AmbiFmt = AmbiFormat_Default;
4145 ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax);
4146 if(device->SourcesMax == 0) device->SourcesMax = 256;
4148 ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
4149 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 64;
4151 if(ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends))
4152 device->NumAuxSends = clampi(
4153 DEFAULT_SENDS, 0, clampi(device->NumAuxSends, 0, MAX_SENDS)
4156 device->NumStereoSources = 1;
4157 device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
4159 // Open the "backend"
4160 V(device->Backend,open)("Loopback");
4163 ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList);
4164 do {
4165 device->next = head;
4166 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device));
4169 TRACE("Created device %p\n", device);
4170 return device;
4173 /* alcIsRenderFormatSupportedSOFT
4175 * Determines if the loopback device supports the given format for rendering.
4177 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
4179 ALCboolean ret = ALC_FALSE;
4181 if(!VerifyDevice(&device) || device->Type != Loopback)
4182 alcSetError(device, ALC_INVALID_DEVICE);
4183 else if(freq <= 0)
4184 alcSetError(device, ALC_INVALID_VALUE);
4185 else
4187 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
4188 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
4189 freq >= MIN_OUTPUT_RATE)
4190 ret = ALC_TRUE;
4192 if(device) ALCdevice_DecRef(device);
4194 return ret;
4197 /* alcRenderSamplesSOFT
4199 * Renders some samples into a buffer, using the format last set by the
4200 * attributes given to alcCreateContext.
4202 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
4204 if(!VerifyDevice(&device) || device->Type != Loopback)
4205 alcSetError(device, ALC_INVALID_DEVICE);
4206 else if(samples < 0 || (samples > 0 && buffer == NULL))
4207 alcSetError(device, ALC_INVALID_VALUE);
4208 else
4210 V0(device->Backend,lock)();
4211 aluMixData(device, buffer, samples);
4212 V0(device->Backend,unlock)();
4214 if(device) ALCdevice_DecRef(device);
4218 /************************************************
4219 * ALC DSP pause/resume functions
4220 ************************************************/
4222 /* alcDevicePauseSOFT
4224 * Pause the DSP to stop audio processing.
4226 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
4228 if(!VerifyDevice(&device) || device->Type != Playback)
4229 alcSetError(device, ALC_INVALID_DEVICE);
4230 else
4232 almtx_lock(&device->BackendLock);
4233 if((device->Flags&DEVICE_RUNNING))
4234 V0(device->Backend,stop)();
4235 device->Flags &= ~DEVICE_RUNNING;
4236 device->Flags |= DEVICE_PAUSED;
4237 almtx_unlock(&device->BackendLock);
4239 if(device) ALCdevice_DecRef(device);
4242 /* alcDeviceResumeSOFT
4244 * Resume the DSP to restart audio processing.
4246 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
4248 if(!VerifyDevice(&device) || device->Type != Playback)
4249 alcSetError(device, ALC_INVALID_DEVICE);
4250 else
4252 almtx_lock(&device->BackendLock);
4253 if((device->Flags&DEVICE_PAUSED))
4255 device->Flags &= ~DEVICE_PAUSED;
4256 if(ATOMIC_LOAD_SEQ(&device->ContextList) != NULL)
4258 if(V0(device->Backend,start)() != ALC_FALSE)
4259 device->Flags |= DEVICE_RUNNING;
4260 else
4262 alcSetError(device, ALC_INVALID_DEVICE);
4263 V0(device->Backend,lock)();
4264 aluHandleDisconnect(device);
4265 V0(device->Backend,unlock)();
4269 almtx_unlock(&device->BackendLock);
4271 if(device) ALCdevice_DecRef(device);
4275 /************************************************
4276 * ALC HRTF functions
4277 ************************************************/
4279 /* alcGetStringiSOFT
4281 * Gets a string parameter at the given index.
4283 ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
4285 const ALCchar *str = NULL;
4287 if(!VerifyDevice(&device) || device->Type == Capture)
4288 alcSetError(device, ALC_INVALID_DEVICE);
4289 else switch(paramName)
4291 case ALC_HRTF_SPECIFIER_SOFT:
4292 if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf.List))
4293 str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf.List, index).name);
4294 else
4295 alcSetError(device, ALC_INVALID_VALUE);
4296 break;
4298 default:
4299 alcSetError(device, ALC_INVALID_ENUM);
4300 break;
4302 if(device) ALCdevice_DecRef(device);
4304 return str;
4307 /* alcResetDeviceSOFT
4309 * Resets the given device output, using the specified attribute list.
4311 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
4313 ALCenum err;
4315 LockLists();
4316 if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected)
4318 UnlockLists();
4319 alcSetError(device, ALC_INVALID_DEVICE);
4320 if(device) ALCdevice_DecRef(device);
4321 return ALC_FALSE;
4323 almtx_lock(&device->BackendLock);
4324 UnlockLists();
4326 err = UpdateDeviceParams(device, attribs);
4327 almtx_unlock(&device->BackendLock);
4329 if(err != ALC_NO_ERROR)
4331 alcSetError(device, err);
4332 if(err == ALC_INVALID_DEVICE)
4334 V0(device->Backend,lock)();
4335 aluHandleDisconnect(device);
4336 V0(device->Backend,unlock)();
4338 ALCdevice_DecRef(device);
4339 return ALC_FALSE;
4341 ALCdevice_DecRef(device);
4343 return ALC_TRUE;