Add an option for wide stereo sources
[openal-soft.git] / Alc / ALc.c
blob7b757a87c1091bb72170b9cf916f1a603730f997
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 = 1.0f;
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 float valf;
773 int i, n;
775 str = getenv("ALSOFT_LOGLEVEL");
776 if(str)
778 long lvl = strtol(str, NULL, 0);
779 if(lvl >= NoLog && lvl <= LogRef)
780 LogLevel = lvl;
783 str = getenv("ALSOFT_LOGFILE");
784 if(str && str[0])
786 FILE *logfile = fopen(str, "wat");
787 if(logfile) LogFile = logfile;
788 else ERR("Failed to open log file '%s'\n", str);
791 ReadALConfig();
793 InitHrtf();
795 #ifdef _WIN32
796 RTPrioLevel = 1;
797 #else
798 RTPrioLevel = 0;
799 #endif
800 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
802 if(ConfigValueStr(NULL, "resampler", &str))
804 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
805 DefaultResampler = PointResampler;
806 else if(strcasecmp(str, "linear") == 0)
807 DefaultResampler = LinearResampler;
808 else if(strcasecmp(str, "cubic") == 0)
809 DefaultResampler = CubicResampler;
810 else
812 char *end;
814 n = strtol(str, &end, 0);
815 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
816 DefaultResampler = n;
817 else
818 WARN("Invalid resampler: %s\n", str);
822 str = getenv("ALSOFT_TRAP_ERROR");
823 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
825 TrapALError = AL_TRUE;
826 TrapALCError = AL_TRUE;
828 else
830 str = getenv("ALSOFT_TRAP_AL_ERROR");
831 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
832 TrapALError = AL_TRUE;
833 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
835 str = getenv("ALSOFT_TRAP_ALC_ERROR");
836 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
837 TrapALCError = ALC_TRUE;
838 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
841 if(ConfigValueFloat("reverb", "boost", &valf))
842 ReverbBoost *= powf(10.0f, valf / 20.0f);
844 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
846 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
847 ConfigValueStr(NULL, "drivers", &devs))
849 int n;
850 size_t len;
851 const char *next = devs;
852 int endlist, delitem;
854 i = 0;
855 do {
856 devs = next;
857 next = strchr(devs, ',');
859 delitem = (devs[0] == '-');
860 if(devs[0] == '-') devs++;
862 if(!devs[0] || devs[0] == ',')
864 endlist = 0;
865 continue;
867 endlist = 1;
869 len = (next ? ((size_t)(next-devs)) : strlen(devs));
870 for(n = i;BackendList[n].Init;n++)
872 if(len == strlen(BackendList[n].name) &&
873 strncmp(BackendList[n].name, devs, len) == 0)
875 if(delitem)
877 do {
878 BackendList[n] = BackendList[n+1];
879 ++n;
880 } while(BackendList[n].Init);
882 else
884 struct BackendInfo Bkp = BackendList[n];
885 while(n > i)
887 BackendList[n] = BackendList[n-1];
888 --n;
890 BackendList[n] = Bkp;
892 i++;
894 break;
897 } while(next++);
899 if(endlist)
901 BackendList[i].name = NULL;
902 BackendList[i].Init = NULL;
903 BackendList[i].Deinit = NULL;
904 BackendList[i].Probe = NULL;
908 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
910 if(!BackendList[i].Init(&BackendList[i].Funcs))
912 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
913 continue;
916 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
917 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
919 PlaybackBackend = BackendList[i];
920 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
922 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
924 CaptureBackend = BackendList[i];
925 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
928 BackendLoopback.Init(&BackendLoopback.Funcs);
930 if(ConfigValueStr(NULL, "excludefx", &str))
932 size_t len;
933 const char *next = str;
935 do {
936 str = next;
937 next = strchr(str, ',');
939 if(!str[0] || next == str)
940 continue;
942 len = (next ? ((size_t)(next-str)) : strlen(str));
943 for(n = 0;EffectList[n].name;n++)
945 if(len == strlen(EffectList[n].name) &&
946 strncmp(EffectList[n].name, str, len) == 0)
947 DisabledEffects[EffectList[n].type] = AL_TRUE;
949 } while(next++);
952 InitEffect(&DefaultEffect);
953 str = getenv("ALSOFT_DEFAULT_REVERB");
954 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
955 LoadReverbPreset(str, &DefaultEffect);
957 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
960 /************************************************
961 * Library deinitialization
962 ************************************************/
963 static void alc_cleanup(void)
965 ALCdevice *dev;
967 free(alcAllDevicesList); alcAllDevicesList = NULL;
968 alcAllDevicesListSize = 0;
969 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
970 alcCaptureDeviceListSize = 0;
972 free(alcDefaultAllDevicesSpecifier);
973 alcDefaultAllDevicesSpecifier = NULL;
974 free(alcCaptureDefaultDeviceSpecifier);
975 alcCaptureDefaultDeviceSpecifier = NULL;
977 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
979 ALCuint num = 0;
980 do {
981 num++;
982 } while((dev=dev->next) != NULL);
983 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
987 static void alc_deinit_safe(void)
989 alc_cleanup();
991 FreeHrtf();
992 FreeALConfig();
994 ThunkExit();
995 DeleteCriticalSection(&ListLock);
996 pthread_key_delete(LocalContext);
998 if(LogFile != stderr)
999 fclose(LogFile);
1000 LogFile = NULL;
1003 static void alc_deinit(void)
1005 int i;
1007 alc_cleanup();
1009 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1010 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1012 for(i = 0;BackendList[i].Deinit;i++)
1013 BackendList[i].Deinit();
1014 BackendLoopback.Deinit();
1016 alc_deinit_safe();
1020 /************************************************
1021 * Device enumeration
1022 ************************************************/
1023 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1025 DO_INITCONFIG();
1027 LockLists();
1028 free(*list);
1029 *list = NULL;
1030 *listsize = 0;
1032 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1033 PlaybackBackend.Probe(type);
1034 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1035 CaptureBackend.Probe(type);
1036 UnlockLists();
1039 static void ProbeAllDevicesList(void)
1040 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1041 static void ProbeCaptureDeviceList(void)
1042 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1045 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1047 size_t len = strlen(name);
1048 void *temp;
1050 if(len == 0)
1051 return;
1053 temp = realloc(*List, (*ListSize) + len + 2);
1054 if(!temp)
1056 ERR("Realloc failed to add %s!\n", name);
1057 return;
1059 *List = temp;
1061 memcpy((*List)+(*ListSize), name, len+1);
1062 *ListSize += len+1;
1063 (*List)[*ListSize] = 0;
1066 #define DECL_APPEND_LIST_FUNC(type) \
1067 void Append##type##List(const ALCchar *name) \
1068 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1070 DECL_APPEND_LIST_FUNC(AllDevices)
1071 DECL_APPEND_LIST_FUNC(CaptureDevice)
1073 #undef DECL_APPEND_LIST_FUNC
1076 /************************************************
1077 * Device format information
1078 ************************************************/
1079 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1081 switch(type)
1083 case DevFmtByte: return "Signed Byte";
1084 case DevFmtUByte: return "Unsigned Byte";
1085 case DevFmtShort: return "Signed Short";
1086 case DevFmtUShort: return "Unsigned Short";
1087 case DevFmtInt: return "Signed Int";
1088 case DevFmtUInt: return "Unsigned Int";
1089 case DevFmtFloat: return "Float";
1091 return "(unknown type)";
1093 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1095 switch(chans)
1097 case DevFmtMono: return "Mono";
1098 case DevFmtStereo: return "Stereo";
1099 case DevFmtQuad: return "Quadraphonic";
1100 case DevFmtX51: return "5.1 Surround";
1101 case DevFmtX51Side: return "5.1 Side";
1102 case DevFmtX61: return "6.1 Surround";
1103 case DevFmtX71: return "7.1 Surround";
1105 return "(unknown channels)";
1108 ALuint BytesFromDevFmt(enum DevFmtType type)
1110 switch(type)
1112 case DevFmtByte: return sizeof(ALbyte);
1113 case DevFmtUByte: return sizeof(ALubyte);
1114 case DevFmtShort: return sizeof(ALshort);
1115 case DevFmtUShort: return sizeof(ALushort);
1116 case DevFmtInt: return sizeof(ALint);
1117 case DevFmtUInt: return sizeof(ALuint);
1118 case DevFmtFloat: return sizeof(ALfloat);
1120 return 0;
1122 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1124 switch(chans)
1126 case DevFmtMono: return 1;
1127 case DevFmtStereo: return 2;
1128 case DevFmtQuad: return 4;
1129 case DevFmtX51: return 6;
1130 case DevFmtX51Side: return 6;
1131 case DevFmtX61: return 7;
1132 case DevFmtX71: return 8;
1134 return 0;
1137 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1138 enum DevFmtType *type)
1140 static const struct {
1141 ALenum format;
1142 enum DevFmtChannels channels;
1143 enum DevFmtType type;
1144 } list[] = {
1145 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1146 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1147 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1149 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1150 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1151 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1153 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1154 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1155 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1157 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1158 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1159 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1161 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1162 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1163 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1165 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1166 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1167 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1169 ALuint i;
1171 for(i = 0;i < COUNTOF(list);i++)
1173 if(list[i].format == format)
1175 *chans = list[i].channels;
1176 *type = list[i].type;
1177 return AL_TRUE;
1181 return AL_FALSE;
1184 static ALCboolean IsValidALCType(ALCenum type)
1186 switch(type)
1188 case ALC_BYTE_SOFT:
1189 case ALC_UNSIGNED_BYTE_SOFT:
1190 case ALC_SHORT_SOFT:
1191 case ALC_UNSIGNED_SHORT_SOFT:
1192 case ALC_INT_SOFT:
1193 case ALC_UNSIGNED_INT_SOFT:
1194 case ALC_FLOAT_SOFT:
1195 return ALC_TRUE;
1197 return ALC_FALSE;
1200 static ALCboolean IsValidALCChannels(ALCenum channels)
1202 switch(channels)
1204 case ALC_MONO_SOFT:
1205 case ALC_STEREO_SOFT:
1206 case ALC_QUAD_SOFT:
1207 case ALC_5POINT1_SOFT:
1208 case ALC_6POINT1_SOFT:
1209 case ALC_7POINT1_SOFT:
1210 return ALC_TRUE;
1212 return ALC_FALSE;
1216 /************************************************
1217 * Miscellaneous ALC helpers
1218 ************************************************/
1220 /* SetDefaultWFXChannelOrder
1222 * Sets the default channel order used by WaveFormatEx.
1224 void SetDefaultWFXChannelOrder(ALCdevice *device)
1226 switch(device->FmtChans)
1228 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1230 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1231 device->DevChannels[1] = FrontRight; break;
1233 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1234 device->DevChannels[1] = FrontRight;
1235 device->DevChannels[2] = BackLeft;
1236 device->DevChannels[3] = BackRight; break;
1238 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1239 device->DevChannels[1] = FrontRight;
1240 device->DevChannels[2] = FrontCenter;
1241 device->DevChannels[3] = LFE;
1242 device->DevChannels[4] = BackLeft;
1243 device->DevChannels[5] = BackRight; break;
1245 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1246 device->DevChannels[1] = FrontRight;
1247 device->DevChannels[2] = FrontCenter;
1248 device->DevChannels[3] = LFE;
1249 device->DevChannels[4] = SideLeft;
1250 device->DevChannels[5] = SideRight; break;
1252 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1253 device->DevChannels[1] = FrontRight;
1254 device->DevChannels[2] = FrontCenter;
1255 device->DevChannels[3] = LFE;
1256 device->DevChannels[4] = BackCenter;
1257 device->DevChannels[5] = SideLeft;
1258 device->DevChannels[6] = SideRight; break;
1260 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1261 device->DevChannels[1] = FrontRight;
1262 device->DevChannels[2] = FrontCenter;
1263 device->DevChannels[3] = LFE;
1264 device->DevChannels[4] = BackLeft;
1265 device->DevChannels[5] = BackRight;
1266 device->DevChannels[6] = SideLeft;
1267 device->DevChannels[7] = SideRight; break;
1271 /* SetDefaultChannelOrder
1273 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1275 void SetDefaultChannelOrder(ALCdevice *device)
1277 switch(device->FmtChans)
1279 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1280 device->DevChannels[1] = FrontRight;
1281 device->DevChannels[2] = BackLeft;
1282 device->DevChannels[3] = BackRight;
1283 device->DevChannels[4] = FrontCenter;
1284 device->DevChannels[5] = LFE;
1285 return;
1287 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1288 device->DevChannels[1] = FrontRight;
1289 device->DevChannels[2] = BackLeft;
1290 device->DevChannels[3] = BackRight;
1291 device->DevChannels[4] = FrontCenter;
1292 device->DevChannels[5] = LFE;
1293 device->DevChannels[6] = SideLeft;
1294 device->DevChannels[7] = SideRight;
1295 return;
1297 /* Same as WFX order */
1298 case DevFmtMono:
1299 case DevFmtStereo:
1300 case DevFmtQuad:
1301 case DevFmtX51Side:
1302 case DevFmtX61:
1303 break;
1305 SetDefaultWFXChannelOrder(device);
1309 /* alcSetError
1311 * Stores the latest ALC device error
1313 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1315 if(TrapALCError)
1317 #ifdef _WIN32
1318 /* DebugBreak() will cause an exception if there is no debugger */
1319 if(IsDebuggerPresent())
1320 DebugBreak();
1321 #elif defined(SIGTRAP)
1322 raise(SIGTRAP);
1323 #endif
1326 if(device)
1327 device->LastError = errorCode;
1328 else
1329 LastNullDeviceError = errorCode;
1333 /* UpdateDeviceParams
1335 * Updates device parameters according to the attribute list (caller is
1336 * responsible for holding the list lock).
1338 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1340 ALCcontext *context;
1341 enum DevFmtChannels oldChans;
1342 enum DevFmtType oldType;
1343 ALCuint oldFreq;
1344 int oldMode;
1345 ALuint i;
1347 // Check for attributes
1348 if(device->Type == Loopback)
1350 enum {
1351 GotFreq = 1<<0,
1352 GotChans = 1<<1,
1353 GotType = 1<<2,
1354 GotAll = GotFreq|GotChans|GotType
1356 ALCuint freq, numMono, numStereo, numSends;
1357 enum DevFmtChannels schans;
1358 enum DevFmtType stype;
1359 ALCuint attrIdx = 0;
1360 ALCint gotFmt = 0;
1362 if(!attrList)
1364 WARN("Missing attributes for loopback device\n");
1365 return ALC_INVALID_VALUE;
1368 numMono = device->NumMonoSources;
1369 numStereo = device->NumStereoSources;
1370 numSends = device->NumAuxSends;
1371 schans = device->FmtChans;
1372 stype = device->FmtType;
1373 freq = device->Frequency;
1375 while(attrList[attrIdx])
1377 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1379 ALCint val = attrList[attrIdx + 1];
1380 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1381 return ALC_INVALID_VALUE;
1382 schans = val;
1383 gotFmt |= GotChans;
1386 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1388 ALCint val = attrList[attrIdx + 1];
1389 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1390 return ALC_INVALID_VALUE;
1391 stype = val;
1392 gotFmt |= GotType;
1395 if(attrList[attrIdx] == ALC_FREQUENCY)
1397 freq = attrList[attrIdx + 1];
1398 if(freq < MIN_OUTPUT_RATE)
1399 return ALC_INVALID_VALUE;
1400 gotFmt |= GotFreq;
1403 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1405 numStereo = attrList[attrIdx + 1];
1406 if(numStereo > device->MaxNoOfSources)
1407 numStereo = device->MaxNoOfSources;
1409 numMono = device->MaxNoOfSources - numStereo;
1412 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1413 numSends = attrList[attrIdx + 1];
1415 attrIdx += 2;
1418 if(gotFmt != GotAll)
1420 WARN("Missing format for loopback device\n");
1421 return ALC_INVALID_VALUE;
1424 ConfigValueUInt(NULL, "sends", &numSends);
1425 numSends = minu(MAX_SENDS, numSends);
1427 if((device->Flags&DEVICE_RUNNING))
1428 ALCdevice_StopPlayback(device);
1429 device->Flags &= ~DEVICE_RUNNING;
1431 device->Frequency = freq;
1432 device->FmtChans = schans;
1433 device->FmtType = stype;
1434 device->NumMonoSources = numMono;
1435 device->NumStereoSources = numStereo;
1436 device->NumAuxSends = numSends;
1438 else if(attrList && attrList[0])
1440 ALCuint freq, numMono, numStereo, numSends;
1441 ALCuint attrIdx = 0;
1443 /* If a context is already running on the device, stop playback so the
1444 * device attributes can be updated. */
1445 if((device->Flags&DEVICE_RUNNING))
1446 ALCdevice_StopPlayback(device);
1447 device->Flags &= ~DEVICE_RUNNING;
1449 freq = device->Frequency;
1450 numMono = device->NumMonoSources;
1451 numStereo = device->NumStereoSources;
1452 numSends = device->NumAuxSends;
1454 while(attrList[attrIdx])
1456 if(attrList[attrIdx] == ALC_FREQUENCY)
1458 freq = attrList[attrIdx + 1];
1459 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1462 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1464 numStereo = attrList[attrIdx + 1];
1465 if(numStereo > device->MaxNoOfSources)
1466 numStereo = device->MaxNoOfSources;
1468 numMono = device->MaxNoOfSources - numStereo;
1471 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1472 numSends = attrList[attrIdx + 1];
1474 attrIdx += 2;
1477 ConfigValueUInt(NULL, "frequency", &freq);
1478 freq = maxu(freq, MIN_OUTPUT_RATE);
1480 ConfigValueUInt(NULL, "sends", &numSends);
1481 numSends = minu(MAX_SENDS, numSends);
1483 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1484 device->Frequency;
1486 device->Frequency = freq;
1487 device->NumMonoSources = numMono;
1488 device->NumStereoSources = numStereo;
1489 device->NumAuxSends = numSends;
1492 if((device->Flags&DEVICE_RUNNING))
1493 return ALC_NO_ERROR;
1495 oldFreq = device->Frequency;
1496 oldChans = device->FmtChans;
1497 oldType = device->FmtType;
1499 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1500 DevFmtChannelsString(device->FmtChans),
1501 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1502 DevFmtTypeString(device->FmtType),
1503 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1504 device->Frequency,
1505 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1506 device->UpdateSize, device->NumUpdates);
1508 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1509 return ALC_INVALID_DEVICE;
1511 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1513 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1514 DevFmtChannelsString(device->FmtChans));
1515 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1517 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1519 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1520 DevFmtTypeString(device->FmtType));
1521 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1523 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1525 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1526 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1529 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1530 DevFmtChannelsString(device->FmtChans),
1531 DevFmtTypeString(device->FmtType), device->Frequency,
1532 device->UpdateSize, device->NumUpdates);
1534 aluInitPanning(device);
1536 for(i = 0;i < MaxChannels;i++)
1538 device->ClickRemoval[i] = 0.0f;
1539 device->PendingClicks[i] = 0.0f;
1542 device->Hrtf = NULL;
1543 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1544 device->Hrtf = GetHrtf(device);
1545 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1547 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1549 if(!device->Bs2b)
1551 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1552 bs2b_clear(device->Bs2b);
1554 bs2b_set_srate(device->Bs2b, device->Frequency);
1555 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1556 TRACE("BS2B level %d\n", device->Bs2bLevel);
1558 else
1560 free(device->Bs2b);
1561 device->Bs2b = NULL;
1562 TRACE("BS2B disabled\n");
1565 device->Flags &= ~DEVICE_WIDE_STEREO;
1566 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1567 device->Flags |= DEVICE_WIDE_STEREO;
1569 oldMode = SetMixerFPUMode();
1570 LockDevice(device);
1571 context = device->ContextList;
1572 while(context)
1574 ALsizei pos;
1576 context->UpdateSources = AL_FALSE;
1577 LockUIntMapRead(&context->EffectSlotMap);
1578 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1580 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1582 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1584 UnlockUIntMapRead(&context->EffectSlotMap);
1585 UnlockDevice(device);
1586 RestoreFPUMode(oldMode);
1587 return ALC_INVALID_DEVICE;
1589 slot->NeedsUpdate = AL_FALSE;
1590 ALeffectState_Update(slot->EffectState, device, slot);
1592 UnlockUIntMapRead(&context->EffectSlotMap);
1594 LockUIntMapRead(&context->SourceMap);
1595 for(pos = 0;pos < context->SourceMap.size;pos++)
1597 ALsource *source = context->SourceMap.array[pos].value;
1598 ALuint s = device->NumAuxSends;
1599 while(s < MAX_SENDS)
1601 if(source->Send[s].Slot)
1602 DecrementRef(&source->Send[s].Slot->ref);
1603 source->Send[s].Slot = NULL;
1604 source->Send[s].Gain = 1.0f;
1605 source->Send[s].GainHF = 1.0f;
1606 s++;
1608 source->NeedsUpdate = AL_FALSE;
1609 ALsource_Update(source, context);
1611 UnlockUIntMapRead(&context->SourceMap);
1613 context = context->next;
1615 if(device->DefaultSlot)
1617 ALeffectslot *slot = device->DefaultSlot;
1619 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1621 UnlockDevice(device);
1622 RestoreFPUMode(oldMode);
1623 return ALC_INVALID_DEVICE;
1625 slot->NeedsUpdate = AL_FALSE;
1626 ALeffectState_Update(slot->EffectState, device, slot);
1628 UnlockDevice(device);
1629 RestoreFPUMode(oldMode);
1631 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1632 return ALC_INVALID_DEVICE;
1633 device->Flags |= DEVICE_RUNNING;
1635 return ALC_NO_ERROR;
1638 /* FreeDevice
1640 * Frees the device structure, and destroys any objects the app failed to
1641 * delete. Called once there's no more references on the device.
1643 static ALCvoid FreeDevice(ALCdevice *device)
1645 TRACE("%p\n", device);
1647 if(device->DefaultSlot)
1649 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1650 device->DefaultSlot->EffectState = NULL;
1653 if(device->BufferMap.size > 0)
1655 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1656 ReleaseALBuffers(device);
1658 ResetUIntMap(&device->BufferMap);
1660 if(device->EffectMap.size > 0)
1662 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1663 ReleaseALEffects(device);
1665 ResetUIntMap(&device->EffectMap);
1667 if(device->FilterMap.size > 0)
1669 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1670 ReleaseALFilters(device);
1672 ResetUIntMap(&device->FilterMap);
1674 free(device->Bs2b);
1675 device->Bs2b = NULL;
1677 free(device->DeviceName);
1678 device->DeviceName = NULL;
1680 DeleteCriticalSection(&device->Mutex);
1682 free(device);
1686 void ALCdevice_IncRef(ALCdevice *device)
1688 RefCount ref;
1689 ref = IncrementRef(&device->ref);
1690 TRACEREF("%p increasing refcount to %u\n", device, ref);
1693 void ALCdevice_DecRef(ALCdevice *device)
1695 RefCount ref;
1696 ref = DecrementRef(&device->ref);
1697 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1698 if(ref == 0) FreeDevice(device);
1701 /* VerifyDevice
1703 * Checks if the device handle is valid, and increments its ref count if so.
1705 static ALCdevice *VerifyDevice(ALCdevice *device)
1707 ALCdevice *tmpDevice;
1709 if(!device)
1710 return NULL;
1712 LockLists();
1713 tmpDevice = DeviceList;
1714 while(tmpDevice && tmpDevice != device)
1715 tmpDevice = tmpDevice->next;
1717 if(tmpDevice)
1718 ALCdevice_IncRef(tmpDevice);
1719 UnlockLists();
1720 return tmpDevice;
1724 /* InitContext
1726 * Initializes context fields
1728 static ALvoid InitContext(ALCcontext *Context)
1730 ALint i, j;
1732 //Initialise listener
1733 Context->Listener.Gain = 1.0f;
1734 Context->Listener.MetersPerUnit = 1.0f;
1735 Context->Listener.Position[0] = 0.0f;
1736 Context->Listener.Position[1] = 0.0f;
1737 Context->Listener.Position[2] = 0.0f;
1738 Context->Listener.Velocity[0] = 0.0f;
1739 Context->Listener.Velocity[1] = 0.0f;
1740 Context->Listener.Velocity[2] = 0.0f;
1741 Context->Listener.Forward[0] = 0.0f;
1742 Context->Listener.Forward[1] = 0.0f;
1743 Context->Listener.Forward[2] = -1.0f;
1744 Context->Listener.Up[0] = 0.0f;
1745 Context->Listener.Up[1] = 1.0f;
1746 Context->Listener.Up[2] = 0.0f;
1747 for(i = 0;i < 4;i++)
1749 for(j = 0;j < 4;j++)
1750 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1753 //Validate Context
1754 Context->LastError = AL_NO_ERROR;
1755 Context->UpdateSources = AL_FALSE;
1756 Context->ActiveSourceCount = 0;
1757 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1758 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1760 //Set globals
1761 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1762 Context->SourceDistanceModel = AL_FALSE;
1763 Context->DopplerFactor = 1.0f;
1764 Context->DopplerVelocity = 1.0f;
1765 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1766 Context->DeferUpdates = AL_FALSE;
1768 Context->ExtensionList = alExtList;
1772 /* FreeContext
1774 * Cleans up the context, and destroys any remaining objects the app failed to
1775 * delete. Called once there's no more references on the context.
1777 static ALCvoid FreeContext(ALCcontext *context)
1779 TRACE("%p\n", context);
1781 if(context->SourceMap.size > 0)
1783 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1784 ReleaseALSources(context);
1786 ResetUIntMap(&context->SourceMap);
1788 if(context->EffectSlotMap.size > 0)
1790 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1791 ReleaseALAuxiliaryEffectSlots(context);
1793 ResetUIntMap(&context->EffectSlotMap);
1795 context->ActiveSourceCount = 0;
1796 free(context->ActiveSources);
1797 context->ActiveSources = NULL;
1798 context->MaxActiveSources = 0;
1800 context->ActiveEffectSlotCount = 0;
1801 free(context->ActiveEffectSlots);
1802 context->ActiveEffectSlots = NULL;
1803 context->MaxActiveEffectSlots = 0;
1805 ALCdevice_DecRef(context->Device);
1806 context->Device = NULL;
1808 //Invalidate context
1809 memset(context, 0, sizeof(ALCcontext));
1810 free(context);
1813 /* ReleaseContext
1815 * Removes the context reference from the given device and removes it from
1816 * being current on the running thread or globally.
1818 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1820 ALCcontext *volatile*tmp_ctx;
1822 if(pthread_getspecific(LocalContext) == context)
1824 WARN("%p released while current on thread\n", context);
1825 pthread_setspecific(LocalContext, NULL);
1826 ALCcontext_DecRef(context);
1829 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1830 ALCcontext_DecRef(context);
1832 LockDevice(device);
1833 tmp_ctx = &device->ContextList;
1834 while(*tmp_ctx)
1836 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1837 break;
1838 tmp_ctx = &(*tmp_ctx)->next;
1840 UnlockDevice(device);
1842 ALCcontext_DecRef(context);
1845 void ALCcontext_IncRef(ALCcontext *context)
1847 RefCount ref;
1848 ref = IncrementRef(&context->ref);
1849 TRACEREF("%p increasing refcount to %u\n", context, ref);
1852 void ALCcontext_DecRef(ALCcontext *context)
1854 RefCount ref;
1855 ref = DecrementRef(&context->ref);
1856 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1857 if(ref == 0) FreeContext(context);
1860 static void ReleaseThreadCtx(void *ptr)
1862 WARN("%p current for thread being destroyed\n", ptr);
1863 ALCcontext_DecRef(ptr);
1866 /* VerifyContext
1868 * Checks that the given context is valid, and increments its reference count.
1870 static ALCcontext *VerifyContext(ALCcontext *context)
1872 ALCdevice *dev;
1874 LockLists();
1875 dev = DeviceList;
1876 while(dev)
1878 ALCcontext *tmp_ctx = dev->ContextList;
1879 while(tmp_ctx)
1881 if(tmp_ctx == context)
1883 ALCcontext_IncRef(tmp_ctx);
1884 UnlockLists();
1885 return tmp_ctx;
1887 tmp_ctx = tmp_ctx->next;
1889 dev = dev->next;
1891 UnlockLists();
1893 return NULL;
1897 /* GetContextRef
1899 * Returns the currently active context for this thread, and adds a reference
1900 * without locking it.
1902 ALCcontext *GetContextRef(void)
1904 ALCcontext *context;
1906 context = pthread_getspecific(LocalContext);
1907 if(context)
1908 ALCcontext_IncRef(context);
1909 else
1911 LockLists();
1912 context = GlobalContext;
1913 if(context)
1914 ALCcontext_IncRef(context);
1915 UnlockLists();
1918 return context;
1922 /************************************************
1923 * Standard ALC functions
1924 ************************************************/
1926 /* alcGetError
1928 * Return last ALC generated error code for the given device
1930 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1932 ALCenum errorCode;
1934 if(VerifyDevice(device))
1936 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1937 ALCdevice_DecRef(device);
1939 else
1940 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1942 return errorCode;
1946 /* alcSuspendContext
1948 * Not functional
1950 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1952 (void)Context;
1955 /* alcProcessContext
1957 * Not functional
1959 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
1961 (void)Context;
1965 /* alcGetString
1967 * Returns information about the device, and error strings
1969 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
1971 const ALCchar *value = NULL;
1973 switch(param)
1975 case ALC_NO_ERROR:
1976 value = alcNoError;
1977 break;
1979 case ALC_INVALID_ENUM:
1980 value = alcErrInvalidEnum;
1981 break;
1983 case ALC_INVALID_VALUE:
1984 value = alcErrInvalidValue;
1985 break;
1987 case ALC_INVALID_DEVICE:
1988 value = alcErrInvalidDevice;
1989 break;
1991 case ALC_INVALID_CONTEXT:
1992 value = alcErrInvalidContext;
1993 break;
1995 case ALC_OUT_OF_MEMORY:
1996 value = alcErrOutOfMemory;
1997 break;
1999 case ALC_DEVICE_SPECIFIER:
2000 value = alcDefaultName;
2001 break;
2003 case ALC_ALL_DEVICES_SPECIFIER:
2004 if(VerifyDevice(Device))
2006 value = Device->DeviceName;
2007 ALCdevice_DecRef(Device);
2009 else
2011 ProbeAllDevicesList();
2012 value = alcAllDevicesList;
2014 break;
2016 case ALC_CAPTURE_DEVICE_SPECIFIER:
2017 if(VerifyDevice(Device))
2019 value = Device->DeviceName;
2020 ALCdevice_DecRef(Device);
2022 else
2024 ProbeCaptureDeviceList();
2025 value = alcCaptureDeviceList;
2027 break;
2029 /* Default devices are always first in the list */
2030 case ALC_DEFAULT_DEVICE_SPECIFIER:
2031 value = alcDefaultName;
2032 break;
2034 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2035 if(!alcAllDevicesList)
2036 ProbeAllDevicesList();
2038 Device = VerifyDevice(Device);
2040 free(alcDefaultAllDevicesSpecifier);
2041 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2042 alcAllDevicesList : "");
2043 if(!alcDefaultAllDevicesSpecifier)
2044 alcSetError(Device, ALC_OUT_OF_MEMORY);
2046 value = alcDefaultAllDevicesSpecifier;
2047 if(Device) ALCdevice_DecRef(Device);
2048 break;
2050 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2051 if(!alcCaptureDeviceList)
2052 ProbeCaptureDeviceList();
2054 Device = VerifyDevice(Device);
2056 free(alcCaptureDefaultDeviceSpecifier);
2057 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2058 alcCaptureDeviceList : "");
2059 if(!alcCaptureDefaultDeviceSpecifier)
2060 alcSetError(Device, ALC_OUT_OF_MEMORY);
2062 value = alcCaptureDefaultDeviceSpecifier;
2063 if(Device) ALCdevice_DecRef(Device);
2064 break;
2066 case ALC_EXTENSIONS:
2067 if(!VerifyDevice(Device))
2068 value = alcNoDeviceExtList;
2069 else
2071 value = alcExtensionList;
2072 ALCdevice_DecRef(Device);
2074 break;
2076 default:
2077 Device = VerifyDevice(Device);
2078 alcSetError(Device, ALC_INVALID_ENUM);
2079 if(Device) ALCdevice_DecRef(Device);
2080 break;
2083 return value;
2087 /* alcGetIntegerv
2089 * Returns information about the device and the version of OpenAL
2091 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2093 device = VerifyDevice(device);
2095 if(size == 0 || data == NULL)
2097 alcSetError(device, ALC_INVALID_VALUE);
2098 if(device) ALCdevice_DecRef(device);
2099 return;
2102 if(!device)
2104 switch(param)
2106 case ALC_MAJOR_VERSION:
2107 *data = alcMajorVersion;
2108 break;
2109 case ALC_MINOR_VERSION:
2110 *data = alcMinorVersion;
2111 break;
2113 case ALC_ATTRIBUTES_SIZE:
2114 case ALC_ALL_ATTRIBUTES:
2115 case ALC_FREQUENCY:
2116 case ALC_REFRESH:
2117 case ALC_SYNC:
2118 case ALC_MONO_SOURCES:
2119 case ALC_STEREO_SOURCES:
2120 case ALC_CAPTURE_SAMPLES:
2121 case ALC_FORMAT_CHANNELS_SOFT:
2122 case ALC_FORMAT_TYPE_SOFT:
2123 alcSetError(NULL, ALC_INVALID_DEVICE);
2124 break;
2126 default:
2127 alcSetError(NULL, ALC_INVALID_ENUM);
2128 break;
2131 else if(device->Type == Capture)
2133 switch(param)
2135 case ALC_CAPTURE_SAMPLES:
2136 LockLists();
2137 /* Re-validate the device since it may have been closed */
2138 ALCdevice_DecRef(device);
2139 if((device=VerifyDevice(device)) != NULL)
2140 *data = ALCdevice_AvailableSamples(device);
2141 else
2142 alcSetError(NULL, ALC_INVALID_DEVICE);
2143 UnlockLists();
2144 break;
2146 case ALC_CONNECTED:
2147 *data = device->Connected;
2148 break;
2150 default:
2151 alcSetError(device, ALC_INVALID_ENUM);
2152 break;
2155 else /* render device */
2157 switch(param)
2159 case ALC_MAJOR_VERSION:
2160 *data = alcMajorVersion;
2161 break;
2163 case ALC_MINOR_VERSION:
2164 *data = alcMinorVersion;
2165 break;
2167 case ALC_EFX_MAJOR_VERSION:
2168 *data = alcEFXMajorVersion;
2169 break;
2171 case ALC_EFX_MINOR_VERSION:
2172 *data = alcEFXMinorVersion;
2173 break;
2175 case ALC_ATTRIBUTES_SIZE:
2176 *data = 13;
2177 break;
2179 case ALC_ALL_ATTRIBUTES:
2180 if(size < 13)
2181 alcSetError(device, ALC_INVALID_VALUE);
2182 else
2184 int i = 0;
2186 data[i++] = ALC_FREQUENCY;
2187 data[i++] = device->Frequency;
2189 if(device->Type != Loopback)
2191 data[i++] = ALC_REFRESH;
2192 data[i++] = device->Frequency / device->UpdateSize;
2194 data[i++] = ALC_SYNC;
2195 data[i++] = ALC_FALSE;
2197 else
2199 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2200 data[i++] = device->FmtChans;
2202 data[i++] = ALC_FORMAT_TYPE_SOFT;
2203 data[i++] = device->FmtType;
2206 data[i++] = ALC_MONO_SOURCES;
2207 data[i++] = device->NumMonoSources;
2209 data[i++] = ALC_STEREO_SOURCES;
2210 data[i++] = device->NumStereoSources;
2212 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2213 data[i++] = device->NumAuxSends;
2215 data[i++] = 0;
2217 break;
2219 case ALC_FREQUENCY:
2220 *data = device->Frequency;
2221 break;
2223 case ALC_REFRESH:
2224 if(device->Type == Loopback)
2225 alcSetError(device, ALC_INVALID_DEVICE);
2226 else
2227 *data = device->Frequency / device->UpdateSize;
2228 break;
2230 case ALC_SYNC:
2231 if(device->Type == Loopback)
2232 alcSetError(device, ALC_INVALID_DEVICE);
2233 else
2234 *data = ALC_FALSE;
2235 break;
2237 case ALC_FORMAT_CHANNELS_SOFT:
2238 if(device->Type != Loopback)
2239 alcSetError(device, ALC_INVALID_DEVICE);
2240 else
2241 *data = device->FmtChans;
2242 break;
2244 case ALC_FORMAT_TYPE_SOFT:
2245 if(device->Type != Loopback)
2246 alcSetError(device, ALC_INVALID_DEVICE);
2247 else
2248 *data = device->FmtType;
2249 break;
2251 case ALC_MONO_SOURCES:
2252 *data = device->NumMonoSources;
2253 break;
2255 case ALC_STEREO_SOURCES:
2256 *data = device->NumStereoSources;
2257 break;
2259 case ALC_MAX_AUXILIARY_SENDS:
2260 *data = device->NumAuxSends;
2261 break;
2263 case ALC_CONNECTED:
2264 *data = device->Connected;
2265 break;
2267 default:
2268 alcSetError(device, ALC_INVALID_ENUM);
2269 break;
2272 if(device)
2273 ALCdevice_DecRef(device);
2277 /* alcIsExtensionPresent
2279 * Determines if there is support for a particular extension
2281 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2283 ALCboolean bResult = ALC_FALSE;
2285 device = VerifyDevice(device);
2287 if(!extName)
2288 alcSetError(device, ALC_INVALID_VALUE);
2289 else
2291 size_t len = strlen(extName);
2292 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2293 while(ptr && *ptr)
2295 if(strncasecmp(ptr, extName, len) == 0 &&
2296 (ptr[len] == '\0' || isspace(ptr[len])))
2298 bResult = ALC_TRUE;
2299 break;
2301 if((ptr=strchr(ptr, ' ')) != NULL)
2303 do {
2304 ++ptr;
2305 } while(isspace(*ptr));
2309 if(device)
2310 ALCdevice_DecRef(device);
2311 return bResult;
2315 /* alcGetProcAddress
2317 * Retrieves the function address for a particular extension function
2319 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2321 ALCvoid *ptr = NULL;
2323 if(!funcName)
2325 device = VerifyDevice(device);
2326 alcSetError(device, ALC_INVALID_VALUE);
2327 if(device) ALCdevice_DecRef(device);
2329 else
2331 ALsizei i = 0;
2332 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2333 i++;
2334 ptr = alcFunctions[i].address;
2337 return ptr;
2341 /* alcGetEnumValue
2343 * Get the value for a particular ALC enumeration name
2345 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2347 ALCenum val = 0;
2349 if(!enumName)
2351 device = VerifyDevice(device);
2352 alcSetError(device, ALC_INVALID_VALUE);
2353 if(device) ALCdevice_DecRef(device);
2355 else
2357 ALsizei i = 0;
2358 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2359 i++;
2360 val = enumeration[i].value;
2363 return val;
2367 /* alcCreateContext
2369 * Create and attach a context to the given device.
2371 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2373 ALCcontext *ALContext;
2374 ALCenum err;
2376 LockLists();
2377 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2379 UnlockLists();
2380 alcSetError(device, ALC_INVALID_DEVICE);
2381 if(device) ALCdevice_DecRef(device);
2382 return NULL;
2385 device->LastError = ALC_NO_ERROR;
2387 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2389 UnlockLists();
2390 alcSetError(device, err);
2391 if(err == ALC_INVALID_DEVICE)
2392 aluHandleDisconnect(device);
2393 ALCdevice_DecRef(device);
2394 return NULL;
2397 ALContext = calloc(1, sizeof(ALCcontext));
2398 if(ALContext)
2400 ALContext->ref = 1;
2402 ALContext->MaxActiveSources = 256;
2403 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2404 ALContext->MaxActiveSources);
2406 if(!ALContext || !ALContext->ActiveSources)
2408 if(!device->ContextList)
2410 ALCdevice_StopPlayback(device);
2411 device->Flags &= ~DEVICE_RUNNING;
2413 UnlockLists();
2415 free(ALContext);
2416 ALContext = NULL;
2418 alcSetError(device, ALC_OUT_OF_MEMORY);
2419 ALCdevice_DecRef(device);
2420 return NULL;
2423 ALContext->Device = device;
2424 ALCdevice_IncRef(device);
2425 InitContext(ALContext);
2427 do {
2428 ALContext->next = device->ContextList;
2429 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2430 UnlockLists();
2432 ALCdevice_DecRef(device);
2434 TRACE("Created context %p\n", ALContext);
2435 return ALContext;
2438 /* alcDestroyContext
2440 * Remove a context from its device
2442 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2444 ALCdevice *Device;
2446 LockLists();
2447 /* alcGetContextsDevice sets an error for invalid contexts */
2448 Device = alcGetContextsDevice(context);
2449 if(Device)
2451 ReleaseContext(context, Device);
2452 if(!Device->ContextList)
2454 ALCdevice_StopPlayback(Device);
2455 Device->Flags &= ~DEVICE_RUNNING;
2458 UnlockLists();
2462 /* alcGetCurrentContext
2464 * Returns the currently active context on the calling thread
2466 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2468 ALCcontext *Context;
2470 Context = pthread_getspecific(LocalContext);
2471 if(!Context) Context = GlobalContext;
2473 return Context;
2476 /* alcGetThreadContext
2478 * Returns the currently active thread-local context
2480 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2482 ALCcontext *Context;
2483 Context = pthread_getspecific(LocalContext);
2484 return Context;
2488 /* alcMakeContextCurrent
2490 * Makes the given context the active process-wide context, and removes the
2491 * thread-local context for the calling thread.
2493 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2495 /* context must be valid or NULL */
2496 if(context && !(context=VerifyContext(context)))
2498 alcSetError(NULL, ALC_INVALID_CONTEXT);
2499 return ALC_FALSE;
2501 /* context's reference count is already incremented */
2502 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2503 if(context) ALCcontext_DecRef(context);
2505 if((context=pthread_getspecific(LocalContext)) != NULL)
2507 pthread_setspecific(LocalContext, NULL);
2508 ALCcontext_DecRef(context);
2511 return ALC_TRUE;
2514 /* alcSetThreadContext
2516 * Makes the given context the active context for the current thread
2518 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2520 ALCcontext *old;
2522 /* context must be valid or NULL */
2523 if(context && !(context=VerifyContext(context)))
2525 alcSetError(NULL, ALC_INVALID_CONTEXT);
2526 return ALC_FALSE;
2528 /* context's reference count is already incremented */
2529 old = pthread_getspecific(LocalContext);
2530 pthread_setspecific(LocalContext, context);
2531 if(old) ALCcontext_DecRef(old);
2533 return ALC_TRUE;
2537 /* alcGetContextsDevice
2539 * Returns the device that a particular context is attached to
2541 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2543 ALCdevice *Device;
2545 if(!(Context=VerifyContext(Context)))
2547 alcSetError(NULL, ALC_INVALID_CONTEXT);
2548 return NULL;
2550 Device = Context->Device;
2551 ALCcontext_DecRef(Context);
2553 return Device;
2557 /* alcOpenDevice
2559 * Opens the named device.
2561 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2563 const ALCchar *fmt;
2564 ALCdevice *device;
2565 ALCenum err;
2567 DO_INITCONFIG();
2569 if(!PlaybackBackend.name)
2571 alcSetError(NULL, ALC_INVALID_VALUE);
2572 return NULL;
2575 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2576 deviceName = NULL;
2578 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2579 if(!device)
2581 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2582 return NULL;
2585 //Validate device
2586 device->Funcs = &PlaybackBackend.Funcs;
2587 device->ref = 1;
2588 device->Connected = ALC_TRUE;
2589 device->Type = Playback;
2590 InitializeCriticalSection(&device->Mutex);
2591 device->LastError = ALC_NO_ERROR;
2593 device->Flags = 0;
2594 device->Bs2b = NULL;
2595 device->Bs2bLevel = 0;
2596 device->DeviceName = NULL;
2598 device->ContextList = NULL;
2600 device->MaxNoOfSources = 256;
2601 device->AuxiliaryEffectSlotMax = 4;
2602 device->NumAuxSends = MAX_SENDS;
2604 InitUIntMap(&device->BufferMap, ~0);
2605 InitUIntMap(&device->EffectMap, ~0);
2606 InitUIntMap(&device->FilterMap, ~0);
2608 //Set output format
2609 device->FmtChans = DevFmtChannelsDefault;
2610 device->FmtType = DevFmtTypeDefault;
2611 device->Frequency = DEFAULT_OUTPUT_RATE;
2612 device->NumUpdates = 4;
2613 device->UpdateSize = 1024;
2615 if(ConfigValueStr(NULL, "channels", &fmt))
2617 static const struct {
2618 const char name[16];
2619 enum DevFmtChannels chans;
2620 } chanlist[] = {
2621 { "mono", DevFmtMono },
2622 { "stereo", DevFmtStereo },
2623 { "quad", DevFmtQuad },
2624 { "surround51", DevFmtX51 },
2625 { "surround61", DevFmtX61 },
2626 { "surround71", DevFmtX71 },
2628 size_t i;
2630 for(i = 0;i < COUNTOF(chanlist);i++)
2632 if(strcasecmp(chanlist[i].name, fmt) == 0)
2634 device->FmtChans = chanlist[i].chans;
2635 device->Flags |= DEVICE_CHANNELS_REQUEST;
2636 break;
2639 if(i == COUNTOF(chanlist))
2640 ERR("Unsupported channels: %s\n", fmt);
2642 if(ConfigValueStr(NULL, "sample-type", &fmt))
2644 static const struct {
2645 const char name[16];
2646 enum DevFmtType type;
2647 } typelist[] = {
2648 { "int8", DevFmtByte },
2649 { "uint8", DevFmtUByte },
2650 { "int16", DevFmtShort },
2651 { "uint16", DevFmtUShort },
2652 { "int32", DevFmtInt },
2653 { "uint32", DevFmtUInt },
2654 { "float32", DevFmtFloat },
2656 size_t i;
2658 for(i = 0;i < COUNTOF(typelist);i++)
2660 if(strcasecmp(typelist[i].name, fmt) == 0)
2662 device->FmtType = typelist[i].type;
2663 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2664 break;
2667 if(i == COUNTOF(typelist))
2668 ERR("Unsupported sample-type: %s\n", fmt);
2670 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2671 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2672 ConfigValueStr(NULL, "format", &fmt))
2674 static const struct {
2675 const char name[32];
2676 enum DevFmtChannels channels;
2677 enum DevFmtType type;
2678 } formats[] = {
2679 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2680 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2681 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2682 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2683 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2684 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2686 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2687 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2688 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2689 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2690 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2691 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2693 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2694 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2695 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2696 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2697 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2698 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2700 size_t i;
2702 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2703 for(i = 0;i < COUNTOF(formats);i++)
2705 if(strcasecmp(fmt, formats[i].name) == 0)
2707 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2708 device->FmtChans = formats[i].channels;
2709 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2710 device->FmtType = formats[i].type;
2711 device->Flags |= DEVICE_FORMAT_REQUEST;
2712 break;
2715 if(i == COUNTOF(formats))
2716 ERR("Unsupported format: %s\n", fmt);
2718 #undef DEVICE_FORMAT_REQUEST
2720 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2722 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2723 if(device->Frequency < MIN_OUTPUT_RATE)
2724 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2725 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2728 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2729 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2731 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2732 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2734 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2735 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2737 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2738 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2740 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2741 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2743 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2745 device->NumStereoSources = 1;
2746 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2748 // Find a playback device to open
2749 LockLists();
2750 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2752 UnlockLists();
2753 DeleteCriticalSection(&device->Mutex);
2754 free(device);
2755 alcSetError(NULL, err);
2756 return NULL;
2758 UnlockLists();
2760 if(DefaultEffect.type != AL_EFFECT_NULL)
2762 device->DefaultSlot = (ALeffectslot*)(device+1);
2763 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2765 device->DefaultSlot = NULL;
2766 ERR("Failed to initialize the default effect slot\n");
2768 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2770 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2771 device->DefaultSlot = NULL;
2772 ERR("Failed to initialize the default effect\n");
2776 do {
2777 device->next = DeviceList;
2778 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2780 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2781 return device;
2784 /* alcCloseDevice
2786 * Closes the given device.
2788 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2790 ALCdevice *volatile*list;
2791 ALCcontext *ctx;
2793 LockLists();
2794 list = &DeviceList;
2795 while(*list && *list != Device)
2796 list = &(*list)->next;
2798 if(!*list || (*list)->Type == Capture)
2800 alcSetError(*list, ALC_INVALID_DEVICE);
2801 UnlockLists();
2802 return ALC_FALSE;
2805 *list = (*list)->next;
2806 UnlockLists();
2808 while((ctx=Device->ContextList) != NULL)
2810 WARN("Releasing context %p\n", ctx);
2811 ReleaseContext(ctx, Device);
2813 if((Device->Flags&DEVICE_RUNNING))
2814 ALCdevice_StopPlayback(Device);
2815 Device->Flags &= ~DEVICE_RUNNING;
2817 ALCdevice_ClosePlayback(Device);
2819 ALCdevice_DecRef(Device);
2821 return ALC_TRUE;
2825 /************************************************
2826 * ALC capture functions
2827 ************************************************/
2828 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2830 ALCdevice *device = NULL;
2831 ALCenum err;
2833 DO_INITCONFIG();
2835 if(!CaptureBackend.name)
2837 alcSetError(NULL, ALC_INVALID_VALUE);
2838 return NULL;
2841 if(samples <= 0)
2843 alcSetError(NULL, ALC_INVALID_VALUE);
2844 return NULL;
2847 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2848 deviceName = NULL;
2850 device = calloc(1, sizeof(ALCdevice));
2851 if(!device)
2853 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2854 return NULL;
2857 //Validate device
2858 device->Funcs = &CaptureBackend.Funcs;
2859 device->ref = 1;
2860 device->Connected = ALC_TRUE;
2861 device->Type = Capture;
2862 InitializeCriticalSection(&device->Mutex);
2864 InitUIntMap(&device->BufferMap, ~0);
2865 InitUIntMap(&device->EffectMap, ~0);
2866 InitUIntMap(&device->FilterMap, ~0);
2868 device->DeviceName = NULL;
2870 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2871 device->Frequency = frequency;
2873 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2874 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2876 DeleteCriticalSection(&device->Mutex);
2877 free(device);
2878 alcSetError(NULL, ALC_INVALID_ENUM);
2879 return NULL;
2882 device->UpdateSize = samples;
2883 device->NumUpdates = 1;
2885 LockLists();
2886 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2888 UnlockLists();
2889 DeleteCriticalSection(&device->Mutex);
2890 free(device);
2891 alcSetError(NULL, err);
2892 return NULL;
2894 UnlockLists();
2896 do {
2897 device->next = DeviceList;
2898 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2900 TRACE("Created device %p\n", device);
2901 return device;
2904 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2906 ALCdevice *volatile*list;
2908 LockLists();
2909 list = &DeviceList;
2910 while(*list && *list != Device)
2911 list = &(*list)->next;
2913 if(!*list || (*list)->Type != Capture)
2915 alcSetError(*list, ALC_INVALID_DEVICE);
2916 UnlockLists();
2917 return ALC_FALSE;
2920 *list = (*list)->next;
2921 UnlockLists();
2923 ALCdevice_CloseCapture(Device);
2925 ALCdevice_DecRef(Device);
2927 return ALC_TRUE;
2930 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2932 LockLists();
2933 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2935 UnlockLists();
2936 alcSetError(device, ALC_INVALID_DEVICE);
2937 if(device) ALCdevice_DecRef(device);
2938 return;
2940 if(device->Connected)
2942 if(!(device->Flags&DEVICE_RUNNING))
2943 ALCdevice_StartCapture(device);
2944 device->Flags |= DEVICE_RUNNING;
2946 UnlockLists();
2948 ALCdevice_DecRef(device);
2951 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2953 LockLists();
2954 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2956 UnlockLists();
2957 alcSetError(device, ALC_INVALID_DEVICE);
2958 if(device) ALCdevice_DecRef(device);
2959 return;
2961 if((device->Flags&DEVICE_RUNNING))
2962 ALCdevice_StopCapture(device);
2963 device->Flags &= ~DEVICE_RUNNING;
2964 UnlockLists();
2966 ALCdevice_DecRef(device);
2969 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
2971 ALCenum err = ALC_INVALID_DEVICE;
2972 LockLists();
2973 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
2975 err = ALC_INVALID_VALUE;
2976 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
2977 err = ALCdevice_CaptureSamples(device, buffer, samples);
2979 UnlockLists();
2980 if(err != ALC_NO_ERROR)
2981 alcSetError(device, err);
2982 if(device) ALCdevice_DecRef(device);
2986 /************************************************
2987 * ALC loopback functions
2988 ************************************************/
2990 /* alcLoopbackOpenDeviceSOFT
2992 * Open a loopback device, for manual rendering.
2994 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
2996 ALCdevice *device;
2998 DO_INITCONFIG();
3000 /* Make sure the device name, if specified, is us. */
3001 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3003 alcSetError(NULL, ALC_INVALID_VALUE);
3004 return NULL;
3007 device = calloc(1, sizeof(ALCdevice));
3008 if(!device)
3010 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3011 return NULL;
3014 //Validate device
3015 device->Funcs = &BackendLoopback.Funcs;
3016 device->ref = 1;
3017 device->Connected = ALC_TRUE;
3018 device->Type = Loopback;
3019 InitializeCriticalSection(&device->Mutex);
3020 device->LastError = ALC_NO_ERROR;
3022 device->Flags = 0;
3023 device->Bs2b = NULL;
3024 device->Bs2bLevel = 0;
3025 device->DeviceName = NULL;
3027 device->ContextList = NULL;
3029 device->MaxNoOfSources = 256;
3030 device->AuxiliaryEffectSlotMax = 4;
3031 device->NumAuxSends = MAX_SENDS;
3033 InitUIntMap(&device->BufferMap, ~0);
3034 InitUIntMap(&device->EffectMap, ~0);
3035 InitUIntMap(&device->FilterMap, ~0);
3037 //Set output format
3038 device->NumUpdates = 0;
3039 device->UpdateSize = 0;
3041 device->Frequency = DEFAULT_OUTPUT_RATE;
3042 device->FmtChans = DevFmtChannelsDefault;
3043 device->FmtType = DevFmtTypeDefault;
3045 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3046 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3048 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3049 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3051 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3052 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3054 device->NumStereoSources = 1;
3055 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3057 // Open the "backend"
3058 ALCdevice_OpenPlayback(device, "Loopback");
3059 do {
3060 device->next = DeviceList;
3061 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3063 TRACE("Created device %p\n", device);
3064 return device;
3067 /* alcIsRenderFormatSupportedSOFT
3069 * Determines if the loopback device supports the given format for rendering.
3071 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3073 ALCboolean ret = ALC_FALSE;
3075 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3076 alcSetError(device, ALC_INVALID_DEVICE);
3077 else if(freq <= 0)
3078 alcSetError(device, ALC_INVALID_VALUE);
3079 else
3081 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3082 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3083 freq >= MIN_OUTPUT_RATE)
3084 ret = ALC_TRUE;
3086 if(device) ALCdevice_DecRef(device);
3088 return ret;
3091 /* alcRenderSamplesSOFT
3093 * Renders some samples into a buffer, using the format last set by the
3094 * attributes given to alcCreateContext.
3096 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3098 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3099 alcSetError(device, ALC_INVALID_DEVICE);
3100 else if(samples < 0 || (samples > 0 && buffer == NULL))
3101 alcSetError(device, ALC_INVALID_VALUE);
3102 else
3103 aluMixData(device, buffer, samples);
3104 if(device) ALCdevice_DecRef(device);