Check for some CPU extensions
[openal-soft.git] / Alc / ALc.c
blobb017c480a9af7e85ce6d44a680ee607507bf477e
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "AL/al.h"
33 #include "AL/alc.h"
34 #include "alThunk.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "bs2b.h"
40 #include "alu.h"
43 /************************************************
44 * Backends
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
50 #endif
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_COREAUDIO
55 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_OSS
58 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_SOLARIS
61 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_SNDIO
64 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_MMDEVAPI
67 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_DSOUND
70 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
71 #endif
72 #ifdef HAVE_WINMM
73 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_PORTAUDIO
76 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
77 #endif
78 #ifdef HAVE_OPENSL
79 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
80 #endif
82 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
83 #ifdef HAVE_WAVE
84 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
85 #endif
87 { NULL, NULL, NULL, NULL, EmptyFuncs }
89 static struct BackendInfo BackendLoopback = {
90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
92 #undef EmptyFuncs
94 static struct BackendInfo PlaybackBackend;
95 static struct BackendInfo CaptureBackend;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction {
101 const ALCchar *funcName;
102 ALCvoid *address;
103 } ALCfunction;
105 typedef struct ALCenums {
106 const ALCchar *enumName;
107 ALCenum value;
108 } ALCenums;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions[] = {
112 DECL(alcCreateContext),
113 DECL(alcMakeContextCurrent),
114 DECL(alcProcessContext),
115 DECL(alcSuspendContext),
116 DECL(alcDestroyContext),
117 DECL(alcGetCurrentContext),
118 DECL(alcGetContextsDevice),
119 DECL(alcOpenDevice),
120 DECL(alcCloseDevice),
121 DECL(alcGetError),
122 DECL(alcIsExtensionPresent),
123 DECL(alcGetProcAddress),
124 DECL(alcGetEnumValue),
125 DECL(alcGetString),
126 DECL(alcGetIntegerv),
127 DECL(alcCaptureOpenDevice),
128 DECL(alcCaptureCloseDevice),
129 DECL(alcCaptureStart),
130 DECL(alcCaptureStop),
131 DECL(alcCaptureSamples),
133 DECL(alcSetThreadContext),
134 DECL(alcGetThreadContext),
136 DECL(alcLoopbackOpenDeviceSOFT),
137 DECL(alcIsRenderFormatSupportedSOFT),
138 DECL(alcRenderSamplesSOFT),
140 DECL(alEnable),
141 DECL(alDisable),
142 DECL(alIsEnabled),
143 DECL(alGetString),
144 DECL(alGetBooleanv),
145 DECL(alGetIntegerv),
146 DECL(alGetFloatv),
147 DECL(alGetDoublev),
148 DECL(alGetBoolean),
149 DECL(alGetInteger),
150 DECL(alGetFloat),
151 DECL(alGetDouble),
152 DECL(alGetError),
153 DECL(alIsExtensionPresent),
154 DECL(alGetProcAddress),
155 DECL(alGetEnumValue),
156 DECL(alListenerf),
157 DECL(alListener3f),
158 DECL(alListenerfv),
159 DECL(alListeneri),
160 DECL(alListener3i),
161 DECL(alListeneriv),
162 DECL(alGetListenerf),
163 DECL(alGetListener3f),
164 DECL(alGetListenerfv),
165 DECL(alGetListeneri),
166 DECL(alGetListener3i),
167 DECL(alGetListeneriv),
168 DECL(alGenSources),
169 DECL(alDeleteSources),
170 DECL(alIsSource),
171 DECL(alSourcef),
172 DECL(alSource3f),
173 DECL(alSourcefv),
174 DECL(alSourcei),
175 DECL(alSource3i),
176 DECL(alSourceiv),
177 DECL(alGetSourcef),
178 DECL(alGetSource3f),
179 DECL(alGetSourcefv),
180 DECL(alGetSourcei),
181 DECL(alGetSource3i),
182 DECL(alGetSourceiv),
183 DECL(alSourcePlayv),
184 DECL(alSourceStopv),
185 DECL(alSourceRewindv),
186 DECL(alSourcePausev),
187 DECL(alSourcePlay),
188 DECL(alSourceStop),
189 DECL(alSourceRewind),
190 DECL(alSourcePause),
191 DECL(alSourceQueueBuffers),
192 DECL(alSourceUnqueueBuffers),
193 DECL(alGenBuffers),
194 DECL(alDeleteBuffers),
195 DECL(alIsBuffer),
196 DECL(alBufferData),
197 DECL(alBufferf),
198 DECL(alBuffer3f),
199 DECL(alBufferfv),
200 DECL(alBufferi),
201 DECL(alBuffer3i),
202 DECL(alBufferiv),
203 DECL(alGetBufferf),
204 DECL(alGetBuffer3f),
205 DECL(alGetBufferfv),
206 DECL(alGetBufferi),
207 DECL(alGetBuffer3i),
208 DECL(alGetBufferiv),
209 DECL(alDopplerFactor),
210 DECL(alDopplerVelocity),
211 DECL(alSpeedOfSound),
212 DECL(alDistanceModel),
214 DECL(alGenFilters),
215 DECL(alDeleteFilters),
216 DECL(alIsFilter),
217 DECL(alFilteri),
218 DECL(alFilteriv),
219 DECL(alFilterf),
220 DECL(alFilterfv),
221 DECL(alGetFilteri),
222 DECL(alGetFilteriv),
223 DECL(alGetFilterf),
224 DECL(alGetFilterfv),
225 DECL(alGenEffects),
226 DECL(alDeleteEffects),
227 DECL(alIsEffect),
228 DECL(alEffecti),
229 DECL(alEffectiv),
230 DECL(alEffectf),
231 DECL(alEffectfv),
232 DECL(alGetEffecti),
233 DECL(alGetEffectiv),
234 DECL(alGetEffectf),
235 DECL(alGetEffectfv),
236 DECL(alGenAuxiliaryEffectSlots),
237 DECL(alDeleteAuxiliaryEffectSlots),
238 DECL(alIsAuxiliaryEffectSlot),
239 DECL(alAuxiliaryEffectSloti),
240 DECL(alAuxiliaryEffectSlotiv),
241 DECL(alAuxiliaryEffectSlotf),
242 DECL(alAuxiliaryEffectSlotfv),
243 DECL(alGetAuxiliaryEffectSloti),
244 DECL(alGetAuxiliaryEffectSlotiv),
245 DECL(alGetAuxiliaryEffectSlotf),
246 DECL(alGetAuxiliaryEffectSlotfv),
248 DECL(alBufferSubDataSOFT),
250 DECL(alBufferSamplesSOFT),
251 DECL(alBufferSubSamplesSOFT),
252 DECL(alGetBufferSamplesSOFT),
253 DECL(alIsBufferFormatSupportedSOFT),
255 DECL(alDeferUpdatesSOFT),
256 DECL(alProcessUpdatesSOFT),
258 { NULL, NULL }
260 #undef DECL
262 #define DECL(x) { #x, (x) }
263 static const ALCenums enumeration[] = {
264 DECL(ALC_INVALID),
265 DECL(ALC_FALSE),
266 DECL(ALC_TRUE),
268 DECL(ALC_MAJOR_VERSION),
269 DECL(ALC_MINOR_VERSION),
270 DECL(ALC_ATTRIBUTES_SIZE),
271 DECL(ALC_ALL_ATTRIBUTES),
272 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
273 DECL(ALC_DEVICE_SPECIFIER),
274 DECL(ALC_ALL_DEVICES_SPECIFIER),
275 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
276 DECL(ALC_EXTENSIONS),
277 DECL(ALC_FREQUENCY),
278 DECL(ALC_REFRESH),
279 DECL(ALC_SYNC),
280 DECL(ALC_MONO_SOURCES),
281 DECL(ALC_STEREO_SOURCES),
282 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
283 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
284 DECL(ALC_CAPTURE_SAMPLES),
285 DECL(ALC_CONNECTED),
287 DECL(ALC_EFX_MAJOR_VERSION),
288 DECL(ALC_EFX_MINOR_VERSION),
289 DECL(ALC_MAX_AUXILIARY_SENDS),
291 DECL(ALC_FORMAT_CHANNELS_SOFT),
292 DECL(ALC_FORMAT_TYPE_SOFT),
294 DECL(ALC_MONO_SOFT),
295 DECL(ALC_STEREO_SOFT),
296 DECL(ALC_QUAD_SOFT),
297 DECL(ALC_5POINT1_SOFT),
298 DECL(ALC_6POINT1_SOFT),
299 DECL(ALC_7POINT1_SOFT),
301 DECL(ALC_BYTE_SOFT),
302 DECL(ALC_UNSIGNED_BYTE_SOFT),
303 DECL(ALC_SHORT_SOFT),
304 DECL(ALC_UNSIGNED_SHORT_SOFT),
305 DECL(ALC_INT_SOFT),
306 DECL(ALC_UNSIGNED_INT_SOFT),
307 DECL(ALC_FLOAT_SOFT),
309 DECL(ALC_NO_ERROR),
310 DECL(ALC_INVALID_DEVICE),
311 DECL(ALC_INVALID_CONTEXT),
312 DECL(ALC_INVALID_ENUM),
313 DECL(ALC_INVALID_VALUE),
314 DECL(ALC_OUT_OF_MEMORY),
317 DECL(AL_INVALID),
318 DECL(AL_NONE),
319 DECL(AL_FALSE),
320 DECL(AL_TRUE),
322 DECL(AL_SOURCE_RELATIVE),
323 DECL(AL_CONE_INNER_ANGLE),
324 DECL(AL_CONE_OUTER_ANGLE),
325 DECL(AL_PITCH),
326 DECL(AL_POSITION),
327 DECL(AL_DIRECTION),
328 DECL(AL_VELOCITY),
329 DECL(AL_LOOPING),
330 DECL(AL_BUFFER),
331 DECL(AL_GAIN),
332 DECL(AL_MIN_GAIN),
333 DECL(AL_MAX_GAIN),
334 DECL(AL_ORIENTATION),
335 DECL(AL_REFERENCE_DISTANCE),
336 DECL(AL_ROLLOFF_FACTOR),
337 DECL(AL_CONE_OUTER_GAIN),
338 DECL(AL_MAX_DISTANCE),
339 DECL(AL_SEC_OFFSET),
340 DECL(AL_SAMPLE_OFFSET),
341 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
342 DECL(AL_BYTE_OFFSET),
343 DECL(AL_BYTE_RW_OFFSETS_SOFT),
344 DECL(AL_SOURCE_TYPE),
345 DECL(AL_STATIC),
346 DECL(AL_STREAMING),
347 DECL(AL_UNDETERMINED),
348 DECL(AL_METERS_PER_UNIT),
349 DECL(AL_DIRECT_CHANNELS_SOFT),
351 DECL(AL_DIRECT_FILTER),
352 DECL(AL_AUXILIARY_SEND_FILTER),
353 DECL(AL_AIR_ABSORPTION_FACTOR),
354 DECL(AL_ROOM_ROLLOFF_FACTOR),
355 DECL(AL_CONE_OUTER_GAINHF),
356 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
357 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
358 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
360 DECL(AL_SOURCE_STATE),
361 DECL(AL_INITIAL),
362 DECL(AL_PLAYING),
363 DECL(AL_PAUSED),
364 DECL(AL_STOPPED),
366 DECL(AL_BUFFERS_QUEUED),
367 DECL(AL_BUFFERS_PROCESSED),
369 DECL(AL_FORMAT_MONO8),
370 DECL(AL_FORMAT_MONO16),
371 DECL(AL_FORMAT_MONO_FLOAT32),
372 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
373 DECL(AL_FORMAT_STEREO8),
374 DECL(AL_FORMAT_STEREO16),
375 DECL(AL_FORMAT_STEREO_FLOAT32),
376 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
377 DECL(AL_FORMAT_MONO_IMA4),
378 DECL(AL_FORMAT_STEREO_IMA4),
379 DECL(AL_FORMAT_QUAD8_LOKI),
380 DECL(AL_FORMAT_QUAD16_LOKI),
381 DECL(AL_FORMAT_QUAD8),
382 DECL(AL_FORMAT_QUAD16),
383 DECL(AL_FORMAT_QUAD32),
384 DECL(AL_FORMAT_51CHN8),
385 DECL(AL_FORMAT_51CHN16),
386 DECL(AL_FORMAT_51CHN32),
387 DECL(AL_FORMAT_61CHN8),
388 DECL(AL_FORMAT_61CHN16),
389 DECL(AL_FORMAT_61CHN32),
390 DECL(AL_FORMAT_71CHN8),
391 DECL(AL_FORMAT_71CHN16),
392 DECL(AL_FORMAT_71CHN32),
393 DECL(AL_FORMAT_REAR8),
394 DECL(AL_FORMAT_REAR16),
395 DECL(AL_FORMAT_REAR32),
396 DECL(AL_FORMAT_MONO_MULAW),
397 DECL(AL_FORMAT_MONO_MULAW_EXT),
398 DECL(AL_FORMAT_STEREO_MULAW),
399 DECL(AL_FORMAT_STEREO_MULAW_EXT),
400 DECL(AL_FORMAT_QUAD_MULAW),
401 DECL(AL_FORMAT_51CHN_MULAW),
402 DECL(AL_FORMAT_61CHN_MULAW),
403 DECL(AL_FORMAT_71CHN_MULAW),
404 DECL(AL_FORMAT_REAR_MULAW),
405 DECL(AL_FORMAT_MONO_ALAW_EXT),
406 DECL(AL_FORMAT_STEREO_ALAW_EXT),
408 DECL(AL_MONO8_SOFT),
409 DECL(AL_MONO16_SOFT),
410 DECL(AL_MONO32F_SOFT),
411 DECL(AL_STEREO8_SOFT),
412 DECL(AL_STEREO16_SOFT),
413 DECL(AL_STEREO32F_SOFT),
414 DECL(AL_QUAD8_SOFT),
415 DECL(AL_QUAD16_SOFT),
416 DECL(AL_QUAD32F_SOFT),
417 DECL(AL_REAR8_SOFT),
418 DECL(AL_REAR16_SOFT),
419 DECL(AL_REAR32F_SOFT),
420 DECL(AL_5POINT1_8_SOFT),
421 DECL(AL_5POINT1_16_SOFT),
422 DECL(AL_5POINT1_32F_SOFT),
423 DECL(AL_6POINT1_8_SOFT),
424 DECL(AL_6POINT1_16_SOFT),
425 DECL(AL_6POINT1_32F_SOFT),
426 DECL(AL_7POINT1_8_SOFT),
427 DECL(AL_7POINT1_16_SOFT),
428 DECL(AL_7POINT1_32F_SOFT),
430 DECL(AL_MONO_SOFT),
431 DECL(AL_STEREO_SOFT),
432 DECL(AL_QUAD_SOFT),
433 DECL(AL_REAR_SOFT),
434 DECL(AL_5POINT1_SOFT),
435 DECL(AL_6POINT1_SOFT),
436 DECL(AL_7POINT1_SOFT),
438 DECL(AL_BYTE_SOFT),
439 DECL(AL_UNSIGNED_BYTE_SOFT),
440 DECL(AL_SHORT_SOFT),
441 DECL(AL_UNSIGNED_SHORT_SOFT),
442 DECL(AL_INT_SOFT),
443 DECL(AL_UNSIGNED_INT_SOFT),
444 DECL(AL_FLOAT_SOFT),
445 DECL(AL_DOUBLE_SOFT),
446 DECL(AL_BYTE3_SOFT),
447 DECL(AL_UNSIGNED_BYTE3_SOFT),
449 DECL(AL_FREQUENCY),
450 DECL(AL_BITS),
451 DECL(AL_CHANNELS),
452 DECL(AL_SIZE),
453 DECL(AL_INTERNAL_FORMAT_SOFT),
454 DECL(AL_BYTE_LENGTH_SOFT),
455 DECL(AL_SAMPLE_LENGTH_SOFT),
456 DECL(AL_SEC_LENGTH_SOFT),
458 DECL(AL_UNUSED),
459 DECL(AL_PENDING),
460 DECL(AL_PROCESSED),
462 DECL(AL_NO_ERROR),
463 DECL(AL_INVALID_NAME),
464 DECL(AL_INVALID_ENUM),
465 DECL(AL_INVALID_VALUE),
466 DECL(AL_INVALID_OPERATION),
467 DECL(AL_OUT_OF_MEMORY),
469 DECL(AL_VENDOR),
470 DECL(AL_VERSION),
471 DECL(AL_RENDERER),
472 DECL(AL_EXTENSIONS),
474 DECL(AL_DOPPLER_FACTOR),
475 DECL(AL_DOPPLER_VELOCITY),
476 DECL(AL_DISTANCE_MODEL),
477 DECL(AL_SPEED_OF_SOUND),
478 DECL(AL_SOURCE_DISTANCE_MODEL),
479 DECL(AL_DEFERRED_UPDATES_SOFT),
481 DECL(AL_INVERSE_DISTANCE),
482 DECL(AL_INVERSE_DISTANCE_CLAMPED),
483 DECL(AL_LINEAR_DISTANCE),
484 DECL(AL_LINEAR_DISTANCE_CLAMPED),
485 DECL(AL_EXPONENT_DISTANCE),
486 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
488 DECL(AL_FILTER_TYPE),
489 DECL(AL_FILTER_NULL),
490 DECL(AL_FILTER_LOWPASS),
491 #if 0
492 DECL(AL_FILTER_HIGHPASS),
493 DECL(AL_FILTER_BANDPASS),
494 #endif
496 DECL(AL_LOWPASS_GAIN),
497 DECL(AL_LOWPASS_GAINHF),
499 DECL(AL_EFFECT_TYPE),
500 DECL(AL_EFFECT_NULL),
501 DECL(AL_EFFECT_REVERB),
502 DECL(AL_EFFECT_EAXREVERB),
503 #if 0
504 DECL(AL_EFFECT_CHORUS),
505 DECL(AL_EFFECT_DISTORTION),
506 #endif
507 DECL(AL_EFFECT_ECHO),
508 #if 0
509 DECL(AL_EFFECT_FLANGER),
510 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
511 DECL(AL_EFFECT_VOCAL_MORPHER),
512 DECL(AL_EFFECT_PITCH_SHIFTER),
513 #endif
514 DECL(AL_EFFECT_RING_MODULATOR),
515 #if 0
516 DECL(AL_EFFECT_AUTOWAH),
517 DECL(AL_EFFECT_COMPRESSOR),
518 DECL(AL_EFFECT_EQUALIZER),
519 #endif
520 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
521 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
523 DECL(AL_EAXREVERB_DENSITY),
524 DECL(AL_EAXREVERB_DIFFUSION),
525 DECL(AL_EAXREVERB_GAIN),
526 DECL(AL_EAXREVERB_GAINHF),
527 DECL(AL_EAXREVERB_GAINLF),
528 DECL(AL_EAXREVERB_DECAY_TIME),
529 DECL(AL_EAXREVERB_DECAY_HFRATIO),
530 DECL(AL_EAXREVERB_DECAY_LFRATIO),
531 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
532 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
533 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
534 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
535 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
536 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
537 DECL(AL_EAXREVERB_ECHO_TIME),
538 DECL(AL_EAXREVERB_ECHO_DEPTH),
539 DECL(AL_EAXREVERB_MODULATION_TIME),
540 DECL(AL_EAXREVERB_MODULATION_DEPTH),
541 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
542 DECL(AL_EAXREVERB_HFREFERENCE),
543 DECL(AL_EAXREVERB_LFREFERENCE),
544 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
545 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
547 DECL(AL_REVERB_DENSITY),
548 DECL(AL_REVERB_DIFFUSION),
549 DECL(AL_REVERB_GAIN),
550 DECL(AL_REVERB_GAINHF),
551 DECL(AL_REVERB_DECAY_TIME),
552 DECL(AL_REVERB_DECAY_HFRATIO),
553 DECL(AL_REVERB_REFLECTIONS_GAIN),
554 DECL(AL_REVERB_REFLECTIONS_DELAY),
555 DECL(AL_REVERB_LATE_REVERB_GAIN),
556 DECL(AL_REVERB_LATE_REVERB_DELAY),
557 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
558 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
559 DECL(AL_REVERB_DECAY_HFLIMIT),
561 DECL(AL_ECHO_DELAY),
562 DECL(AL_ECHO_LRDELAY),
563 DECL(AL_ECHO_DAMPING),
564 DECL(AL_ECHO_FEEDBACK),
565 DECL(AL_ECHO_SPREAD),
567 DECL(AL_RING_MODULATOR_FREQUENCY),
568 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
569 DECL(AL_RING_MODULATOR_WAVEFORM),
571 DECL(AL_DEDICATED_GAIN),
573 { NULL, (ALCenum)0 }
575 #undef DECL
577 static const ALCchar alcNoError[] = "No Error";
578 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
579 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
580 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
581 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
582 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
585 /************************************************
586 * Global variables
587 ************************************************/
589 /* Enumerated device names */
590 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
591 static ALCchar *alcAllDevicesList;
592 static ALCchar *alcCaptureDeviceList;
593 /* Sizes only include the first ending null character, not the second */
594 static size_t alcAllDevicesListSize;
595 static size_t alcCaptureDeviceListSize;
597 /* Default is always the first in the list */
598 static ALCchar *alcDefaultAllDevicesSpecifier;
599 static ALCchar *alcCaptureDefaultDeviceSpecifier;
601 /* Default context extensions */
602 static const ALchar alExtList[] =
603 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
604 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
605 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
606 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
607 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
609 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
611 /* Thread-local current context */
612 static pthread_key_t LocalContext;
613 /* Process-wide current context */
614 static ALCcontext *volatile GlobalContext = NULL;
616 /* Mixing thread piority level */
617 ALint RTPrioLevel;
619 FILE *LogFile;
620 #ifdef _DEBUG
621 enum LogLevel LogLevel = LogWarning;
622 #else
623 enum LogLevel LogLevel = LogError;
624 #endif
626 /* Flag to trap ALC device errors */
627 static ALCboolean TrapALCError = ALC_FALSE;
629 /* One-time configuration init control */
630 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
632 /* Default effect that applies to sources that don't have an effect on send 0 */
633 static ALeffect DefaultEffect;
636 /************************************************
637 * ALC information
638 ************************************************/
639 static const ALCchar alcNoDeviceExtList[] =
640 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
641 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
642 static const ALCchar alcExtensionList[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCint alcMajorVersion = 1;
647 static const ALCint alcMinorVersion = 1;
649 static const ALCint alcEFXMajorVersion = 1;
650 static const ALCint alcEFXMinorVersion = 0;
653 /************************************************
654 * Device lists
655 ************************************************/
656 static ALCdevice *volatile DeviceList = NULL;
658 static CRITICAL_SECTION ListLock;
660 static void LockLists(void)
662 EnterCriticalSection(&ListLock);
664 static void UnlockLists(void)
666 LeaveCriticalSection(&ListLock);
669 /************************************************
670 * Library initialization
671 ************************************************/
672 #if defined(_WIN32)
673 static void alc_init(void);
674 static void alc_deinit(void);
675 static void alc_deinit_safe(void);
677 UIntMap TlsDestructor;
679 #ifndef AL_LIBTYPE_STATIC
680 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
682 ALsizei i;
684 // Perform actions based on the reason for calling.
685 switch(ul_reason_for_call)
687 case DLL_PROCESS_ATTACH:
688 /* Pin the DLL so we won't get unloaded until the process terminates */
689 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
690 (WCHAR*)hModule, &hModule);
691 InitUIntMap(&TlsDestructor, ~0);
692 alc_init();
693 break;
695 case DLL_THREAD_DETACH:
696 LockUIntMapRead(&TlsDestructor);
697 for(i = 0;i < TlsDestructor.size;i++)
699 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
700 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
701 if(ptr && callback)
702 callback(ptr);
704 UnlockUIntMapRead(&TlsDestructor);
705 break;
707 case DLL_PROCESS_DETACH:
708 if(!lpReserved)
709 alc_deinit();
710 else
711 alc_deinit_safe();
712 ResetUIntMap(&TlsDestructor);
713 break;
715 return TRUE;
717 #elif defined(_MSC_VER)
718 #pragma section(".CRT$XCU",read)
719 static void alc_constructor(void);
720 static void alc_destructor(void);
721 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
723 static void alc_constructor(void)
725 atexit(alc_destructor);
726 alc_init();
729 static void alc_destructor(void)
731 alc_deinit();
733 #elif defined(HAVE_GCC_DESTRUCTOR)
734 static void alc_init(void) __attribute__((constructor));
735 static void alc_deinit(void) __attribute__((destructor));
736 #else
737 #error "No static initialization available on this platform!"
738 #endif
740 #elif defined(HAVE_GCC_DESTRUCTOR)
742 static void alc_init(void) __attribute__((constructor));
743 static void alc_deinit(void) __attribute__((destructor));
745 #else
746 #error "No global initialization available on this platform!"
747 #endif
749 static void ReleaseThreadCtx(void *ptr);
750 static void alc_init(void)
752 const char *str;
754 LogFile = stderr;
756 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
757 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
758 ConeScale *= 0.5f;
760 str = getenv("__ALSOFT_REVERSE_Z");
761 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
762 ZScale *= -1.0f;
764 pthread_key_create(&LocalContext, ReleaseThreadCtx);
765 InitializeCriticalSection(&ListLock);
766 ThunkInit();
769 static void alc_initconfig(void)
771 const char *devs, *str;
772 float valf;
773 int i, n;
775 str = getenv("ALSOFT_LOGLEVEL");
776 if(str)
778 long lvl = strtol(str, NULL, 0);
779 if(lvl >= NoLog && lvl <= LogRef)
780 LogLevel = lvl;
783 str = getenv("ALSOFT_LOGFILE");
784 if(str && str[0])
786 FILE *logfile = fopen(str, "wat");
787 if(logfile) LogFile = logfile;
788 else ERR("Failed to open log file '%s'\n", str);
791 ReadALConfig();
793 FillCPUCaps();
794 InitHrtf();
796 #ifdef _WIN32
797 RTPrioLevel = 1;
798 #else
799 RTPrioLevel = 0;
800 #endif
801 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
803 if(ConfigValueStr(NULL, "resampler", &str))
805 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
806 DefaultResampler = PointResampler;
807 else if(strcasecmp(str, "linear") == 0)
808 DefaultResampler = LinearResampler;
809 else if(strcasecmp(str, "cubic") == 0)
810 DefaultResampler = CubicResampler;
811 else
813 char *end;
815 n = strtol(str, &end, 0);
816 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
817 DefaultResampler = n;
818 else
819 WARN("Invalid resampler: %s\n", str);
823 str = getenv("ALSOFT_TRAP_ERROR");
824 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
826 TrapALError = AL_TRUE;
827 TrapALCError = AL_TRUE;
829 else
831 str = getenv("ALSOFT_TRAP_AL_ERROR");
832 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
833 TrapALError = AL_TRUE;
834 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
836 str = getenv("ALSOFT_TRAP_ALC_ERROR");
837 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
838 TrapALCError = ALC_TRUE;
839 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
842 if(ConfigValueFloat("reverb", "boost", &valf))
843 ReverbBoost *= powf(10.0f, valf / 20.0f);
845 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
847 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
848 ConfigValueStr(NULL, "drivers", &devs))
850 int n;
851 size_t len;
852 const char *next = devs;
853 int endlist, delitem;
855 i = 0;
856 do {
857 devs = next;
858 next = strchr(devs, ',');
860 delitem = (devs[0] == '-');
861 if(devs[0] == '-') devs++;
863 if(!devs[0] || devs[0] == ',')
865 endlist = 0;
866 continue;
868 endlist = 1;
870 len = (next ? ((size_t)(next-devs)) : strlen(devs));
871 for(n = i;BackendList[n].Init;n++)
873 if(len == strlen(BackendList[n].name) &&
874 strncmp(BackendList[n].name, devs, len) == 0)
876 if(delitem)
878 do {
879 BackendList[n] = BackendList[n+1];
880 ++n;
881 } while(BackendList[n].Init);
883 else
885 struct BackendInfo Bkp = BackendList[n];
886 while(n > i)
888 BackendList[n] = BackendList[n-1];
889 --n;
891 BackendList[n] = Bkp;
893 i++;
895 break;
898 } while(next++);
900 if(endlist)
902 BackendList[i].name = NULL;
903 BackendList[i].Init = NULL;
904 BackendList[i].Deinit = NULL;
905 BackendList[i].Probe = NULL;
909 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
911 if(!BackendList[i].Init(&BackendList[i].Funcs))
913 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
914 continue;
917 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
918 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
920 PlaybackBackend = BackendList[i];
921 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
923 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
925 CaptureBackend = BackendList[i];
926 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
929 BackendLoopback.Init(&BackendLoopback.Funcs);
931 if(ConfigValueStr(NULL, "excludefx", &str))
933 size_t len;
934 const char *next = str;
936 do {
937 str = next;
938 next = strchr(str, ',');
940 if(!str[0] || next == str)
941 continue;
943 len = (next ? ((size_t)(next-str)) : strlen(str));
944 for(n = 0;EffectList[n].name;n++)
946 if(len == strlen(EffectList[n].name) &&
947 strncmp(EffectList[n].name, str, len) == 0)
948 DisabledEffects[EffectList[n].type] = AL_TRUE;
950 } while(next++);
953 InitEffect(&DefaultEffect);
954 str = getenv("ALSOFT_DEFAULT_REVERB");
955 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
956 LoadReverbPreset(str, &DefaultEffect);
958 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
961 /************************************************
962 * Library deinitialization
963 ************************************************/
964 static void alc_cleanup(void)
966 ALCdevice *dev;
968 free(alcAllDevicesList); alcAllDevicesList = NULL;
969 alcAllDevicesListSize = 0;
970 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
971 alcCaptureDeviceListSize = 0;
973 free(alcDefaultAllDevicesSpecifier);
974 alcDefaultAllDevicesSpecifier = NULL;
975 free(alcCaptureDefaultDeviceSpecifier);
976 alcCaptureDefaultDeviceSpecifier = NULL;
978 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
980 ALCuint num = 0;
981 do {
982 num++;
983 } while((dev=dev->next) != NULL);
984 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
988 static void alc_deinit_safe(void)
990 alc_cleanup();
992 FreeHrtf();
993 FreeALConfig();
995 ThunkExit();
996 DeleteCriticalSection(&ListLock);
997 pthread_key_delete(LocalContext);
999 if(LogFile != stderr)
1000 fclose(LogFile);
1001 LogFile = NULL;
1004 static void alc_deinit(void)
1006 int i;
1008 alc_cleanup();
1010 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1011 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1013 for(i = 0;BackendList[i].Deinit;i++)
1014 BackendList[i].Deinit();
1015 BackendLoopback.Deinit();
1017 alc_deinit_safe();
1021 /************************************************
1022 * Device enumeration
1023 ************************************************/
1024 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1026 DO_INITCONFIG();
1028 LockLists();
1029 free(*list);
1030 *list = NULL;
1031 *listsize = 0;
1033 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1034 PlaybackBackend.Probe(type);
1035 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1036 CaptureBackend.Probe(type);
1037 UnlockLists();
1040 static void ProbeAllDevicesList(void)
1041 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1042 static void ProbeCaptureDeviceList(void)
1043 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1046 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1048 size_t len = strlen(name);
1049 void *temp;
1051 if(len == 0)
1052 return;
1054 temp = realloc(*List, (*ListSize) + len + 2);
1055 if(!temp)
1057 ERR("Realloc failed to add %s!\n", name);
1058 return;
1060 *List = temp;
1062 memcpy((*List)+(*ListSize), name, len+1);
1063 *ListSize += len+1;
1064 (*List)[*ListSize] = 0;
1067 #define DECL_APPEND_LIST_FUNC(type) \
1068 void Append##type##List(const ALCchar *name) \
1069 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1071 DECL_APPEND_LIST_FUNC(AllDevices)
1072 DECL_APPEND_LIST_FUNC(CaptureDevice)
1074 #undef DECL_APPEND_LIST_FUNC
1077 /************************************************
1078 * Device format information
1079 ************************************************/
1080 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1082 switch(type)
1084 case DevFmtByte: return "Signed Byte";
1085 case DevFmtUByte: return "Unsigned Byte";
1086 case DevFmtShort: return "Signed Short";
1087 case DevFmtUShort: return "Unsigned Short";
1088 case DevFmtInt: return "Signed Int";
1089 case DevFmtUInt: return "Unsigned Int";
1090 case DevFmtFloat: return "Float";
1092 return "(unknown type)";
1094 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1096 switch(chans)
1098 case DevFmtMono: return "Mono";
1099 case DevFmtStereo: return "Stereo";
1100 case DevFmtQuad: return "Quadraphonic";
1101 case DevFmtX51: return "5.1 Surround";
1102 case DevFmtX51Side: return "5.1 Side";
1103 case DevFmtX61: return "6.1 Surround";
1104 case DevFmtX71: return "7.1 Surround";
1106 return "(unknown channels)";
1109 ALuint BytesFromDevFmt(enum DevFmtType type)
1111 switch(type)
1113 case DevFmtByte: return sizeof(ALbyte);
1114 case DevFmtUByte: return sizeof(ALubyte);
1115 case DevFmtShort: return sizeof(ALshort);
1116 case DevFmtUShort: return sizeof(ALushort);
1117 case DevFmtInt: return sizeof(ALint);
1118 case DevFmtUInt: return sizeof(ALuint);
1119 case DevFmtFloat: return sizeof(ALfloat);
1121 return 0;
1123 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1125 switch(chans)
1127 case DevFmtMono: return 1;
1128 case DevFmtStereo: return 2;
1129 case DevFmtQuad: return 4;
1130 case DevFmtX51: return 6;
1131 case DevFmtX51Side: return 6;
1132 case DevFmtX61: return 7;
1133 case DevFmtX71: return 8;
1135 return 0;
1138 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1139 enum DevFmtType *type)
1141 static const struct {
1142 ALenum format;
1143 enum DevFmtChannels channels;
1144 enum DevFmtType type;
1145 } list[] = {
1146 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1147 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1148 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1150 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1151 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1152 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1154 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1155 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1156 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1158 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1159 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1160 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1162 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1163 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1164 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1166 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1167 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1168 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1170 ALuint i;
1172 for(i = 0;i < COUNTOF(list);i++)
1174 if(list[i].format == format)
1176 *chans = list[i].channels;
1177 *type = list[i].type;
1178 return AL_TRUE;
1182 return AL_FALSE;
1185 static ALCboolean IsValidALCType(ALCenum type)
1187 switch(type)
1189 case ALC_BYTE_SOFT:
1190 case ALC_UNSIGNED_BYTE_SOFT:
1191 case ALC_SHORT_SOFT:
1192 case ALC_UNSIGNED_SHORT_SOFT:
1193 case ALC_INT_SOFT:
1194 case ALC_UNSIGNED_INT_SOFT:
1195 case ALC_FLOAT_SOFT:
1196 return ALC_TRUE;
1198 return ALC_FALSE;
1201 static ALCboolean IsValidALCChannels(ALCenum channels)
1203 switch(channels)
1205 case ALC_MONO_SOFT:
1206 case ALC_STEREO_SOFT:
1207 case ALC_QUAD_SOFT:
1208 case ALC_5POINT1_SOFT:
1209 case ALC_6POINT1_SOFT:
1210 case ALC_7POINT1_SOFT:
1211 return ALC_TRUE;
1213 return ALC_FALSE;
1217 /************************************************
1218 * Miscellaneous ALC helpers
1219 ************************************************/
1221 /* SetDefaultWFXChannelOrder
1223 * Sets the default channel order used by WaveFormatEx.
1225 void SetDefaultWFXChannelOrder(ALCdevice *device)
1227 switch(device->FmtChans)
1229 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1231 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1232 device->DevChannels[1] = FrontRight; break;
1234 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1235 device->DevChannels[1] = FrontRight;
1236 device->DevChannels[2] = BackLeft;
1237 device->DevChannels[3] = BackRight; break;
1239 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1240 device->DevChannels[1] = FrontRight;
1241 device->DevChannels[2] = FrontCenter;
1242 device->DevChannels[3] = LFE;
1243 device->DevChannels[4] = BackLeft;
1244 device->DevChannels[5] = BackRight; break;
1246 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1247 device->DevChannels[1] = FrontRight;
1248 device->DevChannels[2] = FrontCenter;
1249 device->DevChannels[3] = LFE;
1250 device->DevChannels[4] = SideLeft;
1251 device->DevChannels[5] = SideRight; break;
1253 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1254 device->DevChannels[1] = FrontRight;
1255 device->DevChannels[2] = FrontCenter;
1256 device->DevChannels[3] = LFE;
1257 device->DevChannels[4] = BackCenter;
1258 device->DevChannels[5] = SideLeft;
1259 device->DevChannels[6] = SideRight; break;
1261 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1262 device->DevChannels[1] = FrontRight;
1263 device->DevChannels[2] = FrontCenter;
1264 device->DevChannels[3] = LFE;
1265 device->DevChannels[4] = BackLeft;
1266 device->DevChannels[5] = BackRight;
1267 device->DevChannels[6] = SideLeft;
1268 device->DevChannels[7] = SideRight; break;
1272 /* SetDefaultChannelOrder
1274 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1276 void SetDefaultChannelOrder(ALCdevice *device)
1278 switch(device->FmtChans)
1280 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1281 device->DevChannels[1] = FrontRight;
1282 device->DevChannels[2] = BackLeft;
1283 device->DevChannels[3] = BackRight;
1284 device->DevChannels[4] = FrontCenter;
1285 device->DevChannels[5] = LFE;
1286 return;
1288 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1289 device->DevChannels[1] = FrontRight;
1290 device->DevChannels[2] = BackLeft;
1291 device->DevChannels[3] = BackRight;
1292 device->DevChannels[4] = FrontCenter;
1293 device->DevChannels[5] = LFE;
1294 device->DevChannels[6] = SideLeft;
1295 device->DevChannels[7] = SideRight;
1296 return;
1298 /* Same as WFX order */
1299 case DevFmtMono:
1300 case DevFmtStereo:
1301 case DevFmtQuad:
1302 case DevFmtX51Side:
1303 case DevFmtX61:
1304 break;
1306 SetDefaultWFXChannelOrder(device);
1310 /* alcSetError
1312 * Stores the latest ALC device error
1314 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1316 if(TrapALCError)
1318 #ifdef _WIN32
1319 /* DebugBreak() will cause an exception if there is no debugger */
1320 if(IsDebuggerPresent())
1321 DebugBreak();
1322 #elif defined(SIGTRAP)
1323 raise(SIGTRAP);
1324 #endif
1327 if(device)
1328 device->LastError = errorCode;
1329 else
1330 LastNullDeviceError = errorCode;
1334 /* UpdateDeviceParams
1336 * Updates device parameters according to the attribute list (caller is
1337 * responsible for holding the list lock).
1339 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1341 ALCcontext *context;
1342 enum DevFmtChannels oldChans;
1343 enum DevFmtType oldType;
1344 ALCuint oldFreq;
1345 int oldMode;
1346 ALuint i;
1348 // Check for attributes
1349 if(device->Type == Loopback)
1351 enum {
1352 GotFreq = 1<<0,
1353 GotChans = 1<<1,
1354 GotType = 1<<2,
1355 GotAll = GotFreq|GotChans|GotType
1357 ALCuint freq, numMono, numStereo, numSends;
1358 enum DevFmtChannels schans;
1359 enum DevFmtType stype;
1360 ALCuint attrIdx = 0;
1361 ALCint gotFmt = 0;
1363 if(!attrList)
1365 WARN("Missing attributes for loopback device\n");
1366 return ALC_INVALID_VALUE;
1369 numMono = device->NumMonoSources;
1370 numStereo = device->NumStereoSources;
1371 numSends = device->NumAuxSends;
1372 schans = device->FmtChans;
1373 stype = device->FmtType;
1374 freq = device->Frequency;
1376 while(attrList[attrIdx])
1378 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1380 ALCint val = attrList[attrIdx + 1];
1381 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1382 return ALC_INVALID_VALUE;
1383 schans = val;
1384 gotFmt |= GotChans;
1387 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1389 ALCint val = attrList[attrIdx + 1];
1390 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1391 return ALC_INVALID_VALUE;
1392 stype = val;
1393 gotFmt |= GotType;
1396 if(attrList[attrIdx] == ALC_FREQUENCY)
1398 freq = attrList[attrIdx + 1];
1399 if(freq < MIN_OUTPUT_RATE)
1400 return ALC_INVALID_VALUE;
1401 gotFmt |= GotFreq;
1404 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1406 numStereo = attrList[attrIdx + 1];
1407 if(numStereo > device->MaxNoOfSources)
1408 numStereo = device->MaxNoOfSources;
1410 numMono = device->MaxNoOfSources - numStereo;
1413 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1414 numSends = attrList[attrIdx + 1];
1416 attrIdx += 2;
1419 if(gotFmt != GotAll)
1421 WARN("Missing format for loopback device\n");
1422 return ALC_INVALID_VALUE;
1425 ConfigValueUInt(NULL, "sends", &numSends);
1426 numSends = minu(MAX_SENDS, numSends);
1428 if((device->Flags&DEVICE_RUNNING))
1429 ALCdevice_StopPlayback(device);
1430 device->Flags &= ~DEVICE_RUNNING;
1432 device->Frequency = freq;
1433 device->FmtChans = schans;
1434 device->FmtType = stype;
1435 device->NumMonoSources = numMono;
1436 device->NumStereoSources = numStereo;
1437 device->NumAuxSends = numSends;
1439 else if(attrList && attrList[0])
1441 ALCuint freq, numMono, numStereo, numSends;
1442 ALCuint attrIdx = 0;
1444 /* If a context is already running on the device, stop playback so the
1445 * device attributes can be updated. */
1446 if((device->Flags&DEVICE_RUNNING))
1447 ALCdevice_StopPlayback(device);
1448 device->Flags &= ~DEVICE_RUNNING;
1450 freq = device->Frequency;
1451 numMono = device->NumMonoSources;
1452 numStereo = device->NumStereoSources;
1453 numSends = device->NumAuxSends;
1455 while(attrList[attrIdx])
1457 if(attrList[attrIdx] == ALC_FREQUENCY)
1459 freq = attrList[attrIdx + 1];
1460 device->Flags |= DEVICE_FREQUENCY_REQUEST;
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 ConfigValueUInt(NULL, "frequency", &freq);
1479 freq = maxu(freq, MIN_OUTPUT_RATE);
1481 ConfigValueUInt(NULL, "sends", &numSends);
1482 numSends = minu(MAX_SENDS, numSends);
1484 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1485 device->Frequency;
1487 device->Frequency = freq;
1488 device->NumMonoSources = numMono;
1489 device->NumStereoSources = numStereo;
1490 device->NumAuxSends = numSends;
1493 if((device->Flags&DEVICE_RUNNING))
1494 return ALC_NO_ERROR;
1496 oldFreq = device->Frequency;
1497 oldChans = device->FmtChans;
1498 oldType = device->FmtType;
1500 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1501 DevFmtChannelsString(device->FmtChans),
1502 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1503 DevFmtTypeString(device->FmtType),
1504 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1505 device->Frequency,
1506 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1507 device->UpdateSize, device->NumUpdates);
1509 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1510 return ALC_INVALID_DEVICE;
1512 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1514 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1515 DevFmtChannelsString(device->FmtChans));
1516 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1518 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1520 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1521 DevFmtTypeString(device->FmtType));
1522 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1524 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1526 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1527 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1530 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1531 DevFmtChannelsString(device->FmtChans),
1532 DevFmtTypeString(device->FmtType), device->Frequency,
1533 device->UpdateSize, device->NumUpdates);
1535 aluInitPanning(device);
1537 for(i = 0;i < MaxChannels;i++)
1539 device->ClickRemoval[i] = 0.0f;
1540 device->PendingClicks[i] = 0.0f;
1543 device->Hrtf = NULL;
1544 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1545 device->Hrtf = GetHrtf(device);
1546 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1548 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1550 if(!device->Bs2b)
1552 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1553 bs2b_clear(device->Bs2b);
1555 bs2b_set_srate(device->Bs2b, device->Frequency);
1556 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1557 TRACE("BS2B level %d\n", device->Bs2bLevel);
1559 else
1561 free(device->Bs2b);
1562 device->Bs2b = NULL;
1563 TRACE("BS2B disabled\n");
1566 device->Flags &= ~DEVICE_WIDE_STEREO;
1567 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1568 device->Flags |= DEVICE_WIDE_STEREO;
1570 oldMode = SetMixerFPUMode();
1571 LockDevice(device);
1572 context = device->ContextList;
1573 while(context)
1575 ALsizei pos;
1577 context->UpdateSources = AL_FALSE;
1578 LockUIntMapRead(&context->EffectSlotMap);
1579 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1581 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1583 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1585 UnlockUIntMapRead(&context->EffectSlotMap);
1586 UnlockDevice(device);
1587 RestoreFPUMode(oldMode);
1588 return ALC_INVALID_DEVICE;
1590 slot->NeedsUpdate = AL_FALSE;
1591 ALeffectState_Update(slot->EffectState, device, slot);
1593 UnlockUIntMapRead(&context->EffectSlotMap);
1595 LockUIntMapRead(&context->SourceMap);
1596 for(pos = 0;pos < context->SourceMap.size;pos++)
1598 ALsource *source = context->SourceMap.array[pos].value;
1599 ALuint s = device->NumAuxSends;
1600 while(s < MAX_SENDS)
1602 if(source->Send[s].Slot)
1603 DecrementRef(&source->Send[s].Slot->ref);
1604 source->Send[s].Slot = NULL;
1605 source->Send[s].Gain = 1.0f;
1606 source->Send[s].GainHF = 1.0f;
1607 s++;
1609 source->NeedsUpdate = AL_FALSE;
1610 ALsource_Update(source, context);
1612 UnlockUIntMapRead(&context->SourceMap);
1614 context = context->next;
1616 if(device->DefaultSlot)
1618 ALeffectslot *slot = device->DefaultSlot;
1620 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1622 UnlockDevice(device);
1623 RestoreFPUMode(oldMode);
1624 return ALC_INVALID_DEVICE;
1626 slot->NeedsUpdate = AL_FALSE;
1627 ALeffectState_Update(slot->EffectState, device, slot);
1629 UnlockDevice(device);
1630 RestoreFPUMode(oldMode);
1632 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1633 return ALC_INVALID_DEVICE;
1634 device->Flags |= DEVICE_RUNNING;
1636 return ALC_NO_ERROR;
1639 /* FreeDevice
1641 * Frees the device structure, and destroys any objects the app failed to
1642 * delete. Called once there's no more references on the device.
1644 static ALCvoid FreeDevice(ALCdevice *device)
1646 TRACE("%p\n", device);
1648 if(device->DefaultSlot)
1650 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1651 device->DefaultSlot->EffectState = NULL;
1654 if(device->BufferMap.size > 0)
1656 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1657 ReleaseALBuffers(device);
1659 ResetUIntMap(&device->BufferMap);
1661 if(device->EffectMap.size > 0)
1663 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1664 ReleaseALEffects(device);
1666 ResetUIntMap(&device->EffectMap);
1668 if(device->FilterMap.size > 0)
1670 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1671 ReleaseALFilters(device);
1673 ResetUIntMap(&device->FilterMap);
1675 free(device->Bs2b);
1676 device->Bs2b = NULL;
1678 free(device->DeviceName);
1679 device->DeviceName = NULL;
1681 DeleteCriticalSection(&device->Mutex);
1683 free(device);
1687 void ALCdevice_IncRef(ALCdevice *device)
1689 RefCount ref;
1690 ref = IncrementRef(&device->ref);
1691 TRACEREF("%p increasing refcount to %u\n", device, ref);
1694 void ALCdevice_DecRef(ALCdevice *device)
1696 RefCount ref;
1697 ref = DecrementRef(&device->ref);
1698 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1699 if(ref == 0) FreeDevice(device);
1702 /* VerifyDevice
1704 * Checks if the device handle is valid, and increments its ref count if so.
1706 static ALCdevice *VerifyDevice(ALCdevice *device)
1708 ALCdevice *tmpDevice;
1710 if(!device)
1711 return NULL;
1713 LockLists();
1714 tmpDevice = DeviceList;
1715 while(tmpDevice && tmpDevice != device)
1716 tmpDevice = tmpDevice->next;
1718 if(tmpDevice)
1719 ALCdevice_IncRef(tmpDevice);
1720 UnlockLists();
1721 return tmpDevice;
1725 /* InitContext
1727 * Initializes context fields
1729 static ALvoid InitContext(ALCcontext *Context)
1731 ALint i, j;
1733 //Initialise listener
1734 Context->Listener.Gain = 1.0f;
1735 Context->Listener.MetersPerUnit = 1.0f;
1736 Context->Listener.Position[0] = 0.0f;
1737 Context->Listener.Position[1] = 0.0f;
1738 Context->Listener.Position[2] = 0.0f;
1739 Context->Listener.Velocity[0] = 0.0f;
1740 Context->Listener.Velocity[1] = 0.0f;
1741 Context->Listener.Velocity[2] = 0.0f;
1742 Context->Listener.Forward[0] = 0.0f;
1743 Context->Listener.Forward[1] = 0.0f;
1744 Context->Listener.Forward[2] = -1.0f;
1745 Context->Listener.Up[0] = 0.0f;
1746 Context->Listener.Up[1] = 1.0f;
1747 Context->Listener.Up[2] = 0.0f;
1748 for(i = 0;i < 4;i++)
1750 for(j = 0;j < 4;j++)
1751 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1754 //Validate Context
1755 Context->LastError = AL_NO_ERROR;
1756 Context->UpdateSources = AL_FALSE;
1757 Context->ActiveSourceCount = 0;
1758 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1759 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1761 //Set globals
1762 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1763 Context->SourceDistanceModel = AL_FALSE;
1764 Context->DopplerFactor = 1.0f;
1765 Context->DopplerVelocity = 1.0f;
1766 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1767 Context->DeferUpdates = AL_FALSE;
1769 Context->ExtensionList = alExtList;
1773 /* FreeContext
1775 * Cleans up the context, and destroys any remaining objects the app failed to
1776 * delete. Called once there's no more references on the context.
1778 static ALCvoid FreeContext(ALCcontext *context)
1780 TRACE("%p\n", context);
1782 if(context->SourceMap.size > 0)
1784 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1785 ReleaseALSources(context);
1787 ResetUIntMap(&context->SourceMap);
1789 if(context->EffectSlotMap.size > 0)
1791 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1792 ReleaseALAuxiliaryEffectSlots(context);
1794 ResetUIntMap(&context->EffectSlotMap);
1796 context->ActiveSourceCount = 0;
1797 free(context->ActiveSources);
1798 context->ActiveSources = NULL;
1799 context->MaxActiveSources = 0;
1801 context->ActiveEffectSlotCount = 0;
1802 free(context->ActiveEffectSlots);
1803 context->ActiveEffectSlots = NULL;
1804 context->MaxActiveEffectSlots = 0;
1806 ALCdevice_DecRef(context->Device);
1807 context->Device = NULL;
1809 //Invalidate context
1810 memset(context, 0, sizeof(ALCcontext));
1811 free(context);
1814 /* ReleaseContext
1816 * Removes the context reference from the given device and removes it from
1817 * being current on the running thread or globally.
1819 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1821 ALCcontext *volatile*tmp_ctx;
1823 if(pthread_getspecific(LocalContext) == context)
1825 WARN("%p released while current on thread\n", context);
1826 pthread_setspecific(LocalContext, NULL);
1827 ALCcontext_DecRef(context);
1830 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1831 ALCcontext_DecRef(context);
1833 LockDevice(device);
1834 tmp_ctx = &device->ContextList;
1835 while(*tmp_ctx)
1837 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1838 break;
1839 tmp_ctx = &(*tmp_ctx)->next;
1841 UnlockDevice(device);
1843 ALCcontext_DecRef(context);
1846 void ALCcontext_IncRef(ALCcontext *context)
1848 RefCount ref;
1849 ref = IncrementRef(&context->ref);
1850 TRACEREF("%p increasing refcount to %u\n", context, ref);
1853 void ALCcontext_DecRef(ALCcontext *context)
1855 RefCount ref;
1856 ref = DecrementRef(&context->ref);
1857 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1858 if(ref == 0) FreeContext(context);
1861 static void ReleaseThreadCtx(void *ptr)
1863 WARN("%p current for thread being destroyed\n", ptr);
1864 ALCcontext_DecRef(ptr);
1867 /* VerifyContext
1869 * Checks that the given context is valid, and increments its reference count.
1871 static ALCcontext *VerifyContext(ALCcontext *context)
1873 ALCdevice *dev;
1875 LockLists();
1876 dev = DeviceList;
1877 while(dev)
1879 ALCcontext *tmp_ctx = dev->ContextList;
1880 while(tmp_ctx)
1882 if(tmp_ctx == context)
1884 ALCcontext_IncRef(tmp_ctx);
1885 UnlockLists();
1886 return tmp_ctx;
1888 tmp_ctx = tmp_ctx->next;
1890 dev = dev->next;
1892 UnlockLists();
1894 return NULL;
1898 /* GetContextRef
1900 * Returns the currently active context for this thread, and adds a reference
1901 * without locking it.
1903 ALCcontext *GetContextRef(void)
1905 ALCcontext *context;
1907 context = pthread_getspecific(LocalContext);
1908 if(context)
1909 ALCcontext_IncRef(context);
1910 else
1912 LockLists();
1913 context = GlobalContext;
1914 if(context)
1915 ALCcontext_IncRef(context);
1916 UnlockLists();
1919 return context;
1923 /************************************************
1924 * Standard ALC functions
1925 ************************************************/
1927 /* alcGetError
1929 * Return last ALC generated error code for the given device
1931 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1933 ALCenum errorCode;
1935 if(VerifyDevice(device))
1937 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1938 ALCdevice_DecRef(device);
1940 else
1941 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1943 return errorCode;
1947 /* alcSuspendContext
1949 * Not functional
1951 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1953 (void)Context;
1956 /* alcProcessContext
1958 * Not functional
1960 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
1962 (void)Context;
1966 /* alcGetString
1968 * Returns information about the device, and error strings
1970 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
1972 const ALCchar *value = NULL;
1974 switch(param)
1976 case ALC_NO_ERROR:
1977 value = alcNoError;
1978 break;
1980 case ALC_INVALID_ENUM:
1981 value = alcErrInvalidEnum;
1982 break;
1984 case ALC_INVALID_VALUE:
1985 value = alcErrInvalidValue;
1986 break;
1988 case ALC_INVALID_DEVICE:
1989 value = alcErrInvalidDevice;
1990 break;
1992 case ALC_INVALID_CONTEXT:
1993 value = alcErrInvalidContext;
1994 break;
1996 case ALC_OUT_OF_MEMORY:
1997 value = alcErrOutOfMemory;
1998 break;
2000 case ALC_DEVICE_SPECIFIER:
2001 value = alcDefaultName;
2002 break;
2004 case ALC_ALL_DEVICES_SPECIFIER:
2005 if(VerifyDevice(Device))
2007 value = Device->DeviceName;
2008 ALCdevice_DecRef(Device);
2010 else
2012 ProbeAllDevicesList();
2013 value = alcAllDevicesList;
2015 break;
2017 case ALC_CAPTURE_DEVICE_SPECIFIER:
2018 if(VerifyDevice(Device))
2020 value = Device->DeviceName;
2021 ALCdevice_DecRef(Device);
2023 else
2025 ProbeCaptureDeviceList();
2026 value = alcCaptureDeviceList;
2028 break;
2030 /* Default devices are always first in the list */
2031 case ALC_DEFAULT_DEVICE_SPECIFIER:
2032 value = alcDefaultName;
2033 break;
2035 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2036 if(!alcAllDevicesList)
2037 ProbeAllDevicesList();
2039 Device = VerifyDevice(Device);
2041 free(alcDefaultAllDevicesSpecifier);
2042 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2043 alcAllDevicesList : "");
2044 if(!alcDefaultAllDevicesSpecifier)
2045 alcSetError(Device, ALC_OUT_OF_MEMORY);
2047 value = alcDefaultAllDevicesSpecifier;
2048 if(Device) ALCdevice_DecRef(Device);
2049 break;
2051 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2052 if(!alcCaptureDeviceList)
2053 ProbeCaptureDeviceList();
2055 Device = VerifyDevice(Device);
2057 free(alcCaptureDefaultDeviceSpecifier);
2058 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2059 alcCaptureDeviceList : "");
2060 if(!alcCaptureDefaultDeviceSpecifier)
2061 alcSetError(Device, ALC_OUT_OF_MEMORY);
2063 value = alcCaptureDefaultDeviceSpecifier;
2064 if(Device) ALCdevice_DecRef(Device);
2065 break;
2067 case ALC_EXTENSIONS:
2068 if(!VerifyDevice(Device))
2069 value = alcNoDeviceExtList;
2070 else
2072 value = alcExtensionList;
2073 ALCdevice_DecRef(Device);
2075 break;
2077 default:
2078 Device = VerifyDevice(Device);
2079 alcSetError(Device, ALC_INVALID_ENUM);
2080 if(Device) ALCdevice_DecRef(Device);
2081 break;
2084 return value;
2088 /* alcGetIntegerv
2090 * Returns information about the device and the version of OpenAL
2092 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2094 device = VerifyDevice(device);
2096 if(size == 0 || data == NULL)
2098 alcSetError(device, ALC_INVALID_VALUE);
2099 if(device) ALCdevice_DecRef(device);
2100 return;
2103 if(!device)
2105 switch(param)
2107 case ALC_MAJOR_VERSION:
2108 *data = alcMajorVersion;
2109 break;
2110 case ALC_MINOR_VERSION:
2111 *data = alcMinorVersion;
2112 break;
2114 case ALC_ATTRIBUTES_SIZE:
2115 case ALC_ALL_ATTRIBUTES:
2116 case ALC_FREQUENCY:
2117 case ALC_REFRESH:
2118 case ALC_SYNC:
2119 case ALC_MONO_SOURCES:
2120 case ALC_STEREO_SOURCES:
2121 case ALC_CAPTURE_SAMPLES:
2122 case ALC_FORMAT_CHANNELS_SOFT:
2123 case ALC_FORMAT_TYPE_SOFT:
2124 alcSetError(NULL, ALC_INVALID_DEVICE);
2125 break;
2127 default:
2128 alcSetError(NULL, ALC_INVALID_ENUM);
2129 break;
2132 else if(device->Type == Capture)
2134 switch(param)
2136 case ALC_CAPTURE_SAMPLES:
2137 LockLists();
2138 /* Re-validate the device since it may have been closed */
2139 ALCdevice_DecRef(device);
2140 if((device=VerifyDevice(device)) != NULL)
2141 *data = ALCdevice_AvailableSamples(device);
2142 else
2143 alcSetError(NULL, ALC_INVALID_DEVICE);
2144 UnlockLists();
2145 break;
2147 case ALC_CONNECTED:
2148 *data = device->Connected;
2149 break;
2151 default:
2152 alcSetError(device, ALC_INVALID_ENUM);
2153 break;
2156 else /* render device */
2158 switch(param)
2160 case ALC_MAJOR_VERSION:
2161 *data = alcMajorVersion;
2162 break;
2164 case ALC_MINOR_VERSION:
2165 *data = alcMinorVersion;
2166 break;
2168 case ALC_EFX_MAJOR_VERSION:
2169 *data = alcEFXMajorVersion;
2170 break;
2172 case ALC_EFX_MINOR_VERSION:
2173 *data = alcEFXMinorVersion;
2174 break;
2176 case ALC_ATTRIBUTES_SIZE:
2177 *data = 13;
2178 break;
2180 case ALC_ALL_ATTRIBUTES:
2181 if(size < 13)
2182 alcSetError(device, ALC_INVALID_VALUE);
2183 else
2185 int i = 0;
2187 data[i++] = ALC_FREQUENCY;
2188 data[i++] = device->Frequency;
2190 if(device->Type != Loopback)
2192 data[i++] = ALC_REFRESH;
2193 data[i++] = device->Frequency / device->UpdateSize;
2195 data[i++] = ALC_SYNC;
2196 data[i++] = ALC_FALSE;
2198 else
2200 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2201 data[i++] = device->FmtChans;
2203 data[i++] = ALC_FORMAT_TYPE_SOFT;
2204 data[i++] = device->FmtType;
2207 data[i++] = ALC_MONO_SOURCES;
2208 data[i++] = device->NumMonoSources;
2210 data[i++] = ALC_STEREO_SOURCES;
2211 data[i++] = device->NumStereoSources;
2213 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2214 data[i++] = device->NumAuxSends;
2216 data[i++] = 0;
2218 break;
2220 case ALC_FREQUENCY:
2221 *data = device->Frequency;
2222 break;
2224 case ALC_REFRESH:
2225 if(device->Type == Loopback)
2226 alcSetError(device, ALC_INVALID_DEVICE);
2227 else
2228 *data = device->Frequency / device->UpdateSize;
2229 break;
2231 case ALC_SYNC:
2232 if(device->Type == Loopback)
2233 alcSetError(device, ALC_INVALID_DEVICE);
2234 else
2235 *data = ALC_FALSE;
2236 break;
2238 case ALC_FORMAT_CHANNELS_SOFT:
2239 if(device->Type != Loopback)
2240 alcSetError(device, ALC_INVALID_DEVICE);
2241 else
2242 *data = device->FmtChans;
2243 break;
2245 case ALC_FORMAT_TYPE_SOFT:
2246 if(device->Type != Loopback)
2247 alcSetError(device, ALC_INVALID_DEVICE);
2248 else
2249 *data = device->FmtType;
2250 break;
2252 case ALC_MONO_SOURCES:
2253 *data = device->NumMonoSources;
2254 break;
2256 case ALC_STEREO_SOURCES:
2257 *data = device->NumStereoSources;
2258 break;
2260 case ALC_MAX_AUXILIARY_SENDS:
2261 *data = device->NumAuxSends;
2262 break;
2264 case ALC_CONNECTED:
2265 *data = device->Connected;
2266 break;
2268 default:
2269 alcSetError(device, ALC_INVALID_ENUM);
2270 break;
2273 if(device)
2274 ALCdevice_DecRef(device);
2278 /* alcIsExtensionPresent
2280 * Determines if there is support for a particular extension
2282 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2284 ALCboolean bResult = ALC_FALSE;
2286 device = VerifyDevice(device);
2288 if(!extName)
2289 alcSetError(device, ALC_INVALID_VALUE);
2290 else
2292 size_t len = strlen(extName);
2293 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2294 while(ptr && *ptr)
2296 if(strncasecmp(ptr, extName, len) == 0 &&
2297 (ptr[len] == '\0' || isspace(ptr[len])))
2299 bResult = ALC_TRUE;
2300 break;
2302 if((ptr=strchr(ptr, ' ')) != NULL)
2304 do {
2305 ++ptr;
2306 } while(isspace(*ptr));
2310 if(device)
2311 ALCdevice_DecRef(device);
2312 return bResult;
2316 /* alcGetProcAddress
2318 * Retrieves the function address for a particular extension function
2320 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2322 ALCvoid *ptr = NULL;
2324 if(!funcName)
2326 device = VerifyDevice(device);
2327 alcSetError(device, ALC_INVALID_VALUE);
2328 if(device) ALCdevice_DecRef(device);
2330 else
2332 ALsizei i = 0;
2333 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2334 i++;
2335 ptr = alcFunctions[i].address;
2338 return ptr;
2342 /* alcGetEnumValue
2344 * Get the value for a particular ALC enumeration name
2346 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2348 ALCenum val = 0;
2350 if(!enumName)
2352 device = VerifyDevice(device);
2353 alcSetError(device, ALC_INVALID_VALUE);
2354 if(device) ALCdevice_DecRef(device);
2356 else
2358 ALsizei i = 0;
2359 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2360 i++;
2361 val = enumeration[i].value;
2364 return val;
2368 /* alcCreateContext
2370 * Create and attach a context to the given device.
2372 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2374 ALCcontext *ALContext;
2375 ALCenum err;
2377 LockLists();
2378 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2380 UnlockLists();
2381 alcSetError(device, ALC_INVALID_DEVICE);
2382 if(device) ALCdevice_DecRef(device);
2383 return NULL;
2386 device->LastError = ALC_NO_ERROR;
2388 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2390 UnlockLists();
2391 alcSetError(device, err);
2392 if(err == ALC_INVALID_DEVICE)
2393 aluHandleDisconnect(device);
2394 ALCdevice_DecRef(device);
2395 return NULL;
2398 ALContext = calloc(1, sizeof(ALCcontext));
2399 if(ALContext)
2401 ALContext->ref = 1;
2403 ALContext->MaxActiveSources = 256;
2404 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2405 ALContext->MaxActiveSources);
2407 if(!ALContext || !ALContext->ActiveSources)
2409 if(!device->ContextList)
2411 ALCdevice_StopPlayback(device);
2412 device->Flags &= ~DEVICE_RUNNING;
2414 UnlockLists();
2416 free(ALContext);
2417 ALContext = NULL;
2419 alcSetError(device, ALC_OUT_OF_MEMORY);
2420 ALCdevice_DecRef(device);
2421 return NULL;
2424 ALContext->Device = device;
2425 ALCdevice_IncRef(device);
2426 InitContext(ALContext);
2428 do {
2429 ALContext->next = device->ContextList;
2430 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2431 UnlockLists();
2433 ALCdevice_DecRef(device);
2435 TRACE("Created context %p\n", ALContext);
2436 return ALContext;
2439 /* alcDestroyContext
2441 * Remove a context from its device
2443 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2445 ALCdevice *Device;
2447 LockLists();
2448 /* alcGetContextsDevice sets an error for invalid contexts */
2449 Device = alcGetContextsDevice(context);
2450 if(Device)
2452 ReleaseContext(context, Device);
2453 if(!Device->ContextList)
2455 ALCdevice_StopPlayback(Device);
2456 Device->Flags &= ~DEVICE_RUNNING;
2459 UnlockLists();
2463 /* alcGetCurrentContext
2465 * Returns the currently active context on the calling thread
2467 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2469 ALCcontext *Context;
2471 Context = pthread_getspecific(LocalContext);
2472 if(!Context) Context = GlobalContext;
2474 return Context;
2477 /* alcGetThreadContext
2479 * Returns the currently active thread-local context
2481 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2483 ALCcontext *Context;
2484 Context = pthread_getspecific(LocalContext);
2485 return Context;
2489 /* alcMakeContextCurrent
2491 * Makes the given context the active process-wide context, and removes the
2492 * thread-local context for the calling thread.
2494 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2496 /* context must be valid or NULL */
2497 if(context && !(context=VerifyContext(context)))
2499 alcSetError(NULL, ALC_INVALID_CONTEXT);
2500 return ALC_FALSE;
2502 /* context's reference count is already incremented */
2503 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2504 if(context) ALCcontext_DecRef(context);
2506 if((context=pthread_getspecific(LocalContext)) != NULL)
2508 pthread_setspecific(LocalContext, NULL);
2509 ALCcontext_DecRef(context);
2512 return ALC_TRUE;
2515 /* alcSetThreadContext
2517 * Makes the given context the active context for the current thread
2519 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2521 ALCcontext *old;
2523 /* context must be valid or NULL */
2524 if(context && !(context=VerifyContext(context)))
2526 alcSetError(NULL, ALC_INVALID_CONTEXT);
2527 return ALC_FALSE;
2529 /* context's reference count is already incremented */
2530 old = pthread_getspecific(LocalContext);
2531 pthread_setspecific(LocalContext, context);
2532 if(old) ALCcontext_DecRef(old);
2534 return ALC_TRUE;
2538 /* alcGetContextsDevice
2540 * Returns the device that a particular context is attached to
2542 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2544 ALCdevice *Device;
2546 if(!(Context=VerifyContext(Context)))
2548 alcSetError(NULL, ALC_INVALID_CONTEXT);
2549 return NULL;
2551 Device = Context->Device;
2552 ALCcontext_DecRef(Context);
2554 return Device;
2558 /* alcOpenDevice
2560 * Opens the named device.
2562 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2564 const ALCchar *fmt;
2565 ALCdevice *device;
2566 ALCenum err;
2568 DO_INITCONFIG();
2570 if(!PlaybackBackend.name)
2572 alcSetError(NULL, ALC_INVALID_VALUE);
2573 return NULL;
2576 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2577 deviceName = NULL;
2579 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2580 if(!device)
2582 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2583 return NULL;
2586 //Validate device
2587 device->Funcs = &PlaybackBackend.Funcs;
2588 device->ref = 1;
2589 device->Connected = ALC_TRUE;
2590 device->Type = Playback;
2591 InitializeCriticalSection(&device->Mutex);
2592 device->LastError = ALC_NO_ERROR;
2594 device->Flags = 0;
2595 device->Bs2b = NULL;
2596 device->Bs2bLevel = 0;
2597 device->DeviceName = NULL;
2599 device->ContextList = NULL;
2601 device->MaxNoOfSources = 256;
2602 device->AuxiliaryEffectSlotMax = 4;
2603 device->NumAuxSends = MAX_SENDS;
2605 InitUIntMap(&device->BufferMap, ~0);
2606 InitUIntMap(&device->EffectMap, ~0);
2607 InitUIntMap(&device->FilterMap, ~0);
2609 //Set output format
2610 device->FmtChans = DevFmtChannelsDefault;
2611 device->FmtType = DevFmtTypeDefault;
2612 device->Frequency = DEFAULT_OUTPUT_RATE;
2613 device->NumUpdates = 4;
2614 device->UpdateSize = 1024;
2616 if(ConfigValueStr(NULL, "channels", &fmt))
2618 static const struct {
2619 const char name[16];
2620 enum DevFmtChannels chans;
2621 } chanlist[] = {
2622 { "mono", DevFmtMono },
2623 { "stereo", DevFmtStereo },
2624 { "quad", DevFmtQuad },
2625 { "surround51", DevFmtX51 },
2626 { "surround61", DevFmtX61 },
2627 { "surround71", DevFmtX71 },
2629 size_t i;
2631 for(i = 0;i < COUNTOF(chanlist);i++)
2633 if(strcasecmp(chanlist[i].name, fmt) == 0)
2635 device->FmtChans = chanlist[i].chans;
2636 device->Flags |= DEVICE_CHANNELS_REQUEST;
2637 break;
2640 if(i == COUNTOF(chanlist))
2641 ERR("Unsupported channels: %s\n", fmt);
2643 if(ConfigValueStr(NULL, "sample-type", &fmt))
2645 static const struct {
2646 const char name[16];
2647 enum DevFmtType type;
2648 } typelist[] = {
2649 { "int8", DevFmtByte },
2650 { "uint8", DevFmtUByte },
2651 { "int16", DevFmtShort },
2652 { "uint16", DevFmtUShort },
2653 { "int32", DevFmtInt },
2654 { "uint32", DevFmtUInt },
2655 { "float32", DevFmtFloat },
2657 size_t i;
2659 for(i = 0;i < COUNTOF(typelist);i++)
2661 if(strcasecmp(typelist[i].name, fmt) == 0)
2663 device->FmtType = typelist[i].type;
2664 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2665 break;
2668 if(i == COUNTOF(typelist))
2669 ERR("Unsupported sample-type: %s\n", fmt);
2671 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2672 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2673 ConfigValueStr(NULL, "format", &fmt))
2675 static const struct {
2676 const char name[32];
2677 enum DevFmtChannels channels;
2678 enum DevFmtType type;
2679 } formats[] = {
2680 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2681 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2682 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2683 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2684 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2685 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2687 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2688 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2689 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2690 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2691 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2692 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2694 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2695 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2696 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2697 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2698 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2699 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2701 size_t i;
2703 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2704 for(i = 0;i < COUNTOF(formats);i++)
2706 if(strcasecmp(fmt, formats[i].name) == 0)
2708 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2709 device->FmtChans = formats[i].channels;
2710 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2711 device->FmtType = formats[i].type;
2712 device->Flags |= DEVICE_FORMAT_REQUEST;
2713 break;
2716 if(i == COUNTOF(formats))
2717 ERR("Unsupported format: %s\n", fmt);
2719 #undef DEVICE_FORMAT_REQUEST
2721 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2723 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2724 if(device->Frequency < MIN_OUTPUT_RATE)
2725 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2726 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2729 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2730 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2732 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2733 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2735 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2736 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2738 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2739 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2741 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2742 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2744 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2746 device->NumStereoSources = 1;
2747 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2749 // Find a playback device to open
2750 LockLists();
2751 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2753 UnlockLists();
2754 DeleteCriticalSection(&device->Mutex);
2755 free(device);
2756 alcSetError(NULL, err);
2757 return NULL;
2759 UnlockLists();
2761 if(DefaultEffect.type != AL_EFFECT_NULL)
2763 device->DefaultSlot = (ALeffectslot*)(device+1);
2764 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2766 device->DefaultSlot = NULL;
2767 ERR("Failed to initialize the default effect slot\n");
2769 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2771 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2772 device->DefaultSlot = NULL;
2773 ERR("Failed to initialize the default effect\n");
2777 do {
2778 device->next = DeviceList;
2779 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2781 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2782 return device;
2785 /* alcCloseDevice
2787 * Closes the given device.
2789 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2791 ALCdevice *volatile*list;
2792 ALCcontext *ctx;
2794 LockLists();
2795 list = &DeviceList;
2796 while(*list && *list != Device)
2797 list = &(*list)->next;
2799 if(!*list || (*list)->Type == Capture)
2801 alcSetError(*list, ALC_INVALID_DEVICE);
2802 UnlockLists();
2803 return ALC_FALSE;
2806 *list = (*list)->next;
2807 UnlockLists();
2809 while((ctx=Device->ContextList) != NULL)
2811 WARN("Releasing context %p\n", ctx);
2812 ReleaseContext(ctx, Device);
2814 if((Device->Flags&DEVICE_RUNNING))
2815 ALCdevice_StopPlayback(Device);
2816 Device->Flags &= ~DEVICE_RUNNING;
2818 ALCdevice_ClosePlayback(Device);
2820 ALCdevice_DecRef(Device);
2822 return ALC_TRUE;
2826 /************************************************
2827 * ALC capture functions
2828 ************************************************/
2829 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2831 ALCdevice *device = NULL;
2832 ALCenum err;
2834 DO_INITCONFIG();
2836 if(!CaptureBackend.name)
2838 alcSetError(NULL, ALC_INVALID_VALUE);
2839 return NULL;
2842 if(samples <= 0)
2844 alcSetError(NULL, ALC_INVALID_VALUE);
2845 return NULL;
2848 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2849 deviceName = NULL;
2851 device = calloc(1, sizeof(ALCdevice));
2852 if(!device)
2854 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2855 return NULL;
2858 //Validate device
2859 device->Funcs = &CaptureBackend.Funcs;
2860 device->ref = 1;
2861 device->Connected = ALC_TRUE;
2862 device->Type = Capture;
2863 InitializeCriticalSection(&device->Mutex);
2865 InitUIntMap(&device->BufferMap, ~0);
2866 InitUIntMap(&device->EffectMap, ~0);
2867 InitUIntMap(&device->FilterMap, ~0);
2869 device->DeviceName = NULL;
2871 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2872 device->Frequency = frequency;
2874 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2875 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2877 DeleteCriticalSection(&device->Mutex);
2878 free(device);
2879 alcSetError(NULL, ALC_INVALID_ENUM);
2880 return NULL;
2883 device->UpdateSize = samples;
2884 device->NumUpdates = 1;
2886 LockLists();
2887 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2889 UnlockLists();
2890 DeleteCriticalSection(&device->Mutex);
2891 free(device);
2892 alcSetError(NULL, err);
2893 return NULL;
2895 UnlockLists();
2897 do {
2898 device->next = DeviceList;
2899 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2901 TRACE("Created device %p\n", device);
2902 return device;
2905 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2907 ALCdevice *volatile*list;
2909 LockLists();
2910 list = &DeviceList;
2911 while(*list && *list != Device)
2912 list = &(*list)->next;
2914 if(!*list || (*list)->Type != Capture)
2916 alcSetError(*list, ALC_INVALID_DEVICE);
2917 UnlockLists();
2918 return ALC_FALSE;
2921 *list = (*list)->next;
2922 UnlockLists();
2924 ALCdevice_CloseCapture(Device);
2926 ALCdevice_DecRef(Device);
2928 return ALC_TRUE;
2931 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2933 LockLists();
2934 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2936 UnlockLists();
2937 alcSetError(device, ALC_INVALID_DEVICE);
2938 if(device) ALCdevice_DecRef(device);
2939 return;
2941 if(device->Connected)
2943 if(!(device->Flags&DEVICE_RUNNING))
2944 ALCdevice_StartCapture(device);
2945 device->Flags |= DEVICE_RUNNING;
2947 UnlockLists();
2949 ALCdevice_DecRef(device);
2952 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2954 LockLists();
2955 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2957 UnlockLists();
2958 alcSetError(device, ALC_INVALID_DEVICE);
2959 if(device) ALCdevice_DecRef(device);
2960 return;
2962 if((device->Flags&DEVICE_RUNNING))
2963 ALCdevice_StopCapture(device);
2964 device->Flags &= ~DEVICE_RUNNING;
2965 UnlockLists();
2967 ALCdevice_DecRef(device);
2970 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
2972 ALCenum err = ALC_INVALID_DEVICE;
2973 LockLists();
2974 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
2976 err = ALC_INVALID_VALUE;
2977 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
2978 err = ALCdevice_CaptureSamples(device, buffer, samples);
2980 UnlockLists();
2981 if(err != ALC_NO_ERROR)
2982 alcSetError(device, err);
2983 if(device) ALCdevice_DecRef(device);
2987 /************************************************
2988 * ALC loopback functions
2989 ************************************************/
2991 /* alcLoopbackOpenDeviceSOFT
2993 * Open a loopback device, for manual rendering.
2995 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
2997 ALCdevice *device;
2999 DO_INITCONFIG();
3001 /* Make sure the device name, if specified, is us. */
3002 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3004 alcSetError(NULL, ALC_INVALID_VALUE);
3005 return NULL;
3008 device = calloc(1, sizeof(ALCdevice));
3009 if(!device)
3011 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3012 return NULL;
3015 //Validate device
3016 device->Funcs = &BackendLoopback.Funcs;
3017 device->ref = 1;
3018 device->Connected = ALC_TRUE;
3019 device->Type = Loopback;
3020 InitializeCriticalSection(&device->Mutex);
3021 device->LastError = ALC_NO_ERROR;
3023 device->Flags = 0;
3024 device->Bs2b = NULL;
3025 device->Bs2bLevel = 0;
3026 device->DeviceName = NULL;
3028 device->ContextList = NULL;
3030 device->MaxNoOfSources = 256;
3031 device->AuxiliaryEffectSlotMax = 4;
3032 device->NumAuxSends = MAX_SENDS;
3034 InitUIntMap(&device->BufferMap, ~0);
3035 InitUIntMap(&device->EffectMap, ~0);
3036 InitUIntMap(&device->FilterMap, ~0);
3038 //Set output format
3039 device->NumUpdates = 0;
3040 device->UpdateSize = 0;
3042 device->Frequency = DEFAULT_OUTPUT_RATE;
3043 device->FmtChans = DevFmtChannelsDefault;
3044 device->FmtType = DevFmtTypeDefault;
3046 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3047 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3049 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3050 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3052 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3053 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3055 device->NumStereoSources = 1;
3056 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3058 // Open the "backend"
3059 ALCdevice_OpenPlayback(device, "Loopback");
3060 do {
3061 device->next = DeviceList;
3062 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3064 TRACE("Created device %p\n", device);
3065 return device;
3068 /* alcIsRenderFormatSupportedSOFT
3070 * Determines if the loopback device supports the given format for rendering.
3072 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3074 ALCboolean ret = ALC_FALSE;
3076 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3077 alcSetError(device, ALC_INVALID_DEVICE);
3078 else if(freq <= 0)
3079 alcSetError(device, ALC_INVALID_VALUE);
3080 else
3082 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3083 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3084 freq >= MIN_OUTPUT_RATE)
3085 ret = ALC_TRUE;
3087 if(device) ALCdevice_DecRef(device);
3089 return ret;
3092 /* alcRenderSamplesSOFT
3094 * Renders some samples into a buffer, using the format last set by the
3095 * attributes given to alcCreateContext.
3097 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3099 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3100 alcSetError(device, ALC_INVALID_DEVICE);
3101 else if(samples < 0 || (samples > 0 && buffer == NULL))
3102 alcSetError(device, ALC_INVALID_VALUE);
3103 else
3104 aluMixData(device, buffer, samples);
3105 if(device) ALCdevice_DecRef(device);