Add wrapper methods to ensure aligned allocations
[openal-soft/openal-hmr.git] / Alc / ALc.c
blobee2bd8a9a12db006a80bb58cb698f8e13f8e8c8c
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 = 0;
795 #ifdef HAVE_SSE
796 capfilter |= CPU_CAP_SSE;
797 #endif
798 #ifdef HAVE_NEON
799 capfilter |= CPU_CAP_NEON;
800 #endif
801 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
803 if(strcasecmp(str, "all") == 0)
804 capfilter = 0;
805 else
807 size_t len;
808 const char *next = str;
810 i = 0;
811 do {
812 str = next;
813 next = strchr(str, ',');
815 while(isspace(str[0]))
816 str++;
817 if(!str[0] || str[0] == ',')
818 continue;
820 len = (next ? ((size_t)(next-str)) : strlen(str));
821 if(strncasecmp(str, "sse", len) == 0)
822 capfilter &= ~CPU_CAP_SSE;
823 else if(strncasecmp(str, "neon", len) == 0)
824 capfilter &= ~CPU_CAP_NEON;
825 else
826 WARN("Invalid CPU extension \"%s\"\n", str);
827 } while(next++);
830 FillCPUCaps(capfilter);
832 InitHrtf();
834 #ifdef _WIN32
835 RTPrioLevel = 1;
836 #else
837 RTPrioLevel = 0;
838 #endif
839 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
841 if(ConfigValueStr(NULL, "resampler", &str))
843 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
844 DefaultResampler = PointResampler;
845 else if(strcasecmp(str, "linear") == 0)
846 DefaultResampler = LinearResampler;
847 else if(strcasecmp(str, "cubic") == 0)
848 DefaultResampler = CubicResampler;
849 else
851 char *end;
853 n = strtol(str, &end, 0);
854 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
855 DefaultResampler = n;
856 else
857 WARN("Invalid resampler: %s\n", str);
861 str = getenv("ALSOFT_TRAP_ERROR");
862 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 TrapALError = AL_TRUE;
865 TrapALCError = AL_TRUE;
867 else
869 str = getenv("ALSOFT_TRAP_AL_ERROR");
870 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
871 TrapALError = AL_TRUE;
872 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
874 str = getenv("ALSOFT_TRAP_ALC_ERROR");
875 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
876 TrapALCError = ALC_TRUE;
877 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
880 if(ConfigValueFloat("reverb", "boost", &valf))
881 ReverbBoost *= powf(10.0f, valf / 20.0f);
883 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
885 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
886 ConfigValueStr(NULL, "drivers", &devs))
888 int n;
889 size_t len;
890 const char *next = devs;
891 int endlist, delitem;
893 i = 0;
894 do {
895 devs = next;
896 next = strchr(devs, ',');
898 delitem = (devs[0] == '-');
899 if(devs[0] == '-') devs++;
901 if(!devs[0] || devs[0] == ',')
903 endlist = 0;
904 continue;
906 endlist = 1;
908 len = (next ? ((size_t)(next-devs)) : strlen(devs));
909 for(n = i;BackendList[n].Init;n++)
911 if(len == strlen(BackendList[n].name) &&
912 strncmp(BackendList[n].name, devs, len) == 0)
914 if(delitem)
916 do {
917 BackendList[n] = BackendList[n+1];
918 ++n;
919 } while(BackendList[n].Init);
921 else
923 struct BackendInfo Bkp = BackendList[n];
924 while(n > i)
926 BackendList[n] = BackendList[n-1];
927 --n;
929 BackendList[n] = Bkp;
931 i++;
933 break;
936 } while(next++);
938 if(endlist)
940 BackendList[i].name = NULL;
941 BackendList[i].Init = NULL;
942 BackendList[i].Deinit = NULL;
943 BackendList[i].Probe = NULL;
947 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
949 if(!BackendList[i].Init(&BackendList[i].Funcs))
951 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
952 continue;
955 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
956 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
958 PlaybackBackend = BackendList[i];
959 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
961 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
963 CaptureBackend = BackendList[i];
964 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
967 BackendLoopback.Init(&BackendLoopback.Funcs);
969 if(ConfigValueStr(NULL, "excludefx", &str))
971 size_t len;
972 const char *next = str;
974 do {
975 str = next;
976 next = strchr(str, ',');
978 if(!str[0] || next == str)
979 continue;
981 len = (next ? ((size_t)(next-str)) : strlen(str));
982 for(n = 0;EffectList[n].name;n++)
984 if(len == strlen(EffectList[n].name) &&
985 strncmp(EffectList[n].name, str, len) == 0)
986 DisabledEffects[EffectList[n].type] = AL_TRUE;
988 } while(next++);
991 InitEffect(&DefaultEffect);
992 str = getenv("ALSOFT_DEFAULT_REVERB");
993 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
994 LoadReverbPreset(str, &DefaultEffect);
996 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
999 /************************************************
1000 * Library deinitialization
1001 ************************************************/
1002 static void alc_cleanup(void)
1004 ALCdevice *dev;
1006 free(alcAllDevicesList); alcAllDevicesList = NULL;
1007 alcAllDevicesListSize = 0;
1008 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1009 alcCaptureDeviceListSize = 0;
1011 free(alcDefaultAllDevicesSpecifier);
1012 alcDefaultAllDevicesSpecifier = NULL;
1013 free(alcCaptureDefaultDeviceSpecifier);
1014 alcCaptureDefaultDeviceSpecifier = NULL;
1016 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1018 ALCuint num = 0;
1019 do {
1020 num++;
1021 } while((dev=dev->next) != NULL);
1022 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1026 static void alc_deinit_safe(void)
1028 alc_cleanup();
1030 FreeHrtf();
1031 FreeALConfig();
1033 ThunkExit();
1034 DeleteCriticalSection(&ListLock);
1035 pthread_key_delete(LocalContext);
1037 if(LogFile != stderr)
1038 fclose(LogFile);
1039 LogFile = NULL;
1042 static void alc_deinit(void)
1044 int i;
1046 alc_cleanup();
1048 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1049 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1051 for(i = 0;BackendList[i].Deinit;i++)
1052 BackendList[i].Deinit();
1053 BackendLoopback.Deinit();
1055 alc_deinit_safe();
1059 /************************************************
1060 * Device enumeration
1061 ************************************************/
1062 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1064 DO_INITCONFIG();
1066 LockLists();
1067 free(*list);
1068 *list = NULL;
1069 *listsize = 0;
1071 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1072 PlaybackBackend.Probe(type);
1073 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1074 CaptureBackend.Probe(type);
1075 UnlockLists();
1078 static void ProbeAllDevicesList(void)
1079 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1080 static void ProbeCaptureDeviceList(void)
1081 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1084 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1086 size_t len = strlen(name);
1087 void *temp;
1089 if(len == 0)
1090 return;
1092 temp = realloc(*List, (*ListSize) + len + 2);
1093 if(!temp)
1095 ERR("Realloc failed to add %s!\n", name);
1096 return;
1098 *List = temp;
1100 memcpy((*List)+(*ListSize), name, len+1);
1101 *ListSize += len+1;
1102 (*List)[*ListSize] = 0;
1105 #define DECL_APPEND_LIST_FUNC(type) \
1106 void Append##type##List(const ALCchar *name) \
1107 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1109 DECL_APPEND_LIST_FUNC(AllDevices)
1110 DECL_APPEND_LIST_FUNC(CaptureDevice)
1112 #undef DECL_APPEND_LIST_FUNC
1115 /************************************************
1116 * Device format information
1117 ************************************************/
1118 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1120 switch(type)
1122 case DevFmtByte: return "Signed Byte";
1123 case DevFmtUByte: return "Unsigned Byte";
1124 case DevFmtShort: return "Signed Short";
1125 case DevFmtUShort: return "Unsigned Short";
1126 case DevFmtInt: return "Signed Int";
1127 case DevFmtUInt: return "Unsigned Int";
1128 case DevFmtFloat: return "Float";
1130 return "(unknown type)";
1132 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1134 switch(chans)
1136 case DevFmtMono: return "Mono";
1137 case DevFmtStereo: return "Stereo";
1138 case DevFmtQuad: return "Quadraphonic";
1139 case DevFmtX51: return "5.1 Surround";
1140 case DevFmtX51Side: return "5.1 Side";
1141 case DevFmtX61: return "6.1 Surround";
1142 case DevFmtX71: return "7.1 Surround";
1144 return "(unknown channels)";
1147 ALuint BytesFromDevFmt(enum DevFmtType type)
1149 switch(type)
1151 case DevFmtByte: return sizeof(ALbyte);
1152 case DevFmtUByte: return sizeof(ALubyte);
1153 case DevFmtShort: return sizeof(ALshort);
1154 case DevFmtUShort: return sizeof(ALushort);
1155 case DevFmtInt: return sizeof(ALint);
1156 case DevFmtUInt: return sizeof(ALuint);
1157 case DevFmtFloat: return sizeof(ALfloat);
1159 return 0;
1161 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1163 switch(chans)
1165 case DevFmtMono: return 1;
1166 case DevFmtStereo: return 2;
1167 case DevFmtQuad: return 4;
1168 case DevFmtX51: return 6;
1169 case DevFmtX51Side: return 6;
1170 case DevFmtX61: return 7;
1171 case DevFmtX71: return 8;
1173 return 0;
1176 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1177 enum DevFmtType *type)
1179 static const struct {
1180 ALenum format;
1181 enum DevFmtChannels channels;
1182 enum DevFmtType type;
1183 } list[] = {
1184 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1185 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1186 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1188 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1189 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1190 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1192 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1193 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1194 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1196 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1197 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1198 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1200 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1201 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1202 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1204 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1205 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1206 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1208 ALuint i;
1210 for(i = 0;i < COUNTOF(list);i++)
1212 if(list[i].format == format)
1214 *chans = list[i].channels;
1215 *type = list[i].type;
1216 return AL_TRUE;
1220 return AL_FALSE;
1223 static ALCboolean IsValidALCType(ALCenum type)
1225 switch(type)
1227 case ALC_BYTE_SOFT:
1228 case ALC_UNSIGNED_BYTE_SOFT:
1229 case ALC_SHORT_SOFT:
1230 case ALC_UNSIGNED_SHORT_SOFT:
1231 case ALC_INT_SOFT:
1232 case ALC_UNSIGNED_INT_SOFT:
1233 case ALC_FLOAT_SOFT:
1234 return ALC_TRUE;
1236 return ALC_FALSE;
1239 static ALCboolean IsValidALCChannels(ALCenum channels)
1241 switch(channels)
1243 case ALC_MONO_SOFT:
1244 case ALC_STEREO_SOFT:
1245 case ALC_QUAD_SOFT:
1246 case ALC_5POINT1_SOFT:
1247 case ALC_6POINT1_SOFT:
1248 case ALC_7POINT1_SOFT:
1249 return ALC_TRUE;
1251 return ALC_FALSE;
1255 /************************************************
1256 * Miscellaneous ALC helpers
1257 ************************************************/
1259 /* SetDefaultWFXChannelOrder
1261 * Sets the default channel order used by WaveFormatEx.
1263 void SetDefaultWFXChannelOrder(ALCdevice *device)
1265 switch(device->FmtChans)
1267 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1269 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1270 device->DevChannels[1] = FrontRight; break;
1272 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1273 device->DevChannels[1] = FrontRight;
1274 device->DevChannels[2] = BackLeft;
1275 device->DevChannels[3] = BackRight; break;
1277 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1278 device->DevChannels[1] = FrontRight;
1279 device->DevChannels[2] = FrontCenter;
1280 device->DevChannels[3] = LFE;
1281 device->DevChannels[4] = BackLeft;
1282 device->DevChannels[5] = BackRight; break;
1284 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1285 device->DevChannels[1] = FrontRight;
1286 device->DevChannels[2] = FrontCenter;
1287 device->DevChannels[3] = LFE;
1288 device->DevChannels[4] = SideLeft;
1289 device->DevChannels[5] = SideRight; break;
1291 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1292 device->DevChannels[1] = FrontRight;
1293 device->DevChannels[2] = FrontCenter;
1294 device->DevChannels[3] = LFE;
1295 device->DevChannels[4] = BackCenter;
1296 device->DevChannels[5] = SideLeft;
1297 device->DevChannels[6] = SideRight; break;
1299 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1300 device->DevChannels[1] = FrontRight;
1301 device->DevChannels[2] = FrontCenter;
1302 device->DevChannels[3] = LFE;
1303 device->DevChannels[4] = BackLeft;
1304 device->DevChannels[5] = BackRight;
1305 device->DevChannels[6] = SideLeft;
1306 device->DevChannels[7] = SideRight; break;
1310 /* SetDefaultChannelOrder
1312 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1314 void SetDefaultChannelOrder(ALCdevice *device)
1316 switch(device->FmtChans)
1318 case DevFmtX51: 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 return;
1326 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1327 device->DevChannels[1] = FrontRight;
1328 device->DevChannels[2] = BackLeft;
1329 device->DevChannels[3] = BackRight;
1330 device->DevChannels[4] = FrontCenter;
1331 device->DevChannels[5] = LFE;
1332 device->DevChannels[6] = SideLeft;
1333 device->DevChannels[7] = SideRight;
1334 return;
1336 /* Same as WFX order */
1337 case DevFmtMono:
1338 case DevFmtStereo:
1339 case DevFmtQuad:
1340 case DevFmtX51Side:
1341 case DevFmtX61:
1342 break;
1344 SetDefaultWFXChannelOrder(device);
1348 /* alcSetError
1350 * Stores the latest ALC device error
1352 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1354 if(TrapALCError)
1356 #ifdef _WIN32
1357 /* DebugBreak() will cause an exception if there is no debugger */
1358 if(IsDebuggerPresent())
1359 DebugBreak();
1360 #elif defined(SIGTRAP)
1361 raise(SIGTRAP);
1362 #endif
1365 if(device)
1366 device->LastError = errorCode;
1367 else
1368 LastNullDeviceError = errorCode;
1372 /* UpdateDeviceParams
1374 * Updates device parameters according to the attribute list (caller is
1375 * responsible for holding the list lock).
1377 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1379 ALCcontext *context;
1380 enum DevFmtChannels oldChans;
1381 enum DevFmtType oldType;
1382 ALCuint oldFreq;
1383 int oldMode;
1384 ALuint i;
1386 // Check for attributes
1387 if(device->Type == Loopback)
1389 enum {
1390 GotFreq = 1<<0,
1391 GotChans = 1<<1,
1392 GotType = 1<<2,
1393 GotAll = GotFreq|GotChans|GotType
1395 ALCuint freq, numMono, numStereo, numSends;
1396 enum DevFmtChannels schans;
1397 enum DevFmtType stype;
1398 ALCuint attrIdx = 0;
1399 ALCint gotFmt = 0;
1401 if(!attrList)
1403 WARN("Missing attributes for loopback device\n");
1404 return ALC_INVALID_VALUE;
1407 numMono = device->NumMonoSources;
1408 numStereo = device->NumStereoSources;
1409 numSends = device->NumAuxSends;
1410 schans = device->FmtChans;
1411 stype = device->FmtType;
1412 freq = device->Frequency;
1414 while(attrList[attrIdx])
1416 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1418 ALCint val = attrList[attrIdx + 1];
1419 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1420 return ALC_INVALID_VALUE;
1421 schans = val;
1422 gotFmt |= GotChans;
1425 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1427 ALCint val = attrList[attrIdx + 1];
1428 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1429 return ALC_INVALID_VALUE;
1430 stype = val;
1431 gotFmt |= GotType;
1434 if(attrList[attrIdx] == ALC_FREQUENCY)
1436 freq = attrList[attrIdx + 1];
1437 if(freq < MIN_OUTPUT_RATE)
1438 return ALC_INVALID_VALUE;
1439 gotFmt |= GotFreq;
1442 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1444 numStereo = attrList[attrIdx + 1];
1445 if(numStereo > device->MaxNoOfSources)
1446 numStereo = device->MaxNoOfSources;
1448 numMono = device->MaxNoOfSources - numStereo;
1451 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1452 numSends = attrList[attrIdx + 1];
1454 attrIdx += 2;
1457 if(gotFmt != GotAll)
1459 WARN("Missing format for loopback device\n");
1460 return ALC_INVALID_VALUE;
1463 ConfigValueUInt(NULL, "sends", &numSends);
1464 numSends = minu(MAX_SENDS, numSends);
1466 if((device->Flags&DEVICE_RUNNING))
1467 ALCdevice_StopPlayback(device);
1468 device->Flags &= ~DEVICE_RUNNING;
1470 device->Frequency = freq;
1471 device->FmtChans = schans;
1472 device->FmtType = stype;
1473 device->NumMonoSources = numMono;
1474 device->NumStereoSources = numStereo;
1475 device->NumAuxSends = numSends;
1477 else if(attrList && attrList[0])
1479 ALCuint freq, numMono, numStereo, numSends;
1480 ALCuint attrIdx = 0;
1482 /* If a context is already running on the device, stop playback so the
1483 * device attributes can be updated. */
1484 if((device->Flags&DEVICE_RUNNING))
1485 ALCdevice_StopPlayback(device);
1486 device->Flags &= ~DEVICE_RUNNING;
1488 freq = device->Frequency;
1489 numMono = device->NumMonoSources;
1490 numStereo = device->NumStereoSources;
1491 numSends = device->NumAuxSends;
1493 while(attrList[attrIdx])
1495 if(attrList[attrIdx] == ALC_FREQUENCY)
1497 freq = attrList[attrIdx + 1];
1498 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1501 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1503 numStereo = attrList[attrIdx + 1];
1504 if(numStereo > device->MaxNoOfSources)
1505 numStereo = device->MaxNoOfSources;
1507 numMono = device->MaxNoOfSources - numStereo;
1510 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1511 numSends = attrList[attrIdx + 1];
1513 attrIdx += 2;
1516 ConfigValueUInt(NULL, "frequency", &freq);
1517 freq = maxu(freq, MIN_OUTPUT_RATE);
1519 ConfigValueUInt(NULL, "sends", &numSends);
1520 numSends = minu(MAX_SENDS, numSends);
1522 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1523 device->Frequency;
1525 device->Frequency = freq;
1526 device->NumMonoSources = numMono;
1527 device->NumStereoSources = numStereo;
1528 device->NumAuxSends = numSends;
1531 if((device->Flags&DEVICE_RUNNING))
1532 return ALC_NO_ERROR;
1534 oldFreq = device->Frequency;
1535 oldChans = device->FmtChans;
1536 oldType = device->FmtType;
1538 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1539 DevFmtChannelsString(device->FmtChans),
1540 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1541 DevFmtTypeString(device->FmtType),
1542 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1543 device->Frequency,
1544 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1545 device->UpdateSize, device->NumUpdates);
1547 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1548 return ALC_INVALID_DEVICE;
1550 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1552 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1553 DevFmtChannelsString(device->FmtChans));
1554 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1556 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1558 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1559 DevFmtTypeString(device->FmtType));
1560 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1562 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1564 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1565 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1568 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1569 DevFmtChannelsString(device->FmtChans),
1570 DevFmtTypeString(device->FmtType), device->Frequency,
1571 device->UpdateSize, device->NumUpdates);
1573 aluInitPanning(device);
1575 for(i = 0;i < MaxChannels;i++)
1577 device->ClickRemoval[i] = 0.0f;
1578 device->PendingClicks[i] = 0.0f;
1581 device->Hrtf = NULL;
1582 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1583 device->Hrtf = GetHrtf(device);
1584 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1586 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1588 if(!device->Bs2b)
1590 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1591 bs2b_clear(device->Bs2b);
1593 bs2b_set_srate(device->Bs2b, device->Frequency);
1594 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1595 TRACE("BS2B level %d\n", device->Bs2bLevel);
1597 else
1599 free(device->Bs2b);
1600 device->Bs2b = NULL;
1601 TRACE("BS2B disabled\n");
1604 device->Flags &= ~DEVICE_WIDE_STEREO;
1605 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1606 device->Flags |= DEVICE_WIDE_STEREO;
1608 oldMode = SetMixerFPUMode();
1609 LockDevice(device);
1610 context = device->ContextList;
1611 while(context)
1613 ALsizei pos;
1615 context->UpdateSources = AL_FALSE;
1616 LockUIntMapRead(&context->EffectSlotMap);
1617 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1619 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1621 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1623 UnlockUIntMapRead(&context->EffectSlotMap);
1624 UnlockDevice(device);
1625 RestoreFPUMode(oldMode);
1626 return ALC_INVALID_DEVICE;
1628 slot->NeedsUpdate = AL_FALSE;
1629 ALeffectState_Update(slot->EffectState, device, slot);
1631 UnlockUIntMapRead(&context->EffectSlotMap);
1633 LockUIntMapRead(&context->SourceMap);
1634 for(pos = 0;pos < context->SourceMap.size;pos++)
1636 ALsource *source = context->SourceMap.array[pos].value;
1637 ALuint s = device->NumAuxSends;
1638 while(s < MAX_SENDS)
1640 if(source->Send[s].Slot)
1641 DecrementRef(&source->Send[s].Slot->ref);
1642 source->Send[s].Slot = NULL;
1643 source->Send[s].Gain = 1.0f;
1644 source->Send[s].GainHF = 1.0f;
1645 s++;
1647 source->NeedsUpdate = AL_FALSE;
1648 ALsource_Update(source, context);
1650 UnlockUIntMapRead(&context->SourceMap);
1652 context = context->next;
1654 if(device->DefaultSlot)
1656 ALeffectslot *slot = device->DefaultSlot;
1658 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1660 UnlockDevice(device);
1661 RestoreFPUMode(oldMode);
1662 return ALC_INVALID_DEVICE;
1664 slot->NeedsUpdate = AL_FALSE;
1665 ALeffectState_Update(slot->EffectState, device, slot);
1667 UnlockDevice(device);
1668 RestoreFPUMode(oldMode);
1670 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1671 return ALC_INVALID_DEVICE;
1672 device->Flags |= DEVICE_RUNNING;
1674 return ALC_NO_ERROR;
1677 /* FreeDevice
1679 * Frees the device structure, and destroys any objects the app failed to
1680 * delete. Called once there's no more references on the device.
1682 static ALCvoid FreeDevice(ALCdevice *device)
1684 TRACE("%p\n", device);
1686 if(device->DefaultSlot)
1688 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1689 device->DefaultSlot->EffectState = NULL;
1692 if(device->BufferMap.size > 0)
1694 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1695 ReleaseALBuffers(device);
1697 ResetUIntMap(&device->BufferMap);
1699 if(device->EffectMap.size > 0)
1701 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1702 ReleaseALEffects(device);
1704 ResetUIntMap(&device->EffectMap);
1706 if(device->FilterMap.size > 0)
1708 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1709 ReleaseALFilters(device);
1711 ResetUIntMap(&device->FilterMap);
1713 free(device->Bs2b);
1714 device->Bs2b = NULL;
1716 free(device->DeviceName);
1717 device->DeviceName = NULL;
1719 DeleteCriticalSection(&device->Mutex);
1721 free(device);
1725 void ALCdevice_IncRef(ALCdevice *device)
1727 RefCount ref;
1728 ref = IncrementRef(&device->ref);
1729 TRACEREF("%p increasing refcount to %u\n", device, ref);
1732 void ALCdevice_DecRef(ALCdevice *device)
1734 RefCount ref;
1735 ref = DecrementRef(&device->ref);
1736 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1737 if(ref == 0) FreeDevice(device);
1740 /* VerifyDevice
1742 * Checks if the device handle is valid, and increments its ref count if so.
1744 static ALCdevice *VerifyDevice(ALCdevice *device)
1746 ALCdevice *tmpDevice;
1748 if(!device)
1749 return NULL;
1751 LockLists();
1752 tmpDevice = DeviceList;
1753 while(tmpDevice && tmpDevice != device)
1754 tmpDevice = tmpDevice->next;
1756 if(tmpDevice)
1757 ALCdevice_IncRef(tmpDevice);
1758 UnlockLists();
1759 return tmpDevice;
1763 /* InitContext
1765 * Initializes context fields
1767 static ALvoid InitContext(ALCcontext *Context)
1769 ALint i, j;
1771 //Initialise listener
1772 Context->Listener.Gain = 1.0f;
1773 Context->Listener.MetersPerUnit = 1.0f;
1774 Context->Listener.Position[0] = 0.0f;
1775 Context->Listener.Position[1] = 0.0f;
1776 Context->Listener.Position[2] = 0.0f;
1777 Context->Listener.Velocity[0] = 0.0f;
1778 Context->Listener.Velocity[1] = 0.0f;
1779 Context->Listener.Velocity[2] = 0.0f;
1780 Context->Listener.Forward[0] = 0.0f;
1781 Context->Listener.Forward[1] = 0.0f;
1782 Context->Listener.Forward[2] = -1.0f;
1783 Context->Listener.Up[0] = 0.0f;
1784 Context->Listener.Up[1] = 1.0f;
1785 Context->Listener.Up[2] = 0.0f;
1786 for(i = 0;i < 4;i++)
1788 for(j = 0;j < 4;j++)
1789 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1792 //Validate Context
1793 Context->LastError = AL_NO_ERROR;
1794 Context->UpdateSources = AL_FALSE;
1795 Context->ActiveSourceCount = 0;
1796 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1797 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1799 //Set globals
1800 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1801 Context->SourceDistanceModel = AL_FALSE;
1802 Context->DopplerFactor = 1.0f;
1803 Context->DopplerVelocity = 1.0f;
1804 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1805 Context->DeferUpdates = AL_FALSE;
1807 Context->ExtensionList = alExtList;
1811 /* FreeContext
1813 * Cleans up the context, and destroys any remaining objects the app failed to
1814 * delete. Called once there's no more references on the context.
1816 static ALCvoid FreeContext(ALCcontext *context)
1818 TRACE("%p\n", context);
1820 if(context->SourceMap.size > 0)
1822 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1823 ReleaseALSources(context);
1825 ResetUIntMap(&context->SourceMap);
1827 if(context->EffectSlotMap.size > 0)
1829 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1830 ReleaseALAuxiliaryEffectSlots(context);
1832 ResetUIntMap(&context->EffectSlotMap);
1834 context->ActiveSourceCount = 0;
1835 free(context->ActiveSources);
1836 context->ActiveSources = NULL;
1837 context->MaxActiveSources = 0;
1839 context->ActiveEffectSlotCount = 0;
1840 free(context->ActiveEffectSlots);
1841 context->ActiveEffectSlots = NULL;
1842 context->MaxActiveEffectSlots = 0;
1844 ALCdevice_DecRef(context->Device);
1845 context->Device = NULL;
1847 //Invalidate context
1848 memset(context, 0, sizeof(ALCcontext));
1849 free(context);
1852 /* ReleaseContext
1854 * Removes the context reference from the given device and removes it from
1855 * being current on the running thread or globally.
1857 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1859 ALCcontext *volatile*tmp_ctx;
1861 if(pthread_getspecific(LocalContext) == context)
1863 WARN("%p released while current on thread\n", context);
1864 pthread_setspecific(LocalContext, NULL);
1865 ALCcontext_DecRef(context);
1868 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1869 ALCcontext_DecRef(context);
1871 LockDevice(device);
1872 tmp_ctx = &device->ContextList;
1873 while(*tmp_ctx)
1875 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1876 break;
1877 tmp_ctx = &(*tmp_ctx)->next;
1879 UnlockDevice(device);
1881 ALCcontext_DecRef(context);
1884 void ALCcontext_IncRef(ALCcontext *context)
1886 RefCount ref;
1887 ref = IncrementRef(&context->ref);
1888 TRACEREF("%p increasing refcount to %u\n", context, ref);
1891 void ALCcontext_DecRef(ALCcontext *context)
1893 RefCount ref;
1894 ref = DecrementRef(&context->ref);
1895 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1896 if(ref == 0) FreeContext(context);
1899 static void ReleaseThreadCtx(void *ptr)
1901 WARN("%p current for thread being destroyed\n", ptr);
1902 ALCcontext_DecRef(ptr);
1905 /* VerifyContext
1907 * Checks that the given context is valid, and increments its reference count.
1909 static ALCcontext *VerifyContext(ALCcontext *context)
1911 ALCdevice *dev;
1913 LockLists();
1914 dev = DeviceList;
1915 while(dev)
1917 ALCcontext *tmp_ctx = dev->ContextList;
1918 while(tmp_ctx)
1920 if(tmp_ctx == context)
1922 ALCcontext_IncRef(tmp_ctx);
1923 UnlockLists();
1924 return tmp_ctx;
1926 tmp_ctx = tmp_ctx->next;
1928 dev = dev->next;
1930 UnlockLists();
1932 return NULL;
1936 /* GetContextRef
1938 * Returns the currently active context for this thread, and adds a reference
1939 * without locking it.
1941 ALCcontext *GetContextRef(void)
1943 ALCcontext *context;
1945 context = pthread_getspecific(LocalContext);
1946 if(context)
1947 ALCcontext_IncRef(context);
1948 else
1950 LockLists();
1951 context = GlobalContext;
1952 if(context)
1953 ALCcontext_IncRef(context);
1954 UnlockLists();
1957 return context;
1961 /************************************************
1962 * Standard ALC functions
1963 ************************************************/
1965 /* alcGetError
1967 * Return last ALC generated error code for the given device
1969 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1971 ALCenum errorCode;
1973 if(VerifyDevice(device))
1975 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1976 ALCdevice_DecRef(device);
1978 else
1979 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1981 return errorCode;
1985 /* alcSuspendContext
1987 * Not functional
1989 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1991 (void)Context;
1994 /* alcProcessContext
1996 * Not functional
1998 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2000 (void)Context;
2004 /* alcGetString
2006 * Returns information about the device, and error strings
2008 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2010 const ALCchar *value = NULL;
2012 switch(param)
2014 case ALC_NO_ERROR:
2015 value = alcNoError;
2016 break;
2018 case ALC_INVALID_ENUM:
2019 value = alcErrInvalidEnum;
2020 break;
2022 case ALC_INVALID_VALUE:
2023 value = alcErrInvalidValue;
2024 break;
2026 case ALC_INVALID_DEVICE:
2027 value = alcErrInvalidDevice;
2028 break;
2030 case ALC_INVALID_CONTEXT:
2031 value = alcErrInvalidContext;
2032 break;
2034 case ALC_OUT_OF_MEMORY:
2035 value = alcErrOutOfMemory;
2036 break;
2038 case ALC_DEVICE_SPECIFIER:
2039 value = alcDefaultName;
2040 break;
2042 case ALC_ALL_DEVICES_SPECIFIER:
2043 if(VerifyDevice(Device))
2045 value = Device->DeviceName;
2046 ALCdevice_DecRef(Device);
2048 else
2050 ProbeAllDevicesList();
2051 value = alcAllDevicesList;
2053 break;
2055 case ALC_CAPTURE_DEVICE_SPECIFIER:
2056 if(VerifyDevice(Device))
2058 value = Device->DeviceName;
2059 ALCdevice_DecRef(Device);
2061 else
2063 ProbeCaptureDeviceList();
2064 value = alcCaptureDeviceList;
2066 break;
2068 /* Default devices are always first in the list */
2069 case ALC_DEFAULT_DEVICE_SPECIFIER:
2070 value = alcDefaultName;
2071 break;
2073 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2074 if(!alcAllDevicesList)
2075 ProbeAllDevicesList();
2077 Device = VerifyDevice(Device);
2079 free(alcDefaultAllDevicesSpecifier);
2080 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2081 alcAllDevicesList : "");
2082 if(!alcDefaultAllDevicesSpecifier)
2083 alcSetError(Device, ALC_OUT_OF_MEMORY);
2085 value = alcDefaultAllDevicesSpecifier;
2086 if(Device) ALCdevice_DecRef(Device);
2087 break;
2089 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2090 if(!alcCaptureDeviceList)
2091 ProbeCaptureDeviceList();
2093 Device = VerifyDevice(Device);
2095 free(alcCaptureDefaultDeviceSpecifier);
2096 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2097 alcCaptureDeviceList : "");
2098 if(!alcCaptureDefaultDeviceSpecifier)
2099 alcSetError(Device, ALC_OUT_OF_MEMORY);
2101 value = alcCaptureDefaultDeviceSpecifier;
2102 if(Device) ALCdevice_DecRef(Device);
2103 break;
2105 case ALC_EXTENSIONS:
2106 if(!VerifyDevice(Device))
2107 value = alcNoDeviceExtList;
2108 else
2110 value = alcExtensionList;
2111 ALCdevice_DecRef(Device);
2113 break;
2115 default:
2116 Device = VerifyDevice(Device);
2117 alcSetError(Device, ALC_INVALID_ENUM);
2118 if(Device) ALCdevice_DecRef(Device);
2119 break;
2122 return value;
2126 /* alcGetIntegerv
2128 * Returns information about the device and the version of OpenAL
2130 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2132 device = VerifyDevice(device);
2134 if(size == 0 || data == NULL)
2136 alcSetError(device, ALC_INVALID_VALUE);
2137 if(device) ALCdevice_DecRef(device);
2138 return;
2141 if(!device)
2143 switch(param)
2145 case ALC_MAJOR_VERSION:
2146 *data = alcMajorVersion;
2147 break;
2148 case ALC_MINOR_VERSION:
2149 *data = alcMinorVersion;
2150 break;
2152 case ALC_ATTRIBUTES_SIZE:
2153 case ALC_ALL_ATTRIBUTES:
2154 case ALC_FREQUENCY:
2155 case ALC_REFRESH:
2156 case ALC_SYNC:
2157 case ALC_MONO_SOURCES:
2158 case ALC_STEREO_SOURCES:
2159 case ALC_CAPTURE_SAMPLES:
2160 case ALC_FORMAT_CHANNELS_SOFT:
2161 case ALC_FORMAT_TYPE_SOFT:
2162 alcSetError(NULL, ALC_INVALID_DEVICE);
2163 break;
2165 default:
2166 alcSetError(NULL, ALC_INVALID_ENUM);
2167 break;
2170 else if(device->Type == Capture)
2172 switch(param)
2174 case ALC_CAPTURE_SAMPLES:
2175 LockLists();
2176 /* Re-validate the device since it may have been closed */
2177 ALCdevice_DecRef(device);
2178 if((device=VerifyDevice(device)) != NULL)
2179 *data = ALCdevice_AvailableSamples(device);
2180 else
2181 alcSetError(NULL, ALC_INVALID_DEVICE);
2182 UnlockLists();
2183 break;
2185 case ALC_CONNECTED:
2186 *data = device->Connected;
2187 break;
2189 default:
2190 alcSetError(device, ALC_INVALID_ENUM);
2191 break;
2194 else /* render device */
2196 switch(param)
2198 case ALC_MAJOR_VERSION:
2199 *data = alcMajorVersion;
2200 break;
2202 case ALC_MINOR_VERSION:
2203 *data = alcMinorVersion;
2204 break;
2206 case ALC_EFX_MAJOR_VERSION:
2207 *data = alcEFXMajorVersion;
2208 break;
2210 case ALC_EFX_MINOR_VERSION:
2211 *data = alcEFXMinorVersion;
2212 break;
2214 case ALC_ATTRIBUTES_SIZE:
2215 *data = 13;
2216 break;
2218 case ALC_ALL_ATTRIBUTES:
2219 if(size < 13)
2220 alcSetError(device, ALC_INVALID_VALUE);
2221 else
2223 int i = 0;
2225 data[i++] = ALC_FREQUENCY;
2226 data[i++] = device->Frequency;
2228 if(device->Type != Loopback)
2230 data[i++] = ALC_REFRESH;
2231 data[i++] = device->Frequency / device->UpdateSize;
2233 data[i++] = ALC_SYNC;
2234 data[i++] = ALC_FALSE;
2236 else
2238 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2239 data[i++] = device->FmtChans;
2241 data[i++] = ALC_FORMAT_TYPE_SOFT;
2242 data[i++] = device->FmtType;
2245 data[i++] = ALC_MONO_SOURCES;
2246 data[i++] = device->NumMonoSources;
2248 data[i++] = ALC_STEREO_SOURCES;
2249 data[i++] = device->NumStereoSources;
2251 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2252 data[i++] = device->NumAuxSends;
2254 data[i++] = 0;
2256 break;
2258 case ALC_FREQUENCY:
2259 *data = device->Frequency;
2260 break;
2262 case ALC_REFRESH:
2263 if(device->Type == Loopback)
2264 alcSetError(device, ALC_INVALID_DEVICE);
2265 else
2266 *data = device->Frequency / device->UpdateSize;
2267 break;
2269 case ALC_SYNC:
2270 if(device->Type == Loopback)
2271 alcSetError(device, ALC_INVALID_DEVICE);
2272 else
2273 *data = ALC_FALSE;
2274 break;
2276 case ALC_FORMAT_CHANNELS_SOFT:
2277 if(device->Type != Loopback)
2278 alcSetError(device, ALC_INVALID_DEVICE);
2279 else
2280 *data = device->FmtChans;
2281 break;
2283 case ALC_FORMAT_TYPE_SOFT:
2284 if(device->Type != Loopback)
2285 alcSetError(device, ALC_INVALID_DEVICE);
2286 else
2287 *data = device->FmtType;
2288 break;
2290 case ALC_MONO_SOURCES:
2291 *data = device->NumMonoSources;
2292 break;
2294 case ALC_STEREO_SOURCES:
2295 *data = device->NumStereoSources;
2296 break;
2298 case ALC_MAX_AUXILIARY_SENDS:
2299 *data = device->NumAuxSends;
2300 break;
2302 case ALC_CONNECTED:
2303 *data = device->Connected;
2304 break;
2306 default:
2307 alcSetError(device, ALC_INVALID_ENUM);
2308 break;
2311 if(device)
2312 ALCdevice_DecRef(device);
2316 /* alcIsExtensionPresent
2318 * Determines if there is support for a particular extension
2320 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2322 ALCboolean bResult = ALC_FALSE;
2324 device = VerifyDevice(device);
2326 if(!extName)
2327 alcSetError(device, ALC_INVALID_VALUE);
2328 else
2330 size_t len = strlen(extName);
2331 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2332 while(ptr && *ptr)
2334 if(strncasecmp(ptr, extName, len) == 0 &&
2335 (ptr[len] == '\0' || isspace(ptr[len])))
2337 bResult = ALC_TRUE;
2338 break;
2340 if((ptr=strchr(ptr, ' ')) != NULL)
2342 do {
2343 ++ptr;
2344 } while(isspace(*ptr));
2348 if(device)
2349 ALCdevice_DecRef(device);
2350 return bResult;
2354 /* alcGetProcAddress
2356 * Retrieves the function address for a particular extension function
2358 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2360 ALCvoid *ptr = NULL;
2362 if(!funcName)
2364 device = VerifyDevice(device);
2365 alcSetError(device, ALC_INVALID_VALUE);
2366 if(device) ALCdevice_DecRef(device);
2368 else
2370 ALsizei i = 0;
2371 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2372 i++;
2373 ptr = alcFunctions[i].address;
2376 return ptr;
2380 /* alcGetEnumValue
2382 * Get the value for a particular ALC enumeration name
2384 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2386 ALCenum val = 0;
2388 if(!enumName)
2390 device = VerifyDevice(device);
2391 alcSetError(device, ALC_INVALID_VALUE);
2392 if(device) ALCdevice_DecRef(device);
2394 else
2396 ALsizei i = 0;
2397 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2398 i++;
2399 val = enumeration[i].value;
2402 return val;
2406 /* alcCreateContext
2408 * Create and attach a context to the given device.
2410 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2412 ALCcontext *ALContext;
2413 ALCenum err;
2415 LockLists();
2416 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2418 UnlockLists();
2419 alcSetError(device, ALC_INVALID_DEVICE);
2420 if(device) ALCdevice_DecRef(device);
2421 return NULL;
2424 device->LastError = ALC_NO_ERROR;
2426 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2428 UnlockLists();
2429 alcSetError(device, err);
2430 if(err == ALC_INVALID_DEVICE)
2431 aluHandleDisconnect(device);
2432 ALCdevice_DecRef(device);
2433 return NULL;
2436 ALContext = calloc(1, sizeof(ALCcontext));
2437 if(ALContext)
2439 ALContext->ref = 1;
2441 ALContext->MaxActiveSources = 256;
2442 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2443 ALContext->MaxActiveSources);
2445 if(!ALContext || !ALContext->ActiveSources)
2447 if(!device->ContextList)
2449 ALCdevice_StopPlayback(device);
2450 device->Flags &= ~DEVICE_RUNNING;
2452 UnlockLists();
2454 free(ALContext);
2455 ALContext = NULL;
2457 alcSetError(device, ALC_OUT_OF_MEMORY);
2458 ALCdevice_DecRef(device);
2459 return NULL;
2462 ALContext->Device = device;
2463 ALCdevice_IncRef(device);
2464 InitContext(ALContext);
2466 do {
2467 ALContext->next = device->ContextList;
2468 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2469 UnlockLists();
2471 ALCdevice_DecRef(device);
2473 TRACE("Created context %p\n", ALContext);
2474 return ALContext;
2477 /* alcDestroyContext
2479 * Remove a context from its device
2481 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2483 ALCdevice *Device;
2485 LockLists();
2486 /* alcGetContextsDevice sets an error for invalid contexts */
2487 Device = alcGetContextsDevice(context);
2488 if(Device)
2490 ReleaseContext(context, Device);
2491 if(!Device->ContextList)
2493 ALCdevice_StopPlayback(Device);
2494 Device->Flags &= ~DEVICE_RUNNING;
2497 UnlockLists();
2501 /* alcGetCurrentContext
2503 * Returns the currently active context on the calling thread
2505 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2507 ALCcontext *Context;
2509 Context = pthread_getspecific(LocalContext);
2510 if(!Context) Context = GlobalContext;
2512 return Context;
2515 /* alcGetThreadContext
2517 * Returns the currently active thread-local context
2519 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2521 ALCcontext *Context;
2522 Context = pthread_getspecific(LocalContext);
2523 return Context;
2527 /* alcMakeContextCurrent
2529 * Makes the given context the active process-wide context, and removes the
2530 * thread-local context for the calling thread.
2532 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2534 /* context must be valid or NULL */
2535 if(context && !(context=VerifyContext(context)))
2537 alcSetError(NULL, ALC_INVALID_CONTEXT);
2538 return ALC_FALSE;
2540 /* context's reference count is already incremented */
2541 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2542 if(context) ALCcontext_DecRef(context);
2544 if((context=pthread_getspecific(LocalContext)) != NULL)
2546 pthread_setspecific(LocalContext, NULL);
2547 ALCcontext_DecRef(context);
2550 return ALC_TRUE;
2553 /* alcSetThreadContext
2555 * Makes the given context the active context for the current thread
2557 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2559 ALCcontext *old;
2561 /* context must be valid or NULL */
2562 if(context && !(context=VerifyContext(context)))
2564 alcSetError(NULL, ALC_INVALID_CONTEXT);
2565 return ALC_FALSE;
2567 /* context's reference count is already incremented */
2568 old = pthread_getspecific(LocalContext);
2569 pthread_setspecific(LocalContext, context);
2570 if(old) ALCcontext_DecRef(old);
2572 return ALC_TRUE;
2576 /* alcGetContextsDevice
2578 * Returns the device that a particular context is attached to
2580 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2582 ALCdevice *Device;
2584 if(!(Context=VerifyContext(Context)))
2586 alcSetError(NULL, ALC_INVALID_CONTEXT);
2587 return NULL;
2589 Device = Context->Device;
2590 ALCcontext_DecRef(Context);
2592 return Device;
2596 /* alcOpenDevice
2598 * Opens the named device.
2600 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2602 const ALCchar *fmt;
2603 ALCdevice *device;
2604 ALCenum err;
2606 DO_INITCONFIG();
2608 if(!PlaybackBackend.name)
2610 alcSetError(NULL, ALC_INVALID_VALUE);
2611 return NULL;
2614 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2615 deviceName = NULL;
2617 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2618 if(!device)
2620 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2621 return NULL;
2624 //Validate device
2625 device->Funcs = &PlaybackBackend.Funcs;
2626 device->ref = 1;
2627 device->Connected = ALC_TRUE;
2628 device->Type = Playback;
2629 InitializeCriticalSection(&device->Mutex);
2630 device->LastError = ALC_NO_ERROR;
2632 device->Flags = 0;
2633 device->Bs2b = NULL;
2634 device->Bs2bLevel = 0;
2635 device->DeviceName = NULL;
2637 device->ContextList = NULL;
2639 device->MaxNoOfSources = 256;
2640 device->AuxiliaryEffectSlotMax = 4;
2641 device->NumAuxSends = MAX_SENDS;
2643 InitUIntMap(&device->BufferMap, ~0);
2644 InitUIntMap(&device->EffectMap, ~0);
2645 InitUIntMap(&device->FilterMap, ~0);
2647 //Set output format
2648 device->FmtChans = DevFmtChannelsDefault;
2649 device->FmtType = DevFmtTypeDefault;
2650 device->Frequency = DEFAULT_OUTPUT_RATE;
2651 device->NumUpdates = 4;
2652 device->UpdateSize = 1024;
2654 if(ConfigValueStr(NULL, "channels", &fmt))
2656 static const struct {
2657 const char name[16];
2658 enum DevFmtChannels chans;
2659 } chanlist[] = {
2660 { "mono", DevFmtMono },
2661 { "stereo", DevFmtStereo },
2662 { "quad", DevFmtQuad },
2663 { "surround51", DevFmtX51 },
2664 { "surround61", DevFmtX61 },
2665 { "surround71", DevFmtX71 },
2667 size_t i;
2669 for(i = 0;i < COUNTOF(chanlist);i++)
2671 if(strcasecmp(chanlist[i].name, fmt) == 0)
2673 device->FmtChans = chanlist[i].chans;
2674 device->Flags |= DEVICE_CHANNELS_REQUEST;
2675 break;
2678 if(i == COUNTOF(chanlist))
2679 ERR("Unsupported channels: %s\n", fmt);
2681 if(ConfigValueStr(NULL, "sample-type", &fmt))
2683 static const struct {
2684 const char name[16];
2685 enum DevFmtType type;
2686 } typelist[] = {
2687 { "int8", DevFmtByte },
2688 { "uint8", DevFmtUByte },
2689 { "int16", DevFmtShort },
2690 { "uint16", DevFmtUShort },
2691 { "int32", DevFmtInt },
2692 { "uint32", DevFmtUInt },
2693 { "float32", DevFmtFloat },
2695 size_t i;
2697 for(i = 0;i < COUNTOF(typelist);i++)
2699 if(strcasecmp(typelist[i].name, fmt) == 0)
2701 device->FmtType = typelist[i].type;
2702 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2703 break;
2706 if(i == COUNTOF(typelist))
2707 ERR("Unsupported sample-type: %s\n", fmt);
2709 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2710 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2711 ConfigValueStr(NULL, "format", &fmt))
2713 static const struct {
2714 const char name[32];
2715 enum DevFmtChannels channels;
2716 enum DevFmtType type;
2717 } formats[] = {
2718 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2719 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2720 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2721 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2722 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2723 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2725 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2726 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2727 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2728 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2729 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2730 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2732 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2733 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2734 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2735 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2736 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2737 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2739 size_t i;
2741 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2742 for(i = 0;i < COUNTOF(formats);i++)
2744 if(strcasecmp(fmt, formats[i].name) == 0)
2746 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2747 device->FmtChans = formats[i].channels;
2748 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2749 device->FmtType = formats[i].type;
2750 device->Flags |= DEVICE_FORMAT_REQUEST;
2751 break;
2754 if(i == COUNTOF(formats))
2755 ERR("Unsupported format: %s\n", fmt);
2757 #undef DEVICE_FORMAT_REQUEST
2759 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2761 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2762 if(device->Frequency < MIN_OUTPUT_RATE)
2763 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2764 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2767 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2768 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2770 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2771 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2773 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2774 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2776 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2777 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2779 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2780 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2782 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2784 device->NumStereoSources = 1;
2785 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2787 // Find a playback device to open
2788 LockLists();
2789 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2791 UnlockLists();
2792 DeleteCriticalSection(&device->Mutex);
2793 free(device);
2794 alcSetError(NULL, err);
2795 return NULL;
2797 UnlockLists();
2799 if(DefaultEffect.type != AL_EFFECT_NULL)
2801 device->DefaultSlot = (ALeffectslot*)(device+1);
2802 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2804 device->DefaultSlot = NULL;
2805 ERR("Failed to initialize the default effect slot\n");
2807 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2809 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2810 device->DefaultSlot = NULL;
2811 ERR("Failed to initialize the default effect\n");
2815 do {
2816 device->next = DeviceList;
2817 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2819 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2820 return device;
2823 /* alcCloseDevice
2825 * Closes the given device.
2827 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2829 ALCdevice *volatile*list;
2830 ALCcontext *ctx;
2832 LockLists();
2833 list = &DeviceList;
2834 while(*list && *list != Device)
2835 list = &(*list)->next;
2837 if(!*list || (*list)->Type == Capture)
2839 alcSetError(*list, ALC_INVALID_DEVICE);
2840 UnlockLists();
2841 return ALC_FALSE;
2844 *list = (*list)->next;
2845 UnlockLists();
2847 while((ctx=Device->ContextList) != NULL)
2849 WARN("Releasing context %p\n", ctx);
2850 ReleaseContext(ctx, Device);
2852 if((Device->Flags&DEVICE_RUNNING))
2853 ALCdevice_StopPlayback(Device);
2854 Device->Flags &= ~DEVICE_RUNNING;
2856 ALCdevice_ClosePlayback(Device);
2858 ALCdevice_DecRef(Device);
2860 return ALC_TRUE;
2864 /************************************************
2865 * ALC capture functions
2866 ************************************************/
2867 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2869 ALCdevice *device = NULL;
2870 ALCenum err;
2872 DO_INITCONFIG();
2874 if(!CaptureBackend.name)
2876 alcSetError(NULL, ALC_INVALID_VALUE);
2877 return NULL;
2880 if(samples <= 0)
2882 alcSetError(NULL, ALC_INVALID_VALUE);
2883 return NULL;
2886 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2887 deviceName = NULL;
2889 device = calloc(1, sizeof(ALCdevice));
2890 if(!device)
2892 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2893 return NULL;
2896 //Validate device
2897 device->Funcs = &CaptureBackend.Funcs;
2898 device->ref = 1;
2899 device->Connected = ALC_TRUE;
2900 device->Type = Capture;
2901 InitializeCriticalSection(&device->Mutex);
2903 InitUIntMap(&device->BufferMap, ~0);
2904 InitUIntMap(&device->EffectMap, ~0);
2905 InitUIntMap(&device->FilterMap, ~0);
2907 device->DeviceName = NULL;
2909 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2910 device->Frequency = frequency;
2912 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2913 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2915 DeleteCriticalSection(&device->Mutex);
2916 free(device);
2917 alcSetError(NULL, ALC_INVALID_ENUM);
2918 return NULL;
2921 device->UpdateSize = samples;
2922 device->NumUpdates = 1;
2924 LockLists();
2925 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2927 UnlockLists();
2928 DeleteCriticalSection(&device->Mutex);
2929 free(device);
2930 alcSetError(NULL, err);
2931 return NULL;
2933 UnlockLists();
2935 do {
2936 device->next = DeviceList;
2937 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2939 TRACE("Created device %p\n", device);
2940 return device;
2943 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2945 ALCdevice *volatile*list;
2947 LockLists();
2948 list = &DeviceList;
2949 while(*list && *list != Device)
2950 list = &(*list)->next;
2952 if(!*list || (*list)->Type != Capture)
2954 alcSetError(*list, ALC_INVALID_DEVICE);
2955 UnlockLists();
2956 return ALC_FALSE;
2959 *list = (*list)->next;
2960 UnlockLists();
2962 ALCdevice_CloseCapture(Device);
2964 ALCdevice_DecRef(Device);
2966 return ALC_TRUE;
2969 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2971 LockLists();
2972 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2974 UnlockLists();
2975 alcSetError(device, ALC_INVALID_DEVICE);
2976 if(device) ALCdevice_DecRef(device);
2977 return;
2979 if(device->Connected)
2981 if(!(device->Flags&DEVICE_RUNNING))
2982 ALCdevice_StartCapture(device);
2983 device->Flags |= DEVICE_RUNNING;
2985 UnlockLists();
2987 ALCdevice_DecRef(device);
2990 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2992 LockLists();
2993 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2995 UnlockLists();
2996 alcSetError(device, ALC_INVALID_DEVICE);
2997 if(device) ALCdevice_DecRef(device);
2998 return;
3000 if((device->Flags&DEVICE_RUNNING))
3001 ALCdevice_StopCapture(device);
3002 device->Flags &= ~DEVICE_RUNNING;
3003 UnlockLists();
3005 ALCdevice_DecRef(device);
3008 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3010 ALCenum err = ALC_INVALID_DEVICE;
3011 LockLists();
3012 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3014 err = ALC_INVALID_VALUE;
3015 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3016 err = ALCdevice_CaptureSamples(device, buffer, samples);
3018 UnlockLists();
3019 if(err != ALC_NO_ERROR)
3020 alcSetError(device, err);
3021 if(device) ALCdevice_DecRef(device);
3025 /************************************************
3026 * ALC loopback functions
3027 ************************************************/
3029 /* alcLoopbackOpenDeviceSOFT
3031 * Open a loopback device, for manual rendering.
3033 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3035 ALCdevice *device;
3037 DO_INITCONFIG();
3039 /* Make sure the device name, if specified, is us. */
3040 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3042 alcSetError(NULL, ALC_INVALID_VALUE);
3043 return NULL;
3046 device = calloc(1, sizeof(ALCdevice));
3047 if(!device)
3049 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3050 return NULL;
3053 //Validate device
3054 device->Funcs = &BackendLoopback.Funcs;
3055 device->ref = 1;
3056 device->Connected = ALC_TRUE;
3057 device->Type = Loopback;
3058 InitializeCriticalSection(&device->Mutex);
3059 device->LastError = ALC_NO_ERROR;
3061 device->Flags = 0;
3062 device->Bs2b = NULL;
3063 device->Bs2bLevel = 0;
3064 device->DeviceName = NULL;
3066 device->ContextList = NULL;
3068 device->MaxNoOfSources = 256;
3069 device->AuxiliaryEffectSlotMax = 4;
3070 device->NumAuxSends = MAX_SENDS;
3072 InitUIntMap(&device->BufferMap, ~0);
3073 InitUIntMap(&device->EffectMap, ~0);
3074 InitUIntMap(&device->FilterMap, ~0);
3076 //Set output format
3077 device->NumUpdates = 0;
3078 device->UpdateSize = 0;
3080 device->Frequency = DEFAULT_OUTPUT_RATE;
3081 device->FmtChans = DevFmtChannelsDefault;
3082 device->FmtType = DevFmtTypeDefault;
3084 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3085 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3087 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3088 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3090 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3091 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3093 device->NumStereoSources = 1;
3094 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3096 // Open the "backend"
3097 ALCdevice_OpenPlayback(device, "Loopback");
3098 do {
3099 device->next = DeviceList;
3100 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3102 TRACE("Created device %p\n", device);
3103 return device;
3106 /* alcIsRenderFormatSupportedSOFT
3108 * Determines if the loopback device supports the given format for rendering.
3110 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3112 ALCboolean ret = ALC_FALSE;
3114 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3115 alcSetError(device, ALC_INVALID_DEVICE);
3116 else if(freq <= 0)
3117 alcSetError(device, ALC_INVALID_VALUE);
3118 else
3120 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3121 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3122 freq >= MIN_OUTPUT_RATE)
3123 ret = ALC_TRUE;
3125 if(device) ALCdevice_DecRef(device);
3127 return ret;
3130 /* alcRenderSamplesSOFT
3132 * Renders some samples into a buffer, using the format last set by the
3133 * attributes given to alcCreateContext.
3135 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3137 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3138 alcSetError(device, ALC_INVALID_DEVICE);
3139 else if(samples < 0 || (samples > 0 && buffer == NULL))
3140 alcSetError(device, ALC_INVALID_VALUE);
3141 else
3142 aluMixData(device, buffer, samples);
3143 if(device) ALCdevice_DecRef(device);