Warn about SSE performance with non-multiple-of-4 update sizes
[openal-soft.git] / Alc / ALc.c
blob4914ae7f7e0a683c0547bf33b1177b369c50486b
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 #ifdef _WIN32
840 RTPrioLevel = 1;
841 #else
842 RTPrioLevel = 0;
843 #endif
844 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
846 if(ConfigValueStr(NULL, "resampler", &str))
848 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
849 DefaultResampler = PointResampler;
850 else if(strcasecmp(str, "linear") == 0)
851 DefaultResampler = LinearResampler;
852 else if(strcasecmp(str, "cubic") == 0)
853 DefaultResampler = CubicResampler;
854 else
856 char *end;
858 n = strtol(str, &end, 0);
859 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
860 DefaultResampler = n;
861 else
862 WARN("Invalid resampler: %s\n", str);
866 str = getenv("ALSOFT_TRAP_ERROR");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
869 TrapALError = AL_TRUE;
870 TrapALCError = AL_TRUE;
872 else
874 str = getenv("ALSOFT_TRAP_AL_ERROR");
875 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
876 TrapALError = AL_TRUE;
877 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
879 str = getenv("ALSOFT_TRAP_ALC_ERROR");
880 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
881 TrapALCError = ALC_TRUE;
882 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
885 if(ConfigValueFloat("reverb", "boost", &valf))
886 ReverbBoost *= powf(10.0f, valf / 20.0f);
888 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
890 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
891 ConfigValueStr(NULL, "drivers", &devs))
893 int n;
894 size_t len;
895 const char *next = devs;
896 int endlist, delitem;
898 i = 0;
899 do {
900 devs = next;
901 next = strchr(devs, ',');
903 delitem = (devs[0] == '-');
904 if(devs[0] == '-') devs++;
906 if(!devs[0] || devs[0] == ',')
908 endlist = 0;
909 continue;
911 endlist = 1;
913 len = (next ? ((size_t)(next-devs)) : strlen(devs));
914 for(n = i;BackendList[n].Init;n++)
916 if(len == strlen(BackendList[n].name) &&
917 strncmp(BackendList[n].name, devs, len) == 0)
919 if(delitem)
921 do {
922 BackendList[n] = BackendList[n+1];
923 ++n;
924 } while(BackendList[n].Init);
926 else
928 struct BackendInfo Bkp = BackendList[n];
929 while(n > i)
931 BackendList[n] = BackendList[n-1];
932 --n;
934 BackendList[n] = Bkp;
936 i++;
938 break;
941 } while(next++);
943 if(endlist)
945 BackendList[i].name = NULL;
946 BackendList[i].Init = NULL;
947 BackendList[i].Deinit = NULL;
948 BackendList[i].Probe = NULL;
952 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
954 if(!BackendList[i].Init(&BackendList[i].Funcs))
956 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
957 continue;
960 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
961 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
963 PlaybackBackend = BackendList[i];
964 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
966 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
968 CaptureBackend = BackendList[i];
969 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
972 BackendLoopback.Init(&BackendLoopback.Funcs);
974 if(ConfigValueStr(NULL, "excludefx", &str))
976 size_t len;
977 const char *next = str;
979 do {
980 str = next;
981 next = strchr(str, ',');
983 if(!str[0] || next == str)
984 continue;
986 len = (next ? ((size_t)(next-str)) : strlen(str));
987 for(n = 0;EffectList[n].name;n++)
989 if(len == strlen(EffectList[n].name) &&
990 strncmp(EffectList[n].name, str, len) == 0)
991 DisabledEffects[EffectList[n].type] = AL_TRUE;
993 } while(next++);
996 InitEffect(&DefaultEffect);
997 str = getenv("ALSOFT_DEFAULT_REVERB");
998 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
999 LoadReverbPreset(str, &DefaultEffect);
1001 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1004 /************************************************
1005 * Library deinitialization
1006 ************************************************/
1007 static void alc_cleanup(void)
1009 ALCdevice *dev;
1011 free(alcAllDevicesList); alcAllDevicesList = NULL;
1012 alcAllDevicesListSize = 0;
1013 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1014 alcCaptureDeviceListSize = 0;
1016 free(alcDefaultAllDevicesSpecifier);
1017 alcDefaultAllDevicesSpecifier = NULL;
1018 free(alcCaptureDefaultDeviceSpecifier);
1019 alcCaptureDefaultDeviceSpecifier = NULL;
1021 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1023 ALCuint num = 0;
1024 do {
1025 num++;
1026 } while((dev=dev->next) != NULL);
1027 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1031 static void alc_deinit_safe(void)
1033 alc_cleanup();
1035 FreeHrtfs();
1036 FreeALConfig();
1038 ThunkExit();
1039 DeleteCriticalSection(&ListLock);
1040 pthread_key_delete(LocalContext);
1042 if(LogFile != stderr)
1043 fclose(LogFile);
1044 LogFile = NULL;
1047 static void alc_deinit(void)
1049 int i;
1051 alc_cleanup();
1053 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1054 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1056 for(i = 0;BackendList[i].Deinit;i++)
1057 BackendList[i].Deinit();
1058 BackendLoopback.Deinit();
1060 alc_deinit_safe();
1064 /************************************************
1065 * Device enumeration
1066 ************************************************/
1067 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1069 DO_INITCONFIG();
1071 LockLists();
1072 free(*list);
1073 *list = NULL;
1074 *listsize = 0;
1076 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1077 PlaybackBackend.Probe(type);
1078 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1079 CaptureBackend.Probe(type);
1080 UnlockLists();
1083 static void ProbeAllDevicesList(void)
1084 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1085 static void ProbeCaptureDeviceList(void)
1086 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1089 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1091 size_t len = strlen(name);
1092 void *temp;
1094 if(len == 0)
1095 return;
1097 temp = realloc(*List, (*ListSize) + len + 2);
1098 if(!temp)
1100 ERR("Realloc failed to add %s!\n", name);
1101 return;
1103 *List = temp;
1105 memcpy((*List)+(*ListSize), name, len+1);
1106 *ListSize += len+1;
1107 (*List)[*ListSize] = 0;
1110 #define DECL_APPEND_LIST_FUNC(type) \
1111 void Append##type##List(const ALCchar *name) \
1112 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1114 DECL_APPEND_LIST_FUNC(AllDevices)
1115 DECL_APPEND_LIST_FUNC(CaptureDevice)
1117 #undef DECL_APPEND_LIST_FUNC
1120 /************************************************
1121 * Device format information
1122 ************************************************/
1123 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1125 switch(type)
1127 case DevFmtByte: return "Signed Byte";
1128 case DevFmtUByte: return "Unsigned Byte";
1129 case DevFmtShort: return "Signed Short";
1130 case DevFmtUShort: return "Unsigned Short";
1131 case DevFmtInt: return "Signed Int";
1132 case DevFmtUInt: return "Unsigned Int";
1133 case DevFmtFloat: return "Float";
1135 return "(unknown type)";
1137 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1139 switch(chans)
1141 case DevFmtMono: return "Mono";
1142 case DevFmtStereo: return "Stereo";
1143 case DevFmtQuad: return "Quadraphonic";
1144 case DevFmtX51: return "5.1 Surround";
1145 case DevFmtX51Side: return "5.1 Side";
1146 case DevFmtX61: return "6.1 Surround";
1147 case DevFmtX71: return "7.1 Surround";
1149 return "(unknown channels)";
1152 ALuint BytesFromDevFmt(enum DevFmtType type)
1154 switch(type)
1156 case DevFmtByte: return sizeof(ALbyte);
1157 case DevFmtUByte: return sizeof(ALubyte);
1158 case DevFmtShort: return sizeof(ALshort);
1159 case DevFmtUShort: return sizeof(ALushort);
1160 case DevFmtInt: return sizeof(ALint);
1161 case DevFmtUInt: return sizeof(ALuint);
1162 case DevFmtFloat: return sizeof(ALfloat);
1164 return 0;
1166 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1168 switch(chans)
1170 case DevFmtMono: return 1;
1171 case DevFmtStereo: return 2;
1172 case DevFmtQuad: return 4;
1173 case DevFmtX51: return 6;
1174 case DevFmtX51Side: return 6;
1175 case DevFmtX61: return 7;
1176 case DevFmtX71: return 8;
1178 return 0;
1181 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1182 enum DevFmtType *type)
1184 static const struct {
1185 ALenum format;
1186 enum DevFmtChannels channels;
1187 enum DevFmtType type;
1188 } list[] = {
1189 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1190 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1191 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1193 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1194 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1195 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1197 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1198 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1199 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1201 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1202 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1203 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1205 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1206 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1207 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1209 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1210 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1211 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1213 ALuint i;
1215 for(i = 0;i < COUNTOF(list);i++)
1217 if(list[i].format == format)
1219 *chans = list[i].channels;
1220 *type = list[i].type;
1221 return AL_TRUE;
1225 return AL_FALSE;
1228 static ALCboolean IsValidALCType(ALCenum type)
1230 switch(type)
1232 case ALC_BYTE_SOFT:
1233 case ALC_UNSIGNED_BYTE_SOFT:
1234 case ALC_SHORT_SOFT:
1235 case ALC_UNSIGNED_SHORT_SOFT:
1236 case ALC_INT_SOFT:
1237 case ALC_UNSIGNED_INT_SOFT:
1238 case ALC_FLOAT_SOFT:
1239 return ALC_TRUE;
1241 return ALC_FALSE;
1244 static ALCboolean IsValidALCChannels(ALCenum channels)
1246 switch(channels)
1248 case ALC_MONO_SOFT:
1249 case ALC_STEREO_SOFT:
1250 case ALC_QUAD_SOFT:
1251 case ALC_5POINT1_SOFT:
1252 case ALC_6POINT1_SOFT:
1253 case ALC_7POINT1_SOFT:
1254 return ALC_TRUE;
1256 return ALC_FALSE;
1260 /************************************************
1261 * Miscellaneous ALC helpers
1262 ************************************************/
1264 void ALCdevice_LockDefault(ALCdevice *device)
1266 EnterCriticalSection(&device->Mutex);
1268 void ALCdevice_UnlockDefault(ALCdevice *device)
1270 LeaveCriticalSection(&device->Mutex);
1272 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
1274 (void)device;
1275 return 0;
1278 /* SetDefaultWFXChannelOrder
1280 * Sets the default channel order used by WaveFormatEx.
1282 void SetDefaultWFXChannelOrder(ALCdevice *device)
1284 switch(device->FmtChans)
1286 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1288 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1289 device->DevChannels[1] = FrontRight; break;
1291 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1292 device->DevChannels[1] = FrontRight;
1293 device->DevChannels[2] = BackLeft;
1294 device->DevChannels[3] = BackRight; break;
1296 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1297 device->DevChannels[1] = FrontRight;
1298 device->DevChannels[2] = FrontCenter;
1299 device->DevChannels[3] = LFE;
1300 device->DevChannels[4] = BackLeft;
1301 device->DevChannels[5] = BackRight; break;
1303 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1304 device->DevChannels[1] = FrontRight;
1305 device->DevChannels[2] = FrontCenter;
1306 device->DevChannels[3] = LFE;
1307 device->DevChannels[4] = SideLeft;
1308 device->DevChannels[5] = SideRight; break;
1310 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1311 device->DevChannels[1] = FrontRight;
1312 device->DevChannels[2] = FrontCenter;
1313 device->DevChannels[3] = LFE;
1314 device->DevChannels[4] = BackCenter;
1315 device->DevChannels[5] = SideLeft;
1316 device->DevChannels[6] = SideRight; break;
1318 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1319 device->DevChannels[1] = FrontRight;
1320 device->DevChannels[2] = FrontCenter;
1321 device->DevChannels[3] = LFE;
1322 device->DevChannels[4] = BackLeft;
1323 device->DevChannels[5] = BackRight;
1324 device->DevChannels[6] = SideLeft;
1325 device->DevChannels[7] = SideRight; break;
1329 /* SetDefaultChannelOrder
1331 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1333 void SetDefaultChannelOrder(ALCdevice *device)
1335 switch(device->FmtChans)
1337 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1338 device->DevChannels[1] = FrontRight;
1339 device->DevChannels[2] = BackLeft;
1340 device->DevChannels[3] = BackRight;
1341 device->DevChannels[4] = FrontCenter;
1342 device->DevChannels[5] = LFE;
1343 return;
1345 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1346 device->DevChannels[1] = FrontRight;
1347 device->DevChannels[2] = BackLeft;
1348 device->DevChannels[3] = BackRight;
1349 device->DevChannels[4] = FrontCenter;
1350 device->DevChannels[5] = LFE;
1351 device->DevChannels[6] = SideLeft;
1352 device->DevChannels[7] = SideRight;
1353 return;
1355 /* Same as WFX order */
1356 case DevFmtMono:
1357 case DevFmtStereo:
1358 case DevFmtQuad:
1359 case DevFmtX51Side:
1360 case DevFmtX61:
1361 break;
1363 SetDefaultWFXChannelOrder(device);
1367 /* alcSetError
1369 * Stores the latest ALC device error
1371 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1373 if(TrapALCError)
1375 #ifdef _WIN32
1376 /* DebugBreak() will cause an exception if there is no debugger */
1377 if(IsDebuggerPresent())
1378 DebugBreak();
1379 #elif defined(SIGTRAP)
1380 raise(SIGTRAP);
1381 #endif
1384 if(device)
1385 device->LastError = errorCode;
1386 else
1387 LastNullDeviceError = errorCode;
1391 /* UpdateDeviceParams
1393 * Updates device parameters according to the attribute list (caller is
1394 * responsible for holding the list lock).
1396 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1398 ALCcontext *context;
1399 enum DevFmtChannels oldChans;
1400 enum DevFmtType oldType;
1401 ALCuint oldFreq;
1402 int oldMode;
1403 ALuint i;
1405 // Check for attributes
1406 if(device->Type == Loopback)
1408 enum {
1409 GotFreq = 1<<0,
1410 GotChans = 1<<1,
1411 GotType = 1<<2,
1412 GotAll = GotFreq|GotChans|GotType
1414 ALCuint freq, numMono, numStereo, numSends;
1415 enum DevFmtChannels schans;
1416 enum DevFmtType stype;
1417 ALCuint attrIdx = 0;
1418 ALCint gotFmt = 0;
1420 if(!attrList)
1422 WARN("Missing attributes for loopback device\n");
1423 return ALC_INVALID_VALUE;
1426 numMono = device->NumMonoSources;
1427 numStereo = device->NumStereoSources;
1428 numSends = device->NumAuxSends;
1429 schans = device->FmtChans;
1430 stype = device->FmtType;
1431 freq = device->Frequency;
1433 while(attrList[attrIdx])
1435 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1437 ALCint val = attrList[attrIdx + 1];
1438 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1439 return ALC_INVALID_VALUE;
1440 schans = val;
1441 gotFmt |= GotChans;
1444 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1446 ALCint val = attrList[attrIdx + 1];
1447 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1448 return ALC_INVALID_VALUE;
1449 stype = val;
1450 gotFmt |= GotType;
1453 if(attrList[attrIdx] == ALC_FREQUENCY)
1455 freq = attrList[attrIdx + 1];
1456 if(freq < MIN_OUTPUT_RATE)
1457 return ALC_INVALID_VALUE;
1458 gotFmt |= GotFreq;
1461 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1463 numStereo = attrList[attrIdx + 1];
1464 if(numStereo > device->MaxNoOfSources)
1465 numStereo = device->MaxNoOfSources;
1467 numMono = device->MaxNoOfSources - numStereo;
1470 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1471 numSends = attrList[attrIdx + 1];
1473 attrIdx += 2;
1476 if(gotFmt != GotAll)
1478 WARN("Missing format for loopback device\n");
1479 return ALC_INVALID_VALUE;
1482 ConfigValueUInt(NULL, "sends", &numSends);
1483 numSends = minu(MAX_SENDS, numSends);
1485 if((device->Flags&DEVICE_RUNNING))
1486 ALCdevice_StopPlayback(device);
1487 device->Flags &= ~DEVICE_RUNNING;
1489 device->Frequency = freq;
1490 device->FmtChans = schans;
1491 device->FmtType = stype;
1492 device->NumMonoSources = numMono;
1493 device->NumStereoSources = numStereo;
1494 device->NumAuxSends = numSends;
1496 else if(attrList && attrList[0])
1498 ALCuint freq, numMono, numStereo, numSends;
1499 ALCuint attrIdx = 0;
1501 /* If a context is already running on the device, stop playback so the
1502 * device attributes can be updated. */
1503 if((device->Flags&DEVICE_RUNNING))
1504 ALCdevice_StopPlayback(device);
1505 device->Flags &= ~DEVICE_RUNNING;
1507 freq = device->Frequency;
1508 numMono = device->NumMonoSources;
1509 numStereo = device->NumStereoSources;
1510 numSends = device->NumAuxSends;
1512 while(attrList[attrIdx])
1514 if(attrList[attrIdx] == ALC_FREQUENCY)
1516 freq = attrList[attrIdx + 1];
1517 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1520 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1522 numStereo = attrList[attrIdx + 1];
1523 if(numStereo > device->MaxNoOfSources)
1524 numStereo = device->MaxNoOfSources;
1526 numMono = device->MaxNoOfSources - numStereo;
1529 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1530 numSends = attrList[attrIdx + 1];
1532 attrIdx += 2;
1535 ConfigValueUInt(NULL, "frequency", &freq);
1536 freq = maxu(freq, MIN_OUTPUT_RATE);
1538 ConfigValueUInt(NULL, "sends", &numSends);
1539 numSends = minu(MAX_SENDS, numSends);
1541 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1542 device->Frequency;
1544 device->Frequency = freq;
1545 device->NumMonoSources = numMono;
1546 device->NumStereoSources = numStereo;
1547 device->NumAuxSends = numSends;
1550 if((device->Flags&DEVICE_RUNNING))
1551 return ALC_NO_ERROR;
1553 oldFreq = device->Frequency;
1554 oldChans = device->FmtChans;
1555 oldType = device->FmtType;
1557 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1558 DevFmtChannelsString(device->FmtChans),
1559 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1560 DevFmtTypeString(device->FmtType),
1561 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1562 device->Frequency,
1563 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1564 device->UpdateSize, device->NumUpdates);
1566 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1567 return ALC_INVALID_DEVICE;
1569 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1571 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1572 DevFmtChannelsString(device->FmtChans));
1573 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1575 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1577 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1578 DevFmtTypeString(device->FmtType));
1579 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1581 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1583 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1584 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1587 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1588 DevFmtChannelsString(device->FmtChans),
1589 DevFmtTypeString(device->FmtType), device->Frequency,
1590 device->UpdateSize, device->NumUpdates);
1592 aluInitPanning(device);
1594 for(i = 0;i < MaxChannels;i++)
1596 device->ClickRemoval[i] = 0.0f;
1597 device->PendingClicks[i] = 0.0f;
1600 device->Hrtf = NULL;
1601 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1602 device->Hrtf = GetHrtf(device);
1603 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1605 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1607 if(!device->Bs2b)
1609 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1610 bs2b_clear(device->Bs2b);
1612 bs2b_set_srate(device->Bs2b, device->Frequency);
1613 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1614 TRACE("BS2B level %d\n", device->Bs2bLevel);
1616 else
1618 free(device->Bs2b);
1619 device->Bs2b = NULL;
1620 TRACE("BS2B disabled\n");
1623 device->Flags &= ~DEVICE_WIDE_STEREO;
1624 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1625 device->Flags |= DEVICE_WIDE_STEREO;
1627 if(!device->Hrtf && (device->UpdateSize&3))
1629 if((CPUCapFlags&CPU_CAP_SSE))
1630 WARN("SSE performance is degraded with a non-multiple of 4 update size (%u)\n", device->UpdateSize);
1633 oldMode = SetMixerFPUMode();
1634 ALCdevice_Lock(device);
1635 context = device->ContextList;
1636 while(context)
1638 ALsizei pos;
1640 context->UpdateSources = AL_FALSE;
1641 LockUIntMapRead(&context->EffectSlotMap);
1642 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1644 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1646 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1648 UnlockUIntMapRead(&context->EffectSlotMap);
1649 ALCdevice_Unlock(device);
1650 RestoreFPUMode(oldMode);
1651 return ALC_INVALID_DEVICE;
1653 slot->NeedsUpdate = AL_FALSE;
1654 ALeffectState_Update(slot->EffectState, device, slot);
1656 UnlockUIntMapRead(&context->EffectSlotMap);
1658 LockUIntMapRead(&context->SourceMap);
1659 for(pos = 0;pos < context->SourceMap.size;pos++)
1661 ALsource *source = context->SourceMap.array[pos].value;
1662 ALuint s = device->NumAuxSends;
1663 while(s < MAX_SENDS)
1665 if(source->Send[s].Slot)
1666 DecrementRef(&source->Send[s].Slot->ref);
1667 source->Send[s].Slot = NULL;
1668 source->Send[s].Gain = 1.0f;
1669 source->Send[s].GainHF = 1.0f;
1670 s++;
1672 source->NeedsUpdate = AL_FALSE;
1673 ALsource_Update(source, context);
1675 UnlockUIntMapRead(&context->SourceMap);
1677 context = context->next;
1679 if(device->DefaultSlot)
1681 ALeffectslot *slot = device->DefaultSlot;
1683 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1685 ALCdevice_Unlock(device);
1686 RestoreFPUMode(oldMode);
1687 return ALC_INVALID_DEVICE;
1689 slot->NeedsUpdate = AL_FALSE;
1690 ALeffectState_Update(slot->EffectState, device, slot);
1692 ALCdevice_Unlock(device);
1693 RestoreFPUMode(oldMode);
1695 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1696 return ALC_INVALID_DEVICE;
1697 device->Flags |= DEVICE_RUNNING;
1699 return ALC_NO_ERROR;
1702 /* FreeDevice
1704 * Frees the device structure, and destroys any objects the app failed to
1705 * delete. Called once there's no more references on the device.
1707 static ALCvoid FreeDevice(ALCdevice *device)
1709 TRACE("%p\n", device);
1711 if(device->Type != Capture)
1712 ALCdevice_ClosePlayback(device);
1713 else
1714 ALCdevice_CloseCapture(device);
1716 if(device->DefaultSlot)
1718 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1719 device->DefaultSlot->EffectState = NULL;
1722 if(device->BufferMap.size > 0)
1724 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1725 ReleaseALBuffers(device);
1727 ResetUIntMap(&device->BufferMap);
1729 if(device->EffectMap.size > 0)
1731 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1732 ReleaseALEffects(device);
1734 ResetUIntMap(&device->EffectMap);
1736 if(device->FilterMap.size > 0)
1738 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1739 ReleaseALFilters(device);
1741 ResetUIntMap(&device->FilterMap);
1743 free(device->Bs2b);
1744 device->Bs2b = NULL;
1746 free(device->DeviceName);
1747 device->DeviceName = NULL;
1749 DeleteCriticalSection(&device->Mutex);
1751 al_free(device);
1755 void ALCdevice_IncRef(ALCdevice *device)
1757 RefCount ref;
1758 ref = IncrementRef(&device->ref);
1759 TRACEREF("%p increasing refcount to %u\n", device, ref);
1762 void ALCdevice_DecRef(ALCdevice *device)
1764 RefCount ref;
1765 ref = DecrementRef(&device->ref);
1766 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1767 if(ref == 0) FreeDevice(device);
1770 /* VerifyDevice
1772 * Checks if the device handle is valid, and increments its ref count if so.
1774 static ALCdevice *VerifyDevice(ALCdevice *device)
1776 ALCdevice *tmpDevice;
1778 if(!device)
1779 return NULL;
1781 LockLists();
1782 tmpDevice = DeviceList;
1783 while(tmpDevice && tmpDevice != device)
1784 tmpDevice = tmpDevice->next;
1786 if(tmpDevice)
1787 ALCdevice_IncRef(tmpDevice);
1788 UnlockLists();
1789 return tmpDevice;
1793 /* InitContext
1795 * Initializes context fields
1797 static ALvoid InitContext(ALCcontext *Context)
1799 ALint i, j;
1801 //Initialise listener
1802 Context->Listener.Gain = 1.0f;
1803 Context->Listener.MetersPerUnit = 1.0f;
1804 Context->Listener.Position[0] = 0.0f;
1805 Context->Listener.Position[1] = 0.0f;
1806 Context->Listener.Position[2] = 0.0f;
1807 Context->Listener.Velocity[0] = 0.0f;
1808 Context->Listener.Velocity[1] = 0.0f;
1809 Context->Listener.Velocity[2] = 0.0f;
1810 Context->Listener.Forward[0] = 0.0f;
1811 Context->Listener.Forward[1] = 0.0f;
1812 Context->Listener.Forward[2] = -1.0f;
1813 Context->Listener.Up[0] = 0.0f;
1814 Context->Listener.Up[1] = 1.0f;
1815 Context->Listener.Up[2] = 0.0f;
1816 for(i = 0;i < 4;i++)
1818 for(j = 0;j < 4;j++)
1819 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1822 //Validate Context
1823 Context->LastError = AL_NO_ERROR;
1824 Context->UpdateSources = AL_FALSE;
1825 Context->ActiveSourceCount = 0;
1826 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1827 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1829 //Set globals
1830 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1831 Context->SourceDistanceModel = AL_FALSE;
1832 Context->DopplerFactor = 1.0f;
1833 Context->DopplerVelocity = 1.0f;
1834 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1835 Context->DeferUpdates = AL_FALSE;
1837 Context->ExtensionList = alExtList;
1841 /* FreeContext
1843 * Cleans up the context, and destroys any remaining objects the app failed to
1844 * delete. Called once there's no more references on the context.
1846 static ALCvoid FreeContext(ALCcontext *context)
1848 TRACE("%p\n", context);
1850 if(context->SourceMap.size > 0)
1852 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1853 ReleaseALSources(context);
1855 ResetUIntMap(&context->SourceMap);
1857 if(context->EffectSlotMap.size > 0)
1859 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1860 ReleaseALAuxiliaryEffectSlots(context);
1862 ResetUIntMap(&context->EffectSlotMap);
1864 context->ActiveSourceCount = 0;
1865 free(context->ActiveSources);
1866 context->ActiveSources = NULL;
1867 context->MaxActiveSources = 0;
1869 context->ActiveEffectSlotCount = 0;
1870 free(context->ActiveEffectSlots);
1871 context->ActiveEffectSlots = NULL;
1872 context->MaxActiveEffectSlots = 0;
1874 ALCdevice_DecRef(context->Device);
1875 context->Device = NULL;
1877 //Invalidate context
1878 memset(context, 0, sizeof(ALCcontext));
1879 free(context);
1882 /* ReleaseContext
1884 * Removes the context reference from the given device and removes it from
1885 * being current on the running thread or globally.
1887 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1889 ALCcontext *volatile*tmp_ctx;
1891 if(pthread_getspecific(LocalContext) == context)
1893 WARN("%p released while current on thread\n", context);
1894 pthread_setspecific(LocalContext, NULL);
1895 ALCcontext_DecRef(context);
1898 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1899 ALCcontext_DecRef(context);
1901 ALCdevice_Lock(device);
1902 tmp_ctx = &device->ContextList;
1903 while(*tmp_ctx)
1905 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1906 break;
1907 tmp_ctx = &(*tmp_ctx)->next;
1909 ALCdevice_Unlock(device);
1911 ALCcontext_DecRef(context);
1914 void ALCcontext_IncRef(ALCcontext *context)
1916 RefCount ref;
1917 ref = IncrementRef(&context->ref);
1918 TRACEREF("%p increasing refcount to %u\n", context, ref);
1921 void ALCcontext_DecRef(ALCcontext *context)
1923 RefCount ref;
1924 ref = DecrementRef(&context->ref);
1925 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1926 if(ref == 0) FreeContext(context);
1929 static void ReleaseThreadCtx(void *ptr)
1931 WARN("%p current for thread being destroyed\n", ptr);
1932 ALCcontext_DecRef(ptr);
1935 /* VerifyContext
1937 * Checks that the given context is valid, and increments its reference count.
1939 static ALCcontext *VerifyContext(ALCcontext *context)
1941 ALCdevice *dev;
1943 LockLists();
1944 dev = DeviceList;
1945 while(dev)
1947 ALCcontext *tmp_ctx = dev->ContextList;
1948 while(tmp_ctx)
1950 if(tmp_ctx == context)
1952 ALCcontext_IncRef(tmp_ctx);
1953 UnlockLists();
1954 return tmp_ctx;
1956 tmp_ctx = tmp_ctx->next;
1958 dev = dev->next;
1960 UnlockLists();
1962 return NULL;
1966 /* GetContextRef
1968 * Returns the currently active context for this thread, and adds a reference
1969 * without locking it.
1971 ALCcontext *GetContextRef(void)
1973 ALCcontext *context;
1975 context = pthread_getspecific(LocalContext);
1976 if(context)
1977 ALCcontext_IncRef(context);
1978 else
1980 LockLists();
1981 context = GlobalContext;
1982 if(context)
1983 ALCcontext_IncRef(context);
1984 UnlockLists();
1987 return context;
1991 /************************************************
1992 * Standard ALC functions
1993 ************************************************/
1995 /* alcGetError
1997 * Return last ALC generated error code for the given device
1999 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2001 ALCenum errorCode;
2003 if(VerifyDevice(device))
2005 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2006 ALCdevice_DecRef(device);
2008 else
2009 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2011 return errorCode;
2015 /* alcSuspendContext
2017 * Not functional
2019 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
2021 (void)Context;
2024 /* alcProcessContext
2026 * Not functional
2028 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2030 (void)Context;
2034 /* alcGetString
2036 * Returns information about the device, and error strings
2038 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2040 const ALCchar *value = NULL;
2042 switch(param)
2044 case ALC_NO_ERROR:
2045 value = alcNoError;
2046 break;
2048 case ALC_INVALID_ENUM:
2049 value = alcErrInvalidEnum;
2050 break;
2052 case ALC_INVALID_VALUE:
2053 value = alcErrInvalidValue;
2054 break;
2056 case ALC_INVALID_DEVICE:
2057 value = alcErrInvalidDevice;
2058 break;
2060 case ALC_INVALID_CONTEXT:
2061 value = alcErrInvalidContext;
2062 break;
2064 case ALC_OUT_OF_MEMORY:
2065 value = alcErrOutOfMemory;
2066 break;
2068 case ALC_DEVICE_SPECIFIER:
2069 value = alcDefaultName;
2070 break;
2072 case ALC_ALL_DEVICES_SPECIFIER:
2073 if(VerifyDevice(Device))
2075 value = Device->DeviceName;
2076 ALCdevice_DecRef(Device);
2078 else
2080 ProbeAllDevicesList();
2081 value = alcAllDevicesList;
2083 break;
2085 case ALC_CAPTURE_DEVICE_SPECIFIER:
2086 if(VerifyDevice(Device))
2088 value = Device->DeviceName;
2089 ALCdevice_DecRef(Device);
2091 else
2093 ProbeCaptureDeviceList();
2094 value = alcCaptureDeviceList;
2096 break;
2098 /* Default devices are always first in the list */
2099 case ALC_DEFAULT_DEVICE_SPECIFIER:
2100 value = alcDefaultName;
2101 break;
2103 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2104 if(!alcAllDevicesList)
2105 ProbeAllDevicesList();
2107 Device = VerifyDevice(Device);
2109 free(alcDefaultAllDevicesSpecifier);
2110 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2111 alcAllDevicesList : "");
2112 if(!alcDefaultAllDevicesSpecifier)
2113 alcSetError(Device, ALC_OUT_OF_MEMORY);
2115 value = alcDefaultAllDevicesSpecifier;
2116 if(Device) ALCdevice_DecRef(Device);
2117 break;
2119 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2120 if(!alcCaptureDeviceList)
2121 ProbeCaptureDeviceList();
2123 Device = VerifyDevice(Device);
2125 free(alcCaptureDefaultDeviceSpecifier);
2126 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2127 alcCaptureDeviceList : "");
2128 if(!alcCaptureDefaultDeviceSpecifier)
2129 alcSetError(Device, ALC_OUT_OF_MEMORY);
2131 value = alcCaptureDefaultDeviceSpecifier;
2132 if(Device) ALCdevice_DecRef(Device);
2133 break;
2135 case ALC_EXTENSIONS:
2136 if(!VerifyDevice(Device))
2137 value = alcNoDeviceExtList;
2138 else
2140 value = alcExtensionList;
2141 ALCdevice_DecRef(Device);
2143 break;
2145 default:
2146 Device = VerifyDevice(Device);
2147 alcSetError(Device, ALC_INVALID_ENUM);
2148 if(Device) ALCdevice_DecRef(Device);
2149 break;
2152 return value;
2156 /* alcGetIntegerv
2158 * Returns information about the device and the version of OpenAL
2160 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2162 device = VerifyDevice(device);
2164 if(size == 0 || data == NULL)
2166 alcSetError(device, ALC_INVALID_VALUE);
2167 if(device) ALCdevice_DecRef(device);
2168 return;
2171 if(!device)
2173 switch(param)
2175 case ALC_MAJOR_VERSION:
2176 *data = alcMajorVersion;
2177 break;
2178 case ALC_MINOR_VERSION:
2179 *data = alcMinorVersion;
2180 break;
2182 case ALC_ATTRIBUTES_SIZE:
2183 case ALC_ALL_ATTRIBUTES:
2184 case ALC_FREQUENCY:
2185 case ALC_REFRESH:
2186 case ALC_SYNC:
2187 case ALC_MONO_SOURCES:
2188 case ALC_STEREO_SOURCES:
2189 case ALC_CAPTURE_SAMPLES:
2190 case ALC_FORMAT_CHANNELS_SOFT:
2191 case ALC_FORMAT_TYPE_SOFT:
2192 alcSetError(NULL, ALC_INVALID_DEVICE);
2193 break;
2195 default:
2196 alcSetError(NULL, ALC_INVALID_ENUM);
2197 break;
2200 else if(device->Type == Capture)
2202 switch(param)
2204 case ALC_CAPTURE_SAMPLES:
2205 LockLists();
2206 /* Re-validate the device since it may have been closed */
2207 ALCdevice_DecRef(device);
2208 if((device=VerifyDevice(device)) != NULL)
2209 *data = ALCdevice_AvailableSamples(device);
2210 else
2211 alcSetError(NULL, ALC_INVALID_DEVICE);
2212 UnlockLists();
2213 break;
2215 case ALC_CONNECTED:
2216 *data = device->Connected;
2217 break;
2219 default:
2220 alcSetError(device, ALC_INVALID_ENUM);
2221 break;
2224 else /* render device */
2226 switch(param)
2228 case ALC_MAJOR_VERSION:
2229 *data = alcMajorVersion;
2230 break;
2232 case ALC_MINOR_VERSION:
2233 *data = alcMinorVersion;
2234 break;
2236 case ALC_EFX_MAJOR_VERSION:
2237 *data = alcEFXMajorVersion;
2238 break;
2240 case ALC_EFX_MINOR_VERSION:
2241 *data = alcEFXMinorVersion;
2242 break;
2244 case ALC_ATTRIBUTES_SIZE:
2245 *data = 13;
2246 break;
2248 case ALC_ALL_ATTRIBUTES:
2249 if(size < 13)
2250 alcSetError(device, ALC_INVALID_VALUE);
2251 else
2253 int i = 0;
2255 data[i++] = ALC_FREQUENCY;
2256 data[i++] = device->Frequency;
2258 if(device->Type != Loopback)
2260 data[i++] = ALC_REFRESH;
2261 data[i++] = device->Frequency / device->UpdateSize;
2263 data[i++] = ALC_SYNC;
2264 data[i++] = ALC_FALSE;
2266 else
2268 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2269 data[i++] = device->FmtChans;
2271 data[i++] = ALC_FORMAT_TYPE_SOFT;
2272 data[i++] = device->FmtType;
2275 data[i++] = ALC_MONO_SOURCES;
2276 data[i++] = device->NumMonoSources;
2278 data[i++] = ALC_STEREO_SOURCES;
2279 data[i++] = device->NumStereoSources;
2281 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2282 data[i++] = device->NumAuxSends;
2284 data[i++] = 0;
2286 break;
2288 case ALC_FREQUENCY:
2289 *data = device->Frequency;
2290 break;
2292 case ALC_REFRESH:
2293 if(device->Type == Loopback)
2294 alcSetError(device, ALC_INVALID_DEVICE);
2295 else
2296 *data = device->Frequency / device->UpdateSize;
2297 break;
2299 case ALC_SYNC:
2300 if(device->Type == Loopback)
2301 alcSetError(device, ALC_INVALID_DEVICE);
2302 else
2303 *data = ALC_FALSE;
2304 break;
2306 case ALC_FORMAT_CHANNELS_SOFT:
2307 if(device->Type != Loopback)
2308 alcSetError(device, ALC_INVALID_DEVICE);
2309 else
2310 *data = device->FmtChans;
2311 break;
2313 case ALC_FORMAT_TYPE_SOFT:
2314 if(device->Type != Loopback)
2315 alcSetError(device, ALC_INVALID_DEVICE);
2316 else
2317 *data = device->FmtType;
2318 break;
2320 case ALC_MONO_SOURCES:
2321 *data = device->NumMonoSources;
2322 break;
2324 case ALC_STEREO_SOURCES:
2325 *data = device->NumStereoSources;
2326 break;
2328 case ALC_MAX_AUXILIARY_SENDS:
2329 *data = device->NumAuxSends;
2330 break;
2332 case ALC_CONNECTED:
2333 *data = device->Connected;
2334 break;
2336 default:
2337 alcSetError(device, ALC_INVALID_ENUM);
2338 break;
2341 if(device)
2342 ALCdevice_DecRef(device);
2346 /* alcIsExtensionPresent
2348 * Determines if there is support for a particular extension
2350 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2352 ALCboolean bResult = ALC_FALSE;
2354 device = VerifyDevice(device);
2356 if(!extName)
2357 alcSetError(device, ALC_INVALID_VALUE);
2358 else
2360 size_t len = strlen(extName);
2361 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2362 while(ptr && *ptr)
2364 if(strncasecmp(ptr, extName, len) == 0 &&
2365 (ptr[len] == '\0' || isspace(ptr[len])))
2367 bResult = ALC_TRUE;
2368 break;
2370 if((ptr=strchr(ptr, ' ')) != NULL)
2372 do {
2373 ++ptr;
2374 } while(isspace(*ptr));
2378 if(device)
2379 ALCdevice_DecRef(device);
2380 return bResult;
2384 /* alcGetProcAddress
2386 * Retrieves the function address for a particular extension function
2388 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2390 ALCvoid *ptr = NULL;
2392 if(!funcName)
2394 device = VerifyDevice(device);
2395 alcSetError(device, ALC_INVALID_VALUE);
2396 if(device) ALCdevice_DecRef(device);
2398 else
2400 ALsizei i = 0;
2401 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2402 i++;
2403 ptr = alcFunctions[i].address;
2406 return ptr;
2410 /* alcGetEnumValue
2412 * Get the value for a particular ALC enumeration name
2414 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2416 ALCenum val = 0;
2418 if(!enumName)
2420 device = VerifyDevice(device);
2421 alcSetError(device, ALC_INVALID_VALUE);
2422 if(device) ALCdevice_DecRef(device);
2424 else
2426 ALsizei i = 0;
2427 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2428 i++;
2429 val = enumeration[i].value;
2432 return val;
2436 /* alcCreateContext
2438 * Create and attach a context to the given device.
2440 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2442 ALCcontext *ALContext;
2443 ALCenum err;
2445 LockLists();
2446 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2448 UnlockLists();
2449 alcSetError(device, ALC_INVALID_DEVICE);
2450 if(device) ALCdevice_DecRef(device);
2451 return NULL;
2454 device->LastError = ALC_NO_ERROR;
2456 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2458 UnlockLists();
2459 alcSetError(device, err);
2460 if(err == ALC_INVALID_DEVICE)
2461 aluHandleDisconnect(device);
2462 ALCdevice_DecRef(device);
2463 return NULL;
2466 ALContext = calloc(1, sizeof(ALCcontext));
2467 if(ALContext)
2469 ALContext->ref = 1;
2471 ALContext->MaxActiveSources = 256;
2472 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2473 ALContext->MaxActiveSources);
2475 if(!ALContext || !ALContext->ActiveSources)
2477 if(!device->ContextList)
2479 ALCdevice_StopPlayback(device);
2480 device->Flags &= ~DEVICE_RUNNING;
2482 UnlockLists();
2484 free(ALContext);
2485 ALContext = NULL;
2487 alcSetError(device, ALC_OUT_OF_MEMORY);
2488 ALCdevice_DecRef(device);
2489 return NULL;
2492 ALContext->Device = device;
2493 ALCdevice_IncRef(device);
2494 InitContext(ALContext);
2496 do {
2497 ALContext->next = device->ContextList;
2498 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2499 UnlockLists();
2501 ALCdevice_DecRef(device);
2503 TRACE("Created context %p\n", ALContext);
2504 return ALContext;
2507 /* alcDestroyContext
2509 * Remove a context from its device
2511 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2513 ALCdevice *Device;
2515 LockLists();
2516 /* alcGetContextsDevice sets an error for invalid contexts */
2517 Device = alcGetContextsDevice(context);
2518 if(Device)
2520 ReleaseContext(context, Device);
2521 if(!Device->ContextList)
2523 ALCdevice_StopPlayback(Device);
2524 Device->Flags &= ~DEVICE_RUNNING;
2527 UnlockLists();
2531 /* alcGetCurrentContext
2533 * Returns the currently active context on the calling thread
2535 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2537 ALCcontext *Context;
2539 Context = pthread_getspecific(LocalContext);
2540 if(!Context) Context = GlobalContext;
2542 return Context;
2545 /* alcGetThreadContext
2547 * Returns the currently active thread-local context
2549 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2551 ALCcontext *Context;
2552 Context = pthread_getspecific(LocalContext);
2553 return Context;
2557 /* alcMakeContextCurrent
2559 * Makes the given context the active process-wide context, and removes the
2560 * thread-local context for the calling thread.
2562 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2564 /* context must be valid or NULL */
2565 if(context && !(context=VerifyContext(context)))
2567 alcSetError(NULL, ALC_INVALID_CONTEXT);
2568 return ALC_FALSE;
2570 /* context's reference count is already incremented */
2571 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2572 if(context) ALCcontext_DecRef(context);
2574 if((context=pthread_getspecific(LocalContext)) != NULL)
2576 pthread_setspecific(LocalContext, NULL);
2577 ALCcontext_DecRef(context);
2580 return ALC_TRUE;
2583 /* alcSetThreadContext
2585 * Makes the given context the active context for the current thread
2587 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2589 ALCcontext *old;
2591 /* context must be valid or NULL */
2592 if(context && !(context=VerifyContext(context)))
2594 alcSetError(NULL, ALC_INVALID_CONTEXT);
2595 return ALC_FALSE;
2597 /* context's reference count is already incremented */
2598 old = pthread_getspecific(LocalContext);
2599 pthread_setspecific(LocalContext, context);
2600 if(old) ALCcontext_DecRef(old);
2602 return ALC_TRUE;
2606 /* alcGetContextsDevice
2608 * Returns the device that a particular context is attached to
2610 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2612 ALCdevice *Device;
2614 if(!(Context=VerifyContext(Context)))
2616 alcSetError(NULL, ALC_INVALID_CONTEXT);
2617 return NULL;
2619 Device = Context->Device;
2620 ALCcontext_DecRef(Context);
2622 return Device;
2626 /* alcOpenDevice
2628 * Opens the named device.
2630 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2632 const ALCchar *fmt;
2633 ALCdevice *device;
2634 ALCenum err;
2636 DO_INITCONFIG();
2638 if(!PlaybackBackend.name)
2640 alcSetError(NULL, ALC_INVALID_VALUE);
2641 return NULL;
2644 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2645 deviceName = NULL;
2647 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
2648 if(!device)
2650 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2651 return NULL;
2654 //Validate device
2655 device->Funcs = &PlaybackBackend.Funcs;
2656 device->ref = 1;
2657 device->Connected = ALC_TRUE;
2658 device->Type = Playback;
2659 InitializeCriticalSection(&device->Mutex);
2660 device->LastError = ALC_NO_ERROR;
2662 device->Flags = 0;
2663 device->Bs2b = NULL;
2664 device->Bs2bLevel = 0;
2665 device->DeviceName = NULL;
2667 device->ContextList = NULL;
2669 device->MaxNoOfSources = 256;
2670 device->AuxiliaryEffectSlotMax = 4;
2671 device->NumAuxSends = MAX_SENDS;
2673 InitUIntMap(&device->BufferMap, ~0);
2674 InitUIntMap(&device->EffectMap, ~0);
2675 InitUIntMap(&device->FilterMap, ~0);
2677 //Set output format
2678 device->FmtChans = DevFmtChannelsDefault;
2679 device->FmtType = DevFmtTypeDefault;
2680 device->Frequency = DEFAULT_OUTPUT_RATE;
2681 device->NumUpdates = 4;
2682 device->UpdateSize = 1024;
2684 if(ConfigValueStr(NULL, "channels", &fmt))
2686 static const struct {
2687 const char name[16];
2688 enum DevFmtChannels chans;
2689 } chanlist[] = {
2690 { "mono", DevFmtMono },
2691 { "stereo", DevFmtStereo },
2692 { "quad", DevFmtQuad },
2693 { "surround51", DevFmtX51 },
2694 { "surround61", DevFmtX61 },
2695 { "surround71", DevFmtX71 },
2697 size_t i;
2699 for(i = 0;i < COUNTOF(chanlist);i++)
2701 if(strcasecmp(chanlist[i].name, fmt) == 0)
2703 device->FmtChans = chanlist[i].chans;
2704 device->Flags |= DEVICE_CHANNELS_REQUEST;
2705 break;
2708 if(i == COUNTOF(chanlist))
2709 ERR("Unsupported channels: %s\n", fmt);
2711 if(ConfigValueStr(NULL, "sample-type", &fmt))
2713 static const struct {
2714 const char name[16];
2715 enum DevFmtType type;
2716 } typelist[] = {
2717 { "int8", DevFmtByte },
2718 { "uint8", DevFmtUByte },
2719 { "int16", DevFmtShort },
2720 { "uint16", DevFmtUShort },
2721 { "int32", DevFmtInt },
2722 { "uint32", DevFmtUInt },
2723 { "float32", DevFmtFloat },
2725 size_t i;
2727 for(i = 0;i < COUNTOF(typelist);i++)
2729 if(strcasecmp(typelist[i].name, fmt) == 0)
2731 device->FmtType = typelist[i].type;
2732 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2733 break;
2736 if(i == COUNTOF(typelist))
2737 ERR("Unsupported sample-type: %s\n", fmt);
2739 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2740 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2741 ConfigValueStr(NULL, "format", &fmt))
2743 static const struct {
2744 const char name[32];
2745 enum DevFmtChannels channels;
2746 enum DevFmtType type;
2747 } formats[] = {
2748 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2749 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2750 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2751 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2752 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2753 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2755 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2756 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2757 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2758 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2759 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2760 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2762 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2763 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2764 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2765 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2766 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2767 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2769 size_t i;
2771 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2772 for(i = 0;i < COUNTOF(formats);i++)
2774 if(strcasecmp(fmt, formats[i].name) == 0)
2776 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2777 device->FmtChans = formats[i].channels;
2778 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2779 device->FmtType = formats[i].type;
2780 device->Flags |= DEVICE_FORMAT_REQUEST;
2781 break;
2784 if(i == COUNTOF(formats))
2785 ERR("Unsupported format: %s\n", fmt);
2787 #undef DEVICE_FORMAT_REQUEST
2789 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2791 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2792 if(device->Frequency < MIN_OUTPUT_RATE)
2793 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2794 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2797 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2798 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2800 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2801 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2803 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2804 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2806 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2807 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2809 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2810 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2812 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2814 device->NumStereoSources = 1;
2815 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2817 // Find a playback device to open
2818 LockLists();
2819 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2821 UnlockLists();
2822 DeleteCriticalSection(&device->Mutex);
2823 al_free(device);
2824 alcSetError(NULL, err);
2825 return NULL;
2827 UnlockLists();
2829 if(DefaultEffect.type != AL_EFFECT_NULL)
2831 device->DefaultSlot = (ALeffectslot*)(device+1);
2832 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2834 device->DefaultSlot = NULL;
2835 ERR("Failed to initialize the default effect slot\n");
2837 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2839 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2840 device->DefaultSlot = NULL;
2841 ERR("Failed to initialize the default effect\n");
2845 do {
2846 device->next = DeviceList;
2847 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2849 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2850 return device;
2853 /* alcCloseDevice
2855 * Closes the given device.
2857 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2859 ALCdevice *volatile*list;
2860 ALCcontext *ctx;
2862 LockLists();
2863 list = &DeviceList;
2864 while(*list && *list != Device)
2865 list = &(*list)->next;
2867 if(!*list || (*list)->Type == Capture)
2869 alcSetError(*list, ALC_INVALID_DEVICE);
2870 UnlockLists();
2871 return ALC_FALSE;
2874 *list = (*list)->next;
2875 UnlockLists();
2877 while((ctx=Device->ContextList) != NULL)
2879 WARN("Releasing context %p\n", ctx);
2880 ReleaseContext(ctx, Device);
2882 if((Device->Flags&DEVICE_RUNNING))
2883 ALCdevice_StopPlayback(Device);
2884 Device->Flags &= ~DEVICE_RUNNING;
2886 ALCdevice_DecRef(Device);
2888 return ALC_TRUE;
2892 /************************************************
2893 * ALC capture functions
2894 ************************************************/
2895 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2897 ALCdevice *device = NULL;
2898 ALCenum err;
2900 DO_INITCONFIG();
2902 if(!CaptureBackend.name)
2904 alcSetError(NULL, ALC_INVALID_VALUE);
2905 return NULL;
2908 if(samples <= 0)
2910 alcSetError(NULL, ALC_INVALID_VALUE);
2911 return NULL;
2914 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2915 deviceName = NULL;
2917 device = al_calloc(16, sizeof(ALCdevice));
2918 if(!device)
2920 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2921 return NULL;
2924 //Validate device
2925 device->Funcs = &CaptureBackend.Funcs;
2926 device->ref = 1;
2927 device->Connected = ALC_TRUE;
2928 device->Type = Capture;
2929 InitializeCriticalSection(&device->Mutex);
2931 InitUIntMap(&device->BufferMap, ~0);
2932 InitUIntMap(&device->EffectMap, ~0);
2933 InitUIntMap(&device->FilterMap, ~0);
2935 device->DeviceName = NULL;
2937 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2938 device->Frequency = frequency;
2940 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2941 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2943 DeleteCriticalSection(&device->Mutex);
2944 al_free(device);
2945 alcSetError(NULL, ALC_INVALID_ENUM);
2946 return NULL;
2949 device->UpdateSize = samples;
2950 device->NumUpdates = 1;
2952 LockLists();
2953 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2955 UnlockLists();
2956 DeleteCriticalSection(&device->Mutex);
2957 al_free(device);
2958 alcSetError(NULL, err);
2959 return NULL;
2961 UnlockLists();
2963 do {
2964 device->next = DeviceList;
2965 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2967 TRACE("Created device %p\n", device);
2968 return device;
2971 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2973 ALCdevice *volatile*list;
2975 LockLists();
2976 list = &DeviceList;
2977 while(*list && *list != Device)
2978 list = &(*list)->next;
2980 if(!*list || (*list)->Type != Capture)
2982 alcSetError(*list, ALC_INVALID_DEVICE);
2983 UnlockLists();
2984 return ALC_FALSE;
2987 *list = (*list)->next;
2988 UnlockLists();
2990 ALCdevice_DecRef(Device);
2992 return ALC_TRUE;
2995 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2997 LockLists();
2998 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3000 UnlockLists();
3001 alcSetError(device, ALC_INVALID_DEVICE);
3002 if(device) ALCdevice_DecRef(device);
3003 return;
3005 if(device->Connected)
3007 if(!(device->Flags&DEVICE_RUNNING))
3008 ALCdevice_StartCapture(device);
3009 device->Flags |= DEVICE_RUNNING;
3011 UnlockLists();
3013 ALCdevice_DecRef(device);
3016 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3018 LockLists();
3019 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3021 UnlockLists();
3022 alcSetError(device, ALC_INVALID_DEVICE);
3023 if(device) ALCdevice_DecRef(device);
3024 return;
3026 if((device->Flags&DEVICE_RUNNING))
3027 ALCdevice_StopCapture(device);
3028 device->Flags &= ~DEVICE_RUNNING;
3029 UnlockLists();
3031 ALCdevice_DecRef(device);
3034 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3036 ALCenum err = ALC_INVALID_DEVICE;
3037 LockLists();
3038 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3040 err = ALC_INVALID_VALUE;
3041 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3042 err = ALCdevice_CaptureSamples(device, buffer, samples);
3044 UnlockLists();
3045 if(err != ALC_NO_ERROR)
3046 alcSetError(device, err);
3047 if(device) ALCdevice_DecRef(device);
3051 /************************************************
3052 * ALC loopback functions
3053 ************************************************/
3055 /* alcLoopbackOpenDeviceSOFT
3057 * Open a loopback device, for manual rendering.
3059 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3061 ALCdevice *device;
3063 DO_INITCONFIG();
3065 /* Make sure the device name, if specified, is us. */
3066 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3068 alcSetError(NULL, ALC_INVALID_VALUE);
3069 return NULL;
3072 device = al_calloc(16, sizeof(ALCdevice));
3073 if(!device)
3075 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3076 return NULL;
3079 //Validate device
3080 device->Funcs = &BackendLoopback.Funcs;
3081 device->ref = 1;
3082 device->Connected = ALC_TRUE;
3083 device->Type = Loopback;
3084 InitializeCriticalSection(&device->Mutex);
3085 device->LastError = ALC_NO_ERROR;
3087 device->Flags = 0;
3088 device->Bs2b = NULL;
3089 device->Bs2bLevel = 0;
3090 device->DeviceName = NULL;
3092 device->ContextList = NULL;
3094 device->MaxNoOfSources = 256;
3095 device->AuxiliaryEffectSlotMax = 4;
3096 device->NumAuxSends = MAX_SENDS;
3098 InitUIntMap(&device->BufferMap, ~0);
3099 InitUIntMap(&device->EffectMap, ~0);
3100 InitUIntMap(&device->FilterMap, ~0);
3102 //Set output format
3103 device->NumUpdates = 0;
3104 device->UpdateSize = 0;
3106 device->Frequency = DEFAULT_OUTPUT_RATE;
3107 device->FmtChans = DevFmtChannelsDefault;
3108 device->FmtType = DevFmtTypeDefault;
3110 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3111 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3113 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3114 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3116 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3117 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3119 device->NumStereoSources = 1;
3120 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3122 // Open the "backend"
3123 ALCdevice_OpenPlayback(device, "Loopback");
3124 do {
3125 device->next = DeviceList;
3126 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3128 TRACE("Created device %p\n", device);
3129 return device;
3132 /* alcIsRenderFormatSupportedSOFT
3134 * Determines if the loopback device supports the given format for rendering.
3136 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3138 ALCboolean ret = ALC_FALSE;
3140 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3141 alcSetError(device, ALC_INVALID_DEVICE);
3142 else if(freq <= 0)
3143 alcSetError(device, ALC_INVALID_VALUE);
3144 else
3146 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3147 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3148 freq >= MIN_OUTPUT_RATE)
3149 ret = ALC_TRUE;
3151 if(device) ALCdevice_DecRef(device);
3153 return ret;
3156 /* alcRenderSamplesSOFT
3158 * Renders some samples into a buffer, using the format last set by the
3159 * attributes given to alcCreateContext.
3161 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3163 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3164 alcSetError(device, ALC_INVALID_DEVICE);
3165 else if(samples < 0 || (samples > 0 && buffer == NULL))
3166 alcSetError(device, ALC_INVALID_VALUE);
3167 else
3168 aluMixData(device, buffer, samples);
3169 if(device) ALCdevice_DecRef(device);