Keep the backend device open until the last reference is released
[openal-soft/openal-hmr.git] / Alc / ALc.c
blobf72122f3ca71e5e446b5dae732c030e4451e89b0
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 }
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(alGetSourcei64SOFT),
259 DECL(alGetSourcei64vSOFT),
261 { NULL, NULL }
263 #undef DECL
265 #define DECL(x) { #x, (x) }
266 static const ALCenums enumeration[] = {
267 DECL(ALC_INVALID),
268 DECL(ALC_FALSE),
269 DECL(ALC_TRUE),
271 DECL(ALC_MAJOR_VERSION),
272 DECL(ALC_MINOR_VERSION),
273 DECL(ALC_ATTRIBUTES_SIZE),
274 DECL(ALC_ALL_ATTRIBUTES),
275 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
276 DECL(ALC_DEVICE_SPECIFIER),
277 DECL(ALC_ALL_DEVICES_SPECIFIER),
278 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
279 DECL(ALC_EXTENSIONS),
280 DECL(ALC_FREQUENCY),
281 DECL(ALC_REFRESH),
282 DECL(ALC_SYNC),
283 DECL(ALC_MONO_SOURCES),
284 DECL(ALC_STEREO_SOURCES),
285 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
286 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
287 DECL(ALC_CAPTURE_SAMPLES),
288 DECL(ALC_CONNECTED),
290 DECL(ALC_EFX_MAJOR_VERSION),
291 DECL(ALC_EFX_MINOR_VERSION),
292 DECL(ALC_MAX_AUXILIARY_SENDS),
294 DECL(ALC_FORMAT_CHANNELS_SOFT),
295 DECL(ALC_FORMAT_TYPE_SOFT),
297 DECL(ALC_MONO_SOFT),
298 DECL(ALC_STEREO_SOFT),
299 DECL(ALC_QUAD_SOFT),
300 DECL(ALC_5POINT1_SOFT),
301 DECL(ALC_6POINT1_SOFT),
302 DECL(ALC_7POINT1_SOFT),
304 DECL(ALC_BYTE_SOFT),
305 DECL(ALC_UNSIGNED_BYTE_SOFT),
306 DECL(ALC_SHORT_SOFT),
307 DECL(ALC_UNSIGNED_SHORT_SOFT),
308 DECL(ALC_INT_SOFT),
309 DECL(ALC_UNSIGNED_INT_SOFT),
310 DECL(ALC_FLOAT_SOFT),
312 DECL(ALC_NO_ERROR),
313 DECL(ALC_INVALID_DEVICE),
314 DECL(ALC_INVALID_CONTEXT),
315 DECL(ALC_INVALID_ENUM),
316 DECL(ALC_INVALID_VALUE),
317 DECL(ALC_OUT_OF_MEMORY),
320 DECL(AL_INVALID),
321 DECL(AL_NONE),
322 DECL(AL_FALSE),
323 DECL(AL_TRUE),
325 DECL(AL_SOURCE_RELATIVE),
326 DECL(AL_CONE_INNER_ANGLE),
327 DECL(AL_CONE_OUTER_ANGLE),
328 DECL(AL_PITCH),
329 DECL(AL_POSITION),
330 DECL(AL_DIRECTION),
331 DECL(AL_VELOCITY),
332 DECL(AL_LOOPING),
333 DECL(AL_BUFFER),
334 DECL(AL_GAIN),
335 DECL(AL_MIN_GAIN),
336 DECL(AL_MAX_GAIN),
337 DECL(AL_ORIENTATION),
338 DECL(AL_REFERENCE_DISTANCE),
339 DECL(AL_ROLLOFF_FACTOR),
340 DECL(AL_CONE_OUTER_GAIN),
341 DECL(AL_MAX_DISTANCE),
342 DECL(AL_SEC_OFFSET),
343 DECL(AL_SAMPLE_OFFSET),
344 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
345 DECL(AL_BYTE_OFFSET),
346 DECL(AL_BYTE_RW_OFFSETS_SOFT),
347 DECL(AL_SOURCE_TYPE),
348 DECL(AL_STATIC),
349 DECL(AL_STREAMING),
350 DECL(AL_UNDETERMINED),
351 DECL(AL_METERS_PER_UNIT),
352 DECL(AL_DIRECT_CHANNELS_SOFT),
354 DECL(AL_DIRECT_FILTER),
355 DECL(AL_AUXILIARY_SEND_FILTER),
356 DECL(AL_AIR_ABSORPTION_FACTOR),
357 DECL(AL_ROOM_ROLLOFF_FACTOR),
358 DECL(AL_CONE_OUTER_GAINHF),
359 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
360 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
361 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
363 DECL(AL_SOURCE_STATE),
364 DECL(AL_INITIAL),
365 DECL(AL_PLAYING),
366 DECL(AL_PAUSED),
367 DECL(AL_STOPPED),
369 DECL(AL_BUFFERS_QUEUED),
370 DECL(AL_BUFFERS_PROCESSED),
372 DECL(AL_FORMAT_MONO8),
373 DECL(AL_FORMAT_MONO16),
374 DECL(AL_FORMAT_MONO_FLOAT32),
375 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
376 DECL(AL_FORMAT_STEREO8),
377 DECL(AL_FORMAT_STEREO16),
378 DECL(AL_FORMAT_STEREO_FLOAT32),
379 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
380 DECL(AL_FORMAT_MONO_IMA4),
381 DECL(AL_FORMAT_STEREO_IMA4),
382 DECL(AL_FORMAT_QUAD8_LOKI),
383 DECL(AL_FORMAT_QUAD16_LOKI),
384 DECL(AL_FORMAT_QUAD8),
385 DECL(AL_FORMAT_QUAD16),
386 DECL(AL_FORMAT_QUAD32),
387 DECL(AL_FORMAT_51CHN8),
388 DECL(AL_FORMAT_51CHN16),
389 DECL(AL_FORMAT_51CHN32),
390 DECL(AL_FORMAT_61CHN8),
391 DECL(AL_FORMAT_61CHN16),
392 DECL(AL_FORMAT_61CHN32),
393 DECL(AL_FORMAT_71CHN8),
394 DECL(AL_FORMAT_71CHN16),
395 DECL(AL_FORMAT_71CHN32),
396 DECL(AL_FORMAT_REAR8),
397 DECL(AL_FORMAT_REAR16),
398 DECL(AL_FORMAT_REAR32),
399 DECL(AL_FORMAT_MONO_MULAW),
400 DECL(AL_FORMAT_MONO_MULAW_EXT),
401 DECL(AL_FORMAT_STEREO_MULAW),
402 DECL(AL_FORMAT_STEREO_MULAW_EXT),
403 DECL(AL_FORMAT_QUAD_MULAW),
404 DECL(AL_FORMAT_51CHN_MULAW),
405 DECL(AL_FORMAT_61CHN_MULAW),
406 DECL(AL_FORMAT_71CHN_MULAW),
407 DECL(AL_FORMAT_REAR_MULAW),
408 DECL(AL_FORMAT_MONO_ALAW_EXT),
409 DECL(AL_FORMAT_STEREO_ALAW_EXT),
411 DECL(AL_MONO8_SOFT),
412 DECL(AL_MONO16_SOFT),
413 DECL(AL_MONO32F_SOFT),
414 DECL(AL_STEREO8_SOFT),
415 DECL(AL_STEREO16_SOFT),
416 DECL(AL_STEREO32F_SOFT),
417 DECL(AL_QUAD8_SOFT),
418 DECL(AL_QUAD16_SOFT),
419 DECL(AL_QUAD32F_SOFT),
420 DECL(AL_REAR8_SOFT),
421 DECL(AL_REAR16_SOFT),
422 DECL(AL_REAR32F_SOFT),
423 DECL(AL_5POINT1_8_SOFT),
424 DECL(AL_5POINT1_16_SOFT),
425 DECL(AL_5POINT1_32F_SOFT),
426 DECL(AL_6POINT1_8_SOFT),
427 DECL(AL_6POINT1_16_SOFT),
428 DECL(AL_6POINT1_32F_SOFT),
429 DECL(AL_7POINT1_8_SOFT),
430 DECL(AL_7POINT1_16_SOFT),
431 DECL(AL_7POINT1_32F_SOFT),
433 DECL(AL_MONO_SOFT),
434 DECL(AL_STEREO_SOFT),
435 DECL(AL_QUAD_SOFT),
436 DECL(AL_REAR_SOFT),
437 DECL(AL_5POINT1_SOFT),
438 DECL(AL_6POINT1_SOFT),
439 DECL(AL_7POINT1_SOFT),
441 DECL(AL_BYTE_SOFT),
442 DECL(AL_UNSIGNED_BYTE_SOFT),
443 DECL(AL_SHORT_SOFT),
444 DECL(AL_UNSIGNED_SHORT_SOFT),
445 DECL(AL_INT_SOFT),
446 DECL(AL_UNSIGNED_INT_SOFT),
447 DECL(AL_FLOAT_SOFT),
448 DECL(AL_DOUBLE_SOFT),
449 DECL(AL_BYTE3_SOFT),
450 DECL(AL_UNSIGNED_BYTE3_SOFT),
452 DECL(AL_FREQUENCY),
453 DECL(AL_BITS),
454 DECL(AL_CHANNELS),
455 DECL(AL_SIZE),
456 DECL(AL_INTERNAL_FORMAT_SOFT),
457 DECL(AL_BYTE_LENGTH_SOFT),
458 DECL(AL_SAMPLE_LENGTH_SOFT),
459 DECL(AL_SEC_LENGTH_SOFT),
461 DECL(AL_UNUSED),
462 DECL(AL_PENDING),
463 DECL(AL_PROCESSED),
465 DECL(AL_NO_ERROR),
466 DECL(AL_INVALID_NAME),
467 DECL(AL_INVALID_ENUM),
468 DECL(AL_INVALID_VALUE),
469 DECL(AL_INVALID_OPERATION),
470 DECL(AL_OUT_OF_MEMORY),
472 DECL(AL_VENDOR),
473 DECL(AL_VERSION),
474 DECL(AL_RENDERER),
475 DECL(AL_EXTENSIONS),
477 DECL(AL_DOPPLER_FACTOR),
478 DECL(AL_DOPPLER_VELOCITY),
479 DECL(AL_DISTANCE_MODEL),
480 DECL(AL_SPEED_OF_SOUND),
481 DECL(AL_SOURCE_DISTANCE_MODEL),
482 DECL(AL_DEFERRED_UPDATES_SOFT),
484 DECL(AL_INVERSE_DISTANCE),
485 DECL(AL_INVERSE_DISTANCE_CLAMPED),
486 DECL(AL_LINEAR_DISTANCE),
487 DECL(AL_LINEAR_DISTANCE_CLAMPED),
488 DECL(AL_EXPONENT_DISTANCE),
489 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
491 DECL(AL_FILTER_TYPE),
492 DECL(AL_FILTER_NULL),
493 DECL(AL_FILTER_LOWPASS),
494 #if 0
495 DECL(AL_FILTER_HIGHPASS),
496 DECL(AL_FILTER_BANDPASS),
497 #endif
499 DECL(AL_LOWPASS_GAIN),
500 DECL(AL_LOWPASS_GAINHF),
502 DECL(AL_EFFECT_TYPE),
503 DECL(AL_EFFECT_NULL),
504 DECL(AL_EFFECT_REVERB),
505 DECL(AL_EFFECT_EAXREVERB),
506 #if 0
507 DECL(AL_EFFECT_CHORUS),
508 DECL(AL_EFFECT_DISTORTION),
509 #endif
510 DECL(AL_EFFECT_ECHO),
511 #if 0
512 DECL(AL_EFFECT_FLANGER),
513 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
514 DECL(AL_EFFECT_VOCAL_MORPHER),
515 DECL(AL_EFFECT_PITCH_SHIFTER),
516 #endif
517 DECL(AL_EFFECT_RING_MODULATOR),
518 #if 0
519 DECL(AL_EFFECT_AUTOWAH),
520 DECL(AL_EFFECT_COMPRESSOR),
521 DECL(AL_EFFECT_EQUALIZER),
522 #endif
523 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
524 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
526 DECL(AL_EAXREVERB_DENSITY),
527 DECL(AL_EAXREVERB_DIFFUSION),
528 DECL(AL_EAXREVERB_GAIN),
529 DECL(AL_EAXREVERB_GAINHF),
530 DECL(AL_EAXREVERB_GAINLF),
531 DECL(AL_EAXREVERB_DECAY_TIME),
532 DECL(AL_EAXREVERB_DECAY_HFRATIO),
533 DECL(AL_EAXREVERB_DECAY_LFRATIO),
534 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
535 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
536 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
537 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
538 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
539 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
540 DECL(AL_EAXREVERB_ECHO_TIME),
541 DECL(AL_EAXREVERB_ECHO_DEPTH),
542 DECL(AL_EAXREVERB_MODULATION_TIME),
543 DECL(AL_EAXREVERB_MODULATION_DEPTH),
544 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
545 DECL(AL_EAXREVERB_HFREFERENCE),
546 DECL(AL_EAXREVERB_LFREFERENCE),
547 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
548 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
550 DECL(AL_REVERB_DENSITY),
551 DECL(AL_REVERB_DIFFUSION),
552 DECL(AL_REVERB_GAIN),
553 DECL(AL_REVERB_GAINHF),
554 DECL(AL_REVERB_DECAY_TIME),
555 DECL(AL_REVERB_DECAY_HFRATIO),
556 DECL(AL_REVERB_REFLECTIONS_GAIN),
557 DECL(AL_REVERB_REFLECTIONS_DELAY),
558 DECL(AL_REVERB_LATE_REVERB_GAIN),
559 DECL(AL_REVERB_LATE_REVERB_DELAY),
560 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
561 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
562 DECL(AL_REVERB_DECAY_HFLIMIT),
564 DECL(AL_ECHO_DELAY),
565 DECL(AL_ECHO_LRDELAY),
566 DECL(AL_ECHO_DAMPING),
567 DECL(AL_ECHO_FEEDBACK),
568 DECL(AL_ECHO_SPREAD),
570 DECL(AL_RING_MODULATOR_FREQUENCY),
571 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
572 DECL(AL_RING_MODULATOR_WAVEFORM),
574 DECL(AL_DEDICATED_GAIN),
576 { NULL, (ALCenum)0 }
578 #undef DECL
580 static const ALCchar alcNoError[] = "No Error";
581 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
582 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
583 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
584 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
585 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
588 /************************************************
589 * Global variables
590 ************************************************/
592 /* Enumerated device names */
593 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
594 static ALCchar *alcAllDevicesList;
595 static ALCchar *alcCaptureDeviceList;
596 /* Sizes only include the first ending null character, not the second */
597 static size_t alcAllDevicesListSize;
598 static size_t alcCaptureDeviceListSize;
600 /* Default is always the first in the list */
601 static ALCchar *alcDefaultAllDevicesSpecifier;
602 static ALCchar *alcCaptureDefaultDeviceSpecifier;
604 /* Default context extensions */
605 static const ALchar alExtList[] =
606 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
607 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
608 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
609 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
610 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
612 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
614 /* Thread-local current context */
615 static pthread_key_t LocalContext;
616 /* Process-wide current context */
617 static ALCcontext *volatile GlobalContext = NULL;
619 /* Mixing thread piority level */
620 ALint RTPrioLevel;
622 FILE *LogFile;
623 #ifdef _DEBUG
624 enum LogLevel LogLevel = LogWarning;
625 #else
626 enum LogLevel LogLevel = LogError;
627 #endif
629 /* Flag to trap ALC device errors */
630 static ALCboolean TrapALCError = ALC_FALSE;
632 /* One-time configuration init control */
633 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
635 /* Default effect that applies to sources that don't have an effect on send 0 */
636 static ALeffect DefaultEffect;
639 /************************************************
640 * ALC information
641 ************************************************/
642 static const ALCchar alcNoDeviceExtList[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
645 static const ALCchar alcExtensionList[] =
646 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
647 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
648 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
649 static const ALCint alcMajorVersion = 1;
650 static const ALCint alcMinorVersion = 1;
652 static const ALCint alcEFXMajorVersion = 1;
653 static const ALCint alcEFXMinorVersion = 0;
656 /************************************************
657 * Device lists
658 ************************************************/
659 static ALCdevice *volatile DeviceList = NULL;
661 static CRITICAL_SECTION ListLock;
663 static void LockLists(void)
665 EnterCriticalSection(&ListLock);
667 static void UnlockLists(void)
669 LeaveCriticalSection(&ListLock);
672 /************************************************
673 * Library initialization
674 ************************************************/
675 #if defined(_WIN32)
676 static void alc_init(void);
677 static void alc_deinit(void);
678 static void alc_deinit_safe(void);
680 UIntMap TlsDestructor;
682 #ifndef AL_LIBTYPE_STATIC
683 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
685 ALsizei i;
687 // Perform actions based on the reason for calling.
688 switch(ul_reason_for_call)
690 case DLL_PROCESS_ATTACH:
691 /* Pin the DLL so we won't get unloaded until the process terminates */
692 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
693 (WCHAR*)hModule, &hModule);
694 InitUIntMap(&TlsDestructor, ~0);
695 alc_init();
696 break;
698 case DLL_THREAD_DETACH:
699 LockUIntMapRead(&TlsDestructor);
700 for(i = 0;i < TlsDestructor.size;i++)
702 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
703 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
704 if(ptr && callback)
705 callback(ptr);
707 UnlockUIntMapRead(&TlsDestructor);
708 break;
710 case DLL_PROCESS_DETACH:
711 if(!lpReserved)
712 alc_deinit();
713 else
714 alc_deinit_safe();
715 ResetUIntMap(&TlsDestructor);
716 break;
718 return TRUE;
720 #elif defined(_MSC_VER)
721 #pragma section(".CRT$XCU",read)
722 static void alc_constructor(void);
723 static void alc_destructor(void);
724 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
726 static void alc_constructor(void)
728 atexit(alc_destructor);
729 alc_init();
732 static void alc_destructor(void)
734 alc_deinit();
736 #elif defined(HAVE_GCC_DESTRUCTOR)
737 static void alc_init(void) __attribute__((constructor));
738 static void alc_deinit(void) __attribute__((destructor));
739 #else
740 #error "No static initialization available on this platform!"
741 #endif
743 #elif defined(HAVE_GCC_DESTRUCTOR)
745 static void alc_init(void) __attribute__((constructor));
746 static void alc_deinit(void) __attribute__((destructor));
748 #else
749 #error "No global initialization available on this platform!"
750 #endif
752 static void ReleaseThreadCtx(void *ptr);
753 static void alc_init(void)
755 const char *str;
757 LogFile = stderr;
759 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
760 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
761 ConeScale *= 0.5f;
763 str = getenv("__ALSOFT_REVERSE_Z");
764 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
765 ZScale *= -1.0f;
767 pthread_key_create(&LocalContext, ReleaseThreadCtx);
768 InitializeCriticalSection(&ListLock);
769 ThunkInit();
772 static void alc_initconfig(void)
774 const char *devs, *str;
775 ALuint capfilter;
776 float valf;
777 int i, n;
779 str = getenv("ALSOFT_LOGLEVEL");
780 if(str)
782 long lvl = strtol(str, NULL, 0);
783 if(lvl >= NoLog && lvl <= LogRef)
784 LogLevel = lvl;
787 str = getenv("ALSOFT_LOGFILE");
788 if(str && str[0])
790 FILE *logfile = fopen(str, "wat");
791 if(logfile) LogFile = logfile;
792 else ERR("Failed to open log file '%s'\n", str);
795 ReadALConfig();
797 capfilter = 0;
798 #ifdef HAVE_SSE
799 capfilter |= CPU_CAP_SSE;
800 #endif
801 #ifdef HAVE_NEON
802 capfilter |= CPU_CAP_NEON;
803 #endif
804 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
806 if(strcasecmp(str, "all") == 0)
807 capfilter = 0;
808 else
810 size_t len;
811 const char *next = str;
813 i = 0;
814 do {
815 str = next;
816 next = strchr(str, ',');
818 while(isspace(str[0]))
819 str++;
820 if(!str[0] || str[0] == ',')
821 continue;
823 len = (next ? ((size_t)(next-str)) : strlen(str));
824 if(strncasecmp(str, "sse", len) == 0)
825 capfilter &= ~CPU_CAP_SSE;
826 else if(strncasecmp(str, "neon", len) == 0)
827 capfilter &= ~CPU_CAP_NEON;
828 else
829 WARN("Invalid CPU extension \"%s\"\n", str);
830 } while(next++);
833 FillCPUCaps(capfilter);
835 InitHrtf();
837 #ifdef _WIN32
838 RTPrioLevel = 1;
839 #else
840 RTPrioLevel = 0;
841 #endif
842 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
844 if(ConfigValueStr(NULL, "resampler", &str))
846 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
847 DefaultResampler = PointResampler;
848 else if(strcasecmp(str, "linear") == 0)
849 DefaultResampler = LinearResampler;
850 else if(strcasecmp(str, "cubic") == 0)
851 DefaultResampler = CubicResampler;
852 else
854 char *end;
856 n = strtol(str, &end, 0);
857 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
858 DefaultResampler = n;
859 else
860 WARN("Invalid resampler: %s\n", str);
864 str = getenv("ALSOFT_TRAP_ERROR");
865 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
867 TrapALError = AL_TRUE;
868 TrapALCError = AL_TRUE;
870 else
872 str = getenv("ALSOFT_TRAP_AL_ERROR");
873 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
874 TrapALError = AL_TRUE;
875 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
877 str = getenv("ALSOFT_TRAP_ALC_ERROR");
878 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
879 TrapALCError = ALC_TRUE;
880 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
883 if(ConfigValueFloat("reverb", "boost", &valf))
884 ReverbBoost *= powf(10.0f, valf / 20.0f);
886 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
888 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
889 ConfigValueStr(NULL, "drivers", &devs))
891 int n;
892 size_t len;
893 const char *next = devs;
894 int endlist, delitem;
896 i = 0;
897 do {
898 devs = next;
899 next = strchr(devs, ',');
901 delitem = (devs[0] == '-');
902 if(devs[0] == '-') devs++;
904 if(!devs[0] || devs[0] == ',')
906 endlist = 0;
907 continue;
909 endlist = 1;
911 len = (next ? ((size_t)(next-devs)) : strlen(devs));
912 for(n = i;BackendList[n].Init;n++)
914 if(len == strlen(BackendList[n].name) &&
915 strncmp(BackendList[n].name, devs, len) == 0)
917 if(delitem)
919 do {
920 BackendList[n] = BackendList[n+1];
921 ++n;
922 } while(BackendList[n].Init);
924 else
926 struct BackendInfo Bkp = BackendList[n];
927 while(n > i)
929 BackendList[n] = BackendList[n-1];
930 --n;
932 BackendList[n] = Bkp;
934 i++;
936 break;
939 } while(next++);
941 if(endlist)
943 BackendList[i].name = NULL;
944 BackendList[i].Init = NULL;
945 BackendList[i].Deinit = NULL;
946 BackendList[i].Probe = NULL;
950 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
952 if(!BackendList[i].Init(&BackendList[i].Funcs))
954 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
955 continue;
958 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
959 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
961 PlaybackBackend = BackendList[i];
962 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
964 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
966 CaptureBackend = BackendList[i];
967 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
970 BackendLoopback.Init(&BackendLoopback.Funcs);
972 if(ConfigValueStr(NULL, "excludefx", &str))
974 size_t len;
975 const char *next = str;
977 do {
978 str = next;
979 next = strchr(str, ',');
981 if(!str[0] || next == str)
982 continue;
984 len = (next ? ((size_t)(next-str)) : strlen(str));
985 for(n = 0;EffectList[n].name;n++)
987 if(len == strlen(EffectList[n].name) &&
988 strncmp(EffectList[n].name, str, len) == 0)
989 DisabledEffects[EffectList[n].type] = AL_TRUE;
991 } while(next++);
994 InitEffect(&DefaultEffect);
995 str = getenv("ALSOFT_DEFAULT_REVERB");
996 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
997 LoadReverbPreset(str, &DefaultEffect);
999 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1002 /************************************************
1003 * Library deinitialization
1004 ************************************************/
1005 static void alc_cleanup(void)
1007 ALCdevice *dev;
1009 free(alcAllDevicesList); alcAllDevicesList = NULL;
1010 alcAllDevicesListSize = 0;
1011 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1012 alcCaptureDeviceListSize = 0;
1014 free(alcDefaultAllDevicesSpecifier);
1015 alcDefaultAllDevicesSpecifier = NULL;
1016 free(alcCaptureDefaultDeviceSpecifier);
1017 alcCaptureDefaultDeviceSpecifier = NULL;
1019 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1021 ALCuint num = 0;
1022 do {
1023 num++;
1024 } while((dev=dev->next) != NULL);
1025 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1029 static void alc_deinit_safe(void)
1031 alc_cleanup();
1033 FreeHrtf();
1034 FreeALConfig();
1036 ThunkExit();
1037 DeleteCriticalSection(&ListLock);
1038 pthread_key_delete(LocalContext);
1040 if(LogFile != stderr)
1041 fclose(LogFile);
1042 LogFile = NULL;
1045 static void alc_deinit(void)
1047 int i;
1049 alc_cleanup();
1051 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1052 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1054 for(i = 0;BackendList[i].Deinit;i++)
1055 BackendList[i].Deinit();
1056 BackendLoopback.Deinit();
1058 alc_deinit_safe();
1062 /************************************************
1063 * Device enumeration
1064 ************************************************/
1065 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1067 DO_INITCONFIG();
1069 LockLists();
1070 free(*list);
1071 *list = NULL;
1072 *listsize = 0;
1074 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1075 PlaybackBackend.Probe(type);
1076 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1077 CaptureBackend.Probe(type);
1078 UnlockLists();
1081 static void ProbeAllDevicesList(void)
1082 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1083 static void ProbeCaptureDeviceList(void)
1084 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1087 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1089 size_t len = strlen(name);
1090 void *temp;
1092 if(len == 0)
1093 return;
1095 temp = realloc(*List, (*ListSize) + len + 2);
1096 if(!temp)
1098 ERR("Realloc failed to add %s!\n", name);
1099 return;
1101 *List = temp;
1103 memcpy((*List)+(*ListSize), name, len+1);
1104 *ListSize += len+1;
1105 (*List)[*ListSize] = 0;
1108 #define DECL_APPEND_LIST_FUNC(type) \
1109 void Append##type##List(const ALCchar *name) \
1110 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1112 DECL_APPEND_LIST_FUNC(AllDevices)
1113 DECL_APPEND_LIST_FUNC(CaptureDevice)
1115 #undef DECL_APPEND_LIST_FUNC
1118 /************************************************
1119 * Device format information
1120 ************************************************/
1121 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1123 switch(type)
1125 case DevFmtByte: return "Signed Byte";
1126 case DevFmtUByte: return "Unsigned Byte";
1127 case DevFmtShort: return "Signed Short";
1128 case DevFmtUShort: return "Unsigned Short";
1129 case DevFmtInt: return "Signed Int";
1130 case DevFmtUInt: return "Unsigned Int";
1131 case DevFmtFloat: return "Float";
1133 return "(unknown type)";
1135 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1137 switch(chans)
1139 case DevFmtMono: return "Mono";
1140 case DevFmtStereo: return "Stereo";
1141 case DevFmtQuad: return "Quadraphonic";
1142 case DevFmtX51: return "5.1 Surround";
1143 case DevFmtX51Side: return "5.1 Side";
1144 case DevFmtX61: return "6.1 Surround";
1145 case DevFmtX71: return "7.1 Surround";
1147 return "(unknown channels)";
1150 ALuint BytesFromDevFmt(enum DevFmtType type)
1152 switch(type)
1154 case DevFmtByte: return sizeof(ALbyte);
1155 case DevFmtUByte: return sizeof(ALubyte);
1156 case DevFmtShort: return sizeof(ALshort);
1157 case DevFmtUShort: return sizeof(ALushort);
1158 case DevFmtInt: return sizeof(ALint);
1159 case DevFmtUInt: return sizeof(ALuint);
1160 case DevFmtFloat: return sizeof(ALfloat);
1162 return 0;
1164 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1166 switch(chans)
1168 case DevFmtMono: return 1;
1169 case DevFmtStereo: return 2;
1170 case DevFmtQuad: return 4;
1171 case DevFmtX51: return 6;
1172 case DevFmtX51Side: return 6;
1173 case DevFmtX61: return 7;
1174 case DevFmtX71: return 8;
1176 return 0;
1179 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1180 enum DevFmtType *type)
1182 static const struct {
1183 ALenum format;
1184 enum DevFmtChannels channels;
1185 enum DevFmtType type;
1186 } list[] = {
1187 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1188 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1189 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1191 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1192 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1193 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1195 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1196 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1197 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1199 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1200 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1201 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1203 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1204 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1205 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1207 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1208 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1209 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1211 ALuint i;
1213 for(i = 0;i < COUNTOF(list);i++)
1215 if(list[i].format == format)
1217 *chans = list[i].channels;
1218 *type = list[i].type;
1219 return AL_TRUE;
1223 return AL_FALSE;
1226 static ALCboolean IsValidALCType(ALCenum type)
1228 switch(type)
1230 case ALC_BYTE_SOFT:
1231 case ALC_UNSIGNED_BYTE_SOFT:
1232 case ALC_SHORT_SOFT:
1233 case ALC_UNSIGNED_SHORT_SOFT:
1234 case ALC_INT_SOFT:
1235 case ALC_UNSIGNED_INT_SOFT:
1236 case ALC_FLOAT_SOFT:
1237 return ALC_TRUE;
1239 return ALC_FALSE;
1242 static ALCboolean IsValidALCChannels(ALCenum channels)
1244 switch(channels)
1246 case ALC_MONO_SOFT:
1247 case ALC_STEREO_SOFT:
1248 case ALC_QUAD_SOFT:
1249 case ALC_5POINT1_SOFT:
1250 case ALC_6POINT1_SOFT:
1251 case ALC_7POINT1_SOFT:
1252 return ALC_TRUE;
1254 return ALC_FALSE;
1258 /************************************************
1259 * Miscellaneous ALC helpers
1260 ************************************************/
1262 /* SetDefaultWFXChannelOrder
1264 * Sets the default channel order used by WaveFormatEx.
1266 void SetDefaultWFXChannelOrder(ALCdevice *device)
1268 switch(device->FmtChans)
1270 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1272 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1273 device->DevChannels[1] = FrontRight; break;
1275 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1276 device->DevChannels[1] = FrontRight;
1277 device->DevChannels[2] = BackLeft;
1278 device->DevChannels[3] = BackRight; break;
1280 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1281 device->DevChannels[1] = FrontRight;
1282 device->DevChannels[2] = FrontCenter;
1283 device->DevChannels[3] = LFE;
1284 device->DevChannels[4] = BackLeft;
1285 device->DevChannels[5] = BackRight; break;
1287 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1288 device->DevChannels[1] = FrontRight;
1289 device->DevChannels[2] = FrontCenter;
1290 device->DevChannels[3] = LFE;
1291 device->DevChannels[4] = SideLeft;
1292 device->DevChannels[5] = SideRight; break;
1294 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1295 device->DevChannels[1] = FrontRight;
1296 device->DevChannels[2] = FrontCenter;
1297 device->DevChannels[3] = LFE;
1298 device->DevChannels[4] = BackCenter;
1299 device->DevChannels[5] = SideLeft;
1300 device->DevChannels[6] = SideRight; break;
1302 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1303 device->DevChannels[1] = FrontRight;
1304 device->DevChannels[2] = FrontCenter;
1305 device->DevChannels[3] = LFE;
1306 device->DevChannels[4] = BackLeft;
1307 device->DevChannels[5] = BackRight;
1308 device->DevChannels[6] = SideLeft;
1309 device->DevChannels[7] = SideRight; break;
1313 /* SetDefaultChannelOrder
1315 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1317 void SetDefaultChannelOrder(ALCdevice *device)
1319 switch(device->FmtChans)
1321 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1322 device->DevChannels[1] = FrontRight;
1323 device->DevChannels[2] = BackLeft;
1324 device->DevChannels[3] = BackRight;
1325 device->DevChannels[4] = FrontCenter;
1326 device->DevChannels[5] = LFE;
1327 return;
1329 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1330 device->DevChannels[1] = FrontRight;
1331 device->DevChannels[2] = BackLeft;
1332 device->DevChannels[3] = BackRight;
1333 device->DevChannels[4] = FrontCenter;
1334 device->DevChannels[5] = LFE;
1335 device->DevChannels[6] = SideLeft;
1336 device->DevChannels[7] = SideRight;
1337 return;
1339 /* Same as WFX order */
1340 case DevFmtMono:
1341 case DevFmtStereo:
1342 case DevFmtQuad:
1343 case DevFmtX51Side:
1344 case DevFmtX61:
1345 break;
1347 SetDefaultWFXChannelOrder(device);
1351 /* alcSetError
1353 * Stores the latest ALC device error
1355 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1357 if(TrapALCError)
1359 #ifdef _WIN32
1360 /* DebugBreak() will cause an exception if there is no debugger */
1361 if(IsDebuggerPresent())
1362 DebugBreak();
1363 #elif defined(SIGTRAP)
1364 raise(SIGTRAP);
1365 #endif
1368 if(device)
1369 device->LastError = errorCode;
1370 else
1371 LastNullDeviceError = errorCode;
1375 /* UpdateDeviceParams
1377 * Updates device parameters according to the attribute list (caller is
1378 * responsible for holding the list lock).
1380 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1382 ALCcontext *context;
1383 enum DevFmtChannels oldChans;
1384 enum DevFmtType oldType;
1385 ALCuint oldFreq;
1386 int oldMode;
1387 ALuint i;
1389 // Check for attributes
1390 if(device->Type == Loopback)
1392 enum {
1393 GotFreq = 1<<0,
1394 GotChans = 1<<1,
1395 GotType = 1<<2,
1396 GotAll = GotFreq|GotChans|GotType
1398 ALCuint freq, numMono, numStereo, numSends;
1399 enum DevFmtChannels schans;
1400 enum DevFmtType stype;
1401 ALCuint attrIdx = 0;
1402 ALCint gotFmt = 0;
1404 if(!attrList)
1406 WARN("Missing attributes for loopback device\n");
1407 return ALC_INVALID_VALUE;
1410 numMono = device->NumMonoSources;
1411 numStereo = device->NumStereoSources;
1412 numSends = device->NumAuxSends;
1413 schans = device->FmtChans;
1414 stype = device->FmtType;
1415 freq = device->Frequency;
1417 while(attrList[attrIdx])
1419 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1421 ALCint val = attrList[attrIdx + 1];
1422 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1423 return ALC_INVALID_VALUE;
1424 schans = val;
1425 gotFmt |= GotChans;
1428 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1430 ALCint val = attrList[attrIdx + 1];
1431 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1432 return ALC_INVALID_VALUE;
1433 stype = val;
1434 gotFmt |= GotType;
1437 if(attrList[attrIdx] == ALC_FREQUENCY)
1439 freq = attrList[attrIdx + 1];
1440 if(freq < MIN_OUTPUT_RATE)
1441 return ALC_INVALID_VALUE;
1442 gotFmt |= GotFreq;
1445 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1447 numStereo = attrList[attrIdx + 1];
1448 if(numStereo > device->MaxNoOfSources)
1449 numStereo = device->MaxNoOfSources;
1451 numMono = device->MaxNoOfSources - numStereo;
1454 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1455 numSends = attrList[attrIdx + 1];
1457 attrIdx += 2;
1460 if(gotFmt != GotAll)
1462 WARN("Missing format for loopback device\n");
1463 return ALC_INVALID_VALUE;
1466 ConfigValueUInt(NULL, "sends", &numSends);
1467 numSends = minu(MAX_SENDS, numSends);
1469 if((device->Flags&DEVICE_RUNNING))
1470 ALCdevice_StopPlayback(device);
1471 device->Flags &= ~DEVICE_RUNNING;
1473 device->Frequency = freq;
1474 device->FmtChans = schans;
1475 device->FmtType = stype;
1476 device->NumMonoSources = numMono;
1477 device->NumStereoSources = numStereo;
1478 device->NumAuxSends = numSends;
1480 else if(attrList && attrList[0])
1482 ALCuint freq, numMono, numStereo, numSends;
1483 ALCuint attrIdx = 0;
1485 /* If a context is already running on the device, stop playback so the
1486 * device attributes can be updated. */
1487 if((device->Flags&DEVICE_RUNNING))
1488 ALCdevice_StopPlayback(device);
1489 device->Flags &= ~DEVICE_RUNNING;
1491 freq = device->Frequency;
1492 numMono = device->NumMonoSources;
1493 numStereo = device->NumStereoSources;
1494 numSends = device->NumAuxSends;
1496 while(attrList[attrIdx])
1498 if(attrList[attrIdx] == ALC_FREQUENCY)
1500 freq = attrList[attrIdx + 1];
1501 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1504 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1506 numStereo = attrList[attrIdx + 1];
1507 if(numStereo > device->MaxNoOfSources)
1508 numStereo = device->MaxNoOfSources;
1510 numMono = device->MaxNoOfSources - numStereo;
1513 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1514 numSends = attrList[attrIdx + 1];
1516 attrIdx += 2;
1519 ConfigValueUInt(NULL, "frequency", &freq);
1520 freq = maxu(freq, MIN_OUTPUT_RATE);
1522 ConfigValueUInt(NULL, "sends", &numSends);
1523 numSends = minu(MAX_SENDS, numSends);
1525 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1526 device->Frequency;
1528 device->Frequency = freq;
1529 device->NumMonoSources = numMono;
1530 device->NumStereoSources = numStereo;
1531 device->NumAuxSends = numSends;
1534 if((device->Flags&DEVICE_RUNNING))
1535 return ALC_NO_ERROR;
1537 oldFreq = device->Frequency;
1538 oldChans = device->FmtChans;
1539 oldType = device->FmtType;
1541 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1542 DevFmtChannelsString(device->FmtChans),
1543 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1544 DevFmtTypeString(device->FmtType),
1545 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1546 device->Frequency,
1547 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1548 device->UpdateSize, device->NumUpdates);
1550 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1551 return ALC_INVALID_DEVICE;
1553 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1555 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1556 DevFmtChannelsString(device->FmtChans));
1557 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1559 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1561 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1562 DevFmtTypeString(device->FmtType));
1563 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1565 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1567 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1568 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1571 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1572 DevFmtChannelsString(device->FmtChans),
1573 DevFmtTypeString(device->FmtType), device->Frequency,
1574 device->UpdateSize, device->NumUpdates);
1576 aluInitPanning(device);
1578 for(i = 0;i < MaxChannels;i++)
1580 device->ClickRemoval[i] = 0.0f;
1581 device->PendingClicks[i] = 0.0f;
1584 device->Hrtf = NULL;
1585 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1586 device->Hrtf = GetHrtf(device);
1587 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1589 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1591 if(!device->Bs2b)
1593 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1594 bs2b_clear(device->Bs2b);
1596 bs2b_set_srate(device->Bs2b, device->Frequency);
1597 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1598 TRACE("BS2B level %d\n", device->Bs2bLevel);
1600 else
1602 free(device->Bs2b);
1603 device->Bs2b = NULL;
1604 TRACE("BS2B disabled\n");
1607 device->Flags &= ~DEVICE_WIDE_STEREO;
1608 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1609 device->Flags |= DEVICE_WIDE_STEREO;
1611 oldMode = SetMixerFPUMode();
1612 LockDevice(device);
1613 context = device->ContextList;
1614 while(context)
1616 ALsizei pos;
1618 context->UpdateSources = AL_FALSE;
1619 LockUIntMapRead(&context->EffectSlotMap);
1620 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1622 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1624 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1626 UnlockUIntMapRead(&context->EffectSlotMap);
1627 UnlockDevice(device);
1628 RestoreFPUMode(oldMode);
1629 return ALC_INVALID_DEVICE;
1631 slot->NeedsUpdate = AL_FALSE;
1632 ALeffectState_Update(slot->EffectState, device, slot);
1634 UnlockUIntMapRead(&context->EffectSlotMap);
1636 LockUIntMapRead(&context->SourceMap);
1637 for(pos = 0;pos < context->SourceMap.size;pos++)
1639 ALsource *source = context->SourceMap.array[pos].value;
1640 ALuint s = device->NumAuxSends;
1641 while(s < MAX_SENDS)
1643 if(source->Send[s].Slot)
1644 DecrementRef(&source->Send[s].Slot->ref);
1645 source->Send[s].Slot = NULL;
1646 source->Send[s].Gain = 1.0f;
1647 source->Send[s].GainHF = 1.0f;
1648 s++;
1650 source->NeedsUpdate = AL_FALSE;
1651 ALsource_Update(source, context);
1653 UnlockUIntMapRead(&context->SourceMap);
1655 context = context->next;
1657 if(device->DefaultSlot)
1659 ALeffectslot *slot = device->DefaultSlot;
1661 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1663 UnlockDevice(device);
1664 RestoreFPUMode(oldMode);
1665 return ALC_INVALID_DEVICE;
1667 slot->NeedsUpdate = AL_FALSE;
1668 ALeffectState_Update(slot->EffectState, device, slot);
1670 UnlockDevice(device);
1671 RestoreFPUMode(oldMode);
1673 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1674 return ALC_INVALID_DEVICE;
1675 device->Flags |= DEVICE_RUNNING;
1677 return ALC_NO_ERROR;
1680 /* FreeDevice
1682 * Frees the device structure, and destroys any objects the app failed to
1683 * delete. Called once there's no more references on the device.
1685 static ALCvoid FreeDevice(ALCdevice *device)
1687 TRACE("%p\n", device);
1689 if(device->Type != Capture)
1690 ALCdevice_ClosePlayback(device);
1691 else
1692 ALCdevice_CloseCapture(device);
1694 if(device->DefaultSlot)
1696 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1697 device->DefaultSlot->EffectState = NULL;
1700 if(device->BufferMap.size > 0)
1702 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1703 ReleaseALBuffers(device);
1705 ResetUIntMap(&device->BufferMap);
1707 if(device->EffectMap.size > 0)
1709 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1710 ReleaseALEffects(device);
1712 ResetUIntMap(&device->EffectMap);
1714 if(device->FilterMap.size > 0)
1716 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1717 ReleaseALFilters(device);
1719 ResetUIntMap(&device->FilterMap);
1721 free(device->Bs2b);
1722 device->Bs2b = NULL;
1724 free(device->DeviceName);
1725 device->DeviceName = NULL;
1727 DeleteCriticalSection(&device->Mutex);
1729 free(device);
1733 void ALCdevice_IncRef(ALCdevice *device)
1735 RefCount ref;
1736 ref = IncrementRef(&device->ref);
1737 TRACEREF("%p increasing refcount to %u\n", device, ref);
1740 void ALCdevice_DecRef(ALCdevice *device)
1742 RefCount ref;
1743 ref = DecrementRef(&device->ref);
1744 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1745 if(ref == 0) FreeDevice(device);
1748 /* VerifyDevice
1750 * Checks if the device handle is valid, and increments its ref count if so.
1752 static ALCdevice *VerifyDevice(ALCdevice *device)
1754 ALCdevice *tmpDevice;
1756 if(!device)
1757 return NULL;
1759 LockLists();
1760 tmpDevice = DeviceList;
1761 while(tmpDevice && tmpDevice != device)
1762 tmpDevice = tmpDevice->next;
1764 if(tmpDevice)
1765 ALCdevice_IncRef(tmpDevice);
1766 UnlockLists();
1767 return tmpDevice;
1771 /* InitContext
1773 * Initializes context fields
1775 static ALvoid InitContext(ALCcontext *Context)
1777 ALint i, j;
1779 //Initialise listener
1780 Context->Listener.Gain = 1.0f;
1781 Context->Listener.MetersPerUnit = 1.0f;
1782 Context->Listener.Position[0] = 0.0f;
1783 Context->Listener.Position[1] = 0.0f;
1784 Context->Listener.Position[2] = 0.0f;
1785 Context->Listener.Velocity[0] = 0.0f;
1786 Context->Listener.Velocity[1] = 0.0f;
1787 Context->Listener.Velocity[2] = 0.0f;
1788 Context->Listener.Forward[0] = 0.0f;
1789 Context->Listener.Forward[1] = 0.0f;
1790 Context->Listener.Forward[2] = -1.0f;
1791 Context->Listener.Up[0] = 0.0f;
1792 Context->Listener.Up[1] = 1.0f;
1793 Context->Listener.Up[2] = 0.0f;
1794 for(i = 0;i < 4;i++)
1796 for(j = 0;j < 4;j++)
1797 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1800 //Validate Context
1801 Context->LastError = AL_NO_ERROR;
1802 Context->UpdateSources = AL_FALSE;
1803 Context->ActiveSourceCount = 0;
1804 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1805 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1807 //Set globals
1808 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1809 Context->SourceDistanceModel = AL_FALSE;
1810 Context->DopplerFactor = 1.0f;
1811 Context->DopplerVelocity = 1.0f;
1812 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1813 Context->DeferUpdates = AL_FALSE;
1815 Context->ExtensionList = alExtList;
1819 /* FreeContext
1821 * Cleans up the context, and destroys any remaining objects the app failed to
1822 * delete. Called once there's no more references on the context.
1824 static ALCvoid FreeContext(ALCcontext *context)
1826 TRACE("%p\n", context);
1828 if(context->SourceMap.size > 0)
1830 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1831 ReleaseALSources(context);
1833 ResetUIntMap(&context->SourceMap);
1835 if(context->EffectSlotMap.size > 0)
1837 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1838 ReleaseALAuxiliaryEffectSlots(context);
1840 ResetUIntMap(&context->EffectSlotMap);
1842 context->ActiveSourceCount = 0;
1843 free(context->ActiveSources);
1844 context->ActiveSources = NULL;
1845 context->MaxActiveSources = 0;
1847 context->ActiveEffectSlotCount = 0;
1848 free(context->ActiveEffectSlots);
1849 context->ActiveEffectSlots = NULL;
1850 context->MaxActiveEffectSlots = 0;
1852 ALCdevice_DecRef(context->Device);
1853 context->Device = NULL;
1855 //Invalidate context
1856 memset(context, 0, sizeof(ALCcontext));
1857 free(context);
1860 /* ReleaseContext
1862 * Removes the context reference from the given device and removes it from
1863 * being current on the running thread or globally.
1865 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1867 ALCcontext *volatile*tmp_ctx;
1869 if(pthread_getspecific(LocalContext) == context)
1871 WARN("%p released while current on thread\n", context);
1872 pthread_setspecific(LocalContext, NULL);
1873 ALCcontext_DecRef(context);
1876 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1877 ALCcontext_DecRef(context);
1879 LockDevice(device);
1880 tmp_ctx = &device->ContextList;
1881 while(*tmp_ctx)
1883 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1884 break;
1885 tmp_ctx = &(*tmp_ctx)->next;
1887 UnlockDevice(device);
1889 ALCcontext_DecRef(context);
1892 void ALCcontext_IncRef(ALCcontext *context)
1894 RefCount ref;
1895 ref = IncrementRef(&context->ref);
1896 TRACEREF("%p increasing refcount to %u\n", context, ref);
1899 void ALCcontext_DecRef(ALCcontext *context)
1901 RefCount ref;
1902 ref = DecrementRef(&context->ref);
1903 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1904 if(ref == 0) FreeContext(context);
1907 static void ReleaseThreadCtx(void *ptr)
1909 WARN("%p current for thread being destroyed\n", ptr);
1910 ALCcontext_DecRef(ptr);
1913 /* VerifyContext
1915 * Checks that the given context is valid, and increments its reference count.
1917 static ALCcontext *VerifyContext(ALCcontext *context)
1919 ALCdevice *dev;
1921 LockLists();
1922 dev = DeviceList;
1923 while(dev)
1925 ALCcontext *tmp_ctx = dev->ContextList;
1926 while(tmp_ctx)
1928 if(tmp_ctx == context)
1930 ALCcontext_IncRef(tmp_ctx);
1931 UnlockLists();
1932 return tmp_ctx;
1934 tmp_ctx = tmp_ctx->next;
1936 dev = dev->next;
1938 UnlockLists();
1940 return NULL;
1944 /* GetContextRef
1946 * Returns the currently active context for this thread, and adds a reference
1947 * without locking it.
1949 ALCcontext *GetContextRef(void)
1951 ALCcontext *context;
1953 context = pthread_getspecific(LocalContext);
1954 if(context)
1955 ALCcontext_IncRef(context);
1956 else
1958 LockLists();
1959 context = GlobalContext;
1960 if(context)
1961 ALCcontext_IncRef(context);
1962 UnlockLists();
1965 return context;
1969 /************************************************
1970 * Standard ALC functions
1971 ************************************************/
1973 /* alcGetError
1975 * Return last ALC generated error code for the given device
1977 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1979 ALCenum errorCode;
1981 if(VerifyDevice(device))
1983 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1984 ALCdevice_DecRef(device);
1986 else
1987 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
1989 return errorCode;
1993 /* alcSuspendContext
1995 * Not functional
1997 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
1999 (void)Context;
2002 /* alcProcessContext
2004 * Not functional
2006 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2008 (void)Context;
2012 /* alcGetString
2014 * Returns information about the device, and error strings
2016 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2018 const ALCchar *value = NULL;
2020 switch(param)
2022 case ALC_NO_ERROR:
2023 value = alcNoError;
2024 break;
2026 case ALC_INVALID_ENUM:
2027 value = alcErrInvalidEnum;
2028 break;
2030 case ALC_INVALID_VALUE:
2031 value = alcErrInvalidValue;
2032 break;
2034 case ALC_INVALID_DEVICE:
2035 value = alcErrInvalidDevice;
2036 break;
2038 case ALC_INVALID_CONTEXT:
2039 value = alcErrInvalidContext;
2040 break;
2042 case ALC_OUT_OF_MEMORY:
2043 value = alcErrOutOfMemory;
2044 break;
2046 case ALC_DEVICE_SPECIFIER:
2047 value = alcDefaultName;
2048 break;
2050 case ALC_ALL_DEVICES_SPECIFIER:
2051 if(VerifyDevice(Device))
2053 value = Device->DeviceName;
2054 ALCdevice_DecRef(Device);
2056 else
2058 ProbeAllDevicesList();
2059 value = alcAllDevicesList;
2061 break;
2063 case ALC_CAPTURE_DEVICE_SPECIFIER:
2064 if(VerifyDevice(Device))
2066 value = Device->DeviceName;
2067 ALCdevice_DecRef(Device);
2069 else
2071 ProbeCaptureDeviceList();
2072 value = alcCaptureDeviceList;
2074 break;
2076 /* Default devices are always first in the list */
2077 case ALC_DEFAULT_DEVICE_SPECIFIER:
2078 value = alcDefaultName;
2079 break;
2081 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2082 if(!alcAllDevicesList)
2083 ProbeAllDevicesList();
2085 Device = VerifyDevice(Device);
2087 free(alcDefaultAllDevicesSpecifier);
2088 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2089 alcAllDevicesList : "");
2090 if(!alcDefaultAllDevicesSpecifier)
2091 alcSetError(Device, ALC_OUT_OF_MEMORY);
2093 value = alcDefaultAllDevicesSpecifier;
2094 if(Device) ALCdevice_DecRef(Device);
2095 break;
2097 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2098 if(!alcCaptureDeviceList)
2099 ProbeCaptureDeviceList();
2101 Device = VerifyDevice(Device);
2103 free(alcCaptureDefaultDeviceSpecifier);
2104 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2105 alcCaptureDeviceList : "");
2106 if(!alcCaptureDefaultDeviceSpecifier)
2107 alcSetError(Device, ALC_OUT_OF_MEMORY);
2109 value = alcCaptureDefaultDeviceSpecifier;
2110 if(Device) ALCdevice_DecRef(Device);
2111 break;
2113 case ALC_EXTENSIONS:
2114 if(!VerifyDevice(Device))
2115 value = alcNoDeviceExtList;
2116 else
2118 value = alcExtensionList;
2119 ALCdevice_DecRef(Device);
2121 break;
2123 default:
2124 Device = VerifyDevice(Device);
2125 alcSetError(Device, ALC_INVALID_ENUM);
2126 if(Device) ALCdevice_DecRef(Device);
2127 break;
2130 return value;
2134 /* alcGetIntegerv
2136 * Returns information about the device and the version of OpenAL
2138 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2140 device = VerifyDevice(device);
2142 if(size == 0 || data == NULL)
2144 alcSetError(device, ALC_INVALID_VALUE);
2145 if(device) ALCdevice_DecRef(device);
2146 return;
2149 if(!device)
2151 switch(param)
2153 case ALC_MAJOR_VERSION:
2154 *data = alcMajorVersion;
2155 break;
2156 case ALC_MINOR_VERSION:
2157 *data = alcMinorVersion;
2158 break;
2160 case ALC_ATTRIBUTES_SIZE:
2161 case ALC_ALL_ATTRIBUTES:
2162 case ALC_FREQUENCY:
2163 case ALC_REFRESH:
2164 case ALC_SYNC:
2165 case ALC_MONO_SOURCES:
2166 case ALC_STEREO_SOURCES:
2167 case ALC_CAPTURE_SAMPLES:
2168 case ALC_FORMAT_CHANNELS_SOFT:
2169 case ALC_FORMAT_TYPE_SOFT:
2170 alcSetError(NULL, ALC_INVALID_DEVICE);
2171 break;
2173 default:
2174 alcSetError(NULL, ALC_INVALID_ENUM);
2175 break;
2178 else if(device->Type == Capture)
2180 switch(param)
2182 case ALC_CAPTURE_SAMPLES:
2183 LockLists();
2184 /* Re-validate the device since it may have been closed */
2185 ALCdevice_DecRef(device);
2186 if((device=VerifyDevice(device)) != NULL)
2187 *data = ALCdevice_AvailableSamples(device);
2188 else
2189 alcSetError(NULL, ALC_INVALID_DEVICE);
2190 UnlockLists();
2191 break;
2193 case ALC_CONNECTED:
2194 *data = device->Connected;
2195 break;
2197 default:
2198 alcSetError(device, ALC_INVALID_ENUM);
2199 break;
2202 else /* render device */
2204 switch(param)
2206 case ALC_MAJOR_VERSION:
2207 *data = alcMajorVersion;
2208 break;
2210 case ALC_MINOR_VERSION:
2211 *data = alcMinorVersion;
2212 break;
2214 case ALC_EFX_MAJOR_VERSION:
2215 *data = alcEFXMajorVersion;
2216 break;
2218 case ALC_EFX_MINOR_VERSION:
2219 *data = alcEFXMinorVersion;
2220 break;
2222 case ALC_ATTRIBUTES_SIZE:
2223 *data = 13;
2224 break;
2226 case ALC_ALL_ATTRIBUTES:
2227 if(size < 13)
2228 alcSetError(device, ALC_INVALID_VALUE);
2229 else
2231 int i = 0;
2233 data[i++] = ALC_FREQUENCY;
2234 data[i++] = device->Frequency;
2236 if(device->Type != Loopback)
2238 data[i++] = ALC_REFRESH;
2239 data[i++] = device->Frequency / device->UpdateSize;
2241 data[i++] = ALC_SYNC;
2242 data[i++] = ALC_FALSE;
2244 else
2246 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2247 data[i++] = device->FmtChans;
2249 data[i++] = ALC_FORMAT_TYPE_SOFT;
2250 data[i++] = device->FmtType;
2253 data[i++] = ALC_MONO_SOURCES;
2254 data[i++] = device->NumMonoSources;
2256 data[i++] = ALC_STEREO_SOURCES;
2257 data[i++] = device->NumStereoSources;
2259 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2260 data[i++] = device->NumAuxSends;
2262 data[i++] = 0;
2264 break;
2266 case ALC_FREQUENCY:
2267 *data = device->Frequency;
2268 break;
2270 case ALC_REFRESH:
2271 if(device->Type == Loopback)
2272 alcSetError(device, ALC_INVALID_DEVICE);
2273 else
2274 *data = device->Frequency / device->UpdateSize;
2275 break;
2277 case ALC_SYNC:
2278 if(device->Type == Loopback)
2279 alcSetError(device, ALC_INVALID_DEVICE);
2280 else
2281 *data = ALC_FALSE;
2282 break;
2284 case ALC_FORMAT_CHANNELS_SOFT:
2285 if(device->Type != Loopback)
2286 alcSetError(device, ALC_INVALID_DEVICE);
2287 else
2288 *data = device->FmtChans;
2289 break;
2291 case ALC_FORMAT_TYPE_SOFT:
2292 if(device->Type != Loopback)
2293 alcSetError(device, ALC_INVALID_DEVICE);
2294 else
2295 *data = device->FmtType;
2296 break;
2298 case ALC_MONO_SOURCES:
2299 *data = device->NumMonoSources;
2300 break;
2302 case ALC_STEREO_SOURCES:
2303 *data = device->NumStereoSources;
2304 break;
2306 case ALC_MAX_AUXILIARY_SENDS:
2307 *data = device->NumAuxSends;
2308 break;
2310 case ALC_CONNECTED:
2311 *data = device->Connected;
2312 break;
2314 default:
2315 alcSetError(device, ALC_INVALID_ENUM);
2316 break;
2319 if(device)
2320 ALCdevice_DecRef(device);
2324 /* alcIsExtensionPresent
2326 * Determines if there is support for a particular extension
2328 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2330 ALCboolean bResult = ALC_FALSE;
2332 device = VerifyDevice(device);
2334 if(!extName)
2335 alcSetError(device, ALC_INVALID_VALUE);
2336 else
2338 size_t len = strlen(extName);
2339 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2340 while(ptr && *ptr)
2342 if(strncasecmp(ptr, extName, len) == 0 &&
2343 (ptr[len] == '\0' || isspace(ptr[len])))
2345 bResult = ALC_TRUE;
2346 break;
2348 if((ptr=strchr(ptr, ' ')) != NULL)
2350 do {
2351 ++ptr;
2352 } while(isspace(*ptr));
2356 if(device)
2357 ALCdevice_DecRef(device);
2358 return bResult;
2362 /* alcGetProcAddress
2364 * Retrieves the function address for a particular extension function
2366 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2368 ALCvoid *ptr = NULL;
2370 if(!funcName)
2372 device = VerifyDevice(device);
2373 alcSetError(device, ALC_INVALID_VALUE);
2374 if(device) ALCdevice_DecRef(device);
2376 else
2378 ALsizei i = 0;
2379 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2380 i++;
2381 ptr = alcFunctions[i].address;
2384 return ptr;
2388 /* alcGetEnumValue
2390 * Get the value for a particular ALC enumeration name
2392 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2394 ALCenum val = 0;
2396 if(!enumName)
2398 device = VerifyDevice(device);
2399 alcSetError(device, ALC_INVALID_VALUE);
2400 if(device) ALCdevice_DecRef(device);
2402 else
2404 ALsizei i = 0;
2405 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2406 i++;
2407 val = enumeration[i].value;
2410 return val;
2414 /* alcCreateContext
2416 * Create and attach a context to the given device.
2418 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2420 ALCcontext *ALContext;
2421 ALCenum err;
2423 LockLists();
2424 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2426 UnlockLists();
2427 alcSetError(device, ALC_INVALID_DEVICE);
2428 if(device) ALCdevice_DecRef(device);
2429 return NULL;
2432 device->LastError = ALC_NO_ERROR;
2434 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2436 UnlockLists();
2437 alcSetError(device, err);
2438 if(err == ALC_INVALID_DEVICE)
2439 aluHandleDisconnect(device);
2440 ALCdevice_DecRef(device);
2441 return NULL;
2444 ALContext = calloc(1, sizeof(ALCcontext));
2445 if(ALContext)
2447 ALContext->ref = 1;
2449 ALContext->MaxActiveSources = 256;
2450 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2451 ALContext->MaxActiveSources);
2453 if(!ALContext || !ALContext->ActiveSources)
2455 if(!device->ContextList)
2457 ALCdevice_StopPlayback(device);
2458 device->Flags &= ~DEVICE_RUNNING;
2460 UnlockLists();
2462 free(ALContext);
2463 ALContext = NULL;
2465 alcSetError(device, ALC_OUT_OF_MEMORY);
2466 ALCdevice_DecRef(device);
2467 return NULL;
2470 ALContext->Device = device;
2471 ALCdevice_IncRef(device);
2472 InitContext(ALContext);
2474 do {
2475 ALContext->next = device->ContextList;
2476 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2477 UnlockLists();
2479 ALCdevice_DecRef(device);
2481 TRACE("Created context %p\n", ALContext);
2482 return ALContext;
2485 /* alcDestroyContext
2487 * Remove a context from its device
2489 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2491 ALCdevice *Device;
2493 LockLists();
2494 /* alcGetContextsDevice sets an error for invalid contexts */
2495 Device = alcGetContextsDevice(context);
2496 if(Device)
2498 ReleaseContext(context, Device);
2499 if(!Device->ContextList)
2501 ALCdevice_StopPlayback(Device);
2502 Device->Flags &= ~DEVICE_RUNNING;
2505 UnlockLists();
2509 /* alcGetCurrentContext
2511 * Returns the currently active context on the calling thread
2513 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2515 ALCcontext *Context;
2517 Context = pthread_getspecific(LocalContext);
2518 if(!Context) Context = GlobalContext;
2520 return Context;
2523 /* alcGetThreadContext
2525 * Returns the currently active thread-local context
2527 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2529 ALCcontext *Context;
2530 Context = pthread_getspecific(LocalContext);
2531 return Context;
2535 /* alcMakeContextCurrent
2537 * Makes the given context the active process-wide context, and removes the
2538 * thread-local context for the calling thread.
2540 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2542 /* context must be valid or NULL */
2543 if(context && !(context=VerifyContext(context)))
2545 alcSetError(NULL, ALC_INVALID_CONTEXT);
2546 return ALC_FALSE;
2548 /* context's reference count is already incremented */
2549 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2550 if(context) ALCcontext_DecRef(context);
2552 if((context=pthread_getspecific(LocalContext)) != NULL)
2554 pthread_setspecific(LocalContext, NULL);
2555 ALCcontext_DecRef(context);
2558 return ALC_TRUE;
2561 /* alcSetThreadContext
2563 * Makes the given context the active context for the current thread
2565 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2567 ALCcontext *old;
2569 /* context must be valid or NULL */
2570 if(context && !(context=VerifyContext(context)))
2572 alcSetError(NULL, ALC_INVALID_CONTEXT);
2573 return ALC_FALSE;
2575 /* context's reference count is already incremented */
2576 old = pthread_getspecific(LocalContext);
2577 pthread_setspecific(LocalContext, context);
2578 if(old) ALCcontext_DecRef(old);
2580 return ALC_TRUE;
2584 /* alcGetContextsDevice
2586 * Returns the device that a particular context is attached to
2588 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2590 ALCdevice *Device;
2592 if(!(Context=VerifyContext(Context)))
2594 alcSetError(NULL, ALC_INVALID_CONTEXT);
2595 return NULL;
2597 Device = Context->Device;
2598 ALCcontext_DecRef(Context);
2600 return Device;
2604 /* alcOpenDevice
2606 * Opens the named device.
2608 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2610 const ALCchar *fmt;
2611 ALCdevice *device;
2612 ALCenum err;
2614 DO_INITCONFIG();
2616 if(!PlaybackBackend.name)
2618 alcSetError(NULL, ALC_INVALID_VALUE);
2619 return NULL;
2622 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2623 deviceName = NULL;
2625 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2626 if(!device)
2628 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2629 return NULL;
2632 //Validate device
2633 device->Funcs = &PlaybackBackend.Funcs;
2634 device->ref = 1;
2635 device->Connected = ALC_TRUE;
2636 device->Type = Playback;
2637 InitializeCriticalSection(&device->Mutex);
2638 device->LastError = ALC_NO_ERROR;
2640 device->Flags = 0;
2641 device->Bs2b = NULL;
2642 device->Bs2bLevel = 0;
2643 device->DeviceName = NULL;
2645 device->ContextList = NULL;
2647 device->MaxNoOfSources = 256;
2648 device->AuxiliaryEffectSlotMax = 4;
2649 device->NumAuxSends = MAX_SENDS;
2651 InitUIntMap(&device->BufferMap, ~0);
2652 InitUIntMap(&device->EffectMap, ~0);
2653 InitUIntMap(&device->FilterMap, ~0);
2655 //Set output format
2656 device->FmtChans = DevFmtChannelsDefault;
2657 device->FmtType = DevFmtTypeDefault;
2658 device->Frequency = DEFAULT_OUTPUT_RATE;
2659 device->NumUpdates = 4;
2660 device->UpdateSize = 1024;
2662 if(ConfigValueStr(NULL, "channels", &fmt))
2664 static const struct {
2665 const char name[16];
2666 enum DevFmtChannels chans;
2667 } chanlist[] = {
2668 { "mono", DevFmtMono },
2669 { "stereo", DevFmtStereo },
2670 { "quad", DevFmtQuad },
2671 { "surround51", DevFmtX51 },
2672 { "surround61", DevFmtX61 },
2673 { "surround71", DevFmtX71 },
2675 size_t i;
2677 for(i = 0;i < COUNTOF(chanlist);i++)
2679 if(strcasecmp(chanlist[i].name, fmt) == 0)
2681 device->FmtChans = chanlist[i].chans;
2682 device->Flags |= DEVICE_CHANNELS_REQUEST;
2683 break;
2686 if(i == COUNTOF(chanlist))
2687 ERR("Unsupported channels: %s\n", fmt);
2689 if(ConfigValueStr(NULL, "sample-type", &fmt))
2691 static const struct {
2692 const char name[16];
2693 enum DevFmtType type;
2694 } typelist[] = {
2695 { "int8", DevFmtByte },
2696 { "uint8", DevFmtUByte },
2697 { "int16", DevFmtShort },
2698 { "uint16", DevFmtUShort },
2699 { "int32", DevFmtInt },
2700 { "uint32", DevFmtUInt },
2701 { "float32", DevFmtFloat },
2703 size_t i;
2705 for(i = 0;i < COUNTOF(typelist);i++)
2707 if(strcasecmp(typelist[i].name, fmt) == 0)
2709 device->FmtType = typelist[i].type;
2710 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2711 break;
2714 if(i == COUNTOF(typelist))
2715 ERR("Unsupported sample-type: %s\n", fmt);
2717 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2718 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2719 ConfigValueStr(NULL, "format", &fmt))
2721 static const struct {
2722 const char name[32];
2723 enum DevFmtChannels channels;
2724 enum DevFmtType type;
2725 } formats[] = {
2726 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2727 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2728 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2729 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2730 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2731 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2733 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2734 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2735 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2736 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2737 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2738 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2740 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2741 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2742 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2743 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2744 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2745 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2747 size_t i;
2749 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2750 for(i = 0;i < COUNTOF(formats);i++)
2752 if(strcasecmp(fmt, formats[i].name) == 0)
2754 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2755 device->FmtChans = formats[i].channels;
2756 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2757 device->FmtType = formats[i].type;
2758 device->Flags |= DEVICE_FORMAT_REQUEST;
2759 break;
2762 if(i == COUNTOF(formats))
2763 ERR("Unsupported format: %s\n", fmt);
2765 #undef DEVICE_FORMAT_REQUEST
2767 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2769 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2770 if(device->Frequency < MIN_OUTPUT_RATE)
2771 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2772 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2775 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2776 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2778 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2779 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2781 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2782 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2784 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2785 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2787 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2788 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2790 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2792 device->NumStereoSources = 1;
2793 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2795 // Find a playback device to open
2796 LockLists();
2797 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2799 UnlockLists();
2800 DeleteCriticalSection(&device->Mutex);
2801 free(device);
2802 alcSetError(NULL, err);
2803 return NULL;
2805 UnlockLists();
2807 if(DefaultEffect.type != AL_EFFECT_NULL)
2809 device->DefaultSlot = (ALeffectslot*)(device+1);
2810 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2812 device->DefaultSlot = NULL;
2813 ERR("Failed to initialize the default effect slot\n");
2815 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2817 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2818 device->DefaultSlot = NULL;
2819 ERR("Failed to initialize the default effect\n");
2823 do {
2824 device->next = DeviceList;
2825 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2827 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2828 return device;
2831 /* alcCloseDevice
2833 * Closes the given device.
2835 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2837 ALCdevice *volatile*list;
2838 ALCcontext *ctx;
2840 LockLists();
2841 list = &DeviceList;
2842 while(*list && *list != Device)
2843 list = &(*list)->next;
2845 if(!*list || (*list)->Type == Capture)
2847 alcSetError(*list, ALC_INVALID_DEVICE);
2848 UnlockLists();
2849 return ALC_FALSE;
2852 *list = (*list)->next;
2853 UnlockLists();
2855 while((ctx=Device->ContextList) != NULL)
2857 WARN("Releasing context %p\n", ctx);
2858 ReleaseContext(ctx, Device);
2860 if((Device->Flags&DEVICE_RUNNING))
2861 ALCdevice_StopPlayback(Device);
2862 Device->Flags &= ~DEVICE_RUNNING;
2864 ALCdevice_DecRef(Device);
2866 return ALC_TRUE;
2870 /************************************************
2871 * ALC capture functions
2872 ************************************************/
2873 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2875 ALCdevice *device = NULL;
2876 ALCenum err;
2878 DO_INITCONFIG();
2880 if(!CaptureBackend.name)
2882 alcSetError(NULL, ALC_INVALID_VALUE);
2883 return NULL;
2886 if(samples <= 0)
2888 alcSetError(NULL, ALC_INVALID_VALUE);
2889 return NULL;
2892 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2893 deviceName = NULL;
2895 device = calloc(1, sizeof(ALCdevice));
2896 if(!device)
2898 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2899 return NULL;
2902 //Validate device
2903 device->Funcs = &CaptureBackend.Funcs;
2904 device->ref = 1;
2905 device->Connected = ALC_TRUE;
2906 device->Type = Capture;
2907 InitializeCriticalSection(&device->Mutex);
2909 InitUIntMap(&device->BufferMap, ~0);
2910 InitUIntMap(&device->EffectMap, ~0);
2911 InitUIntMap(&device->FilterMap, ~0);
2913 device->DeviceName = NULL;
2915 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2916 device->Frequency = frequency;
2918 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2919 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2921 DeleteCriticalSection(&device->Mutex);
2922 free(device);
2923 alcSetError(NULL, ALC_INVALID_ENUM);
2924 return NULL;
2927 device->UpdateSize = samples;
2928 device->NumUpdates = 1;
2930 LockLists();
2931 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2933 UnlockLists();
2934 DeleteCriticalSection(&device->Mutex);
2935 free(device);
2936 alcSetError(NULL, err);
2937 return NULL;
2939 UnlockLists();
2941 do {
2942 device->next = DeviceList;
2943 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2945 TRACE("Created device %p\n", device);
2946 return device;
2949 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2951 ALCdevice *volatile*list;
2953 LockLists();
2954 list = &DeviceList;
2955 while(*list && *list != Device)
2956 list = &(*list)->next;
2958 if(!*list || (*list)->Type != Capture)
2960 alcSetError(*list, ALC_INVALID_DEVICE);
2961 UnlockLists();
2962 return ALC_FALSE;
2965 *list = (*list)->next;
2966 UnlockLists();
2968 ALCdevice_DecRef(Device);
2970 return ALC_TRUE;
2973 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2975 LockLists();
2976 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2978 UnlockLists();
2979 alcSetError(device, ALC_INVALID_DEVICE);
2980 if(device) ALCdevice_DecRef(device);
2981 return;
2983 if(device->Connected)
2985 if(!(device->Flags&DEVICE_RUNNING))
2986 ALCdevice_StartCapture(device);
2987 device->Flags |= DEVICE_RUNNING;
2989 UnlockLists();
2991 ALCdevice_DecRef(device);
2994 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
2996 LockLists();
2997 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2999 UnlockLists();
3000 alcSetError(device, ALC_INVALID_DEVICE);
3001 if(device) ALCdevice_DecRef(device);
3002 return;
3004 if((device->Flags&DEVICE_RUNNING))
3005 ALCdevice_StopCapture(device);
3006 device->Flags &= ~DEVICE_RUNNING;
3007 UnlockLists();
3009 ALCdevice_DecRef(device);
3012 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3014 ALCenum err = ALC_INVALID_DEVICE;
3015 LockLists();
3016 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3018 err = ALC_INVALID_VALUE;
3019 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3020 err = ALCdevice_CaptureSamples(device, buffer, samples);
3022 UnlockLists();
3023 if(err != ALC_NO_ERROR)
3024 alcSetError(device, err);
3025 if(device) ALCdevice_DecRef(device);
3029 /************************************************
3030 * ALC loopback functions
3031 ************************************************/
3033 /* alcLoopbackOpenDeviceSOFT
3035 * Open a loopback device, for manual rendering.
3037 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3039 ALCdevice *device;
3041 DO_INITCONFIG();
3043 /* Make sure the device name, if specified, is us. */
3044 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3046 alcSetError(NULL, ALC_INVALID_VALUE);
3047 return NULL;
3050 device = calloc(1, sizeof(ALCdevice));
3051 if(!device)
3053 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3054 return NULL;
3057 //Validate device
3058 device->Funcs = &BackendLoopback.Funcs;
3059 device->ref = 1;
3060 device->Connected = ALC_TRUE;
3061 device->Type = Loopback;
3062 InitializeCriticalSection(&device->Mutex);
3063 device->LastError = ALC_NO_ERROR;
3065 device->Flags = 0;
3066 device->Bs2b = NULL;
3067 device->Bs2bLevel = 0;
3068 device->DeviceName = NULL;
3070 device->ContextList = NULL;
3072 device->MaxNoOfSources = 256;
3073 device->AuxiliaryEffectSlotMax = 4;
3074 device->NumAuxSends = MAX_SENDS;
3076 InitUIntMap(&device->BufferMap, ~0);
3077 InitUIntMap(&device->EffectMap, ~0);
3078 InitUIntMap(&device->FilterMap, ~0);
3080 //Set output format
3081 device->NumUpdates = 0;
3082 device->UpdateSize = 0;
3084 device->Frequency = DEFAULT_OUTPUT_RATE;
3085 device->FmtChans = DevFmtChannelsDefault;
3086 device->FmtType = DevFmtTypeDefault;
3088 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3089 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3091 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3092 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3094 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3095 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3097 device->NumStereoSources = 1;
3098 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3100 // Open the "backend"
3101 ALCdevice_OpenPlayback(device, "Loopback");
3102 do {
3103 device->next = DeviceList;
3104 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3106 TRACE("Created device %p\n", device);
3107 return device;
3110 /* alcIsRenderFormatSupportedSOFT
3112 * Determines if the loopback device supports the given format for rendering.
3114 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3116 ALCboolean ret = ALC_FALSE;
3118 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3119 alcSetError(device, ALC_INVALID_DEVICE);
3120 else if(freq <= 0)
3121 alcSetError(device, ALC_INVALID_VALUE);
3122 else
3124 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3125 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3126 freq >= MIN_OUTPUT_RATE)
3127 ret = ALC_TRUE;
3129 if(device) ALCdevice_DecRef(device);
3131 return ret;
3134 /* alcRenderSamplesSOFT
3136 * Renders some samples into a buffer, using the format last set by the
3137 * attributes given to alcCreateContext.
3139 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3141 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3142 alcSetError(device, ALC_INVALID_DEVICE);
3143 else if(samples < 0 || (samples > 0 && buffer == NULL))
3144 alcSetError(device, ALC_INVALID_VALUE);
3145 else
3146 aluMixData(device, buffer, samples);
3147 if(device) ALCdevice_DecRef(device);