Add preliminary AL_EXT_BFORMAT support
[openal-soft.git] / Alc / ALc.c
blob7763f501939ddbd872889fbda2cafb3e398768c7
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_PULSEAUDIO
65 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_ALSA
68 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_COREAUDIO
71 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
72 #endif
73 #ifdef HAVE_OSS
74 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
75 #endif
76 #ifdef HAVE_SOLARIS
77 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SNDIO
80 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_QSA
83 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_MMDEVAPI
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
87 #endif
88 #ifdef HAVE_DSOUND
89 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_WINMM
92 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
93 #endif
94 #ifdef HAVE_PORTAUDIO
95 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
96 #endif
97 #ifdef HAVE_OPENSL
98 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
99 #endif
101 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
102 #ifdef HAVE_WAVE
103 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #endif
106 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
108 #undef EmptyFuncs
110 static struct BackendInfo PlaybackBackend;
111 static struct BackendInfo CaptureBackend;
114 /************************************************
115 * Functions, enums, and errors
116 ************************************************/
117 typedef struct ALCfunction {
118 const ALCchar *funcName;
119 ALCvoid *address;
120 } ALCfunction;
122 typedef struct ALCenums {
123 const ALCchar *enumName;
124 ALCenum value;
125 } ALCenums;
127 #define DECL(x) { #x, (ALCvoid*)(x) }
128 static const ALCfunction alcFunctions[] = {
129 DECL(alcCreateContext),
130 DECL(alcMakeContextCurrent),
131 DECL(alcProcessContext),
132 DECL(alcSuspendContext),
133 DECL(alcDestroyContext),
134 DECL(alcGetCurrentContext),
135 DECL(alcGetContextsDevice),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
143 DECL(alcGetIntegerv),
144 DECL(alcCaptureOpenDevice),
145 DECL(alcCaptureCloseDevice),
146 DECL(alcCaptureStart),
147 DECL(alcCaptureStop),
148 DECL(alcCaptureSamples),
150 DECL(alcSetThreadContext),
151 DECL(alcGetThreadContext),
153 DECL(alcLoopbackOpenDeviceSOFT),
154 DECL(alcIsRenderFormatSupportedSOFT),
155 DECL(alcRenderSamplesSOFT),
157 DECL(alcDevicePauseSOFT),
158 DECL(alcDeviceResumeSOFT),
160 DECL(alcGetInteger64vSOFT),
162 DECL(alEnable),
163 DECL(alDisable),
164 DECL(alIsEnabled),
165 DECL(alGetString),
166 DECL(alGetBooleanv),
167 DECL(alGetIntegerv),
168 DECL(alGetFloatv),
169 DECL(alGetDoublev),
170 DECL(alGetBoolean),
171 DECL(alGetInteger),
172 DECL(alGetFloat),
173 DECL(alGetDouble),
174 DECL(alGetError),
175 DECL(alIsExtensionPresent),
176 DECL(alGetProcAddress),
177 DECL(alGetEnumValue),
178 DECL(alListenerf),
179 DECL(alListener3f),
180 DECL(alListenerfv),
181 DECL(alListeneri),
182 DECL(alListener3i),
183 DECL(alListeneriv),
184 DECL(alGetListenerf),
185 DECL(alGetListener3f),
186 DECL(alGetListenerfv),
187 DECL(alGetListeneri),
188 DECL(alGetListener3i),
189 DECL(alGetListeneriv),
190 DECL(alGenSources),
191 DECL(alDeleteSources),
192 DECL(alIsSource),
193 DECL(alSourcef),
194 DECL(alSource3f),
195 DECL(alSourcefv),
196 DECL(alSourcei),
197 DECL(alSource3i),
198 DECL(alSourceiv),
199 DECL(alGetSourcef),
200 DECL(alGetSource3f),
201 DECL(alGetSourcefv),
202 DECL(alGetSourcei),
203 DECL(alGetSource3i),
204 DECL(alGetSourceiv),
205 DECL(alSourcePlayv),
206 DECL(alSourceStopv),
207 DECL(alSourceRewindv),
208 DECL(alSourcePausev),
209 DECL(alSourcePlay),
210 DECL(alSourceStop),
211 DECL(alSourceRewind),
212 DECL(alSourcePause),
213 DECL(alSourceQueueBuffers),
214 DECL(alSourceUnqueueBuffers),
215 DECL(alGenBuffers),
216 DECL(alDeleteBuffers),
217 DECL(alIsBuffer),
218 DECL(alBufferData),
219 DECL(alBufferf),
220 DECL(alBuffer3f),
221 DECL(alBufferfv),
222 DECL(alBufferi),
223 DECL(alBuffer3i),
224 DECL(alBufferiv),
225 DECL(alGetBufferf),
226 DECL(alGetBuffer3f),
227 DECL(alGetBufferfv),
228 DECL(alGetBufferi),
229 DECL(alGetBuffer3i),
230 DECL(alGetBufferiv),
231 DECL(alDopplerFactor),
232 DECL(alDopplerVelocity),
233 DECL(alSpeedOfSound),
234 DECL(alDistanceModel),
236 DECL(alGenFilters),
237 DECL(alDeleteFilters),
238 DECL(alIsFilter),
239 DECL(alFilteri),
240 DECL(alFilteriv),
241 DECL(alFilterf),
242 DECL(alFilterfv),
243 DECL(alGetFilteri),
244 DECL(alGetFilteriv),
245 DECL(alGetFilterf),
246 DECL(alGetFilterfv),
247 DECL(alGenEffects),
248 DECL(alDeleteEffects),
249 DECL(alIsEffect),
250 DECL(alEffecti),
251 DECL(alEffectiv),
252 DECL(alEffectf),
253 DECL(alEffectfv),
254 DECL(alGetEffecti),
255 DECL(alGetEffectiv),
256 DECL(alGetEffectf),
257 DECL(alGetEffectfv),
258 DECL(alGenAuxiliaryEffectSlots),
259 DECL(alDeleteAuxiliaryEffectSlots),
260 DECL(alIsAuxiliaryEffectSlot),
261 DECL(alAuxiliaryEffectSloti),
262 DECL(alAuxiliaryEffectSlotiv),
263 DECL(alAuxiliaryEffectSlotf),
264 DECL(alAuxiliaryEffectSlotfv),
265 DECL(alGetAuxiliaryEffectSloti),
266 DECL(alGetAuxiliaryEffectSlotiv),
267 DECL(alGetAuxiliaryEffectSlotf),
268 DECL(alGetAuxiliaryEffectSlotfv),
270 DECL(alBufferSubDataSOFT),
272 DECL(alBufferSamplesSOFT),
273 DECL(alBufferSubSamplesSOFT),
274 DECL(alGetBufferSamplesSOFT),
275 DECL(alIsBufferFormatSupportedSOFT),
277 DECL(alDeferUpdatesSOFT),
278 DECL(alProcessUpdatesSOFT),
280 DECL(alSourcedSOFT),
281 DECL(alSource3dSOFT),
282 DECL(alSourcedvSOFT),
283 DECL(alGetSourcedSOFT),
284 DECL(alGetSource3dSOFT),
285 DECL(alGetSourcedvSOFT),
286 DECL(alSourcei64SOFT),
287 DECL(alSource3i64SOFT),
288 DECL(alSourcei64vSOFT),
289 DECL(alGetSourcei64SOFT),
290 DECL(alGetSource3i64SOFT),
291 DECL(alGetSourcei64vSOFT),
293 DECL(alGenSoundfontsSOFT),
294 DECL(alDeleteSoundfontsSOFT),
295 DECL(alIsSoundfontSOFT),
296 DECL(alGetSoundfontivSOFT),
297 DECL(alSoundfontPresetsSOFT),
298 DECL(alGenPresetsSOFT),
299 DECL(alDeletePresetsSOFT),
300 DECL(alIsPresetSOFT),
301 DECL(alPresetiSOFT),
302 DECL(alPresetivSOFT),
303 DECL(alGetPresetivSOFT),
304 DECL(alPresetFontsoundsSOFT),
305 DECL(alGenFontsoundsSOFT),
306 DECL(alDeleteFontsoundsSOFT),
307 DECL(alIsFontsoundSOFT),
308 DECL(alFontsoundiSOFT),
309 DECL(alFontsound2iSOFT),
310 DECL(alFontsoundivSOFT),
311 DECL(alGetFontsoundivSOFT),
312 DECL(alFontsoundModulatoriSOFT),
313 DECL(alGetFontsoundModulatorivSOFT),
314 DECL(alMidiSoundfontSOFT),
315 DECL(alMidiSoundfontvSOFT),
316 DECL(alMidiEventSOFT),
317 DECL(alMidiSysExSOFT),
318 DECL(alMidiPlaySOFT),
319 DECL(alMidiPauseSOFT),
320 DECL(alMidiStopSOFT),
321 DECL(alMidiResetSOFT),
322 DECL(alMidiGainSOFT),
323 DECL(alGetInteger64SOFT),
324 DECL(alGetInteger64vSOFT),
325 DECL(alLoadSoundfontSOFT),
327 { NULL, NULL }
329 #undef DECL
331 #define DECL(x) { #x, (x) }
332 static const ALCenums enumeration[] = {
333 DECL(ALC_INVALID),
334 DECL(ALC_FALSE),
335 DECL(ALC_TRUE),
337 DECL(ALC_MAJOR_VERSION),
338 DECL(ALC_MINOR_VERSION),
339 DECL(ALC_ATTRIBUTES_SIZE),
340 DECL(ALC_ALL_ATTRIBUTES),
341 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
342 DECL(ALC_DEVICE_SPECIFIER),
343 DECL(ALC_ALL_DEVICES_SPECIFIER),
344 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
345 DECL(ALC_EXTENSIONS),
346 DECL(ALC_FREQUENCY),
347 DECL(ALC_REFRESH),
348 DECL(ALC_SYNC),
349 DECL(ALC_MONO_SOURCES),
350 DECL(ALC_STEREO_SOURCES),
351 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
352 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
353 DECL(ALC_CAPTURE_SAMPLES),
354 DECL(ALC_CONNECTED),
356 DECL(ALC_EFX_MAJOR_VERSION),
357 DECL(ALC_EFX_MINOR_VERSION),
358 DECL(ALC_MAX_AUXILIARY_SENDS),
360 DECL(ALC_FORMAT_CHANNELS_SOFT),
361 DECL(ALC_FORMAT_TYPE_SOFT),
363 DECL(ALC_MONO_SOFT),
364 DECL(ALC_STEREO_SOFT),
365 DECL(ALC_QUAD_SOFT),
366 DECL(ALC_5POINT1_SOFT),
367 DECL(ALC_6POINT1_SOFT),
368 DECL(ALC_7POINT1_SOFT),
370 DECL(ALC_BYTE_SOFT),
371 DECL(ALC_UNSIGNED_BYTE_SOFT),
372 DECL(ALC_SHORT_SOFT),
373 DECL(ALC_UNSIGNED_SHORT_SOFT),
374 DECL(ALC_INT_SOFT),
375 DECL(ALC_UNSIGNED_INT_SOFT),
376 DECL(ALC_FLOAT_SOFT),
378 DECL(ALC_NO_ERROR),
379 DECL(ALC_INVALID_DEVICE),
380 DECL(ALC_INVALID_CONTEXT),
381 DECL(ALC_INVALID_ENUM),
382 DECL(ALC_INVALID_VALUE),
383 DECL(ALC_OUT_OF_MEMORY),
386 DECL(AL_INVALID),
387 DECL(AL_NONE),
388 DECL(AL_FALSE),
389 DECL(AL_TRUE),
391 DECL(AL_SOURCE_RELATIVE),
392 DECL(AL_CONE_INNER_ANGLE),
393 DECL(AL_CONE_OUTER_ANGLE),
394 DECL(AL_PITCH),
395 DECL(AL_POSITION),
396 DECL(AL_DIRECTION),
397 DECL(AL_VELOCITY),
398 DECL(AL_LOOPING),
399 DECL(AL_BUFFER),
400 DECL(AL_GAIN),
401 DECL(AL_MIN_GAIN),
402 DECL(AL_MAX_GAIN),
403 DECL(AL_ORIENTATION),
404 DECL(AL_REFERENCE_DISTANCE),
405 DECL(AL_ROLLOFF_FACTOR),
406 DECL(AL_CONE_OUTER_GAIN),
407 DECL(AL_MAX_DISTANCE),
408 DECL(AL_SEC_OFFSET),
409 DECL(AL_SAMPLE_OFFSET),
410 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
411 DECL(AL_BYTE_OFFSET),
412 DECL(AL_BYTE_RW_OFFSETS_SOFT),
413 DECL(AL_SOURCE_TYPE),
414 DECL(AL_STATIC),
415 DECL(AL_STREAMING),
416 DECL(AL_UNDETERMINED),
417 DECL(AL_METERS_PER_UNIT),
418 DECL(AL_DIRECT_CHANNELS_SOFT),
420 DECL(AL_DIRECT_FILTER),
421 DECL(AL_AUXILIARY_SEND_FILTER),
422 DECL(AL_AIR_ABSORPTION_FACTOR),
423 DECL(AL_ROOM_ROLLOFF_FACTOR),
424 DECL(AL_CONE_OUTER_GAINHF),
425 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
426 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
427 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
429 DECL(AL_SOURCE_STATE),
430 DECL(AL_INITIAL),
431 DECL(AL_PLAYING),
432 DECL(AL_PAUSED),
433 DECL(AL_STOPPED),
435 DECL(AL_BUFFERS_QUEUED),
436 DECL(AL_BUFFERS_PROCESSED),
438 DECL(AL_FORMAT_MONO8),
439 DECL(AL_FORMAT_MONO16),
440 DECL(AL_FORMAT_MONO_FLOAT32),
441 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
442 DECL(AL_FORMAT_STEREO8),
443 DECL(AL_FORMAT_STEREO16),
444 DECL(AL_FORMAT_STEREO_FLOAT32),
445 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
446 DECL(AL_FORMAT_MONO_IMA4),
447 DECL(AL_FORMAT_STEREO_IMA4),
448 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
449 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
450 DECL(AL_FORMAT_QUAD8_LOKI),
451 DECL(AL_FORMAT_QUAD16_LOKI),
452 DECL(AL_FORMAT_QUAD8),
453 DECL(AL_FORMAT_QUAD16),
454 DECL(AL_FORMAT_QUAD32),
455 DECL(AL_FORMAT_51CHN8),
456 DECL(AL_FORMAT_51CHN16),
457 DECL(AL_FORMAT_51CHN32),
458 DECL(AL_FORMAT_61CHN8),
459 DECL(AL_FORMAT_61CHN16),
460 DECL(AL_FORMAT_61CHN32),
461 DECL(AL_FORMAT_71CHN8),
462 DECL(AL_FORMAT_71CHN16),
463 DECL(AL_FORMAT_71CHN32),
464 DECL(AL_FORMAT_REAR8),
465 DECL(AL_FORMAT_REAR16),
466 DECL(AL_FORMAT_REAR32),
467 DECL(AL_FORMAT_MONO_MULAW),
468 DECL(AL_FORMAT_MONO_MULAW_EXT),
469 DECL(AL_FORMAT_STEREO_MULAW),
470 DECL(AL_FORMAT_STEREO_MULAW_EXT),
471 DECL(AL_FORMAT_QUAD_MULAW),
472 DECL(AL_FORMAT_51CHN_MULAW),
473 DECL(AL_FORMAT_61CHN_MULAW),
474 DECL(AL_FORMAT_71CHN_MULAW),
475 DECL(AL_FORMAT_REAR_MULAW),
476 DECL(AL_FORMAT_MONO_ALAW_EXT),
477 DECL(AL_FORMAT_STEREO_ALAW_EXT),
479 DECL(AL_MONO8_SOFT),
480 DECL(AL_MONO16_SOFT),
481 DECL(AL_MONO32F_SOFT),
482 DECL(AL_STEREO8_SOFT),
483 DECL(AL_STEREO16_SOFT),
484 DECL(AL_STEREO32F_SOFT),
485 DECL(AL_QUAD8_SOFT),
486 DECL(AL_QUAD16_SOFT),
487 DECL(AL_QUAD32F_SOFT),
488 DECL(AL_REAR8_SOFT),
489 DECL(AL_REAR16_SOFT),
490 DECL(AL_REAR32F_SOFT),
491 DECL(AL_5POINT1_8_SOFT),
492 DECL(AL_5POINT1_16_SOFT),
493 DECL(AL_5POINT1_32F_SOFT),
494 DECL(AL_6POINT1_8_SOFT),
495 DECL(AL_6POINT1_16_SOFT),
496 DECL(AL_6POINT1_32F_SOFT),
497 DECL(AL_7POINT1_8_SOFT),
498 DECL(AL_7POINT1_16_SOFT),
499 DECL(AL_7POINT1_32F_SOFT),
500 DECL(AL_FORMAT_BFORMAT2D_8),
501 DECL(AL_FORMAT_BFORMAT2D_16),
502 DECL(AL_FORMAT_BFORMAT2D_FLOAT32),
503 DECL(AL_FORMAT_BFORMAT3D_8),
504 DECL(AL_FORMAT_BFORMAT3D_16),
505 DECL(AL_FORMAT_BFORMAT3D_FLOAT32),
507 DECL(AL_MONO_SOFT),
508 DECL(AL_STEREO_SOFT),
509 DECL(AL_QUAD_SOFT),
510 DECL(AL_REAR_SOFT),
511 DECL(AL_5POINT1_SOFT),
512 DECL(AL_6POINT1_SOFT),
513 DECL(AL_7POINT1_SOFT),
515 DECL(AL_BYTE_SOFT),
516 DECL(AL_UNSIGNED_BYTE_SOFT),
517 DECL(AL_SHORT_SOFT),
518 DECL(AL_UNSIGNED_SHORT_SOFT),
519 DECL(AL_INT_SOFT),
520 DECL(AL_UNSIGNED_INT_SOFT),
521 DECL(AL_FLOAT_SOFT),
522 DECL(AL_DOUBLE_SOFT),
523 DECL(AL_BYTE3_SOFT),
524 DECL(AL_UNSIGNED_BYTE3_SOFT),
526 DECL(AL_FREQUENCY),
527 DECL(AL_BITS),
528 DECL(AL_CHANNELS),
529 DECL(AL_SIZE),
530 DECL(AL_INTERNAL_FORMAT_SOFT),
531 DECL(AL_BYTE_LENGTH_SOFT),
532 DECL(AL_SAMPLE_LENGTH_SOFT),
533 DECL(AL_SEC_LENGTH_SOFT),
534 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
535 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
537 DECL(AL_UNUSED),
538 DECL(AL_PENDING),
539 DECL(AL_PROCESSED),
541 DECL(AL_NO_ERROR),
542 DECL(AL_INVALID_NAME),
543 DECL(AL_INVALID_ENUM),
544 DECL(AL_INVALID_VALUE),
545 DECL(AL_INVALID_OPERATION),
546 DECL(AL_OUT_OF_MEMORY),
548 DECL(AL_VENDOR),
549 DECL(AL_VERSION),
550 DECL(AL_RENDERER),
551 DECL(AL_EXTENSIONS),
553 DECL(AL_DOPPLER_FACTOR),
554 DECL(AL_DOPPLER_VELOCITY),
555 DECL(AL_DISTANCE_MODEL),
556 DECL(AL_SPEED_OF_SOUND),
557 DECL(AL_SOURCE_DISTANCE_MODEL),
558 DECL(AL_DEFERRED_UPDATES_SOFT),
560 DECL(AL_INVERSE_DISTANCE),
561 DECL(AL_INVERSE_DISTANCE_CLAMPED),
562 DECL(AL_LINEAR_DISTANCE),
563 DECL(AL_LINEAR_DISTANCE_CLAMPED),
564 DECL(AL_EXPONENT_DISTANCE),
565 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
567 DECL(AL_FILTER_TYPE),
568 DECL(AL_FILTER_NULL),
569 DECL(AL_FILTER_LOWPASS),
570 DECL(AL_FILTER_HIGHPASS),
571 DECL(AL_FILTER_BANDPASS),
573 DECL(AL_LOWPASS_GAIN),
574 DECL(AL_LOWPASS_GAINHF),
576 DECL(AL_HIGHPASS_GAIN),
577 DECL(AL_HIGHPASS_GAINLF),
579 DECL(AL_BANDPASS_GAIN),
580 DECL(AL_BANDPASS_GAINHF),
581 DECL(AL_BANDPASS_GAINLF),
583 DECL(AL_EFFECT_TYPE),
584 DECL(AL_EFFECT_NULL),
585 DECL(AL_EFFECT_REVERB),
586 DECL(AL_EFFECT_EAXREVERB),
587 DECL(AL_EFFECT_CHORUS),
588 DECL(AL_EFFECT_DISTORTION),
589 DECL(AL_EFFECT_ECHO),
590 DECL(AL_EFFECT_FLANGER),
591 #if 0
592 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
593 DECL(AL_EFFECT_VOCAL_MORPHER),
594 DECL(AL_EFFECT_PITCH_SHIFTER),
595 #endif
596 DECL(AL_EFFECT_RING_MODULATOR),
597 #if 0
598 DECL(AL_EFFECT_AUTOWAH),
599 #endif
600 DECL(AL_EFFECT_COMPRESSOR),
601 DECL(AL_EFFECT_EQUALIZER),
602 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
603 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
605 DECL(AL_EAXREVERB_DENSITY),
606 DECL(AL_EAXREVERB_DIFFUSION),
607 DECL(AL_EAXREVERB_GAIN),
608 DECL(AL_EAXREVERB_GAINHF),
609 DECL(AL_EAXREVERB_GAINLF),
610 DECL(AL_EAXREVERB_DECAY_TIME),
611 DECL(AL_EAXREVERB_DECAY_HFRATIO),
612 DECL(AL_EAXREVERB_DECAY_LFRATIO),
613 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
614 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
615 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
616 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
617 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
618 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
619 DECL(AL_EAXREVERB_ECHO_TIME),
620 DECL(AL_EAXREVERB_ECHO_DEPTH),
621 DECL(AL_EAXREVERB_MODULATION_TIME),
622 DECL(AL_EAXREVERB_MODULATION_DEPTH),
623 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
624 DECL(AL_EAXREVERB_HFREFERENCE),
625 DECL(AL_EAXREVERB_LFREFERENCE),
626 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
627 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
629 DECL(AL_REVERB_DENSITY),
630 DECL(AL_REVERB_DIFFUSION),
631 DECL(AL_REVERB_GAIN),
632 DECL(AL_REVERB_GAINHF),
633 DECL(AL_REVERB_DECAY_TIME),
634 DECL(AL_REVERB_DECAY_HFRATIO),
635 DECL(AL_REVERB_REFLECTIONS_GAIN),
636 DECL(AL_REVERB_REFLECTIONS_DELAY),
637 DECL(AL_REVERB_LATE_REVERB_GAIN),
638 DECL(AL_REVERB_LATE_REVERB_DELAY),
639 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
640 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
641 DECL(AL_REVERB_DECAY_HFLIMIT),
643 DECL(AL_CHORUS_WAVEFORM),
644 DECL(AL_CHORUS_PHASE),
645 DECL(AL_CHORUS_RATE),
646 DECL(AL_CHORUS_DEPTH),
647 DECL(AL_CHORUS_FEEDBACK),
648 DECL(AL_CHORUS_DELAY),
650 DECL(AL_DISTORTION_EDGE),
651 DECL(AL_DISTORTION_GAIN),
652 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
653 DECL(AL_DISTORTION_EQCENTER),
654 DECL(AL_DISTORTION_EQBANDWIDTH),
656 DECL(AL_ECHO_DELAY),
657 DECL(AL_ECHO_LRDELAY),
658 DECL(AL_ECHO_DAMPING),
659 DECL(AL_ECHO_FEEDBACK),
660 DECL(AL_ECHO_SPREAD),
662 DECL(AL_FLANGER_WAVEFORM),
663 DECL(AL_FLANGER_PHASE),
664 DECL(AL_FLANGER_RATE),
665 DECL(AL_FLANGER_DEPTH),
666 DECL(AL_FLANGER_FEEDBACK),
667 DECL(AL_FLANGER_DELAY),
669 DECL(AL_RING_MODULATOR_FREQUENCY),
670 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
671 DECL(AL_RING_MODULATOR_WAVEFORM),
673 #if 0
674 DECL(AL_AUTOWAH_ATTACK_TIME),
675 DECL(AL_AUTOWAH_PEAK_GAIN),
676 DECL(AL_AUTOWAH_RELEASE_TIME),
677 DECL(AL_AUTOWAH_RESONANCE),
678 #endif
680 DECL(AL_COMPRESSOR_ONOFF),
682 DECL(AL_EQUALIZER_LOW_GAIN),
683 DECL(AL_EQUALIZER_LOW_CUTOFF),
684 DECL(AL_EQUALIZER_MID1_GAIN),
685 DECL(AL_EQUALIZER_MID1_CENTER),
686 DECL(AL_EQUALIZER_MID1_WIDTH),
687 DECL(AL_EQUALIZER_MID2_GAIN),
688 DECL(AL_EQUALIZER_MID2_CENTER),
689 DECL(AL_EQUALIZER_MID2_WIDTH),
690 DECL(AL_EQUALIZER_HIGH_GAIN),
691 DECL(AL_EQUALIZER_HIGH_CUTOFF),
693 DECL(AL_DEDICATED_GAIN),
695 { NULL, (ALCenum)0 }
697 #undef DECL
699 static const ALCchar alcNoError[] = "No Error";
700 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
701 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
702 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
703 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
704 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
707 /************************************************
708 * Global variables
709 ************************************************/
711 /* Enumerated device names */
712 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
714 static al_string alcAllDevicesList;
715 static al_string alcCaptureDeviceList;
717 /* Default is always the first in the list */
718 static ALCchar *alcDefaultAllDevicesSpecifier;
719 static ALCchar *alcCaptureDefaultDeviceSpecifier;
721 /* Default context extensions */
722 static const ALchar alExtList[] =
723 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
724 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
725 "AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
726 "AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_block_alignment "
727 "AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates "
728 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
729 "AL_SOFT_source_latency AL_SOFT_source_length";
731 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
733 /* Thread-local current context */
734 static altss_t LocalContext;
735 /* Process-wide current context */
736 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
738 /* Mixing thread piority level */
739 ALint RTPrioLevel;
741 FILE *LogFile;
742 #ifdef _DEBUG
743 enum LogLevel LogLevel = LogWarning;
744 #else
745 enum LogLevel LogLevel = LogError;
746 #endif
748 /* Flag to trap ALC device errors */
749 static ALCboolean TrapALCError = ALC_FALSE;
751 /* One-time configuration init control */
752 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
754 /* Default effect that applies to sources that don't have an effect on send 0 */
755 static ALeffect DefaultEffect;
757 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
758 * updates.
760 static ALCboolean SuspendDefers = ALC_TRUE;
763 /************************************************
764 * ALC information
765 ************************************************/
766 static const ALCchar alcNoDeviceExtList[] =
767 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
768 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
769 static const ALCchar alcExtensionList[] =
770 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
771 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
772 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
773 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
774 static const ALCint alcMajorVersion = 1;
775 static const ALCint alcMinorVersion = 1;
777 static const ALCint alcEFXMajorVersion = 1;
778 static const ALCint alcEFXMinorVersion = 0;
781 /************************************************
782 * Device lists
783 ************************************************/
784 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
786 static almtx_t ListLock;
787 static inline void LockLists(void)
789 int lockret = almtx_lock(&ListLock);
790 assert(lockret == althrd_success);
792 static inline void UnlockLists(void)
794 int unlockret = almtx_unlock(&ListLock);
795 assert(unlockret == althrd_success);
798 /************************************************
799 * Library initialization
800 ************************************************/
801 #if defined(_WIN32)
802 static void alc_init(void);
803 static void alc_deinit(void);
804 static void alc_deinit_safe(void);
806 #ifndef AL_LIBTYPE_STATIC
807 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
809 switch(reason)
811 case DLL_PROCESS_ATTACH:
812 /* Pin the DLL so we won't get unloaded until the process terminates */
813 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
814 (WCHAR*)hModule, &hModule);
815 alc_init();
816 break;
818 case DLL_THREAD_DETACH:
819 break;
821 case DLL_PROCESS_DETACH:
822 if(!lpReserved)
823 alc_deinit();
824 else
825 alc_deinit_safe();
826 break;
828 return TRUE;
830 #elif defined(_MSC_VER)
831 #pragma section(".CRT$XCU",read)
832 static void alc_constructor(void);
833 static void alc_destructor(void);
834 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
836 static void alc_constructor(void)
838 atexit(alc_destructor);
839 alc_init();
842 static void alc_destructor(void)
844 alc_deinit();
846 #elif defined(HAVE_GCC_DESTRUCTOR)
847 static void alc_init(void) __attribute__((constructor));
848 static void alc_deinit(void) __attribute__((destructor));
849 #else
850 #error "No static initialization available on this platform!"
851 #endif
853 #elif defined(HAVE_GCC_DESTRUCTOR)
855 static void alc_init(void) __attribute__((constructor));
856 static void alc_deinit(void) __attribute__((destructor));
858 #else
859 #error "No global initialization available on this platform!"
860 #endif
862 static void ReleaseThreadCtx(void *ptr);
863 static void alc_init(void)
865 const char *str;
866 int ret;
868 LogFile = stderr;
870 AL_STRING_INIT(alcAllDevicesList);
871 AL_STRING_INIT(alcCaptureDeviceList);
873 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
874 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
875 ConeScale *= 0.5f;
877 str = getenv("__ALSOFT_REVERSE_Z");
878 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
879 ZScale *= -1.0f;
881 ret = altss_create(&LocalContext, ReleaseThreadCtx);
882 assert(ret == althrd_success);
884 ret = almtx_init(&ListLock, almtx_recursive);
885 assert(ret == althrd_success);
887 ThunkInit();
890 static void alc_initconfig(void)
892 const char *devs, *str;
893 ALuint capfilter;
894 float valf;
895 int i, n;
897 str = getenv("ALSOFT_LOGLEVEL");
898 if(str)
900 long lvl = strtol(str, NULL, 0);
901 if(lvl >= NoLog && lvl <= LogRef)
902 LogLevel = lvl;
905 str = getenv("ALSOFT_LOGFILE");
906 if(str && str[0])
908 FILE *logfile = al_fopen(str, "wt");
909 if(logfile) LogFile = logfile;
910 else ERR("Failed to open log file '%s'\n", str);
914 char buf[1024] = "";
915 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
916 for(i = 1;BackendList[i].name;i++)
917 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
918 TRACE("Supported backends: %s\n", buf);
920 ReadALConfig();
922 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
923 if(str && *str)
925 if(strcasecmp(str, "ignore") == 0)
927 SuspendDefers = ALC_FALSE;
928 TRACE("Selected context suspend behavior, \"ignore\"\n");
930 else
931 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
934 capfilter = 0;
935 #if defined(HAVE_SSE4_1)
936 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
937 #elif defined(HAVE_SSE2)
938 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
939 #elif defined(HAVE_SSE)
940 capfilter |= CPU_CAP_SSE;
941 #endif
942 #ifdef HAVE_NEON
943 capfilter |= CPU_CAP_NEON;
944 #endif
945 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
947 if(strcasecmp(str, "all") == 0)
948 capfilter = 0;
949 else
951 size_t len;
952 const char *next = str;
954 do {
955 str = next;
956 while(isspace(str[0]))
957 str++;
958 next = strchr(str, ',');
960 if(!str[0] || str[0] == ',')
961 continue;
963 len = (next ? ((size_t)(next-str)) : strlen(str));
964 while(len > 0 && isspace(str[len-1]))
965 len--;
966 if(len == 3 && strncasecmp(str, "sse", len) == 0)
967 capfilter &= ~CPU_CAP_SSE;
968 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
969 capfilter &= ~CPU_CAP_SSE2;
970 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
971 capfilter &= ~CPU_CAP_SSE4_1;
972 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
973 capfilter &= ~CPU_CAP_NEON;
974 else
975 WARN("Invalid CPU extension \"%s\"\n", str);
976 } while(next++);
979 FillCPUCaps(capfilter);
981 #ifdef _WIN32
982 RTPrioLevel = 1;
983 #else
984 RTPrioLevel = 0;
985 #endif
986 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
988 if(ConfigValueStr(NULL, "resampler", &str))
990 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
991 DefaultResampler = PointResampler;
992 else if(strcasecmp(str, "linear") == 0)
993 DefaultResampler = LinearResampler;
994 else if(strcasecmp(str, "cubic") == 0)
995 DefaultResampler = CubicResampler;
996 else
998 char *end;
1000 n = strtol(str, &end, 0);
1001 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
1002 DefaultResampler = n;
1003 else
1004 WARN("Invalid resampler: %s\n", str);
1008 str = getenv("ALSOFT_TRAP_ERROR");
1009 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1011 TrapALError = AL_TRUE;
1012 TrapALCError = AL_TRUE;
1014 else
1016 str = getenv("ALSOFT_TRAP_AL_ERROR");
1017 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1018 TrapALError = AL_TRUE;
1019 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
1021 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1022 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1023 TrapALCError = ALC_TRUE;
1024 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1027 if(ConfigValueFloat("reverb", "boost", &valf))
1028 ReverbBoost *= powf(10.0f, valf / 20.0f);
1030 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1032 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1033 ConfigValueStr(NULL, "drivers", &devs))
1035 int n;
1036 size_t len;
1037 const char *next = devs;
1038 int endlist, delitem;
1040 i = 0;
1041 do {
1042 devs = next;
1043 while(isspace(devs[0]))
1044 devs++;
1045 next = strchr(devs, ',');
1047 delitem = (devs[0] == '-');
1048 if(devs[0] == '-') devs++;
1050 if(!devs[0] || devs[0] == ',')
1052 endlist = 0;
1053 continue;
1055 endlist = 1;
1057 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1058 while(len > 0 && isspace(devs[len-1]))
1059 len--;
1060 for(n = i;BackendList[n].name;n++)
1062 if(len == strlen(BackendList[n].name) &&
1063 strncmp(BackendList[n].name, devs, len) == 0)
1065 if(delitem)
1067 do {
1068 BackendList[n] = BackendList[n+1];
1069 ++n;
1070 } while(BackendList[n].name);
1072 else
1074 struct BackendInfo Bkp = BackendList[n];
1075 while(n > i)
1077 BackendList[n] = BackendList[n-1];
1078 --n;
1080 BackendList[n] = Bkp;
1082 i++;
1084 break;
1087 } while(next++);
1089 if(endlist)
1091 BackendList[i].name = NULL;
1092 BackendList[i].getFactory = NULL;
1093 BackendList[i].Init = NULL;
1094 BackendList[i].Deinit = NULL;
1095 BackendList[i].Probe = NULL;
1099 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1101 if(BackendList[i].getFactory)
1103 ALCbackendFactory *factory = BackendList[i].getFactory();
1104 if(!V0(factory,init)())
1106 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1107 continue;
1110 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1111 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1113 PlaybackBackend = BackendList[i];
1114 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1116 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1118 CaptureBackend = BackendList[i];
1119 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1122 continue;
1125 if(!BackendList[i].Init(&BackendList[i].Funcs))
1127 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1128 continue;
1131 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1132 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1134 PlaybackBackend = BackendList[i];
1135 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1137 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1139 CaptureBackend = BackendList[i];
1140 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1144 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1145 V0(factory,init)();
1148 if(ConfigValueStr(NULL, "excludefx", &str))
1150 size_t len;
1151 const char *next = str;
1153 do {
1154 str = next;
1155 next = strchr(str, ',');
1157 if(!str[0] || next == str)
1158 continue;
1160 len = (next ? ((size_t)(next-str)) : strlen(str));
1161 for(n = 0;EffectList[n].name;n++)
1163 if(len == strlen(EffectList[n].name) &&
1164 strncmp(EffectList[n].name, str, len) == 0)
1165 DisabledEffects[EffectList[n].type] = AL_TRUE;
1167 } while(next++);
1170 InitEffectFactoryMap();
1172 InitEffect(&DefaultEffect);
1173 str = getenv("ALSOFT_DEFAULT_REVERB");
1174 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1175 LoadReverbPreset(str, &DefaultEffect);
1177 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1180 /************************************************
1181 * Library deinitialization
1182 ************************************************/
1183 static void alc_cleanup(void)
1185 ALCdevice *dev;
1187 AL_STRING_DEINIT(alcAllDevicesList);
1188 AL_STRING_DEINIT(alcCaptureDeviceList);
1190 free(alcDefaultAllDevicesSpecifier);
1191 alcDefaultAllDevicesSpecifier = NULL;
1192 free(alcCaptureDefaultDeviceSpecifier);
1193 alcCaptureDefaultDeviceSpecifier = NULL;
1195 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1197 ALCuint num = 0;
1198 do {
1199 num++;
1200 } while((dev=dev->next) != NULL);
1201 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1204 DeinitEffectFactoryMap();
1207 static void alc_deinit_safe(void)
1209 alc_cleanup();
1211 FreeHrtfs();
1212 FreeALConfig();
1214 ThunkExit();
1215 almtx_destroy(&ListLock);
1216 altss_delete(LocalContext);
1218 if(LogFile != stderr)
1219 fclose(LogFile);
1220 LogFile = NULL;
1223 static void alc_deinit(void)
1225 int i;
1227 alc_cleanup();
1229 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1230 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1232 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1234 if(!BackendList[i].getFactory)
1235 BackendList[i].Deinit();
1236 else
1238 ALCbackendFactory *factory = BackendList[i].getFactory();
1239 V0(factory,deinit)();
1243 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1244 V0(factory,deinit)();
1247 alc_deinit_safe();
1251 /************************************************
1252 * Device enumeration
1253 ************************************************/
1254 static void ProbeDevices(al_string *list, enum DevProbe type)
1256 DO_INITCONFIG();
1258 LockLists();
1259 al_string_clear(list);
1261 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1263 if(!PlaybackBackend.getFactory)
1264 PlaybackBackend.Probe(type);
1265 else
1267 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1268 V(factory,probe)(type);
1271 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1273 if(!CaptureBackend.getFactory)
1274 CaptureBackend.Probe(type);
1275 else
1277 ALCbackendFactory *factory = CaptureBackend.getFactory();
1278 V(factory,probe)(type);
1281 UnlockLists();
1283 static void ProbeAllDevicesList(void)
1284 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1285 static void ProbeCaptureDeviceList(void)
1286 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1288 static void AppendDevice(const ALCchar *name, al_string *devnames)
1290 size_t len = strlen(name);
1291 if(len > 0)
1292 al_string_append_range(devnames, name, name+len+1);
1294 void AppendAllDevicesList(const ALCchar *name)
1295 { AppendDevice(name, &alcAllDevicesList); }
1296 void AppendCaptureDeviceList(const ALCchar *name)
1297 { AppendDevice(name, &alcCaptureDeviceList); }
1300 /************************************************
1301 * Device format information
1302 ************************************************/
1303 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1305 switch(type)
1307 case DevFmtByte: return "Signed Byte";
1308 case DevFmtUByte: return "Unsigned Byte";
1309 case DevFmtShort: return "Signed Short";
1310 case DevFmtUShort: return "Unsigned Short";
1311 case DevFmtInt: return "Signed Int";
1312 case DevFmtUInt: return "Unsigned Int";
1313 case DevFmtFloat: return "Float";
1315 return "(unknown type)";
1317 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1319 switch(chans)
1321 case DevFmtMono: return "Mono";
1322 case DevFmtStereo: return "Stereo";
1323 case DevFmtQuad: return "Quadraphonic";
1324 case DevFmtX51: return "5.1 Surround";
1325 case DevFmtX51Side: return "5.1 Side";
1326 case DevFmtX61: return "6.1 Surround";
1327 case DevFmtX71: return "7.1 Surround";
1329 return "(unknown channels)";
1332 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1333 ALuint BytesFromDevFmt(enum DevFmtType type)
1335 switch(type)
1337 case DevFmtByte: return sizeof(ALbyte);
1338 case DevFmtUByte: return sizeof(ALubyte);
1339 case DevFmtShort: return sizeof(ALshort);
1340 case DevFmtUShort: return sizeof(ALushort);
1341 case DevFmtInt: return sizeof(ALint);
1342 case DevFmtUInt: return sizeof(ALuint);
1343 case DevFmtFloat: return sizeof(ALfloat);
1345 return 0;
1347 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1349 switch(chans)
1351 case DevFmtMono: return 1;
1352 case DevFmtStereo: return 2;
1353 case DevFmtQuad: return 4;
1354 case DevFmtX51: return 6;
1355 case DevFmtX51Side: return 6;
1356 case DevFmtX61: return 7;
1357 case DevFmtX71: return 8;
1359 return 0;
1362 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1363 enum DevFmtChannels *chans, enum DevFmtType *type)
1365 static const struct {
1366 ALenum format;
1367 enum DevFmtChannels channels;
1368 enum DevFmtType type;
1369 } list[] = {
1370 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1371 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1372 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1374 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1375 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1376 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1378 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1379 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1380 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1382 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1383 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1384 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1386 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1387 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1388 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1390 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1391 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1392 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1394 ALuint i;
1396 for(i = 0;i < COUNTOF(list);i++)
1398 if(list[i].format == format)
1400 *chans = list[i].channels;
1401 *type = list[i].type;
1402 return AL_TRUE;
1406 return AL_FALSE;
1409 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1411 switch(type)
1413 case ALC_BYTE_SOFT:
1414 case ALC_UNSIGNED_BYTE_SOFT:
1415 case ALC_SHORT_SOFT:
1416 case ALC_UNSIGNED_SHORT_SOFT:
1417 case ALC_INT_SOFT:
1418 case ALC_UNSIGNED_INT_SOFT:
1419 case ALC_FLOAT_SOFT:
1420 return ALC_TRUE;
1422 return ALC_FALSE;
1425 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1427 switch(channels)
1429 case ALC_MONO_SOFT:
1430 case ALC_STEREO_SOFT:
1431 case ALC_QUAD_SOFT:
1432 case ALC_5POINT1_SOFT:
1433 case ALC_6POINT1_SOFT:
1434 case ALC_7POINT1_SOFT:
1435 return ALC_TRUE;
1437 return ALC_FALSE;
1441 /************************************************
1442 * Miscellaneous ALC helpers
1443 ************************************************/
1444 extern inline void LockContext(ALCcontext *context);
1445 extern inline void UnlockContext(ALCcontext *context);
1447 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1449 return V0(device->Backend,getLatency)();
1452 void ALCdevice_Lock(ALCdevice *device)
1454 V0(device->Backend,lock)();
1457 void ALCdevice_Unlock(ALCdevice *device)
1459 V0(device->Backend,unlock)();
1463 /* SetDefaultWFXChannelOrder
1465 * Sets the default channel order used by WaveFormatEx.
1467 void SetDefaultWFXChannelOrder(ALCdevice *device)
1469 ALuint i;
1471 for(i = 0;i < MaxChannels;i++)
1472 device->ChannelName[i] = InvalidChannel;
1474 switch(device->FmtChans)
1476 case DevFmtMono: device->ChannelName[0] = FrontCenter;
1477 break;
1478 case DevFmtStereo: device->ChannelName[0] = FrontLeft;
1479 device->ChannelName[1] = FrontRight;
1480 break;
1481 case DevFmtQuad: device->ChannelName[0] = FrontLeft;
1482 device->ChannelName[1] = FrontRight;
1483 device->ChannelName[2] = BackLeft;
1484 device->ChannelName[3] = BackRight;
1485 break;
1486 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1487 device->ChannelName[1] = FrontRight;
1488 device->ChannelName[2] = FrontCenter;
1489 device->ChannelName[3] = LFE;
1490 device->ChannelName[4] = BackLeft;
1491 device->ChannelName[5] = BackRight;
1492 break;
1493 case DevFmtX51Side: device->ChannelName[0] = FrontLeft;
1494 device->ChannelName[1] = FrontRight;
1495 device->ChannelName[2] = FrontCenter;
1496 device->ChannelName[3] = LFE;
1497 device->ChannelName[4] = SideLeft;
1498 device->ChannelName[5] = SideRight;
1499 break;
1500 case DevFmtX61: device->ChannelName[0] = FrontLeft;
1501 device->ChannelName[1] = FrontRight;
1502 device->ChannelName[2] = FrontCenter;
1503 device->ChannelName[3] = LFE;
1504 device->ChannelName[4] = BackCenter;
1505 device->ChannelName[5] = SideLeft;
1506 device->ChannelName[6] = SideRight;
1507 break;
1508 case DevFmtX71: 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 device->ChannelName[6] = SideLeft;
1515 device->ChannelName[7] = SideRight;
1516 break;
1520 /* SetDefaultChannelOrder
1522 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1524 void SetDefaultChannelOrder(ALCdevice *device)
1526 ALuint i;
1528 for(i = 0;i < MaxChannels;i++)
1529 device->ChannelName[i] = InvalidChannel;
1531 switch(device->FmtChans)
1533 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1534 device->ChannelName[1] = FrontRight;
1535 device->ChannelName[2] = BackLeft;
1536 device->ChannelName[3] = BackRight;
1537 device->ChannelName[4] = FrontCenter;
1538 device->ChannelName[5] = LFE;
1539 return;
1540 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1541 device->ChannelName[1] = FrontRight;
1542 device->ChannelName[2] = BackLeft;
1543 device->ChannelName[3] = BackRight;
1544 device->ChannelName[4] = FrontCenter;
1545 device->ChannelName[5] = LFE;
1546 device->ChannelName[6] = SideLeft;
1547 device->ChannelName[7] = SideRight;
1548 return;
1550 /* Same as WFX order */
1551 case DevFmtMono:
1552 case DevFmtStereo:
1553 case DevFmtQuad:
1554 case DevFmtX51Side:
1555 case DevFmtX61:
1556 SetDefaultWFXChannelOrder(device);
1557 break;
1561 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1564 /* ALCcontext_DeferUpdates
1566 * Defers/suspends updates for the given context's listener and sources. This
1567 * does *NOT* stop mixing, but rather prevents certain property changes from
1568 * taking effect.
1570 void ALCcontext_DeferUpdates(ALCcontext *context)
1572 ALCdevice *device = context->Device;
1573 FPUCtl oldMode;
1575 SetMixerFPUMode(&oldMode);
1577 V0(device->Backend,lock)();
1578 if(!ExchangeInt(&context->DeferUpdates, AL_TRUE))
1580 ALboolean UpdateSources;
1581 ALvoice *voice, *voice_end;
1582 ALeffectslot **slot, **slot_end;
1583 /* Make sure all pending updates are performed */
1584 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
1586 voice = context->Voices;
1587 voice_end = voice + context->VoiceCount;
1588 while(voice != voice_end)
1590 ALsource *source = voice->Source;
1591 if(!source) goto next;
1593 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
1595 voice->Source = NULL;
1596 continue;
1599 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
1600 voice->Update(voice, source, context);
1601 next:
1602 voice++;
1605 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
1606 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
1607 while(slot != slot_end)
1609 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
1610 V((*slot)->EffectState,update)(context->Device, *slot);
1611 slot++;
1614 V0(device->Backend,unlock)();
1616 RestoreFPUMode(&oldMode);
1619 /* ALCcontext_ProcessUpdates
1621 * Resumes update processing after being deferred.
1623 void ALCcontext_ProcessUpdates(ALCcontext *context)
1625 ALCdevice *device = context->Device;
1627 V0(device->Backend,lock)();
1628 if(ExchangeInt(&context->DeferUpdates, AL_FALSE))
1630 ALsizei pos;
1632 LockUIntMapRead(&context->SourceMap);
1633 for(pos = 0;pos < context->SourceMap.size;pos++)
1635 ALsource *Source = context->SourceMap.array[pos].value;
1636 ALenum new_state;
1638 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1639 Source->Offset >= 0.0)
1641 ReadLock(&Source->queue_lock);
1642 ApplyOffset(Source);
1643 ReadUnlock(&Source->queue_lock);
1646 new_state = ExchangeInt(&Source->new_state, AL_NONE);
1647 if(new_state)
1648 SetSourceState(Source, context, new_state);
1650 UnlockUIntMapRead(&context->SourceMap);
1652 V0(device->Backend,unlock)();
1656 /* alcSetError
1658 * Stores the latest ALC device error
1660 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1662 if(TrapALCError)
1664 #ifdef _WIN32
1665 /* DebugBreak() will cause an exception if there is no debugger */
1666 if(IsDebuggerPresent())
1667 DebugBreak();
1668 #elif defined(SIGTRAP)
1669 raise(SIGTRAP);
1670 #endif
1673 if(device)
1674 ATOMIC_STORE(&device->LastError, errorCode);
1675 else
1676 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1680 /* UpdateClockBase
1682 * Updates the device's base clock time with however many samples have been
1683 * done. This is used so frequency changes on the device don't cause the time
1684 * to jump forward or back.
1686 static inline void UpdateClockBase(ALCdevice *device)
1688 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1689 device->SamplesDone = 0;
1692 /* UpdateDeviceParams
1694 * Updates device parameters according to the attribute list (caller is
1695 * responsible for holding the list lock).
1697 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1699 ALCcontext *context;
1700 enum DevFmtChannels oldChans;
1701 enum DevFmtType oldType;
1702 ALCuint oldFreq;
1703 FPUCtl oldMode;
1705 // Check for attributes
1706 if(device->Type == Loopback)
1708 enum {
1709 GotFreq = 1<<0,
1710 GotChans = 1<<1,
1711 GotType = 1<<2,
1712 GotAll = GotFreq|GotChans|GotType
1714 ALCuint freq, numMono, numStereo, numSends, flags;
1715 enum DevFmtChannels schans;
1716 enum DevFmtType stype;
1717 ALCuint attrIdx = 0;
1718 ALCint gotFmt = 0;
1720 if(!attrList)
1722 WARN("Missing attributes for loopback device\n");
1723 return ALC_INVALID_VALUE;
1726 numMono = device->NumMonoSources;
1727 numStereo = device->NumStereoSources;
1728 numSends = device->NumAuxSends;
1729 schans = device->FmtChans;
1730 stype = device->FmtType;
1731 freq = device->Frequency;
1732 flags = device->Flags;
1734 while(attrList[attrIdx])
1736 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1738 ALCint val = attrList[attrIdx + 1];
1739 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1740 return ALC_INVALID_VALUE;
1741 schans = val;
1742 gotFmt |= GotChans;
1745 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1747 ALCint val = attrList[attrIdx + 1];
1748 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1749 return ALC_INVALID_VALUE;
1750 stype = val;
1751 gotFmt |= GotType;
1754 if(attrList[attrIdx] == ALC_FREQUENCY)
1756 freq = attrList[attrIdx + 1];
1757 if(freq < MIN_OUTPUT_RATE)
1758 return ALC_INVALID_VALUE;
1759 gotFmt |= GotFreq;
1762 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1764 numStereo = attrList[attrIdx + 1];
1765 if(numStereo > device->MaxNoOfSources)
1766 numStereo = device->MaxNoOfSources;
1768 numMono = device->MaxNoOfSources - numStereo;
1771 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1772 numSends = attrList[attrIdx + 1];
1774 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1776 if(attrList[attrIdx + 1] != ALC_FALSE)
1777 flags |= DEVICE_HRTF_REQUEST;
1778 else
1779 flags &= ~DEVICE_HRTF_REQUEST;
1782 attrIdx += 2;
1785 if(gotFmt != GotAll)
1787 WARN("Missing format for loopback device\n");
1788 return ALC_INVALID_VALUE;
1791 ConfigValueUInt(NULL, "sends", &numSends);
1792 numSends = minu(MAX_SENDS, numSends);
1794 if((device->Flags&DEVICE_RUNNING))
1795 V0(device->Backend,stop)();
1796 device->Flags = (flags & ~DEVICE_RUNNING);
1798 UpdateClockBase(device);
1800 device->Frequency = freq;
1801 device->FmtChans = schans;
1802 device->FmtType = stype;
1803 device->NumMonoSources = numMono;
1804 device->NumStereoSources = numStereo;
1805 device->NumAuxSends = numSends;
1807 else if(attrList && attrList[0])
1809 ALCuint freq, numMono, numStereo, numSends;
1810 ALCuint attrIdx = 0;
1812 /* If a context is already running on the device, stop playback so the
1813 * device attributes can be updated. */
1814 if((device->Flags&DEVICE_RUNNING))
1815 V0(device->Backend,stop)();
1816 device->Flags &= ~DEVICE_RUNNING;
1818 freq = device->Frequency;
1819 numMono = device->NumMonoSources;
1820 numStereo = device->NumStereoSources;
1821 numSends = device->NumAuxSends;
1823 while(attrList[attrIdx])
1825 if(attrList[attrIdx] == ALC_FREQUENCY)
1827 freq = attrList[attrIdx + 1];
1828 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1831 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1833 numStereo = attrList[attrIdx + 1];
1834 if(numStereo > device->MaxNoOfSources)
1835 numStereo = device->MaxNoOfSources;
1837 numMono = device->MaxNoOfSources - numStereo;
1840 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1841 numSends = attrList[attrIdx + 1];
1843 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1845 if(attrList[attrIdx + 1] != ALC_FALSE)
1846 device->Flags |= DEVICE_HRTF_REQUEST;
1847 else
1848 device->Flags &= ~DEVICE_HRTF_REQUEST;
1851 attrIdx += 2;
1854 ConfigValueUInt(NULL, "frequency", &freq);
1855 freq = maxu(freq, MIN_OUTPUT_RATE);
1857 ConfigValueUInt(NULL, "sends", &numSends);
1858 numSends = minu(MAX_SENDS, numSends);
1860 UpdateClockBase(device);
1862 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1863 device->Frequency;
1864 /* SSE and Neon do best with the update size being a multiple of 4 */
1865 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1866 device->UpdateSize = (device->UpdateSize+3)&~3;
1868 device->Frequency = freq;
1869 device->NumMonoSources = numMono;
1870 device->NumStereoSources = numStereo;
1871 device->NumAuxSends = numSends;
1874 if((device->Flags&DEVICE_RUNNING))
1875 return ALC_NO_ERROR;
1877 UpdateClockBase(device);
1879 if(device->Type != Loopback)
1881 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1882 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1883 device->Flags |= DEVICE_HRTF_REQUEST;
1884 else
1885 device->Flags &= ~DEVICE_HRTF_REQUEST;
1887 if((device->Flags&DEVICE_HRTF_REQUEST))
1889 enum DevFmtChannels chans = device->FmtChans;
1890 ALCuint freq = device->Frequency;
1891 if(FindHrtfFormat(&chans, &freq))
1893 if(device->Type != Loopback)
1895 device->Frequency = freq;
1896 device->FmtChans = chans;
1897 device->Flags |= DEVICE_CHANNELS_REQUEST |
1898 DEVICE_FREQUENCY_REQUEST;
1900 else if(device->Frequency != freq || device->FmtChans != chans)
1902 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1903 DevFmtChannelsString(device->FmtChans), device->Frequency);
1904 device->Flags &= ~DEVICE_HRTF_REQUEST;
1909 oldFreq = device->Frequency;
1910 oldChans = device->FmtChans;
1911 oldType = device->FmtType;
1913 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1914 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1915 DevFmtChannelsString(device->FmtChans),
1916 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1917 DevFmtTypeString(device->FmtType),
1918 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1919 device->Frequency,
1920 device->UpdateSize, device->NumUpdates);
1922 if(V0(device->Backend,reset)() == ALC_FALSE)
1923 return ALC_INVALID_DEVICE;
1925 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1927 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1928 DevFmtChannelsString(device->FmtChans));
1929 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1931 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1933 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1934 DevFmtTypeString(device->FmtType));
1935 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1937 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1939 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1940 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1943 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1944 DevFmtChannelsString(device->FmtChans),
1945 DevFmtTypeString(device->FmtType), device->Frequency,
1946 device->UpdateSize, device->NumUpdates);
1948 aluInitPanning(device);
1950 V(device->Synth,update)(device);
1952 device->Hrtf = NULL;
1953 if((device->Flags&DEVICE_HRTF_REQUEST))
1955 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1956 if(!device->Hrtf)
1957 device->Flags &= ~DEVICE_HRTF_REQUEST;
1959 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1961 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1963 if(!device->Bs2b)
1965 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1966 bs2b_clear(device->Bs2b);
1968 bs2b_set_srate(device->Bs2b, device->Frequency);
1969 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1970 TRACE("BS2B level %d\n", device->Bs2bLevel);
1972 else
1974 free(device->Bs2b);
1975 device->Bs2b = NULL;
1976 TRACE("BS2B disabled\n");
1979 device->Flags &= ~DEVICE_WIDE_STEREO;
1980 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1981 device->Flags |= DEVICE_WIDE_STEREO;
1983 if(!device->Hrtf && (device->UpdateSize&3))
1985 if((CPUCapFlags&CPU_CAP_SSE))
1986 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1987 if((CPUCapFlags&CPU_CAP_NEON))
1988 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1991 SetMixerFPUMode(&oldMode);
1992 ALCdevice_Lock(device);
1993 context = ATOMIC_LOAD(&device->ContextList);
1994 while(context)
1996 ALsizei pos;
1998 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
1999 LockUIntMapRead(&context->EffectSlotMap);
2000 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2002 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
2004 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2006 UnlockUIntMapRead(&context->EffectSlotMap);
2007 ALCdevice_Unlock(device);
2008 RestoreFPUMode(&oldMode);
2009 return ALC_INVALID_DEVICE;
2011 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2012 V(slot->EffectState,update)(device, slot);
2014 UnlockUIntMapRead(&context->EffectSlotMap);
2016 LockUIntMapRead(&context->SourceMap);
2017 for(pos = 0;pos < context->SourceMap.size;pos++)
2019 ALsource *source = context->SourceMap.array[pos].value;
2020 ALuint s = device->NumAuxSends;
2021 while(s < MAX_SENDS)
2023 if(source->Send[s].Slot)
2024 DecrementRef(&source->Send[s].Slot->ref);
2025 source->Send[s].Slot = NULL;
2026 source->Send[s].Gain = 1.0f;
2027 source->Send[s].GainHF = 1.0f;
2028 s++;
2030 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
2032 UnlockUIntMapRead(&context->SourceMap);
2034 for(pos = 0;pos < context->VoiceCount;pos++)
2036 ALvoice *voice = &context->Voices[pos];
2037 ALsource *source = voice->Source;
2038 ALuint s = device->NumAuxSends;
2040 while(s < MAX_SENDS)
2042 voice->Send[s].Moving = AL_FALSE;
2043 voice->Send[s].Counter = 0;
2044 s++;
2047 if(source)
2049 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
2050 voice->Update(voice, source, context);
2054 context = context->next;
2056 if(device->DefaultSlot)
2058 ALeffectslot *slot = device->DefaultSlot;
2060 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2062 ALCdevice_Unlock(device);
2063 RestoreFPUMode(&oldMode);
2064 return ALC_INVALID_DEVICE;
2066 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2067 V(slot->EffectState,update)(device, slot);
2069 ALCdevice_Unlock(device);
2070 RestoreFPUMode(&oldMode);
2072 if(!(device->Flags&DEVICE_PAUSED))
2074 if(V0(device->Backend,start)() == ALC_FALSE)
2075 return ALC_INVALID_DEVICE;
2076 device->Flags |= DEVICE_RUNNING;
2079 return ALC_NO_ERROR;
2082 /* FreeDevice
2084 * Frees the device structure, and destroys any objects the app failed to
2085 * delete. Called once there's no more references on the device.
2087 static ALCvoid FreeDevice(ALCdevice *device)
2089 TRACE("%p\n", device);
2091 V0(device->Backend,close)();
2092 DELETE_OBJ(device->Backend);
2093 device->Backend = NULL;
2095 DELETE_OBJ(device->Synth);
2096 device->Synth = NULL;
2098 if(device->DefaultSlot)
2100 ALeffectState *state = device->DefaultSlot->EffectState;
2101 device->DefaultSlot = NULL;
2102 DELETE_OBJ(state);
2105 if(device->DefaultSfont)
2106 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
2107 device->DefaultSfont = NULL;
2109 if(device->BufferMap.size > 0)
2111 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2112 ReleaseALBuffers(device);
2114 ResetUIntMap(&device->BufferMap);
2116 if(device->EffectMap.size > 0)
2118 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2119 ReleaseALEffects(device);
2121 ResetUIntMap(&device->EffectMap);
2123 if(device->FilterMap.size > 0)
2125 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2126 ReleaseALFilters(device);
2128 ResetUIntMap(&device->FilterMap);
2130 if(device->SfontMap.size > 0)
2132 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2133 ReleaseALSoundfonts(device);
2135 ResetUIntMap(&device->SfontMap);
2137 if(device->PresetMap.size > 0)
2139 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2140 ReleaseALPresets(device);
2142 ResetUIntMap(&device->PresetMap);
2144 if(device->FontsoundMap.size > 0)
2146 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2147 ReleaseALFontsounds(device);
2149 ResetUIntMap(&device->FontsoundMap);
2151 free(device->Bs2b);
2152 device->Bs2b = NULL;
2154 AL_STRING_DEINIT(device->DeviceName);
2156 al_free(device);
2160 void ALCdevice_IncRef(ALCdevice *device)
2162 uint ref;
2163 ref = IncrementRef(&device->ref);
2164 TRACEREF("%p increasing refcount to %u\n", device, ref);
2167 void ALCdevice_DecRef(ALCdevice *device)
2169 uint ref;
2170 ref = DecrementRef(&device->ref);
2171 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2172 if(ref == 0) FreeDevice(device);
2175 /* VerifyDevice
2177 * Checks if the device handle is valid, and increments its ref count if so.
2179 static ALCdevice *VerifyDevice(ALCdevice *device)
2181 ALCdevice *tmpDevice;
2183 if(!device)
2184 return NULL;
2186 LockLists();
2187 tmpDevice = ATOMIC_LOAD(&DeviceList);
2188 while(tmpDevice && tmpDevice != device)
2189 tmpDevice = tmpDevice->next;
2191 if(tmpDevice)
2192 ALCdevice_IncRef(tmpDevice);
2193 UnlockLists();
2194 return tmpDevice;
2198 /* InitContext
2200 * Initializes context fields
2202 static ALvoid InitContext(ALCcontext *Context)
2204 ALint i, j;
2206 //Initialise listener
2207 Context->Listener->Gain = 1.0f;
2208 Context->Listener->MetersPerUnit = 1.0f;
2209 Context->Listener->Position[0] = 0.0f;
2210 Context->Listener->Position[1] = 0.0f;
2211 Context->Listener->Position[2] = 0.0f;
2212 Context->Listener->Velocity[0] = 0.0f;
2213 Context->Listener->Velocity[1] = 0.0f;
2214 Context->Listener->Velocity[2] = 0.0f;
2215 Context->Listener->Forward[0] = 0.0f;
2216 Context->Listener->Forward[1] = 0.0f;
2217 Context->Listener->Forward[2] = -1.0f;
2218 Context->Listener->Up[0] = 0.0f;
2219 Context->Listener->Up[1] = 1.0f;
2220 Context->Listener->Up[2] = 0.0f;
2221 for(i = 0;i < 4;i++)
2223 for(j = 0;j < 4;j++)
2224 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2226 for(i = 0;i < 3;i++)
2227 Context->Listener->Params.Velocity[i] = 0.0f;
2229 //Validate Context
2230 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2231 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2232 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2233 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2235 //Set globals
2236 Context->DistanceModel = DefaultDistanceModel;
2237 Context->SourceDistanceModel = AL_FALSE;
2238 Context->DopplerFactor = 1.0f;
2239 Context->DopplerVelocity = 1.0f;
2240 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2241 Context->DeferUpdates = AL_FALSE;
2243 Context->ExtensionList = alExtList;
2247 /* FreeContext
2249 * Cleans up the context, and destroys any remaining objects the app failed to
2250 * delete. Called once there's no more references on the context.
2252 static void FreeContext(ALCcontext *context)
2254 TRACE("%p\n", context);
2256 if(context->SourceMap.size > 0)
2258 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2259 ReleaseALSources(context);
2261 ResetUIntMap(&context->SourceMap);
2263 if(context->EffectSlotMap.size > 0)
2265 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2266 ReleaseALAuxiliaryEffectSlots(context);
2268 ResetUIntMap(&context->EffectSlotMap);
2270 al_free(context->Voices);
2271 context->Voices = NULL;
2272 context->VoiceCount = 0;
2273 context->MaxVoices = 0;
2275 VECTOR_DEINIT(context->ActiveAuxSlots);
2277 ALCdevice_DecRef(context->Device);
2278 context->Device = NULL;
2280 //Invalidate context
2281 memset(context, 0, sizeof(ALCcontext));
2282 al_free(context);
2285 /* ReleaseContext
2287 * Removes the context reference from the given device and removes it from
2288 * being current on the running thread or globally.
2290 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2292 ALCcontext *nextctx;
2293 ALCcontext *origctx;
2295 if(altss_get(LocalContext) == context)
2297 WARN("%p released while current on thread\n", context);
2298 altss_set(LocalContext, NULL);
2299 ALCcontext_DecRef(context);
2302 origctx = context;
2303 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2304 ALCcontext_DecRef(context);
2306 ALCdevice_Lock(device);
2307 origctx = context;
2308 nextctx = context->next;
2309 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2311 ALCcontext *list;
2312 do {
2313 list = origctx;
2314 origctx = context;
2315 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2317 ALCdevice_Unlock(device);
2319 ALCcontext_DecRef(context);
2322 void ALCcontext_IncRef(ALCcontext *context)
2324 uint ref;
2325 ref = IncrementRef(&context->ref);
2326 TRACEREF("%p increasing refcount to %u\n", context, ref);
2329 void ALCcontext_DecRef(ALCcontext *context)
2331 uint ref;
2332 ref = DecrementRef(&context->ref);
2333 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2334 if(ref == 0) FreeContext(context);
2337 static void ReleaseThreadCtx(void *ptr)
2339 WARN("%p current for thread being destroyed\n", ptr);
2340 ALCcontext_DecRef(ptr);
2343 /* VerifyContext
2345 * Checks that the given context is valid, and increments its reference count.
2347 static ALCcontext *VerifyContext(ALCcontext *context)
2349 ALCdevice *dev;
2351 LockLists();
2352 dev = ATOMIC_LOAD(&DeviceList);
2353 while(dev)
2355 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2356 while(ctx)
2358 if(ctx == context)
2360 ALCcontext_IncRef(ctx);
2361 UnlockLists();
2362 return ctx;
2364 ctx = ctx->next;
2366 dev = dev->next;
2368 UnlockLists();
2370 return NULL;
2374 /* GetContextRef
2376 * Returns the currently active context for this thread, and adds a reference
2377 * without locking it.
2379 ALCcontext *GetContextRef(void)
2381 ALCcontext *context;
2383 context = altss_get(LocalContext);
2384 if(context)
2385 ALCcontext_IncRef(context);
2386 else
2388 LockLists();
2389 context = ATOMIC_LOAD(&GlobalContext);
2390 if(context)
2391 ALCcontext_IncRef(context);
2392 UnlockLists();
2395 return context;
2399 /************************************************
2400 * Standard ALC functions
2401 ************************************************/
2403 /* alcGetError
2405 * Return last ALC generated error code for the given device
2407 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2409 ALCenum errorCode;
2411 if(VerifyDevice(device))
2413 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2414 ALCdevice_DecRef(device);
2416 else
2417 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2419 return errorCode;
2423 /* alcSuspendContext
2425 * Suspends updates for the given context
2427 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2429 if(!SuspendDefers)
2430 return;
2432 context = VerifyContext(context);
2433 if(!context)
2434 alcSetError(NULL, ALC_INVALID_CONTEXT);
2435 else
2437 ALCcontext_DeferUpdates(context);
2438 ALCcontext_DecRef(context);
2442 /* alcProcessContext
2444 * Resumes processing updates for the given context
2446 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2448 if(!SuspendDefers)
2449 return;
2451 context = VerifyContext(context);
2452 if(!context)
2453 alcSetError(NULL, ALC_INVALID_CONTEXT);
2454 else
2456 ALCcontext_ProcessUpdates(context);
2457 ALCcontext_DecRef(context);
2462 /* alcGetString
2464 * Returns information about the device, and error strings
2466 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2468 const ALCchar *value = NULL;
2470 switch(param)
2472 case ALC_NO_ERROR:
2473 value = alcNoError;
2474 break;
2476 case ALC_INVALID_ENUM:
2477 value = alcErrInvalidEnum;
2478 break;
2480 case ALC_INVALID_VALUE:
2481 value = alcErrInvalidValue;
2482 break;
2484 case ALC_INVALID_DEVICE:
2485 value = alcErrInvalidDevice;
2486 break;
2488 case ALC_INVALID_CONTEXT:
2489 value = alcErrInvalidContext;
2490 break;
2492 case ALC_OUT_OF_MEMORY:
2493 value = alcErrOutOfMemory;
2494 break;
2496 case ALC_DEVICE_SPECIFIER:
2497 value = alcDefaultName;
2498 break;
2500 case ALC_ALL_DEVICES_SPECIFIER:
2501 if(VerifyDevice(Device))
2503 value = al_string_get_cstr(Device->DeviceName);
2504 ALCdevice_DecRef(Device);
2506 else
2508 ProbeAllDevicesList();
2509 value = al_string_get_cstr(alcAllDevicesList);
2511 break;
2513 case ALC_CAPTURE_DEVICE_SPECIFIER:
2514 if(VerifyDevice(Device))
2516 value = al_string_get_cstr(Device->DeviceName);
2517 ALCdevice_DecRef(Device);
2519 else
2521 ProbeCaptureDeviceList();
2522 value = al_string_get_cstr(alcCaptureDeviceList);
2524 break;
2526 /* Default devices are always first in the list */
2527 case ALC_DEFAULT_DEVICE_SPECIFIER:
2528 value = alcDefaultName;
2529 break;
2531 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2532 if(al_string_empty(alcAllDevicesList))
2533 ProbeAllDevicesList();
2535 Device = VerifyDevice(Device);
2537 free(alcDefaultAllDevicesSpecifier);
2538 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2539 if(!alcDefaultAllDevicesSpecifier)
2540 alcSetError(Device, ALC_OUT_OF_MEMORY);
2542 value = alcDefaultAllDevicesSpecifier;
2543 if(Device) ALCdevice_DecRef(Device);
2544 break;
2546 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2547 if(al_string_empty(alcCaptureDeviceList))
2548 ProbeCaptureDeviceList();
2550 Device = VerifyDevice(Device);
2552 free(alcCaptureDefaultDeviceSpecifier);
2553 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2554 if(!alcCaptureDefaultDeviceSpecifier)
2555 alcSetError(Device, ALC_OUT_OF_MEMORY);
2557 value = alcCaptureDefaultDeviceSpecifier;
2558 if(Device) ALCdevice_DecRef(Device);
2559 break;
2561 case ALC_EXTENSIONS:
2562 if(!VerifyDevice(Device))
2563 value = alcNoDeviceExtList;
2564 else
2566 value = alcExtensionList;
2567 ALCdevice_DecRef(Device);
2569 break;
2571 default:
2572 Device = VerifyDevice(Device);
2573 alcSetError(Device, ALC_INVALID_ENUM);
2574 if(Device) ALCdevice_DecRef(Device);
2575 break;
2578 return value;
2582 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2584 ALCsizei i;
2586 if(size <= 0 || values == NULL)
2588 alcSetError(device, ALC_INVALID_VALUE);
2589 return 0;
2592 if(!device)
2594 switch(param)
2596 case ALC_MAJOR_VERSION:
2597 values[0] = alcMajorVersion;
2598 return 1;
2599 case ALC_MINOR_VERSION:
2600 values[0] = alcMinorVersion;
2601 return 1;
2603 case ALC_ATTRIBUTES_SIZE:
2604 case ALC_ALL_ATTRIBUTES:
2605 case ALC_FREQUENCY:
2606 case ALC_REFRESH:
2607 case ALC_SYNC:
2608 case ALC_MONO_SOURCES:
2609 case ALC_STEREO_SOURCES:
2610 case ALC_CAPTURE_SAMPLES:
2611 case ALC_FORMAT_CHANNELS_SOFT:
2612 case ALC_FORMAT_TYPE_SOFT:
2613 alcSetError(NULL, ALC_INVALID_DEVICE);
2614 return 0;
2616 default:
2617 alcSetError(NULL, ALC_INVALID_ENUM);
2618 return 0;
2620 return 0;
2623 if(device->Type == Capture)
2625 switch(param)
2627 case ALC_CAPTURE_SAMPLES:
2628 ALCdevice_Lock(device);
2629 values[0] = V0(device->Backend,availableSamples)();
2630 ALCdevice_Unlock(device);
2631 return 1;
2633 case ALC_CONNECTED:
2634 values[0] = device->Connected;
2635 return 1;
2637 default:
2638 alcSetError(device, ALC_INVALID_ENUM);
2639 return 0;
2641 return 0;
2644 /* render device */
2645 switch(param)
2647 case ALC_MAJOR_VERSION:
2648 values[0] = alcMajorVersion;
2649 return 1;
2651 case ALC_MINOR_VERSION:
2652 values[0] = alcMinorVersion;
2653 return 1;
2655 case ALC_EFX_MAJOR_VERSION:
2656 values[0] = alcEFXMajorVersion;
2657 return 1;
2659 case ALC_EFX_MINOR_VERSION:
2660 values[0] = alcEFXMinorVersion;
2661 return 1;
2663 case ALC_ATTRIBUTES_SIZE:
2664 values[0] = 15;
2665 return 1;
2667 case ALC_ALL_ATTRIBUTES:
2668 if(size < 15)
2670 alcSetError(device, ALC_INVALID_VALUE);
2671 return 0;
2674 i = 0;
2675 values[i++] = ALC_FREQUENCY;
2676 values[i++] = device->Frequency;
2678 if(device->Type != Loopback)
2680 values[i++] = ALC_REFRESH;
2681 values[i++] = device->Frequency / device->UpdateSize;
2683 values[i++] = ALC_SYNC;
2684 values[i++] = ALC_FALSE;
2686 else
2688 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2689 values[i++] = device->FmtChans;
2691 values[i++] = ALC_FORMAT_TYPE_SOFT;
2692 values[i++] = device->FmtType;
2695 values[i++] = ALC_MONO_SOURCES;
2696 values[i++] = device->NumMonoSources;
2698 values[i++] = ALC_STEREO_SOURCES;
2699 values[i++] = device->NumStereoSources;
2701 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2702 values[i++] = device->NumAuxSends;
2704 values[i++] = ALC_HRTF_SOFT;
2705 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2707 values[i++] = 0;
2708 return i;
2710 case ALC_FREQUENCY:
2711 values[0] = device->Frequency;
2712 return 1;
2714 case ALC_REFRESH:
2715 if(device->Type == Loopback)
2717 alcSetError(device, ALC_INVALID_DEVICE);
2718 return 0;
2720 values[0] = device->Frequency / device->UpdateSize;
2721 return 1;
2723 case ALC_SYNC:
2724 if(device->Type == Loopback)
2726 alcSetError(device, ALC_INVALID_DEVICE);
2727 return 0;
2729 values[0] = ALC_FALSE;
2730 return 1;
2732 case ALC_FORMAT_CHANNELS_SOFT:
2733 if(device->Type != Loopback)
2735 alcSetError(device, ALC_INVALID_DEVICE);
2736 return 0;
2738 values[0] = device->FmtChans;
2739 return 1;
2741 case ALC_FORMAT_TYPE_SOFT:
2742 if(device->Type != Loopback)
2744 alcSetError(device, ALC_INVALID_DEVICE);
2745 return 0;
2747 values[0] = device->FmtType;
2748 return 1;
2750 case ALC_MONO_SOURCES:
2751 values[0] = device->NumMonoSources;
2752 return 1;
2754 case ALC_STEREO_SOURCES:
2755 values[0] = device->NumStereoSources;
2756 return 1;
2758 case ALC_MAX_AUXILIARY_SENDS:
2759 values[0] = device->NumAuxSends;
2760 return 1;
2762 case ALC_CONNECTED:
2763 values[0] = device->Connected;
2764 return 1;
2766 case ALC_HRTF_SOFT:
2767 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2768 return 1;
2770 default:
2771 alcSetError(device, ALC_INVALID_ENUM);
2772 return 0;
2774 return 0;
2777 /* alcGetIntegerv
2779 * Returns information about the device and the version of OpenAL
2781 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2783 device = VerifyDevice(device);
2784 if(size <= 0 || values == NULL)
2785 alcSetError(device, ALC_INVALID_VALUE);
2786 else
2787 GetIntegerv(device, param, size, values);
2788 if(device) ALCdevice_DecRef(device);
2791 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2793 ALCint *ivals;
2794 ALsizei i;
2796 device = VerifyDevice(device);
2797 if(size <= 0 || values == NULL)
2798 alcSetError(device, ALC_INVALID_VALUE);
2799 else if(!device || device->Type == Capture)
2801 ivals = malloc(size * sizeof(ALCint));
2802 size = GetIntegerv(device, pname, size, ivals);
2803 for(i = 0;i < size;i++)
2804 values[i] = ivals[i];
2805 free(ivals);
2807 else /* render device */
2809 switch(pname)
2811 case ALC_ATTRIBUTES_SIZE:
2812 *values = 17;
2813 break;
2815 case ALC_ALL_ATTRIBUTES:
2816 if(size < 17)
2817 alcSetError(device, ALC_INVALID_VALUE);
2818 else
2820 int i = 0;
2822 V0(device->Backend,lock)();
2823 values[i++] = ALC_FREQUENCY;
2824 values[i++] = device->Frequency;
2826 if(device->Type != Loopback)
2828 values[i++] = ALC_REFRESH;
2829 values[i++] = device->Frequency / device->UpdateSize;
2831 values[i++] = ALC_SYNC;
2832 values[i++] = ALC_FALSE;
2834 else
2836 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2837 values[i++] = device->FmtChans;
2839 values[i++] = ALC_FORMAT_TYPE_SOFT;
2840 values[i++] = device->FmtType;
2843 values[i++] = ALC_MONO_SOURCES;
2844 values[i++] = device->NumMonoSources;
2846 values[i++] = ALC_STEREO_SOURCES;
2847 values[i++] = device->NumStereoSources;
2849 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2850 values[i++] = device->NumAuxSends;
2852 values[i++] = ALC_HRTF_SOFT;
2853 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2855 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2856 values[i++] = device->ClockBase +
2857 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2859 values[i++] = 0;
2860 V0(device->Backend,unlock)();
2862 break;
2864 case ALC_DEVICE_CLOCK_SOFT:
2865 V0(device->Backend,lock)();
2866 *values = device->ClockBase +
2867 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2868 V0(device->Backend,unlock)();
2869 break;
2871 default:
2872 ivals = malloc(size * sizeof(ALCint));
2873 size = GetIntegerv(device, pname, size, ivals);
2874 for(i = 0;i < size;i++)
2875 values[i] = ivals[i];
2876 free(ivals);
2877 break;
2880 if(device)
2881 ALCdevice_DecRef(device);
2885 /* alcIsExtensionPresent
2887 * Determines if there is support for a particular extension
2889 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2891 ALCboolean bResult = ALC_FALSE;
2893 device = VerifyDevice(device);
2895 if(!extName)
2896 alcSetError(device, ALC_INVALID_VALUE);
2897 else
2899 size_t len = strlen(extName);
2900 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2901 while(ptr && *ptr)
2903 if(strncasecmp(ptr, extName, len) == 0 &&
2904 (ptr[len] == '\0' || isspace(ptr[len])))
2906 bResult = ALC_TRUE;
2907 break;
2909 if((ptr=strchr(ptr, ' ')) != NULL)
2911 do {
2912 ++ptr;
2913 } while(isspace(*ptr));
2917 if(device)
2918 ALCdevice_DecRef(device);
2919 return bResult;
2923 /* alcGetProcAddress
2925 * Retrieves the function address for a particular extension function
2927 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2929 ALCvoid *ptr = NULL;
2931 if(!funcName)
2933 device = VerifyDevice(device);
2934 alcSetError(device, ALC_INVALID_VALUE);
2935 if(device) ALCdevice_DecRef(device);
2937 else
2939 ALsizei i = 0;
2940 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2941 i++;
2942 ptr = alcFunctions[i].address;
2945 return ptr;
2949 /* alcGetEnumValue
2951 * Get the value for a particular ALC enumeration name
2953 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2955 ALCenum val = 0;
2957 if(!enumName)
2959 device = VerifyDevice(device);
2960 alcSetError(device, ALC_INVALID_VALUE);
2961 if(device) ALCdevice_DecRef(device);
2963 else
2965 ALsizei i = 0;
2966 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2967 i++;
2968 val = enumeration[i].value;
2971 return val;
2975 /* alcCreateContext
2977 * Create and attach a context to the given device.
2979 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2981 ALCcontext *ALContext;
2982 ALCenum err;
2984 LockLists();
2985 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2987 UnlockLists();
2988 alcSetError(device, ALC_INVALID_DEVICE);
2989 if(device) ALCdevice_DecRef(device);
2990 return NULL;
2993 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
2995 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2997 UnlockLists();
2998 alcSetError(device, err);
2999 if(err == ALC_INVALID_DEVICE)
3001 ALCdevice_Lock(device);
3002 aluHandleDisconnect(device);
3003 ALCdevice_Unlock(device);
3005 ALCdevice_DecRef(device);
3006 return NULL;
3009 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3010 if(ALContext)
3012 InitRef(&ALContext->ref, 1);
3013 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3015 VECTOR_INIT(ALContext->ActiveAuxSlots);
3017 ALContext->VoiceCount = 0;
3018 ALContext->MaxVoices = 256;
3019 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3021 if(!ALContext || !ALContext->Voices)
3023 if(!ATOMIC_LOAD(&device->ContextList))
3025 V0(device->Backend,stop)();
3026 device->Flags &= ~DEVICE_RUNNING;
3028 UnlockLists();
3030 if(ALContext)
3032 al_free(ALContext->Voices);
3033 ALContext->Voices = NULL;
3035 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3037 al_free(ALContext);
3038 ALContext = NULL;
3041 alcSetError(device, ALC_OUT_OF_MEMORY);
3042 ALCdevice_DecRef(device);
3043 return NULL;
3046 ALContext->Device = device;
3047 ALCdevice_IncRef(device);
3048 InitContext(ALContext);
3051 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3052 do {
3053 ALContext->next = head;
3054 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3056 UnlockLists();
3058 ALCdevice_DecRef(device);
3060 TRACE("Created context %p\n", ALContext);
3061 return ALContext;
3064 /* alcDestroyContext
3066 * Remove a context from its device
3068 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3070 ALCdevice *Device;
3072 LockLists();
3073 /* alcGetContextsDevice sets an error for invalid contexts */
3074 Device = alcGetContextsDevice(context);
3075 if(Device)
3077 ReleaseContext(context, Device);
3078 if(!ATOMIC_LOAD(&Device->ContextList))
3080 V0(Device->Backend,stop)();
3081 Device->Flags &= ~DEVICE_RUNNING;
3084 UnlockLists();
3088 /* alcGetCurrentContext
3090 * Returns the currently active context on the calling thread
3092 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3094 ALCcontext *Context = altss_get(LocalContext);
3095 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3096 return Context;
3099 /* alcGetThreadContext
3101 * Returns the currently active thread-local context
3103 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3105 return altss_get(LocalContext);
3109 /* alcMakeContextCurrent
3111 * Makes the given context the active process-wide context, and removes the
3112 * thread-local context for the calling thread.
3114 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3116 /* context must be valid or NULL */
3117 if(context && !(context=VerifyContext(context)))
3119 alcSetError(NULL, ALC_INVALID_CONTEXT);
3120 return ALC_FALSE;
3122 /* context's reference count is already incremented */
3123 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3124 if(context) ALCcontext_DecRef(context);
3126 if((context=altss_get(LocalContext)) != NULL)
3128 altss_set(LocalContext, NULL);
3129 ALCcontext_DecRef(context);
3132 return ALC_TRUE;
3135 /* alcSetThreadContext
3137 * Makes the given context the active context for the current thread
3139 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3141 ALCcontext *old;
3143 /* context must be valid or NULL */
3144 if(context && !(context=VerifyContext(context)))
3146 alcSetError(NULL, ALC_INVALID_CONTEXT);
3147 return ALC_FALSE;
3149 /* context's reference count is already incremented */
3150 old = altss_get(LocalContext);
3151 altss_set(LocalContext, context);
3152 if(old) ALCcontext_DecRef(old);
3154 return ALC_TRUE;
3158 /* alcGetContextsDevice
3160 * Returns the device that a particular context is attached to
3162 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3164 ALCdevice *Device;
3166 if(!(Context=VerifyContext(Context)))
3168 alcSetError(NULL, ALC_INVALID_CONTEXT);
3169 return NULL;
3171 Device = Context->Device;
3172 ALCcontext_DecRef(Context);
3174 return Device;
3178 /* alcOpenDevice
3180 * Opens the named device.
3182 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3184 const ALCchar *fmt;
3185 ALCdevice *device;
3186 ALCenum err;
3188 DO_INITCONFIG();
3190 if(!PlaybackBackend.name)
3192 alcSetError(NULL, ALC_INVALID_VALUE);
3193 return NULL;
3196 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3197 deviceName = NULL;
3199 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3200 if(!device)
3202 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3203 return NULL;
3206 //Validate device
3207 InitRef(&device->ref, 1);
3208 device->Connected = ALC_TRUE;
3209 device->Type = Playback;
3210 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3212 device->Flags = 0;
3213 device->Bs2b = NULL;
3214 device->Bs2bLevel = 0;
3215 AL_STRING_INIT(device->DeviceName);
3217 ATOMIC_INIT(&device->ContextList, NULL);
3219 device->ClockBase = 0;
3220 device->SamplesDone = 0;
3222 device->MaxNoOfSources = 256;
3223 device->AuxiliaryEffectSlotMax = 4;
3224 device->NumAuxSends = MAX_SENDS;
3226 InitUIntMap(&device->BufferMap, ~0);
3227 InitUIntMap(&device->EffectMap, ~0);
3228 InitUIntMap(&device->FilterMap, ~0);
3229 InitUIntMap(&device->SfontMap, ~0);
3230 InitUIntMap(&device->PresetMap, ~0);
3231 InitUIntMap(&device->FontsoundMap, ~0);
3233 //Set output format
3234 device->FmtChans = DevFmtChannelsDefault;
3235 device->FmtType = DevFmtTypeDefault;
3236 device->Frequency = DEFAULT_OUTPUT_RATE;
3237 device->NumUpdates = 4;
3238 device->UpdateSize = 1024;
3240 if(!PlaybackBackend.getFactory)
3241 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3242 ALCbackend_Playback);
3243 else
3245 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3246 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3248 if(!device->Backend)
3250 al_free(device);
3251 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3252 return NULL;
3256 if(ConfigValueStr(NULL, "channels", &fmt))
3258 static const struct {
3259 const char name[16];
3260 enum DevFmtChannels chans;
3261 } chanlist[] = {
3262 { "mono", DevFmtMono },
3263 { "stereo", DevFmtStereo },
3264 { "quad", DevFmtQuad },
3265 { "surround51", DevFmtX51 },
3266 { "surround61", DevFmtX61 },
3267 { "surround71", DevFmtX71 },
3269 size_t i;
3271 for(i = 0;i < COUNTOF(chanlist);i++)
3273 if(strcasecmp(chanlist[i].name, fmt) == 0)
3275 device->FmtChans = chanlist[i].chans;
3276 device->Flags |= DEVICE_CHANNELS_REQUEST;
3277 break;
3280 if(i == COUNTOF(chanlist))
3281 ERR("Unsupported channels: %s\n", fmt);
3283 if(ConfigValueStr(NULL, "sample-type", &fmt))
3285 static const struct {
3286 const char name[16];
3287 enum DevFmtType type;
3288 } typelist[] = {
3289 { "int8", DevFmtByte },
3290 { "uint8", DevFmtUByte },
3291 { "int16", DevFmtShort },
3292 { "uint16", DevFmtUShort },
3293 { "int32", DevFmtInt },
3294 { "uint32", DevFmtUInt },
3295 { "float32", DevFmtFloat },
3297 size_t i;
3299 for(i = 0;i < COUNTOF(typelist);i++)
3301 if(strcasecmp(typelist[i].name, fmt) == 0)
3303 device->FmtType = typelist[i].type;
3304 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3305 break;
3308 if(i == COUNTOF(typelist))
3309 ERR("Unsupported sample-type: %s\n", fmt);
3311 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3312 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3313 ConfigValueStr(NULL, "format", &fmt))
3315 static const struct {
3316 const char name[32];
3317 enum DevFmtChannels channels;
3318 enum DevFmtType type;
3319 } formats[] = {
3320 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3321 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3322 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3323 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3324 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3325 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3327 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3328 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3329 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3330 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3331 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3332 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3334 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3335 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3336 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3337 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3338 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3339 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3341 size_t i;
3343 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3344 for(i = 0;i < COUNTOF(formats);i++)
3346 if(strcasecmp(fmt, formats[i].name) == 0)
3348 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3349 device->FmtChans = formats[i].channels;
3350 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3351 device->FmtType = formats[i].type;
3352 device->Flags |= DEVICE_FORMAT_REQUEST;
3353 break;
3356 if(i == COUNTOF(formats))
3357 ERR("Unsupported format: %s\n", fmt);
3359 #undef DEVICE_FORMAT_REQUEST
3361 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3363 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3364 if(device->Frequency < MIN_OUTPUT_RATE)
3365 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3366 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3369 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3370 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3372 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3373 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3374 if((CPUCapFlags&CPU_CAP_SSE))
3375 device->UpdateSize = (device->UpdateSize+3)&~3;
3377 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3378 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3380 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3381 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3383 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3384 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3386 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3388 device->NumStereoSources = 1;
3389 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3391 device->Synth = SynthCreate(device);
3392 if(!device->Synth)
3394 DELETE_OBJ(device->Backend);
3395 al_free(device);
3396 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3397 return NULL;
3400 // Find a playback device to open
3401 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3403 DELETE_OBJ(device->Synth);
3404 DELETE_OBJ(device->Backend);
3405 al_free(device);
3406 alcSetError(NULL, err);
3407 return NULL;
3410 if(DefaultEffect.type != AL_EFFECT_NULL)
3412 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3413 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3415 device->DefaultSlot = NULL;
3416 ERR("Failed to initialize the default effect slot\n");
3418 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3420 ALeffectState *state = device->DefaultSlot->EffectState;
3421 device->DefaultSlot = NULL;
3422 DELETE_OBJ(state);
3423 ERR("Failed to initialize the default effect\n");
3428 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3429 do {
3430 device->next = head;
3431 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3434 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3435 return device;
3438 /* alcCloseDevice
3440 * Closes the given device.
3442 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3444 ALCdevice *list, *origdev, *nextdev;
3445 ALCcontext *ctx;
3447 LockLists();
3448 list = ATOMIC_LOAD(&DeviceList);
3449 do {
3450 if(list == device)
3451 break;
3452 } while((list=list->next) != NULL);
3453 if(!list || list->Type == Capture)
3455 alcSetError(list, ALC_INVALID_DEVICE);
3456 UnlockLists();
3457 return ALC_FALSE;
3460 origdev = device;
3461 nextdev = device->next;
3462 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3464 do {
3465 list = origdev;
3466 origdev = device;
3467 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3469 UnlockLists();
3471 ctx = ATOMIC_LOAD(&device->ContextList);
3472 while(ctx != NULL)
3474 ALCcontext *next = ctx->next;
3475 WARN("Releasing context %p\n", ctx);
3476 ReleaseContext(ctx, device);
3477 ctx = next;
3479 if((device->Flags&DEVICE_RUNNING))
3480 V0(device->Backend,stop)();
3481 device->Flags &= ~DEVICE_RUNNING;
3483 ALCdevice_DecRef(device);
3485 return ALC_TRUE;
3489 /************************************************
3490 * ALC capture functions
3491 ************************************************/
3492 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3494 ALCdevice *device = NULL;
3495 ALCenum err;
3497 DO_INITCONFIG();
3499 if(!CaptureBackend.name)
3501 alcSetError(NULL, ALC_INVALID_VALUE);
3502 return NULL;
3505 if(samples <= 0)
3507 alcSetError(NULL, ALC_INVALID_VALUE);
3508 return NULL;
3511 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3512 deviceName = NULL;
3514 device = al_calloc(16, sizeof(ALCdevice));
3515 if(!device)
3517 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3518 return NULL;
3521 //Validate device
3522 InitRef(&device->ref, 1);
3523 device->Connected = ALC_TRUE;
3524 device->Type = Capture;
3526 AL_STRING_INIT(device->DeviceName);
3528 InitUIntMap(&device->BufferMap, ~0);
3529 InitUIntMap(&device->EffectMap, ~0);
3530 InitUIntMap(&device->FilterMap, ~0);
3531 InitUIntMap(&device->SfontMap, ~0);
3532 InitUIntMap(&device->PresetMap, ~0);
3533 InitUIntMap(&device->FontsoundMap, ~0);
3535 if(!CaptureBackend.getFactory)
3536 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3537 ALCbackend_Capture);
3538 else
3540 ALCbackendFactory *factory = CaptureBackend.getFactory();
3541 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3543 if(!device->Backend)
3545 al_free(device);
3546 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3547 return NULL;
3550 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3551 device->Frequency = frequency;
3553 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3554 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3556 al_free(device);
3557 alcSetError(NULL, ALC_INVALID_ENUM);
3558 return NULL;
3561 device->UpdateSize = samples;
3562 device->NumUpdates = 1;
3564 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3566 al_free(device);
3567 alcSetError(NULL, err);
3568 return NULL;
3572 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3573 do {
3574 device->next = head;
3575 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3578 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3579 return device;
3582 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3584 ALCdevice *list, *next, *nextdev;
3586 LockLists();
3587 list = ATOMIC_LOAD(&DeviceList);
3588 do {
3589 if(list == device)
3590 break;
3591 } while((list=list->next) != NULL);
3592 if(!list || list->Type != Capture)
3594 alcSetError(list, ALC_INVALID_DEVICE);
3595 UnlockLists();
3596 return ALC_FALSE;
3599 next = device;
3600 nextdev = device->next;
3601 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3603 do {
3604 list = next;
3605 next = device;
3606 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3608 UnlockLists();
3610 ALCdevice_DecRef(device);
3612 return ALC_TRUE;
3615 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3617 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3618 alcSetError(device, ALC_INVALID_DEVICE);
3619 else
3621 ALCdevice_Lock(device);
3622 if(device->Connected)
3624 if(!(device->Flags&DEVICE_RUNNING))
3625 V0(device->Backend,start)();
3626 device->Flags |= DEVICE_RUNNING;
3628 ALCdevice_Unlock(device);
3631 if(device) ALCdevice_DecRef(device);
3634 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3636 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3637 alcSetError(device, ALC_INVALID_DEVICE);
3638 else
3640 ALCdevice_Lock(device);
3641 if((device->Flags&DEVICE_RUNNING))
3642 V0(device->Backend,stop)();
3643 device->Flags &= ~DEVICE_RUNNING;
3644 ALCdevice_Unlock(device);
3647 if(device) ALCdevice_DecRef(device);
3650 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3652 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3653 alcSetError(device, ALC_INVALID_DEVICE);
3654 else
3656 ALCenum err = ALC_INVALID_VALUE;
3658 ALCdevice_Lock(device);
3659 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3660 err = V(device->Backend,captureSamples)(buffer, samples);
3661 ALCdevice_Unlock(device);
3663 if(err != ALC_NO_ERROR)
3664 alcSetError(device, err);
3666 if(device) ALCdevice_DecRef(device);
3670 /************************************************
3671 * ALC loopback functions
3672 ************************************************/
3674 /* alcLoopbackOpenDeviceSOFT
3676 * Open a loopback device, for manual rendering.
3678 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3680 ALCbackendFactory *factory;
3681 ALCdevice *device;
3683 DO_INITCONFIG();
3685 /* Make sure the device name, if specified, is us. */
3686 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3688 alcSetError(NULL, ALC_INVALID_VALUE);
3689 return NULL;
3692 device = al_calloc(16, sizeof(ALCdevice));
3693 if(!device)
3695 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3696 return NULL;
3699 //Validate device
3700 InitRef(&device->ref, 1);
3701 device->Connected = ALC_TRUE;
3702 device->Type = Loopback;
3703 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3705 device->Flags = 0;
3706 device->Bs2b = NULL;
3707 device->Bs2bLevel = 0;
3708 AL_STRING_INIT(device->DeviceName);
3710 ATOMIC_INIT(&device->ContextList, NULL);
3712 device->ClockBase = 0;
3713 device->SamplesDone = 0;
3715 device->MaxNoOfSources = 256;
3716 device->AuxiliaryEffectSlotMax = 4;
3717 device->NumAuxSends = MAX_SENDS;
3719 InitUIntMap(&device->BufferMap, ~0);
3720 InitUIntMap(&device->EffectMap, ~0);
3721 InitUIntMap(&device->FilterMap, ~0);
3722 InitUIntMap(&device->SfontMap, ~0);
3723 InitUIntMap(&device->PresetMap, ~0);
3724 InitUIntMap(&device->FontsoundMap, ~0);
3726 factory = ALCloopbackFactory_getFactory();
3727 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3728 if(!device->Backend)
3730 al_free(device);
3731 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3732 return NULL;
3735 //Set output format
3736 device->NumUpdates = 0;
3737 device->UpdateSize = 0;
3739 device->Frequency = DEFAULT_OUTPUT_RATE;
3740 device->FmtChans = DevFmtChannelsDefault;
3741 device->FmtType = DevFmtTypeDefault;
3743 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3744 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3746 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3747 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3749 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3750 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3752 device->NumStereoSources = 1;
3753 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3755 device->Synth = SynthCreate(device);
3756 if(!device->Synth)
3758 DELETE_OBJ(device->Backend);
3759 al_free(device);
3760 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3761 return NULL;
3764 // Open the "backend"
3765 V(device->Backend,open)("Loopback");
3768 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3769 do {
3770 device->next = head;
3771 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3774 TRACE("Created device %p\n", device);
3775 return device;
3778 /* alcIsRenderFormatSupportedSOFT
3780 * Determines if the loopback device supports the given format for rendering.
3782 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3784 ALCboolean ret = ALC_FALSE;
3786 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3787 alcSetError(device, ALC_INVALID_DEVICE);
3788 else if(freq <= 0)
3789 alcSetError(device, ALC_INVALID_VALUE);
3790 else
3792 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3793 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3794 freq >= MIN_OUTPUT_RATE)
3795 ret = ALC_TRUE;
3797 if(device) ALCdevice_DecRef(device);
3799 return ret;
3802 /* alcRenderSamplesSOFT
3804 * Renders some samples into a buffer, using the format last set by the
3805 * attributes given to alcCreateContext.
3807 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3809 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3810 alcSetError(device, ALC_INVALID_DEVICE);
3811 else if(samples < 0 || (samples > 0 && buffer == NULL))
3812 alcSetError(device, ALC_INVALID_VALUE);
3813 else
3814 aluMixData(device, buffer, samples);
3815 if(device) ALCdevice_DecRef(device);
3819 /************************************************
3820 * ALC DSP pause/resume functions
3821 ************************************************/
3823 /* alcDevicePauseSOFT
3825 * Pause the DSP to stop audio processing.
3827 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3829 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3830 alcSetError(device, ALC_INVALID_DEVICE);
3831 else
3833 LockLists();
3834 if((device->Flags&DEVICE_RUNNING))
3835 V0(device->Backend,stop)();
3836 device->Flags &= ~DEVICE_RUNNING;
3837 device->Flags |= DEVICE_PAUSED;
3838 UnlockLists();
3840 if(device) ALCdevice_DecRef(device);
3843 /* alcDeviceResumeSOFT
3845 * Resume the DSP to restart audio processing.
3847 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3849 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3850 alcSetError(device, ALC_INVALID_DEVICE);
3851 else
3853 LockLists();
3854 if((device->Flags&DEVICE_PAUSED))
3856 device->Flags &= ~DEVICE_PAUSED;
3857 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3859 if(V0(device->Backend,start)() != ALC_FALSE)
3860 device->Flags |= DEVICE_RUNNING;
3861 else
3863 alcSetError(device, ALC_INVALID_DEVICE);
3864 ALCdevice_Lock(device);
3865 aluHandleDisconnect(device);
3866 ALCdevice_Unlock(device);
3870 UnlockLists();
3872 if(device) ALCdevice_DecRef(device);