Rename cmake options so GUIs order them better
[openal-soft.git] / Alc / ALc.c
blobfd5b8894d8a5e63b51cf6bc59ff9da3ea582d1ae
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_SOFT_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);
806 char buf[1024] = "";
807 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
808 for(i = 1;BackendList[i].name;i++)
809 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
810 TRACE("Supported backends: %s\n", buf);
812 ReadALConfig();
814 capfilter = 0;
815 #ifdef HAVE_SSE
816 capfilter |= CPU_CAP_SSE;
817 #endif
818 #ifdef HAVE_NEON
819 capfilter |= CPU_CAP_NEON;
820 #endif
821 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
823 if(strcasecmp(str, "all") == 0)
824 capfilter = 0;
825 else
827 size_t len;
828 const char *next = str;
830 i = 0;
831 do {
832 str = next;
833 next = strchr(str, ',');
835 while(isspace(str[0]))
836 str++;
837 if(!str[0] || str[0] == ',')
838 continue;
840 len = (next ? ((size_t)(next-str)) : strlen(str));
841 if(strncasecmp(str, "sse", len) == 0)
842 capfilter &= ~CPU_CAP_SSE;
843 else if(strncasecmp(str, "neon", len) == 0)
844 capfilter &= ~CPU_CAP_NEON;
845 else
846 WARN("Invalid CPU extension \"%s\"\n", str);
847 } while(next++);
850 FillCPUCaps(capfilter);
852 #ifdef _WIN32
853 RTPrioLevel = 1;
854 #else
855 RTPrioLevel = 0;
856 #endif
857 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
859 if(ConfigValueStr(NULL, "resampler", &str))
861 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
862 DefaultResampler = PointResampler;
863 else if(strcasecmp(str, "linear") == 0)
864 DefaultResampler = LinearResampler;
865 else if(strcasecmp(str, "cubic") == 0)
866 DefaultResampler = CubicResampler;
867 else
869 char *end;
871 n = strtol(str, &end, 0);
872 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
873 DefaultResampler = n;
874 else
875 WARN("Invalid resampler: %s\n", str);
879 str = getenv("ALSOFT_TRAP_ERROR");
880 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
882 TrapALError = AL_TRUE;
883 TrapALCError = AL_TRUE;
885 else
887 str = getenv("ALSOFT_TRAP_AL_ERROR");
888 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
889 TrapALError = AL_TRUE;
890 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
892 str = getenv("ALSOFT_TRAP_ALC_ERROR");
893 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
894 TrapALCError = ALC_TRUE;
895 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
898 if(ConfigValueFloat("reverb", "boost", &valf))
899 ReverbBoost *= powf(10.0f, valf / 20.0f);
901 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
903 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
904 ConfigValueStr(NULL, "drivers", &devs))
906 int n;
907 size_t len;
908 const char *next = devs;
909 int endlist, delitem;
911 i = 0;
912 do {
913 devs = next;
914 next = strchr(devs, ',');
916 delitem = (devs[0] == '-');
917 if(devs[0] == '-') devs++;
919 if(!devs[0] || devs[0] == ',')
921 endlist = 0;
922 continue;
924 endlist = 1;
926 len = (next ? ((size_t)(next-devs)) : strlen(devs));
927 for(n = i;BackendList[n].Init;n++)
929 if(len == strlen(BackendList[n].name) &&
930 strncmp(BackendList[n].name, devs, len) == 0)
932 if(delitem)
934 do {
935 BackendList[n] = BackendList[n+1];
936 ++n;
937 } while(BackendList[n].Init);
939 else
941 struct BackendInfo Bkp = BackendList[n];
942 while(n > i)
944 BackendList[n] = BackendList[n-1];
945 --n;
947 BackendList[n] = Bkp;
949 i++;
951 break;
954 } while(next++);
956 if(endlist)
958 BackendList[i].name = NULL;
959 BackendList[i].Init = NULL;
960 BackendList[i].Deinit = NULL;
961 BackendList[i].Probe = NULL;
965 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
967 if(!BackendList[i].Init(&BackendList[i].Funcs))
969 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
970 continue;
973 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
974 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
976 PlaybackBackend = BackendList[i];
977 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
979 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
981 CaptureBackend = BackendList[i];
982 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
985 BackendLoopback.Init(&BackendLoopback.Funcs);
987 if(ConfigValueStr(NULL, "excludefx", &str))
989 size_t len;
990 const char *next = str;
992 do {
993 str = next;
994 next = strchr(str, ',');
996 if(!str[0] || next == str)
997 continue;
999 len = (next ? ((size_t)(next-str)) : strlen(str));
1000 for(n = 0;EffectList[n].name;n++)
1002 if(len == strlen(EffectList[n].name) &&
1003 strncmp(EffectList[n].name, str, len) == 0)
1004 DisabledEffects[EffectList[n].type] = AL_TRUE;
1006 } while(next++);
1009 InitEffect(&DefaultEffect);
1010 str = getenv("ALSOFT_DEFAULT_REVERB");
1011 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1012 LoadReverbPreset(str, &DefaultEffect);
1014 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1017 /************************************************
1018 * Library deinitialization
1019 ************************************************/
1020 static void alc_cleanup(void)
1022 ALCdevice *dev;
1024 free(alcAllDevicesList); alcAllDevicesList = NULL;
1025 alcAllDevicesListSize = 0;
1026 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1027 alcCaptureDeviceListSize = 0;
1029 free(alcDefaultAllDevicesSpecifier);
1030 alcDefaultAllDevicesSpecifier = NULL;
1031 free(alcCaptureDefaultDeviceSpecifier);
1032 alcCaptureDefaultDeviceSpecifier = NULL;
1034 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1036 ALCuint num = 0;
1037 do {
1038 num++;
1039 } while((dev=dev->next) != NULL);
1040 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1044 static void alc_deinit_safe(void)
1046 alc_cleanup();
1048 FreeHrtfs();
1049 FreeALConfig();
1051 ThunkExit();
1052 DeleteCriticalSection(&ListLock);
1053 pthread_key_delete(LocalContext);
1055 if(LogFile != stderr)
1056 fclose(LogFile);
1057 LogFile = NULL;
1060 static void alc_deinit(void)
1062 int i;
1064 alc_cleanup();
1066 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1067 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1069 for(i = 0;BackendList[i].Deinit;i++)
1070 BackendList[i].Deinit();
1071 BackendLoopback.Deinit();
1073 alc_deinit_safe();
1077 /************************************************
1078 * Device enumeration
1079 ************************************************/
1080 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1082 DO_INITCONFIG();
1084 LockLists();
1085 free(*list);
1086 *list = NULL;
1087 *listsize = 0;
1089 if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe)
1090 PlaybackBackend.Probe(type);
1091 else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe)
1092 CaptureBackend.Probe(type);
1093 UnlockLists();
1096 static void ProbeAllDevicesList(void)
1097 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1098 static void ProbeCaptureDeviceList(void)
1099 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1102 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1104 size_t len = strlen(name);
1105 void *temp;
1107 if(len == 0)
1108 return;
1110 temp = realloc(*List, (*ListSize) + len + 2);
1111 if(!temp)
1113 ERR("Realloc failed to add %s!\n", name);
1114 return;
1116 *List = temp;
1118 memcpy((*List)+(*ListSize), name, len+1);
1119 *ListSize += len+1;
1120 (*List)[*ListSize] = 0;
1123 #define DECL_APPEND_LIST_FUNC(type) \
1124 void Append##type##List(const ALCchar *name) \
1125 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1127 DECL_APPEND_LIST_FUNC(AllDevices)
1128 DECL_APPEND_LIST_FUNC(CaptureDevice)
1130 #undef DECL_APPEND_LIST_FUNC
1133 /************************************************
1134 * Device format information
1135 ************************************************/
1136 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1138 switch(type)
1140 case DevFmtByte: return "Signed Byte";
1141 case DevFmtUByte: return "Unsigned Byte";
1142 case DevFmtShort: return "Signed Short";
1143 case DevFmtUShort: return "Unsigned Short";
1144 case DevFmtInt: return "Signed Int";
1145 case DevFmtUInt: return "Unsigned Int";
1146 case DevFmtFloat: return "Float";
1148 return "(unknown type)";
1150 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1152 switch(chans)
1154 case DevFmtMono: return "Mono";
1155 case DevFmtStereo: return "Stereo";
1156 case DevFmtQuad: return "Quadraphonic";
1157 case DevFmtX51: return "5.1 Surround";
1158 case DevFmtX51Side: return "5.1 Side";
1159 case DevFmtX61: return "6.1 Surround";
1160 case DevFmtX71: return "7.1 Surround";
1162 return "(unknown channels)";
1165 ALuint BytesFromDevFmt(enum DevFmtType type)
1167 switch(type)
1169 case DevFmtByte: return sizeof(ALbyte);
1170 case DevFmtUByte: return sizeof(ALubyte);
1171 case DevFmtShort: return sizeof(ALshort);
1172 case DevFmtUShort: return sizeof(ALushort);
1173 case DevFmtInt: return sizeof(ALint);
1174 case DevFmtUInt: return sizeof(ALuint);
1175 case DevFmtFloat: return sizeof(ALfloat);
1177 return 0;
1179 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1181 switch(chans)
1183 case DevFmtMono: return 1;
1184 case DevFmtStereo: return 2;
1185 case DevFmtQuad: return 4;
1186 case DevFmtX51: return 6;
1187 case DevFmtX51Side: return 6;
1188 case DevFmtX61: return 7;
1189 case DevFmtX71: return 8;
1191 return 0;
1194 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1195 enum DevFmtType *type)
1197 static const struct {
1198 ALenum format;
1199 enum DevFmtChannels channels;
1200 enum DevFmtType type;
1201 } list[] = {
1202 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1203 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1204 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1206 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1207 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1208 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1210 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1211 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1212 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1214 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1215 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1216 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1218 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1219 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1220 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1222 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1223 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1224 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1226 ALuint i;
1228 for(i = 0;i < COUNTOF(list);i++)
1230 if(list[i].format == format)
1232 *chans = list[i].channels;
1233 *type = list[i].type;
1234 return AL_TRUE;
1238 return AL_FALSE;
1241 static ALCboolean IsValidALCType(ALCenum type)
1243 switch(type)
1245 case ALC_BYTE_SOFT:
1246 case ALC_UNSIGNED_BYTE_SOFT:
1247 case ALC_SHORT_SOFT:
1248 case ALC_UNSIGNED_SHORT_SOFT:
1249 case ALC_INT_SOFT:
1250 case ALC_UNSIGNED_INT_SOFT:
1251 case ALC_FLOAT_SOFT:
1252 return ALC_TRUE;
1254 return ALC_FALSE;
1257 static ALCboolean IsValidALCChannels(ALCenum channels)
1259 switch(channels)
1261 case ALC_MONO_SOFT:
1262 case ALC_STEREO_SOFT:
1263 case ALC_QUAD_SOFT:
1264 case ALC_5POINT1_SOFT:
1265 case ALC_6POINT1_SOFT:
1266 case ALC_7POINT1_SOFT:
1267 return ALC_TRUE;
1269 return ALC_FALSE;
1273 /************************************************
1274 * Miscellaneous ALC helpers
1275 ************************************************/
1277 void ALCdevice_LockDefault(ALCdevice *device)
1279 EnterCriticalSection(&device->Mutex);
1281 void ALCdevice_UnlockDefault(ALCdevice *device)
1283 LeaveCriticalSection(&device->Mutex);
1285 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
1287 (void)device;
1288 return 0;
1291 /* SetDefaultWFXChannelOrder
1293 * Sets the default channel order used by WaveFormatEx.
1295 void SetDefaultWFXChannelOrder(ALCdevice *device)
1297 ALuint i;
1299 for(i = 0;i < MaxChannels;i++)
1300 device->ChannelOffsets[i] = INVALID_OFFSET;
1302 switch(device->FmtChans)
1304 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1305 break;
1306 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1307 device->ChannelOffsets[FrontRight] = 1;
1308 break;
1309 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1310 device->ChannelOffsets[FrontRight] = 1;
1311 device->ChannelOffsets[BackLeft] = 2;
1312 device->ChannelOffsets[BackRight] = 3;
1313 break;
1314 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1315 device->ChannelOffsets[FrontRight] = 1;
1316 device->ChannelOffsets[FrontCenter] = 2;
1317 device->ChannelOffsets[LFE] = 3;
1318 device->ChannelOffsets[BackLeft] = 4;
1319 device->ChannelOffsets[BackRight] = 5;
1320 break;
1321 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1322 device->ChannelOffsets[FrontRight] = 1;
1323 device->ChannelOffsets[FrontCenter] = 2;
1324 device->ChannelOffsets[LFE] = 3;
1325 device->ChannelOffsets[SideLeft] = 4;
1326 device->ChannelOffsets[SideRight] = 5;
1327 break;
1328 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1329 device->ChannelOffsets[FrontRight] = 1;
1330 device->ChannelOffsets[FrontCenter] = 2;
1331 device->ChannelOffsets[LFE] = 3;
1332 device->ChannelOffsets[BackCenter] = 4;
1333 device->ChannelOffsets[SideLeft] = 5;
1334 device->ChannelOffsets[SideRight] = 6;
1335 break;
1336 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1337 device->ChannelOffsets[FrontRight] = 1;
1338 device->ChannelOffsets[FrontCenter] = 2;
1339 device->ChannelOffsets[LFE] = 3;
1340 device->ChannelOffsets[BackLeft] = 4;
1341 device->ChannelOffsets[BackRight] = 5;
1342 device->ChannelOffsets[SideLeft] = 6;
1343 device->ChannelOffsets[SideRight] = 7;
1344 break;
1348 /* SetDefaultChannelOrder
1350 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1352 void SetDefaultChannelOrder(ALCdevice *device)
1354 ALuint i;
1356 for(i = 0;i < MaxChannels;i++)
1357 device->ChannelOffsets[i] = INVALID_OFFSET;
1359 switch(device->FmtChans)
1361 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1362 device->ChannelOffsets[FrontRight] = 1;
1363 device->ChannelOffsets[BackLeft] = 2;
1364 device->ChannelOffsets[BackRight] = 3;
1365 device->ChannelOffsets[FrontCenter] = 4;
1366 device->ChannelOffsets[LFE] = 5;
1367 return;
1368 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1369 device->ChannelOffsets[FrontRight] = 1;
1370 device->ChannelOffsets[BackLeft] = 2;
1371 device->ChannelOffsets[BackRight] = 3;
1372 device->ChannelOffsets[FrontCenter] = 4;
1373 device->ChannelOffsets[LFE] = 5;
1374 device->ChannelOffsets[SideLeft] = 6;
1375 device->ChannelOffsets[SideRight] = 7;
1376 return;
1378 /* Same as WFX order */
1379 case DevFmtMono:
1380 case DevFmtStereo:
1381 case DevFmtQuad:
1382 case DevFmtX51Side:
1383 case DevFmtX61:
1384 break;
1386 SetDefaultWFXChannelOrder(device);
1390 /* alcSetError
1392 * Stores the latest ALC device error
1394 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1396 if(TrapALCError)
1398 #ifdef _WIN32
1399 /* DebugBreak() will cause an exception if there is no debugger */
1400 if(IsDebuggerPresent())
1401 DebugBreak();
1402 #elif defined(SIGTRAP)
1403 raise(SIGTRAP);
1404 #endif
1407 if(device)
1408 device->LastError = errorCode;
1409 else
1410 LastNullDeviceError = errorCode;
1414 /* UpdateDeviceParams
1416 * Updates device parameters according to the attribute list (caller is
1417 * responsible for holding the list lock).
1419 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1421 ALCcontext *context;
1422 enum DevFmtChannels oldChans;
1423 enum DevFmtType oldType;
1424 ALCuint oldFreq;
1425 FPUCtl oldMode;
1426 ALuint i;
1428 // Check for attributes
1429 if(device->Type == Loopback)
1431 enum {
1432 GotFreq = 1<<0,
1433 GotChans = 1<<1,
1434 GotType = 1<<2,
1435 GotAll = GotFreq|GotChans|GotType
1437 ALCuint freq, numMono, numStereo, numSends;
1438 enum DevFmtChannels schans;
1439 enum DevFmtType stype;
1440 ALCuint attrIdx = 0;
1441 ALCint gotFmt = 0;
1443 if(!attrList)
1445 WARN("Missing attributes for loopback device\n");
1446 return ALC_INVALID_VALUE;
1449 numMono = device->NumMonoSources;
1450 numStereo = device->NumStereoSources;
1451 numSends = device->NumAuxSends;
1452 schans = device->FmtChans;
1453 stype = device->FmtType;
1454 freq = device->Frequency;
1456 while(attrList[attrIdx])
1458 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1460 ALCint val = attrList[attrIdx + 1];
1461 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1462 return ALC_INVALID_VALUE;
1463 schans = val;
1464 gotFmt |= GotChans;
1467 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1469 ALCint val = attrList[attrIdx + 1];
1470 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1471 return ALC_INVALID_VALUE;
1472 stype = val;
1473 gotFmt |= GotType;
1476 if(attrList[attrIdx] == ALC_FREQUENCY)
1478 freq = attrList[attrIdx + 1];
1479 if(freq < MIN_OUTPUT_RATE)
1480 return ALC_INVALID_VALUE;
1481 gotFmt |= GotFreq;
1484 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1486 numStereo = attrList[attrIdx + 1];
1487 if(numStereo > device->MaxNoOfSources)
1488 numStereo = device->MaxNoOfSources;
1490 numMono = device->MaxNoOfSources - numStereo;
1493 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1494 numSends = attrList[attrIdx + 1];
1496 attrIdx += 2;
1499 if(gotFmt != GotAll)
1501 WARN("Missing format for loopback device\n");
1502 return ALC_INVALID_VALUE;
1505 ConfigValueUInt(NULL, "sends", &numSends);
1506 numSends = minu(MAX_SENDS, numSends);
1508 if((device->Flags&DEVICE_RUNNING))
1509 ALCdevice_StopPlayback(device);
1510 device->Flags &= ~DEVICE_RUNNING;
1512 device->Frequency = freq;
1513 device->FmtChans = schans;
1514 device->FmtType = stype;
1515 device->NumMonoSources = numMono;
1516 device->NumStereoSources = numStereo;
1517 device->NumAuxSends = numSends;
1519 else if(attrList && attrList[0])
1521 ALCuint freq, numMono, numStereo, numSends;
1522 ALCuint attrIdx = 0;
1524 /* If a context is already running on the device, stop playback so the
1525 * device attributes can be updated. */
1526 if((device->Flags&DEVICE_RUNNING))
1527 ALCdevice_StopPlayback(device);
1528 device->Flags &= ~DEVICE_RUNNING;
1530 freq = device->Frequency;
1531 numMono = device->NumMonoSources;
1532 numStereo = device->NumStereoSources;
1533 numSends = device->NumAuxSends;
1535 while(attrList[attrIdx])
1537 if(attrList[attrIdx] == ALC_FREQUENCY)
1539 freq = attrList[attrIdx + 1];
1540 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1543 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1545 numStereo = attrList[attrIdx + 1];
1546 if(numStereo > device->MaxNoOfSources)
1547 numStereo = device->MaxNoOfSources;
1549 numMono = device->MaxNoOfSources - numStereo;
1552 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1553 numSends = attrList[attrIdx + 1];
1555 attrIdx += 2;
1558 ConfigValueUInt(NULL, "frequency", &freq);
1559 freq = maxu(freq, MIN_OUTPUT_RATE);
1561 ConfigValueUInt(NULL, "sends", &numSends);
1562 numSends = minu(MAX_SENDS, numSends);
1564 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1565 device->Frequency;
1566 /* SSE does best with the update size being a multiple of 4 */
1567 if((CPUCapFlags&CPU_CAP_SSE))
1568 device->UpdateSize = (device->UpdateSize+3)&~3;
1570 device->Frequency = freq;
1571 device->NumMonoSources = numMono;
1572 device->NumStereoSources = numStereo;
1573 device->NumAuxSends = numSends;
1576 if((device->Flags&DEVICE_RUNNING))
1577 return ALC_NO_ERROR;
1579 oldFreq = device->Frequency;
1580 oldChans = device->FmtChans;
1581 oldType = device->FmtType;
1583 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1584 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1585 DevFmtChannelsString(device->FmtChans),
1586 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1587 DevFmtTypeString(device->FmtType),
1588 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1589 device->Frequency,
1590 device->UpdateSize, device->NumUpdates);
1592 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1593 return ALC_INVALID_DEVICE;
1595 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1597 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1598 DevFmtChannelsString(device->FmtChans));
1599 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1601 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1603 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1604 DevFmtTypeString(device->FmtType));
1605 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1607 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1609 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1610 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1613 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1614 DevFmtChannelsString(device->FmtChans),
1615 DevFmtTypeString(device->FmtType), device->Frequency,
1616 device->UpdateSize, device->NumUpdates);
1618 aluInitPanning(device);
1620 for(i = 0;i < MaxChannels;i++)
1622 device->ClickRemoval[i] = 0.0f;
1623 device->PendingClicks[i] = 0.0f;
1626 device->Hrtf = NULL;
1627 if(device->Type != Loopback && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
1628 device->Hrtf = GetHrtf(device);
1629 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1631 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1633 if(!device->Bs2b)
1635 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1636 bs2b_clear(device->Bs2b);
1638 bs2b_set_srate(device->Bs2b, device->Frequency);
1639 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1640 TRACE("BS2B level %d\n", device->Bs2bLevel);
1642 else
1644 free(device->Bs2b);
1645 device->Bs2b = NULL;
1646 TRACE("BS2B disabled\n");
1649 device->Flags &= ~DEVICE_WIDE_STEREO;
1650 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1651 device->Flags |= DEVICE_WIDE_STEREO;
1653 if(!device->Hrtf && (device->UpdateSize&3))
1655 if((CPUCapFlags&CPU_CAP_SSE))
1656 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1659 SetMixerFPUMode(&oldMode);
1660 ALCdevice_Lock(device);
1661 context = device->ContextList;
1662 while(context)
1664 ALsizei pos;
1666 context->UpdateSources = AL_FALSE;
1667 LockUIntMapRead(&context->EffectSlotMap);
1668 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1670 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1672 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1674 UnlockUIntMapRead(&context->EffectSlotMap);
1675 ALCdevice_Unlock(device);
1676 RestoreFPUMode(&oldMode);
1677 return ALC_INVALID_DEVICE;
1679 slot->NeedsUpdate = AL_FALSE;
1680 ALeffectState_Update(slot->EffectState, device, slot);
1682 UnlockUIntMapRead(&context->EffectSlotMap);
1684 LockUIntMapRead(&context->SourceMap);
1685 for(pos = 0;pos < context->SourceMap.size;pos++)
1687 ALsource *source = context->SourceMap.array[pos].value;
1688 ALuint s = device->NumAuxSends;
1689 while(s < MAX_SENDS)
1691 if(source->Send[s].Slot)
1692 DecrementRef(&source->Send[s].Slot->ref);
1693 source->Send[s].Slot = NULL;
1694 source->Send[s].Gain = 1.0f;
1695 source->Send[s].GainHF = 1.0f;
1696 s++;
1698 source->NeedsUpdate = AL_FALSE;
1699 ALsource_Update(source, context);
1701 UnlockUIntMapRead(&context->SourceMap);
1703 context = context->next;
1705 if(device->DefaultSlot)
1707 ALeffectslot *slot = device->DefaultSlot;
1709 if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1711 ALCdevice_Unlock(device);
1712 RestoreFPUMode(&oldMode);
1713 return ALC_INVALID_DEVICE;
1715 slot->NeedsUpdate = AL_FALSE;
1716 ALeffectState_Update(slot->EffectState, device, slot);
1718 ALCdevice_Unlock(device);
1719 RestoreFPUMode(&oldMode);
1721 if(ALCdevice_StartPlayback(device) == ALC_FALSE)
1722 return ALC_INVALID_DEVICE;
1723 device->Flags |= DEVICE_RUNNING;
1725 return ALC_NO_ERROR;
1728 /* FreeDevice
1730 * Frees the device structure, and destroys any objects the app failed to
1731 * delete. Called once there's no more references on the device.
1733 static ALCvoid FreeDevice(ALCdevice *device)
1735 TRACE("%p\n", device);
1737 if(device->Type != Capture)
1738 ALCdevice_ClosePlayback(device);
1739 else
1740 ALCdevice_CloseCapture(device);
1742 if(device->DefaultSlot)
1744 ALeffectState_Destroy(device->DefaultSlot->EffectState);
1745 device->DefaultSlot->EffectState = NULL;
1748 if(device->BufferMap.size > 0)
1750 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1751 ReleaseALBuffers(device);
1753 ResetUIntMap(&device->BufferMap);
1755 if(device->EffectMap.size > 0)
1757 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1758 ReleaseALEffects(device);
1760 ResetUIntMap(&device->EffectMap);
1762 if(device->FilterMap.size > 0)
1764 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1765 ReleaseALFilters(device);
1767 ResetUIntMap(&device->FilterMap);
1769 free(device->Bs2b);
1770 device->Bs2b = NULL;
1772 free(device->DeviceName);
1773 device->DeviceName = NULL;
1775 DeleteCriticalSection(&device->Mutex);
1777 al_free(device);
1781 void ALCdevice_IncRef(ALCdevice *device)
1783 RefCount ref;
1784 ref = IncrementRef(&device->ref);
1785 TRACEREF("%p increasing refcount to %u\n", device, ref);
1788 void ALCdevice_DecRef(ALCdevice *device)
1790 RefCount ref;
1791 ref = DecrementRef(&device->ref);
1792 TRACEREF("%p decreasing refcount to %u\n", device, ref);
1793 if(ref == 0) FreeDevice(device);
1796 /* VerifyDevice
1798 * Checks if the device handle is valid, and increments its ref count if so.
1800 static ALCdevice *VerifyDevice(ALCdevice *device)
1802 ALCdevice *tmpDevice;
1804 if(!device)
1805 return NULL;
1807 LockLists();
1808 tmpDevice = DeviceList;
1809 while(tmpDevice && tmpDevice != device)
1810 tmpDevice = tmpDevice->next;
1812 if(tmpDevice)
1813 ALCdevice_IncRef(tmpDevice);
1814 UnlockLists();
1815 return tmpDevice;
1819 /* InitContext
1821 * Initializes context fields
1823 static ALvoid InitContext(ALCcontext *Context)
1825 ALint i, j;
1827 //Initialise listener
1828 Context->Listener->Gain = 1.0f;
1829 Context->Listener->MetersPerUnit = 1.0f;
1830 Context->Listener->Position[0] = 0.0f;
1831 Context->Listener->Position[1] = 0.0f;
1832 Context->Listener->Position[2] = 0.0f;
1833 Context->Listener->Velocity[0] = 0.0f;
1834 Context->Listener->Velocity[1] = 0.0f;
1835 Context->Listener->Velocity[2] = 0.0f;
1836 Context->Listener->Forward[0] = 0.0f;
1837 Context->Listener->Forward[1] = 0.0f;
1838 Context->Listener->Forward[2] = -1.0f;
1839 Context->Listener->Up[0] = 0.0f;
1840 Context->Listener->Up[1] = 1.0f;
1841 Context->Listener->Up[2] = 0.0f;
1842 for(i = 0;i < 4;i++)
1844 for(j = 0;j < 4;j++)
1845 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
1847 for(i = 0;i < 3;i++)
1848 Context->Listener->Params.Velocity[i] = 0.0f;
1850 //Validate Context
1851 Context->LastError = AL_NO_ERROR;
1852 Context->UpdateSources = AL_FALSE;
1853 Context->ActiveSourceCount = 0;
1854 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
1855 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
1857 //Set globals
1858 Context->DistanceModel = DefaultDistanceModel;
1859 Context->SourceDistanceModel = AL_FALSE;
1860 Context->DopplerFactor = 1.0f;
1861 Context->DopplerVelocity = 1.0f;
1862 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
1863 Context->DeferUpdates = AL_FALSE;
1865 Context->ExtensionList = alExtList;
1869 /* FreeContext
1871 * Cleans up the context, and destroys any remaining objects the app failed to
1872 * delete. Called once there's no more references on the context.
1874 static ALCvoid FreeContext(ALCcontext *context)
1876 TRACE("%p\n", context);
1878 if(context->SourceMap.size > 0)
1880 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
1881 ReleaseALSources(context);
1883 ResetUIntMap(&context->SourceMap);
1885 if(context->EffectSlotMap.size > 0)
1887 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
1888 ReleaseALAuxiliaryEffectSlots(context);
1890 ResetUIntMap(&context->EffectSlotMap);
1892 context->ActiveSourceCount = 0;
1893 free(context->ActiveSources);
1894 context->ActiveSources = NULL;
1895 context->MaxActiveSources = 0;
1897 context->ActiveEffectSlotCount = 0;
1898 free(context->ActiveEffectSlots);
1899 context->ActiveEffectSlots = NULL;
1900 context->MaxActiveEffectSlots = 0;
1902 ALCdevice_DecRef(context->Device);
1903 context->Device = NULL;
1905 //Invalidate context
1906 memset(context, 0, sizeof(ALCcontext));
1907 free(context);
1910 /* ReleaseContext
1912 * Removes the context reference from the given device and removes it from
1913 * being current on the running thread or globally.
1915 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
1917 ALCcontext *volatile*tmp_ctx;
1919 if(pthread_getspecific(LocalContext) == context)
1921 WARN("%p released while current on thread\n", context);
1922 pthread_setspecific(LocalContext, NULL);
1923 ALCcontext_DecRef(context);
1926 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL))
1927 ALCcontext_DecRef(context);
1929 ALCdevice_Lock(device);
1930 tmp_ctx = &device->ContextList;
1931 while(*tmp_ctx)
1933 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next))
1934 break;
1935 tmp_ctx = &(*tmp_ctx)->next;
1937 ALCdevice_Unlock(device);
1939 ALCcontext_DecRef(context);
1942 void ALCcontext_IncRef(ALCcontext *context)
1944 RefCount ref;
1945 ref = IncrementRef(&context->ref);
1946 TRACEREF("%p increasing refcount to %u\n", context, ref);
1949 void ALCcontext_DecRef(ALCcontext *context)
1951 RefCount ref;
1952 ref = DecrementRef(&context->ref);
1953 TRACEREF("%p decreasing refcount to %u\n", context, ref);
1954 if(ref == 0) FreeContext(context);
1957 static void ReleaseThreadCtx(void *ptr)
1959 WARN("%p current for thread being destroyed\n", ptr);
1960 ALCcontext_DecRef(ptr);
1963 /* VerifyContext
1965 * Checks that the given context is valid, and increments its reference count.
1967 static ALCcontext *VerifyContext(ALCcontext *context)
1969 ALCdevice *dev;
1971 LockLists();
1972 dev = DeviceList;
1973 while(dev)
1975 ALCcontext *tmp_ctx = dev->ContextList;
1976 while(tmp_ctx)
1978 if(tmp_ctx == context)
1980 ALCcontext_IncRef(tmp_ctx);
1981 UnlockLists();
1982 return tmp_ctx;
1984 tmp_ctx = tmp_ctx->next;
1986 dev = dev->next;
1988 UnlockLists();
1990 return NULL;
1994 /* GetContextRef
1996 * Returns the currently active context for this thread, and adds a reference
1997 * without locking it.
1999 ALCcontext *GetContextRef(void)
2001 ALCcontext *context;
2003 context = pthread_getspecific(LocalContext);
2004 if(context)
2005 ALCcontext_IncRef(context);
2006 else
2008 LockLists();
2009 context = GlobalContext;
2010 if(context)
2011 ALCcontext_IncRef(context);
2012 UnlockLists();
2015 return context;
2019 /************************************************
2020 * Standard ALC functions
2021 ************************************************/
2023 /* alcGetError
2025 * Return last ALC generated error code for the given device
2027 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2029 ALCenum errorCode;
2031 if(VerifyDevice(device))
2033 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2034 ALCdevice_DecRef(device);
2036 else
2037 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2039 return errorCode;
2043 /* alcSuspendContext
2045 * Not functional
2047 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
2049 (void)Context;
2052 /* alcProcessContext
2054 * Not functional
2056 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
2058 (void)Context;
2062 /* alcGetString
2064 * Returns information about the device, and error strings
2066 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2068 const ALCchar *value = NULL;
2070 switch(param)
2072 case ALC_NO_ERROR:
2073 value = alcNoError;
2074 break;
2076 case ALC_INVALID_ENUM:
2077 value = alcErrInvalidEnum;
2078 break;
2080 case ALC_INVALID_VALUE:
2081 value = alcErrInvalidValue;
2082 break;
2084 case ALC_INVALID_DEVICE:
2085 value = alcErrInvalidDevice;
2086 break;
2088 case ALC_INVALID_CONTEXT:
2089 value = alcErrInvalidContext;
2090 break;
2092 case ALC_OUT_OF_MEMORY:
2093 value = alcErrOutOfMemory;
2094 break;
2096 case ALC_DEVICE_SPECIFIER:
2097 value = alcDefaultName;
2098 break;
2100 case ALC_ALL_DEVICES_SPECIFIER:
2101 if(VerifyDevice(Device))
2103 value = Device->DeviceName;
2104 ALCdevice_DecRef(Device);
2106 else
2108 ProbeAllDevicesList();
2109 value = alcAllDevicesList;
2111 break;
2113 case ALC_CAPTURE_DEVICE_SPECIFIER:
2114 if(VerifyDevice(Device))
2116 value = Device->DeviceName;
2117 ALCdevice_DecRef(Device);
2119 else
2121 ProbeCaptureDeviceList();
2122 value = alcCaptureDeviceList;
2124 break;
2126 /* Default devices are always first in the list */
2127 case ALC_DEFAULT_DEVICE_SPECIFIER:
2128 value = alcDefaultName;
2129 break;
2131 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2132 if(!alcAllDevicesList)
2133 ProbeAllDevicesList();
2135 Device = VerifyDevice(Device);
2137 free(alcDefaultAllDevicesSpecifier);
2138 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2139 alcAllDevicesList : "");
2140 if(!alcDefaultAllDevicesSpecifier)
2141 alcSetError(Device, ALC_OUT_OF_MEMORY);
2143 value = alcDefaultAllDevicesSpecifier;
2144 if(Device) ALCdevice_DecRef(Device);
2145 break;
2147 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2148 if(!alcCaptureDeviceList)
2149 ProbeCaptureDeviceList();
2151 Device = VerifyDevice(Device);
2153 free(alcCaptureDefaultDeviceSpecifier);
2154 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2155 alcCaptureDeviceList : "");
2156 if(!alcCaptureDefaultDeviceSpecifier)
2157 alcSetError(Device, ALC_OUT_OF_MEMORY);
2159 value = alcCaptureDefaultDeviceSpecifier;
2160 if(Device) ALCdevice_DecRef(Device);
2161 break;
2163 case ALC_EXTENSIONS:
2164 if(!VerifyDevice(Device))
2165 value = alcNoDeviceExtList;
2166 else
2168 value = alcExtensionList;
2169 ALCdevice_DecRef(Device);
2171 break;
2173 default:
2174 Device = VerifyDevice(Device);
2175 alcSetError(Device, ALC_INVALID_ENUM);
2176 if(Device) ALCdevice_DecRef(Device);
2177 break;
2180 return value;
2184 /* alcGetIntegerv
2186 * Returns information about the device and the version of OpenAL
2188 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
2190 device = VerifyDevice(device);
2192 if(size == 0 || data == NULL)
2194 alcSetError(device, ALC_INVALID_VALUE);
2195 if(device) ALCdevice_DecRef(device);
2196 return;
2199 if(!device)
2201 switch(param)
2203 case ALC_MAJOR_VERSION:
2204 *data = alcMajorVersion;
2205 break;
2206 case ALC_MINOR_VERSION:
2207 *data = alcMinorVersion;
2208 break;
2210 case ALC_ATTRIBUTES_SIZE:
2211 case ALC_ALL_ATTRIBUTES:
2212 case ALC_FREQUENCY:
2213 case ALC_REFRESH:
2214 case ALC_SYNC:
2215 case ALC_MONO_SOURCES:
2216 case ALC_STEREO_SOURCES:
2217 case ALC_CAPTURE_SAMPLES:
2218 case ALC_FORMAT_CHANNELS_SOFT:
2219 case ALC_FORMAT_TYPE_SOFT:
2220 alcSetError(NULL, ALC_INVALID_DEVICE);
2221 break;
2223 default:
2224 alcSetError(NULL, ALC_INVALID_ENUM);
2225 break;
2228 else if(device->Type == Capture)
2230 switch(param)
2232 case ALC_CAPTURE_SAMPLES:
2233 ALCdevice_Lock(device);
2234 *data = ALCdevice_AvailableSamples(device);
2235 ALCdevice_Unlock(device);
2236 break;
2238 case ALC_CONNECTED:
2239 *data = device->Connected;
2240 break;
2242 default:
2243 alcSetError(device, ALC_INVALID_ENUM);
2244 break;
2247 else /* render device */
2249 switch(param)
2251 case ALC_MAJOR_VERSION:
2252 *data = alcMajorVersion;
2253 break;
2255 case ALC_MINOR_VERSION:
2256 *data = alcMinorVersion;
2257 break;
2259 case ALC_EFX_MAJOR_VERSION:
2260 *data = alcEFXMajorVersion;
2261 break;
2263 case ALC_EFX_MINOR_VERSION:
2264 *data = alcEFXMinorVersion;
2265 break;
2267 case ALC_ATTRIBUTES_SIZE:
2268 *data = 13;
2269 break;
2271 case ALC_ALL_ATTRIBUTES:
2272 if(size < 13)
2273 alcSetError(device, ALC_INVALID_VALUE);
2274 else
2276 int i = 0;
2278 data[i++] = ALC_FREQUENCY;
2279 data[i++] = device->Frequency;
2281 if(device->Type != Loopback)
2283 data[i++] = ALC_REFRESH;
2284 data[i++] = device->Frequency / device->UpdateSize;
2286 data[i++] = ALC_SYNC;
2287 data[i++] = ALC_FALSE;
2289 else
2291 data[i++] = ALC_FORMAT_CHANNELS_SOFT;
2292 data[i++] = device->FmtChans;
2294 data[i++] = ALC_FORMAT_TYPE_SOFT;
2295 data[i++] = device->FmtType;
2298 data[i++] = ALC_MONO_SOURCES;
2299 data[i++] = device->NumMonoSources;
2301 data[i++] = ALC_STEREO_SOURCES;
2302 data[i++] = device->NumStereoSources;
2304 data[i++] = ALC_MAX_AUXILIARY_SENDS;
2305 data[i++] = device->NumAuxSends;
2307 data[i++] = 0;
2309 break;
2311 case ALC_FREQUENCY:
2312 *data = device->Frequency;
2313 break;
2315 case ALC_REFRESH:
2316 if(device->Type == Loopback)
2317 alcSetError(device, ALC_INVALID_DEVICE);
2318 else
2319 *data = device->Frequency / device->UpdateSize;
2320 break;
2322 case ALC_SYNC:
2323 if(device->Type == Loopback)
2324 alcSetError(device, ALC_INVALID_DEVICE);
2325 else
2326 *data = ALC_FALSE;
2327 break;
2329 case ALC_FORMAT_CHANNELS_SOFT:
2330 if(device->Type != Loopback)
2331 alcSetError(device, ALC_INVALID_DEVICE);
2332 else
2333 *data = device->FmtChans;
2334 break;
2336 case ALC_FORMAT_TYPE_SOFT:
2337 if(device->Type != Loopback)
2338 alcSetError(device, ALC_INVALID_DEVICE);
2339 else
2340 *data = device->FmtType;
2341 break;
2343 case ALC_MONO_SOURCES:
2344 *data = device->NumMonoSources;
2345 break;
2347 case ALC_STEREO_SOURCES:
2348 *data = device->NumStereoSources;
2349 break;
2351 case ALC_MAX_AUXILIARY_SENDS:
2352 *data = device->NumAuxSends;
2353 break;
2355 case ALC_CONNECTED:
2356 *data = device->Connected;
2357 break;
2359 default:
2360 alcSetError(device, ALC_INVALID_ENUM);
2361 break;
2364 if(device)
2365 ALCdevice_DecRef(device);
2369 /* alcIsExtensionPresent
2371 * Determines if there is support for a particular extension
2373 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2375 ALCboolean bResult = ALC_FALSE;
2377 device = VerifyDevice(device);
2379 if(!extName)
2380 alcSetError(device, ALC_INVALID_VALUE);
2381 else
2383 size_t len = strlen(extName);
2384 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2385 while(ptr && *ptr)
2387 if(strncasecmp(ptr, extName, len) == 0 &&
2388 (ptr[len] == '\0' || isspace(ptr[len])))
2390 bResult = ALC_TRUE;
2391 break;
2393 if((ptr=strchr(ptr, ' ')) != NULL)
2395 do {
2396 ++ptr;
2397 } while(isspace(*ptr));
2401 if(device)
2402 ALCdevice_DecRef(device);
2403 return bResult;
2407 /* alcGetProcAddress
2409 * Retrieves the function address for a particular extension function
2411 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2413 ALCvoid *ptr = NULL;
2415 if(!funcName)
2417 device = VerifyDevice(device);
2418 alcSetError(device, ALC_INVALID_VALUE);
2419 if(device) ALCdevice_DecRef(device);
2421 else
2423 ALsizei i = 0;
2424 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2425 i++;
2426 ptr = alcFunctions[i].address;
2429 return ptr;
2433 /* alcGetEnumValue
2435 * Get the value for a particular ALC enumeration name
2437 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2439 ALCenum val = 0;
2441 if(!enumName)
2443 device = VerifyDevice(device);
2444 alcSetError(device, ALC_INVALID_VALUE);
2445 if(device) ALCdevice_DecRef(device);
2447 else
2449 ALsizei i = 0;
2450 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2451 i++;
2452 val = enumeration[i].value;
2455 return val;
2459 /* alcCreateContext
2461 * Create and attach a context to the given device.
2463 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2465 ALCcontext *ALContext;
2466 ALCenum err;
2468 LockLists();
2469 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2471 UnlockLists();
2472 alcSetError(device, ALC_INVALID_DEVICE);
2473 if(device) ALCdevice_DecRef(device);
2474 return NULL;
2477 device->LastError = ALC_NO_ERROR;
2479 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2481 UnlockLists();
2482 alcSetError(device, err);
2483 if(err == ALC_INVALID_DEVICE)
2485 ALCdevice_Lock(device);
2486 aluHandleDisconnect(device);
2487 ALCdevice_Unlock(device);
2489 ALCdevice_DecRef(device);
2490 return NULL;
2493 ALContext = calloc(1, sizeof(ALCcontext)+15+sizeof(ALlistener));
2494 if(ALContext)
2496 ALContext->ref = 1;
2497 ALContext->Listener = (ALlistener*)(((ALintptrEXT)(ALContext+1)+15)&~15);
2499 ALContext->MaxActiveSources = 256;
2500 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
2501 ALContext->MaxActiveSources);
2503 if(!ALContext || !ALContext->ActiveSources)
2505 if(!device->ContextList)
2507 ALCdevice_StopPlayback(device);
2508 device->Flags &= ~DEVICE_RUNNING;
2510 UnlockLists();
2512 free(ALContext);
2513 ALContext = NULL;
2515 alcSetError(device, ALC_OUT_OF_MEMORY);
2516 ALCdevice_DecRef(device);
2517 return NULL;
2520 ALContext->Device = device;
2521 ALCdevice_IncRef(device);
2522 InitContext(ALContext);
2524 do {
2525 ALContext->next = device->ContextList;
2526 } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext));
2527 UnlockLists();
2529 ALCdevice_DecRef(device);
2531 TRACE("Created context %p\n", ALContext);
2532 return ALContext;
2535 /* alcDestroyContext
2537 * Remove a context from its device
2539 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2541 ALCdevice *Device;
2543 LockLists();
2544 /* alcGetContextsDevice sets an error for invalid contexts */
2545 Device = alcGetContextsDevice(context);
2546 if(Device)
2548 ReleaseContext(context, Device);
2549 if(!Device->ContextList)
2551 ALCdevice_StopPlayback(Device);
2552 Device->Flags &= ~DEVICE_RUNNING;
2555 UnlockLists();
2559 /* alcGetCurrentContext
2561 * Returns the currently active context on the calling thread
2563 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2565 ALCcontext *Context;
2567 Context = pthread_getspecific(LocalContext);
2568 if(!Context) Context = GlobalContext;
2570 return Context;
2573 /* alcGetThreadContext
2575 * Returns the currently active thread-local context
2577 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2579 ALCcontext *Context;
2580 Context = pthread_getspecific(LocalContext);
2581 return Context;
2585 /* alcMakeContextCurrent
2587 * Makes the given context the active process-wide context, and removes the
2588 * thread-local context for the calling thread.
2590 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2592 /* context must be valid or NULL */
2593 if(context && !(context=VerifyContext(context)))
2595 alcSetError(NULL, ALC_INVALID_CONTEXT);
2596 return ALC_FALSE;
2598 /* context's reference count is already incremented */
2599 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2600 if(context) ALCcontext_DecRef(context);
2602 if((context=pthread_getspecific(LocalContext)) != NULL)
2604 pthread_setspecific(LocalContext, NULL);
2605 ALCcontext_DecRef(context);
2608 return ALC_TRUE;
2611 /* alcSetThreadContext
2613 * Makes the given context the active context for the current thread
2615 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2617 ALCcontext *old;
2619 /* context must be valid or NULL */
2620 if(context && !(context=VerifyContext(context)))
2622 alcSetError(NULL, ALC_INVALID_CONTEXT);
2623 return ALC_FALSE;
2625 /* context's reference count is already incremented */
2626 old = pthread_getspecific(LocalContext);
2627 pthread_setspecific(LocalContext, context);
2628 if(old) ALCcontext_DecRef(old);
2630 return ALC_TRUE;
2634 /* alcGetContextsDevice
2636 * Returns the device that a particular context is attached to
2638 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
2640 ALCdevice *Device;
2642 if(!(Context=VerifyContext(Context)))
2644 alcSetError(NULL, ALC_INVALID_CONTEXT);
2645 return NULL;
2647 Device = Context->Device;
2648 ALCcontext_DecRef(Context);
2650 return Device;
2654 /* alcOpenDevice
2656 * Opens the named device.
2658 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
2660 const ALCchar *fmt;
2661 ALCdevice *device;
2662 ALCenum err;
2664 DO_INITCONFIG();
2666 if(!PlaybackBackend.name)
2668 alcSetError(NULL, ALC_INVALID_VALUE);
2669 return NULL;
2672 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2673 deviceName = NULL;
2675 device = al_calloc(16, sizeof(ALCdevice)+15+sizeof(ALeffectslot));
2676 if(!device)
2678 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2679 return NULL;
2682 //Validate device
2683 device->Funcs = &PlaybackBackend.Funcs;
2684 device->ref = 1;
2685 device->Connected = ALC_TRUE;
2686 device->Type = Playback;
2687 InitializeCriticalSection(&device->Mutex);
2688 device->LastError = ALC_NO_ERROR;
2690 device->Flags = 0;
2691 device->Bs2b = NULL;
2692 device->Bs2bLevel = 0;
2693 device->DeviceName = NULL;
2695 device->ContextList = NULL;
2697 device->MaxNoOfSources = 256;
2698 device->AuxiliaryEffectSlotMax = 4;
2699 device->NumAuxSends = MAX_SENDS;
2701 InitUIntMap(&device->BufferMap, ~0);
2702 InitUIntMap(&device->EffectMap, ~0);
2703 InitUIntMap(&device->FilterMap, ~0);
2705 //Set output format
2706 device->FmtChans = DevFmtChannelsDefault;
2707 device->FmtType = DevFmtTypeDefault;
2708 device->Frequency = DEFAULT_OUTPUT_RATE;
2709 device->NumUpdates = 4;
2710 device->UpdateSize = 1024;
2712 if(ConfigValueStr(NULL, "channels", &fmt))
2714 static const struct {
2715 const char name[16];
2716 enum DevFmtChannels chans;
2717 } chanlist[] = {
2718 { "mono", DevFmtMono },
2719 { "stereo", DevFmtStereo },
2720 { "quad", DevFmtQuad },
2721 { "surround51", DevFmtX51 },
2722 { "surround61", DevFmtX61 },
2723 { "surround71", DevFmtX71 },
2725 size_t i;
2727 for(i = 0;i < COUNTOF(chanlist);i++)
2729 if(strcasecmp(chanlist[i].name, fmt) == 0)
2731 device->FmtChans = chanlist[i].chans;
2732 device->Flags |= DEVICE_CHANNELS_REQUEST;
2733 break;
2736 if(i == COUNTOF(chanlist))
2737 ERR("Unsupported channels: %s\n", fmt);
2739 if(ConfigValueStr(NULL, "sample-type", &fmt))
2741 static const struct {
2742 const char name[16];
2743 enum DevFmtType type;
2744 } typelist[] = {
2745 { "int8", DevFmtByte },
2746 { "uint8", DevFmtUByte },
2747 { "int16", DevFmtShort },
2748 { "uint16", DevFmtUShort },
2749 { "int32", DevFmtInt },
2750 { "uint32", DevFmtUInt },
2751 { "float32", DevFmtFloat },
2753 size_t i;
2755 for(i = 0;i < COUNTOF(typelist);i++)
2757 if(strcasecmp(typelist[i].name, fmt) == 0)
2759 device->FmtType = typelist[i].type;
2760 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
2761 break;
2764 if(i == COUNTOF(typelist))
2765 ERR("Unsupported sample-type: %s\n", fmt);
2767 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2768 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
2769 ConfigValueStr(NULL, "format", &fmt))
2771 static const struct {
2772 const char name[32];
2773 enum DevFmtChannels channels;
2774 enum DevFmtType type;
2775 } formats[] = {
2776 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
2777 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
2778 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
2779 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
2780 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
2781 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
2783 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
2784 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
2785 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
2786 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
2787 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
2788 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
2790 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
2791 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
2792 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
2793 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
2794 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
2795 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
2797 size_t i;
2799 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2800 for(i = 0;i < COUNTOF(formats);i++)
2802 if(strcasecmp(fmt, formats[i].name) == 0)
2804 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
2805 device->FmtChans = formats[i].channels;
2806 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
2807 device->FmtType = formats[i].type;
2808 device->Flags |= DEVICE_FORMAT_REQUEST;
2809 break;
2812 if(i == COUNTOF(formats))
2813 ERR("Unsupported format: %s\n", fmt);
2815 #undef DEVICE_FORMAT_REQUEST
2817 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
2819 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2820 if(device->Frequency < MIN_OUTPUT_RATE)
2821 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
2822 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
2825 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
2826 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
2828 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
2829 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
2830 if((CPUCapFlags&CPU_CAP_SSE))
2831 device->UpdateSize = (device->UpdateSize+3)&~3;
2833 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
2834 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
2836 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
2837 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
2839 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
2840 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
2842 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
2844 device->NumStereoSources = 1;
2845 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
2847 // Find a playback device to open
2848 if((err=ALCdevice_OpenPlayback(device, deviceName)) != ALC_NO_ERROR)
2850 DeleteCriticalSection(&device->Mutex);
2851 al_free(device);
2852 alcSetError(NULL, err);
2853 return NULL;
2856 if(DefaultEffect.type != AL_EFFECT_NULL)
2858 device->DefaultSlot = (ALeffectslot*)(((ALintptrEXT)(device+1)+15)&~15);
2859 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
2861 device->DefaultSlot = NULL;
2862 ERR("Failed to initialize the default effect slot\n");
2864 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
2866 ALeffectState_Destroy(device->DefaultSlot->EffectState);
2867 device->DefaultSlot = NULL;
2868 ERR("Failed to initialize the default effect\n");
2872 do {
2873 device->next = DeviceList;
2874 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2876 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2877 return device;
2880 /* alcCloseDevice
2882 * Closes the given device.
2884 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
2886 ALCdevice *volatile*list;
2887 ALCcontext *ctx;
2889 LockLists();
2890 list = &DeviceList;
2891 while(*list && *list != Device)
2892 list = &(*list)->next;
2894 if(!*list || (*list)->Type == Capture)
2896 alcSetError(*list, ALC_INVALID_DEVICE);
2897 UnlockLists();
2898 return ALC_FALSE;
2901 *list = (*list)->next;
2902 UnlockLists();
2904 while((ctx=Device->ContextList) != NULL)
2906 WARN("Releasing context %p\n", ctx);
2907 ReleaseContext(ctx, Device);
2909 if((Device->Flags&DEVICE_RUNNING))
2910 ALCdevice_StopPlayback(Device);
2911 Device->Flags &= ~DEVICE_RUNNING;
2913 ALCdevice_DecRef(Device);
2915 return ALC_TRUE;
2919 /************************************************
2920 * ALC capture functions
2921 ************************************************/
2922 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
2924 ALCdevice *device = NULL;
2925 ALCenum err;
2927 DO_INITCONFIG();
2929 if(!CaptureBackend.name)
2931 alcSetError(NULL, ALC_INVALID_VALUE);
2932 return NULL;
2935 if(samples <= 0)
2937 alcSetError(NULL, ALC_INVALID_VALUE);
2938 return NULL;
2941 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
2942 deviceName = NULL;
2944 device = al_calloc(16, sizeof(ALCdevice));
2945 if(!device)
2947 alcSetError(NULL, ALC_OUT_OF_MEMORY);
2948 return NULL;
2951 //Validate device
2952 device->Funcs = &CaptureBackend.Funcs;
2953 device->ref = 1;
2954 device->Connected = ALC_TRUE;
2955 device->Type = Capture;
2956 InitializeCriticalSection(&device->Mutex);
2958 InitUIntMap(&device->BufferMap, ~0);
2959 InitUIntMap(&device->EffectMap, ~0);
2960 InitUIntMap(&device->FilterMap, ~0);
2962 device->DeviceName = NULL;
2964 device->Flags |= DEVICE_FREQUENCY_REQUEST;
2965 device->Frequency = frequency;
2967 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
2968 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
2970 DeleteCriticalSection(&device->Mutex);
2971 al_free(device);
2972 alcSetError(NULL, ALC_INVALID_ENUM);
2973 return NULL;
2976 device->UpdateSize = samples;
2977 device->NumUpdates = 1;
2979 if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
2981 DeleteCriticalSection(&device->Mutex);
2982 al_free(device);
2983 alcSetError(NULL, err);
2984 return NULL;
2987 do {
2988 device->next = DeviceList;
2989 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
2991 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
2992 return device;
2995 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
2997 ALCdevice *volatile*list;
2999 LockLists();
3000 list = &DeviceList;
3001 while(*list && *list != Device)
3002 list = &(*list)->next;
3004 if(!*list || (*list)->Type != Capture)
3006 alcSetError(*list, ALC_INVALID_DEVICE);
3007 UnlockLists();
3008 return ALC_FALSE;
3011 *list = (*list)->next;
3012 UnlockLists();
3014 ALCdevice_DecRef(Device);
3016 return ALC_TRUE;
3019 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3021 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3022 alcSetError(device, ALC_INVALID_DEVICE);
3023 else
3025 ALCdevice_Lock(device);
3026 if(device->Connected)
3028 if(!(device->Flags&DEVICE_RUNNING))
3029 ALCdevice_StartCapture(device);
3030 device->Flags |= DEVICE_RUNNING;
3032 ALCdevice_Unlock(device);
3035 if(device) ALCdevice_DecRef(device);
3038 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3040 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3041 alcSetError(device, ALC_INVALID_DEVICE);
3042 else
3044 ALCdevice_Lock(device);
3045 if((device->Flags&DEVICE_RUNNING))
3046 ALCdevice_StopCapture(device);
3047 device->Flags &= ~DEVICE_RUNNING;
3048 ALCdevice_Unlock(device);
3051 if(device) ALCdevice_DecRef(device);
3054 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3056 if(!(device=VerifyDevice(device)) && device->Type != Capture)
3057 alcSetError(device, ALC_INVALID_DEVICE);
3058 else
3060 ALCenum err = ALC_INVALID_VALUE;
3062 ALCdevice_Lock(device);
3063 if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
3064 err = ALCdevice_CaptureSamples(device, buffer, samples);
3065 ALCdevice_Unlock(device);
3067 if(err != ALC_NO_ERROR)
3068 alcSetError(device, err);
3070 if(device) ALCdevice_DecRef(device);
3074 /************************************************
3075 * ALC loopback functions
3076 ************************************************/
3078 /* alcLoopbackOpenDeviceSOFT
3080 * Open a loopback device, for manual rendering.
3082 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3084 ALCdevice *device;
3086 DO_INITCONFIG();
3088 /* Make sure the device name, if specified, is us. */
3089 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3091 alcSetError(NULL, ALC_INVALID_VALUE);
3092 return NULL;
3095 device = al_calloc(16, sizeof(ALCdevice));
3096 if(!device)
3098 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3099 return NULL;
3102 //Validate device
3103 device->Funcs = &BackendLoopback.Funcs;
3104 device->ref = 1;
3105 device->Connected = ALC_TRUE;
3106 device->Type = Loopback;
3107 InitializeCriticalSection(&device->Mutex);
3108 device->LastError = ALC_NO_ERROR;
3110 device->Flags = 0;
3111 device->Bs2b = NULL;
3112 device->Bs2bLevel = 0;
3113 device->DeviceName = NULL;
3115 device->ContextList = NULL;
3117 device->MaxNoOfSources = 256;
3118 device->AuxiliaryEffectSlotMax = 4;
3119 device->NumAuxSends = MAX_SENDS;
3121 InitUIntMap(&device->BufferMap, ~0);
3122 InitUIntMap(&device->EffectMap, ~0);
3123 InitUIntMap(&device->FilterMap, ~0);
3125 //Set output format
3126 device->NumUpdates = 0;
3127 device->UpdateSize = 0;
3129 device->Frequency = DEFAULT_OUTPUT_RATE;
3130 device->FmtChans = DevFmtChannelsDefault;
3131 device->FmtType = DevFmtTypeDefault;
3133 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3134 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3136 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3137 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3139 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3140 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3142 device->NumStereoSources = 1;
3143 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3145 // Open the "backend"
3146 ALCdevice_OpenPlayback(device, "Loopback");
3147 do {
3148 device->next = DeviceList;
3149 } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
3151 TRACE("Created device %p\n", device);
3152 return device;
3155 /* alcIsRenderFormatSupportedSOFT
3157 * Determines if the loopback device supports the given format for rendering.
3159 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3161 ALCboolean ret = ALC_FALSE;
3163 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3164 alcSetError(device, ALC_INVALID_DEVICE);
3165 else if(freq <= 0)
3166 alcSetError(device, ALC_INVALID_VALUE);
3167 else
3169 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3170 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3171 freq >= MIN_OUTPUT_RATE)
3172 ret = ALC_TRUE;
3174 if(device) ALCdevice_DecRef(device);
3176 return ret;
3179 /* alcRenderSamplesSOFT
3181 * Renders some samples into a buffer, using the format last set by the
3182 * attributes given to alcCreateContext.
3184 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3186 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3187 alcSetError(device, ALC_INVALID_DEVICE);
3188 else if(samples < 0 || (samples > 0 && buffer == NULL))
3189 alcSetError(device, ALC_INVALID_VALUE);
3190 else
3191 aluMixData(device, buffer, samples);
3192 if(device) ALCdevice_DecRef(device);