Add a config option to disable use of CPU extensions
[openal-soft/openal-hmr.git] / Alc / ALc.c
blobe664d25a14c63c052484c9ff92baa3fa030f1818
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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 "AL/al.h"
33 #include "AL/alc.h"
34 #include "alThunk.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "bs2b.h"
40 #include "alu.h"
43 /************************************************
44 * Backends
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
50 #endif
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_COREAUDIO
55 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_OSS
58 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_SOLARIS
61 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_SNDIO
64 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_MMDEVAPI
67 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_DSOUND
70 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
71 #endif
72 #ifdef HAVE_WINMM
73 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_PORTAUDIO
76 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
77 #endif
78 #ifdef HAVE_OPENSL
79 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
80 #endif
82 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
83 #ifdef HAVE_WAVE
84 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
85 #endif
87 { NULL, NULL, NULL, NULL, EmptyFuncs }
89 static struct BackendInfo BackendLoopback = {
90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
92 #undef EmptyFuncs
94 static struct BackendInfo PlaybackBackend;
95 static struct BackendInfo CaptureBackend;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction {
101 const ALCchar *funcName;
102 ALCvoid *address;
103 } ALCfunction;
105 typedef struct ALCenums {
106 const ALCchar *enumName;
107 ALCenum value;
108 } ALCenums;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions[] = {
112 DECL(alcCreateContext),
113 DECL(alcMakeContextCurrent),
114 DECL(alcProcessContext),
115 DECL(alcSuspendContext),
116 DECL(alcDestroyContext),
117 DECL(alcGetCurrentContext),
118 DECL(alcGetContextsDevice),
119 DECL(alcOpenDevice),
120 DECL(alcCloseDevice),
121 DECL(alcGetError),
122 DECL(alcIsExtensionPresent),
123 DECL(alcGetProcAddress),
124 DECL(alcGetEnumValue),
125 DECL(alcGetString),
126 DECL(alcGetIntegerv),
127 DECL(alcCaptureOpenDevice),
128 DECL(alcCaptureCloseDevice),
129 DECL(alcCaptureStart),
130 DECL(alcCaptureStop),
131 DECL(alcCaptureSamples),
133 DECL(alcSetThreadContext),
134 DECL(alcGetThreadContext),
136 DECL(alcLoopbackOpenDeviceSOFT),
137 DECL(alcIsRenderFormatSupportedSOFT),
138 DECL(alcRenderSamplesSOFT),
140 DECL(alEnable),
141 DECL(alDisable),
142 DECL(alIsEnabled),
143 DECL(alGetString),
144 DECL(alGetBooleanv),
145 DECL(alGetIntegerv),
146 DECL(alGetFloatv),
147 DECL(alGetDoublev),
148 DECL(alGetBoolean),
149 DECL(alGetInteger),
150 DECL(alGetFloat),
151 DECL(alGetDouble),
152 DECL(alGetError),
153 DECL(alIsExtensionPresent),
154 DECL(alGetProcAddress),
155 DECL(alGetEnumValue),
156 DECL(alListenerf),
157 DECL(alListener3f),
158 DECL(alListenerfv),
159 DECL(alListeneri),
160 DECL(alListener3i),
161 DECL(alListeneriv),
162 DECL(alGetListenerf),
163 DECL(alGetListener3f),
164 DECL(alGetListenerfv),
165 DECL(alGetListeneri),
166 DECL(alGetListener3i),
167 DECL(alGetListeneriv),
168 DECL(alGenSources),
169 DECL(alDeleteSources),
170 DECL(alIsSource),
171 DECL(alSourcef),
172 DECL(alSource3f),
173 DECL(alSourcefv),
174 DECL(alSourcei),
175 DECL(alSource3i),
176 DECL(alSourceiv),
177 DECL(alGetSourcef),
178 DECL(alGetSource3f),
179 DECL(alGetSourcefv),
180 DECL(alGetSourcei),
181 DECL(alGetSource3i),
182 DECL(alGetSourceiv),
183 DECL(alSourcePlayv),
184 DECL(alSourceStopv),
185 DECL(alSourceRewindv),
186 DECL(alSourcePausev),
187 DECL(alSourcePlay),
188 DECL(alSourceStop),
189 DECL(alSourceRewind),
190 DECL(alSourcePause),
191 DECL(alSourceQueueBuffers),
192 DECL(alSourceUnqueueBuffers),
193 DECL(alGenBuffers),
194 DECL(alDeleteBuffers),
195 DECL(alIsBuffer),
196 DECL(alBufferData),
197 DECL(alBufferf),
198 DECL(alBuffer3f),
199 DECL(alBufferfv),
200 DECL(alBufferi),
201 DECL(alBuffer3i),
202 DECL(alBufferiv),
203 DECL(alGetBufferf),
204 DECL(alGetBuffer3f),
205 DECL(alGetBufferfv),
206 DECL(alGetBufferi),
207 DECL(alGetBuffer3i),
208 DECL(alGetBufferiv),
209 DECL(alDopplerFactor),
210 DECL(alDopplerVelocity),
211 DECL(alSpeedOfSound),
212 DECL(alDistanceModel),
214 DECL(alGenFilters),
215 DECL(alDeleteFilters),
216 DECL(alIsFilter),
217 DECL(alFilteri),
218 DECL(alFilteriv),
219 DECL(alFilterf),
220 DECL(alFilterfv),
221 DECL(alGetFilteri),
222 DECL(alGetFilteriv),
223 DECL(alGetFilterf),
224 DECL(alGetFilterfv),
225 DECL(alGenEffects),
226 DECL(alDeleteEffects),
227 DECL(alIsEffect),
228 DECL(alEffecti),
229 DECL(alEffectiv),
230 DECL(alEffectf),
231 DECL(alEffectfv),
232 DECL(alGetEffecti),
233 DECL(alGetEffectiv),
234 DECL(alGetEffectf),
235 DECL(alGetEffectfv),
236 DECL(alGenAuxiliaryEffectSlots),
237 DECL(alDeleteAuxiliaryEffectSlots),
238 DECL(alIsAuxiliaryEffectSlot),
239 DECL(alAuxiliaryEffectSloti),
240 DECL(alAuxiliaryEffectSlotiv),
241 DECL(alAuxiliaryEffectSlotf),
242 DECL(alAuxiliaryEffectSlotfv),
243 DECL(alGetAuxiliaryEffectSloti),
244 DECL(alGetAuxiliaryEffectSlotiv),
245 DECL(alGetAuxiliaryEffectSlotf),
246 DECL(alGetAuxiliaryEffectSlotfv),
248 DECL(alBufferSubDataSOFT),
250 DECL(alBufferSamplesSOFT),
251 DECL(alBufferSubSamplesSOFT),
252 DECL(alGetBufferSamplesSOFT),
253 DECL(alIsBufferFormatSupportedSOFT),
255 DECL(alDeferUpdatesSOFT),
256 DECL(alProcessUpdatesSOFT),
258 { NULL, NULL }
260 #undef DECL
262 #define DECL(x) { #x, (x) }
263 static const ALCenums enumeration[] = {
264 DECL(ALC_INVALID),
265 DECL(ALC_FALSE),
266 DECL(ALC_TRUE),
268 DECL(ALC_MAJOR_VERSION),
269 DECL(ALC_MINOR_VERSION),
270 DECL(ALC_ATTRIBUTES_SIZE),
271 DECL(ALC_ALL_ATTRIBUTES),
272 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
273 DECL(ALC_DEVICE_SPECIFIER),
274 DECL(ALC_ALL_DEVICES_SPECIFIER),
275 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
276 DECL(ALC_EXTENSIONS),
277 DECL(ALC_FREQUENCY),
278 DECL(ALC_REFRESH),
279 DECL(ALC_SYNC),
280 DECL(ALC_MONO_SOURCES),
281 DECL(ALC_STEREO_SOURCES),
282 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
283 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
284 DECL(ALC_CAPTURE_SAMPLES),
285 DECL(ALC_CONNECTED),
287 DECL(ALC_EFX_MAJOR_VERSION),
288 DECL(ALC_EFX_MINOR_VERSION),
289 DECL(ALC_MAX_AUXILIARY_SENDS),
291 DECL(ALC_FORMAT_CHANNELS_SOFT),
292 DECL(ALC_FORMAT_TYPE_SOFT),
294 DECL(ALC_MONO_SOFT),
295 DECL(ALC_STEREO_SOFT),
296 DECL(ALC_QUAD_SOFT),
297 DECL(ALC_5POINT1_SOFT),
298 DECL(ALC_6POINT1_SOFT),
299 DECL(ALC_7POINT1_SOFT),
301 DECL(ALC_BYTE_SOFT),
302 DECL(ALC_UNSIGNED_BYTE_SOFT),
303 DECL(ALC_SHORT_SOFT),
304 DECL(ALC_UNSIGNED_SHORT_SOFT),
305 DECL(ALC_INT_SOFT),
306 DECL(ALC_UNSIGNED_INT_SOFT),
307 DECL(ALC_FLOAT_SOFT),
309 DECL(ALC_NO_ERROR),
310 DECL(ALC_INVALID_DEVICE),
311 DECL(ALC_INVALID_CONTEXT),
312 DECL(ALC_INVALID_ENUM),
313 DECL(ALC_INVALID_VALUE),
314 DECL(ALC_OUT_OF_MEMORY),
317 DECL(AL_INVALID),
318 DECL(AL_NONE),
319 DECL(AL_FALSE),
320 DECL(AL_TRUE),
322 DECL(AL_SOURCE_RELATIVE),
323 DECL(AL_CONE_INNER_ANGLE),
324 DECL(AL_CONE_OUTER_ANGLE),
325 DECL(AL_PITCH),
326 DECL(AL_POSITION),
327 DECL(AL_DIRECTION),
328 DECL(AL_VELOCITY),
329 DECL(AL_LOOPING),
330 DECL(AL_BUFFER),
331 DECL(AL_GAIN),
332 DECL(AL_MIN_GAIN),
333 DECL(AL_MAX_GAIN),
334 DECL(AL_ORIENTATION),
335 DECL(AL_REFERENCE_DISTANCE),
336 DECL(AL_ROLLOFF_FACTOR),
337 DECL(AL_CONE_OUTER_GAIN),
338 DECL(AL_MAX_DISTANCE),
339 DECL(AL_SEC_OFFSET),
340 DECL(AL_SAMPLE_OFFSET),
341 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
342 DECL(AL_BYTE_OFFSET),
343 DECL(AL_BYTE_RW_OFFSETS_SOFT),
344 DECL(AL_SOURCE_TYPE),
345 DECL(AL_STATIC),
346 DECL(AL_STREAMING),
347 DECL(AL_UNDETERMINED),
348 DECL(AL_METERS_PER_UNIT),
349 DECL(AL_DIRECT_CHANNELS_SOFT),
351 DECL(AL_DIRECT_FILTER),
352 DECL(AL_AUXILIARY_SEND_FILTER),
353 DECL(AL_AIR_ABSORPTION_FACTOR),
354 DECL(AL_ROOM_ROLLOFF_FACTOR),
355 DECL(AL_CONE_OUTER_GAINHF),
356 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
357 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
358 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
360 DECL(AL_SOURCE_STATE),
361 DECL(AL_INITIAL),
362 DECL(AL_PLAYING),
363 DECL(AL_PAUSED),
364 DECL(AL_STOPPED),
366 DECL(AL_BUFFERS_QUEUED),
367 DECL(AL_BUFFERS_PROCESSED),
369 DECL(AL_FORMAT_MONO8),
370 DECL(AL_FORMAT_MONO16),
371 DECL(AL_FORMAT_MONO_FLOAT32),
372 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
373 DECL(AL_FORMAT_STEREO8),
374 DECL(AL_FORMAT_STEREO16),
375 DECL(AL_FORMAT_STEREO_FLOAT32),
376 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
377 DECL(AL_FORMAT_MONO_IMA4),
378 DECL(AL_FORMAT_STEREO_IMA4),
379 DECL(AL_FORMAT_QUAD8_LOKI),
380 DECL(AL_FORMAT_QUAD16_LOKI),
381 DECL(AL_FORMAT_QUAD8),
382 DECL(AL_FORMAT_QUAD16),
383 DECL(AL_FORMAT_QUAD32),
384 DECL(AL_FORMAT_51CHN8),
385 DECL(AL_FORMAT_51CHN16),
386 DECL(AL_FORMAT_51CHN32),
387 DECL(AL_FORMAT_61CHN8),
388 DECL(AL_FORMAT_61CHN16),
389 DECL(AL_FORMAT_61CHN32),
390 DECL(AL_FORMAT_71CHN8),
391 DECL(AL_FORMAT_71CHN16),
392 DECL(AL_FORMAT_71CHN32),
393 DECL(AL_FORMAT_REAR8),
394 DECL(AL_FORMAT_REAR16),
395 DECL(AL_FORMAT_REAR32),
396 DECL(AL_FORMAT_MONO_MULAW),
397 DECL(AL_FORMAT_MONO_MULAW_EXT),
398 DECL(AL_FORMAT_STEREO_MULAW),
399 DECL(AL_FORMAT_STEREO_MULAW_EXT),
400 DECL(AL_FORMAT_QUAD_MULAW),
401 DECL(AL_FORMAT_51CHN_MULAW),
402 DECL(AL_FORMAT_61CHN_MULAW),
403 DECL(AL_FORMAT_71CHN_MULAW),
404 DECL(AL_FORMAT_REAR_MULAW),
405 DECL(AL_FORMAT_MONO_ALAW_EXT),
406 DECL(AL_FORMAT_STEREO_ALAW_EXT),
408 DECL(AL_MONO8_SOFT),
409 DECL(AL_MONO16_SOFT),
410 DECL(AL_MONO32F_SOFT),
411 DECL(AL_STEREO8_SOFT),
412 DECL(AL_STEREO16_SOFT),
413 DECL(AL_STEREO32F_SOFT),
414 DECL(AL_QUAD8_SOFT),
415 DECL(AL_QUAD16_SOFT),
416 DECL(AL_QUAD32F_SOFT),
417 DECL(AL_REAR8_SOFT),
418 DECL(AL_REAR16_SOFT),
419 DECL(AL_REAR32F_SOFT),
420 DECL(AL_5POINT1_8_SOFT),
421 DECL(AL_5POINT1_16_SOFT),
422 DECL(AL_5POINT1_32F_SOFT),
423 DECL(AL_6POINT1_8_SOFT),
424 DECL(AL_6POINT1_16_SOFT),
425 DECL(AL_6POINT1_32F_SOFT),
426 DECL(AL_7POINT1_8_SOFT),
427 DECL(AL_7POINT1_16_SOFT),
428 DECL(AL_7POINT1_32F_SOFT),
430 DECL(AL_MONO_SOFT),
431 DECL(AL_STEREO_SOFT),
432 DECL(AL_QUAD_SOFT),
433 DECL(AL_REAR_SOFT),
434 DECL(AL_5POINT1_SOFT),
435 DECL(AL_6POINT1_SOFT),
436 DECL(AL_7POINT1_SOFT),
438 DECL(AL_BYTE_SOFT),
439 DECL(AL_UNSIGNED_BYTE_SOFT),
440 DECL(AL_SHORT_SOFT),
441 DECL(AL_UNSIGNED_SHORT_SOFT),
442 DECL(AL_INT_SOFT),
443 DECL(AL_UNSIGNED_INT_SOFT),
444 DECL(AL_FLOAT_SOFT),
445 DECL(AL_DOUBLE_SOFT),
446 DECL(AL_BYTE3_SOFT),
447 DECL(AL_UNSIGNED_BYTE3_SOFT),
449 DECL(AL_FREQUENCY),
450 DECL(AL_BITS),
451 DECL(AL_CHANNELS),
452 DECL(AL_SIZE),
453 DECL(AL_INTERNAL_FORMAT_SOFT),
454 DECL(AL_BYTE_LENGTH_SOFT),
455 DECL(AL_SAMPLE_LENGTH_SOFT),
456 DECL(AL_SEC_LENGTH_SOFT),
458 DECL(AL_UNUSED),
459 DECL(AL_PENDING),
460 DECL(AL_PROCESSED),
462 DECL(AL_NO_ERROR),
463 DECL(AL_INVALID_NAME),
464 DECL(AL_INVALID_ENUM),
465 DECL(AL_INVALID_VALUE),
466 DECL(AL_INVALID_OPERATION),
467 DECL(AL_OUT_OF_MEMORY),
469 DECL(AL_VENDOR),
470 DECL(AL_VERSION),
471 DECL(AL_RENDERER),
472 DECL(AL_EXTENSIONS),
474 DECL(AL_DOPPLER_FACTOR),
475 DECL(AL_DOPPLER_VELOCITY),
476 DECL(AL_DISTANCE_MODEL),
477 DECL(AL_SPEED_OF_SOUND),
478 DECL(AL_SOURCE_DISTANCE_MODEL),
479 DECL(AL_DEFERRED_UPDATES_SOFT),
481 DECL(AL_INVERSE_DISTANCE),
482 DECL(AL_INVERSE_DISTANCE_CLAMPED),
483 DECL(AL_LINEAR_DISTANCE),
484 DECL(AL_LINEAR_DISTANCE_CLAMPED),
485 DECL(AL_EXPONENT_DISTANCE),
486 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
488 DECL(AL_FILTER_TYPE),
489 DECL(AL_FILTER_NULL),
490 DECL(AL_FILTER_LOWPASS),
491 #if 0
492 DECL(AL_FILTER_HIGHPASS),
493 DECL(AL_FILTER_BANDPASS),
494 #endif
496 DECL(AL_LOWPASS_GAIN),
497 DECL(AL_LOWPASS_GAINHF),
499 DECL(AL_EFFECT_TYPE),
500 DECL(AL_EFFECT_NULL),
501 DECL(AL_EFFECT_REVERB),
502 DECL(AL_EFFECT_EAXREVERB),
503 #if 0
504 DECL(AL_EFFECT_CHORUS),
505 DECL(AL_EFFECT_DISTORTION),
506 #endif
507 DECL(AL_EFFECT_ECHO),
508 #if 0
509 DECL(AL_EFFECT_FLANGER),
510 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
511 DECL(AL_EFFECT_VOCAL_MORPHER),
512 DECL(AL_EFFECT_PITCH_SHIFTER),
513 #endif
514 DECL(AL_EFFECT_RING_MODULATOR),
515 #if 0
516 DECL(AL_EFFECT_AUTOWAH),
517 DECL(AL_EFFECT_COMPRESSOR),
518 DECL(AL_EFFECT_EQUALIZER),
519 #endif
520 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
521 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
523 DECL(AL_EAXREVERB_DENSITY),
524 DECL(AL_EAXREVERB_DIFFUSION),
525 DECL(AL_EAXREVERB_GAIN),
526 DECL(AL_EAXREVERB_GAINHF),
527 DECL(AL_EAXREVERB_GAINLF),
528 DECL(AL_EAXREVERB_DECAY_TIME),
529 DECL(AL_EAXREVERB_DECAY_HFRATIO),
530 DECL(AL_EAXREVERB_DECAY_LFRATIO),
531 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
532 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
533 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
534 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
535 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
536 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
537 DECL(AL_EAXREVERB_ECHO_TIME),
538 DECL(AL_EAXREVERB_ECHO_DEPTH),
539 DECL(AL_EAXREVERB_MODULATION_TIME),
540 DECL(AL_EAXREVERB_MODULATION_DEPTH),
541 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
542 DECL(AL_EAXREVERB_HFREFERENCE),
543 DECL(AL_EAXREVERB_LFREFERENCE),
544 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
545 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
547 DECL(AL_REVERB_DENSITY),
548 DECL(AL_REVERB_DIFFUSION),
549 DECL(AL_REVERB_GAIN),
550 DECL(AL_REVERB_GAINHF),
551 DECL(AL_REVERB_DECAY_TIME),
552 DECL(AL_REVERB_DECAY_HFRATIO),
553 DECL(AL_REVERB_REFLECTIONS_GAIN),
554 DECL(AL_REVERB_REFLECTIONS_DELAY),
555 DECL(AL_REVERB_LATE_REVERB_GAIN),
556 DECL(AL_REVERB_LATE_REVERB_DELAY),
557 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
558 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
559 DECL(AL_REVERB_DECAY_HFLIMIT),
561 DECL(AL_ECHO_DELAY),
562 DECL(AL_ECHO_LRDELAY),
563 DECL(AL_ECHO_DAMPING),
564 DECL(AL_ECHO_FEEDBACK),
565 DECL(AL_ECHO_SPREAD),
567 DECL(AL_RING_MODULATOR_FREQUENCY),
568 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
569 DECL(AL_RING_MODULATOR_WAVEFORM),
571 DECL(AL_DEDICATED_GAIN),
573 { NULL, (ALCenum)0 }
575 #undef DECL
577 static const ALCchar alcNoError[] = "No Error";
578 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
579 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
580 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
581 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
582 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
585 /************************************************
586 * Global variables
587 ************************************************/
589 /* Enumerated device names */
590 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
591 static ALCchar *alcAllDevicesList;
592 static ALCchar *alcCaptureDeviceList;
593 /* Sizes only include the first ending null character, not the second */
594 static size_t alcAllDevicesListSize;
595 static size_t alcCaptureDeviceListSize;
597 /* Default is always the first in the list */
598 static ALCchar *alcDefaultAllDevicesSpecifier;
599 static ALCchar *alcCaptureDefaultDeviceSpecifier;
601 /* Default context extensions */
602 static const ALchar alExtList[] =
603 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
604 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
605 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
606 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
607 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
609 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
611 /* Thread-local current context */
612 static pthread_key_t LocalContext;
613 /* Process-wide current context */
614 static ALCcontext *volatile GlobalContext = NULL;
616 /* Mixing thread piority level */
617 ALint RTPrioLevel;
619 FILE *LogFile;
620 #ifdef _DEBUG
621 enum LogLevel LogLevel = LogWarning;
622 #else
623 enum LogLevel LogLevel = LogError;
624 #endif
626 /* Flag to trap ALC device errors */
627 static ALCboolean TrapALCError = ALC_FALSE;
629 /* One-time configuration init control */
630 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
632 /* Default effect that applies to sources that don't have an effect on send 0 */
633 static ALeffect DefaultEffect;
636 /************************************************
637 * ALC information
638 ************************************************/
639 static const ALCchar alcNoDeviceExtList[] =
640 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
641 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
642 static const ALCchar alcExtensionList[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCint alcMajorVersion = 1;
647 static const ALCint alcMinorVersion = 1;
649 static const ALCint alcEFXMajorVersion = 1;
650 static const ALCint alcEFXMinorVersion = 0;
653 /************************************************
654 * Device lists
655 ************************************************/
656 static ALCdevice *volatile DeviceList = NULL;
658 static CRITICAL_SECTION ListLock;
660 static void LockLists(void)
662 EnterCriticalSection(&ListLock);
664 static void UnlockLists(void)
666 LeaveCriticalSection(&ListLock);
669 /************************************************
670 * Library initialization
671 ************************************************/
672 #if defined(_WIN32)
673 static void alc_init(void);
674 static void alc_deinit(void);
675 static void alc_deinit_safe(void);
677 UIntMap TlsDestructor;
679 #ifndef AL_LIBTYPE_STATIC
680 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
682 ALsizei i;
684 // Perform actions based on the reason for calling.
685 switch(ul_reason_for_call)
687 case DLL_PROCESS_ATTACH:
688 /* Pin the DLL so we won't get unloaded until the process terminates */
689 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
690 (WCHAR*)hModule, &hModule);
691 InitUIntMap(&TlsDestructor, ~0);
692 alc_init();
693 break;
695 case DLL_THREAD_DETACH:
696 LockUIntMapRead(&TlsDestructor);
697 for(i = 0;i < TlsDestructor.size;i++)
699 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
700 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
701 if(ptr && callback)
702 callback(ptr);
704 UnlockUIntMapRead(&TlsDestructor);
705 break;
707 case DLL_PROCESS_DETACH:
708 if(!lpReserved)
709 alc_deinit();
710 else
711 alc_deinit_safe();
712 ResetUIntMap(&TlsDestructor);
713 break;
715 return TRUE;
717 #elif defined(_MSC_VER)
718 #pragma section(".CRT$XCU",read)
719 static void alc_constructor(void);
720 static void alc_destructor(void);
721 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
723 static void alc_constructor(void)
725 atexit(alc_destructor);
726 alc_init();
729 static void alc_destructor(void)
731 alc_deinit();
733 #elif defined(HAVE_GCC_DESTRUCTOR)
734 static void alc_init(void) __attribute__((constructor));
735 static void alc_deinit(void) __attribute__((destructor));
736 #else
737 #error "No static initialization available on this platform!"
738 #endif
740 #elif defined(HAVE_GCC_DESTRUCTOR)
742 static void alc_init(void) __attribute__((constructor));
743 static void alc_deinit(void) __attribute__((destructor));
745 #else
746 #error "No global initialization available on this platform!"
747 #endif
749 static void ReleaseThreadCtx(void *ptr);
750 static void alc_init(void)
752 const char *str;
754 LogFile = stderr;
756 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
757 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
758 ConeScale *= 0.5f;
760 str = getenv("__ALSOFT_REVERSE_Z");
761 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
762 ZScale *= -1.0f;
764 pthread_key_create(&LocalContext, ReleaseThreadCtx);
765 InitializeCriticalSection(&ListLock);
766 ThunkInit();
769 static void alc_initconfig(void)
771 const char *devs, *str;
772 ALuint capfilter;
773 float valf;
774 int i, n;
776 str = getenv("ALSOFT_LOGLEVEL");
777 if(str)
779 long lvl = strtol(str, NULL, 0);
780 if(lvl >= NoLog && lvl <= LogRef)
781 LogLevel = lvl;
784 str = getenv("ALSOFT_LOGFILE");
785 if(str && str[0])
787 FILE *logfile = fopen(str, "wat");
788 if(logfile) LogFile = logfile;
789 else ERR("Failed to open log file '%s'\n", str);
792 ReadALConfig();
794 capfilter = CPU_CAP_ALL;
795 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
797 if(strcasecmp(str, "all") == 0)
798 capfilter = 0;
799 else
801 size_t len;
802 const char *next = str;
804 i = 0;
805 do {
806 str = next;
807 next = strchr(str, ',');
809 while(isspace(str[0]))
810 str++;
811 if(!str[0] || str[0] == ',')
812 continue;
814 len = (next ? ((size_t)(next-str)) : strlen(str));
815 if(strncasecmp(str, "neon", len) == 0)
816 capfilter &= ~CPU_CAP_NEON;
817 else
818 WARN("Invalid CPU extension \"%s\"\n", str);
819 } while(next++);
822 FillCPUCaps(capfilter);
824 InitHrtf();
826 #ifdef _WIN32
827 RTPrioLevel = 1;
828 #else
829 RTPrioLevel = 0;
830 #endif
831 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
833 if(ConfigValueStr(NULL, "resampler", &str))
835 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
836 DefaultResampler = PointResampler;
837 else if(strcasecmp(str, "linear") == 0)
838 DefaultResampler = LinearResampler;
839 else if(strcasecmp(str, "cubic") == 0)
840 DefaultResampler = CubicResampler;
841 else
843 char *end;
845 n = strtol(str, &end, 0);
846 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
847 DefaultResampler = n;
848 else
849 WARN("Invalid resampler: %s\n", str);
853 str = getenv("ALSOFT_TRAP_ERROR");
854 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
856 TrapALError = AL_TRUE;
857 TrapALCError = AL_TRUE;
859 else
861 str = getenv("ALSOFT_TRAP_AL_ERROR");
862 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
863 TrapALError = AL_TRUE;
864 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
866 str = getenv("ALSOFT_TRAP_ALC_ERROR");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 TrapALCError = ALC_TRUE;
869 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
872 if(ConfigValueFloat("reverb", "boost", &valf))
873 ReverbBoost *= powf(10.0f, valf / 20.0f);
875 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
877 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
878 ConfigValueStr(NULL, "drivers", &devs))
880 int n;
881 size_t len;
882 const char *next = devs;
883 int endlist, delitem;
885 i = 0;
886 do {
887 devs = next;
888 next = strchr(devs, ',');
890 delitem = (devs[0] == '-');
891 if(devs[0] == '-') devs++;
893 if(!devs[0] || devs[0] == ',')
895 endlist = 0;
896 continue;
898 endlist = 1;
900 len = (next ? ((size_t)(next-devs)) : strlen(devs));
901 for(n = i;BackendList[n].Init;n++)
903 if(len == strlen(BackendList[n].name) &&
904 strncmp(BackendList[n].name, devs, len) == 0)
906 if(delitem)
908 do {
909 BackendList[n] = BackendList[n+1];
910 ++n;
911 } while(BackendList[n].Init);
913 else
915 struct BackendInfo Bkp = BackendList[n];
916 while(n > i)
918 BackendList[n] = BackendList[n-1];
919 --n;
921 BackendList[n] = Bkp;
923 i++;
925 break;
928 } while(next++);
930 if(endlist)
932 BackendList[i].name = NULL;
933 BackendList[i].Init = NULL;
934 BackendList[i].Deinit = NULL;
935 BackendList[i].Probe = NULL;
939 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
941 if(!BackendList[i].Init(&BackendList[i].Funcs))
943 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
944 continue;
947 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
948 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
950 PlaybackBackend = BackendList[i];
951 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
953 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
955 CaptureBackend = BackendList[i];
956 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
959 BackendLoopback.Init(&BackendLoopback.Funcs);
961 if(ConfigValueStr(NULL, "excludefx", &str))
963 size_t len;
964 const char *next = str;
966 do {
967 str = next;
968 next = strchr(str, ',');
970 if(!str[0] || next == str)
971 continue;
973 len = (next ? ((size_t)(next-str)) : strlen(str));
974 for(n = 0;EffectList[n].name;n++)
976 if(len == strlen(EffectList[n].name) &&
977 strncmp(EffectList[n].name, str, len) == 0)
978 DisabledEffects[EffectList[n].type] = AL_TRUE;
980 } while(next++);
983 InitEffect(&DefaultEffect);
984 str = getenv("ALSOFT_DEFAULT_REVERB");
985 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
986 LoadReverbPreset(str, &DefaultEffect);
988 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
991 /************************************************
992 * Library deinitialization
993 ************************************************/
994 static void alc_cleanup(void)
996 ALCdevice *dev;
998 free(alcAllDevicesList); alcAllDevicesList = NULL;
999 alcAllDevicesListSize = 0;
1000 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1001 alcCaptureDeviceListSize = 0;
1003 free(alcDefaultAllDevicesSpecifier);
1004 alcDefaultAllDevicesSpecifier = NULL;
1005 free(alcCaptureDefaultDeviceSpecifier);
1006 alcCaptureDefaultDeviceSpecifier = NULL;
1008 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1010 ALCuint num = 0;
1011 do {
1012 num++;
1013 } while((dev=dev->next) != NULL);
1014 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1018 static void alc_deinit_safe(void)
1020 alc_cleanup();
1022 FreeHrtf();
1023 FreeALConfig();
1025 ThunkExit();
1026 DeleteCriticalSection(&ListLock);
1027 pthread_key_delete(LocalContext);
1029 if(LogFile != stderr)
1030 fclose(LogFile);
1031 LogFile = NULL;
1034 static void alc_deinit(void)
1036 int i;
1038 alc_cleanup();
1040 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1041 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1043 for(i = 0;BackendList[i].Deinit;i++)
1044 BackendList[i].Deinit();
1045 BackendLoopback.Deinit();
1047 alc_deinit_safe();
1051 /************************************************
1052 * Device enumeration
1053 ************************************************/
1054 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1056 DO_INITCONFIG();
1058 LockLists();
1059 free(*list);
1060 *list = NULL;
1061 *listsize = 0;
1063 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1064 PlaybackBackend.Probe(type);
1065 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1066 CaptureBackend.Probe(type);
1067 UnlockLists();
1070 static void ProbeAllDevicesList(void)
1071 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1072 static void ProbeCaptureDeviceList(void)
1073 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1076 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1078 size_t len = strlen(name);
1079 void *temp;
1081 if(len == 0)
1082 return;
1084 temp = realloc(*List, (*ListSize) + len + 2);
1085 if(!temp)
1087 ERR("Realloc failed to add %s!\n", name);
1088 return;
1090 *List = temp;
1092 memcpy((*List)+(*ListSize), name, len+1);
1093 *ListSize += len+1;
1094 (*List)[*ListSize] = 0;
1097 #define DECL_APPEND_LIST_FUNC(type) \
1098 void Append##type##List(const ALCchar *name) \
1099 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1101 DECL_APPEND_LIST_FUNC(AllDevices)
1102 DECL_APPEND_LIST_FUNC(CaptureDevice)
1104 #undef DECL_APPEND_LIST_FUNC
1107 /************************************************
1108 * Device format information
1109 ************************************************/
1110 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1112 switch(type)
1114 case DevFmtByte: return "Signed Byte";
1115 case DevFmtUByte: return "Unsigned Byte";
1116 case DevFmtShort: return "Signed Short";
1117 case DevFmtUShort: return "Unsigned Short";
1118 case DevFmtInt: return "Signed Int";
1119 case DevFmtUInt: return "Unsigned Int";
1120 case DevFmtFloat: return "Float";
1122 return "(unknown type)";
1124 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1126 switch(chans)
1128 case DevFmtMono: return "Mono";
1129 case DevFmtStereo: return "Stereo";
1130 case DevFmtQuad: return "Quadraphonic";
1131 case DevFmtX51: return "5.1 Surround";
1132 case DevFmtX51Side: return "5.1 Side";
1133 case DevFmtX61: return "6.1 Surround";
1134 case DevFmtX71: return "7.1 Surround";
1136 return "(unknown channels)";
1139 ALuint BytesFromDevFmt(enum DevFmtType type)
1141 switch(type)
1143 case DevFmtByte: return sizeof(ALbyte);
1144 case DevFmtUByte: return sizeof(ALubyte);
1145 case DevFmtShort: return sizeof(ALshort);
1146 case DevFmtUShort: return sizeof(ALushort);
1147 case DevFmtInt: return sizeof(ALint);
1148 case DevFmtUInt: return sizeof(ALuint);
1149 case DevFmtFloat: return sizeof(ALfloat);
1151 return 0;
1153 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1155 switch(chans)
1157 case DevFmtMono: return 1;
1158 case DevFmtStereo: return 2;
1159 case DevFmtQuad: return 4;
1160 case DevFmtX51: return 6;
1161 case DevFmtX51Side: return 6;
1162 case DevFmtX61: return 7;
1163 case DevFmtX71: return 8;
1165 return 0;
1168 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1169 enum DevFmtType *type)
1171 static const struct {
1172 ALenum format;
1173 enum DevFmtChannels channels;
1174 enum DevFmtType type;
1175 } list[] = {
1176 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1177 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1178 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1180 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1181 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1182 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1184 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1185 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1186 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1188 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1189 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1190 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1192 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1193 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1194 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1196 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1197 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1198 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1200 ALuint i;
1202 for(i = 0;i < COUNTOF(list);i++)
1204 if(list[i].format == format)
1206 *chans = list[i].channels;
1207 *type = list[i].type;
1208 return AL_TRUE;
1212 return AL_FALSE;
1215 static ALCboolean IsValidALCType(ALCenum type)
1217 switch(type)
1219 case ALC_BYTE_SOFT:
1220 case ALC_UNSIGNED_BYTE_SOFT:
1221 case ALC_SHORT_SOFT:
1222 case ALC_UNSIGNED_SHORT_SOFT:
1223 case ALC_INT_SOFT:
1224 case ALC_UNSIGNED_INT_SOFT:
1225 case ALC_FLOAT_SOFT:
1226 return ALC_TRUE;
1228 return ALC_FALSE;
1231 static ALCboolean IsValidALCChannels(ALCenum channels)
1233 switch(channels)
1235 case ALC_MONO_SOFT:
1236 case ALC_STEREO_SOFT:
1237 case ALC_QUAD_SOFT:
1238 case ALC_5POINT1_SOFT:
1239 case ALC_6POINT1_SOFT:
1240 case ALC_7POINT1_SOFT:
1241 return ALC_TRUE;
1243 return ALC_FALSE;
1247 /************************************************
1248 * Miscellaneous ALC helpers
1249 ************************************************/
1251 /* SetDefaultWFXChannelOrder
1253 * Sets the default channel order used by WaveFormatEx.
1255 void SetDefaultWFXChannelOrder(ALCdevice *device)
1257 switch(device->FmtChans)
1259 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1261 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1262 device->DevChannels[1] = FrontRight; break;
1264 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1265 device->DevChannels[1] = FrontRight;
1266 device->DevChannels[2] = BackLeft;
1267 device->DevChannels[3] = BackRight; break;
1269 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1270 device->DevChannels[1] = FrontRight;
1271 device->DevChannels[2] = FrontCenter;
1272 device->DevChannels[3] = LFE;
1273 device->DevChannels[4] = BackLeft;
1274 device->DevChannels[5] = BackRight; break;
1276 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1277 device->DevChannels[1] = FrontRight;
1278 device->DevChannels[2] = FrontCenter;
1279 device->DevChannels[3] = LFE;
1280 device->DevChannels[4] = SideLeft;
1281 device->DevChannels[5] = SideRight; break;
1283 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1284 device->DevChannels[1] = FrontRight;
1285 device->DevChannels[2] = FrontCenter;
1286 device->DevChannels[3] = LFE;
1287 device->DevChannels[4] = BackCenter;
1288 device->DevChannels[5] = SideLeft;
1289 device->DevChannels[6] = SideRight; break;
1291 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1292 device->DevChannels[1] = FrontRight;
1293 device->DevChannels[2] = FrontCenter;
1294 device->DevChannels[3] = LFE;
1295 device->DevChannels[4] = BackLeft;
1296 device->DevChannels[5] = BackRight;
1297 device->DevChannels[6] = SideLeft;
1298 device->DevChannels[7] = SideRight; break;
1302 /* SetDefaultChannelOrder
1304 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1306 void SetDefaultChannelOrder(ALCdevice *device)
1308 switch(device->FmtChans)
1310 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1311 device->DevChannels[1] = FrontRight;
1312 device->DevChannels[2] = BackLeft;
1313 device->DevChannels[3] = BackRight;
1314 device->DevChannels[4] = FrontCenter;
1315 device->DevChannels[5] = LFE;
1316 return;
1318 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1319 device->DevChannels[1] = FrontRight;
1320 device->DevChannels[2] = BackLeft;
1321 device->DevChannels[3] = BackRight;
1322 device->DevChannels[4] = FrontCenter;
1323 device->DevChannels[5] = LFE;
1324 device->DevChannels[6] = SideLeft;
1325 device->DevChannels[7] = SideRight;
1326 return;
1328 /* Same as WFX order */
1329 case DevFmtMono:
1330 case DevFmtStereo:
1331 case DevFmtQuad:
1332 case DevFmtX51Side:
1333 case DevFmtX61:
1334 break;
1336 SetDefaultWFXChannelOrder(device);
1340 /* alcSetError
1342 * Stores the latest ALC device error
1344 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1346 if(TrapALCError)
1348 #ifdef _WIN32
1349 /* DebugBreak() will cause an exception if there is no debugger */
1350 if(IsDebuggerPresent())
1351 DebugBreak();
1352 #elif defined(SIGTRAP)
1353 raise(SIGTRAP);
1354 #endif
1357 if(device)
1358 device->LastError = errorCode;
1359 else
1360 LastNullDeviceError = errorCode;
1364 /* UpdateDeviceParams
1366 * Updates device parameters according to the attribute list (caller is
1367 * responsible for holding the list lock).
1369 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1371 ALCcontext *context;
1372 enum DevFmtChannels oldChans;
1373 enum DevFmtType oldType;
1374 ALCuint oldFreq;
1375 int oldMode;
1376 ALuint i;
1378 // Check for attributes
1379 if(device->Type == Loopback)
1381 enum {
1382 GotFreq = 1<<0,
1383 GotChans = 1<<1,
1384 GotType = 1<<2,
1385 GotAll = GotFreq|GotChans|GotType
1387 ALCuint freq, numMono, numStereo, numSends;
1388 enum DevFmtChannels schans;
1389 enum DevFmtType stype;
1390 ALCuint attrIdx = 0;
1391 ALCint gotFmt = 0;
1393 if(!attrList)
1395 WARN("Missing attributes for loopback device\n");
1396 return ALC_INVALID_VALUE;
1399 numMono = device->NumMonoSources;
1400 numStereo = device->NumStereoSources;
1401 numSends = device->NumAuxSends;
1402 schans = device->FmtChans;
1403 stype = device->FmtType;
1404 freq = device->Frequency;
1406 while(attrList[attrIdx])
1408 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1410 ALCint val = attrList[attrIdx + 1];
1411 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1412 return ALC_INVALID_VALUE;
1413 schans = val;
1414 gotFmt |= GotChans;
1417 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1419 ALCint val = attrList[attrIdx + 1];
1420 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1421 return ALC_INVALID_VALUE;
1422 stype = val;
1423 gotFmt |= GotType;
1426 if(attrList[attrIdx] == ALC_FREQUENCY)
1428 freq = attrList[attrIdx + 1];
1429 if(freq < MIN_OUTPUT_RATE)
1430 return ALC_INVALID_VALUE;
1431 gotFmt |= GotFreq;
1434 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1436 numStereo = attrList[attrIdx + 1];
1437 if(numStereo > device->MaxNoOfSources)
1438 numStereo = device->MaxNoOfSources;
1440 numMono = device->MaxNoOfSources - numStereo;
1443 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1444 numSends = attrList[attrIdx + 1];
1446 attrIdx += 2;
1449 if(gotFmt != GotAll)
1451 WARN("Missing format for loopback device\n");
1452 return ALC_INVALID_VALUE;
1455 ConfigValueUInt(NULL, "sends", &numSends);
1456 numSends = minu(MAX_SENDS, numSends);
1458 if((device->Flags&DEVICE_RUNNING))
1459 ALCdevice_StopPlayback(device);
1460 device->Flags &= ~DEVICE_RUNNING;
1462 device->Frequency = freq;
1463 device->FmtChans = schans;
1464 device->FmtType = stype;
1465 device->NumMonoSources = numMono;
1466 device->NumStereoSources = numStereo;
1467 device->NumAuxSends = numSends;
1469 else if(attrList && attrList[0])
1471 ALCuint freq, numMono, numStereo, numSends;
1472 ALCuint attrIdx = 0;
1474 /* If a context is already running on the device, stop playback so the
1475 * device attributes can be updated. */
1476 if((device->Flags&DEVICE_RUNNING))
1477 ALCdevice_StopPlayback(device);
1478 device->Flags &= ~DEVICE_RUNNING;
1480 freq = device->Frequency;
1481 numMono = device->NumMonoSources;
1482 numStereo = device->NumStereoSources;
1483 numSends = device->NumAuxSends;
1485 while(attrList[attrIdx])
1487 if(attrList[attrIdx] == ALC_FREQUENCY)
1489 freq = attrList[attrIdx + 1];
1490 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1493 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1495 numStereo = attrList[attrIdx + 1];
1496 if(numStereo > device->MaxNoOfSources)
1497 numStereo = device->MaxNoOfSources;
1499 numMono = device->MaxNoOfSources - numStereo;
1502 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1503 numSends = attrList[attrIdx + 1];
1505 attrIdx += 2;
1508 ConfigValueUInt(NULL, "frequency", &freq);
1509 freq = maxu(freq, MIN_OUTPUT_RATE);
1511 ConfigValueUInt(NULL, "sends", &numSends);
1512 numSends = minu(MAX_SENDS, numSends);
1514 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1515 device->Frequency;
1517 device->Frequency = freq;
1518 device->NumMonoSources = numMono;
1519 device->NumStereoSources = numStereo;
1520 device->NumAuxSends = numSends;
1523 if((device->Flags&DEVICE_RUNNING))
1524 return ALC_NO_ERROR;
1526 oldFreq = device->Frequency;
1527 oldChans = device->FmtChans;
1528 oldType = device->FmtType;
1530 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1531 DevFmtChannelsString(device->FmtChans),
1532 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1533 DevFmtTypeString(device->FmtType),
1534 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1535 device->Frequency,
1536 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1537 device->UpdateSize, device->NumUpdates);
1539 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1540 return ALC_INVALID_DEVICE;
1542 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1544 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1545 DevFmtChannelsString(device->FmtChans));
1546 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1548 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1550 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1551 DevFmtTypeString(device->FmtType));
1552 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1554 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1556 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1557 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1560 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1561 DevFmtChannelsString(device->FmtChans),
1562 DevFmtTypeString(device->FmtType), device->Frequency,
1563 device->UpdateSize, device->NumUpdates);
1565 aluInitPanning(device);
1567 for(i = 0;i < MaxChannels;i++)
1569 device->ClickRemoval[i] = 0.0f;
1570 device->PendingClicks[i] = 0.0f;
1573 device->Hrtf = NULL;
1574 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1575 device->Hrtf = GetHrtf(device);
1576 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1578 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1580 if(!device->Bs2b)
1582 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1583 bs2b_clear(device->Bs2b);
1585 bs2b_set_srate(device->Bs2b, device->Frequency);
1586 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1587 TRACE("BS2B level %d\n", device->Bs2bLevel);
1589 else
1591 free(device->Bs2b);
1592 device->Bs2b = NULL;
1593 TRACE("BS2B disabled\n");
1596 device->Flags &= ~DEVICE_WIDE_STEREO;
1597 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1598 device->Flags |= DEVICE_WIDE_STEREO;
1600 oldMode = SetMixerFPUMode();
1601 LockDevice(device);
1602 context = device->ContextList;
1603 while(context)
1605 ALsizei pos;
1607 context->UpdateSources = AL_FALSE;
1608 LockUIntMapRead(&context->EffectSlotMap);
1609 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1611 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1613 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1615 UnlockUIntMapRead(&context->EffectSlotMap);
1616 UnlockDevice(device);
1617 RestoreFPUMode(oldMode);
1618 return ALC_INVALID_DEVICE;
1620 slot->NeedsUpdate = AL_FALSE;
1621 ALeffectState_Update(slot->EffectState, device, slot);
1623 UnlockUIntMapRead(&context->EffectSlotMap);
1625 LockUIntMapRead(&context->SourceMap);
1626 for(pos = 0;pos < context->SourceMap.size;pos++)
1628 ALsource *source = context->SourceMap.array[pos].value;
1629 ALuint s = device->NumAuxSends;
1630 while(s < MAX_SENDS)
1632 if(source->Send[s].Slot)
1633 DecrementRef(&source->Send[s].Slot->ref);
1634 source->Send[s].Slot = NULL;
1635 source->Send[s].Gain = 1.0f;
1636 source->Send[s].GainHF = 1.0f;
1637 s++;
1639 source->NeedsUpdate = AL_FALSE;
1640 ALsource_Update(source, context);
1642 UnlockUIntMapRead(&context->SourceMap);
1644 context = context->next;
1646 if(device->DefaultSlot)
1648 ALeffectslot *slot = device->DefaultSlot;
1650 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1652 UnlockDevice(device);
1653 RestoreFPUMode(oldMode);
1654 return ALC_INVALID_DEVICE;
1656 slot->NeedsUpdate = AL_FALSE;
1657 ALeffectState_Update(slot->EffectState, device, slot);
1659 UnlockDevice(device);
1660 RestoreFPUMode(oldMode);
1662 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1663 return ALC_INVALID_DEVICE;
1664 device->Flags |= DEVICE_RUNNING;
1666 return ALC_NO_ERROR;
1669 /* FreeDevice
1671 * Frees the device structure, and destroys any objects the app failed to
1672 * delete. Called once there's no more references on the device.
1674 static ALCvoid FreeDevice(ALCdevice *device)
1676 TRACE("%p\n", device);
1678 if(device->DefaultSlot)
1680 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1681 device->DefaultSlot->EffectState = NULL;
1684 if(device->BufferMap.size > 0)
1686 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1687 ReleaseALBuffers(device);
1689 ResetUIntMap(&device->BufferMap);
1691 if(device->EffectMap.size > 0)
1693 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1694 ReleaseALEffects(device);
1696 ResetUIntMap(&device->EffectMap);
1698 if(device->FilterMap.size > 0)
1700 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1701 ReleaseALFilters(device);
1703 ResetUIntMap(&device->FilterMap);
1705 free(device->Bs2b);
1706 device->Bs2b = NULL;
1708 free(device->DeviceName);
1709 device->DeviceName = NULL;
1711 DeleteCriticalSection(&device->Mutex);
1713 free(device);
1717 void ALCdevice_IncRef(ALCdevice *device)
1719 RefCount ref;
1720 ref = IncrementRef(&device->ref);
1721 TRACEREF("%p increasing refcount to %u\n", device, ref);
1724 void ALCdevice_DecRef(ALCdevice *device)
1726 RefCount ref;
1727 ref = DecrementRef(&device->ref);
1728 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1729 if(ref == 0) FreeDevice(device);
1732 /* VerifyDevice
1734 * Checks if the device handle is valid, and increments its ref count if so.
1736 static ALCdevice *VerifyDevice(ALCdevice *device)
1738 ALCdevice *tmpDevice;
1740 if(!device)
1741 return NULL;
1743 LockLists();
1744 tmpDevice = DeviceList;
1745 while(tmpDevice && tmpDevice != device)
1746 tmpDevice = tmpDevice->next;
1748 if(tmpDevice)
1749 ALCdevice_IncRef(tmpDevice);
1750 UnlockLists();
1751 return tmpDevice;
1755 /* InitContext
1757 * Initializes context fields
1759 static ALvoid InitContext(ALCcontext *Context)
1761 ALint i, j;
1763 //Initialise listener
1764 Context->Listener.Gain = 1.0f;
1765 Context->Listener.MetersPerUnit = 1.0f;
1766 Context->Listener.Position[0] = 0.0f;
1767 Context->Listener.Position[1] = 0.0f;
1768 Context->Listener.Position[2] = 0.0f;
1769 Context->Listener.Velocity[0] = 0.0f;
1770 Context->Listener.Velocity[1] = 0.0f;
1771 Context->Listener.Velocity[2] = 0.0f;
1772 Context->Listener.Forward[0] = 0.0f;
1773 Context->Listener.Forward[1] = 0.0f;
1774 Context->Listener.Forward[2] = -1.0f;
1775 Context->Listener.Up[0] = 0.0f;
1776 Context->Listener.Up[1] = 1.0f;
1777 Context->Listener.Up[2] = 0.0f;
1778 for(i = 0;i < 4;i++)
1780 for(j = 0;j < 4;j++)
1781 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1784 //Validate Context
1785 Context->LastError = AL_NO_ERROR;
1786 Context->UpdateSources = AL_FALSE;
1787 Context->ActiveSourceCount = 0;
1788 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1789 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1791 //Set globals
1792 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1793 Context->SourceDistanceModel = AL_FALSE;
1794 Context->DopplerFactor = 1.0f;
1795 Context->DopplerVelocity = 1.0f;
1796 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1797 Context->DeferUpdates = AL_FALSE;
1799 Context->ExtensionList = alExtList;
1803 /* FreeContext
1805 * Cleans up the context, and destroys any remaining objects the app failed to
1806 * delete. Called once there's no more references on the context.
1808 static ALCvoid FreeContext(ALCcontext *context)
1810 TRACE("%p\n", context);
1812 if(context->SourceMap.size > 0)
1814 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1815 ReleaseALSources(context);
1817 ResetUIntMap(&context->SourceMap);
1819 if(context->EffectSlotMap.size > 0)
1821 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1822 ReleaseALAuxiliaryEffectSlots(context);
1824 ResetUIntMap(&context->EffectSlotMap);
1826 context->ActiveSourceCount = 0;
1827 free(context->ActiveSources);
1828 context->ActiveSources = NULL;
1829 context->MaxActiveSources = 0;
1831 context->ActiveEffectSlotCount = 0;
1832 free(context->ActiveEffectSlots);
1833 context->ActiveEffectSlots = NULL;
1834 context->MaxActiveEffectSlots = 0;
1836 ALCdevice_DecRef(context->Device);
1837 context->Device = NULL;
1839 //Invalidate context
1840 memset(context, 0, sizeof(ALCcontext));
1841 free(context);
1844 /* ReleaseContext
1846 * Removes the context reference from the given device and removes it from
1847 * being current on the running thread or globally.
1849 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1851 ALCcontext *volatile*tmp_ctx;
1853 if(pthread_getspecific(LocalContext) == context)
1855 WARN("%p released while current on thread\n", context);
1856 pthread_setspecific(LocalContext, NULL);
1857 ALCcontext_DecRef(context);
1860 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1861 ALCcontext_DecRef(context);
1863 LockDevice(device);
1864 tmp_ctx = &device->ContextList;
1865 while(*tmp_ctx)
1867 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1868 break;
1869 tmp_ctx = &(*tmp_ctx)->next;
1871 UnlockDevice(device);
1873 ALCcontext_DecRef(context);
1876 void ALCcontext_IncRef(ALCcontext *context)
1878 RefCount ref;
1879 ref = IncrementRef(&context->ref);
1880 TRACEREF("%p increasing refcount to %u\n", context, ref);
1883 void ALCcontext_DecRef(ALCcontext *context)
1885 RefCount ref;
1886 ref = DecrementRef(&context->ref);
1887 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1888 if(ref == 0) FreeContext(context);
1891 static void ReleaseThreadCtx(void *ptr)
1893 WARN("%p current for thread being destroyed\n", ptr);
1894 ALCcontext_DecRef(ptr);
1897 /* VerifyContext
1899 * Checks that the given context is valid, and increments its reference count.
1901 static ALCcontext *VerifyContext(ALCcontext *context)
1903 ALCdevice *dev;
1905 LockLists();
1906 dev = DeviceList;
1907 while(dev)
1909 ALCcontext *tmp_ctx = dev->ContextList;
1910 while(tmp_ctx)
1912 if(tmp_ctx == context)
1914 ALCcontext_IncRef(tmp_ctx);
1915 UnlockLists();
1916 return tmp_ctx;
1918 tmp_ctx = tmp_ctx->next;
1920 dev = dev->next;
1922 UnlockLists();
1924 return NULL;
1928 /* GetContextRef
1930 * Returns the currently active context for this thread, and adds a reference
1931 * without locking it.
1933 ALCcontext *GetContextRef(void)
1935 ALCcontext *context;
1937 context = pthread_getspecific(LocalContext);
1938 if(context)
1939 ALCcontext_IncRef(context);
1940 else
1942 LockLists();
1943 context = GlobalContext;
1944 if(context)
1945 ALCcontext_IncRef(context);
1946 UnlockLists();
1949 return context;
1953 /************************************************
1954 * Standard ALC functions
1955 ************************************************/
1957 /* alcGetError
1959 * Return last ALC generated error code for the given device
1961 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1963 ALCenum errorCode;
1965 if(VerifyDevice(device))
1967 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1968 ALCdevice_DecRef(device);
1970 else
1971 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1973 return errorCode;
1977 /* alcSuspendContext
1979 * Not functional
1981 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1983 (void)Context;
1986 /* alcProcessContext
1988 * Not functional
1990 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
1992 (void)Context;
1996 /* alcGetString
1998 * Returns information about the device, and error strings
2000 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2002 const ALCchar *value = NULL;
2004 switch(param)
2006 case ALC_NO_ERROR:
2007 value = alcNoError;
2008 break;
2010 case ALC_INVALID_ENUM:
2011 value = alcErrInvalidEnum;
2012 break;
2014 case ALC_INVALID_VALUE:
2015 value = alcErrInvalidValue;
2016 break;
2018 case ALC_INVALID_DEVICE:
2019 value = alcErrInvalidDevice;
2020 break;
2022 case ALC_INVALID_CONTEXT:
2023 value = alcErrInvalidContext;
2024 break;
2026 case ALC_OUT_OF_MEMORY:
2027 value = alcErrOutOfMemory;
2028 break;
2030 case ALC_DEVICE_SPECIFIER:
2031 value = alcDefaultName;
2032 break;
2034 case ALC_ALL_DEVICES_SPECIFIER:
2035 if(VerifyDevice(Device))
2037 value = Device->DeviceName;
2038 ALCdevice_DecRef(Device);
2040 else
2042 ProbeAllDevicesList();
2043 value = alcAllDevicesList;
2045 break;
2047 case ALC_CAPTURE_DEVICE_SPECIFIER:
2048 if(VerifyDevice(Device))
2050 value = Device->DeviceName;
2051 ALCdevice_DecRef(Device);
2053 else
2055 ProbeCaptureDeviceList();
2056 value = alcCaptureDeviceList;
2058 break;
2060 /* Default devices are always first in the list */
2061 case ALC_DEFAULT_DEVICE_SPECIFIER:
2062 value = alcDefaultName;
2063 break;
2065 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2066 if(!alcAllDevicesList)
2067 ProbeAllDevicesList();
2069 Device = VerifyDevice(Device);
2071 free(alcDefaultAllDevicesSpecifier);
2072 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2073 alcAllDevicesList : "");
2074 if(!alcDefaultAllDevicesSpecifier)
2075 alcSetError(Device, ALC_OUT_OF_MEMORY);
2077 value = alcDefaultAllDevicesSpecifier;
2078 if(Device) ALCdevice_DecRef(Device);
2079 break;
2081 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2082 if(!alcCaptureDeviceList)
2083 ProbeCaptureDeviceList();
2085 Device = VerifyDevice(Device);
2087 free(alcCaptureDefaultDeviceSpecifier);
2088 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2089 alcCaptureDeviceList : "");
2090 if(!alcCaptureDefaultDeviceSpecifier)
2091 alcSetError(Device, ALC_OUT_OF_MEMORY);
2093 value = alcCaptureDefaultDeviceSpecifier;
2094 if(Device) ALCdevice_DecRef(Device);
2095 break;
2097 case ALC_EXTENSIONS:
2098 if(!VerifyDevice(Device))
2099 value = alcNoDeviceExtList;
2100 else
2102 value = alcExtensionList;
2103 ALCdevice_DecRef(Device);
2105 break;
2107 default:
2108 Device = VerifyDevice(Device);
2109 alcSetError(Device, ALC_INVALID_ENUM);
2110 if(Device) ALCdevice_DecRef(Device);
2111 break;
2114 return value;
2118 /* alcGetIntegerv
2120 * Returns information about the device and the version of OpenAL
2122 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2124 device = VerifyDevice(device);
2126 if(size == 0 || data == NULL)
2128 alcSetError(device, ALC_INVALID_VALUE);
2129 if(device) ALCdevice_DecRef(device);
2130 return;
2133 if(!device)
2135 switch(param)
2137 case ALC_MAJOR_VERSION:
2138 *data = alcMajorVersion;
2139 break;
2140 case ALC_MINOR_VERSION:
2141 *data = alcMinorVersion;
2142 break;
2144 case ALC_ATTRIBUTES_SIZE:
2145 case ALC_ALL_ATTRIBUTES:
2146 case ALC_FREQUENCY:
2147 case ALC_REFRESH:
2148 case ALC_SYNC:
2149 case ALC_MONO_SOURCES:
2150 case ALC_STEREO_SOURCES:
2151 case ALC_CAPTURE_SAMPLES:
2152 case ALC_FORMAT_CHANNELS_SOFT:
2153 case ALC_FORMAT_TYPE_SOFT:
2154 alcSetError(NULL, ALC_INVALID_DEVICE);
2155 break;
2157 default:
2158 alcSetError(NULL, ALC_INVALID_ENUM);
2159 break;
2162 else if(device->Type == Capture)
2164 switch(param)
2166 case ALC_CAPTURE_SAMPLES:
2167 LockLists();
2168 /* Re-validate the device since it may have been closed */
2169 ALCdevice_DecRef(device);
2170 if((device=VerifyDevice(device)) != NULL)
2171 *data = ALCdevice_AvailableSamples(device);
2172 else
2173 alcSetError(NULL, ALC_INVALID_DEVICE);
2174 UnlockLists();
2175 break;
2177 case ALC_CONNECTED:
2178 *data = device->Connected;
2179 break;
2181 default:
2182 alcSetError(device, ALC_INVALID_ENUM);
2183 break;
2186 else /* render device */
2188 switch(param)
2190 case ALC_MAJOR_VERSION:
2191 *data = alcMajorVersion;
2192 break;
2194 case ALC_MINOR_VERSION:
2195 *data = alcMinorVersion;
2196 break;
2198 case ALC_EFX_MAJOR_VERSION:
2199 *data = alcEFXMajorVersion;
2200 break;
2202 case ALC_EFX_MINOR_VERSION:
2203 *data = alcEFXMinorVersion;
2204 break;
2206 case ALC_ATTRIBUTES_SIZE:
2207 *data = 13;
2208 break;
2210 case ALC_ALL_ATTRIBUTES:
2211 if(size < 13)
2212 alcSetError(device, ALC_INVALID_VALUE);
2213 else
2215 int i = 0;
2217 data[i++] = ALC_FREQUENCY;
2218 data[i++] = device->Frequency;
2220 if(device->Type != Loopback)
2222 data[i++] = ALC_REFRESH;
2223 data[i++] = device->Frequency / device->UpdateSize;
2225 data[i++] = ALC_SYNC;
2226 data[i++] = ALC_FALSE;
2228 else
2230 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2231 data[i++] = device->FmtChans;
2233 data[i++] = ALC_FORMAT_TYPE_SOFT;
2234 data[i++] = device->FmtType;
2237 data[i++] = ALC_MONO_SOURCES;
2238 data[i++] = device->NumMonoSources;
2240 data[i++] = ALC_STEREO_SOURCES;
2241 data[i++] = device->NumStereoSources;
2243 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2244 data[i++] = device->NumAuxSends;
2246 data[i++] = 0;
2248 break;
2250 case ALC_FREQUENCY:
2251 *data = device->Frequency;
2252 break;
2254 case ALC_REFRESH:
2255 if(device->Type == Loopback)
2256 alcSetError(device, ALC_INVALID_DEVICE);
2257 else
2258 *data = device->Frequency / device->UpdateSize;
2259 break;
2261 case ALC_SYNC:
2262 if(device->Type == Loopback)
2263 alcSetError(device, ALC_INVALID_DEVICE);
2264 else
2265 *data = ALC_FALSE;
2266 break;
2268 case ALC_FORMAT_CHANNELS_SOFT:
2269 if(device->Type != Loopback)
2270 alcSetError(device, ALC_INVALID_DEVICE);
2271 else
2272 *data = device->FmtChans;
2273 break;
2275 case ALC_FORMAT_TYPE_SOFT:
2276 if(device->Type != Loopback)
2277 alcSetError(device, ALC_INVALID_DEVICE);
2278 else
2279 *data = device->FmtType;
2280 break;
2282 case ALC_MONO_SOURCES:
2283 *data = device->NumMonoSources;
2284 break;
2286 case ALC_STEREO_SOURCES:
2287 *data = device->NumStereoSources;
2288 break;
2290 case ALC_MAX_AUXILIARY_SENDS:
2291 *data = device->NumAuxSends;
2292 break;
2294 case ALC_CONNECTED:
2295 *data = device->Connected;
2296 break;
2298 default:
2299 alcSetError(device, ALC_INVALID_ENUM);
2300 break;
2303 if(device)
2304 ALCdevice_DecRef(device);
2308 /* alcIsExtensionPresent
2310 * Determines if there is support for a particular extension
2312 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2314 ALCboolean bResult = ALC_FALSE;
2316 device = VerifyDevice(device);
2318 if(!extName)
2319 alcSetError(device, ALC_INVALID_VALUE);
2320 else
2322 size_t len = strlen(extName);
2323 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2324 while(ptr && *ptr)
2326 if(strncasecmp(ptr, extName, len) == 0 &&
2327 (ptr[len] == '\0' || isspace(ptr[len])))
2329 bResult = ALC_TRUE;
2330 break;
2332 if((ptr=strchr(ptr, ' ')) != NULL)
2334 do {
2335 ++ptr;
2336 } while(isspace(*ptr));
2340 if(device)
2341 ALCdevice_DecRef(device);
2342 return bResult;
2346 /* alcGetProcAddress
2348 * Retrieves the function address for a particular extension function
2350 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2352 ALCvoid *ptr = NULL;
2354 if(!funcName)
2356 device = VerifyDevice(device);
2357 alcSetError(device, ALC_INVALID_VALUE);
2358 if(device) ALCdevice_DecRef(device);
2360 else
2362 ALsizei i = 0;
2363 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2364 i++;
2365 ptr = alcFunctions[i].address;
2368 return ptr;
2372 /* alcGetEnumValue
2374 * Get the value for a particular ALC enumeration name
2376 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2378 ALCenum val = 0;
2380 if(!enumName)
2382 device = VerifyDevice(device);
2383 alcSetError(device, ALC_INVALID_VALUE);
2384 if(device) ALCdevice_DecRef(device);
2386 else
2388 ALsizei i = 0;
2389 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2390 i++;
2391 val = enumeration[i].value;
2394 return val;
2398 /* alcCreateContext
2400 * Create and attach a context to the given device.
2402 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2404 ALCcontext *ALContext;
2405 ALCenum err;
2407 LockLists();
2408 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2410 UnlockLists();
2411 alcSetError(device, ALC_INVALID_DEVICE);
2412 if(device) ALCdevice_DecRef(device);
2413 return NULL;
2416 device->LastError = ALC_NO_ERROR;
2418 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2420 UnlockLists();
2421 alcSetError(device, err);
2422 if(err == ALC_INVALID_DEVICE)
2423 aluHandleDisconnect(device);
2424 ALCdevice_DecRef(device);
2425 return NULL;
2428 ALContext = calloc(1, sizeof(ALCcontext));
2429 if(ALContext)
2431 ALContext->ref = 1;
2433 ALContext->MaxActiveSources = 256;
2434 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2435 ALContext->MaxActiveSources);
2437 if(!ALContext || !ALContext->ActiveSources)
2439 if(!device->ContextList)
2441 ALCdevice_StopPlayback(device);
2442 device->Flags &= ~DEVICE_RUNNING;
2444 UnlockLists();
2446 free(ALContext);
2447 ALContext = NULL;
2449 alcSetError(device, ALC_OUT_OF_MEMORY);
2450 ALCdevice_DecRef(device);
2451 return NULL;
2454 ALContext->Device = device;
2455 ALCdevice_IncRef(device);
2456 InitContext(ALContext);
2458 do {
2459 ALContext->next = device->ContextList;
2460 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2461 UnlockLists();
2463 ALCdevice_DecRef(device);
2465 TRACE("Created context %p\n", ALContext);
2466 return ALContext;
2469 /* alcDestroyContext
2471 * Remove a context from its device
2473 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2475 ALCdevice *Device;
2477 LockLists();
2478 /* alcGetContextsDevice sets an error for invalid contexts */
2479 Device = alcGetContextsDevice(context);
2480 if(Device)
2482 ReleaseContext(context, Device);
2483 if(!Device->ContextList)
2485 ALCdevice_StopPlayback(Device);
2486 Device->Flags &= ~DEVICE_RUNNING;
2489 UnlockLists();
2493 /* alcGetCurrentContext
2495 * Returns the currently active context on the calling thread
2497 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2499 ALCcontext *Context;
2501 Context = pthread_getspecific(LocalContext);
2502 if(!Context) Context = GlobalContext;
2504 return Context;
2507 /* alcGetThreadContext
2509 * Returns the currently active thread-local context
2511 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2513 ALCcontext *Context;
2514 Context = pthread_getspecific(LocalContext);
2515 return Context;
2519 /* alcMakeContextCurrent
2521 * Makes the given context the active process-wide context, and removes the
2522 * thread-local context for the calling thread.
2524 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2526 /* context must be valid or NULL */
2527 if(context && !(context=VerifyContext(context)))
2529 alcSetError(NULL, ALC_INVALID_CONTEXT);
2530 return ALC_FALSE;
2532 /* context's reference count is already incremented */
2533 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2534 if(context) ALCcontext_DecRef(context);
2536 if((context=pthread_getspecific(LocalContext)) != NULL)
2538 pthread_setspecific(LocalContext, NULL);
2539 ALCcontext_DecRef(context);
2542 return ALC_TRUE;
2545 /* alcSetThreadContext
2547 * Makes the given context the active context for the current thread
2549 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2551 ALCcontext *old;
2553 /* context must be valid or NULL */
2554 if(context && !(context=VerifyContext(context)))
2556 alcSetError(NULL, ALC_INVALID_CONTEXT);
2557 return ALC_FALSE;
2559 /* context's reference count is already incremented */
2560 old = pthread_getspecific(LocalContext);
2561 pthread_setspecific(LocalContext, context);
2562 if(old) ALCcontext_DecRef(old);
2564 return ALC_TRUE;
2568 /* alcGetContextsDevice
2570 * Returns the device that a particular context is attached to
2572 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2574 ALCdevice *Device;
2576 if(!(Context=VerifyContext(Context)))
2578 alcSetError(NULL, ALC_INVALID_CONTEXT);
2579 return NULL;
2581 Device = Context->Device;
2582 ALCcontext_DecRef(Context);
2584 return Device;
2588 /* alcOpenDevice
2590 * Opens the named device.
2592 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2594 const ALCchar *fmt;
2595 ALCdevice *device;
2596 ALCenum err;
2598 DO_INITCONFIG();
2600 if(!PlaybackBackend.name)
2602 alcSetError(NULL, ALC_INVALID_VALUE);
2603 return NULL;
2606 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2607 deviceName = NULL;
2609 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2610 if(!device)
2612 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2613 return NULL;
2616 //Validate device
2617 device->Funcs = &PlaybackBackend.Funcs;
2618 device->ref = 1;
2619 device->Connected = ALC_TRUE;
2620 device->Type = Playback;
2621 InitializeCriticalSection(&device->Mutex);
2622 device->LastError = ALC_NO_ERROR;
2624 device->Flags = 0;
2625 device->Bs2b = NULL;
2626 device->Bs2bLevel = 0;
2627 device->DeviceName = NULL;
2629 device->ContextList = NULL;
2631 device->MaxNoOfSources = 256;
2632 device->AuxiliaryEffectSlotMax = 4;
2633 device->NumAuxSends = MAX_SENDS;
2635 InitUIntMap(&device->BufferMap, ~0);
2636 InitUIntMap(&device->EffectMap, ~0);
2637 InitUIntMap(&device->FilterMap, ~0);
2639 //Set output format
2640 device->FmtChans = DevFmtChannelsDefault;
2641 device->FmtType = DevFmtTypeDefault;
2642 device->Frequency = DEFAULT_OUTPUT_RATE;
2643 device->NumUpdates = 4;
2644 device->UpdateSize = 1024;
2646 if(ConfigValueStr(NULL, "channels", &fmt))
2648 static const struct {
2649 const char name[16];
2650 enum DevFmtChannels chans;
2651 } chanlist[] = {
2652 { "mono", DevFmtMono },
2653 { "stereo", DevFmtStereo },
2654 { "quad", DevFmtQuad },
2655 { "surround51", DevFmtX51 },
2656 { "surround61", DevFmtX61 },
2657 { "surround71", DevFmtX71 },
2659 size_t i;
2661 for(i = 0;i < COUNTOF(chanlist);i++)
2663 if(strcasecmp(chanlist[i].name, fmt) == 0)
2665 device->FmtChans = chanlist[i].chans;
2666 device->Flags |= DEVICE_CHANNELS_REQUEST;
2667 break;
2670 if(i == COUNTOF(chanlist))
2671 ERR("Unsupported channels: %s\n", fmt);
2673 if(ConfigValueStr(NULL, "sample-type", &fmt))
2675 static const struct {
2676 const char name[16];
2677 enum DevFmtType type;
2678 } typelist[] = {
2679 { "int8", DevFmtByte },
2680 { "uint8", DevFmtUByte },
2681 { "int16", DevFmtShort },
2682 { "uint16", DevFmtUShort },
2683 { "int32", DevFmtInt },
2684 { "uint32", DevFmtUInt },
2685 { "float32", DevFmtFloat },
2687 size_t i;
2689 for(i = 0;i < COUNTOF(typelist);i++)
2691 if(strcasecmp(typelist[i].name, fmt) == 0)
2693 device->FmtType = typelist[i].type;
2694 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2695 break;
2698 if(i == COUNTOF(typelist))
2699 ERR("Unsupported sample-type: %s\n", fmt);
2701 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2702 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2703 ConfigValueStr(NULL, "format", &fmt))
2705 static const struct {
2706 const char name[32];
2707 enum DevFmtChannels channels;
2708 enum DevFmtType type;
2709 } formats[] = {
2710 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2711 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2712 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2713 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2714 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2715 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2717 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2718 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2719 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2720 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2721 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2722 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2724 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2725 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2726 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2727 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2728 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2729 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2731 size_t i;
2733 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2734 for(i = 0;i < COUNTOF(formats);i++)
2736 if(strcasecmp(fmt, formats[i].name) == 0)
2738 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2739 device->FmtChans = formats[i].channels;
2740 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2741 device->FmtType = formats[i].type;
2742 device->Flags |= DEVICE_FORMAT_REQUEST;
2743 break;
2746 if(i == COUNTOF(formats))
2747 ERR("Unsupported format: %s\n", fmt);
2749 #undef DEVICE_FORMAT_REQUEST
2751 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2753 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2754 if(device->Frequency < MIN_OUTPUT_RATE)
2755 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2756 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2759 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2760 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2762 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2763 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2765 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2766 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2768 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2769 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2771 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2772 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2774 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2776 device->NumStereoSources = 1;
2777 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2779 // Find a playback device to open
2780 LockLists();
2781 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2783 UnlockLists();
2784 DeleteCriticalSection(&device->Mutex);
2785 free(device);
2786 alcSetError(NULL, err);
2787 return NULL;
2789 UnlockLists();
2791 if(DefaultEffect.type != AL_EFFECT_NULL)
2793 device->DefaultSlot = (ALeffectslot*)(device+1);
2794 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2796 device->DefaultSlot = NULL;
2797 ERR("Failed to initialize the default effect slot\n");
2799 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2801 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2802 device->DefaultSlot = NULL;
2803 ERR("Failed to initialize the default effect\n");
2807 do {
2808 device->next = DeviceList;
2809 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2811 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2812 return device;
2815 /* alcCloseDevice
2817 * Closes the given device.
2819 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2821 ALCdevice *volatile*list;
2822 ALCcontext *ctx;
2824 LockLists();
2825 list = &DeviceList;
2826 while(*list && *list != Device)
2827 list = &(*list)->next;
2829 if(!*list || (*list)->Type == Capture)
2831 alcSetError(*list, ALC_INVALID_DEVICE);
2832 UnlockLists();
2833 return ALC_FALSE;
2836 *list = (*list)->next;
2837 UnlockLists();
2839 while((ctx=Device->ContextList) != NULL)
2841 WARN("Releasing context %p\n", ctx);
2842 ReleaseContext(ctx, Device);
2844 if((Device->Flags&DEVICE_RUNNING))
2845 ALCdevice_StopPlayback(Device);
2846 Device->Flags &= ~DEVICE_RUNNING;
2848 ALCdevice_ClosePlayback(Device);
2850 ALCdevice_DecRef(Device);
2852 return ALC_TRUE;
2856 /************************************************
2857 * ALC capture functions
2858 ************************************************/
2859 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2861 ALCdevice *device = NULL;
2862 ALCenum err;
2864 DO_INITCONFIG();
2866 if(!CaptureBackend.name)
2868 alcSetError(NULL, ALC_INVALID_VALUE);
2869 return NULL;
2872 if(samples <= 0)
2874 alcSetError(NULL, ALC_INVALID_VALUE);
2875 return NULL;
2878 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2879 deviceName = NULL;
2881 device = calloc(1, sizeof(ALCdevice));
2882 if(!device)
2884 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2885 return NULL;
2888 //Validate device
2889 device->Funcs = &CaptureBackend.Funcs;
2890 device->ref = 1;
2891 device->Connected = ALC_TRUE;
2892 device->Type = Capture;
2893 InitializeCriticalSection(&device->Mutex);
2895 InitUIntMap(&device->BufferMap, ~0);
2896 InitUIntMap(&device->EffectMap, ~0);
2897 InitUIntMap(&device->FilterMap, ~0);
2899 device->DeviceName = NULL;
2901 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2902 device->Frequency = frequency;
2904 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2905 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2907 DeleteCriticalSection(&device->Mutex);
2908 free(device);
2909 alcSetError(NULL, ALC_INVALID_ENUM);
2910 return NULL;
2913 device->UpdateSize = samples;
2914 device->NumUpdates = 1;
2916 LockLists();
2917 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2919 UnlockLists();
2920 DeleteCriticalSection(&device->Mutex);
2921 free(device);
2922 alcSetError(NULL, err);
2923 return NULL;
2925 UnlockLists();
2927 do {
2928 device->next = DeviceList;
2929 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2931 TRACE("Created device %p\n", device);
2932 return device;
2935 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2937 ALCdevice *volatile*list;
2939 LockLists();
2940 list = &DeviceList;
2941 while(*list && *list != Device)
2942 list = &(*list)->next;
2944 if(!*list || (*list)->Type != Capture)
2946 alcSetError(*list, ALC_INVALID_DEVICE);
2947 UnlockLists();
2948 return ALC_FALSE;
2951 *list = (*list)->next;
2952 UnlockLists();
2954 ALCdevice_CloseCapture(Device);
2956 ALCdevice_DecRef(Device);
2958 return ALC_TRUE;
2961 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2963 LockLists();
2964 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2966 UnlockLists();
2967 alcSetError(device, ALC_INVALID_DEVICE);
2968 if(device) ALCdevice_DecRef(device);
2969 return;
2971 if(device->Connected)
2973 if(!(device->Flags&DEVICE_RUNNING))
2974 ALCdevice_StartCapture(device);
2975 device->Flags |= DEVICE_RUNNING;
2977 UnlockLists();
2979 ALCdevice_DecRef(device);
2982 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2984 LockLists();
2985 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2987 UnlockLists();
2988 alcSetError(device, ALC_INVALID_DEVICE);
2989 if(device) ALCdevice_DecRef(device);
2990 return;
2992 if((device->Flags&DEVICE_RUNNING))
2993 ALCdevice_StopCapture(device);
2994 device->Flags &= ~DEVICE_RUNNING;
2995 UnlockLists();
2997 ALCdevice_DecRef(device);
3000 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3002 ALCenum err = ALC_INVALID_DEVICE;
3003 LockLists();
3004 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3006 err = ALC_INVALID_VALUE;
3007 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3008 err = ALCdevice_CaptureSamples(device, buffer, samples);
3010 UnlockLists();
3011 if(err != ALC_NO_ERROR)
3012 alcSetError(device, err);
3013 if(device) ALCdevice_DecRef(device);
3017 /************************************************
3018 * ALC loopback functions
3019 ************************************************/
3021 /* alcLoopbackOpenDeviceSOFT
3023 * Open a loopback device, for manual rendering.
3025 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3027 ALCdevice *device;
3029 DO_INITCONFIG();
3031 /* Make sure the device name, if specified, is us. */
3032 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3034 alcSetError(NULL, ALC_INVALID_VALUE);
3035 return NULL;
3038 device = calloc(1, sizeof(ALCdevice));
3039 if(!device)
3041 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3042 return NULL;
3045 //Validate device
3046 device->Funcs = &BackendLoopback.Funcs;
3047 device->ref = 1;
3048 device->Connected = ALC_TRUE;
3049 device->Type = Loopback;
3050 InitializeCriticalSection(&device->Mutex);
3051 device->LastError = ALC_NO_ERROR;
3053 device->Flags = 0;
3054 device->Bs2b = NULL;
3055 device->Bs2bLevel = 0;
3056 device->DeviceName = NULL;
3058 device->ContextList = NULL;
3060 device->MaxNoOfSources = 256;
3061 device->AuxiliaryEffectSlotMax = 4;
3062 device->NumAuxSends = MAX_SENDS;
3064 InitUIntMap(&device->BufferMap, ~0);
3065 InitUIntMap(&device->EffectMap, ~0);
3066 InitUIntMap(&device->FilterMap, ~0);
3068 //Set output format
3069 device->NumUpdates = 0;
3070 device->UpdateSize = 0;
3072 device->Frequency = DEFAULT_OUTPUT_RATE;
3073 device->FmtChans = DevFmtChannelsDefault;
3074 device->FmtType = DevFmtTypeDefault;
3076 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3077 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3079 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3080 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3082 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3083 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3085 device->NumStereoSources = 1;
3086 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3088 // Open the "backend"
3089 ALCdevice_OpenPlayback(device, "Loopback");
3090 do {
3091 device->next = DeviceList;
3092 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3094 TRACE("Created device %p\n", device);
3095 return device;
3098 /* alcIsRenderFormatSupportedSOFT
3100 * Determines if the loopback device supports the given format for rendering.
3102 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3104 ALCboolean ret = ALC_FALSE;
3106 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3107 alcSetError(device, ALC_INVALID_DEVICE);
3108 else if(freq <= 0)
3109 alcSetError(device, ALC_INVALID_VALUE);
3110 else
3112 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3113 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3114 freq >= MIN_OUTPUT_RATE)
3115 ret = ALC_TRUE;
3117 if(device) ALCdevice_DecRef(device);
3119 return ret;
3122 /* alcRenderSamplesSOFT
3124 * Renders some samples into a buffer, using the format last set by the
3125 * attributes given to alcCreateContext.
3127 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3129 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3130 alcSetError(device, ALC_INVALID_DEVICE);
3131 else if(samples < 0 || (samples > 0 && buffer == NULL))
3132 alcSetError(device, ALC_INVALID_VALUE);
3133 else
3134 aluMixData(device, buffer, samples);
3135 if(device) ALCdevice_DecRef(device);