Include strings.h if it exists for strncasecmp
[openal-soft.git] / Alc / ALc.c
blobde37c80bf6c144da5191bc0600fddf855ba525b6
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 "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_PULSEAUDIO
65 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_ALSA
68 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_COREAUDIO
71 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
72 #endif
73 #ifdef HAVE_OSS
74 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
75 #endif
76 #ifdef HAVE_SOLARIS
77 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SNDIO
80 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_QSA
83 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_MMDEVAPI
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
87 #endif
88 #ifdef HAVE_DSOUND
89 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_WINMM
92 { "winmm", NULL, alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
93 #endif
94 #ifdef HAVE_PORTAUDIO
95 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
96 #endif
97 #ifdef HAVE_OPENSL
98 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
99 #endif
101 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
102 #ifdef HAVE_WAVE
103 { "wave", NULL, alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
104 #endif
106 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
108 #undef EmptyFuncs
110 static struct BackendInfo PlaybackBackend;
111 static struct BackendInfo CaptureBackend;
114 /************************************************
115 * Functions, enums, and errors
116 ************************************************/
117 typedef struct ALCfunction {
118 const ALCchar *funcName;
119 ALCvoid *address;
120 } ALCfunction;
122 typedef struct ALCenums {
123 const ALCchar *enumName;
124 ALCenum value;
125 } ALCenums;
127 #define DECL(x) { #x, (ALCvoid*)(x) }
128 static const ALCfunction alcFunctions[] = {
129 DECL(alcCreateContext),
130 DECL(alcMakeContextCurrent),
131 DECL(alcProcessContext),
132 DECL(alcSuspendContext),
133 DECL(alcDestroyContext),
134 DECL(alcGetCurrentContext),
135 DECL(alcGetContextsDevice),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
143 DECL(alcGetIntegerv),
144 DECL(alcCaptureOpenDevice),
145 DECL(alcCaptureCloseDevice),
146 DECL(alcCaptureStart),
147 DECL(alcCaptureStop),
148 DECL(alcCaptureSamples),
150 DECL(alcSetThreadContext),
151 DECL(alcGetThreadContext),
153 DECL(alcLoopbackOpenDeviceSOFT),
154 DECL(alcIsRenderFormatSupportedSOFT),
155 DECL(alcRenderSamplesSOFT),
157 DECL(alcDevicePauseSOFT),
158 DECL(alcDeviceResumeSOFT),
160 DECL(alcGetInteger64vSOFT),
162 DECL(alEnable),
163 DECL(alDisable),
164 DECL(alIsEnabled),
165 DECL(alGetString),
166 DECL(alGetBooleanv),
167 DECL(alGetIntegerv),
168 DECL(alGetFloatv),
169 DECL(alGetDoublev),
170 DECL(alGetBoolean),
171 DECL(alGetInteger),
172 DECL(alGetFloat),
173 DECL(alGetDouble),
174 DECL(alGetError),
175 DECL(alIsExtensionPresent),
176 DECL(alGetProcAddress),
177 DECL(alGetEnumValue),
178 DECL(alListenerf),
179 DECL(alListener3f),
180 DECL(alListenerfv),
181 DECL(alListeneri),
182 DECL(alListener3i),
183 DECL(alListeneriv),
184 DECL(alGetListenerf),
185 DECL(alGetListener3f),
186 DECL(alGetListenerfv),
187 DECL(alGetListeneri),
188 DECL(alGetListener3i),
189 DECL(alGetListeneriv),
190 DECL(alGenSources),
191 DECL(alDeleteSources),
192 DECL(alIsSource),
193 DECL(alSourcef),
194 DECL(alSource3f),
195 DECL(alSourcefv),
196 DECL(alSourcei),
197 DECL(alSource3i),
198 DECL(alSourceiv),
199 DECL(alGetSourcef),
200 DECL(alGetSource3f),
201 DECL(alGetSourcefv),
202 DECL(alGetSourcei),
203 DECL(alGetSource3i),
204 DECL(alGetSourceiv),
205 DECL(alSourcePlayv),
206 DECL(alSourceStopv),
207 DECL(alSourceRewindv),
208 DECL(alSourcePausev),
209 DECL(alSourcePlay),
210 DECL(alSourceStop),
211 DECL(alSourceRewind),
212 DECL(alSourcePause),
213 DECL(alSourceQueueBuffers),
214 DECL(alSourceUnqueueBuffers),
215 DECL(alGenBuffers),
216 DECL(alDeleteBuffers),
217 DECL(alIsBuffer),
218 DECL(alBufferData),
219 DECL(alBufferf),
220 DECL(alBuffer3f),
221 DECL(alBufferfv),
222 DECL(alBufferi),
223 DECL(alBuffer3i),
224 DECL(alBufferiv),
225 DECL(alGetBufferf),
226 DECL(alGetBuffer3f),
227 DECL(alGetBufferfv),
228 DECL(alGetBufferi),
229 DECL(alGetBuffer3i),
230 DECL(alGetBufferiv),
231 DECL(alDopplerFactor),
232 DECL(alDopplerVelocity),
233 DECL(alSpeedOfSound),
234 DECL(alDistanceModel),
236 DECL(alGenFilters),
237 DECL(alDeleteFilters),
238 DECL(alIsFilter),
239 DECL(alFilteri),
240 DECL(alFilteriv),
241 DECL(alFilterf),
242 DECL(alFilterfv),
243 DECL(alGetFilteri),
244 DECL(alGetFilteriv),
245 DECL(alGetFilterf),
246 DECL(alGetFilterfv),
247 DECL(alGenEffects),
248 DECL(alDeleteEffects),
249 DECL(alIsEffect),
250 DECL(alEffecti),
251 DECL(alEffectiv),
252 DECL(alEffectf),
253 DECL(alEffectfv),
254 DECL(alGetEffecti),
255 DECL(alGetEffectiv),
256 DECL(alGetEffectf),
257 DECL(alGetEffectfv),
258 DECL(alGenAuxiliaryEffectSlots),
259 DECL(alDeleteAuxiliaryEffectSlots),
260 DECL(alIsAuxiliaryEffectSlot),
261 DECL(alAuxiliaryEffectSloti),
262 DECL(alAuxiliaryEffectSlotiv),
263 DECL(alAuxiliaryEffectSlotf),
264 DECL(alAuxiliaryEffectSlotfv),
265 DECL(alGetAuxiliaryEffectSloti),
266 DECL(alGetAuxiliaryEffectSlotiv),
267 DECL(alGetAuxiliaryEffectSlotf),
268 DECL(alGetAuxiliaryEffectSlotfv),
270 DECL(alBufferSubDataSOFT),
272 DECL(alBufferSamplesSOFT),
273 DECL(alBufferSubSamplesSOFT),
274 DECL(alGetBufferSamplesSOFT),
275 DECL(alIsBufferFormatSupportedSOFT),
277 DECL(alDeferUpdatesSOFT),
278 DECL(alProcessUpdatesSOFT),
280 DECL(alSourcedSOFT),
281 DECL(alSource3dSOFT),
282 DECL(alSourcedvSOFT),
283 DECL(alGetSourcedSOFT),
284 DECL(alGetSource3dSOFT),
285 DECL(alGetSourcedvSOFT),
286 DECL(alSourcei64SOFT),
287 DECL(alSource3i64SOFT),
288 DECL(alSourcei64vSOFT),
289 DECL(alGetSourcei64SOFT),
290 DECL(alGetSource3i64SOFT),
291 DECL(alGetSourcei64vSOFT),
293 DECL(alGenSoundfontsSOFT),
294 DECL(alDeleteSoundfontsSOFT),
295 DECL(alIsSoundfontSOFT),
296 DECL(alSoundfontSamplesSOFT),
297 DECL(alGetSoundfontSamplesSOFT),
298 DECL(alSoundfontMapSamplesSOFT),
299 DECL(alSoundfontUnmapSamplesSOFT),
300 DECL(alGetSoundfontivSOFT),
301 DECL(alSoundfontPresetsSOFT),
302 DECL(alGenPresetsSOFT),
303 DECL(alDeletePresetsSOFT),
304 DECL(alIsPresetSOFT),
305 DECL(alPresetiSOFT),
306 DECL(alPresetivSOFT),
307 DECL(alGetPresetivSOFT),
308 DECL(alPresetFontsoundsSOFT),
309 DECL(alGenFontsoundsSOFT),
310 DECL(alDeleteFontsoundsSOFT),
311 DECL(alIsFontsoundSOFT),
312 DECL(alFontsoundiSOFT),
313 DECL(alFontsound2iSOFT),
314 DECL(alFontsoundivSOFT),
315 DECL(alGetFontsoundivSOFT),
316 DECL(alFontsoundModulatoriSOFT),
317 DECL(alGetFontsoundModulatorivSOFT),
318 DECL(alMidiSoundfontSOFT),
319 DECL(alMidiSoundfontvSOFT),
320 DECL(alMidiEventSOFT),
321 DECL(alMidiSysExSOFT),
322 DECL(alMidiPlaySOFT),
323 DECL(alMidiPauseSOFT),
324 DECL(alMidiStopSOFT),
325 DECL(alMidiResetSOFT),
326 DECL(alMidiGainSOFT),
327 DECL(alGetInteger64SOFT),
328 DECL(alGetInteger64vSOFT),
329 DECL(alLoadSoundfontSOFT),
331 { NULL, NULL }
333 #undef DECL
335 #define DECL(x) { #x, (x) }
336 static const ALCenums enumeration[] = {
337 DECL(ALC_INVALID),
338 DECL(ALC_FALSE),
339 DECL(ALC_TRUE),
341 DECL(ALC_MAJOR_VERSION),
342 DECL(ALC_MINOR_VERSION),
343 DECL(ALC_ATTRIBUTES_SIZE),
344 DECL(ALC_ALL_ATTRIBUTES),
345 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
346 DECL(ALC_DEVICE_SPECIFIER),
347 DECL(ALC_ALL_DEVICES_SPECIFIER),
348 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
349 DECL(ALC_EXTENSIONS),
350 DECL(ALC_FREQUENCY),
351 DECL(ALC_REFRESH),
352 DECL(ALC_SYNC),
353 DECL(ALC_MONO_SOURCES),
354 DECL(ALC_STEREO_SOURCES),
355 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
356 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
357 DECL(ALC_CAPTURE_SAMPLES),
358 DECL(ALC_CONNECTED),
360 DECL(ALC_EFX_MAJOR_VERSION),
361 DECL(ALC_EFX_MINOR_VERSION),
362 DECL(ALC_MAX_AUXILIARY_SENDS),
364 DECL(ALC_FORMAT_CHANNELS_SOFT),
365 DECL(ALC_FORMAT_TYPE_SOFT),
367 DECL(ALC_MONO_SOFT),
368 DECL(ALC_STEREO_SOFT),
369 DECL(ALC_QUAD_SOFT),
370 DECL(ALC_5POINT1_SOFT),
371 DECL(ALC_6POINT1_SOFT),
372 DECL(ALC_7POINT1_SOFT),
374 DECL(ALC_BYTE_SOFT),
375 DECL(ALC_UNSIGNED_BYTE_SOFT),
376 DECL(ALC_SHORT_SOFT),
377 DECL(ALC_UNSIGNED_SHORT_SOFT),
378 DECL(ALC_INT_SOFT),
379 DECL(ALC_UNSIGNED_INT_SOFT),
380 DECL(ALC_FLOAT_SOFT),
382 DECL(ALC_NO_ERROR),
383 DECL(ALC_INVALID_DEVICE),
384 DECL(ALC_INVALID_CONTEXT),
385 DECL(ALC_INVALID_ENUM),
386 DECL(ALC_INVALID_VALUE),
387 DECL(ALC_OUT_OF_MEMORY),
390 DECL(AL_INVALID),
391 DECL(AL_NONE),
392 DECL(AL_FALSE),
393 DECL(AL_TRUE),
395 DECL(AL_SOURCE_RELATIVE),
396 DECL(AL_CONE_INNER_ANGLE),
397 DECL(AL_CONE_OUTER_ANGLE),
398 DECL(AL_PITCH),
399 DECL(AL_POSITION),
400 DECL(AL_DIRECTION),
401 DECL(AL_VELOCITY),
402 DECL(AL_LOOPING),
403 DECL(AL_BUFFER),
404 DECL(AL_GAIN),
405 DECL(AL_MIN_GAIN),
406 DECL(AL_MAX_GAIN),
407 DECL(AL_ORIENTATION),
408 DECL(AL_REFERENCE_DISTANCE),
409 DECL(AL_ROLLOFF_FACTOR),
410 DECL(AL_CONE_OUTER_GAIN),
411 DECL(AL_MAX_DISTANCE),
412 DECL(AL_SEC_OFFSET),
413 DECL(AL_SAMPLE_OFFSET),
414 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
415 DECL(AL_BYTE_OFFSET),
416 DECL(AL_BYTE_RW_OFFSETS_SOFT),
417 DECL(AL_SOURCE_TYPE),
418 DECL(AL_STATIC),
419 DECL(AL_STREAMING),
420 DECL(AL_UNDETERMINED),
421 DECL(AL_METERS_PER_UNIT),
422 DECL(AL_DIRECT_CHANNELS_SOFT),
424 DECL(AL_DIRECT_FILTER),
425 DECL(AL_AUXILIARY_SEND_FILTER),
426 DECL(AL_AIR_ABSORPTION_FACTOR),
427 DECL(AL_ROOM_ROLLOFF_FACTOR),
428 DECL(AL_CONE_OUTER_GAINHF),
429 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
430 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
431 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
433 DECL(AL_SOURCE_STATE),
434 DECL(AL_INITIAL),
435 DECL(AL_PLAYING),
436 DECL(AL_PAUSED),
437 DECL(AL_STOPPED),
439 DECL(AL_BUFFERS_QUEUED),
440 DECL(AL_BUFFERS_PROCESSED),
442 DECL(AL_FORMAT_MONO8),
443 DECL(AL_FORMAT_MONO16),
444 DECL(AL_FORMAT_MONO_FLOAT32),
445 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
446 DECL(AL_FORMAT_STEREO8),
447 DECL(AL_FORMAT_STEREO16),
448 DECL(AL_FORMAT_STEREO_FLOAT32),
449 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
450 DECL(AL_FORMAT_MONO_IMA4),
451 DECL(AL_FORMAT_STEREO_IMA4),
452 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
453 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
454 DECL(AL_FORMAT_QUAD8_LOKI),
455 DECL(AL_FORMAT_QUAD16_LOKI),
456 DECL(AL_FORMAT_QUAD8),
457 DECL(AL_FORMAT_QUAD16),
458 DECL(AL_FORMAT_QUAD32),
459 DECL(AL_FORMAT_51CHN8),
460 DECL(AL_FORMAT_51CHN16),
461 DECL(AL_FORMAT_51CHN32),
462 DECL(AL_FORMAT_61CHN8),
463 DECL(AL_FORMAT_61CHN16),
464 DECL(AL_FORMAT_61CHN32),
465 DECL(AL_FORMAT_71CHN8),
466 DECL(AL_FORMAT_71CHN16),
467 DECL(AL_FORMAT_71CHN32),
468 DECL(AL_FORMAT_REAR8),
469 DECL(AL_FORMAT_REAR16),
470 DECL(AL_FORMAT_REAR32),
471 DECL(AL_FORMAT_MONO_MULAW),
472 DECL(AL_FORMAT_MONO_MULAW_EXT),
473 DECL(AL_FORMAT_STEREO_MULAW),
474 DECL(AL_FORMAT_STEREO_MULAW_EXT),
475 DECL(AL_FORMAT_QUAD_MULAW),
476 DECL(AL_FORMAT_51CHN_MULAW),
477 DECL(AL_FORMAT_61CHN_MULAW),
478 DECL(AL_FORMAT_71CHN_MULAW),
479 DECL(AL_FORMAT_REAR_MULAW),
480 DECL(AL_FORMAT_MONO_ALAW_EXT),
481 DECL(AL_FORMAT_STEREO_ALAW_EXT),
483 DECL(AL_MONO8_SOFT),
484 DECL(AL_MONO16_SOFT),
485 DECL(AL_MONO32F_SOFT),
486 DECL(AL_STEREO8_SOFT),
487 DECL(AL_STEREO16_SOFT),
488 DECL(AL_STEREO32F_SOFT),
489 DECL(AL_QUAD8_SOFT),
490 DECL(AL_QUAD16_SOFT),
491 DECL(AL_QUAD32F_SOFT),
492 DECL(AL_REAR8_SOFT),
493 DECL(AL_REAR16_SOFT),
494 DECL(AL_REAR32F_SOFT),
495 DECL(AL_5POINT1_8_SOFT),
496 DECL(AL_5POINT1_16_SOFT),
497 DECL(AL_5POINT1_32F_SOFT),
498 DECL(AL_6POINT1_8_SOFT),
499 DECL(AL_6POINT1_16_SOFT),
500 DECL(AL_6POINT1_32F_SOFT),
501 DECL(AL_7POINT1_8_SOFT),
502 DECL(AL_7POINT1_16_SOFT),
503 DECL(AL_7POINT1_32F_SOFT),
505 DECL(AL_MONO_SOFT),
506 DECL(AL_STEREO_SOFT),
507 DECL(AL_QUAD_SOFT),
508 DECL(AL_REAR_SOFT),
509 DECL(AL_5POINT1_SOFT),
510 DECL(AL_6POINT1_SOFT),
511 DECL(AL_7POINT1_SOFT),
513 DECL(AL_BYTE_SOFT),
514 DECL(AL_UNSIGNED_BYTE_SOFT),
515 DECL(AL_SHORT_SOFT),
516 DECL(AL_UNSIGNED_SHORT_SOFT),
517 DECL(AL_INT_SOFT),
518 DECL(AL_UNSIGNED_INT_SOFT),
519 DECL(AL_FLOAT_SOFT),
520 DECL(AL_DOUBLE_SOFT),
521 DECL(AL_BYTE3_SOFT),
522 DECL(AL_UNSIGNED_BYTE3_SOFT),
524 DECL(AL_FREQUENCY),
525 DECL(AL_BITS),
526 DECL(AL_CHANNELS),
527 DECL(AL_SIZE),
528 DECL(AL_INTERNAL_FORMAT_SOFT),
529 DECL(AL_BYTE_LENGTH_SOFT),
530 DECL(AL_SAMPLE_LENGTH_SOFT),
531 DECL(AL_SEC_LENGTH_SOFT),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
535 DECL(AL_UNUSED),
536 DECL(AL_PENDING),
537 DECL(AL_PROCESSED),
539 DECL(AL_NO_ERROR),
540 DECL(AL_INVALID_NAME),
541 DECL(AL_INVALID_ENUM),
542 DECL(AL_INVALID_VALUE),
543 DECL(AL_INVALID_OPERATION),
544 DECL(AL_OUT_OF_MEMORY),
546 DECL(AL_VENDOR),
547 DECL(AL_VERSION),
548 DECL(AL_RENDERER),
549 DECL(AL_EXTENSIONS),
551 DECL(AL_DOPPLER_FACTOR),
552 DECL(AL_DOPPLER_VELOCITY),
553 DECL(AL_DISTANCE_MODEL),
554 DECL(AL_SPEED_OF_SOUND),
555 DECL(AL_SOURCE_DISTANCE_MODEL),
556 DECL(AL_DEFERRED_UPDATES_SOFT),
558 DECL(AL_INVERSE_DISTANCE),
559 DECL(AL_INVERSE_DISTANCE_CLAMPED),
560 DECL(AL_LINEAR_DISTANCE),
561 DECL(AL_LINEAR_DISTANCE_CLAMPED),
562 DECL(AL_EXPONENT_DISTANCE),
563 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
565 DECL(AL_FILTER_TYPE),
566 DECL(AL_FILTER_NULL),
567 DECL(AL_FILTER_LOWPASS),
568 DECL(AL_FILTER_HIGHPASS),
569 DECL(AL_FILTER_BANDPASS),
571 DECL(AL_LOWPASS_GAIN),
572 DECL(AL_LOWPASS_GAINHF),
574 DECL(AL_HIGHPASS_GAIN),
575 DECL(AL_HIGHPASS_GAINLF),
577 DECL(AL_BANDPASS_GAIN),
578 DECL(AL_BANDPASS_GAINHF),
579 DECL(AL_BANDPASS_GAINLF),
581 DECL(AL_EFFECT_TYPE),
582 DECL(AL_EFFECT_NULL),
583 DECL(AL_EFFECT_REVERB),
584 DECL(AL_EFFECT_EAXREVERB),
585 DECL(AL_EFFECT_CHORUS),
586 DECL(AL_EFFECT_DISTORTION),
587 DECL(AL_EFFECT_ECHO),
588 DECL(AL_EFFECT_FLANGER),
589 #if 0
590 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
591 DECL(AL_EFFECT_VOCAL_MORPHER),
592 DECL(AL_EFFECT_PITCH_SHIFTER),
593 #endif
594 DECL(AL_EFFECT_RING_MODULATOR),
595 DECL(AL_EFFECT_AUTOWAH),
596 DECL(AL_EFFECT_COMPRESSOR),
597 DECL(AL_EFFECT_EQUALIZER),
598 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
599 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
601 DECL(AL_EAXREVERB_DENSITY),
602 DECL(AL_EAXREVERB_DIFFUSION),
603 DECL(AL_EAXREVERB_GAIN),
604 DECL(AL_EAXREVERB_GAINHF),
605 DECL(AL_EAXREVERB_GAINLF),
606 DECL(AL_EAXREVERB_DECAY_TIME),
607 DECL(AL_EAXREVERB_DECAY_HFRATIO),
608 DECL(AL_EAXREVERB_DECAY_LFRATIO),
609 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
610 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
611 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
612 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
613 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
614 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
615 DECL(AL_EAXREVERB_ECHO_TIME),
616 DECL(AL_EAXREVERB_ECHO_DEPTH),
617 DECL(AL_EAXREVERB_MODULATION_TIME),
618 DECL(AL_EAXREVERB_MODULATION_DEPTH),
619 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
620 DECL(AL_EAXREVERB_HFREFERENCE),
621 DECL(AL_EAXREVERB_LFREFERENCE),
622 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
623 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
625 DECL(AL_REVERB_DENSITY),
626 DECL(AL_REVERB_DIFFUSION),
627 DECL(AL_REVERB_GAIN),
628 DECL(AL_REVERB_GAINHF),
629 DECL(AL_REVERB_DECAY_TIME),
630 DECL(AL_REVERB_DECAY_HFRATIO),
631 DECL(AL_REVERB_REFLECTIONS_GAIN),
632 DECL(AL_REVERB_REFLECTIONS_DELAY),
633 DECL(AL_REVERB_LATE_REVERB_GAIN),
634 DECL(AL_REVERB_LATE_REVERB_DELAY),
635 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
636 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
637 DECL(AL_REVERB_DECAY_HFLIMIT),
639 DECL(AL_CHORUS_WAVEFORM),
640 DECL(AL_CHORUS_PHASE),
641 DECL(AL_CHORUS_RATE),
642 DECL(AL_CHORUS_DEPTH),
643 DECL(AL_CHORUS_FEEDBACK),
644 DECL(AL_CHORUS_DELAY),
646 DECL(AL_DISTORTION_EDGE),
647 DECL(AL_DISTORTION_GAIN),
648 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
649 DECL(AL_DISTORTION_EQCENTER),
650 DECL(AL_DISTORTION_EQBANDWIDTH),
652 DECL(AL_ECHO_DELAY),
653 DECL(AL_ECHO_LRDELAY),
654 DECL(AL_ECHO_DAMPING),
655 DECL(AL_ECHO_FEEDBACK),
656 DECL(AL_ECHO_SPREAD),
658 DECL(AL_FLANGER_WAVEFORM),
659 DECL(AL_FLANGER_PHASE),
660 DECL(AL_FLANGER_RATE),
661 DECL(AL_FLANGER_DEPTH),
662 DECL(AL_FLANGER_FEEDBACK),
663 DECL(AL_FLANGER_DELAY),
665 DECL(AL_RING_MODULATOR_FREQUENCY),
666 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
667 DECL(AL_RING_MODULATOR_WAVEFORM),
669 DECL(AL_AUTOWAH_ATTACK_TIME),
670 DECL(AL_AUTOWAH_PEAK_GAIN),
671 DECL(AL_AUTOWAH_RELEASE_TIME),
672 DECL(AL_AUTOWAH_RESONANCE),
674 DECL(AL_COMPRESSOR_ONOFF),
676 DECL(AL_EQUALIZER_LOW_GAIN),
677 DECL(AL_EQUALIZER_LOW_CUTOFF),
678 DECL(AL_EQUALIZER_MID1_GAIN),
679 DECL(AL_EQUALIZER_MID1_CENTER),
680 DECL(AL_EQUALIZER_MID1_WIDTH),
681 DECL(AL_EQUALIZER_MID2_GAIN),
682 DECL(AL_EQUALIZER_MID2_CENTER),
683 DECL(AL_EQUALIZER_MID2_WIDTH),
684 DECL(AL_EQUALIZER_HIGH_GAIN),
685 DECL(AL_EQUALIZER_HIGH_CUTOFF),
687 DECL(AL_DEDICATED_GAIN),
689 { NULL, (ALCenum)0 }
691 #undef DECL
693 static const ALCchar alcNoError[] = "No Error";
694 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
695 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
696 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
697 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
698 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
701 /************************************************
702 * Global variables
703 ************************************************/
705 /* Enumerated device names */
706 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
708 static al_string alcAllDevicesList;
709 static al_string alcCaptureDeviceList;
711 /* Default is always the first in the list */
712 static ALCchar *alcDefaultAllDevicesSpecifier;
713 static ALCchar *alcCaptureDefaultDeviceSpecifier;
715 /* Default context extensions */
716 static const ALchar alExtList[] =
717 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
718 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
719 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
720 "AL_LOKI_quadriphonic AL_SOFTX_block_alignment AL_SOFT_buffer_samples "
721 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
722 "AL_SOFT_loop_points AL_SOFTX_MSADPCM AL_SOFT_source_latency";
724 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
726 /* Thread-local current context */
727 static altss_t LocalContext;
728 /* Process-wide current context */
729 static ALCcontext *volatile GlobalContext = NULL;
731 /* Mixing thread piority level */
732 ALint RTPrioLevel;
734 FILE *LogFile;
735 #ifdef _DEBUG
736 enum LogLevel LogLevel = LogWarning;
737 #else
738 enum LogLevel LogLevel = LogError;
739 #endif
741 /* Flag to trap ALC device errors */
742 static ALCboolean TrapALCError = ALC_FALSE;
744 /* One-time configuration init control */
745 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
747 /* Default effect that applies to sources that don't have an effect on send 0 */
748 static ALeffect DefaultEffect;
751 /************************************************
752 * ALC information
753 ************************************************/
754 static const ALCchar alcNoDeviceExtList[] =
755 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
756 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
757 static const ALCchar alcExtensionList[] =
758 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
759 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
760 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
761 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
762 static const ALCint alcMajorVersion = 1;
763 static const ALCint alcMinorVersion = 1;
765 static const ALCint alcEFXMajorVersion = 1;
766 static const ALCint alcEFXMinorVersion = 0;
769 /************************************************
770 * Device lists
771 ************************************************/
772 static ALCdevice *volatile DeviceList = NULL;
774 static almtx_t ListLock;
775 static inline void LockLists(void)
777 int lockret = almtx_lock(&ListLock);
778 assert(lockret == althrd_success);
780 static inline void UnlockLists(void)
782 int unlockret = almtx_unlock(&ListLock);
783 assert(unlockret == althrd_success);
786 /************************************************
787 * Library initialization
788 ************************************************/
789 #if defined(_WIN32)
790 static void alc_init(void);
791 static void alc_deinit(void);
792 static void alc_deinit_safe(void);
794 #ifndef AL_LIBTYPE_STATIC
795 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
797 switch(reason)
799 case DLL_PROCESS_ATTACH:
800 /* Pin the DLL so we won't get unloaded until the process terminates */
801 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
802 (WCHAR*)hModule, &hModule);
803 alc_init();
804 break;
806 case DLL_THREAD_DETACH:
807 break;
809 case DLL_PROCESS_DETACH:
810 if(!lpReserved)
811 alc_deinit();
812 else
813 alc_deinit_safe();
814 break;
816 return TRUE;
818 #elif defined(_MSC_VER)
819 #pragma section(".CRT$XCU",read)
820 static void alc_constructor(void);
821 static void alc_destructor(void);
822 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
824 static void alc_constructor(void)
826 atexit(alc_destructor);
827 alc_init();
830 static void alc_destructor(void)
832 alc_deinit();
834 #elif defined(HAVE_GCC_DESTRUCTOR)
835 static void alc_init(void) __attribute__((constructor));
836 static void alc_deinit(void) __attribute__((destructor));
837 #else
838 #error "No static initialization available on this platform!"
839 #endif
841 #elif defined(HAVE_GCC_DESTRUCTOR)
843 static void alc_init(void) __attribute__((constructor));
844 static void alc_deinit(void) __attribute__((destructor));
846 #else
847 #error "No global initialization available on this platform!"
848 #endif
850 static void ReleaseThreadCtx(void *ptr);
851 static void alc_init(void)
853 const char *str;
854 int ret;
856 LogFile = stderr;
858 AL_STRING_INIT(alcAllDevicesList);
859 AL_STRING_INIT(alcCaptureDeviceList);
861 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
862 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
863 ConeScale *= 0.5f;
865 str = getenv("__ALSOFT_REVERSE_Z");
866 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
867 ZScale *= -1.0f;
869 ret = altss_create(&LocalContext, ReleaseThreadCtx);
870 assert(ret == althrd_success);
872 ret = almtx_init(&ListLock, almtx_recursive);
873 assert(ret == althrd_success);
875 ThunkInit();
878 static void alc_initconfig(void)
880 const char *devs, *str;
881 ALuint capfilter;
882 float valf;
883 int i, n;
885 str = getenv("ALSOFT_LOGLEVEL");
886 if(str)
888 long lvl = strtol(str, NULL, 0);
889 if(lvl >= NoLog && lvl <= LogRef)
890 LogLevel = lvl;
893 str = getenv("ALSOFT_LOGFILE");
894 if(str && str[0])
896 FILE *logfile = al_fopen(str, "wt");
897 if(logfile) LogFile = logfile;
898 else ERR("Failed to open log file '%s'\n", str);
902 char buf[1024] = "";
903 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
904 for(i = 1;BackendList[i].name;i++)
905 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
906 TRACE("Supported backends: %s\n", buf);
908 ReadALConfig();
910 capfilter = 0;
911 #ifdef HAVE_SSE
912 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
913 #endif
914 #ifdef HAVE_NEON
915 capfilter |= CPU_CAP_NEON;
916 #endif
917 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
919 if(strcasecmp(str, "all") == 0)
920 capfilter = 0;
921 else
923 size_t len;
924 const char *next = str;
926 do {
927 str = next;
928 while(isspace(str[0]))
929 str++;
930 next = strchr(str, ',');
932 if(!str[0] || str[0] == ',')
933 continue;
935 len = (next ? ((size_t)(next-str)) : strlen(str));
936 while(len > 0 && isspace(str[len-1]))
937 len--;
938 if(len == 3 && strncasecmp(str, "sse", len) == 0)
939 capfilter &= ~CPU_CAP_SSE;
940 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
941 capfilter &= ~CPU_CAP_SSE2;
942 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
943 capfilter &= ~CPU_CAP_NEON;
944 else
945 WARN("Invalid CPU extension \"%s\"\n", str);
946 } while(next++);
949 FillCPUCaps(capfilter);
951 #ifdef _WIN32
952 RTPrioLevel = 1;
953 #else
954 RTPrioLevel = 0;
955 #endif
956 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
958 if(ConfigValueStr(NULL, "resampler", &str))
960 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
961 DefaultResampler = PointResampler;
962 else if(strcasecmp(str, "linear") == 0)
963 DefaultResampler = LinearResampler;
964 else if(strcasecmp(str, "cubic") == 0)
965 DefaultResampler = CubicResampler;
966 else
968 char *end;
970 n = strtol(str, &end, 0);
971 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
972 DefaultResampler = n;
973 else
974 WARN("Invalid resampler: %s\n", str);
978 str = getenv("ALSOFT_TRAP_ERROR");
979 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
981 TrapALError = AL_TRUE;
982 TrapALCError = AL_TRUE;
984 else
986 str = getenv("ALSOFT_TRAP_AL_ERROR");
987 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALError = AL_TRUE;
989 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
991 str = getenv("ALSOFT_TRAP_ALC_ERROR");
992 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
993 TrapALCError = ALC_TRUE;
994 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
997 if(ConfigValueFloat("reverb", "boost", &valf))
998 ReverbBoost *= powf(10.0f, valf / 20.0f);
1000 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1002 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1003 ConfigValueStr(NULL, "drivers", &devs))
1005 int n;
1006 size_t len;
1007 const char *next = devs;
1008 int endlist, delitem;
1010 i = 0;
1011 do {
1012 devs = next;
1013 while(isspace(devs[0]))
1014 devs++;
1015 next = strchr(devs, ',');
1017 delitem = (devs[0] == '-');
1018 if(devs[0] == '-') devs++;
1020 if(!devs[0] || devs[0] == ',')
1022 endlist = 0;
1023 continue;
1025 endlist = 1;
1027 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1028 while(len > 0 && isspace(devs[len-1]))
1029 len--;
1030 for(n = i;BackendList[n].name;n++)
1032 if(len == strlen(BackendList[n].name) &&
1033 strncmp(BackendList[n].name, devs, len) == 0)
1035 if(delitem)
1037 do {
1038 BackendList[n] = BackendList[n+1];
1039 ++n;
1040 } while(BackendList[n].name);
1042 else
1044 struct BackendInfo Bkp = BackendList[n];
1045 while(n > i)
1047 BackendList[n] = BackendList[n-1];
1048 --n;
1050 BackendList[n] = Bkp;
1052 i++;
1054 break;
1057 } while(next++);
1059 if(endlist)
1061 BackendList[i].name = NULL;
1062 BackendList[i].getFactory = NULL;
1063 BackendList[i].Init = NULL;
1064 BackendList[i].Deinit = NULL;
1065 BackendList[i].Probe = NULL;
1069 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1071 if(BackendList[i].getFactory)
1073 ALCbackendFactory *factory = BackendList[i].getFactory();
1074 if(!V0(factory,init)())
1076 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1077 continue;
1080 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1081 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1083 PlaybackBackend = BackendList[i];
1084 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1086 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1088 CaptureBackend = BackendList[i];
1089 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1092 continue;
1095 if(!BackendList[i].Init(&BackendList[i].Funcs))
1097 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1098 continue;
1101 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1102 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1104 PlaybackBackend = BackendList[i];
1105 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1107 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1109 CaptureBackend = BackendList[i];
1110 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1114 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1115 V0(factory,init)();
1118 if(ConfigValueStr(NULL, "excludefx", &str))
1120 size_t len;
1121 const char *next = str;
1123 do {
1124 str = next;
1125 next = strchr(str, ',');
1127 if(!str[0] || next == str)
1128 continue;
1130 len = (next ? ((size_t)(next-str)) : strlen(str));
1131 for(n = 0;EffectList[n].name;n++)
1133 if(len == strlen(EffectList[n].name) &&
1134 strncmp(EffectList[n].name, str, len) == 0)
1135 DisabledEffects[EffectList[n].type] = AL_TRUE;
1137 } while(next++);
1140 InitEffectFactoryMap();
1142 InitEffect(&DefaultEffect);
1143 str = getenv("ALSOFT_DEFAULT_REVERB");
1144 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1145 LoadReverbPreset(str, &DefaultEffect);
1147 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1150 /************************************************
1151 * Library deinitialization
1152 ************************************************/
1153 static void alc_cleanup(void)
1155 ALCdevice *dev;
1157 AL_STRING_DEINIT(alcAllDevicesList);
1158 AL_STRING_DEINIT(alcCaptureDeviceList);
1160 free(alcDefaultAllDevicesSpecifier);
1161 alcDefaultAllDevicesSpecifier = NULL;
1162 free(alcCaptureDefaultDeviceSpecifier);
1163 alcCaptureDefaultDeviceSpecifier = NULL;
1165 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1167 ALCuint num = 0;
1168 do {
1169 num++;
1170 } while((dev=dev->next) != NULL);
1171 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1174 DeinitEffectFactoryMap();
1177 static void alc_deinit_safe(void)
1179 alc_cleanup();
1181 FreeHrtfs();
1182 FreeALConfig();
1184 ThunkExit();
1185 almtx_destroy(&ListLock);
1186 altss_delete(LocalContext);
1188 if(LogFile != stderr)
1189 fclose(LogFile);
1190 LogFile = NULL;
1193 static void alc_deinit(void)
1195 int i;
1197 alc_cleanup();
1199 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1200 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1202 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1204 if(!BackendList[i].getFactory)
1205 BackendList[i].Deinit();
1206 else
1208 ALCbackendFactory *factory = BackendList[i].getFactory();
1209 V0(factory,deinit)();
1213 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1214 V0(factory,deinit)();
1217 alc_deinit_safe();
1221 /************************************************
1222 * Device enumeration
1223 ************************************************/
1224 static void ProbeDevices(al_string *list, enum DevProbe type)
1226 DO_INITCONFIG();
1228 LockLists();
1229 al_string_clear(list);
1231 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1233 if(!PlaybackBackend.getFactory)
1234 PlaybackBackend.Probe(type);
1235 else
1237 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1238 V(factory,probe)(type);
1241 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1243 if(!CaptureBackend.getFactory)
1244 CaptureBackend.Probe(type);
1245 else
1247 ALCbackendFactory *factory = CaptureBackend.getFactory();
1248 V(factory,probe)(type);
1251 UnlockLists();
1253 static void ProbeAllDevicesList(void)
1254 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1255 static void ProbeCaptureDeviceList(void)
1256 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1258 static void AppendDevice(const ALCchar *name, al_string *devnames)
1260 size_t len = strlen(name);
1261 if(len > 0)
1263 al_string_append_range(devnames, name, name+len);
1264 al_string_append_char(devnames, '\0');
1267 void AppendAllDevicesList(const ALCchar *name)
1268 { AppendDevice(name, &alcAllDevicesList); }
1269 void AppendCaptureDeviceList(const ALCchar *name)
1270 { AppendDevice(name, &alcCaptureDeviceList); }
1273 /************************************************
1274 * Device format information
1275 ************************************************/
1276 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1278 switch(type)
1280 case DevFmtByte: return "Signed Byte";
1281 case DevFmtUByte: return "Unsigned Byte";
1282 case DevFmtShort: return "Signed Short";
1283 case DevFmtUShort: return "Unsigned Short";
1284 case DevFmtInt: return "Signed Int";
1285 case DevFmtUInt: return "Unsigned Int";
1286 case DevFmtFloat: return "Float";
1288 return "(unknown type)";
1290 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1292 switch(chans)
1294 case DevFmtMono: return "Mono";
1295 case DevFmtStereo: return "Stereo";
1296 case DevFmtQuad: return "Quadraphonic";
1297 case DevFmtX51: return "5.1 Surround";
1298 case DevFmtX51Side: return "5.1 Side";
1299 case DevFmtX61: return "6.1 Surround";
1300 case DevFmtX71: return "7.1 Surround";
1302 return "(unknown channels)";
1305 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1306 ALuint BytesFromDevFmt(enum DevFmtType type)
1308 switch(type)
1310 case DevFmtByte: return sizeof(ALbyte);
1311 case DevFmtUByte: return sizeof(ALubyte);
1312 case DevFmtShort: return sizeof(ALshort);
1313 case DevFmtUShort: return sizeof(ALushort);
1314 case DevFmtInt: return sizeof(ALint);
1315 case DevFmtUInt: return sizeof(ALuint);
1316 case DevFmtFloat: return sizeof(ALfloat);
1318 return 0;
1320 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1322 switch(chans)
1324 case DevFmtMono: return 1;
1325 case DevFmtStereo: return 2;
1326 case DevFmtQuad: return 4;
1327 case DevFmtX51: return 6;
1328 case DevFmtX51Side: return 6;
1329 case DevFmtX61: return 7;
1330 case DevFmtX71: return 8;
1332 return 0;
1335 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1336 enum DevFmtType *type)
1338 static const struct {
1339 ALenum format;
1340 enum DevFmtChannels channels;
1341 enum DevFmtType type;
1342 } list[] = {
1343 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1344 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1345 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1347 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1348 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1349 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1351 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1352 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1353 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1355 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1356 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1357 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1359 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1360 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1361 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1363 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1364 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1365 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1367 ALuint i;
1369 for(i = 0;i < COUNTOF(list);i++)
1371 if(list[i].format == format)
1373 *chans = list[i].channels;
1374 *type = list[i].type;
1375 return AL_TRUE;
1379 return AL_FALSE;
1382 static ALCboolean IsValidALCType(ALCenum type)
1384 switch(type)
1386 case ALC_BYTE_SOFT:
1387 case ALC_UNSIGNED_BYTE_SOFT:
1388 case ALC_SHORT_SOFT:
1389 case ALC_UNSIGNED_SHORT_SOFT:
1390 case ALC_INT_SOFT:
1391 case ALC_UNSIGNED_INT_SOFT:
1392 case ALC_FLOAT_SOFT:
1393 return ALC_TRUE;
1395 return ALC_FALSE;
1398 static ALCboolean IsValidALCChannels(ALCenum channels)
1400 switch(channels)
1402 case ALC_MONO_SOFT:
1403 case ALC_STEREO_SOFT:
1404 case ALC_QUAD_SOFT:
1405 case ALC_5POINT1_SOFT:
1406 case ALC_6POINT1_SOFT:
1407 case ALC_7POINT1_SOFT:
1408 return ALC_TRUE;
1410 return ALC_FALSE;
1414 /************************************************
1415 * Miscellaneous ALC helpers
1416 ************************************************/
1417 extern inline void LockContext(ALCcontext *context);
1418 extern inline void UnlockContext(ALCcontext *context);
1420 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *UNUSED(device))
1422 return 0;
1425 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1427 return V0(device->Backend,getLatency)();
1430 void ALCdevice_Lock(ALCdevice *device)
1432 V0(device->Backend,lock)();
1435 void ALCdevice_Unlock(ALCdevice *device)
1437 V0(device->Backend,unlock)();
1441 /* SetDefaultWFXChannelOrder
1443 * Sets the default channel order used by WaveFormatEx.
1445 void SetDefaultWFXChannelOrder(ALCdevice *device)
1447 ALuint i;
1449 for(i = 0;i < MaxChannels;i++)
1450 device->ChannelOffsets[i] = INVALID_OFFSET;
1452 switch(device->FmtChans)
1454 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1455 break;
1456 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1457 device->ChannelOffsets[FrontRight] = 1;
1458 break;
1459 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1460 device->ChannelOffsets[FrontRight] = 1;
1461 device->ChannelOffsets[BackLeft] = 2;
1462 device->ChannelOffsets[BackRight] = 3;
1463 break;
1464 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1465 device->ChannelOffsets[FrontRight] = 1;
1466 device->ChannelOffsets[FrontCenter] = 2;
1467 device->ChannelOffsets[LFE] = 3;
1468 device->ChannelOffsets[BackLeft] = 4;
1469 device->ChannelOffsets[BackRight] = 5;
1470 break;
1471 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1472 device->ChannelOffsets[FrontRight] = 1;
1473 device->ChannelOffsets[FrontCenter] = 2;
1474 device->ChannelOffsets[LFE] = 3;
1475 device->ChannelOffsets[SideLeft] = 4;
1476 device->ChannelOffsets[SideRight] = 5;
1477 break;
1478 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1479 device->ChannelOffsets[FrontRight] = 1;
1480 device->ChannelOffsets[FrontCenter] = 2;
1481 device->ChannelOffsets[LFE] = 3;
1482 device->ChannelOffsets[BackCenter] = 4;
1483 device->ChannelOffsets[SideLeft] = 5;
1484 device->ChannelOffsets[SideRight] = 6;
1485 break;
1486 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1487 device->ChannelOffsets[FrontRight] = 1;
1488 device->ChannelOffsets[FrontCenter] = 2;
1489 device->ChannelOffsets[LFE] = 3;
1490 device->ChannelOffsets[BackLeft] = 4;
1491 device->ChannelOffsets[BackRight] = 5;
1492 device->ChannelOffsets[SideLeft] = 6;
1493 device->ChannelOffsets[SideRight] = 7;
1494 break;
1498 /* SetDefaultChannelOrder
1500 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1502 void SetDefaultChannelOrder(ALCdevice *device)
1504 ALuint i;
1506 for(i = 0;i < MaxChannels;i++)
1507 device->ChannelOffsets[i] = INVALID_OFFSET;
1509 switch(device->FmtChans)
1511 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1512 device->ChannelOffsets[FrontRight] = 1;
1513 device->ChannelOffsets[BackLeft] = 2;
1514 device->ChannelOffsets[BackRight] = 3;
1515 device->ChannelOffsets[FrontCenter] = 4;
1516 device->ChannelOffsets[LFE] = 5;
1517 return;
1518 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1519 device->ChannelOffsets[FrontRight] = 1;
1520 device->ChannelOffsets[BackLeft] = 2;
1521 device->ChannelOffsets[BackRight] = 3;
1522 device->ChannelOffsets[FrontCenter] = 4;
1523 device->ChannelOffsets[LFE] = 5;
1524 device->ChannelOffsets[SideLeft] = 6;
1525 device->ChannelOffsets[SideRight] = 7;
1526 return;
1528 /* Same as WFX order */
1529 case DevFmtMono:
1530 case DevFmtStereo:
1531 case DevFmtQuad:
1532 case DevFmtX51Side:
1533 case DevFmtX61:
1534 break;
1536 SetDefaultWFXChannelOrder(device);
1540 /* alcSetError
1542 * Stores the latest ALC device error
1544 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1546 if(TrapALCError)
1548 #ifdef _WIN32
1549 /* DebugBreak() will cause an exception if there is no debugger */
1550 if(IsDebuggerPresent())
1551 DebugBreak();
1552 #elif defined(SIGTRAP)
1553 raise(SIGTRAP);
1554 #endif
1557 if(device)
1558 device->LastError = errorCode;
1559 else
1560 LastNullDeviceError = errorCode;
1564 /* UpdateClockBase
1566 * Updates the device's base clock time with however many samples have been
1567 * done. This is used so frequency changes on the device don't cause the time
1568 * to jump forward or back.
1570 static inline void UpdateClockBase(ALCdevice *device)
1572 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1573 device->SamplesDone = 0;
1576 /* UpdateDeviceParams
1578 * Updates device parameters according to the attribute list (caller is
1579 * responsible for holding the list lock).
1581 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1583 ALCcontext *context;
1584 enum DevFmtChannels oldChans;
1585 enum DevFmtType oldType;
1586 ALCuint oldFreq;
1587 FPUCtl oldMode;
1589 // Check for attributes
1590 if(device->Type == Loopback)
1592 enum {
1593 GotFreq = 1<<0,
1594 GotChans = 1<<1,
1595 GotType = 1<<2,
1596 GotAll = GotFreq|GotChans|GotType
1598 ALCuint freq, numMono, numStereo, numSends;
1599 enum DevFmtChannels schans;
1600 enum DevFmtType stype;
1601 ALCuint attrIdx = 0;
1602 ALCint gotFmt = 0;
1604 if(!attrList)
1606 WARN("Missing attributes for loopback device\n");
1607 return ALC_INVALID_VALUE;
1610 numMono = device->NumMonoSources;
1611 numStereo = device->NumStereoSources;
1612 numSends = device->NumAuxSends;
1613 schans = device->FmtChans;
1614 stype = device->FmtType;
1615 freq = device->Frequency;
1617 while(attrList[attrIdx])
1619 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1621 ALCint val = attrList[attrIdx + 1];
1622 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1623 return ALC_INVALID_VALUE;
1624 schans = val;
1625 gotFmt |= GotChans;
1628 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1630 ALCint val = attrList[attrIdx + 1];
1631 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1632 return ALC_INVALID_VALUE;
1633 stype = val;
1634 gotFmt |= GotType;
1637 if(attrList[attrIdx] == ALC_FREQUENCY)
1639 freq = attrList[attrIdx + 1];
1640 if(freq < MIN_OUTPUT_RATE)
1641 return ALC_INVALID_VALUE;
1642 gotFmt |= GotFreq;
1645 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1647 numStereo = attrList[attrIdx + 1];
1648 if(numStereo > device->MaxNoOfSources)
1649 numStereo = device->MaxNoOfSources;
1651 numMono = device->MaxNoOfSources - numStereo;
1654 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1655 numSends = attrList[attrIdx + 1];
1657 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1659 if(attrList[attrIdx + 1] != ALC_FALSE)
1660 device->Flags |= DEVICE_HRTF_REQUEST;
1661 else
1662 device->Flags &= ~DEVICE_HRTF_REQUEST;
1665 attrIdx += 2;
1668 if(gotFmt != GotAll)
1670 WARN("Missing format for loopback device\n");
1671 return ALC_INVALID_VALUE;
1674 ConfigValueUInt(NULL, "sends", &numSends);
1675 numSends = minu(MAX_SENDS, numSends);
1677 if((device->Flags&DEVICE_RUNNING))
1678 V0(device->Backend,stop)();
1679 device->Flags &= ~DEVICE_RUNNING;
1681 if(freq != device->Frequency)
1682 UpdateClockBase(device);
1683 device->Frequency = freq;
1684 device->FmtChans = schans;
1685 device->FmtType = stype;
1686 device->NumMonoSources = numMono;
1687 device->NumStereoSources = numStereo;
1688 device->NumAuxSends = numSends;
1690 else if(attrList && attrList[0])
1692 ALCuint freq, numMono, numStereo, numSends;
1693 ALCuint attrIdx = 0;
1695 /* If a context is already running on the device, stop playback so the
1696 * device attributes can be updated. */
1697 if((device->Flags&DEVICE_RUNNING))
1698 V0(device->Backend,stop)();
1699 device->Flags &= ~DEVICE_RUNNING;
1701 freq = device->Frequency;
1702 numMono = device->NumMonoSources;
1703 numStereo = device->NumStereoSources;
1704 numSends = device->NumAuxSends;
1706 while(attrList[attrIdx])
1708 if(attrList[attrIdx] == ALC_FREQUENCY)
1710 freq = attrList[attrIdx + 1];
1711 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1714 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1716 numStereo = attrList[attrIdx + 1];
1717 if(numStereo > device->MaxNoOfSources)
1718 numStereo = device->MaxNoOfSources;
1720 numMono = device->MaxNoOfSources - numStereo;
1723 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1724 numSends = attrList[attrIdx + 1];
1726 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1728 if(attrList[attrIdx + 1] != ALC_FALSE)
1729 device->Flags |= DEVICE_HRTF_REQUEST;
1730 else
1731 device->Flags &= ~DEVICE_HRTF_REQUEST;
1734 attrIdx += 2;
1737 ConfigValueUInt(NULL, "frequency", &freq);
1738 freq = maxu(freq, MIN_OUTPUT_RATE);
1740 ConfigValueUInt(NULL, "sends", &numSends);
1741 numSends = minu(MAX_SENDS, numSends);
1743 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1744 device->Frequency;
1745 /* SSE and Neon do best with the update size being a multiple of 4 */
1746 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1747 device->UpdateSize = (device->UpdateSize+3)&~3;
1749 if(freq != device->Frequency)
1750 UpdateClockBase(device);
1751 device->Frequency = freq;
1752 device->NumMonoSources = numMono;
1753 device->NumStereoSources = numStereo;
1754 device->NumAuxSends = numSends;
1757 if((device->Flags&DEVICE_RUNNING))
1758 return ALC_NO_ERROR;
1760 UpdateClockBase(device);
1762 oldFreq = device->Frequency;
1763 oldChans = device->FmtChans;
1764 oldType = device->FmtType;
1766 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1767 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1768 DevFmtChannelsString(device->FmtChans),
1769 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1770 DevFmtTypeString(device->FmtType),
1771 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1772 device->Frequency,
1773 device->UpdateSize, device->NumUpdates);
1775 if(device->Type != Loopback)
1777 int nohrtf = !(device->Flags&DEVICE_HRTF_REQUEST);
1778 if(GetConfigValueBool(NULL, "hrtf", !nohrtf))
1779 device->Flags |= DEVICE_HRTF_REQUEST;
1780 else
1781 device->Flags &= ~DEVICE_HRTF_REQUEST;
1783 if((device->Flags&DEVICE_HRTF_REQUEST))
1785 enum DevFmtChannels chans;
1786 ALCuint freq;
1787 if(FindHrtfFormat(device, &chans, &freq))
1789 device->Frequency = freq;
1790 device->FmtChans = chans;
1791 device->Flags |= DEVICE_CHANNELS_REQUEST |
1792 DEVICE_FREQUENCY_REQUEST;
1796 if(V0(device->Backend,reset)() == ALC_FALSE)
1797 return ALC_INVALID_DEVICE;
1799 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1801 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1802 DevFmtChannelsString(device->FmtChans));
1803 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1805 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1807 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1808 DevFmtTypeString(device->FmtType));
1809 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1811 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1813 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1814 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1817 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1818 DevFmtChannelsString(device->FmtChans),
1819 DevFmtTypeString(device->FmtType), device->Frequency,
1820 device->UpdateSize, device->NumUpdates);
1822 aluInitPanning(device);
1824 V(device->Synth,update)(device);
1826 device->Hrtf = NULL;
1827 if((device->Flags&DEVICE_HRTF_REQUEST))
1829 device->Hrtf = GetHrtf(device);
1830 if(!device->Hrtf)
1831 device->Flags &= ~DEVICE_HRTF_REQUEST;
1833 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1835 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1837 if(!device->Bs2b)
1839 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1840 bs2b_clear(device->Bs2b);
1842 bs2b_set_srate(device->Bs2b, device->Frequency);
1843 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1844 TRACE("BS2B level %d\n", device->Bs2bLevel);
1846 else
1848 free(device->Bs2b);
1849 device->Bs2b = NULL;
1850 TRACE("BS2B disabled\n");
1853 device->Flags &= ~DEVICE_WIDE_STEREO;
1854 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1855 device->Flags |= DEVICE_WIDE_STEREO;
1857 if(!device->Hrtf && (device->UpdateSize&3))
1859 if((CPUCapFlags&CPU_CAP_SSE))
1860 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1861 if((CPUCapFlags&CPU_CAP_NEON))
1862 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1865 SetMixerFPUMode(&oldMode);
1866 ALCdevice_Lock(device);
1867 context = device->ContextList;
1868 while(context)
1870 ALsizei pos;
1872 context->UpdateSources = AL_FALSE;
1873 LockUIntMapRead(&context->EffectSlotMap);
1874 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1876 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1878 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1880 UnlockUIntMapRead(&context->EffectSlotMap);
1881 ALCdevice_Unlock(device);
1882 RestoreFPUMode(&oldMode);
1883 return ALC_INVALID_DEVICE;
1885 slot->NeedsUpdate = AL_FALSE;
1886 V(slot->EffectState,update)(device, slot);
1888 UnlockUIntMapRead(&context->EffectSlotMap);
1890 LockUIntMapRead(&context->SourceMap);
1891 for(pos = 0;pos < context->SourceMap.size;pos++)
1893 ALsource *source = context->SourceMap.array[pos].value;
1894 ALuint s = device->NumAuxSends;
1895 while(s < MAX_SENDS)
1897 if(source->Send[s].Slot)
1898 DecrementRef(&source->Send[s].Slot->ref);
1899 source->Send[s].Slot = NULL;
1900 source->Send[s].Gain = 1.0f;
1901 source->Send[s].GainHF = 1.0f;
1902 s++;
1904 source->NeedsUpdate = AL_TRUE;
1906 UnlockUIntMapRead(&context->SourceMap);
1908 for(pos = 0;pos < context->ActiveSourceCount;pos++)
1910 ALactivesource *src = context->ActiveSources[pos];
1911 ALsource *source = src->Source;
1912 ALuint s = device->NumAuxSends;
1913 while(s < MAX_SENDS)
1915 src->Send[s].Moving = AL_FALSE;
1916 src->Send[s].Counter = 0;
1917 s++;
1920 src->Update(src, context);
1921 source->NeedsUpdate = AL_FALSE;
1924 context = context->next;
1926 if(device->DefaultSlot)
1928 ALeffectslot *slot = device->DefaultSlot;
1930 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1932 ALCdevice_Unlock(device);
1933 RestoreFPUMode(&oldMode);
1934 return ALC_INVALID_DEVICE;
1936 slot->NeedsUpdate = AL_FALSE;
1937 V(slot->EffectState,update)(device, slot);
1939 ALCdevice_Unlock(device);
1940 RestoreFPUMode(&oldMode);
1942 if(!(device->Flags&DEVICE_PAUSED))
1944 if(V0(device->Backend,start)() == ALC_FALSE)
1945 return ALC_INVALID_DEVICE;
1946 device->Flags |= DEVICE_RUNNING;
1949 return ALC_NO_ERROR;
1952 /* FreeDevice
1954 * Frees the device structure, and destroys any objects the app failed to
1955 * delete. Called once there's no more references on the device.
1957 static ALCvoid FreeDevice(ALCdevice *device)
1959 TRACE("%p\n", device);
1961 V0(device->Backend,close)();
1962 DELETE_OBJ(device->Backend);
1963 device->Backend = NULL;
1965 DELETE_OBJ(device->Synth);
1966 device->Synth = NULL;
1968 if(device->DefaultSlot)
1970 ALeffectState *state = device->DefaultSlot->EffectState;
1971 device->DefaultSlot = NULL;
1972 DELETE_OBJ(state);
1975 if(device->DefaultSfont)
1976 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1977 device->DefaultSfont = NULL;
1979 if(device->BufferMap.size > 0)
1981 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1982 ReleaseALBuffers(device);
1984 ResetUIntMap(&device->BufferMap);
1986 if(device->EffectMap.size > 0)
1988 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1989 ReleaseALEffects(device);
1991 ResetUIntMap(&device->EffectMap);
1993 if(device->FilterMap.size > 0)
1995 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1996 ReleaseALFilters(device);
1998 ResetUIntMap(&device->FilterMap);
2000 if(device->SfontMap.size > 0)
2002 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2003 ReleaseALSoundfonts(device);
2005 ResetUIntMap(&device->SfontMap);
2007 if(device->PresetMap.size > 0)
2009 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2010 ReleaseALPresets(device);
2012 ResetUIntMap(&device->PresetMap);
2014 if(device->FontsoundMap.size > 0)
2016 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2017 ReleaseALFontsounds(device);
2019 ResetUIntMap(&device->FontsoundMap);
2021 free(device->Bs2b);
2022 device->Bs2b = NULL;
2024 AL_STRING_DEINIT(device->DeviceName);
2026 al_free(device);
2030 void ALCdevice_IncRef(ALCdevice *device)
2032 uint ref;
2033 ref = IncrementRef(&device->ref);
2034 TRACEREF("%p increasing refcount to %u\n", device, ref);
2037 void ALCdevice_DecRef(ALCdevice *device)
2039 uint ref;
2040 ref = DecrementRef(&device->ref);
2041 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2042 if(ref == 0) FreeDevice(device);
2045 /* VerifyDevice
2047 * Checks if the device handle is valid, and increments its ref count if so.
2049 static ALCdevice *VerifyDevice(ALCdevice *device)
2051 ALCdevice *tmpDevice;
2053 if(!device)
2054 return NULL;
2056 LockLists();
2057 tmpDevice = DeviceList;
2058 while(tmpDevice && tmpDevice != device)
2059 tmpDevice = tmpDevice->next;
2061 if(tmpDevice)
2062 ALCdevice_IncRef(tmpDevice);
2063 UnlockLists();
2064 return tmpDevice;
2068 /* InitContext
2070 * Initializes context fields
2072 static ALvoid InitContext(ALCcontext *Context)
2074 ALint i, j;
2076 //Initialise listener
2077 Context->Listener->Gain = 1.0f;
2078 Context->Listener->MetersPerUnit = 1.0f;
2079 Context->Listener->Position[0] = 0.0f;
2080 Context->Listener->Position[1] = 0.0f;
2081 Context->Listener->Position[2] = 0.0f;
2082 Context->Listener->Velocity[0] = 0.0f;
2083 Context->Listener->Velocity[1] = 0.0f;
2084 Context->Listener->Velocity[2] = 0.0f;
2085 Context->Listener->Forward[0] = 0.0f;
2086 Context->Listener->Forward[1] = 0.0f;
2087 Context->Listener->Forward[2] = -1.0f;
2088 Context->Listener->Up[0] = 0.0f;
2089 Context->Listener->Up[1] = 1.0f;
2090 Context->Listener->Up[2] = 0.0f;
2091 for(i = 0;i < 4;i++)
2093 for(j = 0;j < 4;j++)
2094 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2096 for(i = 0;i < 3;i++)
2097 Context->Listener->Params.Velocity[i] = 0.0f;
2099 //Validate Context
2100 Context->LastError = AL_NO_ERROR;
2101 Context->UpdateSources = AL_FALSE;
2102 Context->ActiveSourceCount = 0;
2103 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2104 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2106 //Set globals
2107 Context->DistanceModel = DefaultDistanceModel;
2108 Context->SourceDistanceModel = AL_FALSE;
2109 Context->DopplerFactor = 1.0f;
2110 Context->DopplerVelocity = 1.0f;
2111 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2112 Context->DeferUpdates = AL_FALSE;
2114 Context->ExtensionList = alExtList;
2118 /* FreeContext
2120 * Cleans up the context, and destroys any remaining objects the app failed to
2121 * delete. Called once there's no more references on the context.
2123 static ALCvoid FreeContext(ALCcontext *context)
2125 ALsizei i;
2127 TRACE("%p\n", context);
2129 if(context->SourceMap.size > 0)
2131 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2132 ReleaseALSources(context);
2134 ResetUIntMap(&context->SourceMap);
2136 if(context->EffectSlotMap.size > 0)
2138 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2139 ReleaseALAuxiliaryEffectSlots(context);
2141 ResetUIntMap(&context->EffectSlotMap);
2143 for(i = 0;i < context->MaxActiveSources;i++)
2145 al_free(context->ActiveSources[i]);
2146 context->ActiveSources[i] = NULL;
2148 free(context->ActiveSources);
2149 context->ActiveSources = NULL;
2150 context->ActiveSourceCount = 0;
2151 context->MaxActiveSources = 0;
2153 VECTOR_DEINIT(context->ActiveAuxSlots);
2155 ALCdevice_DecRef(context->Device);
2156 context->Device = NULL;
2158 //Invalidate context
2159 memset(context, 0, sizeof(ALCcontext));
2160 free(context);
2163 /* ReleaseContext
2165 * Removes the context reference from the given device and removes it from
2166 * being current on the running thread or globally.
2168 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2170 ALCcontext *volatile*tmp_ctx;
2172 if(altss_get(LocalContext) == context)
2174 WARN("%p released while current on thread\n", context);
2175 altss_set(LocalContext, NULL);
2176 ALCcontext_DecRef(context);
2179 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL) == context)
2180 ALCcontext_DecRef(context);
2182 ALCdevice_Lock(device);
2183 tmp_ctx = &device->ContextList;
2184 while(*tmp_ctx)
2186 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next) == context)
2187 break;
2188 tmp_ctx = &(*tmp_ctx)->next;
2190 ALCdevice_Unlock(device);
2192 ALCcontext_DecRef(context);
2195 void ALCcontext_IncRef(ALCcontext *context)
2197 uint ref;
2198 ref = IncrementRef(&context->ref);
2199 TRACEREF("%p increasing refcount to %u\n", context, ref);
2202 void ALCcontext_DecRef(ALCcontext *context)
2204 uint ref;
2205 ref = DecrementRef(&context->ref);
2206 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2207 if(ref == 0) FreeContext(context);
2210 static void ReleaseThreadCtx(void *ptr)
2212 WARN("%p current for thread being destroyed\n", ptr);
2213 ALCcontext_DecRef(ptr);
2216 /* VerifyContext
2218 * Checks that the given context is valid, and increments its reference count.
2220 static ALCcontext *VerifyContext(ALCcontext *context)
2222 ALCdevice *dev;
2224 LockLists();
2225 dev = DeviceList;
2226 while(dev)
2228 ALCcontext *tmp_ctx = dev->ContextList;
2229 while(tmp_ctx)
2231 if(tmp_ctx == context)
2233 ALCcontext_IncRef(tmp_ctx);
2234 UnlockLists();
2235 return tmp_ctx;
2237 tmp_ctx = tmp_ctx->next;
2239 dev = dev->next;
2241 UnlockLists();
2243 return NULL;
2247 /* GetContextRef
2249 * Returns the currently active context for this thread, and adds a reference
2250 * without locking it.
2252 ALCcontext *GetContextRef(void)
2254 ALCcontext *context;
2256 context = altss_get(LocalContext);
2257 if(context)
2258 ALCcontext_IncRef(context);
2259 else
2261 LockLists();
2262 context = GlobalContext;
2263 if(context)
2264 ALCcontext_IncRef(context);
2265 UnlockLists();
2268 return context;
2272 /************************************************
2273 * Standard ALC functions
2274 ************************************************/
2276 /* alcGetError
2278 * Return last ALC generated error code for the given device
2280 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2282 ALCenum errorCode;
2284 if(VerifyDevice(device))
2286 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2287 ALCdevice_DecRef(device);
2289 else
2290 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2292 return errorCode;
2296 /* alcSuspendContext
2298 * Not functional
2300 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2304 /* alcProcessContext
2306 * Not functional
2308 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2313 /* alcGetString
2315 * Returns information about the device, and error strings
2317 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2319 const ALCchar *value = NULL;
2321 switch(param)
2323 case ALC_NO_ERROR:
2324 value = alcNoError;
2325 break;
2327 case ALC_INVALID_ENUM:
2328 value = alcErrInvalidEnum;
2329 break;
2331 case ALC_INVALID_VALUE:
2332 value = alcErrInvalidValue;
2333 break;
2335 case ALC_INVALID_DEVICE:
2336 value = alcErrInvalidDevice;
2337 break;
2339 case ALC_INVALID_CONTEXT:
2340 value = alcErrInvalidContext;
2341 break;
2343 case ALC_OUT_OF_MEMORY:
2344 value = alcErrOutOfMemory;
2345 break;
2347 case ALC_DEVICE_SPECIFIER:
2348 value = alcDefaultName;
2349 break;
2351 case ALC_ALL_DEVICES_SPECIFIER:
2352 if(VerifyDevice(Device))
2354 value = al_string_get_cstr(Device->DeviceName);
2355 ALCdevice_DecRef(Device);
2357 else
2359 ProbeAllDevicesList();
2360 value = al_string_get_cstr(alcAllDevicesList);
2362 break;
2364 case ALC_CAPTURE_DEVICE_SPECIFIER:
2365 if(VerifyDevice(Device))
2367 value = al_string_get_cstr(Device->DeviceName);
2368 ALCdevice_DecRef(Device);
2370 else
2372 ProbeCaptureDeviceList();
2373 value = al_string_get_cstr(alcCaptureDeviceList);
2375 break;
2377 /* Default devices are always first in the list */
2378 case ALC_DEFAULT_DEVICE_SPECIFIER:
2379 value = alcDefaultName;
2380 break;
2382 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2383 if(al_string_empty(alcAllDevicesList))
2384 ProbeAllDevicesList();
2386 Device = VerifyDevice(Device);
2388 free(alcDefaultAllDevicesSpecifier);
2389 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2390 if(!alcDefaultAllDevicesSpecifier)
2391 alcSetError(Device, ALC_OUT_OF_MEMORY);
2393 value = alcDefaultAllDevicesSpecifier;
2394 if(Device) ALCdevice_DecRef(Device);
2395 break;
2397 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2398 if(al_string_empty(alcCaptureDeviceList))
2399 ProbeCaptureDeviceList();
2401 Device = VerifyDevice(Device);
2403 free(alcCaptureDefaultDeviceSpecifier);
2404 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2405 if(!alcCaptureDefaultDeviceSpecifier)
2406 alcSetError(Device, ALC_OUT_OF_MEMORY);
2408 value = alcCaptureDefaultDeviceSpecifier;
2409 if(Device) ALCdevice_DecRef(Device);
2410 break;
2412 case ALC_EXTENSIONS:
2413 if(!VerifyDevice(Device))
2414 value = alcNoDeviceExtList;
2415 else
2417 value = alcExtensionList;
2418 ALCdevice_DecRef(Device);
2420 break;
2422 default:
2423 Device = VerifyDevice(Device);
2424 alcSetError(Device, ALC_INVALID_ENUM);
2425 if(Device) ALCdevice_DecRef(Device);
2426 break;
2429 return value;
2433 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2435 ALCsizei i;
2437 if(size <= 0 || values == NULL)
2439 alcSetError(device, ALC_INVALID_VALUE);
2440 return 0;
2443 if(!device)
2445 switch(param)
2447 case ALC_MAJOR_VERSION:
2448 values[0] = alcMajorVersion;
2449 return 1;
2450 case ALC_MINOR_VERSION:
2451 values[0] = alcMinorVersion;
2452 return 1;
2454 case ALC_ATTRIBUTES_SIZE:
2455 case ALC_ALL_ATTRIBUTES:
2456 case ALC_FREQUENCY:
2457 case ALC_REFRESH:
2458 case ALC_SYNC:
2459 case ALC_MONO_SOURCES:
2460 case ALC_STEREO_SOURCES:
2461 case ALC_CAPTURE_SAMPLES:
2462 case ALC_FORMAT_CHANNELS_SOFT:
2463 case ALC_FORMAT_TYPE_SOFT:
2464 alcSetError(NULL, ALC_INVALID_DEVICE);
2465 return 0;
2467 default:
2468 alcSetError(NULL, ALC_INVALID_ENUM);
2469 return 0;
2471 return 0;
2474 if(device->Type == Capture)
2476 switch(param)
2478 case ALC_CAPTURE_SAMPLES:
2479 ALCdevice_Lock(device);
2480 values[0] = V0(device->Backend,availableSamples)();
2481 ALCdevice_Unlock(device);
2482 return 1;
2484 case ALC_CONNECTED:
2485 values[0] = device->Connected;
2486 return 1;
2488 default:
2489 alcSetError(device, ALC_INVALID_ENUM);
2490 return 0;
2492 return 0;
2495 /* render device */
2496 switch(param)
2498 case ALC_MAJOR_VERSION:
2499 values[0] = alcMajorVersion;
2500 return 1;
2502 case ALC_MINOR_VERSION:
2503 values[0] = alcMinorVersion;
2504 return 1;
2506 case ALC_EFX_MAJOR_VERSION:
2507 values[0] = alcEFXMajorVersion;
2508 return 1;
2510 case ALC_EFX_MINOR_VERSION:
2511 values[0] = alcEFXMinorVersion;
2512 return 1;
2514 case ALC_ATTRIBUTES_SIZE:
2515 values[0] = 15;
2516 return 1;
2518 case ALC_ALL_ATTRIBUTES:
2519 if(size < 15)
2521 alcSetError(device, ALC_INVALID_VALUE);
2522 return 0;
2525 i = 0;
2526 values[i++] = ALC_FREQUENCY;
2527 values[i++] = device->Frequency;
2529 if(device->Type != Loopback)
2531 values[i++] = ALC_REFRESH;
2532 values[i++] = device->Frequency / device->UpdateSize;
2534 values[i++] = ALC_SYNC;
2535 values[i++] = ALC_FALSE;
2537 else
2539 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2540 values[i++] = device->FmtChans;
2542 values[i++] = ALC_FORMAT_TYPE_SOFT;
2543 values[i++] = device->FmtType;
2546 values[i++] = ALC_MONO_SOURCES;
2547 values[i++] = device->NumMonoSources;
2549 values[i++] = ALC_STEREO_SOURCES;
2550 values[i++] = device->NumStereoSources;
2552 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2553 values[i++] = device->NumAuxSends;
2555 values[i++] = ALC_HRTF_SOFT;
2556 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2558 values[i++] = 0;
2559 return i;
2561 case ALC_FREQUENCY:
2562 values[0] = device->Frequency;
2563 return 1;
2565 case ALC_REFRESH:
2566 if(device->Type == Loopback)
2568 alcSetError(device, ALC_INVALID_DEVICE);
2569 return 0;
2571 values[0] = device->Frequency / device->UpdateSize;
2572 return 1;
2574 case ALC_SYNC:
2575 if(device->Type == Loopback)
2577 alcSetError(device, ALC_INVALID_DEVICE);
2578 return 0;
2580 values[0] = ALC_FALSE;
2581 return 1;
2583 case ALC_FORMAT_CHANNELS_SOFT:
2584 if(device->Type != Loopback)
2586 alcSetError(device, ALC_INVALID_DEVICE);
2587 return 0;
2589 values[0] = device->FmtChans;
2590 return 1;
2592 case ALC_FORMAT_TYPE_SOFT:
2593 if(device->Type != Loopback)
2595 alcSetError(device, ALC_INVALID_DEVICE);
2596 return 0;
2598 values[0] = device->FmtType;
2599 return 1;
2601 case ALC_MONO_SOURCES:
2602 values[0] = device->NumMonoSources;
2603 return 1;
2605 case ALC_STEREO_SOURCES:
2606 values[0] = device->NumStereoSources;
2607 return 1;
2609 case ALC_MAX_AUXILIARY_SENDS:
2610 values[0] = device->NumAuxSends;
2611 return 1;
2613 case ALC_CONNECTED:
2614 values[0] = device->Connected;
2615 return 1;
2617 case ALC_HRTF_SOFT:
2618 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2619 return 1;
2621 default:
2622 alcSetError(device, ALC_INVALID_ENUM);
2623 return 0;
2625 return 0;
2628 /* alcGetIntegerv
2630 * Returns information about the device and the version of OpenAL
2632 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2634 device = VerifyDevice(device);
2635 if(size <= 0 || values == NULL)
2636 alcSetError(device, ALC_INVALID_VALUE);
2637 else
2638 GetIntegerv(device, param, size, values);
2639 if(device) ALCdevice_DecRef(device);
2642 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2644 ALCint *ivals;
2645 ALsizei i;
2647 device = VerifyDevice(device);
2648 if(size <= 0 || values == NULL)
2649 alcSetError(device, ALC_INVALID_VALUE);
2650 else if(!device || device->Type == Capture)
2652 ivals = malloc(size * sizeof(ALCint));
2653 size = GetIntegerv(device, pname, size, ivals);
2654 for(i = 0;i < size;i++)
2655 values[i] = ivals[i];
2656 free(ivals);
2658 else /* render device */
2660 switch(pname)
2662 case ALC_ATTRIBUTES_SIZE:
2663 *values = 17;
2664 break;
2666 case ALC_ALL_ATTRIBUTES:
2667 if(size < 17)
2668 alcSetError(device, ALC_INVALID_VALUE);
2669 else
2671 int i = 0;
2673 V0(device->Backend,lock)();
2674 values[i++] = ALC_FREQUENCY;
2675 values[i++] = device->Frequency;
2677 if(device->Type != Loopback)
2679 values[i++] = ALC_REFRESH;
2680 values[i++] = device->Frequency / device->UpdateSize;
2682 values[i++] = ALC_SYNC;
2683 values[i++] = ALC_FALSE;
2685 else
2687 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2688 values[i++] = device->FmtChans;
2690 values[i++] = ALC_FORMAT_TYPE_SOFT;
2691 values[i++] = device->FmtType;
2694 values[i++] = ALC_MONO_SOURCES;
2695 values[i++] = device->NumMonoSources;
2697 values[i++] = ALC_STEREO_SOURCES;
2698 values[i++] = device->NumStereoSources;
2700 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2701 values[i++] = device->NumAuxSends;
2703 values[i++] = ALC_HRTF_SOFT;
2704 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2706 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2707 values[i++] = device->ClockBase +
2708 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2710 values[i++] = 0;
2711 V0(device->Backend,unlock)();
2713 break;
2715 case ALC_DEVICE_CLOCK_SOFT:
2716 V0(device->Backend,lock)();
2717 *values = device->ClockBase +
2718 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2719 V0(device->Backend,unlock)();
2720 break;
2722 default:
2723 ivals = malloc(size * sizeof(ALCint));
2724 size = GetIntegerv(device, pname, size, ivals);
2725 for(i = 0;i < size;i++)
2726 values[i] = ivals[i];
2727 free(ivals);
2728 break;
2731 if(device)
2732 ALCdevice_DecRef(device);
2736 /* alcIsExtensionPresent
2738 * Determines if there is support for a particular extension
2740 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2742 ALCboolean bResult = ALC_FALSE;
2744 device = VerifyDevice(device);
2746 if(!extName)
2747 alcSetError(device, ALC_INVALID_VALUE);
2748 else
2750 size_t len = strlen(extName);
2751 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2752 while(ptr && *ptr)
2754 if(strncasecmp(ptr, extName, len) == 0 &&
2755 (ptr[len] == '\0' || isspace(ptr[len])))
2757 bResult = ALC_TRUE;
2758 break;
2760 if((ptr=strchr(ptr, ' ')) != NULL)
2762 do {
2763 ++ptr;
2764 } while(isspace(*ptr));
2768 if(device)
2769 ALCdevice_DecRef(device);
2770 return bResult;
2774 /* alcGetProcAddress
2776 * Retrieves the function address for a particular extension function
2778 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2780 ALCvoid *ptr = NULL;
2782 if(!funcName)
2784 device = VerifyDevice(device);
2785 alcSetError(device, ALC_INVALID_VALUE);
2786 if(device) ALCdevice_DecRef(device);
2788 else
2790 ALsizei i = 0;
2791 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2792 i++;
2793 ptr = alcFunctions[i].address;
2796 return ptr;
2800 /* alcGetEnumValue
2802 * Get the value for a particular ALC enumeration name
2804 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2806 ALCenum val = 0;
2808 if(!enumName)
2810 device = VerifyDevice(device);
2811 alcSetError(device, ALC_INVALID_VALUE);
2812 if(device) ALCdevice_DecRef(device);
2814 else
2816 ALsizei i = 0;
2817 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2818 i++;
2819 val = enumeration[i].value;
2822 return val;
2826 /* alcCreateContext
2828 * Create and attach a context to the given device.
2830 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2832 ALCcontext *ALContext;
2833 ALCenum err;
2835 LockLists();
2836 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2838 UnlockLists();
2839 alcSetError(device, ALC_INVALID_DEVICE);
2840 if(device) ALCdevice_DecRef(device);
2841 return NULL;
2844 device->LastError = ALC_NO_ERROR;
2846 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2848 UnlockLists();
2849 alcSetError(device, err);
2850 if(err == ALC_INVALID_DEVICE)
2852 ALCdevice_Lock(device);
2853 aluHandleDisconnect(device);
2854 ALCdevice_Unlock(device);
2856 ALCdevice_DecRef(device);
2857 return NULL;
2860 ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener));
2861 if(ALContext)
2863 InitRef(&ALContext->ref, 1);
2864 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2866 VECTOR_INIT(ALContext->ActiveAuxSlots);
2868 ALContext->MaxActiveSources = 256;
2869 ALContext->ActiveSources = calloc(ALContext->MaxActiveSources,
2870 sizeof(ALContext->ActiveSources[0]));
2872 if(!ALContext || !ALContext->ActiveSources)
2874 if(!device->ContextList)
2876 V0(device->Backend,stop)();
2877 device->Flags &= ~DEVICE_RUNNING;
2879 UnlockLists();
2881 if(ALContext)
2883 free(ALContext->ActiveSources);
2884 ALContext->ActiveSources = NULL;
2886 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2888 free(ALContext);
2889 ALContext = NULL;
2892 alcSetError(device, ALC_OUT_OF_MEMORY);
2893 ALCdevice_DecRef(device);
2894 return NULL;
2897 ALContext->Device = device;
2898 ALCdevice_IncRef(device);
2899 InitContext(ALContext);
2901 do {
2902 ALContext->next = device->ContextList;
2903 } while(CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext) != ALContext->next);
2904 UnlockLists();
2906 ALCdevice_DecRef(device);
2908 TRACE("Created context %p\n", ALContext);
2909 return ALContext;
2912 /* alcDestroyContext
2914 * Remove a context from its device
2916 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2918 ALCdevice *Device;
2920 LockLists();
2921 /* alcGetContextsDevice sets an error for invalid contexts */
2922 Device = alcGetContextsDevice(context);
2923 if(Device)
2925 ReleaseContext(context, Device);
2926 if(!Device->ContextList)
2928 V0(Device->Backend,stop)();
2929 Device->Flags &= ~DEVICE_RUNNING;
2932 UnlockLists();
2936 /* alcGetCurrentContext
2938 * Returns the currently active context on the calling thread
2940 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2942 ALCcontext *Context;
2944 Context = altss_get(LocalContext);
2945 if(!Context) Context = GlobalContext;
2947 return Context;
2950 /* alcGetThreadContext
2952 * Returns the currently active thread-local context
2954 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2956 ALCcontext *Context;
2957 Context = altss_get(LocalContext);
2958 return Context;
2962 /* alcMakeContextCurrent
2964 * Makes the given context the active process-wide context, and removes the
2965 * thread-local context for the calling thread.
2967 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2969 /* context must be valid or NULL */
2970 if(context && !(context=VerifyContext(context)))
2972 alcSetError(NULL, ALC_INVALID_CONTEXT);
2973 return ALC_FALSE;
2975 /* context's reference count is already incremented */
2976 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2977 if(context) ALCcontext_DecRef(context);
2979 if((context=altss_get(LocalContext)) != NULL)
2981 altss_set(LocalContext, NULL);
2982 ALCcontext_DecRef(context);
2985 return ALC_TRUE;
2988 /* alcSetThreadContext
2990 * Makes the given context the active context for the current thread
2992 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2994 ALCcontext *old;
2996 /* context must be valid or NULL */
2997 if(context && !(context=VerifyContext(context)))
2999 alcSetError(NULL, ALC_INVALID_CONTEXT);
3000 return ALC_FALSE;
3002 /* context's reference count is already incremented */
3003 old = altss_get(LocalContext);
3004 altss_set(LocalContext, context);
3005 if(old) ALCcontext_DecRef(old);
3007 return ALC_TRUE;
3011 /* alcGetContextsDevice
3013 * Returns the device that a particular context is attached to
3015 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3017 ALCdevice *Device;
3019 if(!(Context=VerifyContext(Context)))
3021 alcSetError(NULL, ALC_INVALID_CONTEXT);
3022 return NULL;
3024 Device = Context->Device;
3025 ALCcontext_DecRef(Context);
3027 return Device;
3031 /* alcOpenDevice
3033 * Opens the named device.
3035 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3037 const ALCchar *fmt;
3038 ALCdevice *device;
3039 ALCenum err;
3041 DO_INITCONFIG();
3043 if(!PlaybackBackend.name)
3045 alcSetError(NULL, ALC_INVALID_VALUE);
3046 return NULL;
3049 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3050 deviceName = NULL;
3052 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3053 if(!device)
3055 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3056 return NULL;
3059 //Validate device
3060 InitRef(&device->ref, 1);
3061 device->Connected = ALC_TRUE;
3062 device->Type = Playback;
3063 device->LastError = ALC_NO_ERROR;
3065 device->Flags = 0;
3066 device->Bs2b = NULL;
3067 device->Bs2bLevel = 0;
3068 AL_STRING_INIT(device->DeviceName);
3070 device->ContextList = NULL;
3072 device->ClockBase = 0;
3073 device->SamplesDone = 0;
3075 device->MaxNoOfSources = 256;
3076 device->AuxiliaryEffectSlotMax = 4;
3077 device->NumAuxSends = MAX_SENDS;
3079 InitUIntMap(&device->BufferMap, ~0);
3080 InitUIntMap(&device->EffectMap, ~0);
3081 InitUIntMap(&device->FilterMap, ~0);
3082 InitUIntMap(&device->SfontMap, ~0);
3083 InitUIntMap(&device->PresetMap, ~0);
3084 InitUIntMap(&device->FontsoundMap, ~0);
3086 //Set output format
3087 device->FmtChans = DevFmtChannelsDefault;
3088 device->FmtType = DevFmtTypeDefault;
3089 device->Frequency = DEFAULT_OUTPUT_RATE;
3090 device->NumUpdates = 4;
3091 device->UpdateSize = 1024;
3093 if(!PlaybackBackend.getFactory)
3094 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3095 ALCbackend_Playback);
3096 else
3098 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3099 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3101 if(!device->Backend)
3103 al_free(device);
3104 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3105 return NULL;
3109 if(ConfigValueStr(NULL, "channels", &fmt))
3111 static const struct {
3112 const char name[16];
3113 enum DevFmtChannels chans;
3114 } chanlist[] = {
3115 { "mono", DevFmtMono },
3116 { "stereo", DevFmtStereo },
3117 { "quad", DevFmtQuad },
3118 { "surround51", DevFmtX51 },
3119 { "surround61", DevFmtX61 },
3120 { "surround71", DevFmtX71 },
3122 size_t i;
3124 for(i = 0;i < COUNTOF(chanlist);i++)
3126 if(strcasecmp(chanlist[i].name, fmt) == 0)
3128 device->FmtChans = chanlist[i].chans;
3129 device->Flags |= DEVICE_CHANNELS_REQUEST;
3130 break;
3133 if(i == COUNTOF(chanlist))
3134 ERR("Unsupported channels: %s\n", fmt);
3136 if(ConfigValueStr(NULL, "sample-type", &fmt))
3138 static const struct {
3139 const char name[16];
3140 enum DevFmtType type;
3141 } typelist[] = {
3142 { "int8", DevFmtByte },
3143 { "uint8", DevFmtUByte },
3144 { "int16", DevFmtShort },
3145 { "uint16", DevFmtUShort },
3146 { "int32", DevFmtInt },
3147 { "uint32", DevFmtUInt },
3148 { "float32", DevFmtFloat },
3150 size_t i;
3152 for(i = 0;i < COUNTOF(typelist);i++)
3154 if(strcasecmp(typelist[i].name, fmt) == 0)
3156 device->FmtType = typelist[i].type;
3157 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3158 break;
3161 if(i == COUNTOF(typelist))
3162 ERR("Unsupported sample-type: %s\n", fmt);
3164 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3165 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3166 ConfigValueStr(NULL, "format", &fmt))
3168 static const struct {
3169 const char name[32];
3170 enum DevFmtChannels channels;
3171 enum DevFmtType type;
3172 } formats[] = {
3173 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3174 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3175 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3176 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3177 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3178 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3180 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3181 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3182 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3183 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3184 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3185 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3187 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3188 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3189 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3190 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3191 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3192 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3194 size_t i;
3196 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3197 for(i = 0;i < COUNTOF(formats);i++)
3199 if(strcasecmp(fmt, formats[i].name) == 0)
3201 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3202 device->FmtChans = formats[i].channels;
3203 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3204 device->FmtType = formats[i].type;
3205 device->Flags |= DEVICE_FORMAT_REQUEST;
3206 break;
3209 if(i == COUNTOF(formats))
3210 ERR("Unsupported format: %s\n", fmt);
3212 #undef DEVICE_FORMAT_REQUEST
3214 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3216 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3217 if(device->Frequency < MIN_OUTPUT_RATE)
3218 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3219 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3222 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3223 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3225 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3226 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3227 if((CPUCapFlags&CPU_CAP_SSE))
3228 device->UpdateSize = (device->UpdateSize+3)&~3;
3230 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3231 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3233 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3234 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3236 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3237 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3239 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3241 device->NumStereoSources = 1;
3242 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3244 device->Synth = SynthCreate(device);
3245 if(!device->Synth)
3247 DELETE_OBJ(device->Backend);
3248 al_free(device);
3249 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3250 return NULL;
3253 // Find a playback device to open
3254 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3256 DELETE_OBJ(device->Synth);
3257 DELETE_OBJ(device->Backend);
3258 al_free(device);
3259 alcSetError(NULL, err);
3260 return NULL;
3263 if(DefaultEffect.type != AL_EFFECT_NULL)
3265 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3266 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3268 device->DefaultSlot = NULL;
3269 ERR("Failed to initialize the default effect slot\n");
3271 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3273 ALeffectState *state = device->DefaultSlot->EffectState;
3274 device->DefaultSlot = NULL;
3275 DELETE_OBJ(state);
3276 ERR("Failed to initialize the default effect\n");
3280 do {
3281 device->next = DeviceList;
3282 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3284 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3285 return device;
3288 /* alcCloseDevice
3290 * Closes the given device.
3292 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
3294 ALCdevice *volatile*list;
3295 ALCcontext *ctx;
3297 LockLists();
3298 list = &DeviceList;
3299 while(*list && *list != Device)
3300 list = &(*list)->next;
3302 if(!*list || (*list)->Type == Capture)
3304 alcSetError(*list, ALC_INVALID_DEVICE);
3305 UnlockLists();
3306 return ALC_FALSE;
3309 *list = (*list)->next;
3310 UnlockLists();
3312 while((ctx=Device->ContextList) != NULL)
3314 WARN("Releasing context %p\n", ctx);
3315 ReleaseContext(ctx, Device);
3317 if((Device->Flags&DEVICE_RUNNING))
3318 V0(Device->Backend,stop)();
3319 Device->Flags &= ~DEVICE_RUNNING;
3321 ALCdevice_DecRef(Device);
3323 return ALC_TRUE;
3327 /************************************************
3328 * ALC capture functions
3329 ************************************************/
3330 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3332 ALCdevice *device = NULL;
3333 ALCenum err;
3335 DO_INITCONFIG();
3337 if(!CaptureBackend.name)
3339 alcSetError(NULL, ALC_INVALID_VALUE);
3340 return NULL;
3343 if(samples <= 0)
3345 alcSetError(NULL, ALC_INVALID_VALUE);
3346 return NULL;
3349 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3350 deviceName = NULL;
3352 device = al_calloc(16, sizeof(ALCdevice));
3353 if(!device)
3355 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3356 return NULL;
3359 //Validate device
3360 InitRef(&device->ref, 1);
3361 device->Connected = ALC_TRUE;
3362 device->Type = Capture;
3364 AL_STRING_INIT(device->DeviceName);
3366 InitUIntMap(&device->BufferMap, ~0);
3367 InitUIntMap(&device->EffectMap, ~0);
3368 InitUIntMap(&device->FilterMap, ~0);
3369 InitUIntMap(&device->SfontMap, ~0);
3370 InitUIntMap(&device->PresetMap, ~0);
3371 InitUIntMap(&device->FontsoundMap, ~0);
3373 if(!CaptureBackend.getFactory)
3374 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3375 ALCbackend_Capture);
3376 else
3378 ALCbackendFactory *factory = CaptureBackend.getFactory();
3379 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3381 if(!device->Backend)
3383 al_free(device);
3384 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3385 return NULL;
3388 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3389 device->Frequency = frequency;
3391 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3392 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3394 al_free(device);
3395 alcSetError(NULL, ALC_INVALID_ENUM);
3396 return NULL;
3399 device->UpdateSize = samples;
3400 device->NumUpdates = 1;
3402 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3404 al_free(device);
3405 alcSetError(NULL, err);
3406 return NULL;
3409 do {
3410 device->next = DeviceList;
3411 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3413 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3414 return device;
3417 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
3419 ALCdevice *volatile*list;
3421 LockLists();
3422 list = &DeviceList;
3423 while(*list && *list != Device)
3424 list = &(*list)->next;
3426 if(!*list || (*list)->Type != Capture)
3428 alcSetError(*list, ALC_INVALID_DEVICE);
3429 UnlockLists();
3430 return ALC_FALSE;
3433 *list = (*list)->next;
3434 UnlockLists();
3436 ALCdevice_DecRef(Device);
3438 return ALC_TRUE;
3441 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3443 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3444 alcSetError(device, ALC_INVALID_DEVICE);
3445 else
3447 ALCdevice_Lock(device);
3448 if(device->Connected)
3450 if(!(device->Flags&DEVICE_RUNNING))
3451 V0(device->Backend,start)();
3452 device->Flags |= DEVICE_RUNNING;
3454 ALCdevice_Unlock(device);
3457 if(device) ALCdevice_DecRef(device);
3460 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3462 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3463 alcSetError(device, ALC_INVALID_DEVICE);
3464 else
3466 ALCdevice_Lock(device);
3467 if((device->Flags&DEVICE_RUNNING))
3468 V0(device->Backend,stop)();
3469 device->Flags &= ~DEVICE_RUNNING;
3470 ALCdevice_Unlock(device);
3473 if(device) ALCdevice_DecRef(device);
3476 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3478 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3479 alcSetError(device, ALC_INVALID_DEVICE);
3480 else
3482 ALCenum err = ALC_INVALID_VALUE;
3484 ALCdevice_Lock(device);
3485 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3486 err = V(device->Backend,captureSamples)(buffer, samples);
3487 ALCdevice_Unlock(device);
3489 if(err != ALC_NO_ERROR)
3490 alcSetError(device, err);
3492 if(device) ALCdevice_DecRef(device);
3496 /************************************************
3497 * ALC loopback functions
3498 ************************************************/
3500 /* alcLoopbackOpenDeviceSOFT
3502 * Open a loopback device, for manual rendering.
3504 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3506 ALCbackendFactory *factory;
3507 ALCdevice *device;
3509 DO_INITCONFIG();
3511 /* Make sure the device name, if specified, is us. */
3512 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3514 alcSetError(NULL, ALC_INVALID_VALUE);
3515 return NULL;
3518 device = al_calloc(16, sizeof(ALCdevice));
3519 if(!device)
3521 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3522 return NULL;
3525 //Validate device
3526 InitRef(&device->ref, 1);
3527 device->Connected = ALC_TRUE;
3528 device->Type = Loopback;
3529 device->LastError = ALC_NO_ERROR;
3531 device->Flags = 0;
3532 device->Bs2b = NULL;
3533 device->Bs2bLevel = 0;
3534 AL_STRING_INIT(device->DeviceName);
3536 device->ContextList = NULL;
3538 device->ClockBase = 0;
3539 device->SamplesDone = 0;
3541 device->MaxNoOfSources = 256;
3542 device->AuxiliaryEffectSlotMax = 4;
3543 device->NumAuxSends = MAX_SENDS;
3545 InitUIntMap(&device->BufferMap, ~0);
3546 InitUIntMap(&device->EffectMap, ~0);
3547 InitUIntMap(&device->FilterMap, ~0);
3548 InitUIntMap(&device->SfontMap, ~0);
3549 InitUIntMap(&device->PresetMap, ~0);
3550 InitUIntMap(&device->FontsoundMap, ~0);
3552 factory = ALCloopbackFactory_getFactory();
3553 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3554 if(!device->Backend)
3556 al_free(device);
3557 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3558 return NULL;
3561 //Set output format
3562 device->NumUpdates = 0;
3563 device->UpdateSize = 0;
3565 device->Frequency = DEFAULT_OUTPUT_RATE;
3566 device->FmtChans = DevFmtChannelsDefault;
3567 device->FmtType = DevFmtTypeDefault;
3569 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3570 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3572 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3573 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3575 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3576 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3578 device->NumStereoSources = 1;
3579 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3581 device->Synth = SynthCreate(device);
3582 if(!device->Synth)
3584 DELETE_OBJ(device->Backend);
3585 al_free(device);
3586 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3587 return NULL;
3590 // Open the "backend"
3591 V(device->Backend,open)("Loopback");
3592 do {
3593 device->next = DeviceList;
3594 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3596 TRACE("Created device %p\n", device);
3597 return device;
3600 /* alcIsRenderFormatSupportedSOFT
3602 * Determines if the loopback device supports the given format for rendering.
3604 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3606 ALCboolean ret = ALC_FALSE;
3608 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3609 alcSetError(device, ALC_INVALID_DEVICE);
3610 else if(freq <= 0)
3611 alcSetError(device, ALC_INVALID_VALUE);
3612 else
3614 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3615 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3616 freq >= MIN_OUTPUT_RATE)
3617 ret = ALC_TRUE;
3619 if(device) ALCdevice_DecRef(device);
3621 return ret;
3624 /* alcRenderSamplesSOFT
3626 * Renders some samples into a buffer, using the format last set by the
3627 * attributes given to alcCreateContext.
3629 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3631 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3632 alcSetError(device, ALC_INVALID_DEVICE);
3633 else if(samples < 0 || (samples > 0 && buffer == NULL))
3634 alcSetError(device, ALC_INVALID_VALUE);
3635 else
3636 aluMixData(device, buffer, samples);
3637 if(device) ALCdevice_DecRef(device);
3641 /************************************************
3642 * ALC DSP pause/resume functions
3643 ************************************************/
3645 /* alcDevicePauseSOFT
3647 * Pause the DSP to stop audio processing.
3649 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3651 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3652 alcSetError(device, ALC_INVALID_DEVICE);
3653 else
3655 LockLists();
3656 if((device->Flags&DEVICE_RUNNING))
3657 V0(device->Backend,stop)();
3658 device->Flags &= ~DEVICE_RUNNING;
3659 device->Flags |= DEVICE_PAUSED;
3660 UnlockLists();
3662 if(device) ALCdevice_DecRef(device);
3665 /* alcDeviceResumeSOFT
3667 * Resume the DSP to restart audio processing.
3669 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3671 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3672 alcSetError(device, ALC_INVALID_DEVICE);
3673 else
3675 LockLists();
3676 if((device->Flags&DEVICE_PAUSED))
3678 if(V0(device->Backend,start)() != ALC_FALSE)
3680 device->Flags |= DEVICE_RUNNING;
3681 device->Flags &= ~DEVICE_PAUSED;
3683 else
3685 alcSetError(device, ALC_INVALID_DEVICE);
3686 ALCdevice_Lock(device);
3687 aluHandleDisconnect(device);
3688 ALCdevice_Unlock(device);
3691 UnlockLists();
3693 if(device) ALCdevice_DecRef(device);