Make alcSuspendContext and alcProcessContext batch updates
[openal-soft.git] / Alc / ALc.c
blob781e072946811d3f4d6ce3e7edcd77844a372ab9
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),
501 DECL(AL_MONO_SOFT),
502 DECL(AL_STEREO_SOFT),
503 DECL(AL_QUAD_SOFT),
504 DECL(AL_REAR_SOFT),
505 DECL(AL_5POINT1_SOFT),
506 DECL(AL_6POINT1_SOFT),
507 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BYTE_SOFT),
510 DECL(AL_UNSIGNED_BYTE_SOFT),
511 DECL(AL_SHORT_SOFT),
512 DECL(AL_UNSIGNED_SHORT_SOFT),
513 DECL(AL_INT_SOFT),
514 DECL(AL_UNSIGNED_INT_SOFT),
515 DECL(AL_FLOAT_SOFT),
516 DECL(AL_DOUBLE_SOFT),
517 DECL(AL_BYTE3_SOFT),
518 DECL(AL_UNSIGNED_BYTE3_SOFT),
520 DECL(AL_FREQUENCY),
521 DECL(AL_BITS),
522 DECL(AL_CHANNELS),
523 DECL(AL_SIZE),
524 DECL(AL_INTERNAL_FORMAT_SOFT),
525 DECL(AL_BYTE_LENGTH_SOFT),
526 DECL(AL_SAMPLE_LENGTH_SOFT),
527 DECL(AL_SEC_LENGTH_SOFT),
528 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
531 DECL(AL_UNUSED),
532 DECL(AL_PENDING),
533 DECL(AL_PROCESSED),
535 DECL(AL_NO_ERROR),
536 DECL(AL_INVALID_NAME),
537 DECL(AL_INVALID_ENUM),
538 DECL(AL_INVALID_VALUE),
539 DECL(AL_INVALID_OPERATION),
540 DECL(AL_OUT_OF_MEMORY),
542 DECL(AL_VENDOR),
543 DECL(AL_VERSION),
544 DECL(AL_RENDERER),
545 DECL(AL_EXTENSIONS),
547 DECL(AL_DOPPLER_FACTOR),
548 DECL(AL_DOPPLER_VELOCITY),
549 DECL(AL_DISTANCE_MODEL),
550 DECL(AL_SPEED_OF_SOUND),
551 DECL(AL_SOURCE_DISTANCE_MODEL),
552 DECL(AL_DEFERRED_UPDATES_SOFT),
554 DECL(AL_INVERSE_DISTANCE),
555 DECL(AL_INVERSE_DISTANCE_CLAMPED),
556 DECL(AL_LINEAR_DISTANCE),
557 DECL(AL_LINEAR_DISTANCE_CLAMPED),
558 DECL(AL_EXPONENT_DISTANCE),
559 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
561 DECL(AL_FILTER_TYPE),
562 DECL(AL_FILTER_NULL),
563 DECL(AL_FILTER_LOWPASS),
564 DECL(AL_FILTER_HIGHPASS),
565 DECL(AL_FILTER_BANDPASS),
567 DECL(AL_LOWPASS_GAIN),
568 DECL(AL_LOWPASS_GAINHF),
570 DECL(AL_HIGHPASS_GAIN),
571 DECL(AL_HIGHPASS_GAINLF),
573 DECL(AL_BANDPASS_GAIN),
574 DECL(AL_BANDPASS_GAINHF),
575 DECL(AL_BANDPASS_GAINLF),
577 DECL(AL_EFFECT_TYPE),
578 DECL(AL_EFFECT_NULL),
579 DECL(AL_EFFECT_REVERB),
580 DECL(AL_EFFECT_EAXREVERB),
581 DECL(AL_EFFECT_CHORUS),
582 DECL(AL_EFFECT_DISTORTION),
583 DECL(AL_EFFECT_ECHO),
584 DECL(AL_EFFECT_FLANGER),
585 #if 0
586 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
587 DECL(AL_EFFECT_VOCAL_MORPHER),
588 DECL(AL_EFFECT_PITCH_SHIFTER),
589 #endif
590 DECL(AL_EFFECT_RING_MODULATOR),
591 #if 0
592 DECL(AL_EFFECT_AUTOWAH),
593 #endif
594 DECL(AL_EFFECT_COMPRESSOR),
595 DECL(AL_EFFECT_EQUALIZER),
596 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
597 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
599 DECL(AL_EAXREVERB_DENSITY),
600 DECL(AL_EAXREVERB_DIFFUSION),
601 DECL(AL_EAXREVERB_GAIN),
602 DECL(AL_EAXREVERB_GAINHF),
603 DECL(AL_EAXREVERB_GAINLF),
604 DECL(AL_EAXREVERB_DECAY_TIME),
605 DECL(AL_EAXREVERB_DECAY_HFRATIO),
606 DECL(AL_EAXREVERB_DECAY_LFRATIO),
607 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
608 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
609 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
610 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
611 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
612 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
613 DECL(AL_EAXREVERB_ECHO_TIME),
614 DECL(AL_EAXREVERB_ECHO_DEPTH),
615 DECL(AL_EAXREVERB_MODULATION_TIME),
616 DECL(AL_EAXREVERB_MODULATION_DEPTH),
617 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
618 DECL(AL_EAXREVERB_HFREFERENCE),
619 DECL(AL_EAXREVERB_LFREFERENCE),
620 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
621 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
623 DECL(AL_REVERB_DENSITY),
624 DECL(AL_REVERB_DIFFUSION),
625 DECL(AL_REVERB_GAIN),
626 DECL(AL_REVERB_GAINHF),
627 DECL(AL_REVERB_DECAY_TIME),
628 DECL(AL_REVERB_DECAY_HFRATIO),
629 DECL(AL_REVERB_REFLECTIONS_GAIN),
630 DECL(AL_REVERB_REFLECTIONS_DELAY),
631 DECL(AL_REVERB_LATE_REVERB_GAIN),
632 DECL(AL_REVERB_LATE_REVERB_DELAY),
633 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
634 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_REVERB_DECAY_HFLIMIT),
637 DECL(AL_CHORUS_WAVEFORM),
638 DECL(AL_CHORUS_PHASE),
639 DECL(AL_CHORUS_RATE),
640 DECL(AL_CHORUS_DEPTH),
641 DECL(AL_CHORUS_FEEDBACK),
642 DECL(AL_CHORUS_DELAY),
644 DECL(AL_DISTORTION_EDGE),
645 DECL(AL_DISTORTION_GAIN),
646 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
647 DECL(AL_DISTORTION_EQCENTER),
648 DECL(AL_DISTORTION_EQBANDWIDTH),
650 DECL(AL_ECHO_DELAY),
651 DECL(AL_ECHO_LRDELAY),
652 DECL(AL_ECHO_DAMPING),
653 DECL(AL_ECHO_FEEDBACK),
654 DECL(AL_ECHO_SPREAD),
656 DECL(AL_FLANGER_WAVEFORM),
657 DECL(AL_FLANGER_PHASE),
658 DECL(AL_FLANGER_RATE),
659 DECL(AL_FLANGER_DEPTH),
660 DECL(AL_FLANGER_FEEDBACK),
661 DECL(AL_FLANGER_DELAY),
663 DECL(AL_RING_MODULATOR_FREQUENCY),
664 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
665 DECL(AL_RING_MODULATOR_WAVEFORM),
667 #if 0
668 DECL(AL_AUTOWAH_ATTACK_TIME),
669 DECL(AL_AUTOWAH_PEAK_GAIN),
670 DECL(AL_AUTOWAH_RELEASE_TIME),
671 DECL(AL_AUTOWAH_RESONANCE),
672 #endif
674 DECL(AL_COMPRESSOR_ONOFF),
676 DECL(AL_EQUALIZER_LOW_GAIN),
677 DECL(AL_EQUALIZER_LOW_CUTOFF),
678 DECL(AL_EQUALIZER_MID1_GAIN),
679 DECL(AL_EQUALIZER_MID1_CENTER),
680 DECL(AL_EQUALIZER_MID1_WIDTH),
681 DECL(AL_EQUALIZER_MID2_GAIN),
682 DECL(AL_EQUALIZER_MID2_CENTER),
683 DECL(AL_EQUALIZER_MID2_WIDTH),
684 DECL(AL_EQUALIZER_HIGH_GAIN),
685 DECL(AL_EQUALIZER_HIGH_CUTOFF),
687 DECL(AL_DEDICATED_GAIN),
689 { NULL, (ALCenum)0 }
691 #undef DECL
693 static const ALCchar alcNoError[] = "No Error";
694 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
695 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
696 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
697 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
698 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
701 /************************************************
702 * Global variables
703 ************************************************/
705 /* Enumerated device names */
706 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
708 static al_string alcAllDevicesList;
709 static al_string alcCaptureDeviceList;
711 /* Default is always the first in the list */
712 static ALCchar *alcDefaultAllDevicesSpecifier;
713 static ALCchar *alcCaptureDefaultDeviceSpecifier;
715 /* Default context extensions */
716 static const ALchar alExtList[] =
717 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
718 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
719 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
720 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples "
721 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
722 "AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency "
723 "AL_SOFT_source_length";
725 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
727 /* Thread-local current context */
728 static altss_t LocalContext;
729 /* Process-wide current context */
730 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
732 /* Mixing thread piority level */
733 ALint RTPrioLevel;
735 FILE *LogFile;
736 #ifdef _DEBUG
737 enum LogLevel LogLevel = LogWarning;
738 #else
739 enum LogLevel LogLevel = LogError;
740 #endif
742 /* Flag to trap ALC device errors */
743 static ALCboolean TrapALCError = ALC_FALSE;
745 /* One-time configuration init control */
746 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
748 /* Default effect that applies to sources that don't have an effect on send 0 */
749 static ALeffect DefaultEffect;
751 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
752 * updates.
754 static ALCboolean SuspendDefers = ALC_TRUE;
757 /************************************************
758 * ALC information
759 ************************************************/
760 static const ALCchar alcNoDeviceExtList[] =
761 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
762 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
763 static const ALCchar alcExtensionList[] =
764 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
765 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
766 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
767 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
768 static const ALCint alcMajorVersion = 1;
769 static const ALCint alcMinorVersion = 1;
771 static const ALCint alcEFXMajorVersion = 1;
772 static const ALCint alcEFXMinorVersion = 0;
775 /************************************************
776 * Device lists
777 ************************************************/
778 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
780 static almtx_t ListLock;
781 static inline void LockLists(void)
783 int lockret = almtx_lock(&ListLock);
784 assert(lockret == althrd_success);
786 static inline void UnlockLists(void)
788 int unlockret = almtx_unlock(&ListLock);
789 assert(unlockret == althrd_success);
792 /************************************************
793 * Library initialization
794 ************************************************/
795 #if defined(_WIN32)
796 static void alc_init(void);
797 static void alc_deinit(void);
798 static void alc_deinit_safe(void);
800 #ifndef AL_LIBTYPE_STATIC
801 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
803 switch(reason)
805 case DLL_PROCESS_ATTACH:
806 /* Pin the DLL so we won't get unloaded until the process terminates */
807 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
808 (WCHAR*)hModule, &hModule);
809 alc_init();
810 break;
812 case DLL_THREAD_DETACH:
813 break;
815 case DLL_PROCESS_DETACH:
816 if(!lpReserved)
817 alc_deinit();
818 else
819 alc_deinit_safe();
820 break;
822 return TRUE;
824 #elif defined(_MSC_VER)
825 #pragma section(".CRT$XCU",read)
826 static void alc_constructor(void);
827 static void alc_destructor(void);
828 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
830 static void alc_constructor(void)
832 atexit(alc_destructor);
833 alc_init();
836 static void alc_destructor(void)
838 alc_deinit();
840 #elif defined(HAVE_GCC_DESTRUCTOR)
841 static void alc_init(void) __attribute__((constructor));
842 static void alc_deinit(void) __attribute__((destructor));
843 #else
844 #error "No static initialization available on this platform!"
845 #endif
847 #elif defined(HAVE_GCC_DESTRUCTOR)
849 static void alc_init(void) __attribute__((constructor));
850 static void alc_deinit(void) __attribute__((destructor));
852 #else
853 #error "No global initialization available on this platform!"
854 #endif
856 static void ReleaseThreadCtx(void *ptr);
857 static void alc_init(void)
859 const char *str;
860 int ret;
862 LogFile = stderr;
864 AL_STRING_INIT(alcAllDevicesList);
865 AL_STRING_INIT(alcCaptureDeviceList);
867 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
868 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
869 ConeScale *= 0.5f;
871 str = getenv("__ALSOFT_REVERSE_Z");
872 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
873 ZScale *= -1.0f;
875 ret = altss_create(&LocalContext, ReleaseThreadCtx);
876 assert(ret == althrd_success);
878 ret = almtx_init(&ListLock, almtx_recursive);
879 assert(ret == althrd_success);
881 ThunkInit();
884 static void alc_initconfig(void)
886 const char *devs, *str;
887 ALuint capfilter;
888 float valf;
889 int i, n;
891 str = getenv("ALSOFT_LOGLEVEL");
892 if(str)
894 long lvl = strtol(str, NULL, 0);
895 if(lvl >= NoLog && lvl <= LogRef)
896 LogLevel = lvl;
899 str = getenv("ALSOFT_LOGFILE");
900 if(str && str[0])
902 FILE *logfile = al_fopen(str, "wt");
903 if(logfile) LogFile = logfile;
904 else ERR("Failed to open log file '%s'\n", str);
908 char buf[1024] = "";
909 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
910 for(i = 1;BackendList[i].name;i++)
911 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
912 TRACE("Supported backends: %s\n", buf);
914 ReadALConfig();
916 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
917 if(str && *str)
919 if(strcasecmp(str, "ignore") == 0)
921 SuspendDefers = ALC_FALSE;
922 TRACE("Selected context suspend behavior, \"ignore\"\n");
924 else
925 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
928 capfilter = 0;
929 #if defined(HAVE_SSE4_1)
930 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
931 #elif defined(HAVE_SSE2)
932 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
933 #elif defined(HAVE_SSE)
934 capfilter |= CPU_CAP_SSE;
935 #endif
936 #ifdef HAVE_NEON
937 capfilter |= CPU_CAP_NEON;
938 #endif
939 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
941 if(strcasecmp(str, "all") == 0)
942 capfilter = 0;
943 else
945 size_t len;
946 const char *next = str;
948 do {
949 str = next;
950 while(isspace(str[0]))
951 str++;
952 next = strchr(str, ',');
954 if(!str[0] || str[0] == ',')
955 continue;
957 len = (next ? ((size_t)(next-str)) : strlen(str));
958 while(len > 0 && isspace(str[len-1]))
959 len--;
960 if(len == 3 && strncasecmp(str, "sse", len) == 0)
961 capfilter &= ~CPU_CAP_SSE;
962 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
963 capfilter &= ~CPU_CAP_SSE2;
964 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
965 capfilter &= ~CPU_CAP_SSE4_1;
966 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
967 capfilter &= ~CPU_CAP_NEON;
968 else
969 WARN("Invalid CPU extension \"%s\"\n", str);
970 } while(next++);
973 FillCPUCaps(capfilter);
975 #ifdef _WIN32
976 RTPrioLevel = 1;
977 #else
978 RTPrioLevel = 0;
979 #endif
980 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
982 if(ConfigValueStr(NULL, "resampler", &str))
984 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
985 DefaultResampler = PointResampler;
986 else if(strcasecmp(str, "linear") == 0)
987 DefaultResampler = LinearResampler;
988 else if(strcasecmp(str, "cubic") == 0)
989 DefaultResampler = CubicResampler;
990 else
992 char *end;
994 n = strtol(str, &end, 0);
995 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
996 DefaultResampler = n;
997 else
998 WARN("Invalid resampler: %s\n", str);
1002 str = getenv("ALSOFT_TRAP_ERROR");
1003 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1005 TrapALError = AL_TRUE;
1006 TrapALCError = AL_TRUE;
1008 else
1010 str = getenv("ALSOFT_TRAP_AL_ERROR");
1011 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1012 TrapALError = AL_TRUE;
1013 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
1015 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1016 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1017 TrapALCError = ALC_TRUE;
1018 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1021 if(ConfigValueFloat("reverb", "boost", &valf))
1022 ReverbBoost *= powf(10.0f, valf / 20.0f);
1024 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1026 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1027 ConfigValueStr(NULL, "drivers", &devs))
1029 int n;
1030 size_t len;
1031 const char *next = devs;
1032 int endlist, delitem;
1034 i = 0;
1035 do {
1036 devs = next;
1037 while(isspace(devs[0]))
1038 devs++;
1039 next = strchr(devs, ',');
1041 delitem = (devs[0] == '-');
1042 if(devs[0] == '-') devs++;
1044 if(!devs[0] || devs[0] == ',')
1046 endlist = 0;
1047 continue;
1049 endlist = 1;
1051 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1052 while(len > 0 && isspace(devs[len-1]))
1053 len--;
1054 for(n = i;BackendList[n].name;n++)
1056 if(len == strlen(BackendList[n].name) &&
1057 strncmp(BackendList[n].name, devs, len) == 0)
1059 if(delitem)
1061 do {
1062 BackendList[n] = BackendList[n+1];
1063 ++n;
1064 } while(BackendList[n].name);
1066 else
1068 struct BackendInfo Bkp = BackendList[n];
1069 while(n > i)
1071 BackendList[n] = BackendList[n-1];
1072 --n;
1074 BackendList[n] = Bkp;
1076 i++;
1078 break;
1081 } while(next++);
1083 if(endlist)
1085 BackendList[i].name = NULL;
1086 BackendList[i].getFactory = NULL;
1087 BackendList[i].Init = NULL;
1088 BackendList[i].Deinit = NULL;
1089 BackendList[i].Probe = NULL;
1093 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1095 if(BackendList[i].getFactory)
1097 ALCbackendFactory *factory = BackendList[i].getFactory();
1098 if(!V0(factory,init)())
1100 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1101 continue;
1104 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1105 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1107 PlaybackBackend = BackendList[i];
1108 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1110 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1112 CaptureBackend = BackendList[i];
1113 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1116 continue;
1119 if(!BackendList[i].Init(&BackendList[i].Funcs))
1121 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1122 continue;
1125 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1126 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1128 PlaybackBackend = BackendList[i];
1129 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1131 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1133 CaptureBackend = BackendList[i];
1134 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1138 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1139 V0(factory,init)();
1142 if(ConfigValueStr(NULL, "excludefx", &str))
1144 size_t len;
1145 const char *next = str;
1147 do {
1148 str = next;
1149 next = strchr(str, ',');
1151 if(!str[0] || next == str)
1152 continue;
1154 len = (next ? ((size_t)(next-str)) : strlen(str));
1155 for(n = 0;EffectList[n].name;n++)
1157 if(len == strlen(EffectList[n].name) &&
1158 strncmp(EffectList[n].name, str, len) == 0)
1159 DisabledEffects[EffectList[n].type] = AL_TRUE;
1161 } while(next++);
1164 InitEffectFactoryMap();
1166 InitEffect(&DefaultEffect);
1167 str = getenv("ALSOFT_DEFAULT_REVERB");
1168 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1169 LoadReverbPreset(str, &DefaultEffect);
1171 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1174 /************************************************
1175 * Library deinitialization
1176 ************************************************/
1177 static void alc_cleanup(void)
1179 ALCdevice *dev;
1181 AL_STRING_DEINIT(alcAllDevicesList);
1182 AL_STRING_DEINIT(alcCaptureDeviceList);
1184 free(alcDefaultAllDevicesSpecifier);
1185 alcDefaultAllDevicesSpecifier = NULL;
1186 free(alcCaptureDefaultDeviceSpecifier);
1187 alcCaptureDefaultDeviceSpecifier = NULL;
1189 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1191 ALCuint num = 0;
1192 do {
1193 num++;
1194 } while((dev=dev->next) != NULL);
1195 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1198 DeinitEffectFactoryMap();
1201 static void alc_deinit_safe(void)
1203 alc_cleanup();
1205 FreeHrtfs();
1206 FreeALConfig();
1208 ThunkExit();
1209 almtx_destroy(&ListLock);
1210 altss_delete(LocalContext);
1212 if(LogFile != stderr)
1213 fclose(LogFile);
1214 LogFile = NULL;
1217 static void alc_deinit(void)
1219 int i;
1221 alc_cleanup();
1223 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1224 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1226 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1228 if(!BackendList[i].getFactory)
1229 BackendList[i].Deinit();
1230 else
1232 ALCbackendFactory *factory = BackendList[i].getFactory();
1233 V0(factory,deinit)();
1237 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1238 V0(factory,deinit)();
1241 alc_deinit_safe();
1245 /************************************************
1246 * Device enumeration
1247 ************************************************/
1248 static void ProbeDevices(al_string *list, enum DevProbe type)
1250 DO_INITCONFIG();
1252 LockLists();
1253 al_string_clear(list);
1255 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1257 if(!PlaybackBackend.getFactory)
1258 PlaybackBackend.Probe(type);
1259 else
1261 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1262 V(factory,probe)(type);
1265 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1267 if(!CaptureBackend.getFactory)
1268 CaptureBackend.Probe(type);
1269 else
1271 ALCbackendFactory *factory = CaptureBackend.getFactory();
1272 V(factory,probe)(type);
1275 UnlockLists();
1277 static void ProbeAllDevicesList(void)
1278 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1279 static void ProbeCaptureDeviceList(void)
1280 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1282 static void AppendDevice(const ALCchar *name, al_string *devnames)
1284 size_t len = strlen(name);
1285 if(len > 0)
1286 al_string_append_range(devnames, name, name+len+1);
1288 void AppendAllDevicesList(const ALCchar *name)
1289 { AppendDevice(name, &alcAllDevicesList); }
1290 void AppendCaptureDeviceList(const ALCchar *name)
1291 { AppendDevice(name, &alcCaptureDeviceList); }
1294 /************************************************
1295 * Device format information
1296 ************************************************/
1297 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1299 switch(type)
1301 case DevFmtByte: return "Signed Byte";
1302 case DevFmtUByte: return "Unsigned Byte";
1303 case DevFmtShort: return "Signed Short";
1304 case DevFmtUShort: return "Unsigned Short";
1305 case DevFmtInt: return "Signed Int";
1306 case DevFmtUInt: return "Unsigned Int";
1307 case DevFmtFloat: return "Float";
1309 return "(unknown type)";
1311 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1313 switch(chans)
1315 case DevFmtMono: return "Mono";
1316 case DevFmtStereo: return "Stereo";
1317 case DevFmtQuad: return "Quadraphonic";
1318 case DevFmtX51: return "5.1 Surround";
1319 case DevFmtX51Side: return "5.1 Side";
1320 case DevFmtX61: return "6.1 Surround";
1321 case DevFmtX71: return "7.1 Surround";
1323 return "(unknown channels)";
1326 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1327 ALuint BytesFromDevFmt(enum DevFmtType type)
1329 switch(type)
1331 case DevFmtByte: return sizeof(ALbyte);
1332 case DevFmtUByte: return sizeof(ALubyte);
1333 case DevFmtShort: return sizeof(ALshort);
1334 case DevFmtUShort: return sizeof(ALushort);
1335 case DevFmtInt: return sizeof(ALint);
1336 case DevFmtUInt: return sizeof(ALuint);
1337 case DevFmtFloat: return sizeof(ALfloat);
1339 return 0;
1341 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1343 switch(chans)
1345 case DevFmtMono: return 1;
1346 case DevFmtStereo: return 2;
1347 case DevFmtQuad: return 4;
1348 case DevFmtX51: return 6;
1349 case DevFmtX51Side: return 6;
1350 case DevFmtX61: return 7;
1351 case DevFmtX71: return 8;
1353 return 0;
1356 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1357 enum DevFmtChannels *chans, enum DevFmtType *type)
1359 static const struct {
1360 ALenum format;
1361 enum DevFmtChannels channels;
1362 enum DevFmtType type;
1363 } list[] = {
1364 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1365 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1366 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1368 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1369 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1370 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1372 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1373 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1374 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1376 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1377 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1378 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1380 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1381 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1382 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1384 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1385 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1386 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1388 ALuint i;
1390 for(i = 0;i < COUNTOF(list);i++)
1392 if(list[i].format == format)
1394 *chans = list[i].channels;
1395 *type = list[i].type;
1396 return AL_TRUE;
1400 return AL_FALSE;
1403 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1405 switch(type)
1407 case ALC_BYTE_SOFT:
1408 case ALC_UNSIGNED_BYTE_SOFT:
1409 case ALC_SHORT_SOFT:
1410 case ALC_UNSIGNED_SHORT_SOFT:
1411 case ALC_INT_SOFT:
1412 case ALC_UNSIGNED_INT_SOFT:
1413 case ALC_FLOAT_SOFT:
1414 return ALC_TRUE;
1416 return ALC_FALSE;
1419 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1421 switch(channels)
1423 case ALC_MONO_SOFT:
1424 case ALC_STEREO_SOFT:
1425 case ALC_QUAD_SOFT:
1426 case ALC_5POINT1_SOFT:
1427 case ALC_6POINT1_SOFT:
1428 case ALC_7POINT1_SOFT:
1429 return ALC_TRUE;
1431 return ALC_FALSE;
1435 /************************************************
1436 * Miscellaneous ALC helpers
1437 ************************************************/
1438 extern inline void LockContext(ALCcontext *context);
1439 extern inline void UnlockContext(ALCcontext *context);
1441 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1443 return V0(device->Backend,getLatency)();
1446 void ALCdevice_Lock(ALCdevice *device)
1448 V0(device->Backend,lock)();
1451 void ALCdevice_Unlock(ALCdevice *device)
1453 V0(device->Backend,unlock)();
1457 /* SetDefaultWFXChannelOrder
1459 * Sets the default channel order used by WaveFormatEx.
1461 void SetDefaultWFXChannelOrder(ALCdevice *device)
1463 ALuint i;
1465 for(i = 0;i < MaxChannels;i++)
1466 device->ChannelName[i] = InvalidChannel;
1468 switch(device->FmtChans)
1470 case DevFmtMono: device->ChannelName[0] = FrontCenter;
1471 break;
1472 case DevFmtStereo: device->ChannelName[0] = FrontLeft;
1473 device->ChannelName[1] = FrontRight;
1474 break;
1475 case DevFmtQuad: device->ChannelName[0] = FrontLeft;
1476 device->ChannelName[1] = FrontRight;
1477 device->ChannelName[2] = BackLeft;
1478 device->ChannelName[3] = BackRight;
1479 break;
1480 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1481 device->ChannelName[1] = FrontRight;
1482 device->ChannelName[2] = FrontCenter;
1483 device->ChannelName[3] = LFE;
1484 device->ChannelName[4] = BackLeft;
1485 device->ChannelName[5] = BackRight;
1486 break;
1487 case DevFmtX51Side: device->ChannelName[0] = FrontLeft;
1488 device->ChannelName[1] = FrontRight;
1489 device->ChannelName[2] = FrontCenter;
1490 device->ChannelName[3] = LFE;
1491 device->ChannelName[4] = SideLeft;
1492 device->ChannelName[5] = SideRight;
1493 break;
1494 case DevFmtX61: device->ChannelName[0] = FrontLeft;
1495 device->ChannelName[1] = FrontRight;
1496 device->ChannelName[2] = FrontCenter;
1497 device->ChannelName[3] = LFE;
1498 device->ChannelName[4] = BackCenter;
1499 device->ChannelName[5] = SideLeft;
1500 device->ChannelName[6] = SideRight;
1501 break;
1502 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1503 device->ChannelName[1] = FrontRight;
1504 device->ChannelName[2] = FrontCenter;
1505 device->ChannelName[3] = LFE;
1506 device->ChannelName[4] = BackLeft;
1507 device->ChannelName[5] = BackRight;
1508 device->ChannelName[6] = SideLeft;
1509 device->ChannelName[7] = SideRight;
1510 break;
1514 /* SetDefaultChannelOrder
1516 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1518 void SetDefaultChannelOrder(ALCdevice *device)
1520 ALuint i;
1522 for(i = 0;i < MaxChannels;i++)
1523 device->ChannelName[i] = InvalidChannel;
1525 switch(device->FmtChans)
1527 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1528 device->ChannelName[1] = FrontRight;
1529 device->ChannelName[2] = BackLeft;
1530 device->ChannelName[3] = BackRight;
1531 device->ChannelName[4] = FrontCenter;
1532 device->ChannelName[5] = LFE;
1533 return;
1534 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1535 device->ChannelName[1] = FrontRight;
1536 device->ChannelName[2] = BackLeft;
1537 device->ChannelName[3] = BackRight;
1538 device->ChannelName[4] = FrontCenter;
1539 device->ChannelName[5] = LFE;
1540 device->ChannelName[6] = SideLeft;
1541 device->ChannelName[7] = SideRight;
1542 return;
1544 /* Same as WFX order */
1545 case DevFmtMono:
1546 case DevFmtStereo:
1547 case DevFmtQuad:
1548 case DevFmtX51Side:
1549 case DevFmtX61:
1550 SetDefaultWFXChannelOrder(device);
1551 break;
1555 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1558 /* ALCcontext_DeferUpdates
1560 * Defers/suspends updates for the given context's listener and sources. This
1561 * does *NOT* stop mixing, but rather prevents certain property changes from
1562 * taking effect.
1564 void ALCcontext_DeferUpdates(ALCcontext *context)
1566 ALCdevice *device = context->Device;
1567 FPUCtl oldMode;
1569 SetMixerFPUMode(&oldMode);
1571 V0(device->Backend,lock)();
1572 if(!ExchangeInt(&context->DeferUpdates, AL_TRUE))
1574 ALboolean UpdateSources;
1575 ALvoice *voice, *voice_end;
1576 ALeffectslot **slot, **slot_end;
1577 /* Make sure all pending updates are performed */
1578 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
1580 voice = context->Voices;
1581 voice_end = voice + context->VoiceCount;
1582 while(voice != voice_end)
1584 ALsource *source = voice->Source;
1585 if(!source) goto next;
1587 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
1589 voice->Source = NULL;
1590 continue;
1593 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
1594 voice->Update(voice, source, context);
1595 next:
1596 voice++;
1599 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
1600 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
1601 while(slot != slot_end)
1603 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
1604 V((*slot)->EffectState,update)(context->Device, *slot);
1605 slot++;
1608 V0(device->Backend,unlock)();
1610 RestoreFPUMode(&oldMode);
1613 /* ALCcontext_ProcessUpdates
1615 * Resumes update processing after being deferred.
1617 void ALCcontext_ProcessUpdates(ALCcontext *context)
1619 ALCdevice *device = context->Device;
1621 V0(device->Backend,lock)();
1622 if(ExchangeInt(&context->DeferUpdates, AL_FALSE))
1624 ALsizei pos;
1626 LockUIntMapRead(&context->SourceMap);
1627 for(pos = 0;pos < context->SourceMap.size;pos++)
1629 ALsource *Source = context->SourceMap.array[pos].value;
1630 ALenum new_state;
1632 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1633 Source->Offset >= 0.0)
1635 ReadLock(&Source->queue_lock);
1636 ApplyOffset(Source);
1637 ReadUnlock(&Source->queue_lock);
1640 new_state = ExchangeInt(&Source->new_state, AL_NONE);
1641 if(new_state)
1642 SetSourceState(Source, context, new_state);
1644 UnlockUIntMapRead(&context->SourceMap);
1646 V0(device->Backend,unlock)();
1650 /* alcSetError
1652 * Stores the latest ALC device error
1654 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1656 if(TrapALCError)
1658 #ifdef _WIN32
1659 /* DebugBreak() will cause an exception if there is no debugger */
1660 if(IsDebuggerPresent())
1661 DebugBreak();
1662 #elif defined(SIGTRAP)
1663 raise(SIGTRAP);
1664 #endif
1667 if(device)
1668 ATOMIC_STORE(&device->LastError, errorCode);
1669 else
1670 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1674 /* UpdateClockBase
1676 * Updates the device's base clock time with however many samples have been
1677 * done. This is used so frequency changes on the device don't cause the time
1678 * to jump forward or back.
1680 static inline void UpdateClockBase(ALCdevice *device)
1682 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1683 device->SamplesDone = 0;
1686 /* UpdateDeviceParams
1688 * Updates device parameters according to the attribute list (caller is
1689 * responsible for holding the list lock).
1691 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1693 ALCcontext *context;
1694 enum DevFmtChannels oldChans;
1695 enum DevFmtType oldType;
1696 ALCuint oldFreq;
1697 FPUCtl oldMode;
1699 // Check for attributes
1700 if(device->Type == Loopback)
1702 enum {
1703 GotFreq = 1<<0,
1704 GotChans = 1<<1,
1705 GotType = 1<<2,
1706 GotAll = GotFreq|GotChans|GotType
1708 ALCuint freq, numMono, numStereo, numSends, flags;
1709 enum DevFmtChannels schans;
1710 enum DevFmtType stype;
1711 ALCuint attrIdx = 0;
1712 ALCint gotFmt = 0;
1714 if(!attrList)
1716 WARN("Missing attributes for loopback device\n");
1717 return ALC_INVALID_VALUE;
1720 numMono = device->NumMonoSources;
1721 numStereo = device->NumStereoSources;
1722 numSends = device->NumAuxSends;
1723 schans = device->FmtChans;
1724 stype = device->FmtType;
1725 freq = device->Frequency;
1726 flags = device->Flags;
1728 while(attrList[attrIdx])
1730 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1732 ALCint val = attrList[attrIdx + 1];
1733 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1734 return ALC_INVALID_VALUE;
1735 schans = val;
1736 gotFmt |= GotChans;
1739 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1741 ALCint val = attrList[attrIdx + 1];
1742 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1743 return ALC_INVALID_VALUE;
1744 stype = val;
1745 gotFmt |= GotType;
1748 if(attrList[attrIdx] == ALC_FREQUENCY)
1750 freq = attrList[attrIdx + 1];
1751 if(freq < MIN_OUTPUT_RATE)
1752 return ALC_INVALID_VALUE;
1753 gotFmt |= GotFreq;
1756 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1758 numStereo = attrList[attrIdx + 1];
1759 if(numStereo > device->MaxNoOfSources)
1760 numStereo = device->MaxNoOfSources;
1762 numMono = device->MaxNoOfSources - numStereo;
1765 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1766 numSends = attrList[attrIdx + 1];
1768 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1770 if(attrList[attrIdx + 1] != ALC_FALSE)
1771 flags |= DEVICE_HRTF_REQUEST;
1772 else
1773 flags &= ~DEVICE_HRTF_REQUEST;
1776 attrIdx += 2;
1779 if(gotFmt != GotAll)
1781 WARN("Missing format for loopback device\n");
1782 return ALC_INVALID_VALUE;
1785 ConfigValueUInt(NULL, "sends", &numSends);
1786 numSends = minu(MAX_SENDS, numSends);
1788 if((device->Flags&DEVICE_RUNNING))
1789 V0(device->Backend,stop)();
1790 device->Flags = (flags & ~DEVICE_RUNNING);
1792 UpdateClockBase(device);
1794 device->Frequency = freq;
1795 device->FmtChans = schans;
1796 device->FmtType = stype;
1797 device->NumMonoSources = numMono;
1798 device->NumStereoSources = numStereo;
1799 device->NumAuxSends = numSends;
1801 else if(attrList && attrList[0])
1803 ALCuint freq, numMono, numStereo, numSends;
1804 ALCuint attrIdx = 0;
1806 /* If a context is already running on the device, stop playback so the
1807 * device attributes can be updated. */
1808 if((device->Flags&DEVICE_RUNNING))
1809 V0(device->Backend,stop)();
1810 device->Flags &= ~DEVICE_RUNNING;
1812 freq = device->Frequency;
1813 numMono = device->NumMonoSources;
1814 numStereo = device->NumStereoSources;
1815 numSends = device->NumAuxSends;
1817 while(attrList[attrIdx])
1819 if(attrList[attrIdx] == ALC_FREQUENCY)
1821 freq = attrList[attrIdx + 1];
1822 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1825 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1827 numStereo = attrList[attrIdx + 1];
1828 if(numStereo > device->MaxNoOfSources)
1829 numStereo = device->MaxNoOfSources;
1831 numMono = device->MaxNoOfSources - numStereo;
1834 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1835 numSends = attrList[attrIdx + 1];
1837 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1839 if(attrList[attrIdx + 1] != ALC_FALSE)
1840 device->Flags |= DEVICE_HRTF_REQUEST;
1841 else
1842 device->Flags &= ~DEVICE_HRTF_REQUEST;
1845 attrIdx += 2;
1848 ConfigValueUInt(NULL, "frequency", &freq);
1849 freq = maxu(freq, MIN_OUTPUT_RATE);
1851 ConfigValueUInt(NULL, "sends", &numSends);
1852 numSends = minu(MAX_SENDS, numSends);
1854 UpdateClockBase(device);
1856 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1857 device->Frequency;
1858 /* SSE and Neon do best with the update size being a multiple of 4 */
1859 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1860 device->UpdateSize = (device->UpdateSize+3)&~3;
1862 device->Frequency = freq;
1863 device->NumMonoSources = numMono;
1864 device->NumStereoSources = numStereo;
1865 device->NumAuxSends = numSends;
1868 if((device->Flags&DEVICE_RUNNING))
1869 return ALC_NO_ERROR;
1871 UpdateClockBase(device);
1873 if(device->Type != Loopback)
1875 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1876 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1877 device->Flags |= DEVICE_HRTF_REQUEST;
1878 else
1879 device->Flags &= ~DEVICE_HRTF_REQUEST;
1881 if((device->Flags&DEVICE_HRTF_REQUEST))
1883 enum DevFmtChannels chans = device->FmtChans;
1884 ALCuint freq = device->Frequency;
1885 if(FindHrtfFormat(&chans, &freq))
1887 if(device->Type != Loopback)
1889 device->Frequency = freq;
1890 device->FmtChans = chans;
1891 device->Flags |= DEVICE_CHANNELS_REQUEST |
1892 DEVICE_FREQUENCY_REQUEST;
1894 else if(device->Frequency != freq || device->FmtChans != chans)
1896 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1897 DevFmtChannelsString(device->FmtChans), device->Frequency);
1898 device->Flags &= ~DEVICE_HRTF_REQUEST;
1903 oldFreq = device->Frequency;
1904 oldChans = device->FmtChans;
1905 oldType = device->FmtType;
1907 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1908 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1909 DevFmtChannelsString(device->FmtChans),
1910 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1911 DevFmtTypeString(device->FmtType),
1912 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1913 device->Frequency,
1914 device->UpdateSize, device->NumUpdates);
1916 if(V0(device->Backend,reset)() == ALC_FALSE)
1917 return ALC_INVALID_DEVICE;
1919 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1921 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1922 DevFmtChannelsString(device->FmtChans));
1923 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1925 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1927 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1928 DevFmtTypeString(device->FmtType));
1929 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1931 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1933 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1934 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1937 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1938 DevFmtChannelsString(device->FmtChans),
1939 DevFmtTypeString(device->FmtType), device->Frequency,
1940 device->UpdateSize, device->NumUpdates);
1942 aluInitPanning(device);
1944 V(device->Synth,update)(device);
1946 device->Hrtf = NULL;
1947 if((device->Flags&DEVICE_HRTF_REQUEST))
1949 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1950 if(!device->Hrtf)
1951 device->Flags &= ~DEVICE_HRTF_REQUEST;
1953 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1955 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1957 if(!device->Bs2b)
1959 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1960 bs2b_clear(device->Bs2b);
1962 bs2b_set_srate(device->Bs2b, device->Frequency);
1963 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1964 TRACE("BS2B level %d\n", device->Bs2bLevel);
1966 else
1968 free(device->Bs2b);
1969 device->Bs2b = NULL;
1970 TRACE("BS2B disabled\n");
1973 device->Flags &= ~DEVICE_WIDE_STEREO;
1974 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1975 device->Flags |= DEVICE_WIDE_STEREO;
1977 if(!device->Hrtf && (device->UpdateSize&3))
1979 if((CPUCapFlags&CPU_CAP_SSE))
1980 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1981 if((CPUCapFlags&CPU_CAP_NEON))
1982 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1985 SetMixerFPUMode(&oldMode);
1986 ALCdevice_Lock(device);
1987 context = ATOMIC_LOAD(&device->ContextList);
1988 while(context)
1990 ALsizei pos;
1992 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
1993 LockUIntMapRead(&context->EffectSlotMap);
1994 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1996 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1998 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2000 UnlockUIntMapRead(&context->EffectSlotMap);
2001 ALCdevice_Unlock(device);
2002 RestoreFPUMode(&oldMode);
2003 return ALC_INVALID_DEVICE;
2005 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2006 V(slot->EffectState,update)(device, slot);
2008 UnlockUIntMapRead(&context->EffectSlotMap);
2010 LockUIntMapRead(&context->SourceMap);
2011 for(pos = 0;pos < context->SourceMap.size;pos++)
2013 ALsource *source = context->SourceMap.array[pos].value;
2014 ALuint s = device->NumAuxSends;
2015 while(s < MAX_SENDS)
2017 if(source->Send[s].Slot)
2018 DecrementRef(&source->Send[s].Slot->ref);
2019 source->Send[s].Slot = NULL;
2020 source->Send[s].Gain = 1.0f;
2021 source->Send[s].GainHF = 1.0f;
2022 s++;
2024 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
2026 UnlockUIntMapRead(&context->SourceMap);
2028 for(pos = 0;pos < context->VoiceCount;pos++)
2030 ALvoice *voice = &context->Voices[pos];
2031 ALsource *source = voice->Source;
2032 ALuint s = device->NumAuxSends;
2034 while(s < MAX_SENDS)
2036 voice->Send[s].Moving = AL_FALSE;
2037 voice->Send[s].Counter = 0;
2038 s++;
2041 if(source)
2043 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
2044 voice->Update(voice, source, context);
2048 context = context->next;
2050 if(device->DefaultSlot)
2052 ALeffectslot *slot = device->DefaultSlot;
2054 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2056 ALCdevice_Unlock(device);
2057 RestoreFPUMode(&oldMode);
2058 return ALC_INVALID_DEVICE;
2060 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2061 V(slot->EffectState,update)(device, slot);
2063 ALCdevice_Unlock(device);
2064 RestoreFPUMode(&oldMode);
2066 if(!(device->Flags&DEVICE_PAUSED))
2068 if(V0(device->Backend,start)() == ALC_FALSE)
2069 return ALC_INVALID_DEVICE;
2070 device->Flags |= DEVICE_RUNNING;
2073 return ALC_NO_ERROR;
2076 /* FreeDevice
2078 * Frees the device structure, and destroys any objects the app failed to
2079 * delete. Called once there's no more references on the device.
2081 static ALCvoid FreeDevice(ALCdevice *device)
2083 TRACE("%p\n", device);
2085 V0(device->Backend,close)();
2086 DELETE_OBJ(device->Backend);
2087 device->Backend = NULL;
2089 DELETE_OBJ(device->Synth);
2090 device->Synth = NULL;
2092 if(device->DefaultSlot)
2094 ALeffectState *state = device->DefaultSlot->EffectState;
2095 device->DefaultSlot = NULL;
2096 DELETE_OBJ(state);
2099 if(device->DefaultSfont)
2100 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
2101 device->DefaultSfont = NULL;
2103 if(device->BufferMap.size > 0)
2105 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2106 ReleaseALBuffers(device);
2108 ResetUIntMap(&device->BufferMap);
2110 if(device->EffectMap.size > 0)
2112 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2113 ReleaseALEffects(device);
2115 ResetUIntMap(&device->EffectMap);
2117 if(device->FilterMap.size > 0)
2119 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2120 ReleaseALFilters(device);
2122 ResetUIntMap(&device->FilterMap);
2124 if(device->SfontMap.size > 0)
2126 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2127 ReleaseALSoundfonts(device);
2129 ResetUIntMap(&device->SfontMap);
2131 if(device->PresetMap.size > 0)
2133 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2134 ReleaseALPresets(device);
2136 ResetUIntMap(&device->PresetMap);
2138 if(device->FontsoundMap.size > 0)
2140 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2141 ReleaseALFontsounds(device);
2143 ResetUIntMap(&device->FontsoundMap);
2145 free(device->Bs2b);
2146 device->Bs2b = NULL;
2148 AL_STRING_DEINIT(device->DeviceName);
2150 al_free(device);
2154 void ALCdevice_IncRef(ALCdevice *device)
2156 uint ref;
2157 ref = IncrementRef(&device->ref);
2158 TRACEREF("%p increasing refcount to %u\n", device, ref);
2161 void ALCdevice_DecRef(ALCdevice *device)
2163 uint ref;
2164 ref = DecrementRef(&device->ref);
2165 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2166 if(ref == 0) FreeDevice(device);
2169 /* VerifyDevice
2171 * Checks if the device handle is valid, and increments its ref count if so.
2173 static ALCdevice *VerifyDevice(ALCdevice *device)
2175 ALCdevice *tmpDevice;
2177 if(!device)
2178 return NULL;
2180 LockLists();
2181 tmpDevice = ATOMIC_LOAD(&DeviceList);
2182 while(tmpDevice && tmpDevice != device)
2183 tmpDevice = tmpDevice->next;
2185 if(tmpDevice)
2186 ALCdevice_IncRef(tmpDevice);
2187 UnlockLists();
2188 return tmpDevice;
2192 /* InitContext
2194 * Initializes context fields
2196 static ALvoid InitContext(ALCcontext *Context)
2198 ALint i, j;
2200 //Initialise listener
2201 Context->Listener->Gain = 1.0f;
2202 Context->Listener->MetersPerUnit = 1.0f;
2203 Context->Listener->Position[0] = 0.0f;
2204 Context->Listener->Position[1] = 0.0f;
2205 Context->Listener->Position[2] = 0.0f;
2206 Context->Listener->Velocity[0] = 0.0f;
2207 Context->Listener->Velocity[1] = 0.0f;
2208 Context->Listener->Velocity[2] = 0.0f;
2209 Context->Listener->Forward[0] = 0.0f;
2210 Context->Listener->Forward[1] = 0.0f;
2211 Context->Listener->Forward[2] = -1.0f;
2212 Context->Listener->Up[0] = 0.0f;
2213 Context->Listener->Up[1] = 1.0f;
2214 Context->Listener->Up[2] = 0.0f;
2215 for(i = 0;i < 4;i++)
2217 for(j = 0;j < 4;j++)
2218 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2220 for(i = 0;i < 3;i++)
2221 Context->Listener->Params.Velocity[i] = 0.0f;
2223 //Validate Context
2224 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2225 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2226 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2227 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2229 //Set globals
2230 Context->DistanceModel = DefaultDistanceModel;
2231 Context->SourceDistanceModel = AL_FALSE;
2232 Context->DopplerFactor = 1.0f;
2233 Context->DopplerVelocity = 1.0f;
2234 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2235 Context->DeferUpdates = AL_FALSE;
2237 Context->ExtensionList = alExtList;
2241 /* FreeContext
2243 * Cleans up the context, and destroys any remaining objects the app failed to
2244 * delete. Called once there's no more references on the context.
2246 static void FreeContext(ALCcontext *context)
2248 TRACE("%p\n", context);
2250 if(context->SourceMap.size > 0)
2252 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2253 ReleaseALSources(context);
2255 ResetUIntMap(&context->SourceMap);
2257 if(context->EffectSlotMap.size > 0)
2259 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2260 ReleaseALAuxiliaryEffectSlots(context);
2262 ResetUIntMap(&context->EffectSlotMap);
2264 al_free(context->Voices);
2265 context->Voices = NULL;
2266 context->VoiceCount = 0;
2267 context->MaxVoices = 0;
2269 VECTOR_DEINIT(context->ActiveAuxSlots);
2271 ALCdevice_DecRef(context->Device);
2272 context->Device = NULL;
2274 //Invalidate context
2275 memset(context, 0, sizeof(ALCcontext));
2276 al_free(context);
2279 /* ReleaseContext
2281 * Removes the context reference from the given device and removes it from
2282 * being current on the running thread or globally.
2284 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2286 ALCcontext *nextctx;
2287 ALCcontext *origctx;
2289 if(altss_get(LocalContext) == context)
2291 WARN("%p released while current on thread\n", context);
2292 altss_set(LocalContext, NULL);
2293 ALCcontext_DecRef(context);
2296 origctx = context;
2297 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2298 ALCcontext_DecRef(context);
2300 ALCdevice_Lock(device);
2301 origctx = context;
2302 nextctx = context->next;
2303 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2305 ALCcontext *list;
2306 do {
2307 list = origctx;
2308 origctx = context;
2309 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2311 ALCdevice_Unlock(device);
2313 ALCcontext_DecRef(context);
2316 void ALCcontext_IncRef(ALCcontext *context)
2318 uint ref;
2319 ref = IncrementRef(&context->ref);
2320 TRACEREF("%p increasing refcount to %u\n", context, ref);
2323 void ALCcontext_DecRef(ALCcontext *context)
2325 uint ref;
2326 ref = DecrementRef(&context->ref);
2327 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2328 if(ref == 0) FreeContext(context);
2331 static void ReleaseThreadCtx(void *ptr)
2333 WARN("%p current for thread being destroyed\n", ptr);
2334 ALCcontext_DecRef(ptr);
2337 /* VerifyContext
2339 * Checks that the given context is valid, and increments its reference count.
2341 static ALCcontext *VerifyContext(ALCcontext *context)
2343 ALCdevice *dev;
2345 LockLists();
2346 dev = ATOMIC_LOAD(&DeviceList);
2347 while(dev)
2349 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2350 while(ctx)
2352 if(ctx == context)
2354 ALCcontext_IncRef(ctx);
2355 UnlockLists();
2356 return ctx;
2358 ctx = ctx->next;
2360 dev = dev->next;
2362 UnlockLists();
2364 return NULL;
2368 /* GetContextRef
2370 * Returns the currently active context for this thread, and adds a reference
2371 * without locking it.
2373 ALCcontext *GetContextRef(void)
2375 ALCcontext *context;
2377 context = altss_get(LocalContext);
2378 if(context)
2379 ALCcontext_IncRef(context);
2380 else
2382 LockLists();
2383 context = ATOMIC_LOAD(&GlobalContext);
2384 if(context)
2385 ALCcontext_IncRef(context);
2386 UnlockLists();
2389 return context;
2393 /************************************************
2394 * Standard ALC functions
2395 ************************************************/
2397 /* alcGetError
2399 * Return last ALC generated error code for the given device
2401 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2403 ALCenum errorCode;
2405 if(VerifyDevice(device))
2407 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2408 ALCdevice_DecRef(device);
2410 else
2411 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2413 return errorCode;
2417 /* alcSuspendContext
2419 * Suspends updates for the given context
2421 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2423 if(!SuspendDefers)
2424 return;
2426 context = VerifyContext(context);
2427 if(!context)
2428 alcSetError(NULL, ALC_INVALID_CONTEXT);
2429 else
2431 ALCcontext_DeferUpdates(context);
2432 ALCcontext_DecRef(context);
2436 /* alcProcessContext
2438 * Resumes processing updates for the given context
2440 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2442 if(!SuspendDefers)
2443 return;
2445 context = VerifyContext(context);
2446 if(!context)
2447 alcSetError(NULL, ALC_INVALID_CONTEXT);
2448 else
2450 ALCcontext_ProcessUpdates(context);
2451 ALCcontext_DecRef(context);
2456 /* alcGetString
2458 * Returns information about the device, and error strings
2460 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2462 const ALCchar *value = NULL;
2464 switch(param)
2466 case ALC_NO_ERROR:
2467 value = alcNoError;
2468 break;
2470 case ALC_INVALID_ENUM:
2471 value = alcErrInvalidEnum;
2472 break;
2474 case ALC_INVALID_VALUE:
2475 value = alcErrInvalidValue;
2476 break;
2478 case ALC_INVALID_DEVICE:
2479 value = alcErrInvalidDevice;
2480 break;
2482 case ALC_INVALID_CONTEXT:
2483 value = alcErrInvalidContext;
2484 break;
2486 case ALC_OUT_OF_MEMORY:
2487 value = alcErrOutOfMemory;
2488 break;
2490 case ALC_DEVICE_SPECIFIER:
2491 value = alcDefaultName;
2492 break;
2494 case ALC_ALL_DEVICES_SPECIFIER:
2495 if(VerifyDevice(Device))
2497 value = al_string_get_cstr(Device->DeviceName);
2498 ALCdevice_DecRef(Device);
2500 else
2502 ProbeAllDevicesList();
2503 value = al_string_get_cstr(alcAllDevicesList);
2505 break;
2507 case ALC_CAPTURE_DEVICE_SPECIFIER:
2508 if(VerifyDevice(Device))
2510 value = al_string_get_cstr(Device->DeviceName);
2511 ALCdevice_DecRef(Device);
2513 else
2515 ProbeCaptureDeviceList();
2516 value = al_string_get_cstr(alcCaptureDeviceList);
2518 break;
2520 /* Default devices are always first in the list */
2521 case ALC_DEFAULT_DEVICE_SPECIFIER:
2522 value = alcDefaultName;
2523 break;
2525 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2526 if(al_string_empty(alcAllDevicesList))
2527 ProbeAllDevicesList();
2529 Device = VerifyDevice(Device);
2531 free(alcDefaultAllDevicesSpecifier);
2532 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2533 if(!alcDefaultAllDevicesSpecifier)
2534 alcSetError(Device, ALC_OUT_OF_MEMORY);
2536 value = alcDefaultAllDevicesSpecifier;
2537 if(Device) ALCdevice_DecRef(Device);
2538 break;
2540 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2541 if(al_string_empty(alcCaptureDeviceList))
2542 ProbeCaptureDeviceList();
2544 Device = VerifyDevice(Device);
2546 free(alcCaptureDefaultDeviceSpecifier);
2547 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2548 if(!alcCaptureDefaultDeviceSpecifier)
2549 alcSetError(Device, ALC_OUT_OF_MEMORY);
2551 value = alcCaptureDefaultDeviceSpecifier;
2552 if(Device) ALCdevice_DecRef(Device);
2553 break;
2555 case ALC_EXTENSIONS:
2556 if(!VerifyDevice(Device))
2557 value = alcNoDeviceExtList;
2558 else
2560 value = alcExtensionList;
2561 ALCdevice_DecRef(Device);
2563 break;
2565 default:
2566 Device = VerifyDevice(Device);
2567 alcSetError(Device, ALC_INVALID_ENUM);
2568 if(Device) ALCdevice_DecRef(Device);
2569 break;
2572 return value;
2576 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2578 ALCsizei i;
2580 if(size <= 0 || values == NULL)
2582 alcSetError(device, ALC_INVALID_VALUE);
2583 return 0;
2586 if(!device)
2588 switch(param)
2590 case ALC_MAJOR_VERSION:
2591 values[0] = alcMajorVersion;
2592 return 1;
2593 case ALC_MINOR_VERSION:
2594 values[0] = alcMinorVersion;
2595 return 1;
2597 case ALC_ATTRIBUTES_SIZE:
2598 case ALC_ALL_ATTRIBUTES:
2599 case ALC_FREQUENCY:
2600 case ALC_REFRESH:
2601 case ALC_SYNC:
2602 case ALC_MONO_SOURCES:
2603 case ALC_STEREO_SOURCES:
2604 case ALC_CAPTURE_SAMPLES:
2605 case ALC_FORMAT_CHANNELS_SOFT:
2606 case ALC_FORMAT_TYPE_SOFT:
2607 alcSetError(NULL, ALC_INVALID_DEVICE);
2608 return 0;
2610 default:
2611 alcSetError(NULL, ALC_INVALID_ENUM);
2612 return 0;
2614 return 0;
2617 if(device->Type == Capture)
2619 switch(param)
2621 case ALC_CAPTURE_SAMPLES:
2622 ALCdevice_Lock(device);
2623 values[0] = V0(device->Backend,availableSamples)();
2624 ALCdevice_Unlock(device);
2625 return 1;
2627 case ALC_CONNECTED:
2628 values[0] = device->Connected;
2629 return 1;
2631 default:
2632 alcSetError(device, ALC_INVALID_ENUM);
2633 return 0;
2635 return 0;
2638 /* render device */
2639 switch(param)
2641 case ALC_MAJOR_VERSION:
2642 values[0] = alcMajorVersion;
2643 return 1;
2645 case ALC_MINOR_VERSION:
2646 values[0] = alcMinorVersion;
2647 return 1;
2649 case ALC_EFX_MAJOR_VERSION:
2650 values[0] = alcEFXMajorVersion;
2651 return 1;
2653 case ALC_EFX_MINOR_VERSION:
2654 values[0] = alcEFXMinorVersion;
2655 return 1;
2657 case ALC_ATTRIBUTES_SIZE:
2658 values[0] = 15;
2659 return 1;
2661 case ALC_ALL_ATTRIBUTES:
2662 if(size < 15)
2664 alcSetError(device, ALC_INVALID_VALUE);
2665 return 0;
2668 i = 0;
2669 values[i++] = ALC_FREQUENCY;
2670 values[i++] = device->Frequency;
2672 if(device->Type != Loopback)
2674 values[i++] = ALC_REFRESH;
2675 values[i++] = device->Frequency / device->UpdateSize;
2677 values[i++] = ALC_SYNC;
2678 values[i++] = ALC_FALSE;
2680 else
2682 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2683 values[i++] = device->FmtChans;
2685 values[i++] = ALC_FORMAT_TYPE_SOFT;
2686 values[i++] = device->FmtType;
2689 values[i++] = ALC_MONO_SOURCES;
2690 values[i++] = device->NumMonoSources;
2692 values[i++] = ALC_STEREO_SOURCES;
2693 values[i++] = device->NumStereoSources;
2695 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2696 values[i++] = device->NumAuxSends;
2698 values[i++] = ALC_HRTF_SOFT;
2699 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2701 values[i++] = 0;
2702 return i;
2704 case ALC_FREQUENCY:
2705 values[0] = device->Frequency;
2706 return 1;
2708 case ALC_REFRESH:
2709 if(device->Type == Loopback)
2711 alcSetError(device, ALC_INVALID_DEVICE);
2712 return 0;
2714 values[0] = device->Frequency / device->UpdateSize;
2715 return 1;
2717 case ALC_SYNC:
2718 if(device->Type == Loopback)
2720 alcSetError(device, ALC_INVALID_DEVICE);
2721 return 0;
2723 values[0] = ALC_FALSE;
2724 return 1;
2726 case ALC_FORMAT_CHANNELS_SOFT:
2727 if(device->Type != Loopback)
2729 alcSetError(device, ALC_INVALID_DEVICE);
2730 return 0;
2732 values[0] = device->FmtChans;
2733 return 1;
2735 case ALC_FORMAT_TYPE_SOFT:
2736 if(device->Type != Loopback)
2738 alcSetError(device, ALC_INVALID_DEVICE);
2739 return 0;
2741 values[0] = device->FmtType;
2742 return 1;
2744 case ALC_MONO_SOURCES:
2745 values[0] = device->NumMonoSources;
2746 return 1;
2748 case ALC_STEREO_SOURCES:
2749 values[0] = device->NumStereoSources;
2750 return 1;
2752 case ALC_MAX_AUXILIARY_SENDS:
2753 values[0] = device->NumAuxSends;
2754 return 1;
2756 case ALC_CONNECTED:
2757 values[0] = device->Connected;
2758 return 1;
2760 case ALC_HRTF_SOFT:
2761 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2762 return 1;
2764 default:
2765 alcSetError(device, ALC_INVALID_ENUM);
2766 return 0;
2768 return 0;
2771 /* alcGetIntegerv
2773 * Returns information about the device and the version of OpenAL
2775 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2777 device = VerifyDevice(device);
2778 if(size <= 0 || values == NULL)
2779 alcSetError(device, ALC_INVALID_VALUE);
2780 else
2781 GetIntegerv(device, param, size, values);
2782 if(device) ALCdevice_DecRef(device);
2785 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2787 ALCint *ivals;
2788 ALsizei i;
2790 device = VerifyDevice(device);
2791 if(size <= 0 || values == NULL)
2792 alcSetError(device, ALC_INVALID_VALUE);
2793 else if(!device || device->Type == Capture)
2795 ivals = malloc(size * sizeof(ALCint));
2796 size = GetIntegerv(device, pname, size, ivals);
2797 for(i = 0;i < size;i++)
2798 values[i] = ivals[i];
2799 free(ivals);
2801 else /* render device */
2803 switch(pname)
2805 case ALC_ATTRIBUTES_SIZE:
2806 *values = 17;
2807 break;
2809 case ALC_ALL_ATTRIBUTES:
2810 if(size < 17)
2811 alcSetError(device, ALC_INVALID_VALUE);
2812 else
2814 int i = 0;
2816 V0(device->Backend,lock)();
2817 values[i++] = ALC_FREQUENCY;
2818 values[i++] = device->Frequency;
2820 if(device->Type != Loopback)
2822 values[i++] = ALC_REFRESH;
2823 values[i++] = device->Frequency / device->UpdateSize;
2825 values[i++] = ALC_SYNC;
2826 values[i++] = ALC_FALSE;
2828 else
2830 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2831 values[i++] = device->FmtChans;
2833 values[i++] = ALC_FORMAT_TYPE_SOFT;
2834 values[i++] = device->FmtType;
2837 values[i++] = ALC_MONO_SOURCES;
2838 values[i++] = device->NumMonoSources;
2840 values[i++] = ALC_STEREO_SOURCES;
2841 values[i++] = device->NumStereoSources;
2843 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2844 values[i++] = device->NumAuxSends;
2846 values[i++] = ALC_HRTF_SOFT;
2847 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2849 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2850 values[i++] = device->ClockBase +
2851 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2853 values[i++] = 0;
2854 V0(device->Backend,unlock)();
2856 break;
2858 case ALC_DEVICE_CLOCK_SOFT:
2859 V0(device->Backend,lock)();
2860 *values = device->ClockBase +
2861 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2862 V0(device->Backend,unlock)();
2863 break;
2865 default:
2866 ivals = malloc(size * sizeof(ALCint));
2867 size = GetIntegerv(device, pname, size, ivals);
2868 for(i = 0;i < size;i++)
2869 values[i] = ivals[i];
2870 free(ivals);
2871 break;
2874 if(device)
2875 ALCdevice_DecRef(device);
2879 /* alcIsExtensionPresent
2881 * Determines if there is support for a particular extension
2883 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2885 ALCboolean bResult = ALC_FALSE;
2887 device = VerifyDevice(device);
2889 if(!extName)
2890 alcSetError(device, ALC_INVALID_VALUE);
2891 else
2893 size_t len = strlen(extName);
2894 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2895 while(ptr && *ptr)
2897 if(strncasecmp(ptr, extName, len) == 0 &&
2898 (ptr[len] == '\0' || isspace(ptr[len])))
2900 bResult = ALC_TRUE;
2901 break;
2903 if((ptr=strchr(ptr, ' ')) != NULL)
2905 do {
2906 ++ptr;
2907 } while(isspace(*ptr));
2911 if(device)
2912 ALCdevice_DecRef(device);
2913 return bResult;
2917 /* alcGetProcAddress
2919 * Retrieves the function address for a particular extension function
2921 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2923 ALCvoid *ptr = NULL;
2925 if(!funcName)
2927 device = VerifyDevice(device);
2928 alcSetError(device, ALC_INVALID_VALUE);
2929 if(device) ALCdevice_DecRef(device);
2931 else
2933 ALsizei i = 0;
2934 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2935 i++;
2936 ptr = alcFunctions[i].address;
2939 return ptr;
2943 /* alcGetEnumValue
2945 * Get the value for a particular ALC enumeration name
2947 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2949 ALCenum val = 0;
2951 if(!enumName)
2953 device = VerifyDevice(device);
2954 alcSetError(device, ALC_INVALID_VALUE);
2955 if(device) ALCdevice_DecRef(device);
2957 else
2959 ALsizei i = 0;
2960 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2961 i++;
2962 val = enumeration[i].value;
2965 return val;
2969 /* alcCreateContext
2971 * Create and attach a context to the given device.
2973 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2975 ALCcontext *ALContext;
2976 ALCenum err;
2978 LockLists();
2979 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2981 UnlockLists();
2982 alcSetError(device, ALC_INVALID_DEVICE);
2983 if(device) ALCdevice_DecRef(device);
2984 return NULL;
2987 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
2989 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2991 UnlockLists();
2992 alcSetError(device, err);
2993 if(err == ALC_INVALID_DEVICE)
2995 ALCdevice_Lock(device);
2996 aluHandleDisconnect(device);
2997 ALCdevice_Unlock(device);
2999 ALCdevice_DecRef(device);
3000 return NULL;
3003 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3004 if(ALContext)
3006 InitRef(&ALContext->ref, 1);
3007 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3009 VECTOR_INIT(ALContext->ActiveAuxSlots);
3011 ALContext->VoiceCount = 0;
3012 ALContext->MaxVoices = 256;
3013 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3015 if(!ALContext || !ALContext->Voices)
3017 if(!ATOMIC_LOAD(&device->ContextList))
3019 V0(device->Backend,stop)();
3020 device->Flags &= ~DEVICE_RUNNING;
3022 UnlockLists();
3024 if(ALContext)
3026 al_free(ALContext->Voices);
3027 ALContext->Voices = NULL;
3029 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3031 al_free(ALContext);
3032 ALContext = NULL;
3035 alcSetError(device, ALC_OUT_OF_MEMORY);
3036 ALCdevice_DecRef(device);
3037 return NULL;
3040 ALContext->Device = device;
3041 ALCdevice_IncRef(device);
3042 InitContext(ALContext);
3045 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3046 do {
3047 ALContext->next = head;
3048 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3050 UnlockLists();
3052 ALCdevice_DecRef(device);
3054 TRACE("Created context %p\n", ALContext);
3055 return ALContext;
3058 /* alcDestroyContext
3060 * Remove a context from its device
3062 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3064 ALCdevice *Device;
3066 LockLists();
3067 /* alcGetContextsDevice sets an error for invalid contexts */
3068 Device = alcGetContextsDevice(context);
3069 if(Device)
3071 ReleaseContext(context, Device);
3072 if(!ATOMIC_LOAD(&Device->ContextList))
3074 V0(Device->Backend,stop)();
3075 Device->Flags &= ~DEVICE_RUNNING;
3078 UnlockLists();
3082 /* alcGetCurrentContext
3084 * Returns the currently active context on the calling thread
3086 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3088 ALCcontext *Context = altss_get(LocalContext);
3089 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3090 return Context;
3093 /* alcGetThreadContext
3095 * Returns the currently active thread-local context
3097 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3099 return altss_get(LocalContext);
3103 /* alcMakeContextCurrent
3105 * Makes the given context the active process-wide context, and removes the
3106 * thread-local context for the calling thread.
3108 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3110 /* context must be valid or NULL */
3111 if(context && !(context=VerifyContext(context)))
3113 alcSetError(NULL, ALC_INVALID_CONTEXT);
3114 return ALC_FALSE;
3116 /* context's reference count is already incremented */
3117 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3118 if(context) ALCcontext_DecRef(context);
3120 if((context=altss_get(LocalContext)) != NULL)
3122 altss_set(LocalContext, NULL);
3123 ALCcontext_DecRef(context);
3126 return ALC_TRUE;
3129 /* alcSetThreadContext
3131 * Makes the given context the active context for the current thread
3133 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3135 ALCcontext *old;
3137 /* context must be valid or NULL */
3138 if(context && !(context=VerifyContext(context)))
3140 alcSetError(NULL, ALC_INVALID_CONTEXT);
3141 return ALC_FALSE;
3143 /* context's reference count is already incremented */
3144 old = altss_get(LocalContext);
3145 altss_set(LocalContext, context);
3146 if(old) ALCcontext_DecRef(old);
3148 return ALC_TRUE;
3152 /* alcGetContextsDevice
3154 * Returns the device that a particular context is attached to
3156 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3158 ALCdevice *Device;
3160 if(!(Context=VerifyContext(Context)))
3162 alcSetError(NULL, ALC_INVALID_CONTEXT);
3163 return NULL;
3165 Device = Context->Device;
3166 ALCcontext_DecRef(Context);
3168 return Device;
3172 /* alcOpenDevice
3174 * Opens the named device.
3176 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3178 const ALCchar *fmt;
3179 ALCdevice *device;
3180 ALCenum err;
3182 DO_INITCONFIG();
3184 if(!PlaybackBackend.name)
3186 alcSetError(NULL, ALC_INVALID_VALUE);
3187 return NULL;
3190 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3191 deviceName = NULL;
3193 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3194 if(!device)
3196 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3197 return NULL;
3200 //Validate device
3201 InitRef(&device->ref, 1);
3202 device->Connected = ALC_TRUE;
3203 device->Type = Playback;
3204 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3206 device->Flags = 0;
3207 device->Bs2b = NULL;
3208 device->Bs2bLevel = 0;
3209 AL_STRING_INIT(device->DeviceName);
3211 ATOMIC_INIT(&device->ContextList, NULL);
3213 device->ClockBase = 0;
3214 device->SamplesDone = 0;
3216 device->MaxNoOfSources = 256;
3217 device->AuxiliaryEffectSlotMax = 4;
3218 device->NumAuxSends = MAX_SENDS;
3220 InitUIntMap(&device->BufferMap, ~0);
3221 InitUIntMap(&device->EffectMap, ~0);
3222 InitUIntMap(&device->FilterMap, ~0);
3223 InitUIntMap(&device->SfontMap, ~0);
3224 InitUIntMap(&device->PresetMap, ~0);
3225 InitUIntMap(&device->FontsoundMap, ~0);
3227 //Set output format
3228 device->FmtChans = DevFmtChannelsDefault;
3229 device->FmtType = DevFmtTypeDefault;
3230 device->Frequency = DEFAULT_OUTPUT_RATE;
3231 device->NumUpdates = 4;
3232 device->UpdateSize = 1024;
3234 if(!PlaybackBackend.getFactory)
3235 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3236 ALCbackend_Playback);
3237 else
3239 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3240 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3242 if(!device->Backend)
3244 al_free(device);
3245 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3246 return NULL;
3250 if(ConfigValueStr(NULL, "channels", &fmt))
3252 static const struct {
3253 const char name[16];
3254 enum DevFmtChannels chans;
3255 } chanlist[] = {
3256 { "mono", DevFmtMono },
3257 { "stereo", DevFmtStereo },
3258 { "quad", DevFmtQuad },
3259 { "surround51", DevFmtX51 },
3260 { "surround61", DevFmtX61 },
3261 { "surround71", DevFmtX71 },
3263 size_t i;
3265 for(i = 0;i < COUNTOF(chanlist);i++)
3267 if(strcasecmp(chanlist[i].name, fmt) == 0)
3269 device->FmtChans = chanlist[i].chans;
3270 device->Flags |= DEVICE_CHANNELS_REQUEST;
3271 break;
3274 if(i == COUNTOF(chanlist))
3275 ERR("Unsupported channels: %s\n", fmt);
3277 if(ConfigValueStr(NULL, "sample-type", &fmt))
3279 static const struct {
3280 const char name[16];
3281 enum DevFmtType type;
3282 } typelist[] = {
3283 { "int8", DevFmtByte },
3284 { "uint8", DevFmtUByte },
3285 { "int16", DevFmtShort },
3286 { "uint16", DevFmtUShort },
3287 { "int32", DevFmtInt },
3288 { "uint32", DevFmtUInt },
3289 { "float32", DevFmtFloat },
3291 size_t i;
3293 for(i = 0;i < COUNTOF(typelist);i++)
3295 if(strcasecmp(typelist[i].name, fmt) == 0)
3297 device->FmtType = typelist[i].type;
3298 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3299 break;
3302 if(i == COUNTOF(typelist))
3303 ERR("Unsupported sample-type: %s\n", fmt);
3305 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3306 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3307 ConfigValueStr(NULL, "format", &fmt))
3309 static const struct {
3310 const char name[32];
3311 enum DevFmtChannels channels;
3312 enum DevFmtType type;
3313 } formats[] = {
3314 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3315 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3316 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3317 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3318 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3319 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3321 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3322 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3323 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3324 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3325 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3326 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3328 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3329 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3330 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3331 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3332 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3333 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3335 size_t i;
3337 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3338 for(i = 0;i < COUNTOF(formats);i++)
3340 if(strcasecmp(fmt, formats[i].name) == 0)
3342 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3343 device->FmtChans = formats[i].channels;
3344 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3345 device->FmtType = formats[i].type;
3346 device->Flags |= DEVICE_FORMAT_REQUEST;
3347 break;
3350 if(i == COUNTOF(formats))
3351 ERR("Unsupported format: %s\n", fmt);
3353 #undef DEVICE_FORMAT_REQUEST
3355 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3357 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3358 if(device->Frequency < MIN_OUTPUT_RATE)
3359 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3360 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3363 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3364 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3366 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3367 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3368 if((CPUCapFlags&CPU_CAP_SSE))
3369 device->UpdateSize = (device->UpdateSize+3)&~3;
3371 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3372 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3374 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3375 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3377 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3378 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3380 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3382 device->NumStereoSources = 1;
3383 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3385 device->Synth = SynthCreate(device);
3386 if(!device->Synth)
3388 DELETE_OBJ(device->Backend);
3389 al_free(device);
3390 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3391 return NULL;
3394 // Find a playback device to open
3395 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3397 DELETE_OBJ(device->Synth);
3398 DELETE_OBJ(device->Backend);
3399 al_free(device);
3400 alcSetError(NULL, err);
3401 return NULL;
3404 if(DefaultEffect.type != AL_EFFECT_NULL)
3406 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3407 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3409 device->DefaultSlot = NULL;
3410 ERR("Failed to initialize the default effect slot\n");
3412 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3414 ALeffectState *state = device->DefaultSlot->EffectState;
3415 device->DefaultSlot = NULL;
3416 DELETE_OBJ(state);
3417 ERR("Failed to initialize the default effect\n");
3422 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3423 do {
3424 device->next = head;
3425 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3428 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3429 return device;
3432 /* alcCloseDevice
3434 * Closes the given device.
3436 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3438 ALCdevice *list, *origdev, *nextdev;
3439 ALCcontext *ctx;
3441 LockLists();
3442 list = ATOMIC_LOAD(&DeviceList);
3443 do {
3444 if(list == device)
3445 break;
3446 } while((list=list->next) != NULL);
3447 if(!list || list->Type == Capture)
3449 alcSetError(list, ALC_INVALID_DEVICE);
3450 UnlockLists();
3451 return ALC_FALSE;
3454 origdev = device;
3455 nextdev = device->next;
3456 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3458 do {
3459 list = origdev;
3460 origdev = device;
3461 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3463 UnlockLists();
3465 ctx = ATOMIC_LOAD(&device->ContextList);
3466 while(ctx != NULL)
3468 ALCcontext *next = ctx->next;
3469 WARN("Releasing context %p\n", ctx);
3470 ReleaseContext(ctx, device);
3471 ctx = next;
3473 if((device->Flags&DEVICE_RUNNING))
3474 V0(device->Backend,stop)();
3475 device->Flags &= ~DEVICE_RUNNING;
3477 ALCdevice_DecRef(device);
3479 return ALC_TRUE;
3483 /************************************************
3484 * ALC capture functions
3485 ************************************************/
3486 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3488 ALCdevice *device = NULL;
3489 ALCenum err;
3491 DO_INITCONFIG();
3493 if(!CaptureBackend.name)
3495 alcSetError(NULL, ALC_INVALID_VALUE);
3496 return NULL;
3499 if(samples <= 0)
3501 alcSetError(NULL, ALC_INVALID_VALUE);
3502 return NULL;
3505 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3506 deviceName = NULL;
3508 device = al_calloc(16, sizeof(ALCdevice));
3509 if(!device)
3511 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3512 return NULL;
3515 //Validate device
3516 InitRef(&device->ref, 1);
3517 device->Connected = ALC_TRUE;
3518 device->Type = Capture;
3520 AL_STRING_INIT(device->DeviceName);
3522 InitUIntMap(&device->BufferMap, ~0);
3523 InitUIntMap(&device->EffectMap, ~0);
3524 InitUIntMap(&device->FilterMap, ~0);
3525 InitUIntMap(&device->SfontMap, ~0);
3526 InitUIntMap(&device->PresetMap, ~0);
3527 InitUIntMap(&device->FontsoundMap, ~0);
3529 if(!CaptureBackend.getFactory)
3530 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3531 ALCbackend_Capture);
3532 else
3534 ALCbackendFactory *factory = CaptureBackend.getFactory();
3535 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3537 if(!device->Backend)
3539 al_free(device);
3540 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3541 return NULL;
3544 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3545 device->Frequency = frequency;
3547 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3548 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3550 al_free(device);
3551 alcSetError(NULL, ALC_INVALID_ENUM);
3552 return NULL;
3555 device->UpdateSize = samples;
3556 device->NumUpdates = 1;
3558 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3560 al_free(device);
3561 alcSetError(NULL, err);
3562 return NULL;
3566 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3567 do {
3568 device->next = head;
3569 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3572 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3573 return device;
3576 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3578 ALCdevice *list, *next, *nextdev;
3580 LockLists();
3581 list = ATOMIC_LOAD(&DeviceList);
3582 do {
3583 if(list == device)
3584 break;
3585 } while((list=list->next) != NULL);
3586 if(!list || list->Type != Capture)
3588 alcSetError(list, ALC_INVALID_DEVICE);
3589 UnlockLists();
3590 return ALC_FALSE;
3593 next = device;
3594 nextdev = device->next;
3595 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3597 do {
3598 list = next;
3599 next = device;
3600 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3602 UnlockLists();
3604 ALCdevice_DecRef(device);
3606 return ALC_TRUE;
3609 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3611 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3612 alcSetError(device, ALC_INVALID_DEVICE);
3613 else
3615 ALCdevice_Lock(device);
3616 if(device->Connected)
3618 if(!(device->Flags&DEVICE_RUNNING))
3619 V0(device->Backend,start)();
3620 device->Flags |= DEVICE_RUNNING;
3622 ALCdevice_Unlock(device);
3625 if(device) ALCdevice_DecRef(device);
3628 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3630 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3631 alcSetError(device, ALC_INVALID_DEVICE);
3632 else
3634 ALCdevice_Lock(device);
3635 if((device->Flags&DEVICE_RUNNING))
3636 V0(device->Backend,stop)();
3637 device->Flags &= ~DEVICE_RUNNING;
3638 ALCdevice_Unlock(device);
3641 if(device) ALCdevice_DecRef(device);
3644 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3646 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3647 alcSetError(device, ALC_INVALID_DEVICE);
3648 else
3650 ALCenum err = ALC_INVALID_VALUE;
3652 ALCdevice_Lock(device);
3653 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3654 err = V(device->Backend,captureSamples)(buffer, samples);
3655 ALCdevice_Unlock(device);
3657 if(err != ALC_NO_ERROR)
3658 alcSetError(device, err);
3660 if(device) ALCdevice_DecRef(device);
3664 /************************************************
3665 * ALC loopback functions
3666 ************************************************/
3668 /* alcLoopbackOpenDeviceSOFT
3670 * Open a loopback device, for manual rendering.
3672 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3674 ALCbackendFactory *factory;
3675 ALCdevice *device;
3677 DO_INITCONFIG();
3679 /* Make sure the device name, if specified, is us. */
3680 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3682 alcSetError(NULL, ALC_INVALID_VALUE);
3683 return NULL;
3686 device = al_calloc(16, sizeof(ALCdevice));
3687 if(!device)
3689 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3690 return NULL;
3693 //Validate device
3694 InitRef(&device->ref, 1);
3695 device->Connected = ALC_TRUE;
3696 device->Type = Loopback;
3697 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3699 device->Flags = 0;
3700 device->Bs2b = NULL;
3701 device->Bs2bLevel = 0;
3702 AL_STRING_INIT(device->DeviceName);
3704 ATOMIC_INIT(&device->ContextList, NULL);
3706 device->ClockBase = 0;
3707 device->SamplesDone = 0;
3709 device->MaxNoOfSources = 256;
3710 device->AuxiliaryEffectSlotMax = 4;
3711 device->NumAuxSends = MAX_SENDS;
3713 InitUIntMap(&device->BufferMap, ~0);
3714 InitUIntMap(&device->EffectMap, ~0);
3715 InitUIntMap(&device->FilterMap, ~0);
3716 InitUIntMap(&device->SfontMap, ~0);
3717 InitUIntMap(&device->PresetMap, ~0);
3718 InitUIntMap(&device->FontsoundMap, ~0);
3720 factory = ALCloopbackFactory_getFactory();
3721 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3722 if(!device->Backend)
3724 al_free(device);
3725 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3726 return NULL;
3729 //Set output format
3730 device->NumUpdates = 0;
3731 device->UpdateSize = 0;
3733 device->Frequency = DEFAULT_OUTPUT_RATE;
3734 device->FmtChans = DevFmtChannelsDefault;
3735 device->FmtType = DevFmtTypeDefault;
3737 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3738 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3740 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3741 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3743 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3744 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3746 device->NumStereoSources = 1;
3747 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3749 device->Synth = SynthCreate(device);
3750 if(!device->Synth)
3752 DELETE_OBJ(device->Backend);
3753 al_free(device);
3754 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3755 return NULL;
3758 // Open the "backend"
3759 V(device->Backend,open)("Loopback");
3762 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3763 do {
3764 device->next = head;
3765 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3768 TRACE("Created device %p\n", device);
3769 return device;
3772 /* alcIsRenderFormatSupportedSOFT
3774 * Determines if the loopback device supports the given format for rendering.
3776 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3778 ALCboolean ret = ALC_FALSE;
3780 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3781 alcSetError(device, ALC_INVALID_DEVICE);
3782 else if(freq <= 0)
3783 alcSetError(device, ALC_INVALID_VALUE);
3784 else
3786 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3787 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3788 freq >= MIN_OUTPUT_RATE)
3789 ret = ALC_TRUE;
3791 if(device) ALCdevice_DecRef(device);
3793 return ret;
3796 /* alcRenderSamplesSOFT
3798 * Renders some samples into a buffer, using the format last set by the
3799 * attributes given to alcCreateContext.
3801 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3803 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3804 alcSetError(device, ALC_INVALID_DEVICE);
3805 else if(samples < 0 || (samples > 0 && buffer == NULL))
3806 alcSetError(device, ALC_INVALID_VALUE);
3807 else
3808 aluMixData(device, buffer, samples);
3809 if(device) ALCdevice_DecRef(device);
3813 /************************************************
3814 * ALC DSP pause/resume functions
3815 ************************************************/
3817 /* alcDevicePauseSOFT
3819 * Pause the DSP to stop audio processing.
3821 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3823 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3824 alcSetError(device, ALC_INVALID_DEVICE);
3825 else
3827 LockLists();
3828 if((device->Flags&DEVICE_RUNNING))
3829 V0(device->Backend,stop)();
3830 device->Flags &= ~DEVICE_RUNNING;
3831 device->Flags |= DEVICE_PAUSED;
3832 UnlockLists();
3834 if(device) ALCdevice_DecRef(device);
3837 /* alcDeviceResumeSOFT
3839 * Resume the DSP to restart audio processing.
3841 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3843 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3844 alcSetError(device, ALC_INVALID_DEVICE);
3845 else
3847 LockLists();
3848 if((device->Flags&DEVICE_PAUSED))
3850 device->Flags &= ~DEVICE_PAUSED;
3851 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3853 if(V0(device->Backend,start)() != ALC_FALSE)
3854 device->Flags |= DEVICE_RUNNING;
3855 else
3857 alcSetError(device, ALC_INVALID_DEVICE);
3858 ALCdevice_Lock(device);
3859 aluHandleDisconnect(device);
3860 ALCdevice_Unlock(device);
3864 UnlockLists();
3866 if(device) ALCdevice_DecRef(device);