Properly export alGetSource3i64SOFT
[openal-soft.git] / Alc / ALc.c
blob2f994880c17555a566e5ee2fd7e08593b9f3840f
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "AL/al.h"
33 #include "AL/alc.h"
34 #include "alThunk.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alAuxEffectSlot.h"
38 #include "alError.h"
39 #include "bs2b.h"
40 #include "alu.h"
43 /************************************************
44 * Backends
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
50 #endif
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_COREAUDIO
55 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_OSS
58 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_SOLARIS
61 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_SNDIO
64 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_MMDEVAPI
67 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_DSOUND
70 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
71 #endif
72 #ifdef HAVE_WINMM
73 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_PORTAUDIO
76 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
77 #endif
78 #ifdef HAVE_OPENSL
79 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
80 #endif
82 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
83 #ifdef HAVE_WAVE
84 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
85 #endif
87 { NULL, NULL, NULL, NULL, EmptyFuncs }
89 static struct BackendInfo BackendLoopback = {
90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
92 #undef EmptyFuncs
94 static struct BackendInfo PlaybackBackend;
95 static struct BackendInfo CaptureBackend;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction {
101 const ALCchar *funcName;
102 ALCvoid *address;
103 } ALCfunction;
105 typedef struct ALCenums {
106 const ALCchar *enumName;
107 ALCenum value;
108 } ALCenums;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions[] = {
112 DECL(alcCreateContext),
113 DECL(alcMakeContextCurrent),
114 DECL(alcProcessContext),
115 DECL(alcSuspendContext),
116 DECL(alcDestroyContext),
117 DECL(alcGetCurrentContext),
118 DECL(alcGetContextsDevice),
119 DECL(alcOpenDevice),
120 DECL(alcCloseDevice),
121 DECL(alcGetError),
122 DECL(alcIsExtensionPresent),
123 DECL(alcGetProcAddress),
124 DECL(alcGetEnumValue),
125 DECL(alcGetString),
126 DECL(alcGetIntegerv),
127 DECL(alcCaptureOpenDevice),
128 DECL(alcCaptureCloseDevice),
129 DECL(alcCaptureStart),
130 DECL(alcCaptureStop),
131 DECL(alcCaptureSamples),
133 DECL(alcSetThreadContext),
134 DECL(alcGetThreadContext),
136 DECL(alcLoopbackOpenDeviceSOFT),
137 DECL(alcIsRenderFormatSupportedSOFT),
138 DECL(alcRenderSamplesSOFT),
140 DECL(alEnable),
141 DECL(alDisable),
142 DECL(alIsEnabled),
143 DECL(alGetString),
144 DECL(alGetBooleanv),
145 DECL(alGetIntegerv),
146 DECL(alGetFloatv),
147 DECL(alGetDoublev),
148 DECL(alGetBoolean),
149 DECL(alGetInteger),
150 DECL(alGetFloat),
151 DECL(alGetDouble),
152 DECL(alGetError),
153 DECL(alIsExtensionPresent),
154 DECL(alGetProcAddress),
155 DECL(alGetEnumValue),
156 DECL(alListenerf),
157 DECL(alListener3f),
158 DECL(alListenerfv),
159 DECL(alListeneri),
160 DECL(alListener3i),
161 DECL(alListeneriv),
162 DECL(alGetListenerf),
163 DECL(alGetListener3f),
164 DECL(alGetListenerfv),
165 DECL(alGetListeneri),
166 DECL(alGetListener3i),
167 DECL(alGetListeneriv),
168 DECL(alGenSources),
169 DECL(alDeleteSources),
170 DECL(alIsSource),
171 DECL(alSourcef),
172 DECL(alSource3f),
173 DECL(alSourcefv),
174 DECL(alSourcei),
175 DECL(alSource3i),
176 DECL(alSourceiv),
177 DECL(alGetSourcef),
178 DECL(alGetSource3f),
179 DECL(alGetSourcefv),
180 DECL(alGetSourcei),
181 DECL(alGetSource3i),
182 DECL(alGetSourceiv),
183 DECL(alSourcePlayv),
184 DECL(alSourceStopv),
185 DECL(alSourceRewindv),
186 DECL(alSourcePausev),
187 DECL(alSourcePlay),
188 DECL(alSourceStop),
189 DECL(alSourceRewind),
190 DECL(alSourcePause),
191 DECL(alSourceQueueBuffers),
192 DECL(alSourceUnqueueBuffers),
193 DECL(alGenBuffers),
194 DECL(alDeleteBuffers),
195 DECL(alIsBuffer),
196 DECL(alBufferData),
197 DECL(alBufferf),
198 DECL(alBuffer3f),
199 DECL(alBufferfv),
200 DECL(alBufferi),
201 DECL(alBuffer3i),
202 DECL(alBufferiv),
203 DECL(alGetBufferf),
204 DECL(alGetBuffer3f),
205 DECL(alGetBufferfv),
206 DECL(alGetBufferi),
207 DECL(alGetBuffer3i),
208 DECL(alGetBufferiv),
209 DECL(alDopplerFactor),
210 DECL(alDopplerVelocity),
211 DECL(alSpeedOfSound),
212 DECL(alDistanceModel),
214 DECL(alGenFilters),
215 DECL(alDeleteFilters),
216 DECL(alIsFilter),
217 DECL(alFilteri),
218 DECL(alFilteriv),
219 DECL(alFilterf),
220 DECL(alFilterfv),
221 DECL(alGetFilteri),
222 DECL(alGetFilteriv),
223 DECL(alGetFilterf),
224 DECL(alGetFilterfv),
225 DECL(alGenEffects),
226 DECL(alDeleteEffects),
227 DECL(alIsEffect),
228 DECL(alEffecti),
229 DECL(alEffectiv),
230 DECL(alEffectf),
231 DECL(alEffectfv),
232 DECL(alGetEffecti),
233 DECL(alGetEffectiv),
234 DECL(alGetEffectf),
235 DECL(alGetEffectfv),
236 DECL(alGenAuxiliaryEffectSlots),
237 DECL(alDeleteAuxiliaryEffectSlots),
238 DECL(alIsAuxiliaryEffectSlot),
239 DECL(alAuxiliaryEffectSloti),
240 DECL(alAuxiliaryEffectSlotiv),
241 DECL(alAuxiliaryEffectSlotf),
242 DECL(alAuxiliaryEffectSlotfv),
243 DECL(alGetAuxiliaryEffectSloti),
244 DECL(alGetAuxiliaryEffectSlotiv),
245 DECL(alGetAuxiliaryEffectSlotf),
246 DECL(alGetAuxiliaryEffectSlotfv),
248 DECL(alBufferSubDataSOFT),
250 DECL(alBufferSamplesSOFT),
251 DECL(alBufferSubSamplesSOFT),
252 DECL(alGetBufferSamplesSOFT),
253 DECL(alIsBufferFormatSupportedSOFT),
255 DECL(alDeferUpdatesSOFT),
256 DECL(alProcessUpdatesSOFT),
258 DECL(alGetSourcei64SOFT),
259 DECL(alGetSource3i64SOFT),
260 DECL(alGetSourcei64vSOFT),
262 { NULL, NULL }
264 #undef DECL
266 #define DECL(x) { #x, (x) }
267 static const ALCenums enumeration[] = {
268 DECL(ALC_INVALID),
269 DECL(ALC_FALSE),
270 DECL(ALC_TRUE),
272 DECL(ALC_MAJOR_VERSION),
273 DECL(ALC_MINOR_VERSION),
274 DECL(ALC_ATTRIBUTES_SIZE),
275 DECL(ALC_ALL_ATTRIBUTES),
276 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
277 DECL(ALC_DEVICE_SPECIFIER),
278 DECL(ALC_ALL_DEVICES_SPECIFIER),
279 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
280 DECL(ALC_EXTENSIONS),
281 DECL(ALC_FREQUENCY),
282 DECL(ALC_REFRESH),
283 DECL(ALC_SYNC),
284 DECL(ALC_MONO_SOURCES),
285 DECL(ALC_STEREO_SOURCES),
286 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
287 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
288 DECL(ALC_CAPTURE_SAMPLES),
289 DECL(ALC_CONNECTED),
291 DECL(ALC_EFX_MAJOR_VERSION),
292 DECL(ALC_EFX_MINOR_VERSION),
293 DECL(ALC_MAX_AUXILIARY_SENDS),
295 DECL(ALC_FORMAT_CHANNELS_SOFT),
296 DECL(ALC_FORMAT_TYPE_SOFT),
298 DECL(ALC_MONO_SOFT),
299 DECL(ALC_STEREO_SOFT),
300 DECL(ALC_QUAD_SOFT),
301 DECL(ALC_5POINT1_SOFT),
302 DECL(ALC_6POINT1_SOFT),
303 DECL(ALC_7POINT1_SOFT),
305 DECL(ALC_BYTE_SOFT),
306 DECL(ALC_UNSIGNED_BYTE_SOFT),
307 DECL(ALC_SHORT_SOFT),
308 DECL(ALC_UNSIGNED_SHORT_SOFT),
309 DECL(ALC_INT_SOFT),
310 DECL(ALC_UNSIGNED_INT_SOFT),
311 DECL(ALC_FLOAT_SOFT),
313 DECL(ALC_NO_ERROR),
314 DECL(ALC_INVALID_DEVICE),
315 DECL(ALC_INVALID_CONTEXT),
316 DECL(ALC_INVALID_ENUM),
317 DECL(ALC_INVALID_VALUE),
318 DECL(ALC_OUT_OF_MEMORY),
321 DECL(AL_INVALID),
322 DECL(AL_NONE),
323 DECL(AL_FALSE),
324 DECL(AL_TRUE),
326 DECL(AL_SOURCE_RELATIVE),
327 DECL(AL_CONE_INNER_ANGLE),
328 DECL(AL_CONE_OUTER_ANGLE),
329 DECL(AL_PITCH),
330 DECL(AL_POSITION),
331 DECL(AL_DIRECTION),
332 DECL(AL_VELOCITY),
333 DECL(AL_LOOPING),
334 DECL(AL_BUFFER),
335 DECL(AL_GAIN),
336 DECL(AL_MIN_GAIN),
337 DECL(AL_MAX_GAIN),
338 DECL(AL_ORIENTATION),
339 DECL(AL_REFERENCE_DISTANCE),
340 DECL(AL_ROLLOFF_FACTOR),
341 DECL(AL_CONE_OUTER_GAIN),
342 DECL(AL_MAX_DISTANCE),
343 DECL(AL_SEC_OFFSET),
344 DECL(AL_SAMPLE_OFFSET),
345 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
346 DECL(AL_BYTE_OFFSET),
347 DECL(AL_BYTE_RW_OFFSETS_SOFT),
348 DECL(AL_SOURCE_TYPE),
349 DECL(AL_STATIC),
350 DECL(AL_STREAMING),
351 DECL(AL_UNDETERMINED),
352 DECL(AL_METERS_PER_UNIT),
353 DECL(AL_DIRECT_CHANNELS_SOFT),
355 DECL(AL_DIRECT_FILTER),
356 DECL(AL_AUXILIARY_SEND_FILTER),
357 DECL(AL_AIR_ABSORPTION_FACTOR),
358 DECL(AL_ROOM_ROLLOFF_FACTOR),
359 DECL(AL_CONE_OUTER_GAINHF),
360 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
361 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
362 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
364 DECL(AL_SOURCE_STATE),
365 DECL(AL_INITIAL),
366 DECL(AL_PLAYING),
367 DECL(AL_PAUSED),
368 DECL(AL_STOPPED),
370 DECL(AL_BUFFERS_QUEUED),
371 DECL(AL_BUFFERS_PROCESSED),
373 DECL(AL_FORMAT_MONO8),
374 DECL(AL_FORMAT_MONO16),
375 DECL(AL_FORMAT_MONO_FLOAT32),
376 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
377 DECL(AL_FORMAT_STEREO8),
378 DECL(AL_FORMAT_STEREO16),
379 DECL(AL_FORMAT_STEREO_FLOAT32),
380 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
381 DECL(AL_FORMAT_MONO_IMA4),
382 DECL(AL_FORMAT_STEREO_IMA4),
383 DECL(AL_FORMAT_QUAD8_LOKI),
384 DECL(AL_FORMAT_QUAD16_LOKI),
385 DECL(AL_FORMAT_QUAD8),
386 DECL(AL_FORMAT_QUAD16),
387 DECL(AL_FORMAT_QUAD32),
388 DECL(AL_FORMAT_51CHN8),
389 DECL(AL_FORMAT_51CHN16),
390 DECL(AL_FORMAT_51CHN32),
391 DECL(AL_FORMAT_61CHN8),
392 DECL(AL_FORMAT_61CHN16),
393 DECL(AL_FORMAT_61CHN32),
394 DECL(AL_FORMAT_71CHN8),
395 DECL(AL_FORMAT_71CHN16),
396 DECL(AL_FORMAT_71CHN32),
397 DECL(AL_FORMAT_REAR8),
398 DECL(AL_FORMAT_REAR16),
399 DECL(AL_FORMAT_REAR32),
400 DECL(AL_FORMAT_MONO_MULAW),
401 DECL(AL_FORMAT_MONO_MULAW_EXT),
402 DECL(AL_FORMAT_STEREO_MULAW),
403 DECL(AL_FORMAT_STEREO_MULAW_EXT),
404 DECL(AL_FORMAT_QUAD_MULAW),
405 DECL(AL_FORMAT_51CHN_MULAW),
406 DECL(AL_FORMAT_61CHN_MULAW),
407 DECL(AL_FORMAT_71CHN_MULAW),
408 DECL(AL_FORMAT_REAR_MULAW),
409 DECL(AL_FORMAT_MONO_ALAW_EXT),
410 DECL(AL_FORMAT_STEREO_ALAW_EXT),
412 DECL(AL_MONO8_SOFT),
413 DECL(AL_MONO16_SOFT),
414 DECL(AL_MONO32F_SOFT),
415 DECL(AL_STEREO8_SOFT),
416 DECL(AL_STEREO16_SOFT),
417 DECL(AL_STEREO32F_SOFT),
418 DECL(AL_QUAD8_SOFT),
419 DECL(AL_QUAD16_SOFT),
420 DECL(AL_QUAD32F_SOFT),
421 DECL(AL_REAR8_SOFT),
422 DECL(AL_REAR16_SOFT),
423 DECL(AL_REAR32F_SOFT),
424 DECL(AL_5POINT1_8_SOFT),
425 DECL(AL_5POINT1_16_SOFT),
426 DECL(AL_5POINT1_32F_SOFT),
427 DECL(AL_6POINT1_8_SOFT),
428 DECL(AL_6POINT1_16_SOFT),
429 DECL(AL_6POINT1_32F_SOFT),
430 DECL(AL_7POINT1_8_SOFT),
431 DECL(AL_7POINT1_16_SOFT),
432 DECL(AL_7POINT1_32F_SOFT),
434 DECL(AL_MONO_SOFT),
435 DECL(AL_STEREO_SOFT),
436 DECL(AL_QUAD_SOFT),
437 DECL(AL_REAR_SOFT),
438 DECL(AL_5POINT1_SOFT),
439 DECL(AL_6POINT1_SOFT),
440 DECL(AL_7POINT1_SOFT),
442 DECL(AL_BYTE_SOFT),
443 DECL(AL_UNSIGNED_BYTE_SOFT),
444 DECL(AL_SHORT_SOFT),
445 DECL(AL_UNSIGNED_SHORT_SOFT),
446 DECL(AL_INT_SOFT),
447 DECL(AL_UNSIGNED_INT_SOFT),
448 DECL(AL_FLOAT_SOFT),
449 DECL(AL_DOUBLE_SOFT),
450 DECL(AL_BYTE3_SOFT),
451 DECL(AL_UNSIGNED_BYTE3_SOFT),
453 DECL(AL_FREQUENCY),
454 DECL(AL_BITS),
455 DECL(AL_CHANNELS),
456 DECL(AL_SIZE),
457 DECL(AL_INTERNAL_FORMAT_SOFT),
458 DECL(AL_BYTE_LENGTH_SOFT),
459 DECL(AL_SAMPLE_LENGTH_SOFT),
460 DECL(AL_SEC_LENGTH_SOFT),
462 DECL(AL_UNUSED),
463 DECL(AL_PENDING),
464 DECL(AL_PROCESSED),
466 DECL(AL_NO_ERROR),
467 DECL(AL_INVALID_NAME),
468 DECL(AL_INVALID_ENUM),
469 DECL(AL_INVALID_VALUE),
470 DECL(AL_INVALID_OPERATION),
471 DECL(AL_OUT_OF_MEMORY),
473 DECL(AL_VENDOR),
474 DECL(AL_VERSION),
475 DECL(AL_RENDERER),
476 DECL(AL_EXTENSIONS),
478 DECL(AL_DOPPLER_FACTOR),
479 DECL(AL_DOPPLER_VELOCITY),
480 DECL(AL_DISTANCE_MODEL),
481 DECL(AL_SPEED_OF_SOUND),
482 DECL(AL_SOURCE_DISTANCE_MODEL),
483 DECL(AL_DEFERRED_UPDATES_SOFT),
485 DECL(AL_INVERSE_DISTANCE),
486 DECL(AL_INVERSE_DISTANCE_CLAMPED),
487 DECL(AL_LINEAR_DISTANCE),
488 DECL(AL_LINEAR_DISTANCE_CLAMPED),
489 DECL(AL_EXPONENT_DISTANCE),
490 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
492 DECL(AL_FILTER_TYPE),
493 DECL(AL_FILTER_NULL),
494 DECL(AL_FILTER_LOWPASS),
495 #if 0
496 DECL(AL_FILTER_HIGHPASS),
497 DECL(AL_FILTER_BANDPASS),
498 #endif
500 DECL(AL_LOWPASS_GAIN),
501 DECL(AL_LOWPASS_GAINHF),
503 DECL(AL_EFFECT_TYPE),
504 DECL(AL_EFFECT_NULL),
505 DECL(AL_EFFECT_REVERB),
506 DECL(AL_EFFECT_EAXREVERB),
507 #if 0
508 DECL(AL_EFFECT_CHORUS),
509 DECL(AL_EFFECT_DISTORTION),
510 #endif
511 DECL(AL_EFFECT_ECHO),
512 #if 0
513 DECL(AL_EFFECT_FLANGER),
514 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
515 DECL(AL_EFFECT_VOCAL_MORPHER),
516 DECL(AL_EFFECT_PITCH_SHIFTER),
517 #endif
518 DECL(AL_EFFECT_RING_MODULATOR),
519 #if 0
520 DECL(AL_EFFECT_AUTOWAH),
521 DECL(AL_EFFECT_COMPRESSOR),
522 DECL(AL_EFFECT_EQUALIZER),
523 #endif
524 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
525 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
527 DECL(AL_EAXREVERB_DENSITY),
528 DECL(AL_EAXREVERB_DIFFUSION),
529 DECL(AL_EAXREVERB_GAIN),
530 DECL(AL_EAXREVERB_GAINHF),
531 DECL(AL_EAXREVERB_GAINLF),
532 DECL(AL_EAXREVERB_DECAY_TIME),
533 DECL(AL_EAXREVERB_DECAY_HFRATIO),
534 DECL(AL_EAXREVERB_DECAY_LFRATIO),
535 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
536 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
537 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
538 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
539 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
540 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
541 DECL(AL_EAXREVERB_ECHO_TIME),
542 DECL(AL_EAXREVERB_ECHO_DEPTH),
543 DECL(AL_EAXREVERB_MODULATION_TIME),
544 DECL(AL_EAXREVERB_MODULATION_DEPTH),
545 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
546 DECL(AL_EAXREVERB_HFREFERENCE),
547 DECL(AL_EAXREVERB_LFREFERENCE),
548 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
549 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
551 DECL(AL_REVERB_DENSITY),
552 DECL(AL_REVERB_DIFFUSION),
553 DECL(AL_REVERB_GAIN),
554 DECL(AL_REVERB_GAINHF),
555 DECL(AL_REVERB_DECAY_TIME),
556 DECL(AL_REVERB_DECAY_HFRATIO),
557 DECL(AL_REVERB_REFLECTIONS_GAIN),
558 DECL(AL_REVERB_REFLECTIONS_DELAY),
559 DECL(AL_REVERB_LATE_REVERB_GAIN),
560 DECL(AL_REVERB_LATE_REVERB_DELAY),
561 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
562 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
563 DECL(AL_REVERB_DECAY_HFLIMIT),
565 DECL(AL_ECHO_DELAY),
566 DECL(AL_ECHO_LRDELAY),
567 DECL(AL_ECHO_DAMPING),
568 DECL(AL_ECHO_FEEDBACK),
569 DECL(AL_ECHO_SPREAD),
571 DECL(AL_RING_MODULATOR_FREQUENCY),
572 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
573 DECL(AL_RING_MODULATOR_WAVEFORM),
575 DECL(AL_DEDICATED_GAIN),
577 { NULL, (ALCenum)0 }
579 #undef DECL
581 static const ALCchar alcNoError[] = "No Error";
582 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
583 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
584 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
585 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
586 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
589 /************************************************
590 * Global variables
591 ************************************************/
593 /* Enumerated device names */
594 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
595 static ALCchar *alcAllDevicesList;
596 static ALCchar *alcCaptureDeviceList;
597 /* Sizes only include the first ending null character, not the second */
598 static size_t alcAllDevicesListSize;
599 static size_t alcCaptureDeviceListSize;
601 /* Default is always the first in the list */
602 static ALCchar *alcDefaultAllDevicesSpecifier;
603 static ALCchar *alcCaptureDefaultDeviceSpecifier;
605 /* Default context extensions */
606 static const ALchar alExtList[] =
607 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
608 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
609 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
610 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
611 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
613 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
615 /* Thread-local current context */
616 static pthread_key_t LocalContext;
617 /* Process-wide current context */
618 static ALCcontext *volatile GlobalContext = NULL;
620 /* Mixing thread piority level */
621 ALint RTPrioLevel;
623 FILE *LogFile;
624 #ifdef _DEBUG
625 enum LogLevel LogLevel = LogWarning;
626 #else
627 enum LogLevel LogLevel = LogError;
628 #endif
630 /* Flag to trap ALC device errors */
631 static ALCboolean TrapALCError = ALC_FALSE;
633 /* One-time configuration init control */
634 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
636 /* Default effect that applies to sources that don't have an effect on send 0 */
637 static ALeffect DefaultEffect;
640 /************************************************
641 * ALC information
642 ************************************************/
643 static const ALCchar alcNoDeviceExtList[] =
644 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCchar alcExtensionList[] =
647 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
648 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
649 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
650 static const ALCint alcMajorVersion = 1;
651 static const ALCint alcMinorVersion = 1;
653 static const ALCint alcEFXMajorVersion = 1;
654 static const ALCint alcEFXMinorVersion = 0;
657 /************************************************
658 * Device lists
659 ************************************************/
660 static ALCdevice *volatile DeviceList = NULL;
662 static CRITICAL_SECTION ListLock;
664 static void LockLists(void)
666 EnterCriticalSection(&ListLock);
668 static void UnlockLists(void)
670 LeaveCriticalSection(&ListLock);
673 /************************************************
674 * Library initialization
675 ************************************************/
676 #if defined(_WIN32)
677 static void alc_init(void);
678 static void alc_deinit(void);
679 static void alc_deinit_safe(void);
681 UIntMap TlsDestructor;
683 #ifndef AL_LIBTYPE_STATIC
684 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
686 ALsizei i;
688 // Perform actions based on the reason for calling.
689 switch(ul_reason_for_call)
691 case DLL_PROCESS_ATTACH:
692 /* Pin the DLL so we won't get unloaded until the process terminates */
693 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
694 (WCHAR*)hModule, &hModule);
695 InitUIntMap(&TlsDestructor, ~0);
696 alc_init();
697 break;
699 case DLL_THREAD_DETACH:
700 LockUIntMapRead(&TlsDestructor);
701 for(i = 0;i < TlsDestructor.size;i++)
703 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
704 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
705 if(ptr && callback)
706 callback(ptr);
708 UnlockUIntMapRead(&TlsDestructor);
709 break;
711 case DLL_PROCESS_DETACH:
712 if(!lpReserved)
713 alc_deinit();
714 else
715 alc_deinit_safe();
716 ResetUIntMap(&TlsDestructor);
717 break;
719 return TRUE;
721 #elif defined(_MSC_VER)
722 #pragma section(".CRT$XCU",read)
723 static void alc_constructor(void);
724 static void alc_destructor(void);
725 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
727 static void alc_constructor(void)
729 atexit(alc_destructor);
730 alc_init();
733 static void alc_destructor(void)
735 alc_deinit();
737 #elif defined(HAVE_GCC_DESTRUCTOR)
738 static void alc_init(void) __attribute__((constructor));
739 static void alc_deinit(void) __attribute__((destructor));
740 #else
741 #error "No static initialization available on this platform!"
742 #endif
744 #elif defined(HAVE_GCC_DESTRUCTOR)
746 static void alc_init(void) __attribute__((constructor));
747 static void alc_deinit(void) __attribute__((destructor));
749 #else
750 #error "No global initialization available on this platform!"
751 #endif
753 static void ReleaseThreadCtx(void *ptr);
754 static void alc_init(void)
756 const char *str;
758 LogFile = stderr;
760 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
761 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
762 ConeScale *= 0.5f;
764 str = getenv("__ALSOFT_REVERSE_Z");
765 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
766 ZScale *= -1.0f;
768 pthread_key_create(&LocalContext, ReleaseThreadCtx);
769 InitializeCriticalSection(&ListLock);
770 ThunkInit();
773 static void alc_initconfig(void)
775 const char *devs, *str;
776 ALuint capfilter;
777 float valf;
778 int i, n;
780 str = getenv("ALSOFT_LOGLEVEL");
781 if(str)
783 long lvl = strtol(str, NULL, 0);
784 if(lvl >= NoLog && lvl <= LogRef)
785 LogLevel = lvl;
788 str = getenv("ALSOFT_LOGFILE");
789 if(str && str[0])
791 FILE *logfile = fopen(str, "wat");
792 if(logfile) LogFile = logfile;
793 else ERR("Failed to open log file '%s'\n", str);
796 ReadALConfig();
798 capfilter = 0;
799 #ifdef HAVE_SSE
800 capfilter |= CPU_CAP_SSE;
801 #endif
802 #ifdef HAVE_NEON
803 capfilter |= CPU_CAP_NEON;
804 #endif
805 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
807 if(strcasecmp(str, "all") == 0)
808 capfilter = 0;
809 else
811 size_t len;
812 const char *next = str;
814 i = 0;
815 do {
816 str = next;
817 next = strchr(str, ',');
819 while(isspace(str[0]))
820 str++;
821 if(!str[0] || str[0] == ',')
822 continue;
824 len = (next ? ((size_t)(next-str)) : strlen(str));
825 if(strncasecmp(str, "sse", len) == 0)
826 capfilter &= ~CPU_CAP_SSE;
827 else if(strncasecmp(str, "neon", len) == 0)
828 capfilter &= ~CPU_CAP_NEON;
829 else
830 WARN("Invalid CPU extension \"%s\"\n", str);
831 } while(next++);
834 FillCPUCaps(capfilter);
836 InitHrtf();
838 #ifdef _WIN32
839 RTPrioLevel = 1;
840 #else
841 RTPrioLevel = 0;
842 #endif
843 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
845 if(ConfigValueStr(NULL, "resampler", &str))
847 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
848 DefaultResampler = PointResampler;
849 else if(strcasecmp(str, "linear") == 0)
850 DefaultResampler = LinearResampler;
851 else if(strcasecmp(str, "cubic") == 0)
852 DefaultResampler = CubicResampler;
853 else
855 char *end;
857 n = strtol(str, &end, 0);
858 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
859 DefaultResampler = n;
860 else
861 WARN("Invalid resampler: %s\n", str);
865 str = getenv("ALSOFT_TRAP_ERROR");
866 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 TrapALError = AL_TRUE;
869 TrapALCError = AL_TRUE;
871 else
873 str = getenv("ALSOFT_TRAP_AL_ERROR");
874 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
875 TrapALError = AL_TRUE;
876 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
878 str = getenv("ALSOFT_TRAP_ALC_ERROR");
879 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
880 TrapALCError = ALC_TRUE;
881 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
884 if(ConfigValueFloat("reverb", "boost", &valf))
885 ReverbBoost *= powf(10.0f, valf / 20.0f);
887 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
889 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
890 ConfigValueStr(NULL, "drivers", &devs))
892 int n;
893 size_t len;
894 const char *next = devs;
895 int endlist, delitem;
897 i = 0;
898 do {
899 devs = next;
900 next = strchr(devs, ',');
902 delitem = (devs[0] == '-');
903 if(devs[0] == '-') devs++;
905 if(!devs[0] || devs[0] == ',')
907 endlist = 0;
908 continue;
910 endlist = 1;
912 len = (next ? ((size_t)(next-devs)) : strlen(devs));
913 for(n = i;BackendList[n].Init;n++)
915 if(len == strlen(BackendList[n].name) &&
916 strncmp(BackendList[n].name, devs, len) == 0)
918 if(delitem)
920 do {
921 BackendList[n] = BackendList[n+1];
922 ++n;
923 } while(BackendList[n].Init);
925 else
927 struct BackendInfo Bkp = BackendList[n];
928 while(n > i)
930 BackendList[n] = BackendList[n-1];
931 --n;
933 BackendList[n] = Bkp;
935 i++;
937 break;
940 } while(next++);
942 if(endlist)
944 BackendList[i].name = NULL;
945 BackendList[i].Init = NULL;
946 BackendList[i].Deinit = NULL;
947 BackendList[i].Probe = NULL;
951 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
953 if(!BackendList[i].Init(&BackendList[i].Funcs))
955 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
956 continue;
959 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
960 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
962 PlaybackBackend = BackendList[i];
963 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
965 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
967 CaptureBackend = BackendList[i];
968 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
971 BackendLoopback.Init(&BackendLoopback.Funcs);
973 if(ConfigValueStr(NULL, "excludefx", &str))
975 size_t len;
976 const char *next = str;
978 do {
979 str = next;
980 next = strchr(str, ',');
982 if(!str[0] || next == str)
983 continue;
985 len = (next ? ((size_t)(next-str)) : strlen(str));
986 for(n = 0;EffectList[n].name;n++)
988 if(len == strlen(EffectList[n].name) &&
989 strncmp(EffectList[n].name, str, len) == 0)
990 DisabledEffects[EffectList[n].type] = AL_TRUE;
992 } while(next++);
995 InitEffect(&DefaultEffect);
996 str = getenv("ALSOFT_DEFAULT_REVERB");
997 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
998 LoadReverbPreset(str, &DefaultEffect);
1000 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1003 /************************************************
1004 * Library deinitialization
1005 ************************************************/
1006 static void alc_cleanup(void)
1008 ALCdevice *dev;
1010 free(alcAllDevicesList); alcAllDevicesList = NULL;
1011 alcAllDevicesListSize = 0;
1012 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1013 alcCaptureDeviceListSize = 0;
1015 free(alcDefaultAllDevicesSpecifier);
1016 alcDefaultAllDevicesSpecifier = NULL;
1017 free(alcCaptureDefaultDeviceSpecifier);
1018 alcCaptureDefaultDeviceSpecifier = NULL;
1020 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1022 ALCuint num = 0;
1023 do {
1024 num++;
1025 } while((dev=dev->next) != NULL);
1026 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1030 static void alc_deinit_safe(void)
1032 alc_cleanup();
1034 FreeHrtf();
1035 FreeALConfig();
1037 ThunkExit();
1038 DeleteCriticalSection(&ListLock);
1039 pthread_key_delete(LocalContext);
1041 if(LogFile != stderr)
1042 fclose(LogFile);
1043 LogFile = NULL;
1046 static void alc_deinit(void)
1048 int i;
1050 alc_cleanup();
1052 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1053 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1055 for(i = 0;BackendList[i].Deinit;i++)
1056 BackendList[i].Deinit();
1057 BackendLoopback.Deinit();
1059 alc_deinit_safe();
1063 /************************************************
1064 * Device enumeration
1065 ************************************************/
1066 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1068 DO_INITCONFIG();
1070 LockLists();
1071 free(*list);
1072 *list = NULL;
1073 *listsize = 0;
1075 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1076 PlaybackBackend.Probe(type);
1077 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1078 CaptureBackend.Probe(type);
1079 UnlockLists();
1082 static void ProbeAllDevicesList(void)
1083 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1084 static void ProbeCaptureDeviceList(void)
1085 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1088 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1090 size_t len = strlen(name);
1091 void *temp;
1093 if(len == 0)
1094 return;
1096 temp = realloc(*List, (*ListSize) + len + 2);
1097 if(!temp)
1099 ERR("Realloc failed to add %s!\n", name);
1100 return;
1102 *List = temp;
1104 memcpy((*List)+(*ListSize), name, len+1);
1105 *ListSize += len+1;
1106 (*List)[*ListSize] = 0;
1109 #define DECL_APPEND_LIST_FUNC(type) \
1110 void Append##type##List(const ALCchar *name) \
1111 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1113 DECL_APPEND_LIST_FUNC(AllDevices)
1114 DECL_APPEND_LIST_FUNC(CaptureDevice)
1116 #undef DECL_APPEND_LIST_FUNC
1119 /************************************************
1120 * Device format information
1121 ************************************************/
1122 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1124 switch(type)
1126 case DevFmtByte: return "Signed Byte";
1127 case DevFmtUByte: return "Unsigned Byte";
1128 case DevFmtShort: return "Signed Short";
1129 case DevFmtUShort: return "Unsigned Short";
1130 case DevFmtInt: return "Signed Int";
1131 case DevFmtUInt: return "Unsigned Int";
1132 case DevFmtFloat: return "Float";
1134 return "(unknown type)";
1136 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1138 switch(chans)
1140 case DevFmtMono: return "Mono";
1141 case DevFmtStereo: return "Stereo";
1142 case DevFmtQuad: return "Quadraphonic";
1143 case DevFmtX51: return "5.1 Surround";
1144 case DevFmtX51Side: return "5.1 Side";
1145 case DevFmtX61: return "6.1 Surround";
1146 case DevFmtX71: return "7.1 Surround";
1148 return "(unknown channels)";
1151 ALuint BytesFromDevFmt(enum DevFmtType type)
1153 switch(type)
1155 case DevFmtByte: return sizeof(ALbyte);
1156 case DevFmtUByte: return sizeof(ALubyte);
1157 case DevFmtShort: return sizeof(ALshort);
1158 case DevFmtUShort: return sizeof(ALushort);
1159 case DevFmtInt: return sizeof(ALint);
1160 case DevFmtUInt: return sizeof(ALuint);
1161 case DevFmtFloat: return sizeof(ALfloat);
1163 return 0;
1165 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1167 switch(chans)
1169 case DevFmtMono: return 1;
1170 case DevFmtStereo: return 2;
1171 case DevFmtQuad: return 4;
1172 case DevFmtX51: return 6;
1173 case DevFmtX51Side: return 6;
1174 case DevFmtX61: return 7;
1175 case DevFmtX71: return 8;
1177 return 0;
1180 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1181 enum DevFmtType *type)
1183 static const struct {
1184 ALenum format;
1185 enum DevFmtChannels channels;
1186 enum DevFmtType type;
1187 } list[] = {
1188 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1189 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1190 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1192 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1193 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1194 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1196 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1197 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1198 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1200 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1201 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1202 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1204 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1205 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1206 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1208 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1209 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1210 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1212 ALuint i;
1214 for(i = 0;i < COUNTOF(list);i++)
1216 if(list[i].format == format)
1218 *chans = list[i].channels;
1219 *type = list[i].type;
1220 return AL_TRUE;
1224 return AL_FALSE;
1227 static ALCboolean IsValidALCType(ALCenum type)
1229 switch(type)
1231 case ALC_BYTE_SOFT:
1232 case ALC_UNSIGNED_BYTE_SOFT:
1233 case ALC_SHORT_SOFT:
1234 case ALC_UNSIGNED_SHORT_SOFT:
1235 case ALC_INT_SOFT:
1236 case ALC_UNSIGNED_INT_SOFT:
1237 case ALC_FLOAT_SOFT:
1238 return ALC_TRUE;
1240 return ALC_FALSE;
1243 static ALCboolean IsValidALCChannels(ALCenum channels)
1245 switch(channels)
1247 case ALC_MONO_SOFT:
1248 case ALC_STEREO_SOFT:
1249 case ALC_QUAD_SOFT:
1250 case ALC_5POINT1_SOFT:
1251 case ALC_6POINT1_SOFT:
1252 case ALC_7POINT1_SOFT:
1253 return ALC_TRUE;
1255 return ALC_FALSE;
1259 /************************************************
1260 * Miscellaneous ALC helpers
1261 ************************************************/
1263 void ALCdevice_LockDefault(ALCdevice *device)
1265 EnterCriticalSection(&device->Mutex);
1267 void ALCdevice_UnlockDefault(ALCdevice *device)
1269 LeaveCriticalSection(&device->Mutex);
1271 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
1273 (void)device;
1274 return 0;
1277 /* SetDefaultWFXChannelOrder
1279 * Sets the default channel order used by WaveFormatEx.
1281 void SetDefaultWFXChannelOrder(ALCdevice *device)
1283 switch(device->FmtChans)
1285 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1287 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1288 device->DevChannels[1] = FrontRight; break;
1290 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1291 device->DevChannels[1] = FrontRight;
1292 device->DevChannels[2] = BackLeft;
1293 device->DevChannels[3] = BackRight; break;
1295 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1296 device->DevChannels[1] = FrontRight;
1297 device->DevChannels[2] = FrontCenter;
1298 device->DevChannels[3] = LFE;
1299 device->DevChannels[4] = BackLeft;
1300 device->DevChannels[5] = BackRight; break;
1302 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1303 device->DevChannels[1] = FrontRight;
1304 device->DevChannels[2] = FrontCenter;
1305 device->DevChannels[3] = LFE;
1306 device->DevChannels[4] = SideLeft;
1307 device->DevChannels[5] = SideRight; break;
1309 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1310 device->DevChannels[1] = FrontRight;
1311 device->DevChannels[2] = FrontCenter;
1312 device->DevChannels[3] = LFE;
1313 device->DevChannels[4] = BackCenter;
1314 device->DevChannels[5] = SideLeft;
1315 device->DevChannels[6] = SideRight; break;
1317 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1318 device->DevChannels[1] = FrontRight;
1319 device->DevChannels[2] = FrontCenter;
1320 device->DevChannels[3] = LFE;
1321 device->DevChannels[4] = BackLeft;
1322 device->DevChannels[5] = BackRight;
1323 device->DevChannels[6] = SideLeft;
1324 device->DevChannels[7] = SideRight; break;
1328 /* SetDefaultChannelOrder
1330 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1332 void SetDefaultChannelOrder(ALCdevice *device)
1334 switch(device->FmtChans)
1336 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1337 device->DevChannels[1] = FrontRight;
1338 device->DevChannels[2] = BackLeft;
1339 device->DevChannels[3] = BackRight;
1340 device->DevChannels[4] = FrontCenter;
1341 device->DevChannels[5] = LFE;
1342 return;
1344 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1345 device->DevChannels[1] = FrontRight;
1346 device->DevChannels[2] = BackLeft;
1347 device->DevChannels[3] = BackRight;
1348 device->DevChannels[4] = FrontCenter;
1349 device->DevChannels[5] = LFE;
1350 device->DevChannels[6] = SideLeft;
1351 device->DevChannels[7] = SideRight;
1352 return;
1354 /* Same as WFX order */
1355 case DevFmtMono:
1356 case DevFmtStereo:
1357 case DevFmtQuad:
1358 case DevFmtX51Side:
1359 case DevFmtX61:
1360 break;
1362 SetDefaultWFXChannelOrder(device);
1366 /* alcSetError
1368 * Stores the latest ALC device error
1370 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1372 if(TrapALCError)
1374 #ifdef _WIN32
1375 /* DebugBreak() will cause an exception if there is no debugger */
1376 if(IsDebuggerPresent())
1377 DebugBreak();
1378 #elif defined(SIGTRAP)
1379 raise(SIGTRAP);
1380 #endif
1383 if(device)
1384 device->LastError = errorCode;
1385 else
1386 LastNullDeviceError = errorCode;
1390 /* UpdateDeviceParams
1392 * Updates device parameters according to the attribute list (caller is
1393 * responsible for holding the list lock).
1395 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1397 ALCcontext *context;
1398 enum DevFmtChannels oldChans;
1399 enum DevFmtType oldType;
1400 ALCuint oldFreq;
1401 int oldMode;
1402 ALuint i;
1404 // Check for attributes
1405 if(device->Type == Loopback)
1407 enum {
1408 GotFreq = 1<<0,
1409 GotChans = 1<<1,
1410 GotType = 1<<2,
1411 GotAll = GotFreq|GotChans|GotType
1413 ALCuint freq, numMono, numStereo, numSends;
1414 enum DevFmtChannels schans;
1415 enum DevFmtType stype;
1416 ALCuint attrIdx = 0;
1417 ALCint gotFmt = 0;
1419 if(!attrList)
1421 WARN("Missing attributes for loopback device\n");
1422 return ALC_INVALID_VALUE;
1425 numMono = device->NumMonoSources;
1426 numStereo = device->NumStereoSources;
1427 numSends = device->NumAuxSends;
1428 schans = device->FmtChans;
1429 stype = device->FmtType;
1430 freq = device->Frequency;
1432 while(attrList[attrIdx])
1434 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1436 ALCint val = attrList[attrIdx + 1];
1437 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1438 return ALC_INVALID_VALUE;
1439 schans = val;
1440 gotFmt |= GotChans;
1443 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1445 ALCint val = attrList[attrIdx + 1];
1446 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1447 return ALC_INVALID_VALUE;
1448 stype = val;
1449 gotFmt |= GotType;
1452 if(attrList[attrIdx] == ALC_FREQUENCY)
1454 freq = attrList[attrIdx + 1];
1455 if(freq < MIN_OUTPUT_RATE)
1456 return ALC_INVALID_VALUE;
1457 gotFmt |= GotFreq;
1460 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1462 numStereo = attrList[attrIdx + 1];
1463 if(numStereo > device->MaxNoOfSources)
1464 numStereo = device->MaxNoOfSources;
1466 numMono = device->MaxNoOfSources - numStereo;
1469 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1470 numSends = attrList[attrIdx + 1];
1472 attrIdx += 2;
1475 if(gotFmt != GotAll)
1477 WARN("Missing format for loopback device\n");
1478 return ALC_INVALID_VALUE;
1481 ConfigValueUInt(NULL, "sends", &numSends);
1482 numSends = minu(MAX_SENDS, numSends);
1484 if((device->Flags&DEVICE_RUNNING))
1485 ALCdevice_StopPlayback(device);
1486 device->Flags &= ~DEVICE_RUNNING;
1488 device->Frequency = freq;
1489 device->FmtChans = schans;
1490 device->FmtType = stype;
1491 device->NumMonoSources = numMono;
1492 device->NumStereoSources = numStereo;
1493 device->NumAuxSends = numSends;
1495 else if(attrList && attrList[0])
1497 ALCuint freq, numMono, numStereo, numSends;
1498 ALCuint attrIdx = 0;
1500 /* If a context is already running on the device, stop playback so the
1501 * device attributes can be updated. */
1502 if((device->Flags&DEVICE_RUNNING))
1503 ALCdevice_StopPlayback(device);
1504 device->Flags &= ~DEVICE_RUNNING;
1506 freq = device->Frequency;
1507 numMono = device->NumMonoSources;
1508 numStereo = device->NumStereoSources;
1509 numSends = device->NumAuxSends;
1511 while(attrList[attrIdx])
1513 if(attrList[attrIdx] == ALC_FREQUENCY)
1515 freq = attrList[attrIdx + 1];
1516 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1519 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1521 numStereo = attrList[attrIdx + 1];
1522 if(numStereo > device->MaxNoOfSources)
1523 numStereo = device->MaxNoOfSources;
1525 numMono = device->MaxNoOfSources - numStereo;
1528 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1529 numSends = attrList[attrIdx + 1];
1531 attrIdx += 2;
1534 ConfigValueUInt(NULL, "frequency", &freq);
1535 freq = maxu(freq, MIN_OUTPUT_RATE);
1537 ConfigValueUInt(NULL, "sends", &numSends);
1538 numSends = minu(MAX_SENDS, numSends);
1540 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1541 device->Frequency;
1543 device->Frequency = freq;
1544 device->NumMonoSources = numMono;
1545 device->NumStereoSources = numStereo;
1546 device->NumAuxSends = numSends;
1549 if((device->Flags&DEVICE_RUNNING))
1550 return ALC_NO_ERROR;
1552 oldFreq = device->Frequency;
1553 oldChans = device->FmtChans;
1554 oldType = device->FmtType;
1556 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1557 DevFmtChannelsString(device->FmtChans),
1558 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
1559 DevFmtTypeString(device->FmtType),
1560 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?" (requested)":"",
1561 device->Frequency,
1562 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
1563 device->UpdateSize, device->NumUpdates);
1565 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1566 return ALC_INVALID_DEVICE;
1568 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1570 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1571 DevFmtChannelsString(device->FmtChans));
1572 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1574 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1576 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1577 DevFmtTypeString(device->FmtType));
1578 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1580 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1582 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1583 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1586 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1587 DevFmtChannelsString(device->FmtChans),
1588 DevFmtTypeString(device->FmtType), device->Frequency,
1589 device->UpdateSize, device->NumUpdates);
1591 aluInitPanning(device);
1593 for(i = 0;i < MaxChannels;i++)
1595 device->ClickRemoval[i] = 0.0f;
1596 device->PendingClicks[i] = 0.0f;
1599 device->Hrtf = NULL;
1600 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1601 device->Hrtf = GetHrtf(device);
1602 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1604 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1606 if(!device->Bs2b)
1608 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1609 bs2b_clear(device->Bs2b);
1611 bs2b_set_srate(device->Bs2b, device->Frequency);
1612 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1613 TRACE("BS2B level %d\n", device->Bs2bLevel);
1615 else
1617 free(device->Bs2b);
1618 device->Bs2b = NULL;
1619 TRACE("BS2B disabled\n");
1622 device->Flags &= ~DEVICE_WIDE_STEREO;
1623 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1624 device->Flags |= DEVICE_WIDE_STEREO;
1626 oldMode = SetMixerFPUMode();
1627 ALCdevice_Lock(device);
1628 context = device->ContextList;
1629 while(context)
1631 ALsizei pos;
1633 context->UpdateSources = AL_FALSE;
1634 LockUIntMapRead(&context->EffectSlotMap);
1635 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1637 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1639 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1641 UnlockUIntMapRead(&context->EffectSlotMap);
1642 ALCdevice_Unlock(device);
1643 RestoreFPUMode(oldMode);
1644 return ALC_INVALID_DEVICE;
1646 slot->NeedsUpdate = AL_FALSE;
1647 ALeffectState_Update(slot->EffectState, device, slot);
1649 UnlockUIntMapRead(&context->EffectSlotMap);
1651 LockUIntMapRead(&context->SourceMap);
1652 for(pos = 0;pos < context->SourceMap.size;pos++)
1654 ALsource *source = context->SourceMap.array[pos].value;
1655 ALuint s = device->NumAuxSends;
1656 while(s < MAX_SENDS)
1658 if(source->Send[s].Slot)
1659 DecrementRef(&source->Send[s].Slot->ref);
1660 source->Send[s].Slot = NULL;
1661 source->Send[s].Gain = 1.0f;
1662 source->Send[s].GainHF = 1.0f;
1663 s++;
1665 source->NeedsUpdate = AL_FALSE;
1666 ALsource_Update(source, context);
1668 UnlockUIntMapRead(&context->SourceMap);
1670 context = context->next;
1672 if(device->DefaultSlot)
1674 ALeffectslot *slot = device->DefaultSlot;
1676 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1678 ALCdevice_Unlock(device);
1679 RestoreFPUMode(oldMode);
1680 return ALC_INVALID_DEVICE;
1682 slot->NeedsUpdate = AL_FALSE;
1683 ALeffectState_Update(slot->EffectState, device, slot);
1685 ALCdevice_Unlock(device);
1686 RestoreFPUMode(oldMode);
1688 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1689 return ALC_INVALID_DEVICE;
1690 device->Flags |= DEVICE_RUNNING;
1692 return ALC_NO_ERROR;
1695 /* FreeDevice
1697 * Frees the device structure, and destroys any objects the app failed to
1698 * delete. Called once there's no more references on the device.
1700 static ALCvoid FreeDevice(ALCdevice *device)
1702 TRACE("%p\n", device);
1704 if(device->Type != Capture)
1705 ALCdevice_ClosePlayback(device);
1706 else
1707 ALCdevice_CloseCapture(device);
1709 if(device->DefaultSlot)
1711 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1712 device->DefaultSlot->EffectState = NULL;
1715 if(device->BufferMap.size > 0)
1717 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1718 ReleaseALBuffers(device);
1720 ResetUIntMap(&device->BufferMap);
1722 if(device->EffectMap.size > 0)
1724 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1725 ReleaseALEffects(device);
1727 ResetUIntMap(&device->EffectMap);
1729 if(device->FilterMap.size > 0)
1731 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1732 ReleaseALFilters(device);
1734 ResetUIntMap(&device->FilterMap);
1736 free(device->Bs2b);
1737 device->Bs2b = NULL;
1739 free(device->DeviceName);
1740 device->DeviceName = NULL;
1742 DeleteCriticalSection(&device->Mutex);
1744 free(device);
1748 void ALCdevice_IncRef(ALCdevice *device)
1750 RefCount ref;
1751 ref = IncrementRef(&device->ref);
1752 TRACEREF("%p increasing refcount to %u\n", device, ref);
1755 void ALCdevice_DecRef(ALCdevice *device)
1757 RefCount ref;
1758 ref = DecrementRef(&device->ref);
1759 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1760 if(ref == 0) FreeDevice(device);
1763 /* VerifyDevice
1765 * Checks if the device handle is valid, and increments its ref count if so.
1767 static ALCdevice *VerifyDevice(ALCdevice *device)
1769 ALCdevice *tmpDevice;
1771 if(!device)
1772 return NULL;
1774 LockLists();
1775 tmpDevice = DeviceList;
1776 while(tmpDevice && tmpDevice != device)
1777 tmpDevice = tmpDevice->next;
1779 if(tmpDevice)
1780 ALCdevice_IncRef(tmpDevice);
1781 UnlockLists();
1782 return tmpDevice;
1786 /* InitContext
1788 * Initializes context fields
1790 static ALvoid InitContext(ALCcontext *Context)
1792 ALint i, j;
1794 //Initialise listener
1795 Context->Listener.Gain = 1.0f;
1796 Context->Listener.MetersPerUnit = 1.0f;
1797 Context->Listener.Position[0] = 0.0f;
1798 Context->Listener.Position[1] = 0.0f;
1799 Context->Listener.Position[2] = 0.0f;
1800 Context->Listener.Velocity[0] = 0.0f;
1801 Context->Listener.Velocity[1] = 0.0f;
1802 Context->Listener.Velocity[2] = 0.0f;
1803 Context->Listener.Forward[0] = 0.0f;
1804 Context->Listener.Forward[1] = 0.0f;
1805 Context->Listener.Forward[2] = -1.0f;
1806 Context->Listener.Up[0] = 0.0f;
1807 Context->Listener.Up[1] = 1.0f;
1808 Context->Listener.Up[2] = 0.0f;
1809 for(i = 0;i < 4;i++)
1811 for(j = 0;j < 4;j++)
1812 Context->Listener.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1815 //Validate Context
1816 Context->LastError = AL_NO_ERROR;
1817 Context->UpdateSources = AL_FALSE;
1818 Context->ActiveSourceCount = 0;
1819 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1820 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1822 //Set globals
1823 Context->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
1824 Context->SourceDistanceModel = AL_FALSE;
1825 Context->DopplerFactor = 1.0f;
1826 Context->DopplerVelocity = 1.0f;
1827 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1828 Context->DeferUpdates = AL_FALSE;
1830 Context->ExtensionList = alExtList;
1834 /* FreeContext
1836 * Cleans up the context, and destroys any remaining objects the app failed to
1837 * delete. Called once there's no more references on the context.
1839 static ALCvoid FreeContext(ALCcontext *context)
1841 TRACE("%p\n", context);
1843 if(context->SourceMap.size > 0)
1845 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1846 ReleaseALSources(context);
1848 ResetUIntMap(&context->SourceMap);
1850 if(context->EffectSlotMap.size > 0)
1852 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1853 ReleaseALAuxiliaryEffectSlots(context);
1855 ResetUIntMap(&context->EffectSlotMap);
1857 context->ActiveSourceCount = 0;
1858 free(context->ActiveSources);
1859 context->ActiveSources = NULL;
1860 context->MaxActiveSources = 0;
1862 context->ActiveEffectSlotCount = 0;
1863 free(context->ActiveEffectSlots);
1864 context->ActiveEffectSlots = NULL;
1865 context->MaxActiveEffectSlots = 0;
1867 ALCdevice_DecRef(context->Device);
1868 context->Device = NULL;
1870 //Invalidate context
1871 memset(context, 0, sizeof(ALCcontext));
1872 free(context);
1875 /* ReleaseContext
1877 * Removes the context reference from the given device and removes it from
1878 * being current on the running thread or globally.
1880 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1882 ALCcontext *volatile*tmp_ctx;
1884 if(pthread_getspecific(LocalContext) == context)
1886 WARN("%p released while current on thread\n", context);
1887 pthread_setspecific(LocalContext, NULL);
1888 ALCcontext_DecRef(context);
1891 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1892 ALCcontext_DecRef(context);
1894 ALCdevice_Lock(device);
1895 tmp_ctx = &device->ContextList;
1896 while(*tmp_ctx)
1898 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1899 break;
1900 tmp_ctx = &(*tmp_ctx)->next;
1902 ALCdevice_Unlock(device);
1904 ALCcontext_DecRef(context);
1907 void ALCcontext_IncRef(ALCcontext *context)
1909 RefCount ref;
1910 ref = IncrementRef(&context->ref);
1911 TRACEREF("%p increasing refcount to %u\n", context, ref);
1914 void ALCcontext_DecRef(ALCcontext *context)
1916 RefCount ref;
1917 ref = DecrementRef(&context->ref);
1918 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1919 if(ref == 0) FreeContext(context);
1922 static void ReleaseThreadCtx(void *ptr)
1924 WARN("%p current for thread being destroyed\n", ptr);
1925 ALCcontext_DecRef(ptr);
1928 /* VerifyContext
1930 * Checks that the given context is valid, and increments its reference count.
1932 static ALCcontext *VerifyContext(ALCcontext *context)
1934 ALCdevice *dev;
1936 LockLists();
1937 dev = DeviceList;
1938 while(dev)
1940 ALCcontext *tmp_ctx = dev->ContextList;
1941 while(tmp_ctx)
1943 if(tmp_ctx == context)
1945 ALCcontext_IncRef(tmp_ctx);
1946 UnlockLists();
1947 return tmp_ctx;
1949 tmp_ctx = tmp_ctx->next;
1951 dev = dev->next;
1953 UnlockLists();
1955 return NULL;
1959 /* GetContextRef
1961 * Returns the currently active context for this thread, and adds a reference
1962 * without locking it.
1964 ALCcontext *GetContextRef(void)
1966 ALCcontext *context;
1968 context = pthread_getspecific(LocalContext);
1969 if(context)
1970 ALCcontext_IncRef(context);
1971 else
1973 LockLists();
1974 context = GlobalContext;
1975 if(context)
1976 ALCcontext_IncRef(context);
1977 UnlockLists();
1980 return context;
1984 /************************************************
1985 * Standard ALC functions
1986 ************************************************/
1988 /* alcGetError
1990 * Return last ALC generated error code for the given device
1992 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
1994 ALCenum errorCode;
1996 if(VerifyDevice(device))
1998 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
1999 ALCdevice_DecRef(device);
2001 else
2002 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2004 return errorCode;
2008 /* alcSuspendContext
2010 * Not functional
2012 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
2014 (void)Context;
2017 /* alcProcessContext
2019 * Not functional
2021 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2023 (void)Context;
2027 /* alcGetString
2029 * Returns information about the device, and error strings
2031 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2033 const ALCchar *value = NULL;
2035 switch(param)
2037 case ALC_NO_ERROR:
2038 value = alcNoError;
2039 break;
2041 case ALC_INVALID_ENUM:
2042 value = alcErrInvalidEnum;
2043 break;
2045 case ALC_INVALID_VALUE:
2046 value = alcErrInvalidValue;
2047 break;
2049 case ALC_INVALID_DEVICE:
2050 value = alcErrInvalidDevice;
2051 break;
2053 case ALC_INVALID_CONTEXT:
2054 value = alcErrInvalidContext;
2055 break;
2057 case ALC_OUT_OF_MEMORY:
2058 value = alcErrOutOfMemory;
2059 break;
2061 case ALC_DEVICE_SPECIFIER:
2062 value = alcDefaultName;
2063 break;
2065 case ALC_ALL_DEVICES_SPECIFIER:
2066 if(VerifyDevice(Device))
2068 value = Device->DeviceName;
2069 ALCdevice_DecRef(Device);
2071 else
2073 ProbeAllDevicesList();
2074 value = alcAllDevicesList;
2076 break;
2078 case ALC_CAPTURE_DEVICE_SPECIFIER:
2079 if(VerifyDevice(Device))
2081 value = Device->DeviceName;
2082 ALCdevice_DecRef(Device);
2084 else
2086 ProbeCaptureDeviceList();
2087 value = alcCaptureDeviceList;
2089 break;
2091 /* Default devices are always first in the list */
2092 case ALC_DEFAULT_DEVICE_SPECIFIER:
2093 value = alcDefaultName;
2094 break;
2096 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2097 if(!alcAllDevicesList)
2098 ProbeAllDevicesList();
2100 Device = VerifyDevice(Device);
2102 free(alcDefaultAllDevicesSpecifier);
2103 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2104 alcAllDevicesList : "");
2105 if(!alcDefaultAllDevicesSpecifier)
2106 alcSetError(Device, ALC_OUT_OF_MEMORY);
2108 value = alcDefaultAllDevicesSpecifier;
2109 if(Device) ALCdevice_DecRef(Device);
2110 break;
2112 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2113 if(!alcCaptureDeviceList)
2114 ProbeCaptureDeviceList();
2116 Device = VerifyDevice(Device);
2118 free(alcCaptureDefaultDeviceSpecifier);
2119 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2120 alcCaptureDeviceList : "");
2121 if(!alcCaptureDefaultDeviceSpecifier)
2122 alcSetError(Device, ALC_OUT_OF_MEMORY);
2124 value = alcCaptureDefaultDeviceSpecifier;
2125 if(Device) ALCdevice_DecRef(Device);
2126 break;
2128 case ALC_EXTENSIONS:
2129 if(!VerifyDevice(Device))
2130 value = alcNoDeviceExtList;
2131 else
2133 value = alcExtensionList;
2134 ALCdevice_DecRef(Device);
2136 break;
2138 default:
2139 Device = VerifyDevice(Device);
2140 alcSetError(Device, ALC_INVALID_ENUM);
2141 if(Device) ALCdevice_DecRef(Device);
2142 break;
2145 return value;
2149 /* alcGetIntegerv
2151 * Returns information about the device and the version of OpenAL
2153 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2155 device = VerifyDevice(device);
2157 if(size == 0 || data == NULL)
2159 alcSetError(device, ALC_INVALID_VALUE);
2160 if(device) ALCdevice_DecRef(device);
2161 return;
2164 if(!device)
2166 switch(param)
2168 case ALC_MAJOR_VERSION:
2169 *data = alcMajorVersion;
2170 break;
2171 case ALC_MINOR_VERSION:
2172 *data = alcMinorVersion;
2173 break;
2175 case ALC_ATTRIBUTES_SIZE:
2176 case ALC_ALL_ATTRIBUTES:
2177 case ALC_FREQUENCY:
2178 case ALC_REFRESH:
2179 case ALC_SYNC:
2180 case ALC_MONO_SOURCES:
2181 case ALC_STEREO_SOURCES:
2182 case ALC_CAPTURE_SAMPLES:
2183 case ALC_FORMAT_CHANNELS_SOFT:
2184 case ALC_FORMAT_TYPE_SOFT:
2185 alcSetError(NULL, ALC_INVALID_DEVICE);
2186 break;
2188 default:
2189 alcSetError(NULL, ALC_INVALID_ENUM);
2190 break;
2193 else if(device->Type == Capture)
2195 switch(param)
2197 case ALC_CAPTURE_SAMPLES:
2198 LockLists();
2199 /* Re-validate the device since it may have been closed */
2200 ALCdevice_DecRef(device);
2201 if((device=VerifyDevice(device)) != NULL)
2202 *data = ALCdevice_AvailableSamples(device);
2203 else
2204 alcSetError(NULL, ALC_INVALID_DEVICE);
2205 UnlockLists();
2206 break;
2208 case ALC_CONNECTED:
2209 *data = device->Connected;
2210 break;
2212 default:
2213 alcSetError(device, ALC_INVALID_ENUM);
2214 break;
2217 else /* render device */
2219 switch(param)
2221 case ALC_MAJOR_VERSION:
2222 *data = alcMajorVersion;
2223 break;
2225 case ALC_MINOR_VERSION:
2226 *data = alcMinorVersion;
2227 break;
2229 case ALC_EFX_MAJOR_VERSION:
2230 *data = alcEFXMajorVersion;
2231 break;
2233 case ALC_EFX_MINOR_VERSION:
2234 *data = alcEFXMinorVersion;
2235 break;
2237 case ALC_ATTRIBUTES_SIZE:
2238 *data = 13;
2239 break;
2241 case ALC_ALL_ATTRIBUTES:
2242 if(size < 13)
2243 alcSetError(device, ALC_INVALID_VALUE);
2244 else
2246 int i = 0;
2248 data[i++] = ALC_FREQUENCY;
2249 data[i++] = device->Frequency;
2251 if(device->Type != Loopback)
2253 data[i++] = ALC_REFRESH;
2254 data[i++] = device->Frequency / device->UpdateSize;
2256 data[i++] = ALC_SYNC;
2257 data[i++] = ALC_FALSE;
2259 else
2261 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2262 data[i++] = device->FmtChans;
2264 data[i++] = ALC_FORMAT_TYPE_SOFT;
2265 data[i++] = device->FmtType;
2268 data[i++] = ALC_MONO_SOURCES;
2269 data[i++] = device->NumMonoSources;
2271 data[i++] = ALC_STEREO_SOURCES;
2272 data[i++] = device->NumStereoSources;
2274 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2275 data[i++] = device->NumAuxSends;
2277 data[i++] = 0;
2279 break;
2281 case ALC_FREQUENCY:
2282 *data = device->Frequency;
2283 break;
2285 case ALC_REFRESH:
2286 if(device->Type == Loopback)
2287 alcSetError(device, ALC_INVALID_DEVICE);
2288 else
2289 *data = device->Frequency / device->UpdateSize;
2290 break;
2292 case ALC_SYNC:
2293 if(device->Type == Loopback)
2294 alcSetError(device, ALC_INVALID_DEVICE);
2295 else
2296 *data = ALC_FALSE;
2297 break;
2299 case ALC_FORMAT_CHANNELS_SOFT:
2300 if(device->Type != Loopback)
2301 alcSetError(device, ALC_INVALID_DEVICE);
2302 else
2303 *data = device->FmtChans;
2304 break;
2306 case ALC_FORMAT_TYPE_SOFT:
2307 if(device->Type != Loopback)
2308 alcSetError(device, ALC_INVALID_DEVICE);
2309 else
2310 *data = device->FmtType;
2311 break;
2313 case ALC_MONO_SOURCES:
2314 *data = device->NumMonoSources;
2315 break;
2317 case ALC_STEREO_SOURCES:
2318 *data = device->NumStereoSources;
2319 break;
2321 case ALC_MAX_AUXILIARY_SENDS:
2322 *data = device->NumAuxSends;
2323 break;
2325 case ALC_CONNECTED:
2326 *data = device->Connected;
2327 break;
2329 default:
2330 alcSetError(device, ALC_INVALID_ENUM);
2331 break;
2334 if(device)
2335 ALCdevice_DecRef(device);
2339 /* alcIsExtensionPresent
2341 * Determines if there is support for a particular extension
2343 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2345 ALCboolean bResult = ALC_FALSE;
2347 device = VerifyDevice(device);
2349 if(!extName)
2350 alcSetError(device, ALC_INVALID_VALUE);
2351 else
2353 size_t len = strlen(extName);
2354 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2355 while(ptr && *ptr)
2357 if(strncasecmp(ptr, extName, len) == 0 &&
2358 (ptr[len] == '\0' || isspace(ptr[len])))
2360 bResult = ALC_TRUE;
2361 break;
2363 if((ptr=strchr(ptr, ' ')) != NULL)
2365 do {
2366 ++ptr;
2367 } while(isspace(*ptr));
2371 if(device)
2372 ALCdevice_DecRef(device);
2373 return bResult;
2377 /* alcGetProcAddress
2379 * Retrieves the function address for a particular extension function
2381 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2383 ALCvoid *ptr = NULL;
2385 if(!funcName)
2387 device = VerifyDevice(device);
2388 alcSetError(device, ALC_INVALID_VALUE);
2389 if(device) ALCdevice_DecRef(device);
2391 else
2393 ALsizei i = 0;
2394 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2395 i++;
2396 ptr = alcFunctions[i].address;
2399 return ptr;
2403 /* alcGetEnumValue
2405 * Get the value for a particular ALC enumeration name
2407 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2409 ALCenum val = 0;
2411 if(!enumName)
2413 device = VerifyDevice(device);
2414 alcSetError(device, ALC_INVALID_VALUE);
2415 if(device) ALCdevice_DecRef(device);
2417 else
2419 ALsizei i = 0;
2420 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2421 i++;
2422 val = enumeration[i].value;
2425 return val;
2429 /* alcCreateContext
2431 * Create and attach a context to the given device.
2433 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2435 ALCcontext *ALContext;
2436 ALCenum err;
2438 LockLists();
2439 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2441 UnlockLists();
2442 alcSetError(device, ALC_INVALID_DEVICE);
2443 if(device) ALCdevice_DecRef(device);
2444 return NULL;
2447 device->LastError = ALC_NO_ERROR;
2449 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2451 UnlockLists();
2452 alcSetError(device, err);
2453 if(err == ALC_INVALID_DEVICE)
2454 aluHandleDisconnect(device);
2455 ALCdevice_DecRef(device);
2456 return NULL;
2459 ALContext = calloc(1, sizeof(ALCcontext));
2460 if(ALContext)
2462 ALContext->ref = 1;
2464 ALContext->MaxActiveSources = 256;
2465 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2466 ALContext->MaxActiveSources);
2468 if(!ALContext || !ALContext->ActiveSources)
2470 if(!device->ContextList)
2472 ALCdevice_StopPlayback(device);
2473 device->Flags &= ~DEVICE_RUNNING;
2475 UnlockLists();
2477 free(ALContext);
2478 ALContext = NULL;
2480 alcSetError(device, ALC_OUT_OF_MEMORY);
2481 ALCdevice_DecRef(device);
2482 return NULL;
2485 ALContext->Device = device;
2486 ALCdevice_IncRef(device);
2487 InitContext(ALContext);
2489 do {
2490 ALContext->next = device->ContextList;
2491 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2492 UnlockLists();
2494 ALCdevice_DecRef(device);
2496 TRACE("Created context %p\n", ALContext);
2497 return ALContext;
2500 /* alcDestroyContext
2502 * Remove a context from its device
2504 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2506 ALCdevice *Device;
2508 LockLists();
2509 /* alcGetContextsDevice sets an error for invalid contexts */
2510 Device = alcGetContextsDevice(context);
2511 if(Device)
2513 ReleaseContext(context, Device);
2514 if(!Device->ContextList)
2516 ALCdevice_StopPlayback(Device);
2517 Device->Flags &= ~DEVICE_RUNNING;
2520 UnlockLists();
2524 /* alcGetCurrentContext
2526 * Returns the currently active context on the calling thread
2528 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2530 ALCcontext *Context;
2532 Context = pthread_getspecific(LocalContext);
2533 if(!Context) Context = GlobalContext;
2535 return Context;
2538 /* alcGetThreadContext
2540 * Returns the currently active thread-local context
2542 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2544 ALCcontext *Context;
2545 Context = pthread_getspecific(LocalContext);
2546 return Context;
2550 /* alcMakeContextCurrent
2552 * Makes the given context the active process-wide context, and removes the
2553 * thread-local context for the calling thread.
2555 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2557 /* context must be valid or NULL */
2558 if(context && !(context=VerifyContext(context)))
2560 alcSetError(NULL, ALC_INVALID_CONTEXT);
2561 return ALC_FALSE;
2563 /* context's reference count is already incremented */
2564 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2565 if(context) ALCcontext_DecRef(context);
2567 if((context=pthread_getspecific(LocalContext)) != NULL)
2569 pthread_setspecific(LocalContext, NULL);
2570 ALCcontext_DecRef(context);
2573 return ALC_TRUE;
2576 /* alcSetThreadContext
2578 * Makes the given context the active context for the current thread
2580 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2582 ALCcontext *old;
2584 /* context must be valid or NULL */
2585 if(context && !(context=VerifyContext(context)))
2587 alcSetError(NULL, ALC_INVALID_CONTEXT);
2588 return ALC_FALSE;
2590 /* context's reference count is already incremented */
2591 old = pthread_getspecific(LocalContext);
2592 pthread_setspecific(LocalContext, context);
2593 if(old) ALCcontext_DecRef(old);
2595 return ALC_TRUE;
2599 /* alcGetContextsDevice
2601 * Returns the device that a particular context is attached to
2603 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2605 ALCdevice *Device;
2607 if(!(Context=VerifyContext(Context)))
2609 alcSetError(NULL, ALC_INVALID_CONTEXT);
2610 return NULL;
2612 Device = Context->Device;
2613 ALCcontext_DecRef(Context);
2615 return Device;
2619 /* alcOpenDevice
2621 * Opens the named device.
2623 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2625 const ALCchar *fmt;
2626 ALCdevice *device;
2627 ALCenum err;
2629 DO_INITCONFIG();
2631 if(!PlaybackBackend.name)
2633 alcSetError(NULL, ALC_INVALID_VALUE);
2634 return NULL;
2637 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2638 deviceName = NULL;
2640 device = calloc(1, sizeof(ALCdevice)+sizeof(ALeffectslot));
2641 if(!device)
2643 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2644 return NULL;
2647 //Validate device
2648 device->Funcs = &PlaybackBackend.Funcs;
2649 device->ref = 1;
2650 device->Connected = ALC_TRUE;
2651 device->Type = Playback;
2652 InitializeCriticalSection(&device->Mutex);
2653 device->LastError = ALC_NO_ERROR;
2655 device->Flags = 0;
2656 device->Bs2b = NULL;
2657 device->Bs2bLevel = 0;
2658 device->DeviceName = NULL;
2660 device->ContextList = NULL;
2662 device->MaxNoOfSources = 256;
2663 device->AuxiliaryEffectSlotMax = 4;
2664 device->NumAuxSends = MAX_SENDS;
2666 InitUIntMap(&device->BufferMap, ~0);
2667 InitUIntMap(&device->EffectMap, ~0);
2668 InitUIntMap(&device->FilterMap, ~0);
2670 //Set output format
2671 device->FmtChans = DevFmtChannelsDefault;
2672 device->FmtType = DevFmtTypeDefault;
2673 device->Frequency = DEFAULT_OUTPUT_RATE;
2674 device->NumUpdates = 4;
2675 device->UpdateSize = 1024;
2677 if(ConfigValueStr(NULL, "channels", &fmt))
2679 static const struct {
2680 const char name[16];
2681 enum DevFmtChannels chans;
2682 } chanlist[] = {
2683 { "mono", DevFmtMono },
2684 { "stereo", DevFmtStereo },
2685 { "quad", DevFmtQuad },
2686 { "surround51", DevFmtX51 },
2687 { "surround61", DevFmtX61 },
2688 { "surround71", DevFmtX71 },
2690 size_t i;
2692 for(i = 0;i < COUNTOF(chanlist);i++)
2694 if(strcasecmp(chanlist[i].name, fmt) == 0)
2696 device->FmtChans = chanlist[i].chans;
2697 device->Flags |= DEVICE_CHANNELS_REQUEST;
2698 break;
2701 if(i == COUNTOF(chanlist))
2702 ERR("Unsupported channels: %s\n", fmt);
2704 if(ConfigValueStr(NULL, "sample-type", &fmt))
2706 static const struct {
2707 const char name[16];
2708 enum DevFmtType type;
2709 } typelist[] = {
2710 { "int8", DevFmtByte },
2711 { "uint8", DevFmtUByte },
2712 { "int16", DevFmtShort },
2713 { "uint16", DevFmtUShort },
2714 { "int32", DevFmtInt },
2715 { "uint32", DevFmtUInt },
2716 { "float32", DevFmtFloat },
2718 size_t i;
2720 for(i = 0;i < COUNTOF(typelist);i++)
2722 if(strcasecmp(typelist[i].name, fmt) == 0)
2724 device->FmtType = typelist[i].type;
2725 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2726 break;
2729 if(i == COUNTOF(typelist))
2730 ERR("Unsupported sample-type: %s\n", fmt);
2732 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2733 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2734 ConfigValueStr(NULL, "format", &fmt))
2736 static const struct {
2737 const char name[32];
2738 enum DevFmtChannels channels;
2739 enum DevFmtType type;
2740 } formats[] = {
2741 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2742 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2743 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2744 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2745 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2746 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2748 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2749 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2750 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2751 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2752 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2753 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2755 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2756 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2757 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2758 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2759 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2760 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2762 size_t i;
2764 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2765 for(i = 0;i < COUNTOF(formats);i++)
2767 if(strcasecmp(fmt, formats[i].name) == 0)
2769 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2770 device->FmtChans = formats[i].channels;
2771 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2772 device->FmtType = formats[i].type;
2773 device->Flags |= DEVICE_FORMAT_REQUEST;
2774 break;
2777 if(i == COUNTOF(formats))
2778 ERR("Unsupported format: %s\n", fmt);
2780 #undef DEVICE_FORMAT_REQUEST
2782 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2784 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2785 if(device->Frequency < MIN_OUTPUT_RATE)
2786 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2787 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2790 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2791 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2793 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2794 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2796 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2797 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2799 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2800 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2802 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2803 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2805 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2807 device->NumStereoSources = 1;
2808 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2810 // Find a playback device to open
2811 LockLists();
2812 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2814 UnlockLists();
2815 DeleteCriticalSection(&device->Mutex);
2816 free(device);
2817 alcSetError(NULL, err);
2818 return NULL;
2820 UnlockLists();
2822 if(DefaultEffect.type != AL_EFFECT_NULL)
2824 device->DefaultSlot = (ALeffectslot*)(device+1);
2825 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2827 device->DefaultSlot = NULL;
2828 ERR("Failed to initialize the default effect slot\n");
2830 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2832 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2833 device->DefaultSlot = NULL;
2834 ERR("Failed to initialize the default effect\n");
2838 do {
2839 device->next = DeviceList;
2840 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2842 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2843 return device;
2846 /* alcCloseDevice
2848 * Closes the given device.
2850 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2852 ALCdevice *volatile*list;
2853 ALCcontext *ctx;
2855 LockLists();
2856 list = &DeviceList;
2857 while(*list && *list != Device)
2858 list = &(*list)->next;
2860 if(!*list || (*list)->Type == Capture)
2862 alcSetError(*list, ALC_INVALID_DEVICE);
2863 UnlockLists();
2864 return ALC_FALSE;
2867 *list = (*list)->next;
2868 UnlockLists();
2870 while((ctx=Device->ContextList) != NULL)
2872 WARN("Releasing context %p\n", ctx);
2873 ReleaseContext(ctx, Device);
2875 if((Device->Flags&DEVICE_RUNNING))
2876 ALCdevice_StopPlayback(Device);
2877 Device->Flags &= ~DEVICE_RUNNING;
2879 ALCdevice_DecRef(Device);
2881 return ALC_TRUE;
2885 /************************************************
2886 * ALC capture functions
2887 ************************************************/
2888 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2890 ALCdevice *device = NULL;
2891 ALCenum err;
2893 DO_INITCONFIG();
2895 if(!CaptureBackend.name)
2897 alcSetError(NULL, ALC_INVALID_VALUE);
2898 return NULL;
2901 if(samples <= 0)
2903 alcSetError(NULL, ALC_INVALID_VALUE);
2904 return NULL;
2907 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2908 deviceName = NULL;
2910 device = calloc(1, sizeof(ALCdevice));
2911 if(!device)
2913 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2914 return NULL;
2917 //Validate device
2918 device->Funcs = &CaptureBackend.Funcs;
2919 device->ref = 1;
2920 device->Connected = ALC_TRUE;
2921 device->Type = Capture;
2922 InitializeCriticalSection(&device->Mutex);
2924 InitUIntMap(&device->BufferMap, ~0);
2925 InitUIntMap(&device->EffectMap, ~0);
2926 InitUIntMap(&device->FilterMap, ~0);
2928 device->DeviceName = NULL;
2930 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2931 device->Frequency = frequency;
2933 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2934 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2936 DeleteCriticalSection(&device->Mutex);
2937 free(device);
2938 alcSetError(NULL, ALC_INVALID_ENUM);
2939 return NULL;
2942 device->UpdateSize = samples;
2943 device->NumUpdates = 1;
2945 LockLists();
2946 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2948 UnlockLists();
2949 DeleteCriticalSection(&device->Mutex);
2950 free(device);
2951 alcSetError(NULL, err);
2952 return NULL;
2954 UnlockLists();
2956 do {
2957 device->next = DeviceList;
2958 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2960 TRACE("Created device %p\n", device);
2961 return device;
2964 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2966 ALCdevice *volatile*list;
2968 LockLists();
2969 list = &DeviceList;
2970 while(*list && *list != Device)
2971 list = &(*list)->next;
2973 if(!*list || (*list)->Type != Capture)
2975 alcSetError(*list, ALC_INVALID_DEVICE);
2976 UnlockLists();
2977 return ALC_FALSE;
2980 *list = (*list)->next;
2981 UnlockLists();
2983 ALCdevice_DecRef(Device);
2985 return ALC_TRUE;
2988 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
2990 LockLists();
2991 if(!(device=VerifyDevice(device)) || device->Type != Capture)
2993 UnlockLists();
2994 alcSetError(device, ALC_INVALID_DEVICE);
2995 if(device) ALCdevice_DecRef(device);
2996 return;
2998 if(device->Connected)
3000 if(!(device->Flags&DEVICE_RUNNING))
3001 ALCdevice_StartCapture(device);
3002 device->Flags |= DEVICE_RUNNING;
3004 UnlockLists();
3006 ALCdevice_DecRef(device);
3009 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3011 LockLists();
3012 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3014 UnlockLists();
3015 alcSetError(device, ALC_INVALID_DEVICE);
3016 if(device) ALCdevice_DecRef(device);
3017 return;
3019 if((device->Flags&DEVICE_RUNNING))
3020 ALCdevice_StopCapture(device);
3021 device->Flags &= ~DEVICE_RUNNING;
3022 UnlockLists();
3024 ALCdevice_DecRef(device);
3027 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3029 ALCenum err = ALC_INVALID_DEVICE;
3030 LockLists();
3031 if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
3033 err = ALC_INVALID_VALUE;
3034 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3035 err = ALCdevice_CaptureSamples(device, buffer, samples);
3037 UnlockLists();
3038 if(err != ALC_NO_ERROR)
3039 alcSetError(device, err);
3040 if(device) ALCdevice_DecRef(device);
3044 /************************************************
3045 * ALC loopback functions
3046 ************************************************/
3048 /* alcLoopbackOpenDeviceSOFT
3050 * Open a loopback device, for manual rendering.
3052 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3054 ALCdevice *device;
3056 DO_INITCONFIG();
3058 /* Make sure the device name, if specified, is us. */
3059 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3061 alcSetError(NULL, ALC_INVALID_VALUE);
3062 return NULL;
3065 device = calloc(1, sizeof(ALCdevice));
3066 if(!device)
3068 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3069 return NULL;
3072 //Validate device
3073 device->Funcs = &BackendLoopback.Funcs;
3074 device->ref = 1;
3075 device->Connected = ALC_TRUE;
3076 device->Type = Loopback;
3077 InitializeCriticalSection(&device->Mutex);
3078 device->LastError = ALC_NO_ERROR;
3080 device->Flags = 0;
3081 device->Bs2b = NULL;
3082 device->Bs2bLevel = 0;
3083 device->DeviceName = NULL;
3085 device->ContextList = NULL;
3087 device->MaxNoOfSources = 256;
3088 device->AuxiliaryEffectSlotMax = 4;
3089 device->NumAuxSends = MAX_SENDS;
3091 InitUIntMap(&device->BufferMap, ~0);
3092 InitUIntMap(&device->EffectMap, ~0);
3093 InitUIntMap(&device->FilterMap, ~0);
3095 //Set output format
3096 device->NumUpdates = 0;
3097 device->UpdateSize = 0;
3099 device->Frequency = DEFAULT_OUTPUT_RATE;
3100 device->FmtChans = DevFmtChannelsDefault;
3101 device->FmtType = DevFmtTypeDefault;
3103 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3104 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3106 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3107 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3109 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3110 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3112 device->NumStereoSources = 1;
3113 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3115 // Open the "backend"
3116 ALCdevice_OpenPlayback(device, "Loopback");
3117 do {
3118 device->next = DeviceList;
3119 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3121 TRACE("Created device %p\n", device);
3122 return device;
3125 /* alcIsRenderFormatSupportedSOFT
3127 * Determines if the loopback device supports the given format for rendering.
3129 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3131 ALCboolean ret = ALC_FALSE;
3133 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3134 alcSetError(device, ALC_INVALID_DEVICE);
3135 else if(freq <= 0)
3136 alcSetError(device, ALC_INVALID_VALUE);
3137 else
3139 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3140 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3141 freq >= MIN_OUTPUT_RATE)
3142 ret = ALC_TRUE;
3144 if(device) ALCdevice_DecRef(device);
3146 return ret;
3149 /* alcRenderSamplesSOFT
3151 * Renders some samples into a buffer, using the format last set by the
3152 * attributes given to alcCreateContext.
3154 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3156 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3157 alcSetError(device, ALC_INVALID_DEVICE);
3158 else if(samples < 0 || (samples > 0 && buffer == NULL))
3159 alcSetError(device, ALC_INVALID_VALUE);
3160 else
3161 aluMixData(device, buffer, samples);
3162 if(device) ALCdevice_DecRef(device);