Make sure device buffers are 16-byte aligned
[openal-soft/openal-hmr.git] / Alc / ALc.c
blob7731684390d88a79622b7e8a050aaf50272b4139
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, 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 DECL(alGetSourcedSOFT),
259 DECL(alGetSource3dSOFT),
260 DECL(alGetSourcedvSOFT),
261 DECL(alGetSourcei64SOFT),
262 DECL(alGetSource3i64SOFT),
263 DECL(alGetSourcei64vSOFT),
265 { NULL, NULL }
267 #undef DECL
269 #define DECL(x) { #x, (x) }
270 static const ALCenums enumeration[] = {
271 DECL(ALC_INVALID),
272 DECL(ALC_FALSE),
273 DECL(ALC_TRUE),
275 DECL(ALC_MAJOR_VERSION),
276 DECL(ALC_MINOR_VERSION),
277 DECL(ALC_ATTRIBUTES_SIZE),
278 DECL(ALC_ALL_ATTRIBUTES),
279 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
280 DECL(ALC_DEVICE_SPECIFIER),
281 DECL(ALC_ALL_DEVICES_SPECIFIER),
282 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
283 DECL(ALC_EXTENSIONS),
284 DECL(ALC_FREQUENCY),
285 DECL(ALC_REFRESH),
286 DECL(ALC_SYNC),
287 DECL(ALC_MONO_SOURCES),
288 DECL(ALC_STEREO_SOURCES),
289 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
290 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
291 DECL(ALC_CAPTURE_SAMPLES),
292 DECL(ALC_CONNECTED),
294 DECL(ALC_EFX_MAJOR_VERSION),
295 DECL(ALC_EFX_MINOR_VERSION),
296 DECL(ALC_MAX_AUXILIARY_SENDS),
298 DECL(ALC_FORMAT_CHANNELS_SOFT),
299 DECL(ALC_FORMAT_TYPE_SOFT),
301 DECL(ALC_MONO_SOFT),
302 DECL(ALC_STEREO_SOFT),
303 DECL(ALC_QUAD_SOFT),
304 DECL(ALC_5POINT1_SOFT),
305 DECL(ALC_6POINT1_SOFT),
306 DECL(ALC_7POINT1_SOFT),
308 DECL(ALC_BYTE_SOFT),
309 DECL(ALC_UNSIGNED_BYTE_SOFT),
310 DECL(ALC_SHORT_SOFT),
311 DECL(ALC_UNSIGNED_SHORT_SOFT),
312 DECL(ALC_INT_SOFT),
313 DECL(ALC_UNSIGNED_INT_SOFT),
314 DECL(ALC_FLOAT_SOFT),
316 DECL(ALC_NO_ERROR),
317 DECL(ALC_INVALID_DEVICE),
318 DECL(ALC_INVALID_CONTEXT),
319 DECL(ALC_INVALID_ENUM),
320 DECL(ALC_INVALID_VALUE),
321 DECL(ALC_OUT_OF_MEMORY),
324 DECL(AL_INVALID),
325 DECL(AL_NONE),
326 DECL(AL_FALSE),
327 DECL(AL_TRUE),
329 DECL(AL_SOURCE_RELATIVE),
330 DECL(AL_CONE_INNER_ANGLE),
331 DECL(AL_CONE_OUTER_ANGLE),
332 DECL(AL_PITCH),
333 DECL(AL_POSITION),
334 DECL(AL_DIRECTION),
335 DECL(AL_VELOCITY),
336 DECL(AL_LOOPING),
337 DECL(AL_BUFFER),
338 DECL(AL_GAIN),
339 DECL(AL_MIN_GAIN),
340 DECL(AL_MAX_GAIN),
341 DECL(AL_ORIENTATION),
342 DECL(AL_REFERENCE_DISTANCE),
343 DECL(AL_ROLLOFF_FACTOR),
344 DECL(AL_CONE_OUTER_GAIN),
345 DECL(AL_MAX_DISTANCE),
346 DECL(AL_SEC_OFFSET),
347 DECL(AL_SAMPLE_OFFSET),
348 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
349 DECL(AL_BYTE_OFFSET),
350 DECL(AL_BYTE_RW_OFFSETS_SOFT),
351 DECL(AL_SOURCE_TYPE),
352 DECL(AL_STATIC),
353 DECL(AL_STREAMING),
354 DECL(AL_UNDETERMINED),
355 DECL(AL_METERS_PER_UNIT),
356 DECL(AL_DIRECT_CHANNELS_SOFT),
358 DECL(AL_DIRECT_FILTER),
359 DECL(AL_AUXILIARY_SEND_FILTER),
360 DECL(AL_AIR_ABSORPTION_FACTOR),
361 DECL(AL_ROOM_ROLLOFF_FACTOR),
362 DECL(AL_CONE_OUTER_GAINHF),
363 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
364 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
365 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
367 DECL(AL_SOURCE_STATE),
368 DECL(AL_INITIAL),
369 DECL(AL_PLAYING),
370 DECL(AL_PAUSED),
371 DECL(AL_STOPPED),
373 DECL(AL_BUFFERS_QUEUED),
374 DECL(AL_BUFFERS_PROCESSED),
376 DECL(AL_FORMAT_MONO8),
377 DECL(AL_FORMAT_MONO16),
378 DECL(AL_FORMAT_MONO_FLOAT32),
379 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
380 DECL(AL_FORMAT_STEREO8),
381 DECL(AL_FORMAT_STEREO16),
382 DECL(AL_FORMAT_STEREO_FLOAT32),
383 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
384 DECL(AL_FORMAT_MONO_IMA4),
385 DECL(AL_FORMAT_STEREO_IMA4),
386 DECL(AL_FORMAT_QUAD8_LOKI),
387 DECL(AL_FORMAT_QUAD16_LOKI),
388 DECL(AL_FORMAT_QUAD8),
389 DECL(AL_FORMAT_QUAD16),
390 DECL(AL_FORMAT_QUAD32),
391 DECL(AL_FORMAT_51CHN8),
392 DECL(AL_FORMAT_51CHN16),
393 DECL(AL_FORMAT_51CHN32),
394 DECL(AL_FORMAT_61CHN8),
395 DECL(AL_FORMAT_61CHN16),
396 DECL(AL_FORMAT_61CHN32),
397 DECL(AL_FORMAT_71CHN8),
398 DECL(AL_FORMAT_71CHN16),
399 DECL(AL_FORMAT_71CHN32),
400 DECL(AL_FORMAT_REAR8),
401 DECL(AL_FORMAT_REAR16),
402 DECL(AL_FORMAT_REAR32),
403 DECL(AL_FORMAT_MONO_MULAW),
404 DECL(AL_FORMAT_MONO_MULAW_EXT),
405 DECL(AL_FORMAT_STEREO_MULAW),
406 DECL(AL_FORMAT_STEREO_MULAW_EXT),
407 DECL(AL_FORMAT_QUAD_MULAW),
408 DECL(AL_FORMAT_51CHN_MULAW),
409 DECL(AL_FORMAT_61CHN_MULAW),
410 DECL(AL_FORMAT_71CHN_MULAW),
411 DECL(AL_FORMAT_REAR_MULAW),
412 DECL(AL_FORMAT_MONO_ALAW_EXT),
413 DECL(AL_FORMAT_STEREO_ALAW_EXT),
415 DECL(AL_MONO8_SOFT),
416 DECL(AL_MONO16_SOFT),
417 DECL(AL_MONO32F_SOFT),
418 DECL(AL_STEREO8_SOFT),
419 DECL(AL_STEREO16_SOFT),
420 DECL(AL_STEREO32F_SOFT),
421 DECL(AL_QUAD8_SOFT),
422 DECL(AL_QUAD16_SOFT),
423 DECL(AL_QUAD32F_SOFT),
424 DECL(AL_REAR8_SOFT),
425 DECL(AL_REAR16_SOFT),
426 DECL(AL_REAR32F_SOFT),
427 DECL(AL_5POINT1_8_SOFT),
428 DECL(AL_5POINT1_16_SOFT),
429 DECL(AL_5POINT1_32F_SOFT),
430 DECL(AL_6POINT1_8_SOFT),
431 DECL(AL_6POINT1_16_SOFT),
432 DECL(AL_6POINT1_32F_SOFT),
433 DECL(AL_7POINT1_8_SOFT),
434 DECL(AL_7POINT1_16_SOFT),
435 DECL(AL_7POINT1_32F_SOFT),
437 DECL(AL_MONO_SOFT),
438 DECL(AL_STEREO_SOFT),
439 DECL(AL_QUAD_SOFT),
440 DECL(AL_REAR_SOFT),
441 DECL(AL_5POINT1_SOFT),
442 DECL(AL_6POINT1_SOFT),
443 DECL(AL_7POINT1_SOFT),
445 DECL(AL_BYTE_SOFT),
446 DECL(AL_UNSIGNED_BYTE_SOFT),
447 DECL(AL_SHORT_SOFT),
448 DECL(AL_UNSIGNED_SHORT_SOFT),
449 DECL(AL_INT_SOFT),
450 DECL(AL_UNSIGNED_INT_SOFT),
451 DECL(AL_FLOAT_SOFT),
452 DECL(AL_DOUBLE_SOFT),
453 DECL(AL_BYTE3_SOFT),
454 DECL(AL_UNSIGNED_BYTE3_SOFT),
456 DECL(AL_FREQUENCY),
457 DECL(AL_BITS),
458 DECL(AL_CHANNELS),
459 DECL(AL_SIZE),
460 DECL(AL_INTERNAL_FORMAT_SOFT),
461 DECL(AL_BYTE_LENGTH_SOFT),
462 DECL(AL_SAMPLE_LENGTH_SOFT),
463 DECL(AL_SEC_LENGTH_SOFT),
465 DECL(AL_UNUSED),
466 DECL(AL_PENDING),
467 DECL(AL_PROCESSED),
469 DECL(AL_NO_ERROR),
470 DECL(AL_INVALID_NAME),
471 DECL(AL_INVALID_ENUM),
472 DECL(AL_INVALID_VALUE),
473 DECL(AL_INVALID_OPERATION),
474 DECL(AL_OUT_OF_MEMORY),
476 DECL(AL_VENDOR),
477 DECL(AL_VERSION),
478 DECL(AL_RENDERER),
479 DECL(AL_EXTENSIONS),
481 DECL(AL_DOPPLER_FACTOR),
482 DECL(AL_DOPPLER_VELOCITY),
483 DECL(AL_DISTANCE_MODEL),
484 DECL(AL_SPEED_OF_SOUND),
485 DECL(AL_SOURCE_DISTANCE_MODEL),
486 DECL(AL_DEFERRED_UPDATES_SOFT),
488 DECL(AL_INVERSE_DISTANCE),
489 DECL(AL_INVERSE_DISTANCE_CLAMPED),
490 DECL(AL_LINEAR_DISTANCE),
491 DECL(AL_LINEAR_DISTANCE_CLAMPED),
492 DECL(AL_EXPONENT_DISTANCE),
493 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
495 DECL(AL_FILTER_TYPE),
496 DECL(AL_FILTER_NULL),
497 DECL(AL_FILTER_LOWPASS),
498 #if 0
499 DECL(AL_FILTER_HIGHPASS),
500 DECL(AL_FILTER_BANDPASS),
501 #endif
503 DECL(AL_LOWPASS_GAIN),
504 DECL(AL_LOWPASS_GAINHF),
506 DECL(AL_EFFECT_TYPE),
507 DECL(AL_EFFECT_NULL),
508 DECL(AL_EFFECT_REVERB),
509 DECL(AL_EFFECT_EAXREVERB),
510 #if 0
511 DECL(AL_EFFECT_CHORUS),
512 DECL(AL_EFFECT_DISTORTION),
513 #endif
514 DECL(AL_EFFECT_ECHO),
515 #if 0
516 DECL(AL_EFFECT_FLANGER),
517 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
518 DECL(AL_EFFECT_VOCAL_MORPHER),
519 DECL(AL_EFFECT_PITCH_SHIFTER),
520 #endif
521 DECL(AL_EFFECT_RING_MODULATOR),
522 #if 0
523 DECL(AL_EFFECT_AUTOWAH),
524 DECL(AL_EFFECT_COMPRESSOR),
525 DECL(AL_EFFECT_EQUALIZER),
526 #endif
527 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
528 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
530 DECL(AL_EAXREVERB_DENSITY),
531 DECL(AL_EAXREVERB_DIFFUSION),
532 DECL(AL_EAXREVERB_GAIN),
533 DECL(AL_EAXREVERB_GAINHF),
534 DECL(AL_EAXREVERB_GAINLF),
535 DECL(AL_EAXREVERB_DECAY_TIME),
536 DECL(AL_EAXREVERB_DECAY_HFRATIO),
537 DECL(AL_EAXREVERB_DECAY_LFRATIO),
538 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
539 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
540 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
541 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
542 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
543 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
544 DECL(AL_EAXREVERB_ECHO_TIME),
545 DECL(AL_EAXREVERB_ECHO_DEPTH),
546 DECL(AL_EAXREVERB_MODULATION_TIME),
547 DECL(AL_EAXREVERB_MODULATION_DEPTH),
548 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
549 DECL(AL_EAXREVERB_HFREFERENCE),
550 DECL(AL_EAXREVERB_LFREFERENCE),
551 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
552 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
554 DECL(AL_REVERB_DENSITY),
555 DECL(AL_REVERB_DIFFUSION),
556 DECL(AL_REVERB_GAIN),
557 DECL(AL_REVERB_GAINHF),
558 DECL(AL_REVERB_DECAY_TIME),
559 DECL(AL_REVERB_DECAY_HFRATIO),
560 DECL(AL_REVERB_REFLECTIONS_GAIN),
561 DECL(AL_REVERB_REFLECTIONS_DELAY),
562 DECL(AL_REVERB_LATE_REVERB_GAIN),
563 DECL(AL_REVERB_LATE_REVERB_DELAY),
564 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
565 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
566 DECL(AL_REVERB_DECAY_HFLIMIT),
568 DECL(AL_ECHO_DELAY),
569 DECL(AL_ECHO_LRDELAY),
570 DECL(AL_ECHO_DAMPING),
571 DECL(AL_ECHO_FEEDBACK),
572 DECL(AL_ECHO_SPREAD),
574 DECL(AL_RING_MODULATOR_FREQUENCY),
575 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
576 DECL(AL_RING_MODULATOR_WAVEFORM),
578 DECL(AL_DEDICATED_GAIN),
580 { NULL, (ALCenum)0 }
582 #undef DECL
584 static const ALCchar alcNoError[] = "No Error";
585 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
586 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
587 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
588 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
589 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
592 /************************************************
593 * Global variables
594 ************************************************/
596 /* Enumerated device names */
597 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
598 static ALCchar *alcAllDevicesList;
599 static ALCchar *alcCaptureDeviceList;
600 /* Sizes only include the first ending null character, not the second */
601 static size_t alcAllDevicesListSize;
602 static size_t alcCaptureDeviceListSize;
604 /* Default is always the first in the list */
605 static ALCchar *alcDefaultAllDevicesSpecifier;
606 static ALCchar *alcCaptureDefaultDeviceSpecifier;
608 /* Default context extensions */
609 static const ALchar alExtList[] =
610 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
611 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
612 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
613 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
614 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
616 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
618 /* Thread-local current context */
619 static pthread_key_t LocalContext;
620 /* Process-wide current context */
621 static ALCcontext *volatile GlobalContext = NULL;
623 /* Mixing thread piority level */
624 ALint RTPrioLevel;
626 FILE *LogFile;
627 #ifdef _DEBUG
628 enum LogLevel LogLevel = LogWarning;
629 #else
630 enum LogLevel LogLevel = LogError;
631 #endif
633 /* Flag to trap ALC device errors */
634 static ALCboolean TrapALCError = ALC_FALSE;
636 /* One-time configuration init control */
637 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
639 /* Default effect that applies to sources that don't have an effect on send 0 */
640 static ALeffect DefaultEffect;
643 /************************************************
644 * ALC information
645 ************************************************/
646 static const ALCchar alcNoDeviceExtList[] =
647 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
648 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
649 static const ALCchar alcExtensionList[] =
650 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
651 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
652 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
653 static const ALCint alcMajorVersion = 1;
654 static const ALCint alcMinorVersion = 1;
656 static const ALCint alcEFXMajorVersion = 1;
657 static const ALCint alcEFXMinorVersion = 0;
660 /************************************************
661 * Device lists
662 ************************************************/
663 static ALCdevice *volatile DeviceList = NULL;
665 static CRITICAL_SECTION ListLock;
667 static void LockLists(void)
669 EnterCriticalSection(&ListLock);
671 static void UnlockLists(void)
673 LeaveCriticalSection(&ListLock);
676 /************************************************
677 * Library initialization
678 ************************************************/
679 #if defined(_WIN32)
680 static void alc_init(void);
681 static void alc_deinit(void);
682 static void alc_deinit_safe(void);
684 UIntMap TlsDestructor;
686 #ifndef AL_LIBTYPE_STATIC
687 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
689 ALsizei i;
691 // Perform actions based on the reason for calling.
692 switch(ul_reason_for_call)
694 case DLL_PROCESS_ATTACH:
695 /* Pin the DLL so we won't get unloaded until the process terminates */
696 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
697 (WCHAR*)hModule, &hModule);
698 InitUIntMap(&TlsDestructor, ~0);
699 alc_init();
700 break;
702 case DLL_THREAD_DETACH:
703 LockUIntMapRead(&TlsDestructor);
704 for(i = 0;i < TlsDestructor.size;i++)
706 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
707 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
708 if(ptr && callback)
709 callback(ptr);
711 UnlockUIntMapRead(&TlsDestructor);
712 break;
714 case DLL_PROCESS_DETACH:
715 if(!lpReserved)
716 alc_deinit();
717 else
718 alc_deinit_safe();
719 ResetUIntMap(&TlsDestructor);
720 break;
722 return TRUE;
724 #elif defined(_MSC_VER)
725 #pragma section(".CRT$XCU",read)
726 static void alc_constructor(void);
727 static void alc_destructor(void);
728 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
730 static void alc_constructor(void)
732 atexit(alc_destructor);
733 alc_init();
736 static void alc_destructor(void)
738 alc_deinit();
740 #elif defined(HAVE_GCC_DESTRUCTOR)
741 static void alc_init(void) __attribute__((constructor));
742 static void alc_deinit(void) __attribute__((destructor));
743 #else
744 #error "No static initialization available on this platform!"
745 #endif
747 #elif defined(HAVE_GCC_DESTRUCTOR)
749 static void alc_init(void) __attribute__((constructor));
750 static void alc_deinit(void) __attribute__((destructor));
752 #else
753 #error "No global initialization available on this platform!"
754 #endif
756 static void ReleaseThreadCtx(void *ptr);
757 static void alc_init(void)
759 const char *str;
761 LogFile = stderr;
763 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
764 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
765 ConeScale *= 0.5f;
767 str = getenv("__ALSOFT_REVERSE_Z");
768 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
769 ZScale *= -1.0f;
771 pthread_key_create(&LocalContext, ReleaseThreadCtx);
772 InitializeCriticalSection(&ListLock);
773 ThunkInit();
776 static void alc_initconfig(void)
778 const char *devs, *str;
779 ALuint capfilter;
780 float valf;
781 int i, n;
783 str = getenv("ALSOFT_LOGLEVEL");
784 if(str)
786 long lvl = strtol(str, NULL, 0);
787 if(lvl >= NoLog && lvl <= LogRef)
788 LogLevel = lvl;
791 str = getenv("ALSOFT_LOGFILE");
792 if(str && str[0])
794 FILE *logfile = fopen(str, "wat");
795 if(logfile) LogFile = logfile;
796 else ERR("Failed to open log file '%s'\n", str);
799 ReadALConfig();
801 capfilter = 0;
802 #ifdef HAVE_SSE
803 capfilter |= CPU_CAP_SSE;
804 #endif
805 #ifdef HAVE_NEON
806 capfilter |= CPU_CAP_NEON;
807 #endif
808 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
810 if(strcasecmp(str, "all") == 0)
811 capfilter = 0;
812 else
814 size_t len;
815 const char *next = str;
817 i = 0;
818 do {
819 str = next;
820 next = strchr(str, ',');
822 while(isspace(str[0]))
823 str++;
824 if(!str[0] || str[0] == ',')
825 continue;
827 len = (next ? ((size_t)(next-str)) : strlen(str));
828 if(strncasecmp(str, "sse", len) == 0)
829 capfilter &= ~CPU_CAP_SSE;
830 else if(strncasecmp(str, "neon", len) == 0)
831 capfilter &= ~CPU_CAP_NEON;
832 else
833 WARN("Invalid CPU extension \"%s\"\n", str);
834 } while(next++);
837 FillCPUCaps(capfilter);
839 InitHrtf();
841 #ifdef _WIN32
842 RTPrioLevel = 1;
843 #else
844 RTPrioLevel = 0;
845 #endif
846 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
848 if(ConfigValueStr(NULL, "resampler", &str))
850 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
851 DefaultResampler = PointResampler;
852 else if(strcasecmp(str, "linear") == 0)
853 DefaultResampler = LinearResampler;
854 else if(strcasecmp(str, "cubic") == 0)
855 DefaultResampler = CubicResampler;
856 else
858 char *end;
860 n = strtol(str, &end, 0);
861 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
862 DefaultResampler = n;
863 else
864 WARN("Invalid resampler: %s\n", str);
868 str = getenv("ALSOFT_TRAP_ERROR");
869 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
871 TrapALError = AL_TRUE;
872 TrapALCError = AL_TRUE;
874 else
876 str = getenv("ALSOFT_TRAP_AL_ERROR");
877 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
878 TrapALError = AL_TRUE;
879 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
881 str = getenv("ALSOFT_TRAP_ALC_ERROR");
882 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
883 TrapALCError = ALC_TRUE;
884 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
887 if(ConfigValueFloat("reverb", "boost", &valf))
888 ReverbBoost *= powf(10.0f, valf / 20.0f);
890 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
892 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
893 ConfigValueStr(NULL, "drivers", &devs))
895 int n;
896 size_t len;
897 const char *next = devs;
898 int endlist, delitem;
900 i = 0;
901 do {
902 devs = next;
903 next = strchr(devs, ',');
905 delitem = (devs[0] == '-');
906 if(devs[0] == '-') devs++;
908 if(!devs[0] || devs[0] == ',')
910 endlist = 0;
911 continue;
913 endlist = 1;
915 len = (next ? ((size_t)(next-devs)) : strlen(devs));
916 for(n = i;BackendList[n].Init;n++)
918 if(len == strlen(BackendList[n].name) &&
919 strncmp(BackendList[n].name, devs, len) == 0)
921 if(delitem)
923 do {
924 BackendList[n] = BackendList[n+1];
925 ++n;
926 } while(BackendList[n].Init);
928 else
930 struct BackendInfo Bkp = BackendList[n];
931 while(n > i)
933 BackendList[n] = BackendList[n-1];
934 --n;
936 BackendList[n] = Bkp;
938 i++;
940 break;
943 } while(next++);
945 if(endlist)
947 BackendList[i].name = NULL;
948 BackendList[i].Init = NULL;
949 BackendList[i].Deinit = NULL;
950 BackendList[i].Probe = NULL;
954 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
956 if(!BackendList[i].Init(&BackendList[i].Funcs))
958 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
959 continue;
962 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
963 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
965 PlaybackBackend = BackendList[i];
966 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
968 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
970 CaptureBackend = BackendList[i];
971 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
974 BackendLoopback.Init(&BackendLoopback.Funcs);
976 if(ConfigValueStr(NULL, "excludefx", &str))
978 size_t len;
979 const char *next = str;
981 do {
982 str = next;
983 next = strchr(str, ',');
985 if(!str[0] || next == str)
986 continue;
988 len = (next ? ((size_t)(next-str)) : strlen(str));
989 for(n = 0;EffectList[n].name;n++)
991 if(len == strlen(EffectList[n].name) &&
992 strncmp(EffectList[n].name, str, len) == 0)
993 DisabledEffects[EffectList[n].type] = AL_TRUE;
995 } while(next++);
998 InitEffect(&DefaultEffect);
999 str = getenv("ALSOFT_DEFAULT_REVERB");
1000 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1001 LoadReverbPreset(str, &DefaultEffect);
1003 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1006 /************************************************
1007 * Library deinitialization
1008 ************************************************/
1009 static void alc_cleanup(void)
1011 ALCdevice *dev;
1013 free(alcAllDevicesList); alcAllDevicesList = NULL;
1014 alcAllDevicesListSize = 0;
1015 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1016 alcCaptureDeviceListSize = 0;
1018 free(alcDefaultAllDevicesSpecifier);
1019 alcDefaultAllDevicesSpecifier = NULL;
1020 free(alcCaptureDefaultDeviceSpecifier);
1021 alcCaptureDefaultDeviceSpecifier = NULL;
1023 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1025 ALCuint num = 0;
1026 do {
1027 num++;
1028 } while((dev=dev->next) != NULL);
1029 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1033 static void alc_deinit_safe(void)
1035 alc_cleanup();
1037 FreeHrtf();
1038 FreeALConfig();
1040 ThunkExit();
1041 DeleteCriticalSection(&ListLock);
1042 pthread_key_delete(LocalContext);
1044 if(LogFile != stderr)
1045 fclose(LogFile);
1046 LogFile = NULL;
1049 static void alc_deinit(void)
1051 int i;
1053 alc_cleanup();
1055 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1056 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1058 for(i = 0;BackendList[i].Deinit;i++)
1059 BackendList[i].Deinit();
1060 BackendLoopback.Deinit();
1062 alc_deinit_safe();
1066 /************************************************
1067 * Device enumeration
1068 ************************************************/
1069 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1071 DO_INITCONFIG();
1073 LockLists();
1074 free(*list);
1075 *list = NULL;
1076 *listsize = 0;
1078 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1079 PlaybackBackend.Probe(type);
1080 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1081 CaptureBackend.Probe(type);
1082 UnlockLists();
1085 static void ProbeAllDevicesList(void)
1086 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1087 static void ProbeCaptureDeviceList(void)
1088 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1091 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1093 size_t len = strlen(name);
1094 void *temp;
1096 if(len == 0)
1097 return;
1099 temp = realloc(*List, (*ListSize) + len + 2);
1100 if(!temp)
1102 ERR("Realloc failed to add %s!\n", name);
1103 return;
1105 *List = temp;
1107 memcpy((*List)+(*ListSize), name, len+1);
1108 *ListSize += len+1;
1109 (*List)[*ListSize] = 0;
1112 #define DECL_APPEND_LIST_FUNC(type) \
1113 void Append##type##List(const ALCchar *name) \
1114 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1116 DECL_APPEND_LIST_FUNC(AllDevices)
1117 DECL_APPEND_LIST_FUNC(CaptureDevice)
1119 #undef DECL_APPEND_LIST_FUNC
1122 /************************************************
1123 * Device format information
1124 ************************************************/
1125 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1127 switch(type)
1129 case DevFmtByte: return "Signed Byte";
1130 case DevFmtUByte: return "Unsigned Byte";
1131 case DevFmtShort: return "Signed Short";
1132 case DevFmtUShort: return "Unsigned Short";
1133 case DevFmtInt: return "Signed Int";
1134 case DevFmtUInt: return "Unsigned Int";
1135 case DevFmtFloat: return "Float";
1137 return "(unknown type)";
1139 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1141 switch(chans)
1143 case DevFmtMono: return "Mono";
1144 case DevFmtStereo: return "Stereo";
1145 case DevFmtQuad: return "Quadraphonic";
1146 case DevFmtX51: return "5.1 Surround";
1147 case DevFmtX51Side: return "5.1 Side";
1148 case DevFmtX61: return "6.1 Surround";
1149 case DevFmtX71: return "7.1 Surround";
1151 return "(unknown channels)";
1154 ALuint BytesFromDevFmt(enum DevFmtType type)
1156 switch(type)
1158 case DevFmtByte: return sizeof(ALbyte);
1159 case DevFmtUByte: return sizeof(ALubyte);
1160 case DevFmtShort: return sizeof(ALshort);
1161 case DevFmtUShort: return sizeof(ALushort);
1162 case DevFmtInt: return sizeof(ALint);
1163 case DevFmtUInt: return sizeof(ALuint);
1164 case DevFmtFloat: return sizeof(ALfloat);
1166 return 0;
1168 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1170 switch(chans)
1172 case DevFmtMono: return 1;
1173 case DevFmtStereo: return 2;
1174 case DevFmtQuad: return 4;
1175 case DevFmtX51: return 6;
1176 case DevFmtX51Side: return 6;
1177 case DevFmtX61: return 7;
1178 case DevFmtX71: return 8;
1180 return 0;
1183 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1184 enum DevFmtType *type)
1186 static const struct {
1187 ALenum format;
1188 enum DevFmtChannels channels;
1189 enum DevFmtType type;
1190 } list[] = {
1191 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1192 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1193 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1195 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1196 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1197 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1199 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1200 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1201 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1203 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1204 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1205 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1207 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1208 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1209 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1211 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1212 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1213 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1215 ALuint i;
1217 for(i = 0;i < COUNTOF(list);i++)
1219 if(list[i].format == format)
1221 *chans = list[i].channels;
1222 *type = list[i].type;
1223 return AL_TRUE;
1227 return AL_FALSE;
1230 static ALCboolean IsValidALCType(ALCenum type)
1232 switch(type)
1234 case ALC_BYTE_SOFT:
1235 case ALC_UNSIGNED_BYTE_SOFT:
1236 case ALC_SHORT_SOFT:
1237 case ALC_UNSIGNED_SHORT_SOFT:
1238 case ALC_INT_SOFT:
1239 case ALC_UNSIGNED_INT_SOFT:
1240 case ALC_FLOAT_SOFT:
1241 return ALC_TRUE;
1243 return ALC_FALSE;
1246 static ALCboolean IsValidALCChannels(ALCenum channels)
1248 switch(channels)
1250 case ALC_MONO_SOFT:
1251 case ALC_STEREO_SOFT:
1252 case ALC_QUAD_SOFT:
1253 case ALC_5POINT1_SOFT:
1254 case ALC_6POINT1_SOFT:
1255 case ALC_7POINT1_SOFT:
1256 return ALC_TRUE;
1258 return ALC_FALSE;
1262 /************************************************
1263 * Miscellaneous ALC helpers
1264 ************************************************/
1266 void ALCdevice_LockDefault(ALCdevice *device)
1268 EnterCriticalSection(&device->Mutex);
1270 void ALCdevice_UnlockDefault(ALCdevice *device)
1272 LeaveCriticalSection(&device->Mutex);
1274 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
1276 (void)device;
1277 return 0;
1280 /* SetDefaultWFXChannelOrder
1282 * Sets the default channel order used by WaveFormatEx.
1284 void SetDefaultWFXChannelOrder(ALCdevice *device)
1286 switch(device->FmtChans)
1288 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1290 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1291 device->DevChannels[1] = FrontRight; break;
1293 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1294 device->DevChannels[1] = FrontRight;
1295 device->DevChannels[2] = BackLeft;
1296 device->DevChannels[3] = BackRight; break;
1298 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1299 device->DevChannels[1] = FrontRight;
1300 device->DevChannels[2] = FrontCenter;
1301 device->DevChannels[3] = LFE;
1302 device->DevChannels[4] = BackLeft;
1303 device->DevChannels[5] = BackRight; break;
1305 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1306 device->DevChannels[1] = FrontRight;
1307 device->DevChannels[2] = FrontCenter;
1308 device->DevChannels[3] = LFE;
1309 device->DevChannels[4] = SideLeft;
1310 device->DevChannels[5] = SideRight; break;
1312 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1313 device->DevChannels[1] = FrontRight;
1314 device->DevChannels[2] = FrontCenter;
1315 device->DevChannels[3] = LFE;
1316 device->DevChannels[4] = BackCenter;
1317 device->DevChannels[5] = SideLeft;
1318 device->DevChannels[6] = SideRight; break;
1320 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1321 device->DevChannels[1] = FrontRight;
1322 device->DevChannels[2] = FrontCenter;
1323 device->DevChannels[3] = LFE;
1324 device->DevChannels[4] = BackLeft;
1325 device->DevChannels[5] = BackRight;
1326 device->DevChannels[6] = SideLeft;
1327 device->DevChannels[7] = SideRight; break;
1331 /* SetDefaultChannelOrder
1333 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1335 void SetDefaultChannelOrder(ALCdevice *device)
1337 switch(device->FmtChans)
1339 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1340 device->DevChannels[1] = FrontRight;
1341 device->DevChannels[2] = BackLeft;
1342 device->DevChannels[3] = BackRight;
1343 device->DevChannels[4] = FrontCenter;
1344 device->DevChannels[5] = LFE;
1345 return;
1347 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1348 device->DevChannels[1] = FrontRight;
1349 device->DevChannels[2] = BackLeft;
1350 device->DevChannels[3] = BackRight;
1351 device->DevChannels[4] = FrontCenter;
1352 device->DevChannels[5] = LFE;
1353 device->DevChannels[6] = SideLeft;
1354 device->DevChannels[7] = SideRight;
1355 return;
1357 /* Same as WFX order */
1358 case DevFmtMono:
1359 case DevFmtStereo:
1360 case DevFmtQuad:
1361 case DevFmtX51Side:
1362 case DevFmtX61:
1363 break;
1365 SetDefaultWFXChannelOrder(device);
1369 /* alcSetError
1371 * Stores the latest ALC device error
1373 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1375 if(TrapALCError)
1377 #ifdef _WIN32
1378 /* DebugBreak() will cause an exception if there is no debugger */
1379 if(IsDebuggerPresent())
1380 DebugBreak();
1381 #elif defined(SIGTRAP)
1382 raise(SIGTRAP);
1383 #endif
1386 if(device)
1387 device->LastError = errorCode;
1388 else
1389 LastNullDeviceError = errorCode;
1393 /* UpdateDeviceParams
1395 * Updates device parameters according to the attribute list (caller is
1396 * responsible for holding the list lock).
1398 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1400 ALCcontext *context;
1401 enum DevFmtChannels oldChans;
1402 enum DevFmtType oldType;
1403 ALCuint oldFreq;
1404 int oldMode;
1405 ALuint i;
1407 // Check for attributes
1408 if(device->Type == Loopback)
1410 enum {
1411 GotFreq = 1<<0,
1412 GotChans = 1<<1,
1413 GotType = 1<<2,
1414 GotAll = GotFreq|GotChans|GotType
1416 ALCuint freq, numMono, numStereo, numSends;
1417 enum DevFmtChannels schans;
1418 enum DevFmtType stype;
1419 ALCuint attrIdx = 0;
1420 ALCint gotFmt = 0;
1422 if(!attrList)
1424 WARN("Missing attributes for loopback device\n");
1425 return ALC_INVALID_VALUE;
1428 numMono = device->NumMonoSources;
1429 numStereo = device->NumStereoSources;
1430 numSends = device->NumAuxSends;
1431 schans = device->FmtChans;
1432 stype = device->FmtType;
1433 freq = device->Frequency;
1435 while(attrList[attrIdx])
1437 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1439 ALCint val = attrList[attrIdx + 1];
1440 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1441 return ALC_INVALID_VALUE;
1442 schans = val;
1443 gotFmt |= GotChans;
1446 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1448 ALCint val = attrList[attrIdx + 1];
1449 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1450 return ALC_INVALID_VALUE;
1451 stype = val;
1452 gotFmt |= GotType;
1455 if(attrList[attrIdx] == ALC_FREQUENCY)
1457 freq = attrList[attrIdx + 1];
1458 if(freq < MIN_OUTPUT_RATE)
1459 return ALC_INVALID_VALUE;
1460 gotFmt |= GotFreq;
1463 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1465 numStereo = attrList[attrIdx + 1];
1466 if(numStereo > device->MaxNoOfSources)
1467 numStereo = device->MaxNoOfSources;
1469 numMono = device->MaxNoOfSources - numStereo;
1472 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1473 numSends = attrList[attrIdx + 1];
1475 attrIdx += 2;
1478 if(gotFmt != GotAll)
1480 WARN("Missing format for loopback device\n");
1481 return ALC_INVALID_VALUE;
1484 ConfigValueUInt(NULL, "sends", &numSends);
1485 numSends = minu(MAX_SENDS, numSends);
1487 if((device->Flags&DEVICE_RUNNING))
1488 ALCdevice_StopPlayback(device);
1489 device->Flags &= ~DEVICE_RUNNING;
1491 device->Frequency = freq;
1492 device->FmtChans = schans;
1493 device->FmtType = stype;
1494 device->NumMonoSources = numMono;
1495 device->NumStereoSources = numStereo;
1496 device->NumAuxSends = numSends;
1498 else if(attrList && attrList[0])
1500 ALCuint freq, numMono, numStereo, numSends;
1501 ALCuint attrIdx = 0;
1503 /* If a context is already running on the device, stop playback so the
1504 * device attributes can be updated. */
1505 if((device->Flags&DEVICE_RUNNING))
1506 ALCdevice_StopPlayback(device);
1507 device->Flags &= ~DEVICE_RUNNING;
1509 freq = device->Frequency;
1510 numMono = device->NumMonoSources;
1511 numStereo = device->NumStereoSources;
1512 numSends = device->NumAuxSends;
1514 while(attrList[attrIdx])
1516 if(attrList[attrIdx] == ALC_FREQUENCY)
1518 freq = attrList[attrIdx + 1];
1519 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1522 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1524 numStereo = attrList[attrIdx + 1];
1525 if(numStereo > device->MaxNoOfSources)
1526 numStereo = device->MaxNoOfSources;
1528 numMono = device->MaxNoOfSources - numStereo;
1531 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1532 numSends = attrList[attrIdx + 1];
1534 attrIdx += 2;
1537 ConfigValueUInt(NULL, "frequency", &freq);
1538 freq = maxu(freq, MIN_OUTPUT_RATE);
1540 ConfigValueUInt(NULL, "sends", &numSends);
1541 numSends = minu(MAX_SENDS, numSends);
1543 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1544 device->Frequency;
1546 device->Frequency = freq;
1547 device->NumMonoSources = numMono;
1548 device->NumStereoSources = numStereo;
1549 device->NumAuxSends = numSends;
1552 if((device->Flags&DEVICE_RUNNING))
1553 return ALC_NO_ERROR;
1555 oldFreq = device->Frequency;
1556 oldChans = device->FmtChans;
1557 oldType = device->FmtType;
1559 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1560 DevFmtChannelsString(device->FmtChans),
1561 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1562 DevFmtTypeString(device->FmtType),
1563 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1564 device->Frequency,
1565 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1566 device->UpdateSize, device->NumUpdates);
1568 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1569 return ALC_INVALID_DEVICE;
1571 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1573 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1574 DevFmtChannelsString(device->FmtChans));
1575 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1577 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1579 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1580 DevFmtTypeString(device->FmtType));
1581 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1583 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1585 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1586 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1589 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1590 DevFmtChannelsString(device->FmtChans),
1591 DevFmtTypeString(device->FmtType), device->Frequency,
1592 device->UpdateSize, device->NumUpdates);
1594 aluInitPanning(device);
1596 for(i = 0;i < MaxChannels;i++)
1598 device->ClickRemoval[i] = 0.0f;
1599 device->PendingClicks[i] = 0.0f;
1602 device->Hrtf = NULL;
1603 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1604 device->Hrtf = GetHrtf(device);
1605 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1607 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1609 if(!device->Bs2b)
1611 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1612 bs2b_clear(device->Bs2b);
1614 bs2b_set_srate(device->Bs2b, device->Frequency);
1615 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1616 TRACE("BS2B level %d\n", device->Bs2bLevel);
1618 else
1620 free(device->Bs2b);
1621 device->Bs2b = NULL;
1622 TRACE("BS2B disabled\n");
1625 device->Flags &= ~DEVICE_WIDE_STEREO;
1626 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1627 device->Flags |= DEVICE_WIDE_STEREO;
1629 oldMode = SetMixerFPUMode();
1630 ALCdevice_Lock(device);
1631 context = device->ContextList;
1632 while(context)
1634 ALsizei pos;
1636 context->UpdateSources = AL_FALSE;
1637 LockUIntMapRead(&context->EffectSlotMap);
1638 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1640 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1642 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1644 UnlockUIntMapRead(&context->EffectSlotMap);
1645 ALCdevice_Unlock(device);
1646 RestoreFPUMode(oldMode);
1647 return ALC_INVALID_DEVICE;
1649 slot->NeedsUpdate = AL_FALSE;
1650 ALeffectState_Update(slot->EffectState, device, slot);
1652 UnlockUIntMapRead(&context->EffectSlotMap);
1654 LockUIntMapRead(&context->SourceMap);
1655 for(pos = 0;pos < context->SourceMap.size;pos++)
1657 ALsource *source = context->SourceMap.array[pos].value;
1658 ALuint s = device->NumAuxSends;
1659 while(s < MAX_SENDS)
1661 if(source->Send[s].Slot)
1662 DecrementRef(&source->Send[s].Slot->ref);
1663 source->Send[s].Slot = NULL;
1664 source->Send[s].Gain = 1.0f;
1665 source->Send[s].GainHF = 1.0f;
1666 s++;
1668 source->NeedsUpdate = AL_FALSE;
1669 ALsource_Update(source, context);
1671 UnlockUIntMapRead(&context->SourceMap);
1673 context = context->next;
1675 if(device->DefaultSlot)
1677 ALeffectslot *slot = device->DefaultSlot;
1679 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1681 ALCdevice_Unlock(device);
1682 RestoreFPUMode(oldMode);
1683 return ALC_INVALID_DEVICE;
1685 slot->NeedsUpdate = AL_FALSE;
1686 ALeffectState_Update(slot->EffectState, device, slot);
1688 ALCdevice_Unlock(device);
1689 RestoreFPUMode(oldMode);
1691 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1692 return ALC_INVALID_DEVICE;
1693 device->Flags |= DEVICE_RUNNING;
1695 return ALC_NO_ERROR;
1698 /* FreeDevice
1700 * Frees the device structure, and destroys any objects the app failed to
1701 * delete. Called once there's no more references on the device.
1703 static ALCvoid FreeDevice(ALCdevice *device)
1705 TRACE("%p\n", device);
1707 if(device->Type != Capture)
1708 ALCdevice_ClosePlayback(device);
1709 else
1710 ALCdevice_CloseCapture(device);
1712 if(device->DefaultSlot)
1714 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1715 device->DefaultSlot->EffectState = NULL;
1718 if(device->BufferMap.size > 0)
1720 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1721 ReleaseALBuffers(device);
1723 ResetUIntMap(&device->BufferMap);
1725 if(device->EffectMap.size > 0)
1727 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1728 ReleaseALEffects(device);
1730 ResetUIntMap(&device->EffectMap);
1732 if(device->FilterMap.size > 0)
1734 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1735 ReleaseALFilters(device);
1737 ResetUIntMap(&device->FilterMap);
1739 free(device->Bs2b);
1740 device->Bs2b = NULL;
1742 free(device->DeviceName);
1743 device->DeviceName = NULL;
1745 DeleteCriticalSection(&device->Mutex);
1747 al_free(device);
1751 void ALCdevice_IncRef(ALCdevice *device)
1753 RefCount ref;
1754 ref = IncrementRef(&device->ref);
1755 TRACEREF("%p increasing refcount to %u\n", device, ref);
1758 void ALCdevice_DecRef(ALCdevice *device)
1760 RefCount ref;
1761 ref = DecrementRef(&device->ref);
1762 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1763 if(ref == 0) FreeDevice(device);
1766 /* VerifyDevice
1768 * Checks if the device handle is valid, and increments its ref count if so.
1770 static ALCdevice *VerifyDevice(ALCdevice *device)
1772 ALCdevice *tmpDevice;
1774 if(!device)
1775 return NULL;
1777 LockLists();
1778 tmpDevice = DeviceList;
1779 while(tmpDevice && tmpDevice != device)
1780 tmpDevice = tmpDevice->next;
1782 if(tmpDevice)
1783 ALCdevice_IncRef(tmpDevice);
1784 UnlockLists();
1785 return tmpDevice;
1789 /* InitContext
1791 * Initializes context fields
1793 static ALvoid InitContext(ALCcontext *Context)
1795 ALint i, j;
1797 //Initialise listener
1798 Context->Listener.Gain = 1.0f;
1799 Context->Listener.MetersPerUnit = 1.0f;
1800 Context->Listener.Position[0] = 0.0f;
1801 Context->Listener.Position[1] = 0.0f;
1802 Context->Listener.Position[2] = 0.0f;
1803 Context->Listener.Velocity[0] = 0.0f;
1804 Context->Listener.Velocity[1] = 0.0f;
1805 Context->Listener.Velocity[2] = 0.0f;
1806 Context->Listener.Forward[0] = 0.0f;
1807 Context->Listener.Forward[1] = 0.0f;
1808 Context->Listener.Forward[2] = -1.0f;
1809 Context->Listener.Up[0] = 0.0f;
1810 Context->Listener.Up[1] = 1.0f;
1811 Context->Listener.Up[2] = 0.0f;
1812 for(i = 0;i < 4;i++)
1814 for(j = 0;j < 4;j++)
1815 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1818 //Validate Context
1819 Context->LastError = AL_NO_ERROR;
1820 Context->UpdateSources = AL_FALSE;
1821 Context->ActiveSourceCount = 0;
1822 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1823 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1825 //Set globals
1826 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1827 Context->SourceDistanceModel = AL_FALSE;
1828 Context->DopplerFactor = 1.0f;
1829 Context->DopplerVelocity = 1.0f;
1830 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1831 Context->DeferUpdates = AL_FALSE;
1833 Context->ExtensionList = alExtList;
1837 /* FreeContext
1839 * Cleans up the context, and destroys any remaining objects the app failed to
1840 * delete. Called once there's no more references on the context.
1842 static ALCvoid FreeContext(ALCcontext *context)
1844 TRACE("%p\n", context);
1846 if(context->SourceMap.size > 0)
1848 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1849 ReleaseALSources(context);
1851 ResetUIntMap(&context->SourceMap);
1853 if(context->EffectSlotMap.size > 0)
1855 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1856 ReleaseALAuxiliaryEffectSlots(context);
1858 ResetUIntMap(&context->EffectSlotMap);
1860 context->ActiveSourceCount = 0;
1861 free(context->ActiveSources);
1862 context->ActiveSources = NULL;
1863 context->MaxActiveSources = 0;
1865 context->ActiveEffectSlotCount = 0;
1866 free(context->ActiveEffectSlots);
1867 context->ActiveEffectSlots = NULL;
1868 context->MaxActiveEffectSlots = 0;
1870 ALCdevice_DecRef(context->Device);
1871 context->Device = NULL;
1873 //Invalidate context
1874 memset(context, 0, sizeof(ALCcontext));
1875 free(context);
1878 /* ReleaseContext
1880 * Removes the context reference from the given device and removes it from
1881 * being current on the running thread or globally.
1883 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1885 ALCcontext *volatile*tmp_ctx;
1887 if(pthread_getspecific(LocalContext) == context)
1889 WARN("%p released while current on thread\n", context);
1890 pthread_setspecific(LocalContext, NULL);
1891 ALCcontext_DecRef(context);
1894 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1895 ALCcontext_DecRef(context);
1897 ALCdevice_Lock(device);
1898 tmp_ctx = &device->ContextList;
1899 while(*tmp_ctx)
1901 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1902 break;
1903 tmp_ctx = &(*tmp_ctx)->next;
1905 ALCdevice_Unlock(device);
1907 ALCcontext_DecRef(context);
1910 void ALCcontext_IncRef(ALCcontext *context)
1912 RefCount ref;
1913 ref = IncrementRef(&context->ref);
1914 TRACEREF("%p increasing refcount to %u\n", context, ref);
1917 void ALCcontext_DecRef(ALCcontext *context)
1919 RefCount ref;
1920 ref = DecrementRef(&context->ref);
1921 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1922 if(ref == 0) FreeContext(context);
1925 static void ReleaseThreadCtx(void *ptr)
1927 WARN("%p current for thread being destroyed\n", ptr);
1928 ALCcontext_DecRef(ptr);
1931 /* VerifyContext
1933 * Checks that the given context is valid, and increments its reference count.
1935 static ALCcontext *VerifyContext(ALCcontext *context)
1937 ALCdevice *dev;
1939 LockLists();
1940 dev = DeviceList;
1941 while(dev)
1943 ALCcontext *tmp_ctx = dev->ContextList;
1944 while(tmp_ctx)
1946 if(tmp_ctx == context)
1948 ALCcontext_IncRef(tmp_ctx);
1949 UnlockLists();
1950 return tmp_ctx;
1952 tmp_ctx = tmp_ctx->next;
1954 dev = dev->next;
1956 UnlockLists();
1958 return NULL;
1962 /* GetContextRef
1964 * Returns the currently active context for this thread, and adds a reference
1965 * without locking it.
1967 ALCcontext *GetContextRef(void)
1969 ALCcontext *context;
1971 context = pthread_getspecific(LocalContext);
1972 if(context)
1973 ALCcontext_IncRef(context);
1974 else
1976 LockLists();
1977 context = GlobalContext;
1978 if(context)
1979 ALCcontext_IncRef(context);
1980 UnlockLists();
1983 return context;
1987 /************************************************
1988 * Standard ALC functions
1989 ************************************************/
1991 /* alcGetError
1993 * Return last ALC generated error code for the given device
1995 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1997 ALCenum errorCode;
1999 if(VerifyDevice(device))
2001 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2002 ALCdevice_DecRef(device);
2004 else
2005 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2007 return errorCode;
2011 /* alcSuspendContext
2013 * Not functional
2015 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
2017 (void)Context;
2020 /* alcProcessContext
2022 * Not functional
2024 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2026 (void)Context;
2030 /* alcGetString
2032 * Returns information about the device, and error strings
2034 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2036 const ALCchar *value = NULL;
2038 switch(param)
2040 case ALC_NO_ERROR:
2041 value = alcNoError;
2042 break;
2044 case ALC_INVALID_ENUM:
2045 value = alcErrInvalidEnum;
2046 break;
2048 case ALC_INVALID_VALUE:
2049 value = alcErrInvalidValue;
2050 break;
2052 case ALC_INVALID_DEVICE:
2053 value = alcErrInvalidDevice;
2054 break;
2056 case ALC_INVALID_CONTEXT:
2057 value = alcErrInvalidContext;
2058 break;
2060 case ALC_OUT_OF_MEMORY:
2061 value = alcErrOutOfMemory;
2062 break;
2064 case ALC_DEVICE_SPECIFIER:
2065 value = alcDefaultName;
2066 break;
2068 case ALC_ALL_DEVICES_SPECIFIER:
2069 if(VerifyDevice(Device))
2071 value = Device->DeviceName;
2072 ALCdevice_DecRef(Device);
2074 else
2076 ProbeAllDevicesList();
2077 value = alcAllDevicesList;
2079 break;
2081 case ALC_CAPTURE_DEVICE_SPECIFIER:
2082 if(VerifyDevice(Device))
2084 value = Device->DeviceName;
2085 ALCdevice_DecRef(Device);
2087 else
2089 ProbeCaptureDeviceList();
2090 value = alcCaptureDeviceList;
2092 break;
2094 /* Default devices are always first in the list */
2095 case ALC_DEFAULT_DEVICE_SPECIFIER:
2096 value = alcDefaultName;
2097 break;
2099 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2100 if(!alcAllDevicesList)
2101 ProbeAllDevicesList();
2103 Device = VerifyDevice(Device);
2105 free(alcDefaultAllDevicesSpecifier);
2106 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2107 alcAllDevicesList : "");
2108 if(!alcDefaultAllDevicesSpecifier)
2109 alcSetError(Device, ALC_OUT_OF_MEMORY);
2111 value = alcDefaultAllDevicesSpecifier;
2112 if(Device) ALCdevice_DecRef(Device);
2113 break;
2115 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2116 if(!alcCaptureDeviceList)
2117 ProbeCaptureDeviceList();
2119 Device = VerifyDevice(Device);
2121 free(alcCaptureDefaultDeviceSpecifier);
2122 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2123 alcCaptureDeviceList : "");
2124 if(!alcCaptureDefaultDeviceSpecifier)
2125 alcSetError(Device, ALC_OUT_OF_MEMORY);
2127 value = alcCaptureDefaultDeviceSpecifier;
2128 if(Device) ALCdevice_DecRef(Device);
2129 break;
2131 case ALC_EXTENSIONS:
2132 if(!VerifyDevice(Device))
2133 value = alcNoDeviceExtList;
2134 else
2136 value = alcExtensionList;
2137 ALCdevice_DecRef(Device);
2139 break;
2141 default:
2142 Device = VerifyDevice(Device);
2143 alcSetError(Device, ALC_INVALID_ENUM);
2144 if(Device) ALCdevice_DecRef(Device);
2145 break;
2148 return value;
2152 /* alcGetIntegerv
2154 * Returns information about the device and the version of OpenAL
2156 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2158 device = VerifyDevice(device);
2160 if(size == 0 || data == NULL)
2162 alcSetError(device, ALC_INVALID_VALUE);
2163 if(device) ALCdevice_DecRef(device);
2164 return;
2167 if(!device)
2169 switch(param)
2171 case ALC_MAJOR_VERSION:
2172 *data = alcMajorVersion;
2173 break;
2174 case ALC_MINOR_VERSION:
2175 *data = alcMinorVersion;
2176 break;
2178 case ALC_ATTRIBUTES_SIZE:
2179 case ALC_ALL_ATTRIBUTES:
2180 case ALC_FREQUENCY:
2181 case ALC_REFRESH:
2182 case ALC_SYNC:
2183 case ALC_MONO_SOURCES:
2184 case ALC_STEREO_SOURCES:
2185 case ALC_CAPTURE_SAMPLES:
2186 case ALC_FORMAT_CHANNELS_SOFT:
2187 case ALC_FORMAT_TYPE_SOFT:
2188 alcSetError(NULL, ALC_INVALID_DEVICE);
2189 break;
2191 default:
2192 alcSetError(NULL, ALC_INVALID_ENUM);
2193 break;
2196 else if(device->Type == Capture)
2198 switch(param)
2200 case ALC_CAPTURE_SAMPLES:
2201 LockLists();
2202 /* Re-validate the device since it may have been closed */
2203 ALCdevice_DecRef(device);
2204 if((device=VerifyDevice(device)) != NULL)
2205 *data = ALCdevice_AvailableSamples(device);
2206 else
2207 alcSetError(NULL, ALC_INVALID_DEVICE);
2208 UnlockLists();
2209 break;
2211 case ALC_CONNECTED:
2212 *data = device->Connected;
2213 break;
2215 default:
2216 alcSetError(device, ALC_INVALID_ENUM);
2217 break;
2220 else /* render device */
2222 switch(param)
2224 case ALC_MAJOR_VERSION:
2225 *data = alcMajorVersion;
2226 break;
2228 case ALC_MINOR_VERSION:
2229 *data = alcMinorVersion;
2230 break;
2232 case ALC_EFX_MAJOR_VERSION:
2233 *data = alcEFXMajorVersion;
2234 break;
2236 case ALC_EFX_MINOR_VERSION:
2237 *data = alcEFXMinorVersion;
2238 break;
2240 case ALC_ATTRIBUTES_SIZE:
2241 *data = 13;
2242 break;
2244 case ALC_ALL_ATTRIBUTES:
2245 if(size < 13)
2246 alcSetError(device, ALC_INVALID_VALUE);
2247 else
2249 int i = 0;
2251 data[i++] = ALC_FREQUENCY;
2252 data[i++] = device->Frequency;
2254 if(device->Type != Loopback)
2256 data[i++] = ALC_REFRESH;
2257 data[i++] = device->Frequency / device->UpdateSize;
2259 data[i++] = ALC_SYNC;
2260 data[i++] = ALC_FALSE;
2262 else
2264 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2265 data[i++] = device->FmtChans;
2267 data[i++] = ALC_FORMAT_TYPE_SOFT;
2268 data[i++] = device->FmtType;
2271 data[i++] = ALC_MONO_SOURCES;
2272 data[i++] = device->NumMonoSources;
2274 data[i++] = ALC_STEREO_SOURCES;
2275 data[i++] = device->NumStereoSources;
2277 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2278 data[i++] = device->NumAuxSends;
2280 data[i++] = 0;
2282 break;
2284 case ALC_FREQUENCY:
2285 *data = device->Frequency;
2286 break;
2288 case ALC_REFRESH:
2289 if(device->Type == Loopback)
2290 alcSetError(device, ALC_INVALID_DEVICE);
2291 else
2292 *data = device->Frequency / device->UpdateSize;
2293 break;
2295 case ALC_SYNC:
2296 if(device->Type == Loopback)
2297 alcSetError(device, ALC_INVALID_DEVICE);
2298 else
2299 *data = ALC_FALSE;
2300 break;
2302 case ALC_FORMAT_CHANNELS_SOFT:
2303 if(device->Type != Loopback)
2304 alcSetError(device, ALC_INVALID_DEVICE);
2305 else
2306 *data = device->FmtChans;
2307 break;
2309 case ALC_FORMAT_TYPE_SOFT:
2310 if(device->Type != Loopback)
2311 alcSetError(device, ALC_INVALID_DEVICE);
2312 else
2313 *data = device->FmtType;
2314 break;
2316 case ALC_MONO_SOURCES:
2317 *data = device->NumMonoSources;
2318 break;
2320 case ALC_STEREO_SOURCES:
2321 *data = device->NumStereoSources;
2322 break;
2324 case ALC_MAX_AUXILIARY_SENDS:
2325 *data = device->NumAuxSends;
2326 break;
2328 case ALC_CONNECTED:
2329 *data = device->Connected;
2330 break;
2332 default:
2333 alcSetError(device, ALC_INVALID_ENUM);
2334 break;
2337 if(device)
2338 ALCdevice_DecRef(device);
2342 /* alcIsExtensionPresent
2344 * Determines if there is support for a particular extension
2346 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2348 ALCboolean bResult = ALC_FALSE;
2350 device = VerifyDevice(device);
2352 if(!extName)
2353 alcSetError(device, ALC_INVALID_VALUE);
2354 else
2356 size_t len = strlen(extName);
2357 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2358 while(ptr && *ptr)
2360 if(strncasecmp(ptr, extName, len) == 0 &&
2361 (ptr[len] == '\0' || isspace(ptr[len])))
2363 bResult = ALC_TRUE;
2364 break;
2366 if((ptr=strchr(ptr, ' ')) != NULL)
2368 do {
2369 ++ptr;
2370 } while(isspace(*ptr));
2374 if(device)
2375 ALCdevice_DecRef(device);
2376 return bResult;
2380 /* alcGetProcAddress
2382 * Retrieves the function address for a particular extension function
2384 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2386 ALCvoid *ptr = NULL;
2388 if(!funcName)
2390 device = VerifyDevice(device);
2391 alcSetError(device, ALC_INVALID_VALUE);
2392 if(device) ALCdevice_DecRef(device);
2394 else
2396 ALsizei i = 0;
2397 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2398 i++;
2399 ptr = alcFunctions[i].address;
2402 return ptr;
2406 /* alcGetEnumValue
2408 * Get the value for a particular ALC enumeration name
2410 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2412 ALCenum val = 0;
2414 if(!enumName)
2416 device = VerifyDevice(device);
2417 alcSetError(device, ALC_INVALID_VALUE);
2418 if(device) ALCdevice_DecRef(device);
2420 else
2422 ALsizei i = 0;
2423 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2424 i++;
2425 val = enumeration[i].value;
2428 return val;
2432 /* alcCreateContext
2434 * Create and attach a context to the given device.
2436 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2438 ALCcontext *ALContext;
2439 ALCenum err;
2441 LockLists();
2442 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2444 UnlockLists();
2445 alcSetError(device, ALC_INVALID_DEVICE);
2446 if(device) ALCdevice_DecRef(device);
2447 return NULL;
2450 device->LastError = ALC_NO_ERROR;
2452 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2454 UnlockLists();
2455 alcSetError(device, err);
2456 if(err == ALC_INVALID_DEVICE)
2457 aluHandleDisconnect(device);
2458 ALCdevice_DecRef(device);
2459 return NULL;
2462 ALContext = calloc(1, sizeof(ALCcontext));
2463 if(ALContext)
2465 ALContext->ref = 1;
2467 ALContext->MaxActiveSources = 256;
2468 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2469 ALContext->MaxActiveSources);
2471 if(!ALContext || !ALContext->ActiveSources)
2473 if(!device->ContextList)
2475 ALCdevice_StopPlayback(device);
2476 device->Flags &= ~DEVICE_RUNNING;
2478 UnlockLists();
2480 free(ALContext);
2481 ALContext = NULL;
2483 alcSetError(device, ALC_OUT_OF_MEMORY);
2484 ALCdevice_DecRef(device);
2485 return NULL;
2488 ALContext->Device = device;
2489 ALCdevice_IncRef(device);
2490 InitContext(ALContext);
2492 do {
2493 ALContext->next = device->ContextList;
2494 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2495 UnlockLists();
2497 ALCdevice_DecRef(device);
2499 TRACE("Created context %p\n", ALContext);
2500 return ALContext;
2503 /* alcDestroyContext
2505 * Remove a context from its device
2507 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2509 ALCdevice *Device;
2511 LockLists();
2512 /* alcGetContextsDevice sets an error for invalid contexts */
2513 Device = alcGetContextsDevice(context);
2514 if(Device)
2516 ReleaseContext(context, Device);
2517 if(!Device->ContextList)
2519 ALCdevice_StopPlayback(Device);
2520 Device->Flags &= ~DEVICE_RUNNING;
2523 UnlockLists();
2527 /* alcGetCurrentContext
2529 * Returns the currently active context on the calling thread
2531 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2533 ALCcontext *Context;
2535 Context = pthread_getspecific(LocalContext);
2536 if(!Context) Context = GlobalContext;
2538 return Context;
2541 /* alcGetThreadContext
2543 * Returns the currently active thread-local context
2545 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2547 ALCcontext *Context;
2548 Context = pthread_getspecific(LocalContext);
2549 return Context;
2553 /* alcMakeContextCurrent
2555 * Makes the given context the active process-wide context, and removes the
2556 * thread-local context for the calling thread.
2558 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2560 /* context must be valid or NULL */
2561 if(context && !(context=VerifyContext(context)))
2563 alcSetError(NULL, ALC_INVALID_CONTEXT);
2564 return ALC_FALSE;
2566 /* context's reference count is already incremented */
2567 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2568 if(context) ALCcontext_DecRef(context);
2570 if((context=pthread_getspecific(LocalContext)) != NULL)
2572 pthread_setspecific(LocalContext, NULL);
2573 ALCcontext_DecRef(context);
2576 return ALC_TRUE;
2579 /* alcSetThreadContext
2581 * Makes the given context the active context for the current thread
2583 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2585 ALCcontext *old;
2587 /* context must be valid or NULL */
2588 if(context && !(context=VerifyContext(context)))
2590 alcSetError(NULL, ALC_INVALID_CONTEXT);
2591 return ALC_FALSE;
2593 /* context's reference count is already incremented */
2594 old = pthread_getspecific(LocalContext);
2595 pthread_setspecific(LocalContext, context);
2596 if(old) ALCcontext_DecRef(old);
2598 return ALC_TRUE;
2602 /* alcGetContextsDevice
2604 * Returns the device that a particular context is attached to
2606 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2608 ALCdevice *Device;
2610 if(!(Context=VerifyContext(Context)))
2612 alcSetError(NULL, ALC_INVALID_CONTEXT);
2613 return NULL;
2615 Device = Context->Device;
2616 ALCcontext_DecRef(Context);
2618 return Device;
2622 /* alcOpenDevice
2624 * Opens the named device.
2626 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2628 const ALCchar *fmt;
2629 ALCdevice *device;
2630 ALCenum err;
2632 DO_INITCONFIG();
2634 if(!PlaybackBackend.name)
2636 alcSetError(NULL, ALC_INVALID_VALUE);
2637 return NULL;
2640 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2641 deviceName = NULL;
2643 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
2644 if(!device)
2646 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2647 return NULL;
2650 //Validate device
2651 device->Funcs = &PlaybackBackend.Funcs;
2652 device->ref = 1;
2653 device->Connected = ALC_TRUE;
2654 device->Type = Playback;
2655 InitializeCriticalSection(&device->Mutex);
2656 device->LastError = ALC_NO_ERROR;
2658 device->Flags = 0;
2659 device->Bs2b = NULL;
2660 device->Bs2bLevel = 0;
2661 device->DeviceName = NULL;
2663 device->ContextList = NULL;
2665 device->MaxNoOfSources = 256;
2666 device->AuxiliaryEffectSlotMax = 4;
2667 device->NumAuxSends = MAX_SENDS;
2669 InitUIntMap(&device->BufferMap, ~0);
2670 InitUIntMap(&device->EffectMap, ~0);
2671 InitUIntMap(&device->FilterMap, ~0);
2673 //Set output format
2674 device->FmtChans = DevFmtChannelsDefault;
2675 device->FmtType = DevFmtTypeDefault;
2676 device->Frequency = DEFAULT_OUTPUT_RATE;
2677 device->NumUpdates = 4;
2678 device->UpdateSize = 1024;
2680 if(ConfigValueStr(NULL, "channels", &fmt))
2682 static const struct {
2683 const char name[16];
2684 enum DevFmtChannels chans;
2685 } chanlist[] = {
2686 { "mono", DevFmtMono },
2687 { "stereo", DevFmtStereo },
2688 { "quad", DevFmtQuad },
2689 { "surround51", DevFmtX51 },
2690 { "surround61", DevFmtX61 },
2691 { "surround71", DevFmtX71 },
2693 size_t i;
2695 for(i = 0;i < COUNTOF(chanlist);i++)
2697 if(strcasecmp(chanlist[i].name, fmt) == 0)
2699 device->FmtChans = chanlist[i].chans;
2700 device->Flags |= DEVICE_CHANNELS_REQUEST;
2701 break;
2704 if(i == COUNTOF(chanlist))
2705 ERR("Unsupported channels: %s\n", fmt);
2707 if(ConfigValueStr(NULL, "sample-type", &fmt))
2709 static const struct {
2710 const char name[16];
2711 enum DevFmtType type;
2712 } typelist[] = {
2713 { "int8", DevFmtByte },
2714 { "uint8", DevFmtUByte },
2715 { "int16", DevFmtShort },
2716 { "uint16", DevFmtUShort },
2717 { "int32", DevFmtInt },
2718 { "uint32", DevFmtUInt },
2719 { "float32", DevFmtFloat },
2721 size_t i;
2723 for(i = 0;i < COUNTOF(typelist);i++)
2725 if(strcasecmp(typelist[i].name, fmt) == 0)
2727 device->FmtType = typelist[i].type;
2728 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2729 break;
2732 if(i == COUNTOF(typelist))
2733 ERR("Unsupported sample-type: %s\n", fmt);
2735 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2736 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2737 ConfigValueStr(NULL, "format", &fmt))
2739 static const struct {
2740 const char name[32];
2741 enum DevFmtChannels channels;
2742 enum DevFmtType type;
2743 } formats[] = {
2744 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2745 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2746 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2747 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2748 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2749 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2751 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2752 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2753 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2754 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2755 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2756 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2758 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2759 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2760 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2761 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2762 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2763 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2765 size_t i;
2767 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2768 for(i = 0;i < COUNTOF(formats);i++)
2770 if(strcasecmp(fmt, formats[i].name) == 0)
2772 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2773 device->FmtChans = formats[i].channels;
2774 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2775 device->FmtType = formats[i].type;
2776 device->Flags |= DEVICE_FORMAT_REQUEST;
2777 break;
2780 if(i == COUNTOF(formats))
2781 ERR("Unsupported format: %s\n", fmt);
2783 #undef DEVICE_FORMAT_REQUEST
2785 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2787 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2788 if(device->Frequency < MIN_OUTPUT_RATE)
2789 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2790 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2793 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2794 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2796 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2797 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2799 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2800 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2802 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2803 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2805 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2806 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2808 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2810 device->NumStereoSources = 1;
2811 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2813 // Find a playback device to open
2814 LockLists();
2815 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2817 UnlockLists();
2818 DeleteCriticalSection(&device->Mutex);
2819 al_free(device);
2820 alcSetError(NULL, err);
2821 return NULL;
2823 UnlockLists();
2825 if(DefaultEffect.type != AL_EFFECT_NULL)
2827 device->DefaultSlot = (ALeffectslot*)(device+1);
2828 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2830 device->DefaultSlot = NULL;
2831 ERR("Failed to initialize the default effect slot\n");
2833 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2835 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2836 device->DefaultSlot = NULL;
2837 ERR("Failed to initialize the default effect\n");
2841 do {
2842 device->next = DeviceList;
2843 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2845 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2846 return device;
2849 /* alcCloseDevice
2851 * Closes the given device.
2853 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2855 ALCdevice *volatile*list;
2856 ALCcontext *ctx;
2858 LockLists();
2859 list = &DeviceList;
2860 while(*list && *list != Device)
2861 list = &(*list)->next;
2863 if(!*list || (*list)->Type == Capture)
2865 alcSetError(*list, ALC_INVALID_DEVICE);
2866 UnlockLists();
2867 return ALC_FALSE;
2870 *list = (*list)->next;
2871 UnlockLists();
2873 while((ctx=Device->ContextList) != NULL)
2875 WARN("Releasing context %p\n", ctx);
2876 ReleaseContext(ctx, Device);
2878 if((Device->Flags&DEVICE_RUNNING))
2879 ALCdevice_StopPlayback(Device);
2880 Device->Flags &= ~DEVICE_RUNNING;
2882 ALCdevice_DecRef(Device);
2884 return ALC_TRUE;
2888 /************************************************
2889 * ALC capture functions
2890 ************************************************/
2891 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2893 ALCdevice *device = NULL;
2894 ALCenum err;
2896 DO_INITCONFIG();
2898 if(!CaptureBackend.name)
2900 alcSetError(NULL, ALC_INVALID_VALUE);
2901 return NULL;
2904 if(samples <= 0)
2906 alcSetError(NULL, ALC_INVALID_VALUE);
2907 return NULL;
2910 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2911 deviceName = NULL;
2913 device = al_calloc(16, sizeof(ALCdevice));
2914 if(!device)
2916 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2917 return NULL;
2920 //Validate device
2921 device->Funcs = &CaptureBackend.Funcs;
2922 device->ref = 1;
2923 device->Connected = ALC_TRUE;
2924 device->Type = Capture;
2925 InitializeCriticalSection(&device->Mutex);
2927 InitUIntMap(&device->BufferMap, ~0);
2928 InitUIntMap(&device->EffectMap, ~0);
2929 InitUIntMap(&device->FilterMap, ~0);
2931 device->DeviceName = NULL;
2933 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2934 device->Frequency = frequency;
2936 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2937 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2939 DeleteCriticalSection(&device->Mutex);
2940 al_free(device);
2941 alcSetError(NULL, ALC_INVALID_ENUM);
2942 return NULL;
2945 device->UpdateSize = samples;
2946 device->NumUpdates = 1;
2948 LockLists();
2949 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2951 UnlockLists();
2952 DeleteCriticalSection(&device->Mutex);
2953 al_free(device);
2954 alcSetError(NULL, err);
2955 return NULL;
2957 UnlockLists();
2959 do {
2960 device->next = DeviceList;
2961 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2963 TRACE("Created device %p\n", device);
2964 return device;
2967 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2969 ALCdevice *volatile*list;
2971 LockLists();
2972 list = &DeviceList;
2973 while(*list && *list != Device)
2974 list = &(*list)->next;
2976 if(!*list || (*list)->Type != Capture)
2978 alcSetError(*list, ALC_INVALID_DEVICE);
2979 UnlockLists();
2980 return ALC_FALSE;
2983 *list = (*list)->next;
2984 UnlockLists();
2986 ALCdevice_DecRef(Device);
2988 return ALC_TRUE;
2991 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2993 LockLists();
2994 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2996 UnlockLists();
2997 alcSetError(device, ALC_INVALID_DEVICE);
2998 if(device) ALCdevice_DecRef(device);
2999 return;
3001 if(device->Connected)
3003 if(!(device->Flags&DEVICE_RUNNING))
3004 ALCdevice_StartCapture(device);
3005 device->Flags |= DEVICE_RUNNING;
3007 UnlockLists();
3009 ALCdevice_DecRef(device);
3012 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3014 LockLists();
3015 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3017 UnlockLists();
3018 alcSetError(device, ALC_INVALID_DEVICE);
3019 if(device) ALCdevice_DecRef(device);
3020 return;
3022 if((device->Flags&DEVICE_RUNNING))
3023 ALCdevice_StopCapture(device);
3024 device->Flags &= ~DEVICE_RUNNING;
3025 UnlockLists();
3027 ALCdevice_DecRef(device);
3030 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3032 ALCenum err = ALC_INVALID_DEVICE;
3033 LockLists();
3034 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3036 err = ALC_INVALID_VALUE;
3037 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3038 err = ALCdevice_CaptureSamples(device, buffer, samples);
3040 UnlockLists();
3041 if(err != ALC_NO_ERROR)
3042 alcSetError(device, err);
3043 if(device) ALCdevice_DecRef(device);
3047 /************************************************
3048 * ALC loopback functions
3049 ************************************************/
3051 /* alcLoopbackOpenDeviceSOFT
3053 * Open a loopback device, for manual rendering.
3055 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3057 ALCdevice *device;
3059 DO_INITCONFIG();
3061 /* Make sure the device name, if specified, is us. */
3062 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3064 alcSetError(NULL, ALC_INVALID_VALUE);
3065 return NULL;
3068 device = al_calloc(16, sizeof(ALCdevice));
3069 if(!device)
3071 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3072 return NULL;
3075 //Validate device
3076 device->Funcs = &BackendLoopback.Funcs;
3077 device->ref = 1;
3078 device->Connected = ALC_TRUE;
3079 device->Type = Loopback;
3080 InitializeCriticalSection(&device->Mutex);
3081 device->LastError = ALC_NO_ERROR;
3083 device->Flags = 0;
3084 device->Bs2b = NULL;
3085 device->Bs2bLevel = 0;
3086 device->DeviceName = NULL;
3088 device->ContextList = NULL;
3090 device->MaxNoOfSources = 256;
3091 device->AuxiliaryEffectSlotMax = 4;
3092 device->NumAuxSends = MAX_SENDS;
3094 InitUIntMap(&device->BufferMap, ~0);
3095 InitUIntMap(&device->EffectMap, ~0);
3096 InitUIntMap(&device->FilterMap, ~0);
3098 //Set output format
3099 device->NumUpdates = 0;
3100 device->UpdateSize = 0;
3102 device->Frequency = DEFAULT_OUTPUT_RATE;
3103 device->FmtChans = DevFmtChannelsDefault;
3104 device->FmtType = DevFmtTypeDefault;
3106 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3107 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3109 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3110 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3112 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3113 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3115 device->NumStereoSources = 1;
3116 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3118 // Open the "backend"
3119 ALCdevice_OpenPlayback(device, "Loopback");
3120 do {
3121 device->next = DeviceList;
3122 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3124 TRACE("Created device %p\n", device);
3125 return device;
3128 /* alcIsRenderFormatSupportedSOFT
3130 * Determines if the loopback device supports the given format for rendering.
3132 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3134 ALCboolean ret = ALC_FALSE;
3136 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3137 alcSetError(device, ALC_INVALID_DEVICE);
3138 else if(freq <= 0)
3139 alcSetError(device, ALC_INVALID_VALUE);
3140 else
3142 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3143 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3144 freq >= MIN_OUTPUT_RATE)
3145 ret = ALC_TRUE;
3147 if(device) ALCdevice_DecRef(device);
3149 return ret;
3152 /* alcRenderSamplesSOFT
3154 * Renders some samples into a buffer, using the format last set by the
3155 * attributes given to alcCreateContext.
3157 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3159 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3160 alcSetError(device, ALC_INVALID_DEVICE);
3161 else if(samples < 0 || (samples > 0 && buffer == NULL))
3162 alcSetError(device, ALC_INVALID_VALUE);
3163 else
3164 aluMixData(device, buffer, samples);
3165 if(device) ALCdevice_DecRef(device);