Use an asterisk to denote a requested format option in the trace
[openal-soft.git] / Alc / ALc.c
blobcdb8ed6f2362c7b221ddb1e837095fd3c4b3f450
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 "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "bs2b.h"
39 #include "alu.h"
42 /************************************************
43 * Backends
44 ************************************************/
45 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
46 static struct BackendInfo BackendList[] = {
47 #ifdef HAVE_PULSEAUDIO
48 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
49 #endif
50 #ifdef HAVE_ALSA
51 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
52 #endif
53 #ifdef HAVE_COREAUDIO
54 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
55 #endif
56 #ifdef HAVE_OSS
57 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
58 #endif
59 #ifdef HAVE_SOLARIS
60 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
61 #endif
62 #ifdef HAVE_SNDIO
63 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
64 #endif
65 #ifdef HAVE_MMDEVAPI
66 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
67 #endif
68 #ifdef HAVE_DSOUND
69 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
70 #endif
71 #ifdef HAVE_WINMM
72 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
73 #endif
74 #ifdef HAVE_PORTAUDIO
75 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
76 #endif
77 #ifdef HAVE_OPENSL
78 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
79 #endif
81 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
82 #ifdef HAVE_WAVE
83 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
84 #endif
86 { NULL, NULL, NULL, NULL, EmptyFuncs }
88 static struct BackendInfo BackendLoopback = {
89 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
91 #undef EmptyFuncs
93 static struct BackendInfo PlaybackBackend;
94 static struct BackendInfo CaptureBackend;
96 /************************************************
97 * Functions, enums, and errors
98 ************************************************/
99 typedef struct ALCfunction {
100 const ALCchar *funcName;
101 ALCvoid *address;
102 } ALCfunction;
104 typedef struct ALCenums {
105 const ALCchar *enumName;
106 ALCenum value;
107 } ALCenums;
109 #define DECL(x) { #x, (ALCvoid*)(x) }
110 static const ALCfunction alcFunctions[] = {
111 DECL(alcCreateContext),
112 DECL(alcMakeContextCurrent),
113 DECL(alcProcessContext),
114 DECL(alcSuspendContext),
115 DECL(alcDestroyContext),
116 DECL(alcGetCurrentContext),
117 DECL(alcGetContextsDevice),
118 DECL(alcOpenDevice),
119 DECL(alcCloseDevice),
120 DECL(alcGetError),
121 DECL(alcIsExtensionPresent),
122 DECL(alcGetProcAddress),
123 DECL(alcGetEnumValue),
124 DECL(alcGetString),
125 DECL(alcGetIntegerv),
126 DECL(alcCaptureOpenDevice),
127 DECL(alcCaptureCloseDevice),
128 DECL(alcCaptureStart),
129 DECL(alcCaptureStop),
130 DECL(alcCaptureSamples),
132 DECL(alcSetThreadContext),
133 DECL(alcGetThreadContext),
135 DECL(alcLoopbackOpenDeviceSOFT),
136 DECL(alcIsRenderFormatSupportedSOFT),
137 DECL(alcRenderSamplesSOFT),
139 DECL(alEnable),
140 DECL(alDisable),
141 DECL(alIsEnabled),
142 DECL(alGetString),
143 DECL(alGetBooleanv),
144 DECL(alGetIntegerv),
145 DECL(alGetFloatv),
146 DECL(alGetDoublev),
147 DECL(alGetBoolean),
148 DECL(alGetInteger),
149 DECL(alGetFloat),
150 DECL(alGetDouble),
151 DECL(alGetError),
152 DECL(alIsExtensionPresent),
153 DECL(alGetProcAddress),
154 DECL(alGetEnumValue),
155 DECL(alListenerf),
156 DECL(alListener3f),
157 DECL(alListenerfv),
158 DECL(alListeneri),
159 DECL(alListener3i),
160 DECL(alListeneriv),
161 DECL(alGetListenerf),
162 DECL(alGetListener3f),
163 DECL(alGetListenerfv),
164 DECL(alGetListeneri),
165 DECL(alGetListener3i),
166 DECL(alGetListeneriv),
167 DECL(alGenSources),
168 DECL(alDeleteSources),
169 DECL(alIsSource),
170 DECL(alSourcef),
171 DECL(alSource3f),
172 DECL(alSourcefv),
173 DECL(alSourcei),
174 DECL(alSource3i),
175 DECL(alSourceiv),
176 DECL(alGetSourcef),
177 DECL(alGetSource3f),
178 DECL(alGetSourcefv),
179 DECL(alGetSourcei),
180 DECL(alGetSource3i),
181 DECL(alGetSourceiv),
182 DECL(alSourcePlayv),
183 DECL(alSourceStopv),
184 DECL(alSourceRewindv),
185 DECL(alSourcePausev),
186 DECL(alSourcePlay),
187 DECL(alSourceStop),
188 DECL(alSourceRewind),
189 DECL(alSourcePause),
190 DECL(alSourceQueueBuffers),
191 DECL(alSourceUnqueueBuffers),
192 DECL(alGenBuffers),
193 DECL(alDeleteBuffers),
194 DECL(alIsBuffer),
195 DECL(alBufferData),
196 DECL(alBufferf),
197 DECL(alBuffer3f),
198 DECL(alBufferfv),
199 DECL(alBufferi),
200 DECL(alBuffer3i),
201 DECL(alBufferiv),
202 DECL(alGetBufferf),
203 DECL(alGetBuffer3f),
204 DECL(alGetBufferfv),
205 DECL(alGetBufferi),
206 DECL(alGetBuffer3i),
207 DECL(alGetBufferiv),
208 DECL(alDopplerFactor),
209 DECL(alDopplerVelocity),
210 DECL(alSpeedOfSound),
211 DECL(alDistanceModel),
213 DECL(alGenFilters),
214 DECL(alDeleteFilters),
215 DECL(alIsFilter),
216 DECL(alFilteri),
217 DECL(alFilteriv),
218 DECL(alFilterf),
219 DECL(alFilterfv),
220 DECL(alGetFilteri),
221 DECL(alGetFilteriv),
222 DECL(alGetFilterf),
223 DECL(alGetFilterfv),
224 DECL(alGenEffects),
225 DECL(alDeleteEffects),
226 DECL(alIsEffect),
227 DECL(alEffecti),
228 DECL(alEffectiv),
229 DECL(alEffectf),
230 DECL(alEffectfv),
231 DECL(alGetEffecti),
232 DECL(alGetEffectiv),
233 DECL(alGetEffectf),
234 DECL(alGetEffectfv),
235 DECL(alGenAuxiliaryEffectSlots),
236 DECL(alDeleteAuxiliaryEffectSlots),
237 DECL(alIsAuxiliaryEffectSlot),
238 DECL(alAuxiliaryEffectSloti),
239 DECL(alAuxiliaryEffectSlotiv),
240 DECL(alAuxiliaryEffectSlotf),
241 DECL(alAuxiliaryEffectSlotfv),
242 DECL(alGetAuxiliaryEffectSloti),
243 DECL(alGetAuxiliaryEffectSlotiv),
244 DECL(alGetAuxiliaryEffectSlotf),
245 DECL(alGetAuxiliaryEffectSlotfv),
247 DECL(alBufferSubDataSOFT),
249 DECL(alBufferSamplesSOFT),
250 DECL(alBufferSubSamplesSOFT),
251 DECL(alGetBufferSamplesSOFT),
252 DECL(alIsBufferFormatSupportedSOFT),
254 DECL(alDeferUpdatesSOFT),
255 DECL(alProcessUpdatesSOFT),
257 DECL(alSourcedSOFT),
258 DECL(alSource3dSOFT),
259 DECL(alSourcedvSOFT),
260 DECL(alGetSourcedSOFT),
261 DECL(alGetSource3dSOFT),
262 DECL(alGetSourcedvSOFT),
263 DECL(alSourcei64SOFT),
264 DECL(alSource3i64SOFT),
265 DECL(alSourcei64vSOFT),
266 DECL(alGetSourcei64SOFT),
267 DECL(alGetSource3i64SOFT),
268 DECL(alGetSourcei64vSOFT),
270 { NULL, NULL }
272 #undef DECL
274 #define DECL(x) { #x, (x) }
275 static const ALCenums enumeration[] = {
276 DECL(ALC_INVALID),
277 DECL(ALC_FALSE),
278 DECL(ALC_TRUE),
280 DECL(ALC_MAJOR_VERSION),
281 DECL(ALC_MINOR_VERSION),
282 DECL(ALC_ATTRIBUTES_SIZE),
283 DECL(ALC_ALL_ATTRIBUTES),
284 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
285 DECL(ALC_DEVICE_SPECIFIER),
286 DECL(ALC_ALL_DEVICES_SPECIFIER),
287 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
288 DECL(ALC_EXTENSIONS),
289 DECL(ALC_FREQUENCY),
290 DECL(ALC_REFRESH),
291 DECL(ALC_SYNC),
292 DECL(ALC_MONO_SOURCES),
293 DECL(ALC_STEREO_SOURCES),
294 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
295 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
296 DECL(ALC_CAPTURE_SAMPLES),
297 DECL(ALC_CONNECTED),
299 DECL(ALC_EFX_MAJOR_VERSION),
300 DECL(ALC_EFX_MINOR_VERSION),
301 DECL(ALC_MAX_AUXILIARY_SENDS),
303 DECL(ALC_FORMAT_CHANNELS_SOFT),
304 DECL(ALC_FORMAT_TYPE_SOFT),
306 DECL(ALC_MONO_SOFT),
307 DECL(ALC_STEREO_SOFT),
308 DECL(ALC_QUAD_SOFT),
309 DECL(ALC_5POINT1_SOFT),
310 DECL(ALC_6POINT1_SOFT),
311 DECL(ALC_7POINT1_SOFT),
313 DECL(ALC_BYTE_SOFT),
314 DECL(ALC_UNSIGNED_BYTE_SOFT),
315 DECL(ALC_SHORT_SOFT),
316 DECL(ALC_UNSIGNED_SHORT_SOFT),
317 DECL(ALC_INT_SOFT),
318 DECL(ALC_UNSIGNED_INT_SOFT),
319 DECL(ALC_FLOAT_SOFT),
321 DECL(ALC_NO_ERROR),
322 DECL(ALC_INVALID_DEVICE),
323 DECL(ALC_INVALID_CONTEXT),
324 DECL(ALC_INVALID_ENUM),
325 DECL(ALC_INVALID_VALUE),
326 DECL(ALC_OUT_OF_MEMORY),
329 DECL(AL_INVALID),
330 DECL(AL_NONE),
331 DECL(AL_FALSE),
332 DECL(AL_TRUE),
334 DECL(AL_SOURCE_RELATIVE),
335 DECL(AL_CONE_INNER_ANGLE),
336 DECL(AL_CONE_OUTER_ANGLE),
337 DECL(AL_PITCH),
338 DECL(AL_POSITION),
339 DECL(AL_DIRECTION),
340 DECL(AL_VELOCITY),
341 DECL(AL_LOOPING),
342 DECL(AL_BUFFER),
343 DECL(AL_GAIN),
344 DECL(AL_MIN_GAIN),
345 DECL(AL_MAX_GAIN),
346 DECL(AL_ORIENTATION),
347 DECL(AL_REFERENCE_DISTANCE),
348 DECL(AL_ROLLOFF_FACTOR),
349 DECL(AL_CONE_OUTER_GAIN),
350 DECL(AL_MAX_DISTANCE),
351 DECL(AL_SEC_OFFSET),
352 DECL(AL_SAMPLE_OFFSET),
353 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
354 DECL(AL_BYTE_OFFSET),
355 DECL(AL_BYTE_RW_OFFSETS_SOFT),
356 DECL(AL_SOURCE_TYPE),
357 DECL(AL_STATIC),
358 DECL(AL_STREAMING),
359 DECL(AL_UNDETERMINED),
360 DECL(AL_METERS_PER_UNIT),
361 DECL(AL_DIRECT_CHANNELS_SOFT),
363 DECL(AL_DIRECT_FILTER),
364 DECL(AL_AUXILIARY_SEND_FILTER),
365 DECL(AL_AIR_ABSORPTION_FACTOR),
366 DECL(AL_ROOM_ROLLOFF_FACTOR),
367 DECL(AL_CONE_OUTER_GAINHF),
368 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
369 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
370 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
372 DECL(AL_SOURCE_STATE),
373 DECL(AL_INITIAL),
374 DECL(AL_PLAYING),
375 DECL(AL_PAUSED),
376 DECL(AL_STOPPED),
378 DECL(AL_BUFFERS_QUEUED),
379 DECL(AL_BUFFERS_PROCESSED),
381 DECL(AL_FORMAT_MONO8),
382 DECL(AL_FORMAT_MONO16),
383 DECL(AL_FORMAT_MONO_FLOAT32),
384 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
385 DECL(AL_FORMAT_STEREO8),
386 DECL(AL_FORMAT_STEREO16),
387 DECL(AL_FORMAT_STEREO_FLOAT32),
388 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
389 DECL(AL_FORMAT_MONO_IMA4),
390 DECL(AL_FORMAT_STEREO_IMA4),
391 DECL(AL_FORMAT_QUAD8_LOKI),
392 DECL(AL_FORMAT_QUAD16_LOKI),
393 DECL(AL_FORMAT_QUAD8),
394 DECL(AL_FORMAT_QUAD16),
395 DECL(AL_FORMAT_QUAD32),
396 DECL(AL_FORMAT_51CHN8),
397 DECL(AL_FORMAT_51CHN16),
398 DECL(AL_FORMAT_51CHN32),
399 DECL(AL_FORMAT_61CHN8),
400 DECL(AL_FORMAT_61CHN16),
401 DECL(AL_FORMAT_61CHN32),
402 DECL(AL_FORMAT_71CHN8),
403 DECL(AL_FORMAT_71CHN16),
404 DECL(AL_FORMAT_71CHN32),
405 DECL(AL_FORMAT_REAR8),
406 DECL(AL_FORMAT_REAR16),
407 DECL(AL_FORMAT_REAR32),
408 DECL(AL_FORMAT_MONO_MULAW),
409 DECL(AL_FORMAT_MONO_MULAW_EXT),
410 DECL(AL_FORMAT_STEREO_MULAW),
411 DECL(AL_FORMAT_STEREO_MULAW_EXT),
412 DECL(AL_FORMAT_QUAD_MULAW),
413 DECL(AL_FORMAT_51CHN_MULAW),
414 DECL(AL_FORMAT_61CHN_MULAW),
415 DECL(AL_FORMAT_71CHN_MULAW),
416 DECL(AL_FORMAT_REAR_MULAW),
417 DECL(AL_FORMAT_MONO_ALAW_EXT),
418 DECL(AL_FORMAT_STEREO_ALAW_EXT),
420 DECL(AL_MONO8_SOFT),
421 DECL(AL_MONO16_SOFT),
422 DECL(AL_MONO32F_SOFT),
423 DECL(AL_STEREO8_SOFT),
424 DECL(AL_STEREO16_SOFT),
425 DECL(AL_STEREO32F_SOFT),
426 DECL(AL_QUAD8_SOFT),
427 DECL(AL_QUAD16_SOFT),
428 DECL(AL_QUAD32F_SOFT),
429 DECL(AL_REAR8_SOFT),
430 DECL(AL_REAR16_SOFT),
431 DECL(AL_REAR32F_SOFT),
432 DECL(AL_5POINT1_8_SOFT),
433 DECL(AL_5POINT1_16_SOFT),
434 DECL(AL_5POINT1_32F_SOFT),
435 DECL(AL_6POINT1_8_SOFT),
436 DECL(AL_6POINT1_16_SOFT),
437 DECL(AL_6POINT1_32F_SOFT),
438 DECL(AL_7POINT1_8_SOFT),
439 DECL(AL_7POINT1_16_SOFT),
440 DECL(AL_7POINT1_32F_SOFT),
442 DECL(AL_MONO_SOFT),
443 DECL(AL_STEREO_SOFT),
444 DECL(AL_QUAD_SOFT),
445 DECL(AL_REAR_SOFT),
446 DECL(AL_5POINT1_SOFT),
447 DECL(AL_6POINT1_SOFT),
448 DECL(AL_7POINT1_SOFT),
450 DECL(AL_BYTE_SOFT),
451 DECL(AL_UNSIGNED_BYTE_SOFT),
452 DECL(AL_SHORT_SOFT),
453 DECL(AL_UNSIGNED_SHORT_SOFT),
454 DECL(AL_INT_SOFT),
455 DECL(AL_UNSIGNED_INT_SOFT),
456 DECL(AL_FLOAT_SOFT),
457 DECL(AL_DOUBLE_SOFT),
458 DECL(AL_BYTE3_SOFT),
459 DECL(AL_UNSIGNED_BYTE3_SOFT),
461 DECL(AL_FREQUENCY),
462 DECL(AL_BITS),
463 DECL(AL_CHANNELS),
464 DECL(AL_SIZE),
465 DECL(AL_INTERNAL_FORMAT_SOFT),
466 DECL(AL_BYTE_LENGTH_SOFT),
467 DECL(AL_SAMPLE_LENGTH_SOFT),
468 DECL(AL_SEC_LENGTH_SOFT),
470 DECL(AL_UNUSED),
471 DECL(AL_PENDING),
472 DECL(AL_PROCESSED),
474 DECL(AL_NO_ERROR),
475 DECL(AL_INVALID_NAME),
476 DECL(AL_INVALID_ENUM),
477 DECL(AL_INVALID_VALUE),
478 DECL(AL_INVALID_OPERATION),
479 DECL(AL_OUT_OF_MEMORY),
481 DECL(AL_VENDOR),
482 DECL(AL_VERSION),
483 DECL(AL_RENDERER),
484 DECL(AL_EXTENSIONS),
486 DECL(AL_DOPPLER_FACTOR),
487 DECL(AL_DOPPLER_VELOCITY),
488 DECL(AL_DISTANCE_MODEL),
489 DECL(AL_SPEED_OF_SOUND),
490 DECL(AL_SOURCE_DISTANCE_MODEL),
491 DECL(AL_DEFERRED_UPDATES_SOFT),
493 DECL(AL_INVERSE_DISTANCE),
494 DECL(AL_INVERSE_DISTANCE_CLAMPED),
495 DECL(AL_LINEAR_DISTANCE),
496 DECL(AL_LINEAR_DISTANCE_CLAMPED),
497 DECL(AL_EXPONENT_DISTANCE),
498 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
500 DECL(AL_FILTER_TYPE),
501 DECL(AL_FILTER_NULL),
502 DECL(AL_FILTER_LOWPASS),
503 #if 0
504 DECL(AL_FILTER_HIGHPASS),
505 DECL(AL_FILTER_BANDPASS),
506 #endif
508 DECL(AL_LOWPASS_GAIN),
509 DECL(AL_LOWPASS_GAINHF),
511 DECL(AL_EFFECT_TYPE),
512 DECL(AL_EFFECT_NULL),
513 DECL(AL_EFFECT_REVERB),
514 DECL(AL_EFFECT_EAXREVERB),
515 #if 0
516 DECL(AL_EFFECT_CHORUS),
517 DECL(AL_EFFECT_DISTORTION),
518 #endif
519 DECL(AL_EFFECT_ECHO),
520 #if 0
521 DECL(AL_EFFECT_FLANGER),
522 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
523 DECL(AL_EFFECT_VOCAL_MORPHER),
524 DECL(AL_EFFECT_PITCH_SHIFTER),
525 #endif
526 DECL(AL_EFFECT_RING_MODULATOR),
527 #if 0
528 DECL(AL_EFFECT_AUTOWAH),
529 DECL(AL_EFFECT_COMPRESSOR),
530 DECL(AL_EFFECT_EQUALIZER),
531 #endif
532 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
533 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
535 DECL(AL_EAXREVERB_DENSITY),
536 DECL(AL_EAXREVERB_DIFFUSION),
537 DECL(AL_EAXREVERB_GAIN),
538 DECL(AL_EAXREVERB_GAINHF),
539 DECL(AL_EAXREVERB_GAINLF),
540 DECL(AL_EAXREVERB_DECAY_TIME),
541 DECL(AL_EAXREVERB_DECAY_HFRATIO),
542 DECL(AL_EAXREVERB_DECAY_LFRATIO),
543 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
544 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
545 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
546 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
547 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
548 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
549 DECL(AL_EAXREVERB_ECHO_TIME),
550 DECL(AL_EAXREVERB_ECHO_DEPTH),
551 DECL(AL_EAXREVERB_MODULATION_TIME),
552 DECL(AL_EAXREVERB_MODULATION_DEPTH),
553 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
554 DECL(AL_EAXREVERB_HFREFERENCE),
555 DECL(AL_EAXREVERB_LFREFERENCE),
556 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
557 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
559 DECL(AL_REVERB_DENSITY),
560 DECL(AL_REVERB_DIFFUSION),
561 DECL(AL_REVERB_GAIN),
562 DECL(AL_REVERB_GAINHF),
563 DECL(AL_REVERB_DECAY_TIME),
564 DECL(AL_REVERB_DECAY_HFRATIO),
565 DECL(AL_REVERB_REFLECTIONS_GAIN),
566 DECL(AL_REVERB_REFLECTIONS_DELAY),
567 DECL(AL_REVERB_LATE_REVERB_GAIN),
568 DECL(AL_REVERB_LATE_REVERB_DELAY),
569 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
570 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
571 DECL(AL_REVERB_DECAY_HFLIMIT),
573 DECL(AL_ECHO_DELAY),
574 DECL(AL_ECHO_LRDELAY),
575 DECL(AL_ECHO_DAMPING),
576 DECL(AL_ECHO_FEEDBACK),
577 DECL(AL_ECHO_SPREAD),
579 DECL(AL_RING_MODULATOR_FREQUENCY),
580 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
581 DECL(AL_RING_MODULATOR_WAVEFORM),
583 DECL(AL_DEDICATED_GAIN),
585 { NULL, (ALCenum)0 }
587 #undef DECL
589 static const ALCchar alcNoError[] = "No Error";
590 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
591 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
592 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
593 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
594 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
597 /************************************************
598 * Global variables
599 ************************************************/
601 /* Enumerated device names */
602 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
603 static ALCchar *alcAllDevicesList;
604 static ALCchar *alcCaptureDeviceList;
605 /* Sizes only include the first ending null character, not the second */
606 static size_t alcAllDevicesListSize;
607 static size_t alcCaptureDeviceListSize;
609 /* Default is always the first in the list */
610 static ALCchar *alcDefaultAllDevicesSpecifier;
611 static ALCchar *alcCaptureDefaultDeviceSpecifier;
613 /* Default context extensions */
614 static const ALchar alExtList[] =
615 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
616 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
617 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
618 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
619 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points "
620 "AL_SOFTX_source_latency";
622 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
624 /* Thread-local current context */
625 static pthread_key_t LocalContext;
626 /* Process-wide current context */
627 static ALCcontext *volatile GlobalContext = NULL;
629 /* Mixing thread piority level */
630 ALint RTPrioLevel;
632 FILE *LogFile;
633 #ifdef _DEBUG
634 enum LogLevel LogLevel = LogWarning;
635 #else
636 enum LogLevel LogLevel = LogError;
637 #endif
639 /* Flag to trap ALC device errors */
640 static ALCboolean TrapALCError = ALC_FALSE;
642 /* One-time configuration init control */
643 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
645 /* Default effect that applies to sources that don't have an effect on send 0 */
646 static ALeffect DefaultEffect;
649 /************************************************
650 * ALC information
651 ************************************************/
652 static const ALCchar alcNoDeviceExtList[] =
653 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
654 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
655 static const ALCchar alcExtensionList[] =
656 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
657 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
658 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
659 static const ALCint alcMajorVersion = 1;
660 static const ALCint alcMinorVersion = 1;
662 static const ALCint alcEFXMajorVersion = 1;
663 static const ALCint alcEFXMinorVersion = 0;
666 /************************************************
667 * Device lists
668 ************************************************/
669 static ALCdevice *volatile DeviceList = NULL;
671 static CRITICAL_SECTION ListLock;
673 static void LockLists(void)
675 EnterCriticalSection(&ListLock);
677 static void UnlockLists(void)
679 LeaveCriticalSection(&ListLock);
682 /************************************************
683 * Library initialization
684 ************************************************/
685 #if defined(_WIN32)
686 static void alc_init(void);
687 static void alc_deinit(void);
688 static void alc_deinit_safe(void);
690 UIntMap TlsDestructor;
692 #ifndef AL_LIBTYPE_STATIC
693 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
695 ALsizei i;
697 // Perform actions based on the reason for calling.
698 switch(ul_reason_for_call)
700 case DLL_PROCESS_ATTACH:
701 /* Pin the DLL so we won't get unloaded until the process terminates */
702 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
703 (WCHAR*)hModule, &hModule);
704 InitUIntMap(&TlsDestructor, ~0);
705 alc_init();
706 break;
708 case DLL_THREAD_DETACH:
709 LockUIntMapRead(&TlsDestructor);
710 for(i = 0;i < TlsDestructor.size;i++)
712 void *ptr = pthread_getspecific(TlsDestructor.array[i].key);
713 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
714 if(ptr && callback)
715 callback(ptr);
717 UnlockUIntMapRead(&TlsDestructor);
718 break;
720 case DLL_PROCESS_DETACH:
721 if(!lpReserved)
722 alc_deinit();
723 else
724 alc_deinit_safe();
725 ResetUIntMap(&TlsDestructor);
726 break;
728 return TRUE;
730 #elif defined(_MSC_VER)
731 #pragma section(".CRT$XCU",read)
732 static void alc_constructor(void);
733 static void alc_destructor(void);
734 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
736 static void alc_constructor(void)
738 atexit(alc_destructor);
739 alc_init();
742 static void alc_destructor(void)
744 alc_deinit();
746 #elif defined(HAVE_GCC_DESTRUCTOR)
747 static void alc_init(void) __attribute__((constructor));
748 static void alc_deinit(void) __attribute__((destructor));
749 #else
750 #error "No static initialization available on this platform!"
751 #endif
753 #elif defined(HAVE_GCC_DESTRUCTOR)
755 static void alc_init(void) __attribute__((constructor));
756 static void alc_deinit(void) __attribute__((destructor));
758 #else
759 #error "No global initialization available on this platform!"
760 #endif
762 static void ReleaseThreadCtx(void *ptr);
763 static void alc_init(void)
765 const char *str;
767 LogFile = stderr;
769 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
770 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
771 ConeScale *= 0.5f;
773 str = getenv("__ALSOFT_REVERSE_Z");
774 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
775 ZScale *= -1.0f;
777 pthread_key_create(&LocalContext, ReleaseThreadCtx);
778 InitializeCriticalSection(&ListLock);
779 ThunkInit();
782 static void alc_initconfig(void)
784 const char *devs, *str;
785 ALuint capfilter;
786 float valf;
787 int i, n;
789 str = getenv("ALSOFT_LOGLEVEL");
790 if(str)
792 long lvl = strtol(str, NULL, 0);
793 if(lvl >= NoLog && lvl <= LogRef)
794 LogLevel = lvl;
797 str = getenv("ALSOFT_LOGFILE");
798 if(str && str[0])
800 FILE *logfile = fopen(str, "wat");
801 if(logfile) LogFile = logfile;
802 else ERR("Failed to open log file '%s'\n", str);
805 ReadALConfig();
807 capfilter = 0;
808 #ifdef HAVE_SSE
809 capfilter |= CPU_CAP_SSE;
810 #endif
811 #ifdef HAVE_NEON
812 capfilter |= CPU_CAP_NEON;
813 #endif
814 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
816 if(strcasecmp(str, "all") == 0)
817 capfilter = 0;
818 else
820 size_t len;
821 const char *next = str;
823 i = 0;
824 do {
825 str = next;
826 next = strchr(str, ',');
828 while(isspace(str[0]))
829 str++;
830 if(!str[0] || str[0] == ',')
831 continue;
833 len = (next ? ((size_t)(next-str)) : strlen(str));
834 if(strncasecmp(str, "sse", len) == 0)
835 capfilter &= ~CPU_CAP_SSE;
836 else if(strncasecmp(str, "neon", len) == 0)
837 capfilter &= ~CPU_CAP_NEON;
838 else
839 WARN("Invalid CPU extension \"%s\"\n", str);
840 } while(next++);
843 FillCPUCaps(capfilter);
845 #ifdef _WIN32
846 RTPrioLevel = 1;
847 #else
848 RTPrioLevel = 0;
849 #endif
850 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
852 if(ConfigValueStr(NULL, "resampler", &str))
854 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
855 DefaultResampler = PointResampler;
856 else if(strcasecmp(str, "linear") == 0)
857 DefaultResampler = LinearResampler;
858 else if(strcasecmp(str, "cubic") == 0)
859 DefaultResampler = CubicResampler;
860 else
862 char *end;
864 n = strtol(str, &end, 0);
865 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
866 DefaultResampler = n;
867 else
868 WARN("Invalid resampler: %s\n", str);
872 str = getenv("ALSOFT_TRAP_ERROR");
873 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
875 TrapALError = AL_TRUE;
876 TrapALCError = AL_TRUE;
878 else
880 str = getenv("ALSOFT_TRAP_AL_ERROR");
881 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
882 TrapALError = AL_TRUE;
883 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
885 str = getenv("ALSOFT_TRAP_ALC_ERROR");
886 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
887 TrapALCError = ALC_TRUE;
888 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
891 if(ConfigValueFloat("reverb", "boost", &valf))
892 ReverbBoost *= powf(10.0f, valf / 20.0f);
894 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
896 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
897 ConfigValueStr(NULL, "drivers", &devs))
899 int n;
900 size_t len;
901 const char *next = devs;
902 int endlist, delitem;
904 i = 0;
905 do {
906 devs = next;
907 next = strchr(devs, ',');
909 delitem = (devs[0] == '-');
910 if(devs[0] == '-') devs++;
912 if(!devs[0] || devs[0] == ',')
914 endlist = 0;
915 continue;
917 endlist = 1;
919 len = (next ? ((size_t)(next-devs)) : strlen(devs));
920 for(n = i;BackendList[n].Init;n++)
922 if(len == strlen(BackendList[n].name) &&
923 strncmp(BackendList[n].name, devs, len) == 0)
925 if(delitem)
927 do {
928 BackendList[n] = BackendList[n+1];
929 ++n;
930 } while(BackendList[n].Init);
932 else
934 struct BackendInfo Bkp = BackendList[n];
935 while(n > i)
937 BackendList[n] = BackendList[n-1];
938 --n;
940 BackendList[n] = Bkp;
942 i++;
944 break;
947 } while(next++);
949 if(endlist)
951 BackendList[i].name = NULL;
952 BackendList[i].Init = NULL;
953 BackendList[i].Deinit = NULL;
954 BackendList[i].Probe = NULL;
958 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
960 if(!BackendList[i].Init(&BackendList[i].Funcs))
962 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
963 continue;
966 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
967 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
969 PlaybackBackend = BackendList[i];
970 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
972 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
974 CaptureBackend = BackendList[i];
975 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
978 BackendLoopback.Init(&BackendLoopback.Funcs);
980 if(ConfigValueStr(NULL, "excludefx", &str))
982 size_t len;
983 const char *next = str;
985 do {
986 str = next;
987 next = strchr(str, ',');
989 if(!str[0] || next == str)
990 continue;
992 len = (next ? ((size_t)(next-str)) : strlen(str));
993 for(n = 0;EffectList[n].name;n++)
995 if(len == strlen(EffectList[n].name) &&
996 strncmp(EffectList[n].name, str, len) == 0)
997 DisabledEffects[EffectList[n].type] = AL_TRUE;
999 } while(next++);
1002 InitEffect(&DefaultEffect);
1003 str = getenv("ALSOFT_DEFAULT_REVERB");
1004 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1005 LoadReverbPreset(str, &DefaultEffect);
1007 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1010 /************************************************
1011 * Library deinitialization
1012 ************************************************/
1013 static void alc_cleanup(void)
1015 ALCdevice *dev;
1017 free(alcAllDevicesList); alcAllDevicesList = NULL;
1018 alcAllDevicesListSize = 0;
1019 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1020 alcCaptureDeviceListSize = 0;
1022 free(alcDefaultAllDevicesSpecifier);
1023 alcDefaultAllDevicesSpecifier = NULL;
1024 free(alcCaptureDefaultDeviceSpecifier);
1025 alcCaptureDefaultDeviceSpecifier = NULL;
1027 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1029 ALCuint num = 0;
1030 do {
1031 num++;
1032 } while((dev=dev->next) != NULL);
1033 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1037 static void alc_deinit_safe(void)
1039 alc_cleanup();
1041 FreeHrtfs();
1042 FreeALConfig();
1044 ThunkExit();
1045 DeleteCriticalSection(&ListLock);
1046 pthread_key_delete(LocalContext);
1048 if(LogFile != stderr)
1049 fclose(LogFile);
1050 LogFile = NULL;
1053 static void alc_deinit(void)
1055 int i;
1057 alc_cleanup();
1059 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1060 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1062 for(i = 0;BackendList[i].Deinit;i++)
1063 BackendList[i].Deinit();
1064 BackendLoopback.Deinit();
1066 alc_deinit_safe();
1070 /************************************************
1071 * Device enumeration
1072 ************************************************/
1073 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1075 DO_INITCONFIG();
1077 LockLists();
1078 free(*list);
1079 *list = NULL;
1080 *listsize = 0;
1082 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1083 PlaybackBackend.Probe(type);
1084 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1085 CaptureBackend.Probe(type);
1086 UnlockLists();
1089 static void ProbeAllDevicesList(void)
1090 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1091 static void ProbeCaptureDeviceList(void)
1092 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1095 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1097 size_t len = strlen(name);
1098 void *temp;
1100 if(len == 0)
1101 return;
1103 temp = realloc(*List, (*ListSize) + len + 2);
1104 if(!temp)
1106 ERR("Realloc failed to add %s!\n", name);
1107 return;
1109 *List = temp;
1111 memcpy((*List)+(*ListSize), name, len+1);
1112 *ListSize += len+1;
1113 (*List)[*ListSize] = 0;
1116 #define DECL_APPEND_LIST_FUNC(type) \
1117 void Append##type##List(const ALCchar *name) \
1118 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1120 DECL_APPEND_LIST_FUNC(AllDevices)
1121 DECL_APPEND_LIST_FUNC(CaptureDevice)
1123 #undef DECL_APPEND_LIST_FUNC
1126 /************************************************
1127 * Device format information
1128 ************************************************/
1129 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1131 switch(type)
1133 case DevFmtByte: return "Signed Byte";
1134 case DevFmtUByte: return "Unsigned Byte";
1135 case DevFmtShort: return "Signed Short";
1136 case DevFmtUShort: return "Unsigned Short";
1137 case DevFmtInt: return "Signed Int";
1138 case DevFmtUInt: return "Unsigned Int";
1139 case DevFmtFloat: return "Float";
1141 return "(unknown type)";
1143 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1145 switch(chans)
1147 case DevFmtMono: return "Mono";
1148 case DevFmtStereo: return "Stereo";
1149 case DevFmtQuad: return "Quadraphonic";
1150 case DevFmtX51: return "5.1 Surround";
1151 case DevFmtX51Side: return "5.1 Side";
1152 case DevFmtX61: return "6.1 Surround";
1153 case DevFmtX71: return "7.1 Surround";
1155 return "(unknown channels)";
1158 ALuint BytesFromDevFmt(enum DevFmtType type)
1160 switch(type)
1162 case DevFmtByte: return sizeof(ALbyte);
1163 case DevFmtUByte: return sizeof(ALubyte);
1164 case DevFmtShort: return sizeof(ALshort);
1165 case DevFmtUShort: return sizeof(ALushort);
1166 case DevFmtInt: return sizeof(ALint);
1167 case DevFmtUInt: return sizeof(ALuint);
1168 case DevFmtFloat: return sizeof(ALfloat);
1170 return 0;
1172 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1174 switch(chans)
1176 case DevFmtMono: return 1;
1177 case DevFmtStereo: return 2;
1178 case DevFmtQuad: return 4;
1179 case DevFmtX51: return 6;
1180 case DevFmtX51Side: return 6;
1181 case DevFmtX61: return 7;
1182 case DevFmtX71: return 8;
1184 return 0;
1187 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1188 enum DevFmtType *type)
1190 static const struct {
1191 ALenum format;
1192 enum DevFmtChannels channels;
1193 enum DevFmtType type;
1194 } list[] = {
1195 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1196 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1197 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1199 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1200 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1201 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1203 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1204 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1205 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1207 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1208 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1209 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1211 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1212 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1213 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1215 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1216 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1217 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1219 ALuint i;
1221 for(i = 0;i < COUNTOF(list);i++)
1223 if(list[i].format == format)
1225 *chans = list[i].channels;
1226 *type = list[i].type;
1227 return AL_TRUE;
1231 return AL_FALSE;
1234 static ALCboolean IsValidALCType(ALCenum type)
1236 switch(type)
1238 case ALC_BYTE_SOFT:
1239 case ALC_UNSIGNED_BYTE_SOFT:
1240 case ALC_SHORT_SOFT:
1241 case ALC_UNSIGNED_SHORT_SOFT:
1242 case ALC_INT_SOFT:
1243 case ALC_UNSIGNED_INT_SOFT:
1244 case ALC_FLOAT_SOFT:
1245 return ALC_TRUE;
1247 return ALC_FALSE;
1250 static ALCboolean IsValidALCChannels(ALCenum channels)
1252 switch(channels)
1254 case ALC_MONO_SOFT:
1255 case ALC_STEREO_SOFT:
1256 case ALC_QUAD_SOFT:
1257 case ALC_5POINT1_SOFT:
1258 case ALC_6POINT1_SOFT:
1259 case ALC_7POINT1_SOFT:
1260 return ALC_TRUE;
1262 return ALC_FALSE;
1266 /************************************************
1267 * Miscellaneous ALC helpers
1268 ************************************************/
1270 void ALCdevice_LockDefault(ALCdevice *device)
1272 EnterCriticalSection(&device->Mutex);
1274 void ALCdevice_UnlockDefault(ALCdevice *device)
1276 LeaveCriticalSection(&device->Mutex);
1278 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
1280 (void)device;
1281 return 0;
1284 /* SetDefaultWFXChannelOrder
1286 * Sets the default channel order used by WaveFormatEx.
1288 void SetDefaultWFXChannelOrder(ALCdevice *device)
1290 switch(device->FmtChans)
1292 case DevFmtMono: device->DevChannels[0] = FrontCenter; break;
1294 case DevFmtStereo: device->DevChannels[0] = FrontLeft;
1295 device->DevChannels[1] = FrontRight; break;
1297 case DevFmtQuad: device->DevChannels[0] = FrontLeft;
1298 device->DevChannels[1] = FrontRight;
1299 device->DevChannels[2] = BackLeft;
1300 device->DevChannels[3] = BackRight; break;
1302 case DevFmtX51: 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; break;
1309 case DevFmtX51Side: device->DevChannels[0] = FrontLeft;
1310 device->DevChannels[1] = FrontRight;
1311 device->DevChannels[2] = FrontCenter;
1312 device->DevChannels[3] = LFE;
1313 device->DevChannels[4] = SideLeft;
1314 device->DevChannels[5] = SideRight; break;
1316 case DevFmtX61: device->DevChannels[0] = FrontLeft;
1317 device->DevChannels[1] = FrontRight;
1318 device->DevChannels[2] = FrontCenter;
1319 device->DevChannels[3] = LFE;
1320 device->DevChannels[4] = BackCenter;
1321 device->DevChannels[5] = SideLeft;
1322 device->DevChannels[6] = SideRight; break;
1324 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1325 device->DevChannels[1] = FrontRight;
1326 device->DevChannels[2] = FrontCenter;
1327 device->DevChannels[3] = LFE;
1328 device->DevChannels[4] = BackLeft;
1329 device->DevChannels[5] = BackRight;
1330 device->DevChannels[6] = SideLeft;
1331 device->DevChannels[7] = SideRight; break;
1335 /* SetDefaultChannelOrder
1337 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1339 void SetDefaultChannelOrder(ALCdevice *device)
1341 switch(device->FmtChans)
1343 case DevFmtX51: device->DevChannels[0] = FrontLeft;
1344 device->DevChannels[1] = FrontRight;
1345 device->DevChannels[2] = BackLeft;
1346 device->DevChannels[3] = BackRight;
1347 device->DevChannels[4] = FrontCenter;
1348 device->DevChannels[5] = LFE;
1349 return;
1351 case DevFmtX71: device->DevChannels[0] = FrontLeft;
1352 device->DevChannels[1] = FrontRight;
1353 device->DevChannels[2] = BackLeft;
1354 device->DevChannels[3] = BackRight;
1355 device->DevChannels[4] = FrontCenter;
1356 device->DevChannels[5] = LFE;
1357 device->DevChannels[6] = SideLeft;
1358 device->DevChannels[7] = SideRight;
1359 return;
1361 /* Same as WFX order */
1362 case DevFmtMono:
1363 case DevFmtStereo:
1364 case DevFmtQuad:
1365 case DevFmtX51Side:
1366 case DevFmtX61:
1367 break;
1369 SetDefaultWFXChannelOrder(device);
1373 /* alcSetError
1375 * Stores the latest ALC device error
1377 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1379 if(TrapALCError)
1381 #ifdef _WIN32
1382 /* DebugBreak() will cause an exception if there is no debugger */
1383 if(IsDebuggerPresent())
1384 DebugBreak();
1385 #elif defined(SIGTRAP)
1386 raise(SIGTRAP);
1387 #endif
1390 if(device)
1391 device->LastError = errorCode;
1392 else
1393 LastNullDeviceError = errorCode;
1397 /* UpdateDeviceParams
1399 * Updates device parameters according to the attribute list (caller is
1400 * responsible for holding the list lock).
1402 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1404 ALCcontext *context;
1405 enum DevFmtChannels oldChans;
1406 enum DevFmtType oldType;
1407 ALCuint oldFreq;
1408 FPUCtl oldMode;
1409 ALuint i;
1411 // Check for attributes
1412 if(device->Type == Loopback)
1414 enum {
1415 GotFreq = 1<<0,
1416 GotChans = 1<<1,
1417 GotType = 1<<2,
1418 GotAll = GotFreq|GotChans|GotType
1420 ALCuint freq, numMono, numStereo, numSends;
1421 enum DevFmtChannels schans;
1422 enum DevFmtType stype;
1423 ALCuint attrIdx = 0;
1424 ALCint gotFmt = 0;
1426 if(!attrList)
1428 WARN("Missing attributes for loopback device\n");
1429 return ALC_INVALID_VALUE;
1432 numMono = device->NumMonoSources;
1433 numStereo = device->NumStereoSources;
1434 numSends = device->NumAuxSends;
1435 schans = device->FmtChans;
1436 stype = device->FmtType;
1437 freq = device->Frequency;
1439 while(attrList[attrIdx])
1441 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1443 ALCint val = attrList[attrIdx + 1];
1444 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1445 return ALC_INVALID_VALUE;
1446 schans = val;
1447 gotFmt |= GotChans;
1450 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1452 ALCint val = attrList[attrIdx + 1];
1453 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1454 return ALC_INVALID_VALUE;
1455 stype = val;
1456 gotFmt |= GotType;
1459 if(attrList[attrIdx] == ALC_FREQUENCY)
1461 freq = attrList[attrIdx + 1];
1462 if(freq < MIN_OUTPUT_RATE)
1463 return ALC_INVALID_VALUE;
1464 gotFmt |= GotFreq;
1467 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1469 numStereo = attrList[attrIdx + 1];
1470 if(numStereo > device->MaxNoOfSources)
1471 numStereo = device->MaxNoOfSources;
1473 numMono = device->MaxNoOfSources - numStereo;
1476 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1477 numSends = attrList[attrIdx + 1];
1479 attrIdx += 2;
1482 if(gotFmt != GotAll)
1484 WARN("Missing format for loopback device\n");
1485 return ALC_INVALID_VALUE;
1488 ConfigValueUInt(NULL, "sends", &numSends);
1489 numSends = minu(MAX_SENDS, numSends);
1491 if((device->Flags&DEVICE_RUNNING))
1492 ALCdevice_StopPlayback(device);
1493 device->Flags &= ~DEVICE_RUNNING;
1495 device->Frequency = freq;
1496 device->FmtChans = schans;
1497 device->FmtType = stype;
1498 device->NumMonoSources = numMono;
1499 device->NumStereoSources = numStereo;
1500 device->NumAuxSends = numSends;
1502 else if(attrList && attrList[0])
1504 ALCuint freq, numMono, numStereo, numSends;
1505 ALCuint attrIdx = 0;
1507 /* If a context is already running on the device, stop playback so the
1508 * device attributes can be updated. */
1509 if((device->Flags&DEVICE_RUNNING))
1510 ALCdevice_StopPlayback(device);
1511 device->Flags &= ~DEVICE_RUNNING;
1513 freq = device->Frequency;
1514 numMono = device->NumMonoSources;
1515 numStereo = device->NumStereoSources;
1516 numSends = device->NumAuxSends;
1518 while(attrList[attrIdx])
1520 if(attrList[attrIdx] == ALC_FREQUENCY)
1522 freq = attrList[attrIdx + 1];
1523 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1526 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1528 numStereo = attrList[attrIdx + 1];
1529 if(numStereo > device->MaxNoOfSources)
1530 numStereo = device->MaxNoOfSources;
1532 numMono = device->MaxNoOfSources - numStereo;
1535 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1536 numSends = attrList[attrIdx + 1];
1538 attrIdx += 2;
1541 ConfigValueUInt(NULL, "frequency", &freq);
1542 freq = maxu(freq, MIN_OUTPUT_RATE);
1544 ConfigValueUInt(NULL, "sends", &numSends);
1545 numSends = minu(MAX_SENDS, numSends);
1547 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1548 device->Frequency;
1549 /* SSE does best with the update size being a multiple of 4 */
1550 if((CPUCapFlags&CPU_CAP_SSE))
1551 device->UpdateSize = (device->UpdateSize+3)&~3;
1553 device->Frequency = freq;
1554 device->NumMonoSources = numMono;
1555 device->NumStereoSources = numStereo;
1556 device->NumAuxSends = numSends;
1559 if((device->Flags&DEVICE_RUNNING))
1560 return ALC_NO_ERROR;
1562 oldFreq = device->Frequency;
1563 oldChans = device->FmtChans;
1564 oldType = device->FmtType;
1566 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1567 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1568 DevFmtChannelsString(device->FmtChans),
1569 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1570 DevFmtTypeString(device->FmtType),
1571 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1572 device->Frequency,
1573 device->UpdateSize, device->NumUpdates);
1575 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1576 return ALC_INVALID_DEVICE;
1578 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1580 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1581 DevFmtChannelsString(device->FmtChans));
1582 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1584 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1586 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1587 DevFmtTypeString(device->FmtType));
1588 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1590 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1592 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1593 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1596 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1597 DevFmtChannelsString(device->FmtChans),
1598 DevFmtTypeString(device->FmtType), device->Frequency,
1599 device->UpdateSize, device->NumUpdates);
1601 aluInitPanning(device);
1603 for(i = 0;i < MaxChannels;i++)
1605 device->ClickRemoval[i] = 0.0f;
1606 device->PendingClicks[i] = 0.0f;
1609 device->Hrtf = NULL;
1610 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1611 device->Hrtf = GetHrtf(device);
1612 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1614 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1616 if(!device->Bs2b)
1618 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1619 bs2b_clear(device->Bs2b);
1621 bs2b_set_srate(device->Bs2b, device->Frequency);
1622 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1623 TRACE("BS2B level %d\n", device->Bs2bLevel);
1625 else
1627 free(device->Bs2b);
1628 device->Bs2b = NULL;
1629 TRACE("BS2B disabled\n");
1632 device->Flags &= ~DEVICE_WIDE_STEREO;
1633 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1634 device->Flags |= DEVICE_WIDE_STEREO;
1636 if(!device->Hrtf && (device->UpdateSize&3))
1638 if((CPUCapFlags&CPU_CAP_SSE))
1639 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1642 SetMixerFPUMode(&oldMode);
1643 ALCdevice_Lock(device);
1644 context = device->ContextList;
1645 while(context)
1647 ALsizei pos;
1649 context->UpdateSources = AL_FALSE;
1650 LockUIntMapRead(&context->EffectSlotMap);
1651 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1653 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1655 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1657 UnlockUIntMapRead(&context->EffectSlotMap);
1658 ALCdevice_Unlock(device);
1659 RestoreFPUMode(&oldMode);
1660 return ALC_INVALID_DEVICE;
1662 slot->NeedsUpdate = AL_FALSE;
1663 ALeffectState_Update(slot->EffectState, device, slot);
1665 UnlockUIntMapRead(&context->EffectSlotMap);
1667 LockUIntMapRead(&context->SourceMap);
1668 for(pos = 0;pos < context->SourceMap.size;pos++)
1670 ALsource *source = context->SourceMap.array[pos].value;
1671 ALuint s = device->NumAuxSends;
1672 while(s < MAX_SENDS)
1674 if(source->Send[s].Slot)
1675 DecrementRef(&source->Send[s].Slot->ref);
1676 source->Send[s].Slot = NULL;
1677 source->Send[s].Gain = 1.0f;
1678 source->Send[s].GainHF = 1.0f;
1679 s++;
1681 source->NeedsUpdate = AL_FALSE;
1682 ALsource_Update(source, context);
1684 UnlockUIntMapRead(&context->SourceMap);
1686 context = context->next;
1688 if(device->DefaultSlot)
1690 ALeffectslot *slot = device->DefaultSlot;
1692 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1694 ALCdevice_Unlock(device);
1695 RestoreFPUMode(&oldMode);
1696 return ALC_INVALID_DEVICE;
1698 slot->NeedsUpdate = AL_FALSE;
1699 ALeffectState_Update(slot->EffectState, device, slot);
1701 ALCdevice_Unlock(device);
1702 RestoreFPUMode(&oldMode);
1704 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1705 return ALC_INVALID_DEVICE;
1706 device->Flags |= DEVICE_RUNNING;
1708 return ALC_NO_ERROR;
1711 /* FreeDevice
1713 * Frees the device structure, and destroys any objects the app failed to
1714 * delete. Called once there's no more references on the device.
1716 static ALCvoid FreeDevice(ALCdevice *device)
1718 TRACE("%p\n", device);
1720 if(device->Type != Capture)
1721 ALCdevice_ClosePlayback(device);
1722 else
1723 ALCdevice_CloseCapture(device);
1725 if(device->DefaultSlot)
1727 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1728 device->DefaultSlot->EffectState = NULL;
1731 if(device->BufferMap.size > 0)
1733 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1734 ReleaseALBuffers(device);
1736 ResetUIntMap(&device->BufferMap);
1738 if(device->EffectMap.size > 0)
1740 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1741 ReleaseALEffects(device);
1743 ResetUIntMap(&device->EffectMap);
1745 if(device->FilterMap.size > 0)
1747 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1748 ReleaseALFilters(device);
1750 ResetUIntMap(&device->FilterMap);
1752 free(device->Bs2b);
1753 device->Bs2b = NULL;
1755 free(device->DeviceName);
1756 device->DeviceName = NULL;
1758 DeleteCriticalSection(&device->Mutex);
1760 al_free(device);
1764 void ALCdevice_IncRef(ALCdevice *device)
1766 RefCount ref;
1767 ref = IncrementRef(&device->ref);
1768 TRACEREF("%p increasing refcount to %u\n", device, ref);
1771 void ALCdevice_DecRef(ALCdevice *device)
1773 RefCount ref;
1774 ref = DecrementRef(&device->ref);
1775 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1776 if(ref == 0) FreeDevice(device);
1779 /* VerifyDevice
1781 * Checks if the device handle is valid, and increments its ref count if so.
1783 static ALCdevice *VerifyDevice(ALCdevice *device)
1785 ALCdevice *tmpDevice;
1787 if(!device)
1788 return NULL;
1790 LockLists();
1791 tmpDevice = DeviceList;
1792 while(tmpDevice && tmpDevice != device)
1793 tmpDevice = tmpDevice->next;
1795 if(tmpDevice)
1796 ALCdevice_IncRef(tmpDevice);
1797 UnlockLists();
1798 return tmpDevice;
1802 /* InitContext
1804 * Initializes context fields
1806 static ALvoid InitContext(ALCcontext *Context)
1808 ALint i, j;
1810 //Initialise listener
1811 Context->Listener->Gain = 1.0f;
1812 Context->Listener->MetersPerUnit = 1.0f;
1813 Context->Listener->Position[0] = 0.0f;
1814 Context->Listener->Position[1] = 0.0f;
1815 Context->Listener->Position[2] = 0.0f;
1816 Context->Listener->Velocity[0] = 0.0f;
1817 Context->Listener->Velocity[1] = 0.0f;
1818 Context->Listener->Velocity[2] = 0.0f;
1819 Context->Listener->Forward[0] = 0.0f;
1820 Context->Listener->Forward[1] = 0.0f;
1821 Context->Listener->Forward[2] = -1.0f;
1822 Context->Listener->Up[0] = 0.0f;
1823 Context->Listener->Up[1] = 1.0f;
1824 Context->Listener->Up[2] = 0.0f;
1825 for(i = 0;i < 4;i++)
1827 for(j = 0;j < 4;j++)
1828 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1830 for(i = 0;i < 3;i++)
1831 Context->Listener->Params.Velocity[i] = 0.0f;
1833 //Validate Context
1834 Context->LastError = AL_NO_ERROR;
1835 Context->UpdateSources = AL_FALSE;
1836 Context->ActiveSourceCount = 0;
1837 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1838 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1840 //Set globals
1841 Context->DistanceModel = DefaultDistanceModel;
1842 Context->SourceDistanceModel = AL_FALSE;
1843 Context->DopplerFactor = 1.0f;
1844 Context->DopplerVelocity = 1.0f;
1845 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1846 Context->DeferUpdates = AL_FALSE;
1848 Context->ExtensionList = alExtList;
1852 /* FreeContext
1854 * Cleans up the context, and destroys any remaining objects the app failed to
1855 * delete. Called once there's no more references on the context.
1857 static ALCvoid FreeContext(ALCcontext *context)
1859 TRACE("%p\n", context);
1861 if(context->SourceMap.size > 0)
1863 ERR("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1864 ReleaseALSources(context);
1866 ResetUIntMap(&context->SourceMap);
1868 if(context->EffectSlotMap.size > 0)
1870 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1871 ReleaseALAuxiliaryEffectSlots(context);
1873 ResetUIntMap(&context->EffectSlotMap);
1875 context->ActiveSourceCount = 0;
1876 free(context->ActiveSources);
1877 context->ActiveSources = NULL;
1878 context->MaxActiveSources = 0;
1880 context->ActiveEffectSlotCount = 0;
1881 free(context->ActiveEffectSlots);
1882 context->ActiveEffectSlots = NULL;
1883 context->MaxActiveEffectSlots = 0;
1885 ALCdevice_DecRef(context->Device);
1886 context->Device = NULL;
1888 //Invalidate context
1889 memset(context, 0, sizeof(ALCcontext));
1890 free(context);
1893 /* ReleaseContext
1895 * Removes the context reference from the given device and removes it from
1896 * being current on the running thread or globally.
1898 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1900 ALCcontext *volatile*tmp_ctx;
1902 if(pthread_getspecific(LocalContext) == context)
1904 WARN("%p released while current on thread\n", context);
1905 pthread_setspecific(LocalContext, NULL);
1906 ALCcontext_DecRef(context);
1909 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1910 ALCcontext_DecRef(context);
1912 ALCdevice_Lock(device);
1913 tmp_ctx = &device->ContextList;
1914 while(*tmp_ctx)
1916 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1917 break;
1918 tmp_ctx = &(*tmp_ctx)->next;
1920 ALCdevice_Unlock(device);
1922 ALCcontext_DecRef(context);
1925 void ALCcontext_IncRef(ALCcontext *context)
1927 RefCount ref;
1928 ref = IncrementRef(&context->ref);
1929 TRACEREF("%p increasing refcount to %u\n", context, ref);
1932 void ALCcontext_DecRef(ALCcontext *context)
1934 RefCount ref;
1935 ref = DecrementRef(&context->ref);
1936 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1937 if(ref == 0) FreeContext(context);
1940 static void ReleaseThreadCtx(void *ptr)
1942 WARN("%p current for thread being destroyed\n", ptr);
1943 ALCcontext_DecRef(ptr);
1946 /* VerifyContext
1948 * Checks that the given context is valid, and increments its reference count.
1950 static ALCcontext *VerifyContext(ALCcontext *context)
1952 ALCdevice *dev;
1954 LockLists();
1955 dev = DeviceList;
1956 while(dev)
1958 ALCcontext *tmp_ctx = dev->ContextList;
1959 while(tmp_ctx)
1961 if(tmp_ctx == context)
1963 ALCcontext_IncRef(tmp_ctx);
1964 UnlockLists();
1965 return tmp_ctx;
1967 tmp_ctx = tmp_ctx->next;
1969 dev = dev->next;
1971 UnlockLists();
1973 return NULL;
1977 /* GetContextRef
1979 * Returns the currently active context for this thread, and adds a reference
1980 * without locking it.
1982 ALCcontext *GetContextRef(void)
1984 ALCcontext *context;
1986 context = pthread_getspecific(LocalContext);
1987 if(context)
1988 ALCcontext_IncRef(context);
1989 else
1991 LockLists();
1992 context = GlobalContext;
1993 if(context)
1994 ALCcontext_IncRef(context);
1995 UnlockLists();
1998 return context;
2002 /************************************************
2003 * Standard ALC functions
2004 ************************************************/
2006 /* alcGetError
2008 * Return last ALC generated error code for the given device
2010 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2012 ALCenum errorCode;
2014 if(VerifyDevice(device))
2016 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2017 ALCdevice_DecRef(device);
2019 else
2020 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2022 return errorCode;
2026 /* alcSuspendContext
2028 * Not functional
2030 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
2032 (void)Context;
2035 /* alcProcessContext
2037 * Not functional
2039 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2041 (void)Context;
2045 /* alcGetString
2047 * Returns information about the device, and error strings
2049 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2051 const ALCchar *value = NULL;
2053 switch(param)
2055 case ALC_NO_ERROR:
2056 value = alcNoError;
2057 break;
2059 case ALC_INVALID_ENUM:
2060 value = alcErrInvalidEnum;
2061 break;
2063 case ALC_INVALID_VALUE:
2064 value = alcErrInvalidValue;
2065 break;
2067 case ALC_INVALID_DEVICE:
2068 value = alcErrInvalidDevice;
2069 break;
2071 case ALC_INVALID_CONTEXT:
2072 value = alcErrInvalidContext;
2073 break;
2075 case ALC_OUT_OF_MEMORY:
2076 value = alcErrOutOfMemory;
2077 break;
2079 case ALC_DEVICE_SPECIFIER:
2080 value = alcDefaultName;
2081 break;
2083 case ALC_ALL_DEVICES_SPECIFIER:
2084 if(VerifyDevice(Device))
2086 value = Device->DeviceName;
2087 ALCdevice_DecRef(Device);
2089 else
2091 ProbeAllDevicesList();
2092 value = alcAllDevicesList;
2094 break;
2096 case ALC_CAPTURE_DEVICE_SPECIFIER:
2097 if(VerifyDevice(Device))
2099 value = Device->DeviceName;
2100 ALCdevice_DecRef(Device);
2102 else
2104 ProbeCaptureDeviceList();
2105 value = alcCaptureDeviceList;
2107 break;
2109 /* Default devices are always first in the list */
2110 case ALC_DEFAULT_DEVICE_SPECIFIER:
2111 value = alcDefaultName;
2112 break;
2114 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2115 if(!alcAllDevicesList)
2116 ProbeAllDevicesList();
2118 Device = VerifyDevice(Device);
2120 free(alcDefaultAllDevicesSpecifier);
2121 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2122 alcAllDevicesList : "");
2123 if(!alcDefaultAllDevicesSpecifier)
2124 alcSetError(Device, ALC_OUT_OF_MEMORY);
2126 value = alcDefaultAllDevicesSpecifier;
2127 if(Device) ALCdevice_DecRef(Device);
2128 break;
2130 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2131 if(!alcCaptureDeviceList)
2132 ProbeCaptureDeviceList();
2134 Device = VerifyDevice(Device);
2136 free(alcCaptureDefaultDeviceSpecifier);
2137 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2138 alcCaptureDeviceList : "");
2139 if(!alcCaptureDefaultDeviceSpecifier)
2140 alcSetError(Device, ALC_OUT_OF_MEMORY);
2142 value = alcCaptureDefaultDeviceSpecifier;
2143 if(Device) ALCdevice_DecRef(Device);
2144 break;
2146 case ALC_EXTENSIONS:
2147 if(!VerifyDevice(Device))
2148 value = alcNoDeviceExtList;
2149 else
2151 value = alcExtensionList;
2152 ALCdevice_DecRef(Device);
2154 break;
2156 default:
2157 Device = VerifyDevice(Device);
2158 alcSetError(Device, ALC_INVALID_ENUM);
2159 if(Device) ALCdevice_DecRef(Device);
2160 break;
2163 return value;
2167 /* alcGetIntegerv
2169 * Returns information about the device and the version of OpenAL
2171 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2173 device = VerifyDevice(device);
2175 if(size == 0 || data == NULL)
2177 alcSetError(device, ALC_INVALID_VALUE);
2178 if(device) ALCdevice_DecRef(device);
2179 return;
2182 if(!device)
2184 switch(param)
2186 case ALC_MAJOR_VERSION:
2187 *data = alcMajorVersion;
2188 break;
2189 case ALC_MINOR_VERSION:
2190 *data = alcMinorVersion;
2191 break;
2193 case ALC_ATTRIBUTES_SIZE:
2194 case ALC_ALL_ATTRIBUTES:
2195 case ALC_FREQUENCY:
2196 case ALC_REFRESH:
2197 case ALC_SYNC:
2198 case ALC_MONO_SOURCES:
2199 case ALC_STEREO_SOURCES:
2200 case ALC_CAPTURE_SAMPLES:
2201 case ALC_FORMAT_CHANNELS_SOFT:
2202 case ALC_FORMAT_TYPE_SOFT:
2203 alcSetError(NULL, ALC_INVALID_DEVICE);
2204 break;
2206 default:
2207 alcSetError(NULL, ALC_INVALID_ENUM);
2208 break;
2211 else if(device->Type == Capture)
2213 switch(param)
2215 case ALC_CAPTURE_SAMPLES:
2216 ALCdevice_Lock(device);
2217 *data = ALCdevice_AvailableSamples(device);
2218 ALCdevice_Unlock(device);
2219 break;
2221 case ALC_CONNECTED:
2222 *data = device->Connected;
2223 break;
2225 default:
2226 alcSetError(device, ALC_INVALID_ENUM);
2227 break;
2230 else /* render device */
2232 switch(param)
2234 case ALC_MAJOR_VERSION:
2235 *data = alcMajorVersion;
2236 break;
2238 case ALC_MINOR_VERSION:
2239 *data = alcMinorVersion;
2240 break;
2242 case ALC_EFX_MAJOR_VERSION:
2243 *data = alcEFXMajorVersion;
2244 break;
2246 case ALC_EFX_MINOR_VERSION:
2247 *data = alcEFXMinorVersion;
2248 break;
2250 case ALC_ATTRIBUTES_SIZE:
2251 *data = 13;
2252 break;
2254 case ALC_ALL_ATTRIBUTES:
2255 if(size < 13)
2256 alcSetError(device, ALC_INVALID_VALUE);
2257 else
2259 int i = 0;
2261 data[i++] = ALC_FREQUENCY;
2262 data[i++] = device->Frequency;
2264 if(device->Type != Loopback)
2266 data[i++] = ALC_REFRESH;
2267 data[i++] = device->Frequency / device->UpdateSize;
2269 data[i++] = ALC_SYNC;
2270 data[i++] = ALC_FALSE;
2272 else
2274 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2275 data[i++] = device->FmtChans;
2277 data[i++] = ALC_FORMAT_TYPE_SOFT;
2278 data[i++] = device->FmtType;
2281 data[i++] = ALC_MONO_SOURCES;
2282 data[i++] = device->NumMonoSources;
2284 data[i++] = ALC_STEREO_SOURCES;
2285 data[i++] = device->NumStereoSources;
2287 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2288 data[i++] = device->NumAuxSends;
2290 data[i++] = 0;
2292 break;
2294 case ALC_FREQUENCY:
2295 *data = device->Frequency;
2296 break;
2298 case ALC_REFRESH:
2299 if(device->Type == Loopback)
2300 alcSetError(device, ALC_INVALID_DEVICE);
2301 else
2302 *data = device->Frequency / device->UpdateSize;
2303 break;
2305 case ALC_SYNC:
2306 if(device->Type == Loopback)
2307 alcSetError(device, ALC_INVALID_DEVICE);
2308 else
2309 *data = ALC_FALSE;
2310 break;
2312 case ALC_FORMAT_CHANNELS_SOFT:
2313 if(device->Type != Loopback)
2314 alcSetError(device, ALC_INVALID_DEVICE);
2315 else
2316 *data = device->FmtChans;
2317 break;
2319 case ALC_FORMAT_TYPE_SOFT:
2320 if(device->Type != Loopback)
2321 alcSetError(device, ALC_INVALID_DEVICE);
2322 else
2323 *data = device->FmtType;
2324 break;
2326 case ALC_MONO_SOURCES:
2327 *data = device->NumMonoSources;
2328 break;
2330 case ALC_STEREO_SOURCES:
2331 *data = device->NumStereoSources;
2332 break;
2334 case ALC_MAX_AUXILIARY_SENDS:
2335 *data = device->NumAuxSends;
2336 break;
2338 case ALC_CONNECTED:
2339 *data = device->Connected;
2340 break;
2342 default:
2343 alcSetError(device, ALC_INVALID_ENUM);
2344 break;
2347 if(device)
2348 ALCdevice_DecRef(device);
2352 /* alcIsExtensionPresent
2354 * Determines if there is support for a particular extension
2356 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2358 ALCboolean bResult = ALC_FALSE;
2360 device = VerifyDevice(device);
2362 if(!extName)
2363 alcSetError(device, ALC_INVALID_VALUE);
2364 else
2366 size_t len = strlen(extName);
2367 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2368 while(ptr && *ptr)
2370 if(strncasecmp(ptr, extName, len) == 0 &&
2371 (ptr[len] == '\0' || isspace(ptr[len])))
2373 bResult = ALC_TRUE;
2374 break;
2376 if((ptr=strchr(ptr, ' ')) != NULL)
2378 do {
2379 ++ptr;
2380 } while(isspace(*ptr));
2384 if(device)
2385 ALCdevice_DecRef(device);
2386 return bResult;
2390 /* alcGetProcAddress
2392 * Retrieves the function address for a particular extension function
2394 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2396 ALCvoid *ptr = NULL;
2398 if(!funcName)
2400 device = VerifyDevice(device);
2401 alcSetError(device, ALC_INVALID_VALUE);
2402 if(device) ALCdevice_DecRef(device);
2404 else
2406 ALsizei i = 0;
2407 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2408 i++;
2409 ptr = alcFunctions[i].address;
2412 return ptr;
2416 /* alcGetEnumValue
2418 * Get the value for a particular ALC enumeration name
2420 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2422 ALCenum val = 0;
2424 if(!enumName)
2426 device = VerifyDevice(device);
2427 alcSetError(device, ALC_INVALID_VALUE);
2428 if(device) ALCdevice_DecRef(device);
2430 else
2432 ALsizei i = 0;
2433 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2434 i++;
2435 val = enumeration[i].value;
2438 return val;
2442 /* alcCreateContext
2444 * Create and attach a context to the given device.
2446 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2448 ALCcontext *ALContext;
2449 ALCenum err;
2451 LockLists();
2452 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2454 UnlockLists();
2455 alcSetError(device, ALC_INVALID_DEVICE);
2456 if(device) ALCdevice_DecRef(device);
2457 return NULL;
2460 device->LastError = ALC_NO_ERROR;
2462 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2464 UnlockLists();
2465 alcSetError(device, err);
2466 if(err == ALC_INVALID_DEVICE)
2467 aluHandleDisconnect(device);
2468 ALCdevice_DecRef(device);
2469 return NULL;
2472 ALContext = calloc(1, sizeof(ALCcontext)+15+sizeof(ALlistener));
2473 if(ALContext)
2475 ALContext->ref = 1;
2476 ALContext->Listener = (ALlistener*)(((ALintptrEXT)(ALContext+1)+15)&~15);
2478 ALContext->MaxActiveSources = 256;
2479 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2480 ALContext->MaxActiveSources);
2482 if(!ALContext || !ALContext->ActiveSources)
2484 if(!device->ContextList)
2486 ALCdevice_StopPlayback(device);
2487 device->Flags &= ~DEVICE_RUNNING;
2489 UnlockLists();
2491 free(ALContext);
2492 ALContext = NULL;
2494 alcSetError(device, ALC_OUT_OF_MEMORY);
2495 ALCdevice_DecRef(device);
2496 return NULL;
2499 ALContext->Device = device;
2500 ALCdevice_IncRef(device);
2501 InitContext(ALContext);
2503 do {
2504 ALContext->next = device->ContextList;
2505 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2506 UnlockLists();
2508 ALCdevice_DecRef(device);
2510 TRACE("Created context %p\n", ALContext);
2511 return ALContext;
2514 /* alcDestroyContext
2516 * Remove a context from its device
2518 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2520 ALCdevice *Device;
2522 LockLists();
2523 /* alcGetContextsDevice sets an error for invalid contexts */
2524 Device = alcGetContextsDevice(context);
2525 if(Device)
2527 ReleaseContext(context, Device);
2528 if(!Device->ContextList)
2530 ALCdevice_StopPlayback(Device);
2531 Device->Flags &= ~DEVICE_RUNNING;
2534 UnlockLists();
2538 /* alcGetCurrentContext
2540 * Returns the currently active context on the calling thread
2542 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2544 ALCcontext *Context;
2546 Context = pthread_getspecific(LocalContext);
2547 if(!Context) Context = GlobalContext;
2549 return Context;
2552 /* alcGetThreadContext
2554 * Returns the currently active thread-local context
2556 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2558 ALCcontext *Context;
2559 Context = pthread_getspecific(LocalContext);
2560 return Context;
2564 /* alcMakeContextCurrent
2566 * Makes the given context the active process-wide context, and removes the
2567 * thread-local context for the calling thread.
2569 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2571 /* context must be valid or NULL */
2572 if(context && !(context=VerifyContext(context)))
2574 alcSetError(NULL, ALC_INVALID_CONTEXT);
2575 return ALC_FALSE;
2577 /* context's reference count is already incremented */
2578 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2579 if(context) ALCcontext_DecRef(context);
2581 if((context=pthread_getspecific(LocalContext)) != NULL)
2583 pthread_setspecific(LocalContext, NULL);
2584 ALCcontext_DecRef(context);
2587 return ALC_TRUE;
2590 /* alcSetThreadContext
2592 * Makes the given context the active context for the current thread
2594 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2596 ALCcontext *old;
2598 /* context must be valid or NULL */
2599 if(context && !(context=VerifyContext(context)))
2601 alcSetError(NULL, ALC_INVALID_CONTEXT);
2602 return ALC_FALSE;
2604 /* context's reference count is already incremented */
2605 old = pthread_getspecific(LocalContext);
2606 pthread_setspecific(LocalContext, context);
2607 if(old) ALCcontext_DecRef(old);
2609 return ALC_TRUE;
2613 /* alcGetContextsDevice
2615 * Returns the device that a particular context is attached to
2617 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2619 ALCdevice *Device;
2621 if(!(Context=VerifyContext(Context)))
2623 alcSetError(NULL, ALC_INVALID_CONTEXT);
2624 return NULL;
2626 Device = Context->Device;
2627 ALCcontext_DecRef(Context);
2629 return Device;
2633 /* alcOpenDevice
2635 * Opens the named device.
2637 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2639 const ALCchar *fmt;
2640 ALCdevice *device;
2641 ALCenum err;
2643 DO_INITCONFIG();
2645 if(!PlaybackBackend.name)
2647 alcSetError(NULL, ALC_INVALID_VALUE);
2648 return NULL;
2651 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2652 deviceName = NULL;
2654 device = al_calloc(16, sizeof(ALCdevice)+15+sizeof(ALeffectslot));
2655 if(!device)
2657 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2658 return NULL;
2661 //Validate device
2662 device->Funcs = &PlaybackBackend.Funcs;
2663 device->ref = 1;
2664 device->Connected = ALC_TRUE;
2665 device->Type = Playback;
2666 InitializeCriticalSection(&device->Mutex);
2667 device->LastError = ALC_NO_ERROR;
2669 device->Flags = 0;
2670 device->Bs2b = NULL;
2671 device->Bs2bLevel = 0;
2672 device->DeviceName = NULL;
2674 device->ContextList = NULL;
2676 device->MaxNoOfSources = 256;
2677 device->AuxiliaryEffectSlotMax = 4;
2678 device->NumAuxSends = MAX_SENDS;
2680 InitUIntMap(&device->BufferMap, ~0);
2681 InitUIntMap(&device->EffectMap, ~0);
2682 InitUIntMap(&device->FilterMap, ~0);
2684 //Set output format
2685 device->FmtChans = DevFmtChannelsDefault;
2686 device->FmtType = DevFmtTypeDefault;
2687 device->Frequency = DEFAULT_OUTPUT_RATE;
2688 device->NumUpdates = 4;
2689 device->UpdateSize = 1024;
2691 if(ConfigValueStr(NULL, "channels", &fmt))
2693 static const struct {
2694 const char name[16];
2695 enum DevFmtChannels chans;
2696 } chanlist[] = {
2697 { "mono", DevFmtMono },
2698 { "stereo", DevFmtStereo },
2699 { "quad", DevFmtQuad },
2700 { "surround51", DevFmtX51 },
2701 { "surround61", DevFmtX61 },
2702 { "surround71", DevFmtX71 },
2704 size_t i;
2706 for(i = 0;i < COUNTOF(chanlist);i++)
2708 if(strcasecmp(chanlist[i].name, fmt) == 0)
2710 device->FmtChans = chanlist[i].chans;
2711 device->Flags |= DEVICE_CHANNELS_REQUEST;
2712 break;
2715 if(i == COUNTOF(chanlist))
2716 ERR("Unsupported channels: %s\n", fmt);
2718 if(ConfigValueStr(NULL, "sample-type", &fmt))
2720 static const struct {
2721 const char name[16];
2722 enum DevFmtType type;
2723 } typelist[] = {
2724 { "int8", DevFmtByte },
2725 { "uint8", DevFmtUByte },
2726 { "int16", DevFmtShort },
2727 { "uint16", DevFmtUShort },
2728 { "int32", DevFmtInt },
2729 { "uint32", DevFmtUInt },
2730 { "float32", DevFmtFloat },
2732 size_t i;
2734 for(i = 0;i < COUNTOF(typelist);i++)
2736 if(strcasecmp(typelist[i].name, fmt) == 0)
2738 device->FmtType = typelist[i].type;
2739 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2740 break;
2743 if(i == COUNTOF(typelist))
2744 ERR("Unsupported sample-type: %s\n", fmt);
2746 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2747 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2748 ConfigValueStr(NULL, "format", &fmt))
2750 static const struct {
2751 const char name[32];
2752 enum DevFmtChannels channels;
2753 enum DevFmtType type;
2754 } formats[] = {
2755 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2756 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2757 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2758 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2759 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2760 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2762 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2763 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2764 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2765 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2766 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2767 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2769 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2770 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2771 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2772 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2773 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2774 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2776 size_t i;
2778 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2779 for(i = 0;i < COUNTOF(formats);i++)
2781 if(strcasecmp(fmt, formats[i].name) == 0)
2783 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2784 device->FmtChans = formats[i].channels;
2785 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2786 device->FmtType = formats[i].type;
2787 device->Flags |= DEVICE_FORMAT_REQUEST;
2788 break;
2791 if(i == COUNTOF(formats))
2792 ERR("Unsupported format: %s\n", fmt);
2794 #undef DEVICE_FORMAT_REQUEST
2796 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2798 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2799 if(device->Frequency < MIN_OUTPUT_RATE)
2800 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2801 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2804 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2805 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2807 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2808 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2809 if((CPUCapFlags&CPU_CAP_SSE))
2810 device->UpdateSize = (device->UpdateSize+3)&~3;
2812 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2813 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2815 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2816 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2818 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2819 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2821 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2823 device->NumStereoSources = 1;
2824 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2826 // Find a playback device to open
2827 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2829 DeleteCriticalSection(&device->Mutex);
2830 al_free(device);
2831 alcSetError(NULL, err);
2832 return NULL;
2835 if(DefaultEffect.type != AL_EFFECT_NULL)
2837 device->DefaultSlot = (ALeffectslot*)(((ALintptrEXT)(device+1)+15)&~15);
2838 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2840 device->DefaultSlot = NULL;
2841 ERR("Failed to initialize the default effect slot\n");
2843 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2845 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2846 device->DefaultSlot = NULL;
2847 ERR("Failed to initialize the default effect\n");
2851 do {
2852 device->next = DeviceList;
2853 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2855 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2856 return device;
2859 /* alcCloseDevice
2861 * Closes the given device.
2863 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2865 ALCdevice *volatile*list;
2866 ALCcontext *ctx;
2868 LockLists();
2869 list = &DeviceList;
2870 while(*list && *list != Device)
2871 list = &(*list)->next;
2873 if(!*list || (*list)->Type == Capture)
2875 alcSetError(*list, ALC_INVALID_DEVICE);
2876 UnlockLists();
2877 return ALC_FALSE;
2880 *list = (*list)->next;
2881 UnlockLists();
2883 while((ctx=Device->ContextList) != NULL)
2885 WARN("Releasing context %p\n", ctx);
2886 ReleaseContext(ctx, Device);
2888 if((Device->Flags&DEVICE_RUNNING))
2889 ALCdevice_StopPlayback(Device);
2890 Device->Flags &= ~DEVICE_RUNNING;
2892 ALCdevice_DecRef(Device);
2894 return ALC_TRUE;
2898 /************************************************
2899 * ALC capture functions
2900 ************************************************/
2901 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2903 ALCdevice *device = NULL;
2904 ALCenum err;
2906 DO_INITCONFIG();
2908 if(!CaptureBackend.name)
2910 alcSetError(NULL, ALC_INVALID_VALUE);
2911 return NULL;
2914 if(samples <= 0)
2916 alcSetError(NULL, ALC_INVALID_VALUE);
2917 return NULL;
2920 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2921 deviceName = NULL;
2923 device = al_calloc(16, sizeof(ALCdevice));
2924 if(!device)
2926 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2927 return NULL;
2930 //Validate device
2931 device->Funcs = &CaptureBackend.Funcs;
2932 device->ref = 1;
2933 device->Connected = ALC_TRUE;
2934 device->Type = Capture;
2935 InitializeCriticalSection(&device->Mutex);
2937 InitUIntMap(&device->BufferMap, ~0);
2938 InitUIntMap(&device->EffectMap, ~0);
2939 InitUIntMap(&device->FilterMap, ~0);
2941 device->DeviceName = NULL;
2943 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2944 device->Frequency = frequency;
2946 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2947 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2949 DeleteCriticalSection(&device->Mutex);
2950 al_free(device);
2951 alcSetError(NULL, ALC_INVALID_ENUM);
2952 return NULL;
2955 device->UpdateSize = samples;
2956 device->NumUpdates = 1;
2958 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2960 DeleteCriticalSection(&device->Mutex);
2961 al_free(device);
2962 alcSetError(NULL, err);
2963 return NULL;
2966 do {
2967 device->next = DeviceList;
2968 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2970 TRACE("Created device %p\n", device);
2971 return device;
2974 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2976 ALCdevice *volatile*list;
2978 LockLists();
2979 list = &DeviceList;
2980 while(*list && *list != Device)
2981 list = &(*list)->next;
2983 if(!*list || (*list)->Type != Capture)
2985 alcSetError(*list, ALC_INVALID_DEVICE);
2986 UnlockLists();
2987 return ALC_FALSE;
2990 *list = (*list)->next;
2991 UnlockLists();
2993 ALCdevice_DecRef(Device);
2995 return ALC_TRUE;
2998 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3000 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3001 alcSetError(device, ALC_INVALID_DEVICE);
3002 else
3004 ALCdevice_Lock(device);
3005 if(device->Connected)
3007 if(!(device->Flags&DEVICE_RUNNING))
3008 ALCdevice_StartCapture(device);
3009 device->Flags |= DEVICE_RUNNING;
3011 ALCdevice_Unlock(device);
3014 if(device) ALCdevice_DecRef(device);
3017 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3019 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3020 alcSetError(device, ALC_INVALID_DEVICE);
3021 else
3023 ALCdevice_Lock(device);
3024 if((device->Flags&DEVICE_RUNNING))
3025 ALCdevice_StopCapture(device);
3026 device->Flags &= ~DEVICE_RUNNING;
3027 ALCdevice_Unlock(device);
3030 if(device) ALCdevice_DecRef(device);
3033 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3035 if(!(device=VerifyDevice(device)) && device->Type != Capture)
3036 alcSetError(device, ALC_INVALID_DEVICE);
3037 else
3039 ALCenum err = ALC_INVALID_VALUE;
3041 ALCdevice_Lock(device);
3042 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3043 err = ALCdevice_CaptureSamples(device, buffer, samples);
3044 ALCdevice_Unlock(device);
3046 if(err != ALC_NO_ERROR)
3047 alcSetError(device, err);
3049 if(device) ALCdevice_DecRef(device);
3053 /************************************************
3054 * ALC loopback functions
3055 ************************************************/
3057 /* alcLoopbackOpenDeviceSOFT
3059 * Open a loopback device, for manual rendering.
3061 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3063 ALCdevice *device;
3065 DO_INITCONFIG();
3067 /* Make sure the device name, if specified, is us. */
3068 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3070 alcSetError(NULL, ALC_INVALID_VALUE);
3071 return NULL;
3074 device = al_calloc(16, sizeof(ALCdevice));
3075 if(!device)
3077 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3078 return NULL;
3081 //Validate device
3082 device->Funcs = &BackendLoopback.Funcs;
3083 device->ref = 1;
3084 device->Connected = ALC_TRUE;
3085 device->Type = Loopback;
3086 InitializeCriticalSection(&device->Mutex);
3087 device->LastError = ALC_NO_ERROR;
3089 device->Flags = 0;
3090 device->Bs2b = NULL;
3091 device->Bs2bLevel = 0;
3092 device->DeviceName = NULL;
3094 device->ContextList = NULL;
3096 device->MaxNoOfSources = 256;
3097 device->AuxiliaryEffectSlotMax = 4;
3098 device->NumAuxSends = MAX_SENDS;
3100 InitUIntMap(&device->BufferMap, ~0);
3101 InitUIntMap(&device->EffectMap, ~0);
3102 InitUIntMap(&device->FilterMap, ~0);
3104 //Set output format
3105 device->NumUpdates = 0;
3106 device->UpdateSize = 0;
3108 device->Frequency = DEFAULT_OUTPUT_RATE;
3109 device->FmtChans = DevFmtChannelsDefault;
3110 device->FmtType = DevFmtTypeDefault;
3112 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3113 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3115 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3116 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3118 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3119 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3121 device->NumStereoSources = 1;
3122 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3124 // Open the "backend"
3125 ALCdevice_OpenPlayback(device, "Loopback");
3126 do {
3127 device->next = DeviceList;
3128 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3130 TRACE("Created device %p\n", device);
3131 return device;
3134 /* alcIsRenderFormatSupportedSOFT
3136 * Determines if the loopback device supports the given format for rendering.
3138 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3140 ALCboolean ret = ALC_FALSE;
3142 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3143 alcSetError(device, ALC_INVALID_DEVICE);
3144 else if(freq <= 0)
3145 alcSetError(device, ALC_INVALID_VALUE);
3146 else
3148 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3149 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3150 freq >= MIN_OUTPUT_RATE)
3151 ret = ALC_TRUE;
3153 if(device) ALCdevice_DecRef(device);
3155 return ret;
3158 /* alcRenderSamplesSOFT
3160 * Renders some samples into a buffer, using the format last set by the
3161 * attributes given to alcCreateContext.
3163 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3165 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3166 alcSetError(device, ALC_INVALID_DEVICE);
3167 else if(samples < 0 || (samples > 0 && buffer == NULL))
3168 alcSetError(device, ALC_INVALID_VALUE);
3169 else
3170 aluMixData(device, buffer, samples);
3171 if(device) ALCdevice_DecRef(device);