Add a helper to search for a channel index by name
[openal-soft.git] / Alc / ALc.c
blob04c3f398d61cff983bb45987befa2b9578b73d7a
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;
752 /************************************************
753 * ALC information
754 ************************************************/
755 static const ALCchar alcNoDeviceExtList[] =
756 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
757 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
758 static const ALCchar alcExtensionList[] =
759 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
760 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
761 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
762 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
763 static const ALCint alcMajorVersion = 1;
764 static const ALCint alcMinorVersion = 1;
766 static const ALCint alcEFXMajorVersion = 1;
767 static const ALCint alcEFXMinorVersion = 0;
770 /************************************************
771 * Device lists
772 ************************************************/
773 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
775 static almtx_t ListLock;
776 static inline void LockLists(void)
778 int lockret = almtx_lock(&ListLock);
779 assert(lockret == althrd_success);
781 static inline void UnlockLists(void)
783 int unlockret = almtx_unlock(&ListLock);
784 assert(unlockret == althrd_success);
787 /************************************************
788 * Library initialization
789 ************************************************/
790 #if defined(_WIN32)
791 static void alc_init(void);
792 static void alc_deinit(void);
793 static void alc_deinit_safe(void);
795 #ifndef AL_LIBTYPE_STATIC
796 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
798 switch(reason)
800 case DLL_PROCESS_ATTACH:
801 /* Pin the DLL so we won't get unloaded until the process terminates */
802 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 (WCHAR*)hModule, &hModule);
804 alc_init();
805 break;
807 case DLL_THREAD_DETACH:
808 break;
810 case DLL_PROCESS_DETACH:
811 if(!lpReserved)
812 alc_deinit();
813 else
814 alc_deinit_safe();
815 break;
817 return TRUE;
819 #elif defined(_MSC_VER)
820 #pragma section(".CRT$XCU",read)
821 static void alc_constructor(void);
822 static void alc_destructor(void);
823 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
825 static void alc_constructor(void)
827 atexit(alc_destructor);
828 alc_init();
831 static void alc_destructor(void)
833 alc_deinit();
835 #elif defined(HAVE_GCC_DESTRUCTOR)
836 static void alc_init(void) __attribute__((constructor));
837 static void alc_deinit(void) __attribute__((destructor));
838 #else
839 #error "No static initialization available on this platform!"
840 #endif
842 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No global initialization available on this platform!"
849 #endif
851 static void ReleaseThreadCtx(void *ptr);
852 static void alc_init(void)
854 const char *str;
855 int ret;
857 LogFile = stderr;
859 AL_STRING_INIT(alcAllDevicesList);
860 AL_STRING_INIT(alcCaptureDeviceList);
862 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ConeScale *= 0.5f;
866 str = getenv("__ALSOFT_REVERSE_Z");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 ZScale *= -1.0f;
870 ret = altss_create(&LocalContext, ReleaseThreadCtx);
871 assert(ret == althrd_success);
873 ret = almtx_init(&ListLock, almtx_recursive);
874 assert(ret == althrd_success);
876 ThunkInit();
879 static void alc_initconfig(void)
881 const char *devs, *str;
882 ALuint capfilter;
883 float valf;
884 int i, n;
886 str = getenv("ALSOFT_LOGLEVEL");
887 if(str)
889 long lvl = strtol(str, NULL, 0);
890 if(lvl >= NoLog && lvl <= LogRef)
891 LogLevel = lvl;
894 str = getenv("ALSOFT_LOGFILE");
895 if(str && str[0])
897 FILE *logfile = al_fopen(str, "wt");
898 if(logfile) LogFile = logfile;
899 else ERR("Failed to open log file '%s'\n", str);
903 char buf[1024] = "";
904 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
905 for(i = 1;BackendList[i].name;i++)
906 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
907 TRACE("Supported backends: %s\n", buf);
909 ReadALConfig();
911 capfilter = 0;
912 #if defined(HAVE_SSE4_1)
913 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
914 #elif defined(HAVE_SSE2)
915 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
916 #elif defined(HAVE_SSE)
917 capfilter |= CPU_CAP_SSE;
918 #endif
919 #ifdef HAVE_NEON
920 capfilter |= CPU_CAP_NEON;
921 #endif
922 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
924 if(strcasecmp(str, "all") == 0)
925 capfilter = 0;
926 else
928 size_t len;
929 const char *next = str;
931 do {
932 str = next;
933 while(isspace(str[0]))
934 str++;
935 next = strchr(str, ',');
937 if(!str[0] || str[0] == ',')
938 continue;
940 len = (next ? ((size_t)(next-str)) : strlen(str));
941 while(len > 0 && isspace(str[len-1]))
942 len--;
943 if(len == 3 && strncasecmp(str, "sse", len) == 0)
944 capfilter &= ~CPU_CAP_SSE;
945 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
946 capfilter &= ~CPU_CAP_SSE2;
947 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
948 capfilter &= ~CPU_CAP_SSE4_1;
949 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
950 capfilter &= ~CPU_CAP_NEON;
951 else
952 WARN("Invalid CPU extension \"%s\"\n", str);
953 } while(next++);
956 FillCPUCaps(capfilter);
958 #ifdef _WIN32
959 RTPrioLevel = 1;
960 #else
961 RTPrioLevel = 0;
962 #endif
963 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
965 if(ConfigValueStr(NULL, "resampler", &str))
967 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
968 DefaultResampler = PointResampler;
969 else if(strcasecmp(str, "linear") == 0)
970 DefaultResampler = LinearResampler;
971 else if(strcasecmp(str, "cubic") == 0)
972 DefaultResampler = CubicResampler;
973 else
975 char *end;
977 n = strtol(str, &end, 0);
978 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
979 DefaultResampler = n;
980 else
981 WARN("Invalid resampler: %s\n", str);
985 str = getenv("ALSOFT_TRAP_ERROR");
986 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALError = AL_TRUE;
989 TrapALCError = AL_TRUE;
991 else
993 str = getenv("ALSOFT_TRAP_AL_ERROR");
994 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
995 TrapALError = AL_TRUE;
996 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
998 str = getenv("ALSOFT_TRAP_ALC_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1000 TrapALCError = ALC_TRUE;
1001 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1004 if(ConfigValueFloat("reverb", "boost", &valf))
1005 ReverbBoost *= powf(10.0f, valf / 20.0f);
1007 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1009 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1010 ConfigValueStr(NULL, "drivers", &devs))
1012 int n;
1013 size_t len;
1014 const char *next = devs;
1015 int endlist, delitem;
1017 i = 0;
1018 do {
1019 devs = next;
1020 while(isspace(devs[0]))
1021 devs++;
1022 next = strchr(devs, ',');
1024 delitem = (devs[0] == '-');
1025 if(devs[0] == '-') devs++;
1027 if(!devs[0] || devs[0] == ',')
1029 endlist = 0;
1030 continue;
1032 endlist = 1;
1034 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1035 while(len > 0 && isspace(devs[len-1]))
1036 len--;
1037 for(n = i;BackendList[n].name;n++)
1039 if(len == strlen(BackendList[n].name) &&
1040 strncmp(BackendList[n].name, devs, len) == 0)
1042 if(delitem)
1044 do {
1045 BackendList[n] = BackendList[n+1];
1046 ++n;
1047 } while(BackendList[n].name);
1049 else
1051 struct BackendInfo Bkp = BackendList[n];
1052 while(n > i)
1054 BackendList[n] = BackendList[n-1];
1055 --n;
1057 BackendList[n] = Bkp;
1059 i++;
1061 break;
1064 } while(next++);
1066 if(endlist)
1068 BackendList[i].name = NULL;
1069 BackendList[i].getFactory = NULL;
1070 BackendList[i].Init = NULL;
1071 BackendList[i].Deinit = NULL;
1072 BackendList[i].Probe = NULL;
1076 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1078 if(BackendList[i].getFactory)
1080 ALCbackendFactory *factory = BackendList[i].getFactory();
1081 if(!V0(factory,init)())
1083 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1084 continue;
1087 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1088 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1090 PlaybackBackend = BackendList[i];
1091 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1093 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1095 CaptureBackend = BackendList[i];
1096 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1099 continue;
1102 if(!BackendList[i].Init(&BackendList[i].Funcs))
1104 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1105 continue;
1108 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1109 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1111 PlaybackBackend = BackendList[i];
1112 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1114 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1116 CaptureBackend = BackendList[i];
1117 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1121 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1122 V0(factory,init)();
1125 if(ConfigValueStr(NULL, "excludefx", &str))
1127 size_t len;
1128 const char *next = str;
1130 do {
1131 str = next;
1132 next = strchr(str, ',');
1134 if(!str[0] || next == str)
1135 continue;
1137 len = (next ? ((size_t)(next-str)) : strlen(str));
1138 for(n = 0;EffectList[n].name;n++)
1140 if(len == strlen(EffectList[n].name) &&
1141 strncmp(EffectList[n].name, str, len) == 0)
1142 DisabledEffects[EffectList[n].type] = AL_TRUE;
1144 } while(next++);
1147 InitEffectFactoryMap();
1149 InitEffect(&DefaultEffect);
1150 str = getenv("ALSOFT_DEFAULT_REVERB");
1151 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1152 LoadReverbPreset(str, &DefaultEffect);
1154 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1157 /************************************************
1158 * Library deinitialization
1159 ************************************************/
1160 static void alc_cleanup(void)
1162 ALCdevice *dev;
1164 AL_STRING_DEINIT(alcAllDevicesList);
1165 AL_STRING_DEINIT(alcCaptureDeviceList);
1167 free(alcDefaultAllDevicesSpecifier);
1168 alcDefaultAllDevicesSpecifier = NULL;
1169 free(alcCaptureDefaultDeviceSpecifier);
1170 alcCaptureDefaultDeviceSpecifier = NULL;
1172 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1174 ALCuint num = 0;
1175 do {
1176 num++;
1177 } while((dev=dev->next) != NULL);
1178 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1181 DeinitEffectFactoryMap();
1184 static void alc_deinit_safe(void)
1186 alc_cleanup();
1188 FreeHrtfs();
1189 FreeALConfig();
1191 ThunkExit();
1192 almtx_destroy(&ListLock);
1193 altss_delete(LocalContext);
1195 if(LogFile != stderr)
1196 fclose(LogFile);
1197 LogFile = NULL;
1200 static void alc_deinit(void)
1202 int i;
1204 alc_cleanup();
1206 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1207 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1209 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1211 if(!BackendList[i].getFactory)
1212 BackendList[i].Deinit();
1213 else
1215 ALCbackendFactory *factory = BackendList[i].getFactory();
1216 V0(factory,deinit)();
1220 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1221 V0(factory,deinit)();
1224 alc_deinit_safe();
1228 /************************************************
1229 * Device enumeration
1230 ************************************************/
1231 static void ProbeDevices(al_string *list, enum DevProbe type)
1233 DO_INITCONFIG();
1235 LockLists();
1236 al_string_clear(list);
1238 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1240 if(!PlaybackBackend.getFactory)
1241 PlaybackBackend.Probe(type);
1242 else
1244 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1245 V(factory,probe)(type);
1248 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1250 if(!CaptureBackend.getFactory)
1251 CaptureBackend.Probe(type);
1252 else
1254 ALCbackendFactory *factory = CaptureBackend.getFactory();
1255 V(factory,probe)(type);
1258 UnlockLists();
1260 static void ProbeAllDevicesList(void)
1261 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1262 static void ProbeCaptureDeviceList(void)
1263 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1265 static void AppendDevice(const ALCchar *name, al_string *devnames)
1267 size_t len = strlen(name);
1268 if(len > 0)
1269 al_string_append_range(devnames, name, name+len+1);
1271 void AppendAllDevicesList(const ALCchar *name)
1272 { AppendDevice(name, &alcAllDevicesList); }
1273 void AppendCaptureDeviceList(const ALCchar *name)
1274 { AppendDevice(name, &alcCaptureDeviceList); }
1277 /************************************************
1278 * Device format information
1279 ************************************************/
1280 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1282 switch(type)
1284 case DevFmtByte: return "Signed Byte";
1285 case DevFmtUByte: return "Unsigned Byte";
1286 case DevFmtShort: return "Signed Short";
1287 case DevFmtUShort: return "Unsigned Short";
1288 case DevFmtInt: return "Signed Int";
1289 case DevFmtUInt: return "Unsigned Int";
1290 case DevFmtFloat: return "Float";
1292 return "(unknown type)";
1294 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1296 switch(chans)
1298 case DevFmtMono: return "Mono";
1299 case DevFmtStereo: return "Stereo";
1300 case DevFmtQuad: return "Quadraphonic";
1301 case DevFmtX51: return "5.1 Surround";
1302 case DevFmtX51Side: return "5.1 Side";
1303 case DevFmtX61: return "6.1 Surround";
1304 case DevFmtX71: return "7.1 Surround";
1306 return "(unknown channels)";
1309 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1310 ALuint BytesFromDevFmt(enum DevFmtType type)
1312 switch(type)
1314 case DevFmtByte: return sizeof(ALbyte);
1315 case DevFmtUByte: return sizeof(ALubyte);
1316 case DevFmtShort: return sizeof(ALshort);
1317 case DevFmtUShort: return sizeof(ALushort);
1318 case DevFmtInt: return sizeof(ALint);
1319 case DevFmtUInt: return sizeof(ALuint);
1320 case DevFmtFloat: return sizeof(ALfloat);
1322 return 0;
1324 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1326 switch(chans)
1328 case DevFmtMono: return 1;
1329 case DevFmtStereo: return 2;
1330 case DevFmtQuad: return 4;
1331 case DevFmtX51: return 6;
1332 case DevFmtX51Side: return 6;
1333 case DevFmtX61: return 7;
1334 case DevFmtX71: return 8;
1336 return 0;
1339 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1340 enum DevFmtChannels *chans, enum DevFmtType *type)
1342 static const struct {
1343 ALenum format;
1344 enum DevFmtChannels channels;
1345 enum DevFmtType type;
1346 } list[] = {
1347 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1348 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1349 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1351 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1352 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1353 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1355 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1356 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1357 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1359 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1360 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1361 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1363 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1364 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1365 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1367 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1368 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1369 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1371 ALuint i;
1373 for(i = 0;i < COUNTOF(list);i++)
1375 if(list[i].format == format)
1377 *chans = list[i].channels;
1378 *type = list[i].type;
1379 return AL_TRUE;
1383 return AL_FALSE;
1386 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1388 switch(type)
1390 case ALC_BYTE_SOFT:
1391 case ALC_UNSIGNED_BYTE_SOFT:
1392 case ALC_SHORT_SOFT:
1393 case ALC_UNSIGNED_SHORT_SOFT:
1394 case ALC_INT_SOFT:
1395 case ALC_UNSIGNED_INT_SOFT:
1396 case ALC_FLOAT_SOFT:
1397 return ALC_TRUE;
1399 return ALC_FALSE;
1402 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1404 switch(channels)
1406 case ALC_MONO_SOFT:
1407 case ALC_STEREO_SOFT:
1408 case ALC_QUAD_SOFT:
1409 case ALC_5POINT1_SOFT:
1410 case ALC_6POINT1_SOFT:
1411 case ALC_7POINT1_SOFT:
1412 return ALC_TRUE;
1414 return ALC_FALSE;
1418 /************************************************
1419 * Miscellaneous ALC helpers
1420 ************************************************/
1421 extern inline void LockContext(ALCcontext *context);
1422 extern inline void UnlockContext(ALCcontext *context);
1424 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1426 return V0(device->Backend,getLatency)();
1429 void ALCdevice_Lock(ALCdevice *device)
1431 V0(device->Backend,lock)();
1434 void ALCdevice_Unlock(ALCdevice *device)
1436 V0(device->Backend,unlock)();
1440 /* SetDefaultWFXChannelOrder
1442 * Sets the default channel order used by WaveFormatEx.
1444 void SetDefaultWFXChannelOrder(ALCdevice *device)
1446 ALuint i;
1448 for(i = 0;i < MaxChannels;i++)
1449 device->ChannelName[i] = InvalidChannel;
1451 switch(device->FmtChans)
1453 case DevFmtMono: device->ChannelName[0] = FrontCenter;
1454 break;
1455 case DevFmtStereo: device->ChannelName[0] = FrontLeft;
1456 device->ChannelName[1] = FrontRight;
1457 break;
1458 case DevFmtQuad: device->ChannelName[0] = FrontLeft;
1459 device->ChannelName[1] = FrontRight;
1460 device->ChannelName[2] = BackLeft;
1461 device->ChannelName[3] = BackRight;
1462 break;
1463 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1464 device->ChannelName[1] = FrontRight;
1465 device->ChannelName[2] = FrontCenter;
1466 device->ChannelName[3] = LFE;
1467 device->ChannelName[4] = BackLeft;
1468 device->ChannelName[5] = BackRight;
1469 break;
1470 case DevFmtX51Side: device->ChannelName[0] = FrontLeft;
1471 device->ChannelName[1] = FrontRight;
1472 device->ChannelName[2] = FrontCenter;
1473 device->ChannelName[3] = LFE;
1474 device->ChannelName[4] = SideLeft;
1475 device->ChannelName[5] = SideRight;
1476 break;
1477 case DevFmtX61: device->ChannelName[0] = FrontLeft;
1478 device->ChannelName[1] = FrontRight;
1479 device->ChannelName[2] = FrontCenter;
1480 device->ChannelName[3] = LFE;
1481 device->ChannelName[4] = BackCenter;
1482 device->ChannelName[5] = SideLeft;
1483 device->ChannelName[6] = SideRight;
1484 break;
1485 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1486 device->ChannelName[1] = FrontRight;
1487 device->ChannelName[2] = FrontCenter;
1488 device->ChannelName[3] = LFE;
1489 device->ChannelName[4] = BackLeft;
1490 device->ChannelName[5] = BackRight;
1491 device->ChannelName[6] = SideLeft;
1492 device->ChannelName[7] = SideRight;
1493 break;
1497 /* SetDefaultChannelOrder
1499 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1501 void SetDefaultChannelOrder(ALCdevice *device)
1503 ALuint i;
1505 for(i = 0;i < MaxChannels;i++)
1506 device->ChannelName[i] = InvalidChannel;
1508 switch(device->FmtChans)
1510 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1511 device->ChannelName[1] = FrontRight;
1512 device->ChannelName[2] = BackLeft;
1513 device->ChannelName[3] = BackRight;
1514 device->ChannelName[4] = FrontCenter;
1515 device->ChannelName[5] = LFE;
1516 return;
1517 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1518 device->ChannelName[1] = FrontRight;
1519 device->ChannelName[2] = BackLeft;
1520 device->ChannelName[3] = BackRight;
1521 device->ChannelName[4] = FrontCenter;
1522 device->ChannelName[5] = LFE;
1523 device->ChannelName[6] = SideLeft;
1524 device->ChannelName[7] = SideRight;
1525 return;
1527 /* Same as WFX order */
1528 case DevFmtMono:
1529 case DevFmtStereo:
1530 case DevFmtQuad:
1531 case DevFmtX51Side:
1532 case DevFmtX61:
1533 SetDefaultWFXChannelOrder(device);
1534 break;
1538 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1541 /* alcSetError
1543 * Stores the latest ALC device error
1545 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1547 if(TrapALCError)
1549 #ifdef _WIN32
1550 /* DebugBreak() will cause an exception if there is no debugger */
1551 if(IsDebuggerPresent())
1552 DebugBreak();
1553 #elif defined(SIGTRAP)
1554 raise(SIGTRAP);
1555 #endif
1558 if(device)
1559 ATOMIC_STORE(&device->LastError, errorCode);
1560 else
1561 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1565 /* UpdateClockBase
1567 * Updates the device's base clock time with however many samples have been
1568 * done. This is used so frequency changes on the device don't cause the time
1569 * to jump forward or back.
1571 static inline void UpdateClockBase(ALCdevice *device)
1573 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1574 device->SamplesDone = 0;
1577 /* UpdateDeviceParams
1579 * Updates device parameters according to the attribute list (caller is
1580 * responsible for holding the list lock).
1582 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1584 ALCcontext *context;
1585 enum DevFmtChannels oldChans;
1586 enum DevFmtType oldType;
1587 ALCuint oldFreq;
1588 FPUCtl oldMode;
1590 // Check for attributes
1591 if(device->Type == Loopback)
1593 enum {
1594 GotFreq = 1<<0,
1595 GotChans = 1<<1,
1596 GotType = 1<<2,
1597 GotAll = GotFreq|GotChans|GotType
1599 ALCuint freq, numMono, numStereo, numSends, flags;
1600 enum DevFmtChannels schans;
1601 enum DevFmtType stype;
1602 ALCuint attrIdx = 0;
1603 ALCint gotFmt = 0;
1605 if(!attrList)
1607 WARN("Missing attributes for loopback device\n");
1608 return ALC_INVALID_VALUE;
1611 numMono = device->NumMonoSources;
1612 numStereo = device->NumStereoSources;
1613 numSends = device->NumAuxSends;
1614 schans = device->FmtChans;
1615 stype = device->FmtType;
1616 freq = device->Frequency;
1617 flags = device->Flags;
1619 while(attrList[attrIdx])
1621 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1623 ALCint val = attrList[attrIdx + 1];
1624 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1625 return ALC_INVALID_VALUE;
1626 schans = val;
1627 gotFmt |= GotChans;
1630 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1632 ALCint val = attrList[attrIdx + 1];
1633 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1634 return ALC_INVALID_VALUE;
1635 stype = val;
1636 gotFmt |= GotType;
1639 if(attrList[attrIdx] == ALC_FREQUENCY)
1641 freq = attrList[attrIdx + 1];
1642 if(freq < MIN_OUTPUT_RATE)
1643 return ALC_INVALID_VALUE;
1644 gotFmt |= GotFreq;
1647 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1649 numStereo = attrList[attrIdx + 1];
1650 if(numStereo > device->MaxNoOfSources)
1651 numStereo = device->MaxNoOfSources;
1653 numMono = device->MaxNoOfSources - numStereo;
1656 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1657 numSends = attrList[attrIdx + 1];
1659 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1661 if(attrList[attrIdx + 1] != ALC_FALSE)
1662 flags |= DEVICE_HRTF_REQUEST;
1663 else
1664 flags &= ~DEVICE_HRTF_REQUEST;
1667 attrIdx += 2;
1670 if(gotFmt != GotAll)
1672 WARN("Missing format for loopback device\n");
1673 return ALC_INVALID_VALUE;
1676 ConfigValueUInt(NULL, "sends", &numSends);
1677 numSends = minu(MAX_SENDS, numSends);
1679 if((device->Flags&DEVICE_RUNNING))
1680 V0(device->Backend,stop)();
1681 device->Flags = (flags & ~DEVICE_RUNNING);
1683 UpdateClockBase(device);
1685 device->Frequency = freq;
1686 device->FmtChans = schans;
1687 device->FmtType = stype;
1688 device->NumMonoSources = numMono;
1689 device->NumStereoSources = numStereo;
1690 device->NumAuxSends = numSends;
1692 else if(attrList && attrList[0])
1694 ALCuint freq, numMono, numStereo, numSends;
1695 ALCuint attrIdx = 0;
1697 /* If a context is already running on the device, stop playback so the
1698 * device attributes can be updated. */
1699 if((device->Flags&DEVICE_RUNNING))
1700 V0(device->Backend,stop)();
1701 device->Flags &= ~DEVICE_RUNNING;
1703 freq = device->Frequency;
1704 numMono = device->NumMonoSources;
1705 numStereo = device->NumStereoSources;
1706 numSends = device->NumAuxSends;
1708 while(attrList[attrIdx])
1710 if(attrList[attrIdx] == ALC_FREQUENCY)
1712 freq = attrList[attrIdx + 1];
1713 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1716 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1718 numStereo = attrList[attrIdx + 1];
1719 if(numStereo > device->MaxNoOfSources)
1720 numStereo = device->MaxNoOfSources;
1722 numMono = device->MaxNoOfSources - numStereo;
1725 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1726 numSends = attrList[attrIdx + 1];
1728 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1730 if(attrList[attrIdx + 1] != ALC_FALSE)
1731 device->Flags |= DEVICE_HRTF_REQUEST;
1732 else
1733 device->Flags &= ~DEVICE_HRTF_REQUEST;
1736 attrIdx += 2;
1739 ConfigValueUInt(NULL, "frequency", &freq);
1740 freq = maxu(freq, MIN_OUTPUT_RATE);
1742 ConfigValueUInt(NULL, "sends", &numSends);
1743 numSends = minu(MAX_SENDS, numSends);
1745 UpdateClockBase(device);
1747 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1748 device->Frequency;
1749 /* SSE and Neon do best with the update size being a multiple of 4 */
1750 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1751 device->UpdateSize = (device->UpdateSize+3)&~3;
1753 device->Frequency = freq;
1754 device->NumMonoSources = numMono;
1755 device->NumStereoSources = numStereo;
1756 device->NumAuxSends = numSends;
1759 if((device->Flags&DEVICE_RUNNING))
1760 return ALC_NO_ERROR;
1762 UpdateClockBase(device);
1764 if(device->Type != Loopback)
1766 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1767 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1768 device->Flags |= DEVICE_HRTF_REQUEST;
1769 else
1770 device->Flags &= ~DEVICE_HRTF_REQUEST;
1772 if((device->Flags&DEVICE_HRTF_REQUEST))
1774 enum DevFmtChannels chans = device->FmtChans;
1775 ALCuint freq = device->Frequency;
1776 if(FindHrtfFormat(&chans, &freq))
1778 if(device->Type != Loopback)
1780 device->Frequency = freq;
1781 device->FmtChans = chans;
1782 device->Flags |= DEVICE_CHANNELS_REQUEST |
1783 DEVICE_FREQUENCY_REQUEST;
1785 else if(device->Frequency != freq || device->FmtChans != chans)
1787 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1788 DevFmtChannelsString(device->FmtChans), device->Frequency);
1789 device->Flags &= ~DEVICE_HRTF_REQUEST;
1794 oldFreq = device->Frequency;
1795 oldChans = device->FmtChans;
1796 oldType = device->FmtType;
1798 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1799 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1800 DevFmtChannelsString(device->FmtChans),
1801 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1802 DevFmtTypeString(device->FmtType),
1803 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1804 device->Frequency,
1805 device->UpdateSize, device->NumUpdates);
1807 if(V0(device->Backend,reset)() == ALC_FALSE)
1808 return ALC_INVALID_DEVICE;
1810 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1812 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1813 DevFmtChannelsString(device->FmtChans));
1814 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1816 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1818 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1819 DevFmtTypeString(device->FmtType));
1820 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1822 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1824 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1825 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1828 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1829 DevFmtChannelsString(device->FmtChans),
1830 DevFmtTypeString(device->FmtType), device->Frequency,
1831 device->UpdateSize, device->NumUpdates);
1833 aluInitPanning(device);
1835 V(device->Synth,update)(device);
1837 device->Hrtf = NULL;
1838 if((device->Flags&DEVICE_HRTF_REQUEST))
1840 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1841 if(!device->Hrtf)
1842 device->Flags &= ~DEVICE_HRTF_REQUEST;
1844 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1846 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1848 if(!device->Bs2b)
1850 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1851 bs2b_clear(device->Bs2b);
1853 bs2b_set_srate(device->Bs2b, device->Frequency);
1854 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1855 TRACE("BS2B level %d\n", device->Bs2bLevel);
1857 else
1859 free(device->Bs2b);
1860 device->Bs2b = NULL;
1861 TRACE("BS2B disabled\n");
1864 device->Flags &= ~DEVICE_WIDE_STEREO;
1865 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1866 device->Flags |= DEVICE_WIDE_STEREO;
1868 if(!device->Hrtf && (device->UpdateSize&3))
1870 if((CPUCapFlags&CPU_CAP_SSE))
1871 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1872 if((CPUCapFlags&CPU_CAP_NEON))
1873 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1876 SetMixerFPUMode(&oldMode);
1877 ALCdevice_Lock(device);
1878 context = ATOMIC_LOAD(&device->ContextList);
1879 while(context)
1881 ALsizei pos;
1883 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
1884 LockUIntMapRead(&context->EffectSlotMap);
1885 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1887 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1889 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1891 UnlockUIntMapRead(&context->EffectSlotMap);
1892 ALCdevice_Unlock(device);
1893 RestoreFPUMode(&oldMode);
1894 return ALC_INVALID_DEVICE;
1896 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1897 V(slot->EffectState,update)(device, slot);
1899 UnlockUIntMapRead(&context->EffectSlotMap);
1901 LockUIntMapRead(&context->SourceMap);
1902 for(pos = 0;pos < context->SourceMap.size;pos++)
1904 ALsource *source = context->SourceMap.array[pos].value;
1905 ALuint s = device->NumAuxSends;
1906 while(s < MAX_SENDS)
1908 if(source->Send[s].Slot)
1909 DecrementRef(&source->Send[s].Slot->ref);
1910 source->Send[s].Slot = NULL;
1911 source->Send[s].Gain = 1.0f;
1912 source->Send[s].GainHF = 1.0f;
1913 s++;
1915 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
1917 UnlockUIntMapRead(&context->SourceMap);
1919 for(pos = 0;pos < context->VoiceCount;pos++)
1921 ALvoice *voice = &context->Voices[pos];
1922 ALsource *source = voice->Source;
1923 ALuint s = device->NumAuxSends;
1925 while(s < MAX_SENDS)
1927 voice->Send[s].Moving = AL_FALSE;
1928 voice->Send[s].Counter = 0;
1929 s++;
1932 if(source)
1934 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
1935 voice->Update(voice, source, context);
1939 context = context->next;
1941 if(device->DefaultSlot)
1943 ALeffectslot *slot = device->DefaultSlot;
1945 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1947 ALCdevice_Unlock(device);
1948 RestoreFPUMode(&oldMode);
1949 return ALC_INVALID_DEVICE;
1951 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1952 V(slot->EffectState,update)(device, slot);
1954 ALCdevice_Unlock(device);
1955 RestoreFPUMode(&oldMode);
1957 if(!(device->Flags&DEVICE_PAUSED))
1959 if(V0(device->Backend,start)() == ALC_FALSE)
1960 return ALC_INVALID_DEVICE;
1961 device->Flags |= DEVICE_RUNNING;
1964 return ALC_NO_ERROR;
1967 /* FreeDevice
1969 * Frees the device structure, and destroys any objects the app failed to
1970 * delete. Called once there's no more references on the device.
1972 static ALCvoid FreeDevice(ALCdevice *device)
1974 TRACE("%p\n", device);
1976 V0(device->Backend,close)();
1977 DELETE_OBJ(device->Backend);
1978 device->Backend = NULL;
1980 DELETE_OBJ(device->Synth);
1981 device->Synth = NULL;
1983 if(device->DefaultSlot)
1985 ALeffectState *state = device->DefaultSlot->EffectState;
1986 device->DefaultSlot = NULL;
1987 DELETE_OBJ(state);
1990 if(device->DefaultSfont)
1991 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1992 device->DefaultSfont = NULL;
1994 if(device->BufferMap.size > 0)
1996 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1997 ReleaseALBuffers(device);
1999 ResetUIntMap(&device->BufferMap);
2001 if(device->EffectMap.size > 0)
2003 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2004 ReleaseALEffects(device);
2006 ResetUIntMap(&device->EffectMap);
2008 if(device->FilterMap.size > 0)
2010 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2011 ReleaseALFilters(device);
2013 ResetUIntMap(&device->FilterMap);
2015 if(device->SfontMap.size > 0)
2017 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2018 ReleaseALSoundfonts(device);
2020 ResetUIntMap(&device->SfontMap);
2022 if(device->PresetMap.size > 0)
2024 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2025 ReleaseALPresets(device);
2027 ResetUIntMap(&device->PresetMap);
2029 if(device->FontsoundMap.size > 0)
2031 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2032 ReleaseALFontsounds(device);
2034 ResetUIntMap(&device->FontsoundMap);
2036 free(device->Bs2b);
2037 device->Bs2b = NULL;
2039 AL_STRING_DEINIT(device->DeviceName);
2041 al_free(device);
2045 void ALCdevice_IncRef(ALCdevice *device)
2047 uint ref;
2048 ref = IncrementRef(&device->ref);
2049 TRACEREF("%p increasing refcount to %u\n", device, ref);
2052 void ALCdevice_DecRef(ALCdevice *device)
2054 uint ref;
2055 ref = DecrementRef(&device->ref);
2056 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2057 if(ref == 0) FreeDevice(device);
2060 /* VerifyDevice
2062 * Checks if the device handle is valid, and increments its ref count if so.
2064 static ALCdevice *VerifyDevice(ALCdevice *device)
2066 ALCdevice *tmpDevice;
2068 if(!device)
2069 return NULL;
2071 LockLists();
2072 tmpDevice = ATOMIC_LOAD(&DeviceList);
2073 while(tmpDevice && tmpDevice != device)
2074 tmpDevice = tmpDevice->next;
2076 if(tmpDevice)
2077 ALCdevice_IncRef(tmpDevice);
2078 UnlockLists();
2079 return tmpDevice;
2083 /* InitContext
2085 * Initializes context fields
2087 static ALvoid InitContext(ALCcontext *Context)
2089 ALint i, j;
2091 //Initialise listener
2092 Context->Listener->Gain = 1.0f;
2093 Context->Listener->MetersPerUnit = 1.0f;
2094 Context->Listener->Position[0] = 0.0f;
2095 Context->Listener->Position[1] = 0.0f;
2096 Context->Listener->Position[2] = 0.0f;
2097 Context->Listener->Velocity[0] = 0.0f;
2098 Context->Listener->Velocity[1] = 0.0f;
2099 Context->Listener->Velocity[2] = 0.0f;
2100 Context->Listener->Forward[0] = 0.0f;
2101 Context->Listener->Forward[1] = 0.0f;
2102 Context->Listener->Forward[2] = -1.0f;
2103 Context->Listener->Up[0] = 0.0f;
2104 Context->Listener->Up[1] = 1.0f;
2105 Context->Listener->Up[2] = 0.0f;
2106 for(i = 0;i < 4;i++)
2108 for(j = 0;j < 4;j++)
2109 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2111 for(i = 0;i < 3;i++)
2112 Context->Listener->Params.Velocity[i] = 0.0f;
2114 //Validate Context
2115 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2116 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2117 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2118 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2120 //Set globals
2121 Context->DistanceModel = DefaultDistanceModel;
2122 Context->SourceDistanceModel = AL_FALSE;
2123 Context->DopplerFactor = 1.0f;
2124 Context->DopplerVelocity = 1.0f;
2125 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2126 Context->DeferUpdates = AL_FALSE;
2128 Context->ExtensionList = alExtList;
2132 /* FreeContext
2134 * Cleans up the context, and destroys any remaining objects the app failed to
2135 * delete. Called once there's no more references on the context.
2137 static void FreeContext(ALCcontext *context)
2139 TRACE("%p\n", context);
2141 if(context->SourceMap.size > 0)
2143 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2144 ReleaseALSources(context);
2146 ResetUIntMap(&context->SourceMap);
2148 if(context->EffectSlotMap.size > 0)
2150 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2151 ReleaseALAuxiliaryEffectSlots(context);
2153 ResetUIntMap(&context->EffectSlotMap);
2155 al_free(context->Voices);
2156 context->Voices = NULL;
2157 context->VoiceCount = 0;
2158 context->MaxVoices = 0;
2160 VECTOR_DEINIT(context->ActiveAuxSlots);
2162 ALCdevice_DecRef(context->Device);
2163 context->Device = NULL;
2165 //Invalidate context
2166 memset(context, 0, sizeof(ALCcontext));
2167 al_free(context);
2170 /* ReleaseContext
2172 * Removes the context reference from the given device and removes it from
2173 * being current on the running thread or globally.
2175 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2177 ALCcontext *nextctx;
2178 ALCcontext *origctx;
2180 if(altss_get(LocalContext) == context)
2182 WARN("%p released while current on thread\n", context);
2183 altss_set(LocalContext, NULL);
2184 ALCcontext_DecRef(context);
2187 origctx = context;
2188 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2189 ALCcontext_DecRef(context);
2191 ALCdevice_Lock(device);
2192 origctx = context;
2193 nextctx = context->next;
2194 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2196 ALCcontext *list;
2197 do {
2198 list = origctx;
2199 origctx = context;
2200 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2202 ALCdevice_Unlock(device);
2204 ALCcontext_DecRef(context);
2207 void ALCcontext_IncRef(ALCcontext *context)
2209 uint ref;
2210 ref = IncrementRef(&context->ref);
2211 TRACEREF("%p increasing refcount to %u\n", context, ref);
2214 void ALCcontext_DecRef(ALCcontext *context)
2216 uint ref;
2217 ref = DecrementRef(&context->ref);
2218 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2219 if(ref == 0) FreeContext(context);
2222 static void ReleaseThreadCtx(void *ptr)
2224 WARN("%p current for thread being destroyed\n", ptr);
2225 ALCcontext_DecRef(ptr);
2228 /* VerifyContext
2230 * Checks that the given context is valid, and increments its reference count.
2232 static ALCcontext *VerifyContext(ALCcontext *context)
2234 ALCdevice *dev;
2236 LockLists();
2237 dev = ATOMIC_LOAD(&DeviceList);
2238 while(dev)
2240 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2241 while(ctx)
2243 if(ctx == context)
2245 ALCcontext_IncRef(ctx);
2246 UnlockLists();
2247 return ctx;
2249 ctx = ctx->next;
2251 dev = dev->next;
2253 UnlockLists();
2255 return NULL;
2259 /* GetContextRef
2261 * Returns the currently active context for this thread, and adds a reference
2262 * without locking it.
2264 ALCcontext *GetContextRef(void)
2266 ALCcontext *context;
2268 context = altss_get(LocalContext);
2269 if(context)
2270 ALCcontext_IncRef(context);
2271 else
2273 LockLists();
2274 context = ATOMIC_LOAD(&GlobalContext);
2275 if(context)
2276 ALCcontext_IncRef(context);
2277 UnlockLists();
2280 return context;
2284 /************************************************
2285 * Standard ALC functions
2286 ************************************************/
2288 /* alcGetError
2290 * Return last ALC generated error code for the given device
2292 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2294 ALCenum errorCode;
2296 if(VerifyDevice(device))
2298 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2299 ALCdevice_DecRef(device);
2301 else
2302 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2304 return errorCode;
2308 /* alcSuspendContext
2310 * Not functional
2312 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2316 /* alcProcessContext
2318 * Not functional
2320 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2325 /* alcGetString
2327 * Returns information about the device, and error strings
2329 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2331 const ALCchar *value = NULL;
2333 switch(param)
2335 case ALC_NO_ERROR:
2336 value = alcNoError;
2337 break;
2339 case ALC_INVALID_ENUM:
2340 value = alcErrInvalidEnum;
2341 break;
2343 case ALC_INVALID_VALUE:
2344 value = alcErrInvalidValue;
2345 break;
2347 case ALC_INVALID_DEVICE:
2348 value = alcErrInvalidDevice;
2349 break;
2351 case ALC_INVALID_CONTEXT:
2352 value = alcErrInvalidContext;
2353 break;
2355 case ALC_OUT_OF_MEMORY:
2356 value = alcErrOutOfMemory;
2357 break;
2359 case ALC_DEVICE_SPECIFIER:
2360 value = alcDefaultName;
2361 break;
2363 case ALC_ALL_DEVICES_SPECIFIER:
2364 if(VerifyDevice(Device))
2366 value = al_string_get_cstr(Device->DeviceName);
2367 ALCdevice_DecRef(Device);
2369 else
2371 ProbeAllDevicesList();
2372 value = al_string_get_cstr(alcAllDevicesList);
2374 break;
2376 case ALC_CAPTURE_DEVICE_SPECIFIER:
2377 if(VerifyDevice(Device))
2379 value = al_string_get_cstr(Device->DeviceName);
2380 ALCdevice_DecRef(Device);
2382 else
2384 ProbeCaptureDeviceList();
2385 value = al_string_get_cstr(alcCaptureDeviceList);
2387 break;
2389 /* Default devices are always first in the list */
2390 case ALC_DEFAULT_DEVICE_SPECIFIER:
2391 value = alcDefaultName;
2392 break;
2394 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2395 if(al_string_empty(alcAllDevicesList))
2396 ProbeAllDevicesList();
2398 Device = VerifyDevice(Device);
2400 free(alcDefaultAllDevicesSpecifier);
2401 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2402 if(!alcDefaultAllDevicesSpecifier)
2403 alcSetError(Device, ALC_OUT_OF_MEMORY);
2405 value = alcDefaultAllDevicesSpecifier;
2406 if(Device) ALCdevice_DecRef(Device);
2407 break;
2409 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2410 if(al_string_empty(alcCaptureDeviceList))
2411 ProbeCaptureDeviceList();
2413 Device = VerifyDevice(Device);
2415 free(alcCaptureDefaultDeviceSpecifier);
2416 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2417 if(!alcCaptureDefaultDeviceSpecifier)
2418 alcSetError(Device, ALC_OUT_OF_MEMORY);
2420 value = alcCaptureDefaultDeviceSpecifier;
2421 if(Device) ALCdevice_DecRef(Device);
2422 break;
2424 case ALC_EXTENSIONS:
2425 if(!VerifyDevice(Device))
2426 value = alcNoDeviceExtList;
2427 else
2429 value = alcExtensionList;
2430 ALCdevice_DecRef(Device);
2432 break;
2434 default:
2435 Device = VerifyDevice(Device);
2436 alcSetError(Device, ALC_INVALID_ENUM);
2437 if(Device) ALCdevice_DecRef(Device);
2438 break;
2441 return value;
2445 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2447 ALCsizei i;
2449 if(size <= 0 || values == NULL)
2451 alcSetError(device, ALC_INVALID_VALUE);
2452 return 0;
2455 if(!device)
2457 switch(param)
2459 case ALC_MAJOR_VERSION:
2460 values[0] = alcMajorVersion;
2461 return 1;
2462 case ALC_MINOR_VERSION:
2463 values[0] = alcMinorVersion;
2464 return 1;
2466 case ALC_ATTRIBUTES_SIZE:
2467 case ALC_ALL_ATTRIBUTES:
2468 case ALC_FREQUENCY:
2469 case ALC_REFRESH:
2470 case ALC_SYNC:
2471 case ALC_MONO_SOURCES:
2472 case ALC_STEREO_SOURCES:
2473 case ALC_CAPTURE_SAMPLES:
2474 case ALC_FORMAT_CHANNELS_SOFT:
2475 case ALC_FORMAT_TYPE_SOFT:
2476 alcSetError(NULL, ALC_INVALID_DEVICE);
2477 return 0;
2479 default:
2480 alcSetError(NULL, ALC_INVALID_ENUM);
2481 return 0;
2483 return 0;
2486 if(device->Type == Capture)
2488 switch(param)
2490 case ALC_CAPTURE_SAMPLES:
2491 ALCdevice_Lock(device);
2492 values[0] = V0(device->Backend,availableSamples)();
2493 ALCdevice_Unlock(device);
2494 return 1;
2496 case ALC_CONNECTED:
2497 values[0] = device->Connected;
2498 return 1;
2500 default:
2501 alcSetError(device, ALC_INVALID_ENUM);
2502 return 0;
2504 return 0;
2507 /* render device */
2508 switch(param)
2510 case ALC_MAJOR_VERSION:
2511 values[0] = alcMajorVersion;
2512 return 1;
2514 case ALC_MINOR_VERSION:
2515 values[0] = alcMinorVersion;
2516 return 1;
2518 case ALC_EFX_MAJOR_VERSION:
2519 values[0] = alcEFXMajorVersion;
2520 return 1;
2522 case ALC_EFX_MINOR_VERSION:
2523 values[0] = alcEFXMinorVersion;
2524 return 1;
2526 case ALC_ATTRIBUTES_SIZE:
2527 values[0] = 15;
2528 return 1;
2530 case ALC_ALL_ATTRIBUTES:
2531 if(size < 15)
2533 alcSetError(device, ALC_INVALID_VALUE);
2534 return 0;
2537 i = 0;
2538 values[i++] = ALC_FREQUENCY;
2539 values[i++] = device->Frequency;
2541 if(device->Type != Loopback)
2543 values[i++] = ALC_REFRESH;
2544 values[i++] = device->Frequency / device->UpdateSize;
2546 values[i++] = ALC_SYNC;
2547 values[i++] = ALC_FALSE;
2549 else
2551 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2552 values[i++] = device->FmtChans;
2554 values[i++] = ALC_FORMAT_TYPE_SOFT;
2555 values[i++] = device->FmtType;
2558 values[i++] = ALC_MONO_SOURCES;
2559 values[i++] = device->NumMonoSources;
2561 values[i++] = ALC_STEREO_SOURCES;
2562 values[i++] = device->NumStereoSources;
2564 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2565 values[i++] = device->NumAuxSends;
2567 values[i++] = ALC_HRTF_SOFT;
2568 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2570 values[i++] = 0;
2571 return i;
2573 case ALC_FREQUENCY:
2574 values[0] = device->Frequency;
2575 return 1;
2577 case ALC_REFRESH:
2578 if(device->Type == Loopback)
2580 alcSetError(device, ALC_INVALID_DEVICE);
2581 return 0;
2583 values[0] = device->Frequency / device->UpdateSize;
2584 return 1;
2586 case ALC_SYNC:
2587 if(device->Type == Loopback)
2589 alcSetError(device, ALC_INVALID_DEVICE);
2590 return 0;
2592 values[0] = ALC_FALSE;
2593 return 1;
2595 case ALC_FORMAT_CHANNELS_SOFT:
2596 if(device->Type != Loopback)
2598 alcSetError(device, ALC_INVALID_DEVICE);
2599 return 0;
2601 values[0] = device->FmtChans;
2602 return 1;
2604 case ALC_FORMAT_TYPE_SOFT:
2605 if(device->Type != Loopback)
2607 alcSetError(device, ALC_INVALID_DEVICE);
2608 return 0;
2610 values[0] = device->FmtType;
2611 return 1;
2613 case ALC_MONO_SOURCES:
2614 values[0] = device->NumMonoSources;
2615 return 1;
2617 case ALC_STEREO_SOURCES:
2618 values[0] = device->NumStereoSources;
2619 return 1;
2621 case ALC_MAX_AUXILIARY_SENDS:
2622 values[0] = device->NumAuxSends;
2623 return 1;
2625 case ALC_CONNECTED:
2626 values[0] = device->Connected;
2627 return 1;
2629 case ALC_HRTF_SOFT:
2630 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2631 return 1;
2633 default:
2634 alcSetError(device, ALC_INVALID_ENUM);
2635 return 0;
2637 return 0;
2640 /* alcGetIntegerv
2642 * Returns information about the device and the version of OpenAL
2644 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2646 device = VerifyDevice(device);
2647 if(size <= 0 || values == NULL)
2648 alcSetError(device, ALC_INVALID_VALUE);
2649 else
2650 GetIntegerv(device, param, size, values);
2651 if(device) ALCdevice_DecRef(device);
2654 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2656 ALCint *ivals;
2657 ALsizei i;
2659 device = VerifyDevice(device);
2660 if(size <= 0 || values == NULL)
2661 alcSetError(device, ALC_INVALID_VALUE);
2662 else if(!device || device->Type == Capture)
2664 ivals = malloc(size * sizeof(ALCint));
2665 size = GetIntegerv(device, pname, size, ivals);
2666 for(i = 0;i < size;i++)
2667 values[i] = ivals[i];
2668 free(ivals);
2670 else /* render device */
2672 switch(pname)
2674 case ALC_ATTRIBUTES_SIZE:
2675 *values = 17;
2676 break;
2678 case ALC_ALL_ATTRIBUTES:
2679 if(size < 17)
2680 alcSetError(device, ALC_INVALID_VALUE);
2681 else
2683 int i = 0;
2685 V0(device->Backend,lock)();
2686 values[i++] = ALC_FREQUENCY;
2687 values[i++] = device->Frequency;
2689 if(device->Type != Loopback)
2691 values[i++] = ALC_REFRESH;
2692 values[i++] = device->Frequency / device->UpdateSize;
2694 values[i++] = ALC_SYNC;
2695 values[i++] = ALC_FALSE;
2697 else
2699 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2700 values[i++] = device->FmtChans;
2702 values[i++] = ALC_FORMAT_TYPE_SOFT;
2703 values[i++] = device->FmtType;
2706 values[i++] = ALC_MONO_SOURCES;
2707 values[i++] = device->NumMonoSources;
2709 values[i++] = ALC_STEREO_SOURCES;
2710 values[i++] = device->NumStereoSources;
2712 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2713 values[i++] = device->NumAuxSends;
2715 values[i++] = ALC_HRTF_SOFT;
2716 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2718 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2719 values[i++] = device->ClockBase +
2720 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2722 values[i++] = 0;
2723 V0(device->Backend,unlock)();
2725 break;
2727 case ALC_DEVICE_CLOCK_SOFT:
2728 V0(device->Backend,lock)();
2729 *values = device->ClockBase +
2730 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2731 V0(device->Backend,unlock)();
2732 break;
2734 default:
2735 ivals = malloc(size * sizeof(ALCint));
2736 size = GetIntegerv(device, pname, size, ivals);
2737 for(i = 0;i < size;i++)
2738 values[i] = ivals[i];
2739 free(ivals);
2740 break;
2743 if(device)
2744 ALCdevice_DecRef(device);
2748 /* alcIsExtensionPresent
2750 * Determines if there is support for a particular extension
2752 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2754 ALCboolean bResult = ALC_FALSE;
2756 device = VerifyDevice(device);
2758 if(!extName)
2759 alcSetError(device, ALC_INVALID_VALUE);
2760 else
2762 size_t len = strlen(extName);
2763 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2764 while(ptr && *ptr)
2766 if(strncasecmp(ptr, extName, len) == 0 &&
2767 (ptr[len] == '\0' || isspace(ptr[len])))
2769 bResult = ALC_TRUE;
2770 break;
2772 if((ptr=strchr(ptr, ' ')) != NULL)
2774 do {
2775 ++ptr;
2776 } while(isspace(*ptr));
2780 if(device)
2781 ALCdevice_DecRef(device);
2782 return bResult;
2786 /* alcGetProcAddress
2788 * Retrieves the function address for a particular extension function
2790 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2792 ALCvoid *ptr = NULL;
2794 if(!funcName)
2796 device = VerifyDevice(device);
2797 alcSetError(device, ALC_INVALID_VALUE);
2798 if(device) ALCdevice_DecRef(device);
2800 else
2802 ALsizei i = 0;
2803 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2804 i++;
2805 ptr = alcFunctions[i].address;
2808 return ptr;
2812 /* alcGetEnumValue
2814 * Get the value for a particular ALC enumeration name
2816 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2818 ALCenum val = 0;
2820 if(!enumName)
2822 device = VerifyDevice(device);
2823 alcSetError(device, ALC_INVALID_VALUE);
2824 if(device) ALCdevice_DecRef(device);
2826 else
2828 ALsizei i = 0;
2829 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2830 i++;
2831 val = enumeration[i].value;
2834 return val;
2838 /* alcCreateContext
2840 * Create and attach a context to the given device.
2842 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2844 ALCcontext *ALContext;
2845 ALCenum err;
2847 LockLists();
2848 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2850 UnlockLists();
2851 alcSetError(device, ALC_INVALID_DEVICE);
2852 if(device) ALCdevice_DecRef(device);
2853 return NULL;
2856 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
2858 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2860 UnlockLists();
2861 alcSetError(device, err);
2862 if(err == ALC_INVALID_DEVICE)
2864 ALCdevice_Lock(device);
2865 aluHandleDisconnect(device);
2866 ALCdevice_Unlock(device);
2868 ALCdevice_DecRef(device);
2869 return NULL;
2872 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
2873 if(ALContext)
2875 InitRef(&ALContext->ref, 1);
2876 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2878 VECTOR_INIT(ALContext->ActiveAuxSlots);
2880 ALContext->VoiceCount = 0;
2881 ALContext->MaxVoices = 256;
2882 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
2884 if(!ALContext || !ALContext->Voices)
2886 if(!ATOMIC_LOAD(&device->ContextList))
2888 V0(device->Backend,stop)();
2889 device->Flags &= ~DEVICE_RUNNING;
2891 UnlockLists();
2893 if(ALContext)
2895 al_free(ALContext->Voices);
2896 ALContext->Voices = NULL;
2898 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2900 al_free(ALContext);
2901 ALContext = NULL;
2904 alcSetError(device, ALC_OUT_OF_MEMORY);
2905 ALCdevice_DecRef(device);
2906 return NULL;
2909 ALContext->Device = device;
2910 ALCdevice_IncRef(device);
2911 InitContext(ALContext);
2914 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
2915 do {
2916 ALContext->next = head;
2917 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
2919 UnlockLists();
2921 ALCdevice_DecRef(device);
2923 TRACE("Created context %p\n", ALContext);
2924 return ALContext;
2927 /* alcDestroyContext
2929 * Remove a context from its device
2931 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2933 ALCdevice *Device;
2935 LockLists();
2936 /* alcGetContextsDevice sets an error for invalid contexts */
2937 Device = alcGetContextsDevice(context);
2938 if(Device)
2940 ReleaseContext(context, Device);
2941 if(!ATOMIC_LOAD(&Device->ContextList))
2943 V0(Device->Backend,stop)();
2944 Device->Flags &= ~DEVICE_RUNNING;
2947 UnlockLists();
2951 /* alcGetCurrentContext
2953 * Returns the currently active context on the calling thread
2955 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2957 ALCcontext *Context = altss_get(LocalContext);
2958 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
2959 return Context;
2962 /* alcGetThreadContext
2964 * Returns the currently active thread-local context
2966 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2968 return altss_get(LocalContext);
2972 /* alcMakeContextCurrent
2974 * Makes the given context the active process-wide context, and removes the
2975 * thread-local context for the calling thread.
2977 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2979 /* context must be valid or NULL */
2980 if(context && !(context=VerifyContext(context)))
2982 alcSetError(NULL, ALC_INVALID_CONTEXT);
2983 return ALC_FALSE;
2985 /* context's reference count is already incremented */
2986 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
2987 if(context) ALCcontext_DecRef(context);
2989 if((context=altss_get(LocalContext)) != NULL)
2991 altss_set(LocalContext, NULL);
2992 ALCcontext_DecRef(context);
2995 return ALC_TRUE;
2998 /* alcSetThreadContext
3000 * Makes the given context the active context for the current thread
3002 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3004 ALCcontext *old;
3006 /* context must be valid or NULL */
3007 if(context && !(context=VerifyContext(context)))
3009 alcSetError(NULL, ALC_INVALID_CONTEXT);
3010 return ALC_FALSE;
3012 /* context's reference count is already incremented */
3013 old = altss_get(LocalContext);
3014 altss_set(LocalContext, context);
3015 if(old) ALCcontext_DecRef(old);
3017 return ALC_TRUE;
3021 /* alcGetContextsDevice
3023 * Returns the device that a particular context is attached to
3025 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3027 ALCdevice *Device;
3029 if(!(Context=VerifyContext(Context)))
3031 alcSetError(NULL, ALC_INVALID_CONTEXT);
3032 return NULL;
3034 Device = Context->Device;
3035 ALCcontext_DecRef(Context);
3037 return Device;
3041 /* alcOpenDevice
3043 * Opens the named device.
3045 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3047 const ALCchar *fmt;
3048 ALCdevice *device;
3049 ALCenum err;
3051 DO_INITCONFIG();
3053 if(!PlaybackBackend.name)
3055 alcSetError(NULL, ALC_INVALID_VALUE);
3056 return NULL;
3059 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3060 deviceName = NULL;
3062 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3063 if(!device)
3065 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3066 return NULL;
3069 //Validate device
3070 InitRef(&device->ref, 1);
3071 device->Connected = ALC_TRUE;
3072 device->Type = Playback;
3073 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3075 device->Flags = 0;
3076 device->Bs2b = NULL;
3077 device->Bs2bLevel = 0;
3078 AL_STRING_INIT(device->DeviceName);
3080 ATOMIC_INIT(&device->ContextList, NULL);
3082 device->ClockBase = 0;
3083 device->SamplesDone = 0;
3085 device->MaxNoOfSources = 256;
3086 device->AuxiliaryEffectSlotMax = 4;
3087 device->NumAuxSends = MAX_SENDS;
3089 InitUIntMap(&device->BufferMap, ~0);
3090 InitUIntMap(&device->EffectMap, ~0);
3091 InitUIntMap(&device->FilterMap, ~0);
3092 InitUIntMap(&device->SfontMap, ~0);
3093 InitUIntMap(&device->PresetMap, ~0);
3094 InitUIntMap(&device->FontsoundMap, ~0);
3096 //Set output format
3097 device->FmtChans = DevFmtChannelsDefault;
3098 device->FmtType = DevFmtTypeDefault;
3099 device->Frequency = DEFAULT_OUTPUT_RATE;
3100 device->NumUpdates = 4;
3101 device->UpdateSize = 1024;
3103 if(!PlaybackBackend.getFactory)
3104 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3105 ALCbackend_Playback);
3106 else
3108 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3109 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3111 if(!device->Backend)
3113 al_free(device);
3114 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3115 return NULL;
3119 if(ConfigValueStr(NULL, "channels", &fmt))
3121 static const struct {
3122 const char name[16];
3123 enum DevFmtChannels chans;
3124 } chanlist[] = {
3125 { "mono", DevFmtMono },
3126 { "stereo", DevFmtStereo },
3127 { "quad", DevFmtQuad },
3128 { "surround51", DevFmtX51 },
3129 { "surround61", DevFmtX61 },
3130 { "surround71", DevFmtX71 },
3132 size_t i;
3134 for(i = 0;i < COUNTOF(chanlist);i++)
3136 if(strcasecmp(chanlist[i].name, fmt) == 0)
3138 device->FmtChans = chanlist[i].chans;
3139 device->Flags |= DEVICE_CHANNELS_REQUEST;
3140 break;
3143 if(i == COUNTOF(chanlist))
3144 ERR("Unsupported channels: %s\n", fmt);
3146 if(ConfigValueStr(NULL, "sample-type", &fmt))
3148 static const struct {
3149 const char name[16];
3150 enum DevFmtType type;
3151 } typelist[] = {
3152 { "int8", DevFmtByte },
3153 { "uint8", DevFmtUByte },
3154 { "int16", DevFmtShort },
3155 { "uint16", DevFmtUShort },
3156 { "int32", DevFmtInt },
3157 { "uint32", DevFmtUInt },
3158 { "float32", DevFmtFloat },
3160 size_t i;
3162 for(i = 0;i < COUNTOF(typelist);i++)
3164 if(strcasecmp(typelist[i].name, fmt) == 0)
3166 device->FmtType = typelist[i].type;
3167 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3168 break;
3171 if(i == COUNTOF(typelist))
3172 ERR("Unsupported sample-type: %s\n", fmt);
3174 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3175 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3176 ConfigValueStr(NULL, "format", &fmt))
3178 static const struct {
3179 const char name[32];
3180 enum DevFmtChannels channels;
3181 enum DevFmtType type;
3182 } formats[] = {
3183 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3184 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3185 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3186 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3187 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3188 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3190 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3191 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3192 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3193 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3194 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3195 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3197 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3198 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3199 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3200 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3201 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3202 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3204 size_t i;
3206 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3207 for(i = 0;i < COUNTOF(formats);i++)
3209 if(strcasecmp(fmt, formats[i].name) == 0)
3211 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3212 device->FmtChans = formats[i].channels;
3213 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3214 device->FmtType = formats[i].type;
3215 device->Flags |= DEVICE_FORMAT_REQUEST;
3216 break;
3219 if(i == COUNTOF(formats))
3220 ERR("Unsupported format: %s\n", fmt);
3222 #undef DEVICE_FORMAT_REQUEST
3224 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3226 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3227 if(device->Frequency < MIN_OUTPUT_RATE)
3228 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3229 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3232 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3233 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3235 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3236 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3237 if((CPUCapFlags&CPU_CAP_SSE))
3238 device->UpdateSize = (device->UpdateSize+3)&~3;
3240 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3241 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3243 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3244 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3246 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3247 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3249 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3251 device->NumStereoSources = 1;
3252 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3254 device->Synth = SynthCreate(device);
3255 if(!device->Synth)
3257 DELETE_OBJ(device->Backend);
3258 al_free(device);
3259 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3260 return NULL;
3263 // Find a playback device to open
3264 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3266 DELETE_OBJ(device->Synth);
3267 DELETE_OBJ(device->Backend);
3268 al_free(device);
3269 alcSetError(NULL, err);
3270 return NULL;
3273 if(DefaultEffect.type != AL_EFFECT_NULL)
3275 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3276 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3278 device->DefaultSlot = NULL;
3279 ERR("Failed to initialize the default effect slot\n");
3281 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3283 ALeffectState *state = device->DefaultSlot->EffectState;
3284 device->DefaultSlot = NULL;
3285 DELETE_OBJ(state);
3286 ERR("Failed to initialize the default effect\n");
3291 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3292 do {
3293 device->next = head;
3294 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3297 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3298 return device;
3301 /* alcCloseDevice
3303 * Closes the given device.
3305 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3307 ALCdevice *list, *origdev, *nextdev;
3308 ALCcontext *ctx;
3310 LockLists();
3311 list = ATOMIC_LOAD(&DeviceList);
3312 do {
3313 if(list == device)
3314 break;
3315 } while((list=list->next) != NULL);
3316 if(!list || list->Type == Capture)
3318 alcSetError(list, ALC_INVALID_DEVICE);
3319 UnlockLists();
3320 return ALC_FALSE;
3323 origdev = device;
3324 nextdev = device->next;
3325 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3327 do {
3328 list = origdev;
3329 origdev = device;
3330 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3332 UnlockLists();
3334 ctx = ATOMIC_LOAD(&device->ContextList);
3335 while(ctx != NULL)
3337 ALCcontext *next = ctx->next;
3338 WARN("Releasing context %p\n", ctx);
3339 ReleaseContext(ctx, device);
3340 ctx = next;
3342 if((device->Flags&DEVICE_RUNNING))
3343 V0(device->Backend,stop)();
3344 device->Flags &= ~DEVICE_RUNNING;
3346 ALCdevice_DecRef(device);
3348 return ALC_TRUE;
3352 /************************************************
3353 * ALC capture functions
3354 ************************************************/
3355 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3357 ALCdevice *device = NULL;
3358 ALCenum err;
3360 DO_INITCONFIG();
3362 if(!CaptureBackend.name)
3364 alcSetError(NULL, ALC_INVALID_VALUE);
3365 return NULL;
3368 if(samples <= 0)
3370 alcSetError(NULL, ALC_INVALID_VALUE);
3371 return NULL;
3374 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3375 deviceName = NULL;
3377 device = al_calloc(16, sizeof(ALCdevice));
3378 if(!device)
3380 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3381 return NULL;
3384 //Validate device
3385 InitRef(&device->ref, 1);
3386 device->Connected = ALC_TRUE;
3387 device->Type = Capture;
3389 AL_STRING_INIT(device->DeviceName);
3391 InitUIntMap(&device->BufferMap, ~0);
3392 InitUIntMap(&device->EffectMap, ~0);
3393 InitUIntMap(&device->FilterMap, ~0);
3394 InitUIntMap(&device->SfontMap, ~0);
3395 InitUIntMap(&device->PresetMap, ~0);
3396 InitUIntMap(&device->FontsoundMap, ~0);
3398 if(!CaptureBackend.getFactory)
3399 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3400 ALCbackend_Capture);
3401 else
3403 ALCbackendFactory *factory = CaptureBackend.getFactory();
3404 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3406 if(!device->Backend)
3408 al_free(device);
3409 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3410 return NULL;
3413 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3414 device->Frequency = frequency;
3416 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3417 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3419 al_free(device);
3420 alcSetError(NULL, ALC_INVALID_ENUM);
3421 return NULL;
3424 device->UpdateSize = samples;
3425 device->NumUpdates = 1;
3427 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3429 al_free(device);
3430 alcSetError(NULL, err);
3431 return NULL;
3435 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3436 do {
3437 device->next = head;
3438 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3441 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3442 return device;
3445 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3447 ALCdevice *list, *next, *nextdev;
3449 LockLists();
3450 list = ATOMIC_LOAD(&DeviceList);
3451 do {
3452 if(list == device)
3453 break;
3454 } while((list=list->next) != NULL);
3455 if(!list || list->Type != Capture)
3457 alcSetError(list, ALC_INVALID_DEVICE);
3458 UnlockLists();
3459 return ALC_FALSE;
3462 next = device;
3463 nextdev = device->next;
3464 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3466 do {
3467 list = next;
3468 next = device;
3469 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3471 UnlockLists();
3473 ALCdevice_DecRef(device);
3475 return ALC_TRUE;
3478 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3480 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3481 alcSetError(device, ALC_INVALID_DEVICE);
3482 else
3484 ALCdevice_Lock(device);
3485 if(device->Connected)
3487 if(!(device->Flags&DEVICE_RUNNING))
3488 V0(device->Backend,start)();
3489 device->Flags |= DEVICE_RUNNING;
3491 ALCdevice_Unlock(device);
3494 if(device) ALCdevice_DecRef(device);
3497 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3499 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3500 alcSetError(device, ALC_INVALID_DEVICE);
3501 else
3503 ALCdevice_Lock(device);
3504 if((device->Flags&DEVICE_RUNNING))
3505 V0(device->Backend,stop)();
3506 device->Flags &= ~DEVICE_RUNNING;
3507 ALCdevice_Unlock(device);
3510 if(device) ALCdevice_DecRef(device);
3513 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3515 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3516 alcSetError(device, ALC_INVALID_DEVICE);
3517 else
3519 ALCenum err = ALC_INVALID_VALUE;
3521 ALCdevice_Lock(device);
3522 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3523 err = V(device->Backend,captureSamples)(buffer, samples);
3524 ALCdevice_Unlock(device);
3526 if(err != ALC_NO_ERROR)
3527 alcSetError(device, err);
3529 if(device) ALCdevice_DecRef(device);
3533 /************************************************
3534 * ALC loopback functions
3535 ************************************************/
3537 /* alcLoopbackOpenDeviceSOFT
3539 * Open a loopback device, for manual rendering.
3541 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3543 ALCbackendFactory *factory;
3544 ALCdevice *device;
3546 DO_INITCONFIG();
3548 /* Make sure the device name, if specified, is us. */
3549 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3551 alcSetError(NULL, ALC_INVALID_VALUE);
3552 return NULL;
3555 device = al_calloc(16, sizeof(ALCdevice));
3556 if(!device)
3558 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3559 return NULL;
3562 //Validate device
3563 InitRef(&device->ref, 1);
3564 device->Connected = ALC_TRUE;
3565 device->Type = Loopback;
3566 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3568 device->Flags = 0;
3569 device->Bs2b = NULL;
3570 device->Bs2bLevel = 0;
3571 AL_STRING_INIT(device->DeviceName);
3573 ATOMIC_INIT(&device->ContextList, NULL);
3575 device->ClockBase = 0;
3576 device->SamplesDone = 0;
3578 device->MaxNoOfSources = 256;
3579 device->AuxiliaryEffectSlotMax = 4;
3580 device->NumAuxSends = MAX_SENDS;
3582 InitUIntMap(&device->BufferMap, ~0);
3583 InitUIntMap(&device->EffectMap, ~0);
3584 InitUIntMap(&device->FilterMap, ~0);
3585 InitUIntMap(&device->SfontMap, ~0);
3586 InitUIntMap(&device->PresetMap, ~0);
3587 InitUIntMap(&device->FontsoundMap, ~0);
3589 factory = ALCloopbackFactory_getFactory();
3590 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3591 if(!device->Backend)
3593 al_free(device);
3594 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3595 return NULL;
3598 //Set output format
3599 device->NumUpdates = 0;
3600 device->UpdateSize = 0;
3602 device->Frequency = DEFAULT_OUTPUT_RATE;
3603 device->FmtChans = DevFmtChannelsDefault;
3604 device->FmtType = DevFmtTypeDefault;
3606 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3607 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3609 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3610 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3612 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3613 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3615 device->NumStereoSources = 1;
3616 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3618 device->Synth = SynthCreate(device);
3619 if(!device->Synth)
3621 DELETE_OBJ(device->Backend);
3622 al_free(device);
3623 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3624 return NULL;
3627 // Open the "backend"
3628 V(device->Backend,open)("Loopback");
3631 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3632 do {
3633 device->next = head;
3634 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3637 TRACE("Created device %p\n", device);
3638 return device;
3641 /* alcIsRenderFormatSupportedSOFT
3643 * Determines if the loopback device supports the given format for rendering.
3645 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3647 ALCboolean ret = ALC_FALSE;
3649 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3650 alcSetError(device, ALC_INVALID_DEVICE);
3651 else if(freq <= 0)
3652 alcSetError(device, ALC_INVALID_VALUE);
3653 else
3655 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3656 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3657 freq >= MIN_OUTPUT_RATE)
3658 ret = ALC_TRUE;
3660 if(device) ALCdevice_DecRef(device);
3662 return ret;
3665 /* alcRenderSamplesSOFT
3667 * Renders some samples into a buffer, using the format last set by the
3668 * attributes given to alcCreateContext.
3670 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3672 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3673 alcSetError(device, ALC_INVALID_DEVICE);
3674 else if(samples < 0 || (samples > 0 && buffer == NULL))
3675 alcSetError(device, ALC_INVALID_VALUE);
3676 else
3677 aluMixData(device, buffer, samples);
3678 if(device) ALCdevice_DecRef(device);
3682 /************************************************
3683 * ALC DSP pause/resume functions
3684 ************************************************/
3686 /* alcDevicePauseSOFT
3688 * Pause the DSP to stop audio processing.
3690 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3692 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3693 alcSetError(device, ALC_INVALID_DEVICE);
3694 else
3696 LockLists();
3697 if((device->Flags&DEVICE_RUNNING))
3698 V0(device->Backend,stop)();
3699 device->Flags &= ~DEVICE_RUNNING;
3700 device->Flags |= DEVICE_PAUSED;
3701 UnlockLists();
3703 if(device) ALCdevice_DecRef(device);
3706 /* alcDeviceResumeSOFT
3708 * Resume the DSP to restart audio processing.
3710 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3712 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3713 alcSetError(device, ALC_INVALID_DEVICE);
3714 else
3716 LockLists();
3717 if((device->Flags&DEVICE_PAUSED))
3719 device->Flags &= ~DEVICE_PAUSED;
3720 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3722 if(V0(device->Backend,start)() != ALC_FALSE)
3723 device->Flags |= DEVICE_RUNNING;
3724 else
3726 alcSetError(device, ALC_INVALID_DEVICE);
3727 ALCdevice_Lock(device);
3728 aluHandleDisconnect(device);
3729 ALCdevice_Unlock(device);
3733 UnlockLists();
3735 if(device) ALCdevice_DecRef(device);