Update a couple comments
[openal-soft.git] / Alc / ALc.c
blob8531e1defa9818b5e2dcfd5d9cba6b451250c122
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 <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_JACK
65 { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_ALSA
71 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
72 #endif
73 #ifdef HAVE_COREAUDIO
74 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
75 #endif
76 #ifdef HAVE_OSS
77 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SOLARIS
80 { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
81 #endif
82 #ifdef HAVE_SNDIO
83 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_QSA
86 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
87 #endif
88 #ifdef HAVE_MMDEVAPI
89 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_DSOUND
92 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
93 #endif
94 #ifdef HAVE_WINMM
95 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
96 #endif
97 #ifdef HAVE_PORTAUDIO
98 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
99 #endif
100 #ifdef HAVE_OPENSL
101 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
102 #endif
104 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
105 #ifdef HAVE_WAVE
106 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
107 #endif
109 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
111 #undef EmptyFuncs
113 static struct BackendInfo PlaybackBackend;
114 static struct BackendInfo CaptureBackend;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 typedef struct ALCfunction {
121 const ALCchar *funcName;
122 ALCvoid *address;
123 } ALCfunction;
125 typedef struct ALCenums {
126 const ALCchar *enumName;
127 ALCenum value;
128 } ALCenums;
130 #define DECL(x) { #x, (ALCvoid*)(x) }
131 static const ALCfunction alcFunctions[] = {
132 DECL(alcCreateContext),
133 DECL(alcMakeContextCurrent),
134 DECL(alcProcessContext),
135 DECL(alcSuspendContext),
136 DECL(alcDestroyContext),
137 DECL(alcGetCurrentContext),
138 DECL(alcGetContextsDevice),
139 DECL(alcOpenDevice),
140 DECL(alcCloseDevice),
141 DECL(alcGetError),
142 DECL(alcIsExtensionPresent),
143 DECL(alcGetProcAddress),
144 DECL(alcGetEnumValue),
145 DECL(alcGetString),
146 DECL(alcGetIntegerv),
147 DECL(alcCaptureOpenDevice),
148 DECL(alcCaptureCloseDevice),
149 DECL(alcCaptureStart),
150 DECL(alcCaptureStop),
151 DECL(alcCaptureSamples),
153 DECL(alcSetThreadContext),
154 DECL(alcGetThreadContext),
156 DECL(alcLoopbackOpenDeviceSOFT),
157 DECL(alcIsRenderFormatSupportedSOFT),
158 DECL(alcRenderSamplesSOFT),
160 DECL(alcDevicePauseSOFT),
161 DECL(alcDeviceResumeSOFT),
163 DECL(alcGetInteger64vSOFT),
165 DECL(alcResetDeviceSOFT),
167 DECL(alEnable),
168 DECL(alDisable),
169 DECL(alIsEnabled),
170 DECL(alGetString),
171 DECL(alGetBooleanv),
172 DECL(alGetIntegerv),
173 DECL(alGetFloatv),
174 DECL(alGetDoublev),
175 DECL(alGetBoolean),
176 DECL(alGetInteger),
177 DECL(alGetFloat),
178 DECL(alGetDouble),
179 DECL(alGetError),
180 DECL(alIsExtensionPresent),
181 DECL(alGetProcAddress),
182 DECL(alGetEnumValue),
183 DECL(alListenerf),
184 DECL(alListener3f),
185 DECL(alListenerfv),
186 DECL(alListeneri),
187 DECL(alListener3i),
188 DECL(alListeneriv),
189 DECL(alGetListenerf),
190 DECL(alGetListener3f),
191 DECL(alGetListenerfv),
192 DECL(alGetListeneri),
193 DECL(alGetListener3i),
194 DECL(alGetListeneriv),
195 DECL(alGenSources),
196 DECL(alDeleteSources),
197 DECL(alIsSource),
198 DECL(alSourcef),
199 DECL(alSource3f),
200 DECL(alSourcefv),
201 DECL(alSourcei),
202 DECL(alSource3i),
203 DECL(alSourceiv),
204 DECL(alGetSourcef),
205 DECL(alGetSource3f),
206 DECL(alGetSourcefv),
207 DECL(alGetSourcei),
208 DECL(alGetSource3i),
209 DECL(alGetSourceiv),
210 DECL(alSourcePlayv),
211 DECL(alSourceStopv),
212 DECL(alSourceRewindv),
213 DECL(alSourcePausev),
214 DECL(alSourcePlay),
215 DECL(alSourceStop),
216 DECL(alSourceRewind),
217 DECL(alSourcePause),
218 DECL(alSourceQueueBuffers),
219 DECL(alSourceUnqueueBuffers),
220 DECL(alGenBuffers),
221 DECL(alDeleteBuffers),
222 DECL(alIsBuffer),
223 DECL(alBufferData),
224 DECL(alBufferf),
225 DECL(alBuffer3f),
226 DECL(alBufferfv),
227 DECL(alBufferi),
228 DECL(alBuffer3i),
229 DECL(alBufferiv),
230 DECL(alGetBufferf),
231 DECL(alGetBuffer3f),
232 DECL(alGetBufferfv),
233 DECL(alGetBufferi),
234 DECL(alGetBuffer3i),
235 DECL(alGetBufferiv),
236 DECL(alDopplerFactor),
237 DECL(alDopplerVelocity),
238 DECL(alSpeedOfSound),
239 DECL(alDistanceModel),
241 DECL(alGenFilters),
242 DECL(alDeleteFilters),
243 DECL(alIsFilter),
244 DECL(alFilteri),
245 DECL(alFilteriv),
246 DECL(alFilterf),
247 DECL(alFilterfv),
248 DECL(alGetFilteri),
249 DECL(alGetFilteriv),
250 DECL(alGetFilterf),
251 DECL(alGetFilterfv),
252 DECL(alGenEffects),
253 DECL(alDeleteEffects),
254 DECL(alIsEffect),
255 DECL(alEffecti),
256 DECL(alEffectiv),
257 DECL(alEffectf),
258 DECL(alEffectfv),
259 DECL(alGetEffecti),
260 DECL(alGetEffectiv),
261 DECL(alGetEffectf),
262 DECL(alGetEffectfv),
263 DECL(alGenAuxiliaryEffectSlots),
264 DECL(alDeleteAuxiliaryEffectSlots),
265 DECL(alIsAuxiliaryEffectSlot),
266 DECL(alAuxiliaryEffectSloti),
267 DECL(alAuxiliaryEffectSlotiv),
268 DECL(alAuxiliaryEffectSlotf),
269 DECL(alAuxiliaryEffectSlotfv),
270 DECL(alGetAuxiliaryEffectSloti),
271 DECL(alGetAuxiliaryEffectSlotiv),
272 DECL(alGetAuxiliaryEffectSlotf),
273 DECL(alGetAuxiliaryEffectSlotfv),
275 DECL(alBufferSubDataSOFT),
277 DECL(alBufferSamplesSOFT),
278 DECL(alBufferSubSamplesSOFT),
279 DECL(alGetBufferSamplesSOFT),
280 DECL(alIsBufferFormatSupportedSOFT),
282 DECL(alDeferUpdatesSOFT),
283 DECL(alProcessUpdatesSOFT),
285 DECL(alSourcedSOFT),
286 DECL(alSource3dSOFT),
287 DECL(alSourcedvSOFT),
288 DECL(alGetSourcedSOFT),
289 DECL(alGetSource3dSOFT),
290 DECL(alGetSourcedvSOFT),
291 DECL(alSourcei64SOFT),
292 DECL(alSource3i64SOFT),
293 DECL(alSourcei64vSOFT),
294 DECL(alGetSourcei64SOFT),
295 DECL(alGetSource3i64SOFT),
296 DECL(alGetSourcei64vSOFT),
298 DECL(alGenSoundfontsSOFT),
299 DECL(alDeleteSoundfontsSOFT),
300 DECL(alIsSoundfontSOFT),
301 DECL(alGetSoundfontivSOFT),
302 DECL(alSoundfontPresetsSOFT),
303 DECL(alGenPresetsSOFT),
304 DECL(alDeletePresetsSOFT),
305 DECL(alIsPresetSOFT),
306 DECL(alPresetiSOFT),
307 DECL(alPresetivSOFT),
308 DECL(alGetPresetivSOFT),
309 DECL(alPresetFontsoundsSOFT),
310 DECL(alGenFontsoundsSOFT),
311 DECL(alDeleteFontsoundsSOFT),
312 DECL(alIsFontsoundSOFT),
313 DECL(alFontsoundiSOFT),
314 DECL(alFontsound2iSOFT),
315 DECL(alFontsoundivSOFT),
316 DECL(alGetFontsoundivSOFT),
317 DECL(alFontsoundModulatoriSOFT),
318 DECL(alGetFontsoundModulatorivSOFT),
319 DECL(alMidiSoundfontSOFT),
320 DECL(alMidiSoundfontvSOFT),
321 DECL(alMidiEventSOFT),
322 DECL(alMidiSysExSOFT),
323 DECL(alMidiPlaySOFT),
324 DECL(alMidiPauseSOFT),
325 DECL(alMidiStopSOFT),
326 DECL(alMidiResetSOFT),
327 DECL(alMidiGainSOFT),
328 DECL(alGetInteger64SOFT),
329 DECL(alGetInteger64vSOFT),
330 DECL(alLoadSoundfontSOFT),
332 { NULL, NULL }
334 #undef DECL
336 #define DECL(x) { #x, (x) }
337 static const ALCenums enumeration[] = {
338 DECL(ALC_INVALID),
339 DECL(ALC_FALSE),
340 DECL(ALC_TRUE),
342 DECL(ALC_MAJOR_VERSION),
343 DECL(ALC_MINOR_VERSION),
344 DECL(ALC_ATTRIBUTES_SIZE),
345 DECL(ALC_ALL_ATTRIBUTES),
346 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
347 DECL(ALC_DEVICE_SPECIFIER),
348 DECL(ALC_ALL_DEVICES_SPECIFIER),
349 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
350 DECL(ALC_EXTENSIONS),
351 DECL(ALC_FREQUENCY),
352 DECL(ALC_REFRESH),
353 DECL(ALC_SYNC),
354 DECL(ALC_MONO_SOURCES),
355 DECL(ALC_STEREO_SOURCES),
356 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
357 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
358 DECL(ALC_CAPTURE_SAMPLES),
359 DECL(ALC_CONNECTED),
361 DECL(ALC_EFX_MAJOR_VERSION),
362 DECL(ALC_EFX_MINOR_VERSION),
363 DECL(ALC_MAX_AUXILIARY_SENDS),
365 DECL(ALC_FORMAT_CHANNELS_SOFT),
366 DECL(ALC_FORMAT_TYPE_SOFT),
368 DECL(ALC_MONO_SOFT),
369 DECL(ALC_STEREO_SOFT),
370 DECL(ALC_QUAD_SOFT),
371 DECL(ALC_5POINT1_SOFT),
372 DECL(ALC_6POINT1_SOFT),
373 DECL(ALC_7POINT1_SOFT),
375 DECL(ALC_BYTE_SOFT),
376 DECL(ALC_UNSIGNED_BYTE_SOFT),
377 DECL(ALC_SHORT_SOFT),
378 DECL(ALC_UNSIGNED_SHORT_SOFT),
379 DECL(ALC_INT_SOFT),
380 DECL(ALC_UNSIGNED_INT_SOFT),
381 DECL(ALC_FLOAT_SOFT),
383 DECL(ALC_NO_ERROR),
384 DECL(ALC_INVALID_DEVICE),
385 DECL(ALC_INVALID_CONTEXT),
386 DECL(ALC_INVALID_ENUM),
387 DECL(ALC_INVALID_VALUE),
388 DECL(ALC_OUT_OF_MEMORY),
391 DECL(AL_INVALID),
392 DECL(AL_NONE),
393 DECL(AL_FALSE),
394 DECL(AL_TRUE),
396 DECL(AL_SOURCE_RELATIVE),
397 DECL(AL_CONE_INNER_ANGLE),
398 DECL(AL_CONE_OUTER_ANGLE),
399 DECL(AL_PITCH),
400 DECL(AL_POSITION),
401 DECL(AL_DIRECTION),
402 DECL(AL_VELOCITY),
403 DECL(AL_LOOPING),
404 DECL(AL_BUFFER),
405 DECL(AL_GAIN),
406 DECL(AL_MIN_GAIN),
407 DECL(AL_MAX_GAIN),
408 DECL(AL_ORIENTATION),
409 DECL(AL_REFERENCE_DISTANCE),
410 DECL(AL_ROLLOFF_FACTOR),
411 DECL(AL_CONE_OUTER_GAIN),
412 DECL(AL_MAX_DISTANCE),
413 DECL(AL_SEC_OFFSET),
414 DECL(AL_SAMPLE_OFFSET),
415 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
416 DECL(AL_BYTE_OFFSET),
417 DECL(AL_BYTE_RW_OFFSETS_SOFT),
418 DECL(AL_SOURCE_TYPE),
419 DECL(AL_STATIC),
420 DECL(AL_STREAMING),
421 DECL(AL_UNDETERMINED),
422 DECL(AL_METERS_PER_UNIT),
423 DECL(AL_DIRECT_CHANNELS_SOFT),
425 DECL(AL_DIRECT_FILTER),
426 DECL(AL_AUXILIARY_SEND_FILTER),
427 DECL(AL_AIR_ABSORPTION_FACTOR),
428 DECL(AL_ROOM_ROLLOFF_FACTOR),
429 DECL(AL_CONE_OUTER_GAINHF),
430 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
431 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
432 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
434 DECL(AL_SOURCE_STATE),
435 DECL(AL_INITIAL),
436 DECL(AL_PLAYING),
437 DECL(AL_PAUSED),
438 DECL(AL_STOPPED),
440 DECL(AL_BUFFERS_QUEUED),
441 DECL(AL_BUFFERS_PROCESSED),
443 DECL(AL_FORMAT_MONO8),
444 DECL(AL_FORMAT_MONO16),
445 DECL(AL_FORMAT_MONO_FLOAT32),
446 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
447 DECL(AL_FORMAT_STEREO8),
448 DECL(AL_FORMAT_STEREO16),
449 DECL(AL_FORMAT_STEREO_FLOAT32),
450 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
451 DECL(AL_FORMAT_MONO_IMA4),
452 DECL(AL_FORMAT_STEREO_IMA4),
453 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
454 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
455 DECL(AL_FORMAT_QUAD8_LOKI),
456 DECL(AL_FORMAT_QUAD16_LOKI),
457 DECL(AL_FORMAT_QUAD8),
458 DECL(AL_FORMAT_QUAD16),
459 DECL(AL_FORMAT_QUAD32),
460 DECL(AL_FORMAT_51CHN8),
461 DECL(AL_FORMAT_51CHN16),
462 DECL(AL_FORMAT_51CHN32),
463 DECL(AL_FORMAT_61CHN8),
464 DECL(AL_FORMAT_61CHN16),
465 DECL(AL_FORMAT_61CHN32),
466 DECL(AL_FORMAT_71CHN8),
467 DECL(AL_FORMAT_71CHN16),
468 DECL(AL_FORMAT_71CHN32),
469 DECL(AL_FORMAT_REAR8),
470 DECL(AL_FORMAT_REAR16),
471 DECL(AL_FORMAT_REAR32),
472 DECL(AL_FORMAT_MONO_MULAW),
473 DECL(AL_FORMAT_MONO_MULAW_EXT),
474 DECL(AL_FORMAT_STEREO_MULAW),
475 DECL(AL_FORMAT_STEREO_MULAW_EXT),
476 DECL(AL_FORMAT_QUAD_MULAW),
477 DECL(AL_FORMAT_51CHN_MULAW),
478 DECL(AL_FORMAT_61CHN_MULAW),
479 DECL(AL_FORMAT_71CHN_MULAW),
480 DECL(AL_FORMAT_REAR_MULAW),
481 DECL(AL_FORMAT_MONO_ALAW_EXT),
482 DECL(AL_FORMAT_STEREO_ALAW_EXT),
484 DECL(AL_MONO8_SOFT),
485 DECL(AL_MONO16_SOFT),
486 DECL(AL_MONO32F_SOFT),
487 DECL(AL_STEREO8_SOFT),
488 DECL(AL_STEREO16_SOFT),
489 DECL(AL_STEREO32F_SOFT),
490 DECL(AL_QUAD8_SOFT),
491 DECL(AL_QUAD16_SOFT),
492 DECL(AL_QUAD32F_SOFT),
493 DECL(AL_REAR8_SOFT),
494 DECL(AL_REAR16_SOFT),
495 DECL(AL_REAR32F_SOFT),
496 DECL(AL_5POINT1_8_SOFT),
497 DECL(AL_5POINT1_16_SOFT),
498 DECL(AL_5POINT1_32F_SOFT),
499 DECL(AL_6POINT1_8_SOFT),
500 DECL(AL_6POINT1_16_SOFT),
501 DECL(AL_6POINT1_32F_SOFT),
502 DECL(AL_7POINT1_8_SOFT),
503 DECL(AL_7POINT1_16_SOFT),
504 DECL(AL_7POINT1_32F_SOFT),
505 DECL(AL_FORMAT_BFORMAT2D_8),
506 DECL(AL_FORMAT_BFORMAT2D_16),
507 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
508 DECL(AL_FORMAT_BFORMAT2D_MULAW),
509 DECL(AL_FORMAT_BFORMAT3D_8),
510 DECL(AL_FORMAT_BFORMAT3D_16),
511 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
512 DECL(AL_FORMAT_BFORMAT3D_MULAW),
514 DECL(AL_MONO_SOFT),
515 DECL(AL_STEREO_SOFT),
516 DECL(AL_QUAD_SOFT),
517 DECL(AL_REAR_SOFT),
518 DECL(AL_5POINT1_SOFT),
519 DECL(AL_6POINT1_SOFT),
520 DECL(AL_7POINT1_SOFT),
522 DECL(AL_BYTE_SOFT),
523 DECL(AL_UNSIGNED_BYTE_SOFT),
524 DECL(AL_SHORT_SOFT),
525 DECL(AL_UNSIGNED_SHORT_SOFT),
526 DECL(AL_INT_SOFT),
527 DECL(AL_UNSIGNED_INT_SOFT),
528 DECL(AL_FLOAT_SOFT),
529 DECL(AL_DOUBLE_SOFT),
530 DECL(AL_BYTE3_SOFT),
531 DECL(AL_UNSIGNED_BYTE3_SOFT),
533 DECL(AL_FREQUENCY),
534 DECL(AL_BITS),
535 DECL(AL_CHANNELS),
536 DECL(AL_SIZE),
537 DECL(AL_INTERNAL_FORMAT_SOFT),
538 DECL(AL_BYTE_LENGTH_SOFT),
539 DECL(AL_SAMPLE_LENGTH_SOFT),
540 DECL(AL_SEC_LENGTH_SOFT),
541 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
542 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
544 DECL(AL_UNUSED),
545 DECL(AL_PENDING),
546 DECL(AL_PROCESSED),
548 DECL(AL_NO_ERROR),
549 DECL(AL_INVALID_NAME),
550 DECL(AL_INVALID_ENUM),
551 DECL(AL_INVALID_VALUE),
552 DECL(AL_INVALID_OPERATION),
553 DECL(AL_OUT_OF_MEMORY),
555 DECL(AL_VENDOR),
556 DECL(AL_VERSION),
557 DECL(AL_RENDERER),
558 DECL(AL_EXTENSIONS),
560 DECL(AL_DOPPLER_FACTOR),
561 DECL(AL_DOPPLER_VELOCITY),
562 DECL(AL_DISTANCE_MODEL),
563 DECL(AL_SPEED_OF_SOUND),
564 DECL(AL_SOURCE_DISTANCE_MODEL),
565 DECL(AL_DEFERRED_UPDATES_SOFT),
567 DECL(AL_INVERSE_DISTANCE),
568 DECL(AL_INVERSE_DISTANCE_CLAMPED),
569 DECL(AL_LINEAR_DISTANCE),
570 DECL(AL_LINEAR_DISTANCE_CLAMPED),
571 DECL(AL_EXPONENT_DISTANCE),
572 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
574 DECL(AL_FILTER_TYPE),
575 DECL(AL_FILTER_NULL),
576 DECL(AL_FILTER_LOWPASS),
577 DECL(AL_FILTER_HIGHPASS),
578 DECL(AL_FILTER_BANDPASS),
580 DECL(AL_LOWPASS_GAIN),
581 DECL(AL_LOWPASS_GAINHF),
583 DECL(AL_HIGHPASS_GAIN),
584 DECL(AL_HIGHPASS_GAINLF),
586 DECL(AL_BANDPASS_GAIN),
587 DECL(AL_BANDPASS_GAINHF),
588 DECL(AL_BANDPASS_GAINLF),
590 DECL(AL_EFFECT_TYPE),
591 DECL(AL_EFFECT_NULL),
592 DECL(AL_EFFECT_REVERB),
593 DECL(AL_EFFECT_EAXREVERB),
594 DECL(AL_EFFECT_CHORUS),
595 DECL(AL_EFFECT_DISTORTION),
596 DECL(AL_EFFECT_ECHO),
597 DECL(AL_EFFECT_FLANGER),
598 #if 0
599 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
600 DECL(AL_EFFECT_VOCAL_MORPHER),
601 DECL(AL_EFFECT_PITCH_SHIFTER),
602 #endif
603 DECL(AL_EFFECT_RING_MODULATOR),
604 #if 0
605 DECL(AL_EFFECT_AUTOWAH),
606 #endif
607 DECL(AL_EFFECT_COMPRESSOR),
608 DECL(AL_EFFECT_EQUALIZER),
609 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
610 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
612 DECL(AL_EAXREVERB_DENSITY),
613 DECL(AL_EAXREVERB_DIFFUSION),
614 DECL(AL_EAXREVERB_GAIN),
615 DECL(AL_EAXREVERB_GAINHF),
616 DECL(AL_EAXREVERB_GAINLF),
617 DECL(AL_EAXREVERB_DECAY_TIME),
618 DECL(AL_EAXREVERB_DECAY_HFRATIO),
619 DECL(AL_EAXREVERB_DECAY_LFRATIO),
620 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
621 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
622 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
623 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
624 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
625 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
626 DECL(AL_EAXREVERB_ECHO_TIME),
627 DECL(AL_EAXREVERB_ECHO_DEPTH),
628 DECL(AL_EAXREVERB_MODULATION_TIME),
629 DECL(AL_EAXREVERB_MODULATION_DEPTH),
630 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
631 DECL(AL_EAXREVERB_HFREFERENCE),
632 DECL(AL_EAXREVERB_LFREFERENCE),
633 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
634 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
636 DECL(AL_REVERB_DENSITY),
637 DECL(AL_REVERB_DIFFUSION),
638 DECL(AL_REVERB_GAIN),
639 DECL(AL_REVERB_GAINHF),
640 DECL(AL_REVERB_DECAY_TIME),
641 DECL(AL_REVERB_DECAY_HFRATIO),
642 DECL(AL_REVERB_REFLECTIONS_GAIN),
643 DECL(AL_REVERB_REFLECTIONS_DELAY),
644 DECL(AL_REVERB_LATE_REVERB_GAIN),
645 DECL(AL_REVERB_LATE_REVERB_DELAY),
646 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
647 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
648 DECL(AL_REVERB_DECAY_HFLIMIT),
650 DECL(AL_CHORUS_WAVEFORM),
651 DECL(AL_CHORUS_PHASE),
652 DECL(AL_CHORUS_RATE),
653 DECL(AL_CHORUS_DEPTH),
654 DECL(AL_CHORUS_FEEDBACK),
655 DECL(AL_CHORUS_DELAY),
657 DECL(AL_DISTORTION_EDGE),
658 DECL(AL_DISTORTION_GAIN),
659 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
660 DECL(AL_DISTORTION_EQCENTER),
661 DECL(AL_DISTORTION_EQBANDWIDTH),
663 DECL(AL_ECHO_DELAY),
664 DECL(AL_ECHO_LRDELAY),
665 DECL(AL_ECHO_DAMPING),
666 DECL(AL_ECHO_FEEDBACK),
667 DECL(AL_ECHO_SPREAD),
669 DECL(AL_FLANGER_WAVEFORM),
670 DECL(AL_FLANGER_PHASE),
671 DECL(AL_FLANGER_RATE),
672 DECL(AL_FLANGER_DEPTH),
673 DECL(AL_FLANGER_FEEDBACK),
674 DECL(AL_FLANGER_DELAY),
676 DECL(AL_RING_MODULATOR_FREQUENCY),
677 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
678 DECL(AL_RING_MODULATOR_WAVEFORM),
680 #if 0
681 DECL(AL_AUTOWAH_ATTACK_TIME),
682 DECL(AL_AUTOWAH_PEAK_GAIN),
683 DECL(AL_AUTOWAH_RELEASE_TIME),
684 DECL(AL_AUTOWAH_RESONANCE),
685 #endif
687 DECL(AL_COMPRESSOR_ONOFF),
689 DECL(AL_EQUALIZER_LOW_GAIN),
690 DECL(AL_EQUALIZER_LOW_CUTOFF),
691 DECL(AL_EQUALIZER_MID1_GAIN),
692 DECL(AL_EQUALIZER_MID1_CENTER),
693 DECL(AL_EQUALIZER_MID1_WIDTH),
694 DECL(AL_EQUALIZER_MID2_GAIN),
695 DECL(AL_EQUALIZER_MID2_CENTER),
696 DECL(AL_EQUALIZER_MID2_WIDTH),
697 DECL(AL_EQUALIZER_HIGH_GAIN),
698 DECL(AL_EQUALIZER_HIGH_CUTOFF),
700 DECL(AL_DEDICATED_GAIN),
702 { NULL, (ALCenum)0 }
704 #undef DECL
706 static const ALCchar alcNoError[] = "No Error";
707 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
708 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
709 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
710 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
711 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
714 /************************************************
715 * Global variables
716 ************************************************/
718 /* Enumerated device names */
719 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
721 static al_string alcAllDevicesList;
722 static al_string alcCaptureDeviceList;
724 /* Default is always the first in the list */
725 static ALCchar *alcDefaultAllDevicesSpecifier;
726 static ALCchar *alcCaptureDefaultDeviceSpecifier;
728 /* Default context extensions */
729 static const ALchar alExtList[] =
730 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
731 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
732 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
733 "AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_block_alignment "
734 "AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates "
735 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
736 "AL_SOFT_source_latency AL_SOFT_source_length";
738 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
740 /* Thread-local current context */
741 static altss_t LocalContext;
742 /* Process-wide current context */
743 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
745 /* Mixing thread piority level */
746 ALint RTPrioLevel;
748 FILE *LogFile;
749 #ifdef _DEBUG
750 enum LogLevel LogLevel = LogWarning;
751 #else
752 enum LogLevel LogLevel = LogError;
753 #endif
755 /* Flag to trap ALC device errors */
756 static ALCboolean TrapALCError = ALC_FALSE;
758 /* One-time configuration init control */
759 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
761 /* Default effect that applies to sources that don't have an effect on send 0 */
762 static ALeffect DefaultEffect;
764 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
765 * updates.
767 static ALCboolean SuspendDefers = ALC_TRUE;
770 /************************************************
771 * ALC information
772 ************************************************/
773 static const ALCchar alcNoDeviceExtList[] =
774 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
775 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
776 static const ALCchar alcExtensionList[] =
777 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
778 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
779 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
780 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
781 static const ALCint alcMajorVersion = 1;
782 static const ALCint alcMinorVersion = 1;
784 static const ALCint alcEFXMajorVersion = 1;
785 static const ALCint alcEFXMinorVersion = 0;
788 /************************************************
789 * Device lists
790 ************************************************/
791 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
793 static almtx_t ListLock;
794 static inline void LockLists(void)
796 int lockret = almtx_lock(&ListLock);
797 assert(lockret == althrd_success);
799 static inline void UnlockLists(void)
801 int unlockret = almtx_unlock(&ListLock);
802 assert(unlockret == althrd_success);
805 /************************************************
806 * Library initialization
807 ************************************************/
808 #if defined(_WIN32)
809 static void alc_init(void);
810 static void alc_deinit(void);
811 static void alc_deinit_safe(void);
813 #ifndef AL_LIBTYPE_STATIC
814 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
816 switch(reason)
818 case DLL_PROCESS_ATTACH:
819 /* Pin the DLL so we won't get unloaded until the process terminates */
820 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
821 (WCHAR*)hModule, &hModule);
822 alc_init();
823 break;
825 case DLL_THREAD_DETACH:
826 break;
828 case DLL_PROCESS_DETACH:
829 if(!lpReserved)
830 alc_deinit();
831 else
832 alc_deinit_safe();
833 break;
835 return TRUE;
837 #elif defined(_MSC_VER)
838 #pragma section(".CRT$XCU",read)
839 static void alc_constructor(void);
840 static void alc_destructor(void);
841 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
843 static void alc_constructor(void)
845 atexit(alc_destructor);
846 alc_init();
849 static void alc_destructor(void)
851 alc_deinit();
853 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor));
855 static void alc_deinit(void) __attribute__((destructor));
856 #else
857 #error "No static initialization available on this platform!"
858 #endif
860 #elif defined(HAVE_GCC_DESTRUCTOR)
862 static void alc_init(void) __attribute__((constructor));
863 static void alc_deinit(void) __attribute__((destructor));
865 #else
866 #error "No global initialization available on this platform!"
867 #endif
869 static void ReleaseThreadCtx(void *ptr);
870 static void alc_init(void)
872 const char *str;
873 int ret;
875 LogFile = stderr;
877 AL_STRING_INIT(alcAllDevicesList);
878 AL_STRING_INIT(alcCaptureDeviceList);
880 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
881 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
882 ConeScale *= 0.5f;
884 str = getenv("__ALSOFT_REVERSE_Z");
885 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
886 ZScale *= -1.0f;
888 ret = altss_create(&LocalContext, ReleaseThreadCtx);
889 assert(ret == althrd_success);
891 ret = almtx_init(&ListLock, almtx_recursive);
892 assert(ret == althrd_success);
894 ThunkInit();
897 static void alc_initconfig(void)
899 const char *devs, *str;
900 ALuint capfilter;
901 float valf;
902 int i, n;
904 str = getenv("ALSOFT_LOGLEVEL");
905 if(str)
907 long lvl = strtol(str, NULL, 0);
908 if(lvl >= NoLog && lvl <= LogRef)
909 LogLevel = lvl;
912 str = getenv("ALSOFT_LOGFILE");
913 if(str && str[0])
915 FILE *logfile = al_fopen(str, "wt");
916 if(logfile) LogFile = logfile;
917 else ERR("Failed to open log file '%s'\n", str);
921 char buf[1024] = "";
922 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
923 for(i = 1;BackendList[i].name;i++)
924 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
925 TRACE("Supported backends: %s\n", buf);
927 ReadALConfig();
929 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
930 if(str && *str)
932 if(strcasecmp(str, "ignore") == 0)
934 SuspendDefers = ALC_FALSE;
935 TRACE("Selected context suspend behavior, \"ignore\"\n");
937 else
938 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
941 capfilter = 0;
942 #if defined(HAVE_SSE4_1)
943 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
944 #elif defined(HAVE_SSE2)
945 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
946 #elif defined(HAVE_SSE)
947 capfilter |= CPU_CAP_SSE;
948 #endif
949 #ifdef HAVE_NEON
950 capfilter |= CPU_CAP_NEON;
951 #endif
952 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
954 if(strcasecmp(str, "all") == 0)
955 capfilter = 0;
956 else
958 size_t len;
959 const char *next = str;
961 do {
962 str = next;
963 while(isspace(str[0]))
964 str++;
965 next = strchr(str, ',');
967 if(!str[0] || str[0] == ',')
968 continue;
970 len = (next ? ((size_t)(next-str)) : strlen(str));
971 while(len > 0 && isspace(str[len-1]))
972 len--;
973 if(len == 3 && strncasecmp(str, "sse", len) == 0)
974 capfilter &= ~CPU_CAP_SSE;
975 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
976 capfilter &= ~CPU_CAP_SSE2;
977 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
978 capfilter &= ~CPU_CAP_SSE4_1;
979 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
980 capfilter &= ~CPU_CAP_NEON;
981 else
982 WARN("Invalid CPU extension \"%s\"\n", str);
983 } while(next++);
986 FillCPUCaps(capfilter);
988 #ifdef _WIN32
989 RTPrioLevel = 1;
990 #else
991 RTPrioLevel = 0;
992 #endif
993 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
995 if(ConfigValueStr(NULL, "resampler", &str))
997 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
998 DefaultResampler = PointResampler;
999 else if(strcasecmp(str, "linear") == 0)
1000 DefaultResampler = LinearResampler;
1001 else if(strcasecmp(str, "cubic") == 0)
1002 DefaultResampler = CubicResampler;
1003 else
1005 char *end;
1007 n = strtol(str, &end, 0);
1008 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
1009 DefaultResampler = n;
1010 else
1011 WARN("Invalid resampler: %s\n", str);
1014 aluInitResamplers();
1016 str = getenv("ALSOFT_TRAP_ERROR");
1017 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1019 TrapALError = AL_TRUE;
1020 TrapALCError = AL_TRUE;
1022 else
1024 str = getenv("ALSOFT_TRAP_AL_ERROR");
1025 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1026 TrapALError = AL_TRUE;
1027 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
1029 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1030 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1031 TrapALCError = ALC_TRUE;
1032 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1035 if(ConfigValueFloat("reverb", "boost", &valf))
1036 ReverbBoost *= powf(10.0f, valf / 20.0f);
1038 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1040 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1041 ConfigValueStr(NULL, "drivers", &devs))
1043 int n;
1044 size_t len;
1045 const char *next = devs;
1046 int endlist, delitem;
1048 i = 0;
1049 do {
1050 devs = next;
1051 while(isspace(devs[0]))
1052 devs++;
1053 next = strchr(devs, ',');
1055 delitem = (devs[0] == '-');
1056 if(devs[0] == '-') devs++;
1058 if(!devs[0] || devs[0] == ',')
1060 endlist = 0;
1061 continue;
1063 endlist = 1;
1065 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1066 while(len > 0 && isspace(devs[len-1]))
1067 len--;
1068 for(n = i;BackendList[n].name;n++)
1070 if(len == strlen(BackendList[n].name) &&
1071 strncmp(BackendList[n].name, devs, len) == 0)
1073 if(delitem)
1075 do {
1076 BackendList[n] = BackendList[n+1];
1077 ++n;
1078 } while(BackendList[n].name);
1080 else
1082 struct BackendInfo Bkp = BackendList[n];
1083 while(n > i)
1085 BackendList[n] = BackendList[n-1];
1086 --n;
1088 BackendList[n] = Bkp;
1090 i++;
1092 break;
1095 } while(next++);
1097 if(endlist)
1099 BackendList[i].name = NULL;
1100 BackendList[i].getFactory = NULL;
1101 BackendList[i].Init = NULL;
1102 BackendList[i].Deinit = NULL;
1103 BackendList[i].Probe = NULL;
1107 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1109 if(BackendList[i].getFactory)
1111 ALCbackendFactory *factory = BackendList[i].getFactory();
1112 if(!V0(factory,init)())
1114 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1115 continue;
1118 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1119 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1121 PlaybackBackend = BackendList[i];
1122 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1124 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1126 CaptureBackend = BackendList[i];
1127 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1130 continue;
1133 if(!BackendList[i].Init(&BackendList[i].Funcs))
1135 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1136 continue;
1139 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1140 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1142 PlaybackBackend = BackendList[i];
1143 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1145 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1147 CaptureBackend = BackendList[i];
1148 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1152 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1153 V0(factory,init)();
1156 if(ConfigValueStr(NULL, "excludefx", &str))
1158 size_t len;
1159 const char *next = str;
1161 do {
1162 str = next;
1163 next = strchr(str, ',');
1165 if(!str[0] || next == str)
1166 continue;
1168 len = (next ? ((size_t)(next-str)) : strlen(str));
1169 for(n = 0;EffectList[n].name;n++)
1171 if(len == strlen(EffectList[n].name) &&
1172 strncmp(EffectList[n].name, str, len) == 0)
1173 DisabledEffects[EffectList[n].type] = AL_TRUE;
1175 } while(next++);
1178 InitEffectFactoryMap();
1180 InitEffect(&DefaultEffect);
1181 str = getenv("ALSOFT_DEFAULT_REVERB");
1182 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1183 LoadReverbPreset(str, &DefaultEffect);
1185 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1188 /************************************************
1189 * Library deinitialization
1190 ************************************************/
1191 static void alc_cleanup(void)
1193 ALCdevice *dev;
1195 AL_STRING_DEINIT(alcAllDevicesList);
1196 AL_STRING_DEINIT(alcCaptureDeviceList);
1198 free(alcDefaultAllDevicesSpecifier);
1199 alcDefaultAllDevicesSpecifier = NULL;
1200 free(alcCaptureDefaultDeviceSpecifier);
1201 alcCaptureDefaultDeviceSpecifier = NULL;
1203 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1205 ALCuint num = 0;
1206 do {
1207 num++;
1208 } while((dev=dev->next) != NULL);
1209 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1212 DeinitEffectFactoryMap();
1215 static void alc_deinit_safe(void)
1217 alc_cleanup();
1219 FreeHrtfs();
1220 FreeALConfig();
1222 ThunkExit();
1223 almtx_destroy(&ListLock);
1224 altss_delete(LocalContext);
1226 if(LogFile != stderr)
1227 fclose(LogFile);
1228 LogFile = NULL;
1231 static void alc_deinit(void)
1233 int i;
1235 alc_cleanup();
1237 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1238 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1240 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1242 if(!BackendList[i].getFactory)
1243 BackendList[i].Deinit();
1244 else
1246 ALCbackendFactory *factory = BackendList[i].getFactory();
1247 V0(factory,deinit)();
1251 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1252 V0(factory,deinit)();
1255 alc_deinit_safe();
1259 /************************************************
1260 * Device enumeration
1261 ************************************************/
1262 static void ProbeDevices(al_string *list, enum DevProbe type)
1264 DO_INITCONFIG();
1266 LockLists();
1267 al_string_clear(list);
1269 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1271 if(!PlaybackBackend.getFactory)
1272 PlaybackBackend.Probe(type);
1273 else
1275 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1276 V(factory,probe)(type);
1279 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1281 if(!CaptureBackend.getFactory)
1282 CaptureBackend.Probe(type);
1283 else
1285 ALCbackendFactory *factory = CaptureBackend.getFactory();
1286 V(factory,probe)(type);
1289 UnlockLists();
1291 static void ProbeAllDevicesList(void)
1292 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1293 static void ProbeCaptureDeviceList(void)
1294 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1296 static void AppendDevice(const ALCchar *name, al_string *devnames)
1298 size_t len = strlen(name);
1299 if(len > 0)
1300 al_string_append_range(devnames, name, name+len+1);
1302 void AppendAllDevicesList(const ALCchar *name)
1303 { AppendDevice(name, &alcAllDevicesList); }
1304 void AppendCaptureDeviceList(const ALCchar *name)
1305 { AppendDevice(name, &alcCaptureDeviceList); }
1308 /************************************************
1309 * Device format information
1310 ************************************************/
1311 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1313 switch(type)
1315 case DevFmtByte: return "Signed Byte";
1316 case DevFmtUByte: return "Unsigned Byte";
1317 case DevFmtShort: return "Signed Short";
1318 case DevFmtUShort: return "Unsigned Short";
1319 case DevFmtInt: return "Signed Int";
1320 case DevFmtUInt: return "Unsigned Int";
1321 case DevFmtFloat: return "Float";
1323 return "(unknown type)";
1325 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1327 switch(chans)
1329 case DevFmtMono: return "Mono";
1330 case DevFmtStereo: return "Stereo";
1331 case DevFmtQuad: return "Quadraphonic";
1332 case DevFmtX51: return "5.1 Surround";
1333 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1334 case DevFmtX61: return "6.1 Surround";
1335 case DevFmtX71: return "7.1 Surround";
1336 case DevFmtBFormat3D: return "B-Format 3D";
1338 return "(unknown channels)";
1341 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1342 ALuint BytesFromDevFmt(enum DevFmtType type)
1344 switch(type)
1346 case DevFmtByte: return sizeof(ALbyte);
1347 case DevFmtUByte: return sizeof(ALubyte);
1348 case DevFmtShort: return sizeof(ALshort);
1349 case DevFmtUShort: return sizeof(ALushort);
1350 case DevFmtInt: return sizeof(ALint);
1351 case DevFmtUInt: return sizeof(ALuint);
1352 case DevFmtFloat: return sizeof(ALfloat);
1354 return 0;
1356 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1358 switch(chans)
1360 case DevFmtMono: return 1;
1361 case DevFmtStereo: return 2;
1362 case DevFmtQuad: return 4;
1363 case DevFmtX51: return 6;
1364 case DevFmtX51Rear: return 6;
1365 case DevFmtX61: return 7;
1366 case DevFmtX71: return 8;
1367 case DevFmtBFormat3D: return 4;
1369 return 0;
1372 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1373 enum DevFmtChannels *chans, enum DevFmtType *type)
1375 static const struct {
1376 ALenum format;
1377 enum DevFmtChannels channels;
1378 enum DevFmtType type;
1379 } list[] = {
1380 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1381 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1382 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1384 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1385 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1386 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1388 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1389 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1390 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1392 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1393 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1394 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1396 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1397 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1398 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1400 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1401 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1402 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1404 ALuint i;
1406 for(i = 0;i < COUNTOF(list);i++)
1408 if(list[i].format == format)
1410 *chans = list[i].channels;
1411 *type = list[i].type;
1412 return AL_TRUE;
1416 return AL_FALSE;
1419 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1421 switch(type)
1423 case ALC_BYTE_SOFT:
1424 case ALC_UNSIGNED_BYTE_SOFT:
1425 case ALC_SHORT_SOFT:
1426 case ALC_UNSIGNED_SHORT_SOFT:
1427 case ALC_INT_SOFT:
1428 case ALC_UNSIGNED_INT_SOFT:
1429 case ALC_FLOAT_SOFT:
1430 return ALC_TRUE;
1432 return ALC_FALSE;
1435 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1437 switch(channels)
1439 case ALC_MONO_SOFT:
1440 case ALC_STEREO_SOFT:
1441 case ALC_QUAD_SOFT:
1442 case ALC_5POINT1_SOFT:
1443 case ALC_6POINT1_SOFT:
1444 case ALC_7POINT1_SOFT:
1445 return ALC_TRUE;
1447 return ALC_FALSE;
1451 /************************************************
1452 * Miscellaneous ALC helpers
1453 ************************************************/
1454 extern inline void LockContext(ALCcontext *context);
1455 extern inline void UnlockContext(ALCcontext *context);
1457 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1459 return V0(device->Backend,getLatency)();
1462 void ALCdevice_Lock(ALCdevice *device)
1464 V0(device->Backend,lock)();
1467 void ALCdevice_Unlock(ALCdevice *device)
1469 V0(device->Backend,unlock)();
1473 /* SetDefaultWFXChannelOrder
1475 * Sets the default channel order used by WaveFormatEx.
1477 void SetDefaultWFXChannelOrder(ALCdevice *device)
1479 ALuint i;
1481 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1482 device->ChannelName[i] = InvalidChannel;
1484 switch(device->FmtChans)
1486 case DevFmtMono:
1487 device->ChannelName[0] = FrontCenter;
1488 break;
1489 case DevFmtStereo:
1490 device->ChannelName[0] = FrontLeft;
1491 device->ChannelName[1] = FrontRight;
1492 break;
1493 case DevFmtQuad:
1494 device->ChannelName[0] = FrontLeft;
1495 device->ChannelName[1] = FrontRight;
1496 device->ChannelName[2] = BackLeft;
1497 device->ChannelName[3] = BackRight;
1498 break;
1499 case DevFmtX51:
1500 device->ChannelName[0] = FrontLeft;
1501 device->ChannelName[1] = FrontRight;
1502 device->ChannelName[2] = FrontCenter;
1503 device->ChannelName[3] = LFE;
1504 device->ChannelName[4] = SideLeft;
1505 device->ChannelName[5] = SideRight;
1506 break;
1507 case DevFmtX51Rear:
1508 device->ChannelName[0] = FrontLeft;
1509 device->ChannelName[1] = FrontRight;
1510 device->ChannelName[2] = FrontCenter;
1511 device->ChannelName[3] = LFE;
1512 device->ChannelName[4] = BackLeft;
1513 device->ChannelName[5] = BackRight;
1514 break;
1515 case DevFmtX61:
1516 device->ChannelName[0] = FrontLeft;
1517 device->ChannelName[1] = FrontRight;
1518 device->ChannelName[2] = FrontCenter;
1519 device->ChannelName[3] = LFE;
1520 device->ChannelName[4] = BackCenter;
1521 device->ChannelName[5] = SideLeft;
1522 device->ChannelName[6] = SideRight;
1523 break;
1524 case DevFmtX71:
1525 device->ChannelName[0] = FrontLeft;
1526 device->ChannelName[1] = FrontRight;
1527 device->ChannelName[2] = FrontCenter;
1528 device->ChannelName[3] = LFE;
1529 device->ChannelName[4] = BackLeft;
1530 device->ChannelName[5] = BackRight;
1531 device->ChannelName[6] = SideLeft;
1532 device->ChannelName[7] = SideRight;
1533 break;
1534 case DevFmtBFormat3D:
1535 device->ChannelName[0] = Aux0;
1536 device->ChannelName[1] = Aux1;
1537 device->ChannelName[2] = Aux2;
1538 device->ChannelName[3] = Aux3;
1539 break;
1543 /* SetDefaultChannelOrder
1545 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1547 void SetDefaultChannelOrder(ALCdevice *device)
1549 ALuint i;
1551 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1552 device->ChannelName[i] = InvalidChannel;
1554 switch(device->FmtChans)
1556 case DevFmtX51Rear:
1557 device->ChannelName[0] = FrontLeft;
1558 device->ChannelName[1] = FrontRight;
1559 device->ChannelName[2] = BackLeft;
1560 device->ChannelName[3] = BackRight;
1561 device->ChannelName[4] = FrontCenter;
1562 device->ChannelName[5] = LFE;
1563 return;
1564 case DevFmtX71:
1565 device->ChannelName[0] = FrontLeft;
1566 device->ChannelName[1] = FrontRight;
1567 device->ChannelName[2] = BackLeft;
1568 device->ChannelName[3] = BackRight;
1569 device->ChannelName[4] = FrontCenter;
1570 device->ChannelName[5] = LFE;
1571 device->ChannelName[6] = SideLeft;
1572 device->ChannelName[7] = SideRight;
1573 return;
1575 /* Same as WFX order */
1576 case DevFmtMono:
1577 case DevFmtStereo:
1578 case DevFmtQuad:
1579 case DevFmtX51:
1580 case DevFmtX61:
1581 case DevFmtBFormat3D:
1582 SetDefaultWFXChannelOrder(device);
1583 break;
1587 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1590 /* ALCcontext_DeferUpdates
1592 * Defers/suspends updates for the given context's listener and sources. This
1593 * does *NOT* stop mixing, but rather prevents certain property changes from
1594 * taking effect.
1596 void ALCcontext_DeferUpdates(ALCcontext *context)
1598 ALCdevice *device = context->Device;
1599 FPUCtl oldMode;
1601 SetMixerFPUMode(&oldMode);
1603 V0(device->Backend,lock)();
1604 if(!context->DeferUpdates)
1606 ALboolean UpdateSources;
1607 ALvoice *voice, *voice_end;
1608 ALeffectslot **slot, **slot_end;
1610 context->DeferUpdates = AL_TRUE;
1612 /* Make sure all pending updates are performed */
1613 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
1615 voice = context->Voices;
1616 voice_end = voice + context->VoiceCount;
1617 while(voice != voice_end)
1619 ALsource *source = voice->Source;
1620 if(!source) goto next;
1622 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
1624 voice->Source = NULL;
1625 goto next;
1628 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
1629 voice->Update(voice, source, context);
1630 next:
1631 voice++;
1634 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
1635 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
1636 while(slot != slot_end)
1638 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
1639 V((*slot)->EffectState,update)(context->Device, *slot);
1640 slot++;
1643 V0(device->Backend,unlock)();
1645 RestoreFPUMode(&oldMode);
1648 /* ALCcontext_ProcessUpdates
1650 * Resumes update processing after being deferred.
1652 void ALCcontext_ProcessUpdates(ALCcontext *context)
1654 ALCdevice *device = context->Device;
1656 V0(device->Backend,lock)();
1657 if(context->DeferUpdates)
1659 ALsizei pos;
1661 context->DeferUpdates = AL_FALSE;
1663 LockUIntMapRead(&context->SourceMap);
1664 for(pos = 0;pos < context->SourceMap.size;pos++)
1666 ALsource *Source = context->SourceMap.array[pos].value;
1667 ALenum new_state;
1669 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1670 Source->Offset >= 0.0)
1672 ReadLock(&Source->queue_lock);
1673 ApplyOffset(Source);
1674 ReadUnlock(&Source->queue_lock);
1677 new_state = Source->new_state;
1678 Source->new_state = AL_NONE;
1679 if(new_state)
1680 SetSourceState(Source, context, new_state);
1682 UnlockUIntMapRead(&context->SourceMap);
1684 V0(device->Backend,unlock)();
1688 /* alcSetError
1690 * Stores the latest ALC device error
1692 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1694 if(TrapALCError)
1696 #ifdef _WIN32
1697 /* DebugBreak() will cause an exception if there is no debugger */
1698 if(IsDebuggerPresent())
1699 DebugBreak();
1700 #elif defined(SIGTRAP)
1701 raise(SIGTRAP);
1702 #endif
1705 if(device)
1706 ATOMIC_STORE(&device->LastError, errorCode);
1707 else
1708 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1712 /* UpdateClockBase
1714 * Updates the device's base clock time with however many samples have been
1715 * done. This is used so frequency changes on the device don't cause the time
1716 * to jump forward or back.
1718 static inline void UpdateClockBase(ALCdevice *device)
1720 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1721 device->SamplesDone = 0;
1724 /* UpdateDeviceParams
1726 * Updates device parameters according to the attribute list (caller is
1727 * responsible for holding the list lock).
1729 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1731 ALCcontext *context;
1732 enum DevFmtChannels oldChans;
1733 enum DevFmtType oldType;
1734 ALCuint oldFreq;
1735 FPUCtl oldMode;
1736 size_t size;
1738 // Check for attributes
1739 if(device->Type == Loopback)
1741 enum {
1742 GotFreq = 1<<0,
1743 GotChans = 1<<1,
1744 GotType = 1<<2,
1745 GotAll = GotFreq|GotChans|GotType
1747 ALCuint freq, numMono, numStereo, numSends, flags;
1748 enum DevFmtChannels schans;
1749 enum DevFmtType stype;
1750 ALCuint attrIdx = 0;
1751 ALCint gotFmt = 0;
1753 if(!attrList)
1755 WARN("Missing attributes for loopback device\n");
1756 return ALC_INVALID_VALUE;
1759 numMono = device->NumMonoSources;
1760 numStereo = device->NumStereoSources;
1761 numSends = device->NumAuxSends;
1762 schans = device->FmtChans;
1763 stype = device->FmtType;
1764 freq = device->Frequency;
1765 flags = device->Flags;
1767 while(attrList[attrIdx])
1769 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1771 ALCint val = attrList[attrIdx + 1];
1772 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1773 return ALC_INVALID_VALUE;
1774 schans = val;
1775 gotFmt |= GotChans;
1778 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1780 ALCint val = attrList[attrIdx + 1];
1781 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1782 return ALC_INVALID_VALUE;
1783 stype = val;
1784 gotFmt |= GotType;
1787 if(attrList[attrIdx] == ALC_FREQUENCY)
1789 freq = attrList[attrIdx + 1];
1790 if(freq < MIN_OUTPUT_RATE)
1791 return ALC_INVALID_VALUE;
1792 gotFmt |= GotFreq;
1795 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1797 numStereo = attrList[attrIdx + 1];
1798 if(numStereo > device->MaxNoOfSources)
1799 numStereo = device->MaxNoOfSources;
1801 numMono = device->MaxNoOfSources - numStereo;
1804 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1805 numSends = attrList[attrIdx + 1];
1807 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1809 if(attrList[attrIdx + 1] != ALC_FALSE)
1810 flags |= DEVICE_HRTF_REQUEST;
1811 else
1812 flags &= ~DEVICE_HRTF_REQUEST;
1815 attrIdx += 2;
1818 if(gotFmt != GotAll)
1820 WARN("Missing format for loopback device\n");
1821 return ALC_INVALID_VALUE;
1824 ConfigValueUInt(NULL, "sends", &numSends);
1825 numSends = minu(MAX_SENDS, numSends);
1827 if((device->Flags&DEVICE_RUNNING))
1828 V0(device->Backend,stop)();
1829 device->Flags = (flags & ~DEVICE_RUNNING);
1831 UpdateClockBase(device);
1833 device->Frequency = freq;
1834 device->FmtChans = schans;
1835 device->FmtType = stype;
1836 device->NumMonoSources = numMono;
1837 device->NumStereoSources = numStereo;
1838 device->NumAuxSends = numSends;
1840 else if(attrList && attrList[0])
1842 ALCuint freq, numMono, numStereo, numSends;
1843 ALCuint attrIdx = 0;
1845 /* If a context is already running on the device, stop playback so the
1846 * device attributes can be updated. */
1847 if((device->Flags&DEVICE_RUNNING))
1848 V0(device->Backend,stop)();
1849 device->Flags &= ~DEVICE_RUNNING;
1851 freq = device->Frequency;
1852 numMono = device->NumMonoSources;
1853 numStereo = device->NumStereoSources;
1854 numSends = device->NumAuxSends;
1856 while(attrList[attrIdx])
1858 if(attrList[attrIdx] == ALC_FREQUENCY)
1860 freq = attrList[attrIdx + 1];
1861 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1864 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1866 numStereo = attrList[attrIdx + 1];
1867 if(numStereo > device->MaxNoOfSources)
1868 numStereo = device->MaxNoOfSources;
1870 numMono = device->MaxNoOfSources - numStereo;
1873 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1874 numSends = attrList[attrIdx + 1];
1876 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1878 if(attrList[attrIdx + 1] != ALC_FALSE)
1879 device->Flags |= DEVICE_HRTF_REQUEST;
1880 else
1881 device->Flags &= ~DEVICE_HRTF_REQUEST;
1884 attrIdx += 2;
1887 ConfigValueUInt(NULL, "frequency", &freq);
1888 freq = maxu(freq, MIN_OUTPUT_RATE);
1890 ConfigValueUInt(NULL, "sends", &numSends);
1891 numSends = minu(MAX_SENDS, numSends);
1893 UpdateClockBase(device);
1895 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1896 device->Frequency;
1897 /* SSE and Neon do best with the update size being a multiple of 4 */
1898 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1899 device->UpdateSize = (device->UpdateSize+3)&~3;
1901 device->Frequency = freq;
1902 device->NumMonoSources = numMono;
1903 device->NumStereoSources = numStereo;
1904 device->NumAuxSends = numSends;
1907 if((device->Flags&DEVICE_RUNNING))
1908 return ALC_NO_ERROR;
1910 al_free(device->DryBuffer);
1911 device->DryBuffer = NULL;
1913 UpdateClockBase(device);
1915 device->Hrtf_Status = ALC_HRTF_DISABLED_SOFT;
1916 if(device->Type != Loopback && ((device->Flags&DEVICE_HRTF_REQUEST) || GetConfigValueBool(NULL, "hrtf", 0)))
1918 if(!FindHrtfFormat(&device->FmtChans, &device->Frequency))
1920 device->Flags &= ~DEVICE_HRTF_REQUEST;
1921 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1923 else
1924 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST |
1925 DEVICE_HRTF_REQUEST;
1927 if(device->Type == Loopback && (device->Flags&DEVICE_HRTF_REQUEST))
1929 enum DevFmtChannels chans = device->FmtChans;
1930 ALCuint freq = device->Frequency;
1931 if(!FindHrtfFormat(&chans, &freq) || chans != device->FmtChans || freq != device->Frequency)
1933 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1934 DevFmtChannelsString(device->FmtChans), device->Frequency);
1935 device->Flags &= ~DEVICE_HRTF_REQUEST;
1936 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
1940 oldFreq = device->Frequency;
1941 oldChans = device->FmtChans;
1942 oldType = device->FmtType;
1944 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1945 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
1946 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
1947 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
1948 device->UpdateSize, device->NumUpdates
1951 if(V0(device->Backend,reset)() == ALC_FALSE)
1952 return ALC_INVALID_DEVICE;
1954 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1956 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1957 DevFmtChannelsString(device->FmtChans));
1958 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1960 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1962 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1963 DevFmtTypeString(device->FmtType));
1964 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1966 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1968 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1969 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1972 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1973 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1974 device->Frequency, device->UpdateSize, device->NumUpdates
1977 if((device->UpdateSize&3) != 0)
1979 if((CPUCapFlags&CPU_CAP_SSE))
1980 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1981 if((CPUCapFlags&CPU_CAP_NEON))
1982 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1985 device->Hrtf = NULL;
1986 device->Hrtf_Mode = DisabledHrtf;
1987 if(device->FmtChans != DevFmtStereo)
1989 free(device->Bs2b);
1990 device->Bs2b = NULL;
1992 else
1994 bool headphones = device->IsHeadphones;
1995 enum HrtfMode hrtf_mode = FullHrtf;
1996 ALCenum hrtf_status = device->Hrtf_Status;
1997 const char *mode;
1998 int bs2blevel;
1999 int usehrtf;
2001 if(device->Type != Loopback)
2003 if(ConfigValueStr(NULL, "stereo-mode", &mode))
2005 if(strcasecmp(mode, "headphones") == 0)
2006 headphones = true;
2007 else if(strcasecmp(mode, "speakers") == 0)
2008 headphones = false;
2009 else if(strcasecmp(mode, "auto") != 0)
2010 ERR("Unexpected stereo-mode: %s\n", mode);
2013 if(ConfigValueStr(NULL, "hrtf-mode", &mode))
2015 if(strcasecmp(mode, "full") == 0)
2016 hrtf_mode = FullHrtf;
2017 else if(strcasecmp(mode, "basic") == 0)
2018 hrtf_mode = BasicHrtf;
2019 else
2020 ERR("Unexpected hrtf-mode: %s\n", mode);
2025 if(device->Type == Loopback || !ConfigValueBool(NULL, "hrtf", &usehrtf))
2027 usehrtf = (headphones || (device->Flags&DEVICE_HRTF_REQUEST));
2028 if(headphones)
2029 hrtf_status = ALC_HRTF_HEADPHONES_DETECTED_SOFT;
2030 else if(usehrtf)
2031 hrtf_status = ALC_HRTF_ENABLED_SOFT;
2033 else
2035 if(!usehrtf)
2036 hrtf_status = ALC_HRTF_DENIED_SOFT;
2037 else
2038 hrtf_status = ALC_HRTF_REQUIRED_SOFT;
2041 if(!usehrtf)
2042 device->Hrtf_Status = hrtf_status;
2043 else
2045 device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
2046 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
2048 if(device->Hrtf)
2050 device->Hrtf_Mode = hrtf_mode;
2051 device->Hrtf_Status = hrtf_status;
2052 TRACE("HRTF enabled\n");
2053 free(device->Bs2b);
2054 device->Bs2b = NULL;
2056 else
2058 device->Flags &= ~DEVICE_HRTF_REQUEST;
2059 TRACE("HRTF disabled\n");
2061 bs2blevel = (headphones ? 5 : 0);
2062 if(device->Type != Loopback)
2063 ConfigValueInt(NULL, "cf_level", &bs2blevel);
2064 if(bs2blevel > 0 && bs2blevel <= 6)
2066 if(!device->Bs2b)
2068 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
2069 bs2b_clear(device->Bs2b);
2071 bs2b_set_srate(device->Bs2b, device->Frequency);
2072 bs2b_set_level(device->Bs2b, bs2blevel);
2073 TRACE("BS2B enabled\n");
2075 else
2077 free(device->Bs2b);
2078 device->Bs2b = NULL;
2079 TRACE("BS2B disabled\n");
2084 aluInitPanning(device);
2086 /* With HRTF, allocate two extra channels for the post-filter output. */
2087 size = sizeof(device->DryBuffer[0]) * (device->NumChannels + (device->Hrtf ? 2 : 0));
2088 device->DryBuffer = al_calloc(16, size);
2089 if(!device->DryBuffer)
2091 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2092 return ALC_INVALID_DEVICE;
2095 V(device->Synth,update)(device);
2097 SetMixerFPUMode(&oldMode);
2098 V0(device->Backend,lock)();
2099 context = ATOMIC_LOAD(&device->ContextList);
2100 while(context)
2102 ALsizei pos;
2104 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
2105 LockUIntMapRead(&context->EffectSlotMap);
2106 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2108 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
2110 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2112 UnlockUIntMapRead(&context->EffectSlotMap);
2113 V0(device->Backend,unlock)();
2114 RestoreFPUMode(&oldMode);
2115 return ALC_INVALID_DEVICE;
2117 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2118 V(slot->EffectState,update)(device, slot);
2120 UnlockUIntMapRead(&context->EffectSlotMap);
2122 LockUIntMapRead(&context->SourceMap);
2123 for(pos = 0;pos < context->SourceMap.size;pos++)
2125 ALsource *source = context->SourceMap.array[pos].value;
2126 ALuint s = device->NumAuxSends;
2127 while(s < MAX_SENDS)
2129 if(source->Send[s].Slot)
2130 DecrementRef(&source->Send[s].Slot->ref);
2131 source->Send[s].Slot = NULL;
2132 source->Send[s].Gain = 1.0f;
2133 source->Send[s].GainHF = 1.0f;
2134 s++;
2136 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
2138 UnlockUIntMapRead(&context->SourceMap);
2140 for(pos = 0;pos < context->VoiceCount;pos++)
2142 ALvoice *voice = &context->Voices[pos];
2143 ALsource *source = voice->Source;
2144 ALuint s = device->NumAuxSends;
2146 while(s < MAX_SENDS)
2148 voice->Send[s].Moving = AL_FALSE;
2149 voice->Send[s].Counter = 0;
2150 s++;
2153 if(source)
2155 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
2156 voice->Update(voice, source, context);
2160 context = context->next;
2162 if(device->DefaultSlot)
2164 ALeffectslot *slot = device->DefaultSlot;
2166 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2168 V0(device->Backend,unlock)();
2169 RestoreFPUMode(&oldMode);
2170 return ALC_INVALID_DEVICE;
2172 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2173 V(slot->EffectState,update)(device, slot);
2175 V0(device->Backend,unlock)();
2176 RestoreFPUMode(&oldMode);
2178 if(!(device->Flags&DEVICE_PAUSED))
2180 if(V0(device->Backend,start)() == ALC_FALSE)
2181 return ALC_INVALID_DEVICE;
2182 device->Flags |= DEVICE_RUNNING;
2185 return ALC_NO_ERROR;
2188 /* FreeDevice
2190 * Frees the device structure, and destroys any objects the app failed to
2191 * delete. Called once there's no more references on the device.
2193 static ALCvoid FreeDevice(ALCdevice *device)
2195 TRACE("%p\n", device);
2197 V0(device->Backend,close)();
2198 DELETE_OBJ(device->Backend);
2199 device->Backend = NULL;
2201 DELETE_OBJ(device->Synth);
2202 device->Synth = NULL;
2204 if(device->DefaultSlot)
2206 ALeffectState *state = device->DefaultSlot->EffectState;
2207 device->DefaultSlot = NULL;
2208 DELETE_OBJ(state);
2211 if(device->DefaultSfont)
2212 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
2213 device->DefaultSfont = NULL;
2215 if(device->BufferMap.size > 0)
2217 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2218 ReleaseALBuffers(device);
2220 ResetUIntMap(&device->BufferMap);
2222 if(device->EffectMap.size > 0)
2224 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2225 ReleaseALEffects(device);
2227 ResetUIntMap(&device->EffectMap);
2229 if(device->FilterMap.size > 0)
2231 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2232 ReleaseALFilters(device);
2234 ResetUIntMap(&device->FilterMap);
2236 if(device->SfontMap.size > 0)
2238 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2239 ReleaseALSoundfonts(device);
2241 ResetUIntMap(&device->SfontMap);
2243 if(device->PresetMap.size > 0)
2245 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2246 ReleaseALPresets(device);
2248 ResetUIntMap(&device->PresetMap);
2250 if(device->FontsoundMap.size > 0)
2252 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2253 ReleaseALFontsounds(device);
2255 ResetUIntMap(&device->FontsoundMap);
2257 free(device->Bs2b);
2258 device->Bs2b = NULL;
2260 AL_STRING_DEINIT(device->DeviceName);
2262 al_free(device->DryBuffer);
2263 device->DryBuffer = NULL;
2265 al_free(device);
2269 void ALCdevice_IncRef(ALCdevice *device)
2271 uint ref;
2272 ref = IncrementRef(&device->ref);
2273 TRACEREF("%p increasing refcount to %u\n", device, ref);
2276 void ALCdevice_DecRef(ALCdevice *device)
2278 uint ref;
2279 ref = DecrementRef(&device->ref);
2280 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2281 if(ref == 0) FreeDevice(device);
2284 /* VerifyDevice
2286 * Checks if the device handle is valid, and increments its ref count if so.
2288 static ALCdevice *VerifyDevice(ALCdevice *device)
2290 ALCdevice *tmpDevice;
2292 if(!device)
2293 return NULL;
2295 LockLists();
2296 tmpDevice = ATOMIC_LOAD(&DeviceList);
2297 while(tmpDevice && tmpDevice != device)
2298 tmpDevice = tmpDevice->next;
2300 if(tmpDevice)
2301 ALCdevice_IncRef(tmpDevice);
2302 UnlockLists();
2303 return tmpDevice;
2307 /* InitContext
2309 * Initializes context fields
2311 static ALvoid InitContext(ALCcontext *Context)
2313 //Initialise listener
2314 Context->Listener->Gain = 1.0f;
2315 Context->Listener->MetersPerUnit = 1.0f;
2316 aluVectorSet(&Context->Listener->Position, 0.0f, 0.0f, 0.0f, 1.0f);
2317 aluVectorSet(&Context->Listener->Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2318 Context->Listener->Forward[0] = 0.0f;
2319 Context->Listener->Forward[1] = 0.0f;
2320 Context->Listener->Forward[2] = -1.0f;
2321 Context->Listener->Up[0] = 0.0f;
2322 Context->Listener->Up[1] = 1.0f;
2323 Context->Listener->Up[2] = 0.0f;
2324 aluMatrixSet(&Context->Listener->Params.Matrix,
2325 1.0f, 0.0f, 0.0f, 0.0f,
2326 0.0f, 1.0f, 0.0f, 0.0f,
2327 0.0f, 0.0f, 1.0f, 0.0f,
2328 0.0f, 0.0f, 0.0f, 1.0f
2330 aluVectorSet(&Context->Listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2332 //Validate Context
2333 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2334 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2335 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2336 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2338 //Set globals
2339 Context->DistanceModel = DefaultDistanceModel;
2340 Context->SourceDistanceModel = AL_FALSE;
2341 Context->DopplerFactor = 1.0f;
2342 Context->DopplerVelocity = 1.0f;
2343 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2344 Context->DeferUpdates = AL_FALSE;
2346 Context->ExtensionList = alExtList;
2350 /* FreeContext
2352 * Cleans up the context, and destroys any remaining objects the app failed to
2353 * delete. Called once there's no more references on the context.
2355 static void FreeContext(ALCcontext *context)
2357 TRACE("%p\n", context);
2359 if(context->SourceMap.size > 0)
2361 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2362 ReleaseALSources(context);
2364 ResetUIntMap(&context->SourceMap);
2366 if(context->EffectSlotMap.size > 0)
2368 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2369 ReleaseALAuxiliaryEffectSlots(context);
2371 ResetUIntMap(&context->EffectSlotMap);
2373 al_free(context->Voices);
2374 context->Voices = NULL;
2375 context->VoiceCount = 0;
2376 context->MaxVoices = 0;
2378 VECTOR_DEINIT(context->ActiveAuxSlots);
2380 ALCdevice_DecRef(context->Device);
2381 context->Device = NULL;
2383 //Invalidate context
2384 memset(context, 0, sizeof(ALCcontext));
2385 al_free(context);
2388 /* ReleaseContext
2390 * Removes the context reference from the given device and removes it from
2391 * being current on the running thread or globally.
2393 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2395 ALCcontext *nextctx;
2396 ALCcontext *origctx;
2398 if(altss_get(LocalContext) == context)
2400 WARN("%p released while current on thread\n", context);
2401 altss_set(LocalContext, NULL);
2402 ALCcontext_DecRef(context);
2405 origctx = context;
2406 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2407 ALCcontext_DecRef(context);
2409 ALCdevice_Lock(device);
2410 origctx = context;
2411 nextctx = context->next;
2412 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2414 ALCcontext *list;
2415 do {
2416 list = origctx;
2417 origctx = context;
2418 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2420 ALCdevice_Unlock(device);
2422 ALCcontext_DecRef(context);
2425 void ALCcontext_IncRef(ALCcontext *context)
2427 uint ref;
2428 ref = IncrementRef(&context->ref);
2429 TRACEREF("%p increasing refcount to %u\n", context, ref);
2432 void ALCcontext_DecRef(ALCcontext *context)
2434 uint ref;
2435 ref = DecrementRef(&context->ref);
2436 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2437 if(ref == 0) FreeContext(context);
2440 static void ReleaseThreadCtx(void *ptr)
2442 WARN("%p current for thread being destroyed\n", ptr);
2443 ALCcontext_DecRef(ptr);
2446 /* VerifyContext
2448 * Checks that the given context is valid, and increments its reference count.
2450 static ALCcontext *VerifyContext(ALCcontext *context)
2452 ALCdevice *dev;
2454 LockLists();
2455 dev = ATOMIC_LOAD(&DeviceList);
2456 while(dev)
2458 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2459 while(ctx)
2461 if(ctx == context)
2463 ALCcontext_IncRef(ctx);
2464 UnlockLists();
2465 return ctx;
2467 ctx = ctx->next;
2469 dev = dev->next;
2471 UnlockLists();
2473 return NULL;
2477 /* GetContextRef
2479 * Returns the currently active context for this thread, and adds a reference
2480 * without locking it.
2482 ALCcontext *GetContextRef(void)
2484 ALCcontext *context;
2486 context = altss_get(LocalContext);
2487 if(context)
2488 ALCcontext_IncRef(context);
2489 else
2491 LockLists();
2492 context = ATOMIC_LOAD(&GlobalContext);
2493 if(context)
2494 ALCcontext_IncRef(context);
2495 UnlockLists();
2498 return context;
2502 /************************************************
2503 * Standard ALC functions
2504 ************************************************/
2506 /* alcGetError
2508 * Return last ALC generated error code for the given device
2510 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2512 ALCenum errorCode;
2514 if(VerifyDevice(device))
2516 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2517 ALCdevice_DecRef(device);
2519 else
2520 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2522 return errorCode;
2526 /* alcSuspendContext
2528 * Suspends updates for the given context
2530 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2532 if(!SuspendDefers)
2533 return;
2535 context = VerifyContext(context);
2536 if(!context)
2537 alcSetError(NULL, ALC_INVALID_CONTEXT);
2538 else
2540 ALCcontext_DeferUpdates(context);
2541 ALCcontext_DecRef(context);
2545 /* alcProcessContext
2547 * Resumes processing updates for the given context
2549 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2551 if(!SuspendDefers)
2552 return;
2554 context = VerifyContext(context);
2555 if(!context)
2556 alcSetError(NULL, ALC_INVALID_CONTEXT);
2557 else
2559 ALCcontext_ProcessUpdates(context);
2560 ALCcontext_DecRef(context);
2565 /* alcGetString
2567 * Returns information about the device, and error strings
2569 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2571 const ALCchar *value = NULL;
2573 switch(param)
2575 case ALC_NO_ERROR:
2576 value = alcNoError;
2577 break;
2579 case ALC_INVALID_ENUM:
2580 value = alcErrInvalidEnum;
2581 break;
2583 case ALC_INVALID_VALUE:
2584 value = alcErrInvalidValue;
2585 break;
2587 case ALC_INVALID_DEVICE:
2588 value = alcErrInvalidDevice;
2589 break;
2591 case ALC_INVALID_CONTEXT:
2592 value = alcErrInvalidContext;
2593 break;
2595 case ALC_OUT_OF_MEMORY:
2596 value = alcErrOutOfMemory;
2597 break;
2599 case ALC_DEVICE_SPECIFIER:
2600 value = alcDefaultName;
2601 break;
2603 case ALC_ALL_DEVICES_SPECIFIER:
2604 if(VerifyDevice(Device))
2606 value = al_string_get_cstr(Device->DeviceName);
2607 ALCdevice_DecRef(Device);
2609 else
2611 ProbeAllDevicesList();
2612 value = al_string_get_cstr(alcAllDevicesList);
2614 break;
2616 case ALC_CAPTURE_DEVICE_SPECIFIER:
2617 if(VerifyDevice(Device))
2619 value = al_string_get_cstr(Device->DeviceName);
2620 ALCdevice_DecRef(Device);
2622 else
2624 ProbeCaptureDeviceList();
2625 value = al_string_get_cstr(alcCaptureDeviceList);
2627 break;
2629 /* Default devices are always first in the list */
2630 case ALC_DEFAULT_DEVICE_SPECIFIER:
2631 value = alcDefaultName;
2632 break;
2634 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2635 if(al_string_empty(alcAllDevicesList))
2636 ProbeAllDevicesList();
2638 Device = VerifyDevice(Device);
2640 free(alcDefaultAllDevicesSpecifier);
2641 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2642 if(!alcDefaultAllDevicesSpecifier)
2643 alcSetError(Device, ALC_OUT_OF_MEMORY);
2645 value = alcDefaultAllDevicesSpecifier;
2646 if(Device) ALCdevice_DecRef(Device);
2647 break;
2649 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2650 if(al_string_empty(alcCaptureDeviceList))
2651 ProbeCaptureDeviceList();
2653 Device = VerifyDevice(Device);
2655 free(alcCaptureDefaultDeviceSpecifier);
2656 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2657 if(!alcCaptureDefaultDeviceSpecifier)
2658 alcSetError(Device, ALC_OUT_OF_MEMORY);
2660 value = alcCaptureDefaultDeviceSpecifier;
2661 if(Device) ALCdevice_DecRef(Device);
2662 break;
2664 case ALC_EXTENSIONS:
2665 if(!VerifyDevice(Device))
2666 value = alcNoDeviceExtList;
2667 else
2669 value = alcExtensionList;
2670 ALCdevice_DecRef(Device);
2672 break;
2674 default:
2675 Device = VerifyDevice(Device);
2676 alcSetError(Device, ALC_INVALID_ENUM);
2677 if(Device) ALCdevice_DecRef(Device);
2678 break;
2681 return value;
2685 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2687 ALCsizei i;
2689 if(size <= 0 || values == NULL)
2691 alcSetError(device, ALC_INVALID_VALUE);
2692 return 0;
2695 if(!device)
2697 switch(param)
2699 case ALC_MAJOR_VERSION:
2700 values[0] = alcMajorVersion;
2701 return 1;
2702 case ALC_MINOR_VERSION:
2703 values[0] = alcMinorVersion;
2704 return 1;
2706 case ALC_ATTRIBUTES_SIZE:
2707 case ALC_ALL_ATTRIBUTES:
2708 case ALC_FREQUENCY:
2709 case ALC_REFRESH:
2710 case ALC_SYNC:
2711 case ALC_MONO_SOURCES:
2712 case ALC_STEREO_SOURCES:
2713 case ALC_CAPTURE_SAMPLES:
2714 case ALC_FORMAT_CHANNELS_SOFT:
2715 case ALC_FORMAT_TYPE_SOFT:
2716 alcSetError(NULL, ALC_INVALID_DEVICE);
2717 return 0;
2719 default:
2720 alcSetError(NULL, ALC_INVALID_ENUM);
2721 return 0;
2723 return 0;
2726 if(device->Type == Capture)
2728 switch(param)
2730 case ALC_CAPTURE_SAMPLES:
2731 V0(device->Backend,lock)();
2732 values[0] = V0(device->Backend,availableSamples)();
2733 V0(device->Backend,unlock)();
2734 return 1;
2736 case ALC_CONNECTED:
2737 values[0] = device->Connected;
2738 return 1;
2740 default:
2741 alcSetError(device, ALC_INVALID_ENUM);
2742 return 0;
2744 return 0;
2747 /* render device */
2748 switch(param)
2750 case ALC_MAJOR_VERSION:
2751 values[0] = alcMajorVersion;
2752 return 1;
2754 case ALC_MINOR_VERSION:
2755 values[0] = alcMinorVersion;
2756 return 1;
2758 case ALC_EFX_MAJOR_VERSION:
2759 values[0] = alcEFXMajorVersion;
2760 return 1;
2762 case ALC_EFX_MINOR_VERSION:
2763 values[0] = alcEFXMinorVersion;
2764 return 1;
2766 case ALC_ATTRIBUTES_SIZE:
2767 values[0] = 17;
2768 return 1;
2770 case ALC_ALL_ATTRIBUTES:
2771 if(size < 17)
2773 alcSetError(device, ALC_INVALID_VALUE);
2774 return 0;
2777 i = 0;
2778 values[i++] = ALC_FREQUENCY;
2779 values[i++] = device->Frequency;
2781 if(device->Type != Loopback)
2783 values[i++] = ALC_REFRESH;
2784 values[i++] = device->Frequency / device->UpdateSize;
2786 values[i++] = ALC_SYNC;
2787 values[i++] = ALC_FALSE;
2789 else
2791 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2792 values[i++] = device->FmtChans;
2794 values[i++] = ALC_FORMAT_TYPE_SOFT;
2795 values[i++] = device->FmtType;
2798 values[i++] = ALC_MONO_SOURCES;
2799 values[i++] = device->NumMonoSources;
2801 values[i++] = ALC_STEREO_SOURCES;
2802 values[i++] = device->NumStereoSources;
2804 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2805 values[i++] = device->NumAuxSends;
2807 values[i++] = ALC_HRTF_SOFT;
2808 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2810 values[i++] = ALC_HRTF_STATUS_SOFT;
2811 values[i++] = device->Hrtf_Status;
2813 values[i++] = 0;
2814 return i;
2816 case ALC_FREQUENCY:
2817 values[0] = device->Frequency;
2818 return 1;
2820 case ALC_REFRESH:
2821 if(device->Type == Loopback)
2823 alcSetError(device, ALC_INVALID_DEVICE);
2824 return 0;
2826 values[0] = device->Frequency / device->UpdateSize;
2827 return 1;
2829 case ALC_SYNC:
2830 if(device->Type == Loopback)
2832 alcSetError(device, ALC_INVALID_DEVICE);
2833 return 0;
2835 values[0] = ALC_FALSE;
2836 return 1;
2838 case ALC_FORMAT_CHANNELS_SOFT:
2839 if(device->Type != Loopback)
2841 alcSetError(device, ALC_INVALID_DEVICE);
2842 return 0;
2844 values[0] = device->FmtChans;
2845 return 1;
2847 case ALC_FORMAT_TYPE_SOFT:
2848 if(device->Type != Loopback)
2850 alcSetError(device, ALC_INVALID_DEVICE);
2851 return 0;
2853 values[0] = device->FmtType;
2854 return 1;
2856 case ALC_MONO_SOURCES:
2857 values[0] = device->NumMonoSources;
2858 return 1;
2860 case ALC_STEREO_SOURCES:
2861 values[0] = device->NumStereoSources;
2862 return 1;
2864 case ALC_MAX_AUXILIARY_SENDS:
2865 values[0] = device->NumAuxSends;
2866 return 1;
2868 case ALC_CONNECTED:
2869 values[0] = device->Connected;
2870 return 1;
2872 case ALC_HRTF_SOFT:
2873 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2874 return 1;
2876 case ALC_HRTF_STATUS_SOFT:
2877 values[0] = device->Hrtf_Status;
2878 break;
2880 default:
2881 alcSetError(device, ALC_INVALID_ENUM);
2882 return 0;
2884 return 0;
2887 /* alcGetIntegerv
2889 * Returns information about the device and the version of OpenAL
2891 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2893 device = VerifyDevice(device);
2894 if(size <= 0 || values == NULL)
2895 alcSetError(device, ALC_INVALID_VALUE);
2896 else
2897 GetIntegerv(device, param, size, values);
2898 if(device) ALCdevice_DecRef(device);
2901 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2903 ALCint *ivals;
2904 ALsizei i;
2906 device = VerifyDevice(device);
2907 if(size <= 0 || values == NULL)
2908 alcSetError(device, ALC_INVALID_VALUE);
2909 else if(!device || device->Type == Capture)
2911 ivals = malloc(size * sizeof(ALCint));
2912 size = GetIntegerv(device, pname, size, ivals);
2913 for(i = 0;i < size;i++)
2914 values[i] = ivals[i];
2915 free(ivals);
2917 else /* render device */
2919 switch(pname)
2921 case ALC_ATTRIBUTES_SIZE:
2922 *values = 19;
2923 break;
2925 case ALC_ALL_ATTRIBUTES:
2926 if(size < 19)
2927 alcSetError(device, ALC_INVALID_VALUE);
2928 else
2930 int i = 0;
2932 V0(device->Backend,lock)();
2933 values[i++] = ALC_FREQUENCY;
2934 values[i++] = device->Frequency;
2936 if(device->Type != Loopback)
2938 values[i++] = ALC_REFRESH;
2939 values[i++] = device->Frequency / device->UpdateSize;
2941 values[i++] = ALC_SYNC;
2942 values[i++] = ALC_FALSE;
2944 else
2946 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2947 values[i++] = device->FmtChans;
2949 values[i++] = ALC_FORMAT_TYPE_SOFT;
2950 values[i++] = device->FmtType;
2953 values[i++] = ALC_MONO_SOURCES;
2954 values[i++] = device->NumMonoSources;
2956 values[i++] = ALC_STEREO_SOURCES;
2957 values[i++] = device->NumStereoSources;
2959 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2960 values[i++] = device->NumAuxSends;
2962 values[i++] = ALC_HRTF_SOFT;
2963 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2965 values[i++] = ALC_HRTF_STATUS_SOFT;
2966 values[i++] = device->Hrtf_Status;
2968 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2969 values[i++] = device->ClockBase +
2970 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2972 values[i++] = 0;
2973 V0(device->Backend,unlock)();
2975 break;
2977 case ALC_DEVICE_CLOCK_SOFT:
2978 V0(device->Backend,lock)();
2979 *values = device->ClockBase +
2980 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2981 V0(device->Backend,unlock)();
2982 break;
2984 default:
2985 ivals = malloc(size * sizeof(ALCint));
2986 size = GetIntegerv(device, pname, size, ivals);
2987 for(i = 0;i < size;i++)
2988 values[i] = ivals[i];
2989 free(ivals);
2990 break;
2993 if(device)
2994 ALCdevice_DecRef(device);
2998 /* alcIsExtensionPresent
3000 * Determines if there is support for a particular extension
3002 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
3004 ALCboolean bResult = ALC_FALSE;
3006 device = VerifyDevice(device);
3008 if(!extName)
3009 alcSetError(device, ALC_INVALID_VALUE);
3010 else
3012 size_t len = strlen(extName);
3013 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
3014 while(ptr && *ptr)
3016 if(strncasecmp(ptr, extName, len) == 0 &&
3017 (ptr[len] == '\0' || isspace(ptr[len])))
3019 bResult = ALC_TRUE;
3020 break;
3022 if((ptr=strchr(ptr, ' ')) != NULL)
3024 do {
3025 ++ptr;
3026 } while(isspace(*ptr));
3030 if(device)
3031 ALCdevice_DecRef(device);
3032 return bResult;
3036 /* alcGetProcAddress
3038 * Retrieves the function address for a particular extension function
3040 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
3042 ALCvoid *ptr = NULL;
3044 if(!funcName)
3046 device = VerifyDevice(device);
3047 alcSetError(device, ALC_INVALID_VALUE);
3048 if(device) ALCdevice_DecRef(device);
3050 else
3052 ALsizei i = 0;
3053 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
3054 i++;
3055 ptr = alcFunctions[i].address;
3058 return ptr;
3062 /* alcGetEnumValue
3064 * Get the value for a particular ALC enumeration name
3066 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3068 ALCenum val = 0;
3070 if(!enumName)
3072 device = VerifyDevice(device);
3073 alcSetError(device, ALC_INVALID_VALUE);
3074 if(device) ALCdevice_DecRef(device);
3076 else
3078 ALsizei i = 0;
3079 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3080 i++;
3081 val = enumeration[i].value;
3084 return val;
3088 /* alcCreateContext
3090 * Create and attach a context to the given device.
3092 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3094 ALCcontext *ALContext;
3095 ALCenum err;
3097 LockLists();
3098 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
3100 UnlockLists();
3101 alcSetError(device, ALC_INVALID_DEVICE);
3102 if(device) ALCdevice_DecRef(device);
3103 return NULL;
3106 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
3108 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3110 UnlockLists();
3111 alcSetError(device, err);
3112 if(err == ALC_INVALID_DEVICE)
3114 V0(device->Backend,lock)();
3115 aluHandleDisconnect(device);
3116 V0(device->Backend,unlock)();
3118 ALCdevice_DecRef(device);
3119 return NULL;
3122 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3123 if(ALContext)
3125 InitRef(&ALContext->ref, 1);
3126 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3128 VECTOR_INIT(ALContext->ActiveAuxSlots);
3130 ALContext->VoiceCount = 0;
3131 ALContext->MaxVoices = 256;
3132 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3134 if(!ALContext || !ALContext->Voices)
3136 if(!ATOMIC_LOAD(&device->ContextList))
3138 V0(device->Backend,stop)();
3139 device->Flags &= ~DEVICE_RUNNING;
3141 UnlockLists();
3143 if(ALContext)
3145 al_free(ALContext->Voices);
3146 ALContext->Voices = NULL;
3148 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3150 al_free(ALContext);
3151 ALContext = NULL;
3154 alcSetError(device, ALC_OUT_OF_MEMORY);
3155 ALCdevice_DecRef(device);
3156 return NULL;
3159 ALContext->Device = device;
3160 ALCdevice_IncRef(device);
3161 InitContext(ALContext);
3164 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3165 do {
3166 ALContext->next = head;
3167 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3169 UnlockLists();
3171 ALCdevice_DecRef(device);
3173 TRACE("Created context %p\n", ALContext);
3174 return ALContext;
3177 /* alcDestroyContext
3179 * Remove a context from its device
3181 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3183 ALCdevice *Device;
3185 LockLists();
3186 /* alcGetContextsDevice sets an error for invalid contexts */
3187 Device = alcGetContextsDevice(context);
3188 if(Device)
3190 ReleaseContext(context, Device);
3191 if(!ATOMIC_LOAD(&Device->ContextList))
3193 V0(Device->Backend,stop)();
3194 Device->Flags &= ~DEVICE_RUNNING;
3197 UnlockLists();
3201 /* alcGetCurrentContext
3203 * Returns the currently active context on the calling thread
3205 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3207 ALCcontext *Context = altss_get(LocalContext);
3208 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3209 return Context;
3212 /* alcGetThreadContext
3214 * Returns the currently active thread-local context
3216 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3218 return altss_get(LocalContext);
3222 /* alcMakeContextCurrent
3224 * Makes the given context the active process-wide context, and removes the
3225 * thread-local context for the calling thread.
3227 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3229 /* context must be valid or NULL */
3230 if(context && !(context=VerifyContext(context)))
3232 alcSetError(NULL, ALC_INVALID_CONTEXT);
3233 return ALC_FALSE;
3235 /* context's reference count is already incremented */
3236 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3237 if(context) ALCcontext_DecRef(context);
3239 if((context=altss_get(LocalContext)) != NULL)
3241 altss_set(LocalContext, NULL);
3242 ALCcontext_DecRef(context);
3245 return ALC_TRUE;
3248 /* alcSetThreadContext
3250 * Makes the given context the active context for the current thread
3252 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3254 ALCcontext *old;
3256 /* context must be valid or NULL */
3257 if(context && !(context=VerifyContext(context)))
3259 alcSetError(NULL, ALC_INVALID_CONTEXT);
3260 return ALC_FALSE;
3262 /* context's reference count is already incremented */
3263 old = altss_get(LocalContext);
3264 altss_set(LocalContext, context);
3265 if(old) ALCcontext_DecRef(old);
3267 return ALC_TRUE;
3271 /* alcGetContextsDevice
3273 * Returns the device that a particular context is attached to
3275 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3277 ALCdevice *Device;
3279 if(!(Context=VerifyContext(Context)))
3281 alcSetError(NULL, ALC_INVALID_CONTEXT);
3282 return NULL;
3284 Device = Context->Device;
3285 ALCcontext_DecRef(Context);
3287 return Device;
3291 /* alcResetDeviceSOFT
3293 * Resets the given device output, using the specified attribute list.
3295 ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
3297 ALCenum err;
3299 LockLists();
3300 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
3302 UnlockLists();
3303 alcSetError(device, ALC_INVALID_DEVICE);
3304 if(device) ALCdevice_DecRef(device);
3305 return ALC_FALSE;
3308 if((err=UpdateDeviceParams(device, attribs)) != ALC_NO_ERROR)
3310 UnlockLists();
3311 alcSetError(device, err);
3312 if(err == ALC_INVALID_DEVICE)
3314 V0(device->Backend,lock)();
3315 aluHandleDisconnect(device);
3316 V0(device->Backend,unlock)();
3318 ALCdevice_DecRef(device);
3319 return ALC_FALSE;
3321 UnlockLists();
3322 ALCdevice_DecRef(device);
3324 return ALC_TRUE;
3327 /* alcOpenDevice
3329 * Opens the named device.
3331 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3333 const ALCchar *fmt;
3334 ALCdevice *device;
3335 ALCenum err;
3337 DO_INITCONFIG();
3339 if(!PlaybackBackend.name)
3341 alcSetError(NULL, ALC_INVALID_VALUE);
3342 return NULL;
3345 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3346 deviceName = NULL;
3348 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3349 if(!device)
3351 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3352 return NULL;
3355 //Validate device
3356 InitRef(&device->ref, 1);
3357 device->Connected = ALC_TRUE;
3358 device->Type = Playback;
3359 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3361 device->Flags = 0;
3362 device->Bs2b = NULL;
3363 device->Hrtf_Mode = DisabledHrtf;
3364 AL_STRING_INIT(device->DeviceName);
3365 device->DryBuffer = NULL;
3367 ATOMIC_INIT(&device->ContextList, NULL);
3369 device->ClockBase = 0;
3370 device->SamplesDone = 0;
3372 device->MaxNoOfSources = 256;
3373 device->AuxiliaryEffectSlotMax = 4;
3374 device->NumAuxSends = MAX_SENDS;
3376 InitUIntMap(&device->BufferMap, ~0);
3377 InitUIntMap(&device->EffectMap, ~0);
3378 InitUIntMap(&device->FilterMap, ~0);
3379 InitUIntMap(&device->SfontMap, ~0);
3380 InitUIntMap(&device->PresetMap, ~0);
3381 InitUIntMap(&device->FontsoundMap, ~0);
3383 //Set output format
3384 device->FmtChans = DevFmtChannelsDefault;
3385 device->FmtType = DevFmtTypeDefault;
3386 device->Frequency = DEFAULT_OUTPUT_RATE;
3387 device->IsHeadphones = AL_FALSE;
3388 device->NumUpdates = 4;
3389 device->UpdateSize = 1024;
3391 if(!PlaybackBackend.getFactory)
3392 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3393 ALCbackend_Playback);
3394 else
3396 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3397 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3399 if(!device->Backend)
3401 al_free(device);
3402 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3403 return NULL;
3407 if(ConfigValueStr(NULL, "channels", &fmt))
3409 static const struct {
3410 const char name[16];
3411 enum DevFmtChannels chans;
3412 } chanlist[] = {
3413 { "mono", DevFmtMono },
3414 { "stereo", DevFmtStereo },
3415 { "quad", DevFmtQuad },
3416 { "surround51", DevFmtX51 },
3417 { "surround61", DevFmtX61 },
3418 { "surround71", DevFmtX71 },
3419 { "surround51rear", DevFmtX51Rear },
3421 size_t i;
3423 for(i = 0;i < COUNTOF(chanlist);i++)
3425 if(strcasecmp(chanlist[i].name, fmt) == 0)
3427 device->FmtChans = chanlist[i].chans;
3428 device->Flags |= DEVICE_CHANNELS_REQUEST;
3429 break;
3432 if(i == COUNTOF(chanlist))
3433 ERR("Unsupported channels: %s\n", fmt);
3435 if(ConfigValueStr(NULL, "sample-type", &fmt))
3437 static const struct {
3438 const char name[16];
3439 enum DevFmtType type;
3440 } typelist[] = {
3441 { "int8", DevFmtByte },
3442 { "uint8", DevFmtUByte },
3443 { "int16", DevFmtShort },
3444 { "uint16", DevFmtUShort },
3445 { "int32", DevFmtInt },
3446 { "uint32", DevFmtUInt },
3447 { "float32", DevFmtFloat },
3449 size_t i;
3451 for(i = 0;i < COUNTOF(typelist);i++)
3453 if(strcasecmp(typelist[i].name, fmt) == 0)
3455 device->FmtType = typelist[i].type;
3456 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3457 break;
3460 if(i == COUNTOF(typelist))
3461 ERR("Unsupported sample-type: %s\n", fmt);
3464 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3466 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3467 if(device->Frequency < MIN_OUTPUT_RATE)
3468 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3469 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3472 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3473 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3475 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3476 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3477 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3478 device->UpdateSize = (device->UpdateSize+3)&~3;
3480 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3481 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3483 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3484 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3486 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3487 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3489 device->NumStereoSources = 1;
3490 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3492 device->Synth = SynthCreate(device);
3493 if(!device->Synth)
3495 DELETE_OBJ(device->Backend);
3496 al_free(device);
3497 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3498 return NULL;
3501 // Find a playback device to open
3502 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3504 DELETE_OBJ(device->Synth);
3505 DELETE_OBJ(device->Backend);
3506 al_free(device);
3507 alcSetError(NULL, err);
3508 return NULL;
3511 if(DefaultEffect.type != AL_EFFECT_NULL)
3513 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3514 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3516 device->DefaultSlot = NULL;
3517 ERR("Failed to initialize the default effect slot\n");
3519 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3521 ALeffectState *state = device->DefaultSlot->EffectState;
3522 device->DefaultSlot = NULL;
3523 DELETE_OBJ(state);
3524 ERR("Failed to initialize the default effect\n");
3529 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3530 do {
3531 device->next = head;
3532 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3535 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3536 return device;
3539 /* alcCloseDevice
3541 * Closes the given device.
3543 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3545 ALCdevice *list, *origdev, *nextdev;
3546 ALCcontext *ctx;
3548 LockLists();
3549 list = ATOMIC_LOAD(&DeviceList);
3550 do {
3551 if(list == device)
3552 break;
3553 } while((list=list->next) != NULL);
3554 if(!list || list->Type == Capture)
3556 alcSetError(list, ALC_INVALID_DEVICE);
3557 UnlockLists();
3558 return ALC_FALSE;
3561 origdev = device;
3562 nextdev = device->next;
3563 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3565 do {
3566 list = origdev;
3567 origdev = device;
3568 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3570 UnlockLists();
3572 ctx = ATOMIC_LOAD(&device->ContextList);
3573 while(ctx != NULL)
3575 ALCcontext *next = ctx->next;
3576 WARN("Releasing context %p\n", ctx);
3577 ReleaseContext(ctx, device);
3578 ctx = next;
3580 if((device->Flags&DEVICE_RUNNING))
3581 V0(device->Backend,stop)();
3582 device->Flags &= ~DEVICE_RUNNING;
3584 ALCdevice_DecRef(device);
3586 return ALC_TRUE;
3590 /************************************************
3591 * ALC capture functions
3592 ************************************************/
3593 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3595 ALCdevice *device = NULL;
3596 ALCenum err;
3598 DO_INITCONFIG();
3600 if(!CaptureBackend.name)
3602 alcSetError(NULL, ALC_INVALID_VALUE);
3603 return NULL;
3606 if(samples <= 0)
3608 alcSetError(NULL, ALC_INVALID_VALUE);
3609 return NULL;
3612 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3613 deviceName = NULL;
3615 device = al_calloc(16, sizeof(ALCdevice));
3616 if(!device)
3618 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3619 return NULL;
3622 //Validate device
3623 InitRef(&device->ref, 1);
3624 device->Connected = ALC_TRUE;
3625 device->Type = Capture;
3627 AL_STRING_INIT(device->DeviceName);
3628 device->DryBuffer = NULL;
3630 InitUIntMap(&device->BufferMap, ~0);
3631 InitUIntMap(&device->EffectMap, ~0);
3632 InitUIntMap(&device->FilterMap, ~0);
3633 InitUIntMap(&device->SfontMap, ~0);
3634 InitUIntMap(&device->PresetMap, ~0);
3635 InitUIntMap(&device->FontsoundMap, ~0);
3637 if(!CaptureBackend.getFactory)
3638 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3639 ALCbackend_Capture);
3640 else
3642 ALCbackendFactory *factory = CaptureBackend.getFactory();
3643 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3645 if(!device->Backend)
3647 al_free(device);
3648 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3649 return NULL;
3652 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3653 device->Frequency = frequency;
3655 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3656 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3658 al_free(device);
3659 alcSetError(NULL, ALC_INVALID_ENUM);
3660 return NULL;
3662 device->IsHeadphones = AL_FALSE;
3664 device->UpdateSize = samples;
3665 device->NumUpdates = 1;
3667 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3669 al_free(device);
3670 alcSetError(NULL, err);
3671 return NULL;
3675 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3676 do {
3677 device->next = head;
3678 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3681 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3682 return device;
3685 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3687 ALCdevice *list, *next, *nextdev;
3689 LockLists();
3690 list = ATOMIC_LOAD(&DeviceList);
3691 do {
3692 if(list == device)
3693 break;
3694 } while((list=list->next) != NULL);
3695 if(!list || list->Type != Capture)
3697 alcSetError(list, ALC_INVALID_DEVICE);
3698 UnlockLists();
3699 return ALC_FALSE;
3702 next = device;
3703 nextdev = device->next;
3704 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3706 do {
3707 list = next;
3708 next = device;
3709 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3711 UnlockLists();
3713 ALCdevice_DecRef(device);
3715 return ALC_TRUE;
3718 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3720 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3721 alcSetError(device, ALC_INVALID_DEVICE);
3722 else
3724 V0(device->Backend,lock)();
3725 if(!device->Connected)
3726 alcSetError(device, ALC_INVALID_DEVICE);
3727 else if(!(device->Flags&DEVICE_RUNNING))
3729 if(V0(device->Backend,start)())
3730 device->Flags |= DEVICE_RUNNING;
3731 else
3733 aluHandleDisconnect(device);
3734 alcSetError(device, ALC_INVALID_DEVICE);
3737 V0(device->Backend,unlock)();
3740 if(device) ALCdevice_DecRef(device);
3743 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3745 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3746 alcSetError(device, ALC_INVALID_DEVICE);
3747 else
3749 V0(device->Backend,lock)();
3750 if((device->Flags&DEVICE_RUNNING))
3751 V0(device->Backend,stop)();
3752 device->Flags &= ~DEVICE_RUNNING;
3753 V0(device->Backend,unlock)();
3756 if(device) ALCdevice_DecRef(device);
3759 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3761 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3762 alcSetError(device, ALC_INVALID_DEVICE);
3763 else
3765 ALCenum err = ALC_INVALID_VALUE;
3767 V0(device->Backend,lock)();
3768 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3769 err = V(device->Backend,captureSamples)(buffer, samples);
3770 V0(device->Backend,unlock)();
3772 if(err != ALC_NO_ERROR)
3773 alcSetError(device, err);
3775 if(device) ALCdevice_DecRef(device);
3779 /************************************************
3780 * ALC loopback functions
3781 ************************************************/
3783 /* alcLoopbackOpenDeviceSOFT
3785 * Open a loopback device, for manual rendering.
3787 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3789 ALCbackendFactory *factory;
3790 ALCdevice *device;
3792 DO_INITCONFIG();
3794 /* Make sure the device name, if specified, is us. */
3795 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3797 alcSetError(NULL, ALC_INVALID_VALUE);
3798 return NULL;
3801 device = al_calloc(16, sizeof(ALCdevice));
3802 if(!device)
3804 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3805 return NULL;
3808 //Validate device
3809 InitRef(&device->ref, 1);
3810 device->Connected = ALC_TRUE;
3811 device->Type = Loopback;
3812 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3814 device->Flags = 0;
3815 device->Bs2b = NULL;
3816 device->Hrtf_Mode = DisabledHrtf;
3817 AL_STRING_INIT(device->DeviceName);
3818 device->DryBuffer = NULL;
3820 ATOMIC_INIT(&device->ContextList, NULL);
3822 device->ClockBase = 0;
3823 device->SamplesDone = 0;
3825 device->MaxNoOfSources = 256;
3826 device->AuxiliaryEffectSlotMax = 4;
3827 device->NumAuxSends = MAX_SENDS;
3829 InitUIntMap(&device->BufferMap, ~0);
3830 InitUIntMap(&device->EffectMap, ~0);
3831 InitUIntMap(&device->FilterMap, ~0);
3832 InitUIntMap(&device->SfontMap, ~0);
3833 InitUIntMap(&device->PresetMap, ~0);
3834 InitUIntMap(&device->FontsoundMap, ~0);
3836 factory = ALCloopbackFactory_getFactory();
3837 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3838 if(!device->Backend)
3840 al_free(device);
3841 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3842 return NULL;
3845 //Set output format
3846 device->NumUpdates = 0;
3847 device->UpdateSize = 0;
3849 device->Frequency = DEFAULT_OUTPUT_RATE;
3850 device->FmtChans = DevFmtChannelsDefault;
3851 device->FmtType = DevFmtTypeDefault;
3852 device->IsHeadphones = AL_FALSE;
3854 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3855 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3857 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3858 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3860 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3861 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3863 device->NumStereoSources = 1;
3864 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3866 device->Synth = SynthCreate(device);
3867 if(!device->Synth)
3869 DELETE_OBJ(device->Backend);
3870 al_free(device);
3871 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3872 return NULL;
3875 // Open the "backend"
3876 V(device->Backend,open)("Loopback");
3879 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3880 do {
3881 device->next = head;
3882 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3885 TRACE("Created device %p\n", device);
3886 return device;
3889 /* alcIsRenderFormatSupportedSOFT
3891 * Determines if the loopback device supports the given format for rendering.
3893 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3895 ALCboolean ret = ALC_FALSE;
3897 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3898 alcSetError(device, ALC_INVALID_DEVICE);
3899 else if(freq <= 0)
3900 alcSetError(device, ALC_INVALID_VALUE);
3901 else
3903 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3904 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3905 freq >= MIN_OUTPUT_RATE)
3906 ret = ALC_TRUE;
3908 if(device) ALCdevice_DecRef(device);
3910 return ret;
3913 /* alcRenderSamplesSOFT
3915 * Renders some samples into a buffer, using the format last set by the
3916 * attributes given to alcCreateContext.
3918 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3920 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3921 alcSetError(device, ALC_INVALID_DEVICE);
3922 else if(samples < 0 || (samples > 0 && buffer == NULL))
3923 alcSetError(device, ALC_INVALID_VALUE);
3924 else
3925 aluMixData(device, buffer, samples);
3926 if(device) ALCdevice_DecRef(device);
3930 /************************************************
3931 * ALC DSP pause/resume functions
3932 ************************************************/
3934 /* alcDevicePauseSOFT
3936 * Pause the DSP to stop audio processing.
3938 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3940 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3941 alcSetError(device, ALC_INVALID_DEVICE);
3942 else
3944 LockLists();
3945 if((device->Flags&DEVICE_RUNNING))
3946 V0(device->Backend,stop)();
3947 device->Flags &= ~DEVICE_RUNNING;
3948 device->Flags |= DEVICE_PAUSED;
3949 UnlockLists();
3951 if(device) ALCdevice_DecRef(device);
3954 /* alcDeviceResumeSOFT
3956 * Resume the DSP to restart audio processing.
3958 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3960 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3961 alcSetError(device, ALC_INVALID_DEVICE);
3962 else
3964 LockLists();
3965 if((device->Flags&DEVICE_PAUSED))
3967 device->Flags &= ~DEVICE_PAUSED;
3968 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3970 if(V0(device->Backend,start)() != ALC_FALSE)
3971 device->Flags |= DEVICE_RUNNING;
3972 else
3974 alcSetError(device, ALC_INVALID_DEVICE);
3975 V0(device->Backend,lock)();
3976 aluHandleDisconnect(device);
3977 V0(device->Backend,unlock)();
3981 UnlockLists();
3983 if(device) ALCdevice_DecRef(device);