Add an extension string for the in-progress source length extension
[openal-soft.git] / Alc / ALc.c
blob3b3e539737d90541f7a673d850d95b247898f8a9
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_SOFT_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 "
723 "AL_SOFTX_source_length";
725 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
727 /* Thread-local current context */
728 static altss_t LocalContext;
729 /* Process-wide current context */
730 static ALCcontext *volatile GlobalContext = NULL;
732 /* Mixing thread piority level */
733 ALint RTPrioLevel;
735 FILE *LogFile;
736 #ifdef _DEBUG
737 enum LogLevel LogLevel = LogWarning;
738 #else
739 enum LogLevel LogLevel = LogError;
740 #endif
742 /* Flag to trap ALC device errors */
743 static ALCboolean TrapALCError = ALC_FALSE;
745 /* One-time configuration init control */
746 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
748 /* Default effect that applies to sources that don't have an effect on send 0 */
749 static ALeffect DefaultEffect;
752 /************************************************
753 * ALC information
754 ************************************************/
755 static const ALCchar alcNoDeviceExtList[] =
756 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
757 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
758 static const ALCchar alcExtensionList[] =
759 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
760 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
761 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
762 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
763 static const ALCint alcMajorVersion = 1;
764 static const ALCint alcMinorVersion = 1;
766 static const ALCint alcEFXMajorVersion = 1;
767 static const ALCint alcEFXMinorVersion = 0;
770 /************************************************
771 * Device lists
772 ************************************************/
773 static ALCdevice *volatile DeviceList = NULL;
775 static almtx_t ListLock;
776 static inline void LockLists(void)
778 int lockret = almtx_lock(&ListLock);
779 assert(lockret == althrd_success);
781 static inline void UnlockLists(void)
783 int unlockret = almtx_unlock(&ListLock);
784 assert(unlockret == althrd_success);
787 /************************************************
788 * Library initialization
789 ************************************************/
790 #if defined(_WIN32)
791 static void alc_init(void);
792 static void alc_deinit(void);
793 static void alc_deinit_safe(void);
795 #ifndef AL_LIBTYPE_STATIC
796 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
798 switch(reason)
800 case DLL_PROCESS_ATTACH:
801 /* Pin the DLL so we won't get unloaded until the process terminates */
802 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 (WCHAR*)hModule, &hModule);
804 alc_init();
805 break;
807 case DLL_THREAD_DETACH:
808 break;
810 case DLL_PROCESS_DETACH:
811 if(!lpReserved)
812 alc_deinit();
813 else
814 alc_deinit_safe();
815 break;
817 return TRUE;
819 #elif defined(_MSC_VER)
820 #pragma section(".CRT$XCU",read)
821 static void alc_constructor(void);
822 static void alc_destructor(void);
823 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
825 static void alc_constructor(void)
827 atexit(alc_destructor);
828 alc_init();
831 static void alc_destructor(void)
833 alc_deinit();
835 #elif defined(HAVE_GCC_DESTRUCTOR)
836 static void alc_init(void) __attribute__((constructor));
837 static void alc_deinit(void) __attribute__((destructor));
838 #else
839 #error "No static initialization available on this platform!"
840 #endif
842 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No global initialization available on this platform!"
849 #endif
851 static void ReleaseThreadCtx(void *ptr);
852 static void alc_init(void)
854 const char *str;
855 int ret;
857 LogFile = stderr;
859 AL_STRING_INIT(alcAllDevicesList);
860 AL_STRING_INIT(alcCaptureDeviceList);
862 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ConeScale *= 0.5f;
866 str = getenv("__ALSOFT_REVERSE_Z");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 ZScale *= -1.0f;
870 ret = altss_create(&LocalContext, ReleaseThreadCtx);
871 assert(ret == althrd_success);
873 ret = almtx_init(&ListLock, almtx_recursive);
874 assert(ret == althrd_success);
876 ThunkInit();
879 static void alc_initconfig(void)
881 const char *devs, *str;
882 ALuint capfilter;
883 float valf;
884 int i, n;
886 str = getenv("ALSOFT_LOGLEVEL");
887 if(str)
889 long lvl = strtol(str, NULL, 0);
890 if(lvl >= NoLog && lvl <= LogRef)
891 LogLevel = lvl;
894 str = getenv("ALSOFT_LOGFILE");
895 if(str && str[0])
897 FILE *logfile = al_fopen(str, "wt");
898 if(logfile) LogFile = logfile;
899 else ERR("Failed to open log file '%s'\n", str);
903 char buf[1024] = "";
904 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
905 for(i = 1;BackendList[i].name;i++)
906 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
907 TRACE("Supported backends: %s\n", buf);
909 ReadALConfig();
911 capfilter = 0;
912 #ifdef HAVE_SSE
913 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
914 #endif
915 #ifdef HAVE_NEON
916 capfilter |= CPU_CAP_NEON;
917 #endif
918 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
920 if(strcasecmp(str, "all") == 0)
921 capfilter = 0;
922 else
924 size_t len;
925 const char *next = str;
927 do {
928 str = next;
929 while(isspace(str[0]))
930 str++;
931 next = strchr(str, ',');
933 if(!str[0] || str[0] == ',')
934 continue;
936 len = (next ? ((size_t)(next-str)) : strlen(str));
937 while(len > 0 && isspace(str[len-1]))
938 len--;
939 if(len == 3 && strncasecmp(str, "sse", len) == 0)
940 capfilter &= ~CPU_CAP_SSE;
941 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
942 capfilter &= ~CPU_CAP_SSE2;
943 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
944 capfilter &= ~CPU_CAP_NEON;
945 else
946 WARN("Invalid CPU extension \"%s\"\n", str);
947 } while(next++);
950 FillCPUCaps(capfilter);
952 #ifdef _WIN32
953 RTPrioLevel = 1;
954 #else
955 RTPrioLevel = 0;
956 #endif
957 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
959 if(ConfigValueStr(NULL, "resampler", &str))
961 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
962 DefaultResampler = PointResampler;
963 else if(strcasecmp(str, "linear") == 0)
964 DefaultResampler = LinearResampler;
965 else if(strcasecmp(str, "cubic") == 0)
966 DefaultResampler = CubicResampler;
967 else
969 char *end;
971 n = strtol(str, &end, 0);
972 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
973 DefaultResampler = n;
974 else
975 WARN("Invalid resampler: %s\n", str);
979 str = getenv("ALSOFT_TRAP_ERROR");
980 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
982 TrapALError = AL_TRUE;
983 TrapALCError = AL_TRUE;
985 else
987 str = getenv("ALSOFT_TRAP_AL_ERROR");
988 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
989 TrapALError = AL_TRUE;
990 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
992 str = getenv("ALSOFT_TRAP_ALC_ERROR");
993 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
994 TrapALCError = ALC_TRUE;
995 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
998 if(ConfigValueFloat("reverb", "boost", &valf))
999 ReverbBoost *= powf(10.0f, valf / 20.0f);
1001 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1003 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1004 ConfigValueStr(NULL, "drivers", &devs))
1006 int n;
1007 size_t len;
1008 const char *next = devs;
1009 int endlist, delitem;
1011 i = 0;
1012 do {
1013 devs = next;
1014 while(isspace(devs[0]))
1015 devs++;
1016 next = strchr(devs, ',');
1018 delitem = (devs[0] == '-');
1019 if(devs[0] == '-') devs++;
1021 if(!devs[0] || devs[0] == ',')
1023 endlist = 0;
1024 continue;
1026 endlist = 1;
1028 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1029 while(len > 0 && isspace(devs[len-1]))
1030 len--;
1031 for(n = i;BackendList[n].name;n++)
1033 if(len == strlen(BackendList[n].name) &&
1034 strncmp(BackendList[n].name, devs, len) == 0)
1036 if(delitem)
1038 do {
1039 BackendList[n] = BackendList[n+1];
1040 ++n;
1041 } while(BackendList[n].name);
1043 else
1045 struct BackendInfo Bkp = BackendList[n];
1046 while(n > i)
1048 BackendList[n] = BackendList[n-1];
1049 --n;
1051 BackendList[n] = Bkp;
1053 i++;
1055 break;
1058 } while(next++);
1060 if(endlist)
1062 BackendList[i].name = NULL;
1063 BackendList[i].getFactory = NULL;
1064 BackendList[i].Init = NULL;
1065 BackendList[i].Deinit = NULL;
1066 BackendList[i].Probe = NULL;
1070 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1072 if(BackendList[i].getFactory)
1074 ALCbackendFactory *factory = BackendList[i].getFactory();
1075 if(!V0(factory,init)())
1077 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1078 continue;
1081 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1082 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1084 PlaybackBackend = BackendList[i];
1085 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1087 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1089 CaptureBackend = BackendList[i];
1090 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1093 continue;
1096 if(!BackendList[i].Init(&BackendList[i].Funcs))
1098 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1099 continue;
1102 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1103 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1105 PlaybackBackend = BackendList[i];
1106 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1108 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1110 CaptureBackend = BackendList[i];
1111 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1115 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1116 V0(factory,init)();
1119 if(ConfigValueStr(NULL, "excludefx", &str))
1121 size_t len;
1122 const char *next = str;
1124 do {
1125 str = next;
1126 next = strchr(str, ',');
1128 if(!str[0] || next == str)
1129 continue;
1131 len = (next ? ((size_t)(next-str)) : strlen(str));
1132 for(n = 0;EffectList[n].name;n++)
1134 if(len == strlen(EffectList[n].name) &&
1135 strncmp(EffectList[n].name, str, len) == 0)
1136 DisabledEffects[EffectList[n].type] = AL_TRUE;
1138 } while(next++);
1141 InitEffectFactoryMap();
1143 InitEffect(&DefaultEffect);
1144 str = getenv("ALSOFT_DEFAULT_REVERB");
1145 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1146 LoadReverbPreset(str, &DefaultEffect);
1148 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1151 /************************************************
1152 * Library deinitialization
1153 ************************************************/
1154 static void alc_cleanup(void)
1156 ALCdevice *dev;
1158 AL_STRING_DEINIT(alcAllDevicesList);
1159 AL_STRING_DEINIT(alcCaptureDeviceList);
1161 free(alcDefaultAllDevicesSpecifier);
1162 alcDefaultAllDevicesSpecifier = NULL;
1163 free(alcCaptureDefaultDeviceSpecifier);
1164 alcCaptureDefaultDeviceSpecifier = NULL;
1166 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1168 ALCuint num = 0;
1169 do {
1170 num++;
1171 } while((dev=dev->next) != NULL);
1172 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1175 DeinitEffectFactoryMap();
1178 static void alc_deinit_safe(void)
1180 alc_cleanup();
1182 FreeHrtfs();
1183 FreeALConfig();
1185 ThunkExit();
1186 almtx_destroy(&ListLock);
1187 altss_delete(LocalContext);
1189 if(LogFile != stderr)
1190 fclose(LogFile);
1191 LogFile = NULL;
1194 static void alc_deinit(void)
1196 int i;
1198 alc_cleanup();
1200 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1201 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1203 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1205 if(!BackendList[i].getFactory)
1206 BackendList[i].Deinit();
1207 else
1209 ALCbackendFactory *factory = BackendList[i].getFactory();
1210 V0(factory,deinit)();
1214 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1215 V0(factory,deinit)();
1218 alc_deinit_safe();
1222 /************************************************
1223 * Device enumeration
1224 ************************************************/
1225 static void ProbeDevices(al_string *list, enum DevProbe type)
1227 DO_INITCONFIG();
1229 LockLists();
1230 al_string_clear(list);
1232 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1234 if(!PlaybackBackend.getFactory)
1235 PlaybackBackend.Probe(type);
1236 else
1238 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1239 V(factory,probe)(type);
1242 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1244 if(!CaptureBackend.getFactory)
1245 CaptureBackend.Probe(type);
1246 else
1248 ALCbackendFactory *factory = CaptureBackend.getFactory();
1249 V(factory,probe)(type);
1252 UnlockLists();
1254 static void ProbeAllDevicesList(void)
1255 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1256 static void ProbeCaptureDeviceList(void)
1257 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1259 static void AppendDevice(const ALCchar *name, al_string *devnames)
1261 size_t len = strlen(name);
1262 if(len > 0)
1264 al_string_append_range(devnames, name, name+len);
1265 al_string_append_char(devnames, '\0');
1268 void AppendAllDevicesList(const ALCchar *name)
1269 { AppendDevice(name, &alcAllDevicesList); }
1270 void AppendCaptureDeviceList(const ALCchar *name)
1271 { AppendDevice(name, &alcCaptureDeviceList); }
1274 /************************************************
1275 * Device format information
1276 ************************************************/
1277 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1279 switch(type)
1281 case DevFmtByte: return "Signed Byte";
1282 case DevFmtUByte: return "Unsigned Byte";
1283 case DevFmtShort: return "Signed Short";
1284 case DevFmtUShort: return "Unsigned Short";
1285 case DevFmtInt: return "Signed Int";
1286 case DevFmtUInt: return "Unsigned Int";
1287 case DevFmtFloat: return "Float";
1289 return "(unknown type)";
1291 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1293 switch(chans)
1295 case DevFmtMono: return "Mono";
1296 case DevFmtStereo: return "Stereo";
1297 case DevFmtQuad: return "Quadraphonic";
1298 case DevFmtX51: return "5.1 Surround";
1299 case DevFmtX51Side: return "5.1 Side";
1300 case DevFmtX61: return "6.1 Surround";
1301 case DevFmtX71: return "7.1 Surround";
1303 return "(unknown channels)";
1306 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1307 ALuint BytesFromDevFmt(enum DevFmtType type)
1309 switch(type)
1311 case DevFmtByte: return sizeof(ALbyte);
1312 case DevFmtUByte: return sizeof(ALubyte);
1313 case DevFmtShort: return sizeof(ALshort);
1314 case DevFmtUShort: return sizeof(ALushort);
1315 case DevFmtInt: return sizeof(ALint);
1316 case DevFmtUInt: return sizeof(ALuint);
1317 case DevFmtFloat: return sizeof(ALfloat);
1319 return 0;
1321 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1323 switch(chans)
1325 case DevFmtMono: return 1;
1326 case DevFmtStereo: return 2;
1327 case DevFmtQuad: return 4;
1328 case DevFmtX51: return 6;
1329 case DevFmtX51Side: return 6;
1330 case DevFmtX61: return 7;
1331 case DevFmtX71: return 8;
1333 return 0;
1336 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1337 enum DevFmtChannels *chans, enum DevFmtType *type)
1339 static const struct {
1340 ALenum format;
1341 enum DevFmtChannels channels;
1342 enum DevFmtType type;
1343 } list[] = {
1344 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1345 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1346 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1348 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1349 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1350 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1352 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1353 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1354 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1356 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1357 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1358 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1360 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1361 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1362 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1364 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1365 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1366 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1368 ALuint i;
1370 for(i = 0;i < COUNTOF(list);i++)
1372 if(list[i].format == format)
1374 *chans = list[i].channels;
1375 *type = list[i].type;
1376 return AL_TRUE;
1380 return AL_FALSE;
1383 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1385 switch(type)
1387 case ALC_BYTE_SOFT:
1388 case ALC_UNSIGNED_BYTE_SOFT:
1389 case ALC_SHORT_SOFT:
1390 case ALC_UNSIGNED_SHORT_SOFT:
1391 case ALC_INT_SOFT:
1392 case ALC_UNSIGNED_INT_SOFT:
1393 case ALC_FLOAT_SOFT:
1394 return ALC_TRUE;
1396 return ALC_FALSE;
1399 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1401 switch(channels)
1403 case ALC_MONO_SOFT:
1404 case ALC_STEREO_SOFT:
1405 case ALC_QUAD_SOFT:
1406 case ALC_5POINT1_SOFT:
1407 case ALC_6POINT1_SOFT:
1408 case ALC_7POINT1_SOFT:
1409 return ALC_TRUE;
1411 return ALC_FALSE;
1415 /************************************************
1416 * Miscellaneous ALC helpers
1417 ************************************************/
1418 extern inline void LockContext(ALCcontext *context);
1419 extern inline void UnlockContext(ALCcontext *context);
1421 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *UNUSED(device))
1423 return 0;
1426 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1428 return V0(device->Backend,getLatency)();
1431 void ALCdevice_Lock(ALCdevice *device)
1433 V0(device->Backend,lock)();
1436 void ALCdevice_Unlock(ALCdevice *device)
1438 V0(device->Backend,unlock)();
1442 /* SetDefaultWFXChannelOrder
1444 * Sets the default channel order used by WaveFormatEx.
1446 void SetDefaultWFXChannelOrder(ALCdevice *device)
1448 ALuint i;
1450 for(i = 0;i < MaxChannels;i++)
1451 device->ChannelOffsets[i] = INVALID_OFFSET;
1453 switch(device->FmtChans)
1455 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1456 break;
1457 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1458 device->ChannelOffsets[FrontRight] = 1;
1459 break;
1460 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1461 device->ChannelOffsets[FrontRight] = 1;
1462 device->ChannelOffsets[BackLeft] = 2;
1463 device->ChannelOffsets[BackRight] = 3;
1464 break;
1465 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1466 device->ChannelOffsets[FrontRight] = 1;
1467 device->ChannelOffsets[FrontCenter] = 2;
1468 device->ChannelOffsets[LFE] = 3;
1469 device->ChannelOffsets[BackLeft] = 4;
1470 device->ChannelOffsets[BackRight] = 5;
1471 break;
1472 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1473 device->ChannelOffsets[FrontRight] = 1;
1474 device->ChannelOffsets[FrontCenter] = 2;
1475 device->ChannelOffsets[LFE] = 3;
1476 device->ChannelOffsets[SideLeft] = 4;
1477 device->ChannelOffsets[SideRight] = 5;
1478 break;
1479 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1480 device->ChannelOffsets[FrontRight] = 1;
1481 device->ChannelOffsets[FrontCenter] = 2;
1482 device->ChannelOffsets[LFE] = 3;
1483 device->ChannelOffsets[BackCenter] = 4;
1484 device->ChannelOffsets[SideLeft] = 5;
1485 device->ChannelOffsets[SideRight] = 6;
1486 break;
1487 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1488 device->ChannelOffsets[FrontRight] = 1;
1489 device->ChannelOffsets[FrontCenter] = 2;
1490 device->ChannelOffsets[LFE] = 3;
1491 device->ChannelOffsets[BackLeft] = 4;
1492 device->ChannelOffsets[BackRight] = 5;
1493 device->ChannelOffsets[SideLeft] = 6;
1494 device->ChannelOffsets[SideRight] = 7;
1495 break;
1499 /* SetDefaultChannelOrder
1501 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1503 void SetDefaultChannelOrder(ALCdevice *device)
1505 ALuint i;
1507 for(i = 0;i < MaxChannels;i++)
1508 device->ChannelOffsets[i] = INVALID_OFFSET;
1510 switch(device->FmtChans)
1512 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1513 device->ChannelOffsets[FrontRight] = 1;
1514 device->ChannelOffsets[BackLeft] = 2;
1515 device->ChannelOffsets[BackRight] = 3;
1516 device->ChannelOffsets[FrontCenter] = 4;
1517 device->ChannelOffsets[LFE] = 5;
1518 return;
1519 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1520 device->ChannelOffsets[FrontRight] = 1;
1521 device->ChannelOffsets[BackLeft] = 2;
1522 device->ChannelOffsets[BackRight] = 3;
1523 device->ChannelOffsets[FrontCenter] = 4;
1524 device->ChannelOffsets[LFE] = 5;
1525 device->ChannelOffsets[SideLeft] = 6;
1526 device->ChannelOffsets[SideRight] = 7;
1527 return;
1529 /* Same as WFX order */
1530 case DevFmtMono:
1531 case DevFmtStereo:
1532 case DevFmtQuad:
1533 case DevFmtX51Side:
1534 case DevFmtX61:
1535 break;
1537 SetDefaultWFXChannelOrder(device);
1541 /* alcSetError
1543 * Stores the latest ALC device error
1545 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1547 if(TrapALCError)
1549 #ifdef _WIN32
1550 /* DebugBreak() will cause an exception if there is no debugger */
1551 if(IsDebuggerPresent())
1552 DebugBreak();
1553 #elif defined(SIGTRAP)
1554 raise(SIGTRAP);
1555 #endif
1558 if(device)
1559 device->LastError = errorCode;
1560 else
1561 LastNullDeviceError = errorCode;
1565 /* UpdateClockBase
1567 * Updates the device's base clock time with however many samples have been
1568 * done. This is used so frequency changes on the device don't cause the time
1569 * to jump forward or back.
1571 static inline void UpdateClockBase(ALCdevice *device)
1573 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1574 device->SamplesDone = 0;
1577 /* UpdateDeviceParams
1579 * Updates device parameters according to the attribute list (caller is
1580 * responsible for holding the list lock).
1582 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1584 ALCcontext *context;
1585 enum DevFmtChannels oldChans;
1586 enum DevFmtType oldType;
1587 ALCuint oldFreq;
1588 FPUCtl oldMode;
1590 // Check for attributes
1591 if(device->Type == Loopback)
1593 enum {
1594 GotFreq = 1<<0,
1595 GotChans = 1<<1,
1596 GotType = 1<<2,
1597 GotAll = GotFreq|GotChans|GotType
1599 ALCuint freq, numMono, numStereo, numSends;
1600 enum DevFmtChannels schans;
1601 enum DevFmtType stype;
1602 ALCuint attrIdx = 0;
1603 ALCint gotFmt = 0;
1605 if(!attrList)
1607 WARN("Missing attributes for loopback device\n");
1608 return ALC_INVALID_VALUE;
1611 numMono = device->NumMonoSources;
1612 numStereo = device->NumStereoSources;
1613 numSends = device->NumAuxSends;
1614 schans = device->FmtChans;
1615 stype = device->FmtType;
1616 freq = device->Frequency;
1618 while(attrList[attrIdx])
1620 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1622 ALCint val = attrList[attrIdx + 1];
1623 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1624 return ALC_INVALID_VALUE;
1625 schans = val;
1626 gotFmt |= GotChans;
1629 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1631 ALCint val = attrList[attrIdx + 1];
1632 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1633 return ALC_INVALID_VALUE;
1634 stype = val;
1635 gotFmt |= GotType;
1638 if(attrList[attrIdx] == ALC_FREQUENCY)
1640 freq = attrList[attrIdx + 1];
1641 if(freq < MIN_OUTPUT_RATE)
1642 return ALC_INVALID_VALUE;
1643 gotFmt |= GotFreq;
1646 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1648 numStereo = attrList[attrIdx + 1];
1649 if(numStereo > device->MaxNoOfSources)
1650 numStereo = device->MaxNoOfSources;
1652 numMono = device->MaxNoOfSources - numStereo;
1655 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1656 numSends = attrList[attrIdx + 1];
1658 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1660 if(attrList[attrIdx + 1] != ALC_FALSE)
1661 device->Flags |= DEVICE_HRTF_REQUEST;
1662 else
1663 device->Flags &= ~DEVICE_HRTF_REQUEST;
1666 attrIdx += 2;
1669 if(gotFmt != GotAll)
1671 WARN("Missing format for loopback device\n");
1672 return ALC_INVALID_VALUE;
1675 ConfigValueUInt(NULL, "sends", &numSends);
1676 numSends = minu(MAX_SENDS, numSends);
1678 if((device->Flags&DEVICE_RUNNING))
1679 V0(device->Backend,stop)();
1680 device->Flags &= ~DEVICE_RUNNING;
1682 if(freq != device->Frequency)
1683 UpdateClockBase(device);
1684 device->Frequency = freq;
1685 device->FmtChans = schans;
1686 device->FmtType = stype;
1687 device->NumMonoSources = numMono;
1688 device->NumStereoSources = numStereo;
1689 device->NumAuxSends = numSends;
1691 else if(attrList && attrList[0])
1693 ALCuint freq, numMono, numStereo, numSends;
1694 ALCuint attrIdx = 0;
1696 /* If a context is already running on the device, stop playback so the
1697 * device attributes can be updated. */
1698 if((device->Flags&DEVICE_RUNNING))
1699 V0(device->Backend,stop)();
1700 device->Flags &= ~DEVICE_RUNNING;
1702 freq = device->Frequency;
1703 numMono = device->NumMonoSources;
1704 numStereo = device->NumStereoSources;
1705 numSends = device->NumAuxSends;
1707 while(attrList[attrIdx])
1709 if(attrList[attrIdx] == ALC_FREQUENCY)
1711 freq = attrList[attrIdx + 1];
1712 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1715 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1717 numStereo = attrList[attrIdx + 1];
1718 if(numStereo > device->MaxNoOfSources)
1719 numStereo = device->MaxNoOfSources;
1721 numMono = device->MaxNoOfSources - numStereo;
1724 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1725 numSends = attrList[attrIdx + 1];
1727 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1729 if(attrList[attrIdx + 1] != ALC_FALSE)
1730 device->Flags |= DEVICE_HRTF_REQUEST;
1731 else
1732 device->Flags &= ~DEVICE_HRTF_REQUEST;
1735 attrIdx += 2;
1738 ConfigValueUInt(NULL, "frequency", &freq);
1739 freq = maxu(freq, MIN_OUTPUT_RATE);
1741 ConfigValueUInt(NULL, "sends", &numSends);
1742 numSends = minu(MAX_SENDS, numSends);
1744 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1745 device->Frequency;
1746 /* SSE and Neon do best with the update size being a multiple of 4 */
1747 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1748 device->UpdateSize = (device->UpdateSize+3)&~3;
1750 if(freq != device->Frequency)
1751 UpdateClockBase(device);
1752 device->Frequency = freq;
1753 device->NumMonoSources = numMono;
1754 device->NumStereoSources = numStereo;
1755 device->NumAuxSends = numSends;
1758 if((device->Flags&DEVICE_RUNNING))
1759 return ALC_NO_ERROR;
1761 UpdateClockBase(device);
1763 oldFreq = device->Frequency;
1764 oldChans = device->FmtChans;
1765 oldType = device->FmtType;
1767 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1768 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1769 DevFmtChannelsString(device->FmtChans),
1770 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1771 DevFmtTypeString(device->FmtType),
1772 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1773 device->Frequency,
1774 device->UpdateSize, device->NumUpdates);
1776 if(device->Type != Loopback)
1778 int nohrtf = !(device->Flags&DEVICE_HRTF_REQUEST);
1779 if(GetConfigValueBool(NULL, "hrtf", !nohrtf))
1780 device->Flags |= DEVICE_HRTF_REQUEST;
1781 else
1782 device->Flags &= ~DEVICE_HRTF_REQUEST;
1784 if((device->Flags&DEVICE_HRTF_REQUEST))
1786 enum DevFmtChannels chans;
1787 ALCuint freq;
1788 if(FindHrtfFormat(device, &chans, &freq))
1790 device->Frequency = freq;
1791 device->FmtChans = chans;
1792 device->Flags |= DEVICE_CHANNELS_REQUEST |
1793 DEVICE_FREQUENCY_REQUEST;
1797 if(V0(device->Backend,reset)() == ALC_FALSE)
1798 return ALC_INVALID_DEVICE;
1800 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1802 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1803 DevFmtChannelsString(device->FmtChans));
1804 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1806 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1808 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1809 DevFmtTypeString(device->FmtType));
1810 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1812 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1814 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1815 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1818 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1819 DevFmtChannelsString(device->FmtChans),
1820 DevFmtTypeString(device->FmtType), device->Frequency,
1821 device->UpdateSize, device->NumUpdates);
1823 aluInitPanning(device);
1825 V(device->Synth,update)(device);
1827 device->Hrtf = NULL;
1828 if((device->Flags&DEVICE_HRTF_REQUEST))
1830 device->Hrtf = GetHrtf(device);
1831 if(!device->Hrtf)
1832 device->Flags &= ~DEVICE_HRTF_REQUEST;
1834 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1836 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1838 if(!device->Bs2b)
1840 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1841 bs2b_clear(device->Bs2b);
1843 bs2b_set_srate(device->Bs2b, device->Frequency);
1844 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1845 TRACE("BS2B level %d\n", device->Bs2bLevel);
1847 else
1849 free(device->Bs2b);
1850 device->Bs2b = NULL;
1851 TRACE("BS2B disabled\n");
1854 device->Flags &= ~DEVICE_WIDE_STEREO;
1855 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1856 device->Flags |= DEVICE_WIDE_STEREO;
1858 if(!device->Hrtf && (device->UpdateSize&3))
1860 if((CPUCapFlags&CPU_CAP_SSE))
1861 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1862 if((CPUCapFlags&CPU_CAP_NEON))
1863 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1866 SetMixerFPUMode(&oldMode);
1867 ALCdevice_Lock(device);
1868 context = device->ContextList;
1869 while(context)
1871 ALsizei pos;
1873 context->UpdateSources = AL_FALSE;
1874 LockUIntMapRead(&context->EffectSlotMap);
1875 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1877 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1879 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1881 UnlockUIntMapRead(&context->EffectSlotMap);
1882 ALCdevice_Unlock(device);
1883 RestoreFPUMode(&oldMode);
1884 return ALC_INVALID_DEVICE;
1886 slot->NeedsUpdate = AL_FALSE;
1887 V(slot->EffectState,update)(device, slot);
1889 UnlockUIntMapRead(&context->EffectSlotMap);
1891 LockUIntMapRead(&context->SourceMap);
1892 for(pos = 0;pos < context->SourceMap.size;pos++)
1894 ALsource *source = context->SourceMap.array[pos].value;
1895 ALuint s = device->NumAuxSends;
1896 while(s < MAX_SENDS)
1898 if(source->Send[s].Slot)
1899 DecrementRef(&source->Send[s].Slot->ref);
1900 source->Send[s].Slot = NULL;
1901 source->Send[s].Gain = 1.0f;
1902 source->Send[s].GainHF = 1.0f;
1903 s++;
1905 source->NeedsUpdate = AL_TRUE;
1907 UnlockUIntMapRead(&context->SourceMap);
1909 for(pos = 0;pos < context->ActiveSourceCount;pos++)
1911 ALactivesource *src = context->ActiveSources[pos];
1912 ALsource *source = src->Source;
1913 ALuint s = device->NumAuxSends;
1914 while(s < MAX_SENDS)
1916 src->Send[s].Moving = AL_FALSE;
1917 src->Send[s].Counter = 0;
1918 s++;
1921 src->Update(src, context);
1922 source->NeedsUpdate = AL_FALSE;
1925 context = context->next;
1927 if(device->DefaultSlot)
1929 ALeffectslot *slot = device->DefaultSlot;
1931 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1933 ALCdevice_Unlock(device);
1934 RestoreFPUMode(&oldMode);
1935 return ALC_INVALID_DEVICE;
1937 slot->NeedsUpdate = AL_FALSE;
1938 V(slot->EffectState,update)(device, slot);
1940 ALCdevice_Unlock(device);
1941 RestoreFPUMode(&oldMode);
1943 if(!(device->Flags&DEVICE_PAUSED))
1945 if(V0(device->Backend,start)() == ALC_FALSE)
1946 return ALC_INVALID_DEVICE;
1947 device->Flags |= DEVICE_RUNNING;
1950 return ALC_NO_ERROR;
1953 /* FreeDevice
1955 * Frees the device structure, and destroys any objects the app failed to
1956 * delete. Called once there's no more references on the device.
1958 static ALCvoid FreeDevice(ALCdevice *device)
1960 TRACE("%p\n", device);
1962 V0(device->Backend,close)();
1963 DELETE_OBJ(device->Backend);
1964 device->Backend = NULL;
1966 DELETE_OBJ(device->Synth);
1967 device->Synth = NULL;
1969 if(device->DefaultSlot)
1971 ALeffectState *state = device->DefaultSlot->EffectState;
1972 device->DefaultSlot = NULL;
1973 DELETE_OBJ(state);
1976 if(device->DefaultSfont)
1977 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1978 device->DefaultSfont = NULL;
1980 if(device->BufferMap.size > 0)
1982 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1983 ReleaseALBuffers(device);
1985 ResetUIntMap(&device->BufferMap);
1987 if(device->EffectMap.size > 0)
1989 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1990 ReleaseALEffects(device);
1992 ResetUIntMap(&device->EffectMap);
1994 if(device->FilterMap.size > 0)
1996 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1997 ReleaseALFilters(device);
1999 ResetUIntMap(&device->FilterMap);
2001 if(device->SfontMap.size > 0)
2003 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2004 ReleaseALSoundfonts(device);
2006 ResetUIntMap(&device->SfontMap);
2008 if(device->PresetMap.size > 0)
2010 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2011 ReleaseALPresets(device);
2013 ResetUIntMap(&device->PresetMap);
2015 if(device->FontsoundMap.size > 0)
2017 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2018 ReleaseALFontsounds(device);
2020 ResetUIntMap(&device->FontsoundMap);
2022 free(device->Bs2b);
2023 device->Bs2b = NULL;
2025 AL_STRING_DEINIT(device->DeviceName);
2027 al_free(device);
2031 void ALCdevice_IncRef(ALCdevice *device)
2033 uint ref;
2034 ref = IncrementRef(&device->ref);
2035 TRACEREF("%p increasing refcount to %u\n", device, ref);
2038 void ALCdevice_DecRef(ALCdevice *device)
2040 uint ref;
2041 ref = DecrementRef(&device->ref);
2042 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2043 if(ref == 0) FreeDevice(device);
2046 /* VerifyDevice
2048 * Checks if the device handle is valid, and increments its ref count if so.
2050 static ALCdevice *VerifyDevice(ALCdevice *device)
2052 ALCdevice *tmpDevice;
2054 if(!device)
2055 return NULL;
2057 LockLists();
2058 tmpDevice = DeviceList;
2059 while(tmpDevice && tmpDevice != device)
2060 tmpDevice = tmpDevice->next;
2062 if(tmpDevice)
2063 ALCdevice_IncRef(tmpDevice);
2064 UnlockLists();
2065 return tmpDevice;
2069 /* InitContext
2071 * Initializes context fields
2073 static ALvoid InitContext(ALCcontext *Context)
2075 ALint i, j;
2077 //Initialise listener
2078 Context->Listener->Gain = 1.0f;
2079 Context->Listener->MetersPerUnit = 1.0f;
2080 Context->Listener->Position[0] = 0.0f;
2081 Context->Listener->Position[1] = 0.0f;
2082 Context->Listener->Position[2] = 0.0f;
2083 Context->Listener->Velocity[0] = 0.0f;
2084 Context->Listener->Velocity[1] = 0.0f;
2085 Context->Listener->Velocity[2] = 0.0f;
2086 Context->Listener->Forward[0] = 0.0f;
2087 Context->Listener->Forward[1] = 0.0f;
2088 Context->Listener->Forward[2] = -1.0f;
2089 Context->Listener->Up[0] = 0.0f;
2090 Context->Listener->Up[1] = 1.0f;
2091 Context->Listener->Up[2] = 0.0f;
2092 for(i = 0;i < 4;i++)
2094 for(j = 0;j < 4;j++)
2095 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2097 for(i = 0;i < 3;i++)
2098 Context->Listener->Params.Velocity[i] = 0.0f;
2100 //Validate Context
2101 Context->LastError = AL_NO_ERROR;
2102 Context->UpdateSources = AL_FALSE;
2103 Context->ActiveSourceCount = 0;
2104 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2105 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2107 //Set globals
2108 Context->DistanceModel = DefaultDistanceModel;
2109 Context->SourceDistanceModel = AL_FALSE;
2110 Context->DopplerFactor = 1.0f;
2111 Context->DopplerVelocity = 1.0f;
2112 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2113 Context->DeferUpdates = AL_FALSE;
2115 Context->ExtensionList = alExtList;
2119 /* FreeContext
2121 * Cleans up the context, and destroys any remaining objects the app failed to
2122 * delete. Called once there's no more references on the context.
2124 static ALCvoid FreeContext(ALCcontext *context)
2126 ALsizei i;
2128 TRACE("%p\n", context);
2130 if(context->SourceMap.size > 0)
2132 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2133 ReleaseALSources(context);
2135 ResetUIntMap(&context->SourceMap);
2137 if(context->EffectSlotMap.size > 0)
2139 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2140 ReleaseALAuxiliaryEffectSlots(context);
2142 ResetUIntMap(&context->EffectSlotMap);
2144 for(i = 0;i < context->MaxActiveSources;i++)
2146 al_free(context->ActiveSources[i]);
2147 context->ActiveSources[i] = NULL;
2149 free(context->ActiveSources);
2150 context->ActiveSources = NULL;
2151 context->ActiveSourceCount = 0;
2152 context->MaxActiveSources = 0;
2154 VECTOR_DEINIT(context->ActiveAuxSlots);
2156 ALCdevice_DecRef(context->Device);
2157 context->Device = NULL;
2159 //Invalidate context
2160 memset(context, 0, sizeof(ALCcontext));
2161 free(context);
2164 /* ReleaseContext
2166 * Removes the context reference from the given device and removes it from
2167 * being current on the running thread or globally.
2169 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2171 ALCcontext *volatile*tmp_ctx;
2173 if(altss_get(LocalContext) == context)
2175 WARN("%p released while current on thread\n", context);
2176 altss_set(LocalContext, NULL);
2177 ALCcontext_DecRef(context);
2180 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL) == context)
2181 ALCcontext_DecRef(context);
2183 ALCdevice_Lock(device);
2184 tmp_ctx = &device->ContextList;
2185 while(*tmp_ctx)
2187 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next) == context)
2188 break;
2189 tmp_ctx = &(*tmp_ctx)->next;
2191 ALCdevice_Unlock(device);
2193 ALCcontext_DecRef(context);
2196 void ALCcontext_IncRef(ALCcontext *context)
2198 uint ref;
2199 ref = IncrementRef(&context->ref);
2200 TRACEREF("%p increasing refcount to %u\n", context, ref);
2203 void ALCcontext_DecRef(ALCcontext *context)
2205 uint ref;
2206 ref = DecrementRef(&context->ref);
2207 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2208 if(ref == 0) FreeContext(context);
2211 static void ReleaseThreadCtx(void *ptr)
2213 WARN("%p current for thread being destroyed\n", ptr);
2214 ALCcontext_DecRef(ptr);
2217 /* VerifyContext
2219 * Checks that the given context is valid, and increments its reference count.
2221 static ALCcontext *VerifyContext(ALCcontext *context)
2223 ALCdevice *dev;
2225 LockLists();
2226 dev = DeviceList;
2227 while(dev)
2229 ALCcontext *tmp_ctx = dev->ContextList;
2230 while(tmp_ctx)
2232 if(tmp_ctx == context)
2234 ALCcontext_IncRef(tmp_ctx);
2235 UnlockLists();
2236 return tmp_ctx;
2238 tmp_ctx = tmp_ctx->next;
2240 dev = dev->next;
2242 UnlockLists();
2244 return NULL;
2248 /* GetContextRef
2250 * Returns the currently active context for this thread, and adds a reference
2251 * without locking it.
2253 ALCcontext *GetContextRef(void)
2255 ALCcontext *context;
2257 context = altss_get(LocalContext);
2258 if(context)
2259 ALCcontext_IncRef(context);
2260 else
2262 LockLists();
2263 context = GlobalContext;
2264 if(context)
2265 ALCcontext_IncRef(context);
2266 UnlockLists();
2269 return context;
2273 /************************************************
2274 * Standard ALC functions
2275 ************************************************/
2277 /* alcGetError
2279 * Return last ALC generated error code for the given device
2281 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2283 ALCenum errorCode;
2285 if(VerifyDevice(device))
2287 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2288 ALCdevice_DecRef(device);
2290 else
2291 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2293 return errorCode;
2297 /* alcSuspendContext
2299 * Not functional
2301 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2305 /* alcProcessContext
2307 * Not functional
2309 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2314 /* alcGetString
2316 * Returns information about the device, and error strings
2318 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2320 const ALCchar *value = NULL;
2322 switch(param)
2324 case ALC_NO_ERROR:
2325 value = alcNoError;
2326 break;
2328 case ALC_INVALID_ENUM:
2329 value = alcErrInvalidEnum;
2330 break;
2332 case ALC_INVALID_VALUE:
2333 value = alcErrInvalidValue;
2334 break;
2336 case ALC_INVALID_DEVICE:
2337 value = alcErrInvalidDevice;
2338 break;
2340 case ALC_INVALID_CONTEXT:
2341 value = alcErrInvalidContext;
2342 break;
2344 case ALC_OUT_OF_MEMORY:
2345 value = alcErrOutOfMemory;
2346 break;
2348 case ALC_DEVICE_SPECIFIER:
2349 value = alcDefaultName;
2350 break;
2352 case ALC_ALL_DEVICES_SPECIFIER:
2353 if(VerifyDevice(Device))
2355 value = al_string_get_cstr(Device->DeviceName);
2356 ALCdevice_DecRef(Device);
2358 else
2360 ProbeAllDevicesList();
2361 value = al_string_get_cstr(alcAllDevicesList);
2363 break;
2365 case ALC_CAPTURE_DEVICE_SPECIFIER:
2366 if(VerifyDevice(Device))
2368 value = al_string_get_cstr(Device->DeviceName);
2369 ALCdevice_DecRef(Device);
2371 else
2373 ProbeCaptureDeviceList();
2374 value = al_string_get_cstr(alcCaptureDeviceList);
2376 break;
2378 /* Default devices are always first in the list */
2379 case ALC_DEFAULT_DEVICE_SPECIFIER:
2380 value = alcDefaultName;
2381 break;
2383 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2384 if(al_string_empty(alcAllDevicesList))
2385 ProbeAllDevicesList();
2387 Device = VerifyDevice(Device);
2389 free(alcDefaultAllDevicesSpecifier);
2390 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2391 if(!alcDefaultAllDevicesSpecifier)
2392 alcSetError(Device, ALC_OUT_OF_MEMORY);
2394 value = alcDefaultAllDevicesSpecifier;
2395 if(Device) ALCdevice_DecRef(Device);
2396 break;
2398 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2399 if(al_string_empty(alcCaptureDeviceList))
2400 ProbeCaptureDeviceList();
2402 Device = VerifyDevice(Device);
2404 free(alcCaptureDefaultDeviceSpecifier);
2405 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2406 if(!alcCaptureDefaultDeviceSpecifier)
2407 alcSetError(Device, ALC_OUT_OF_MEMORY);
2409 value = alcCaptureDefaultDeviceSpecifier;
2410 if(Device) ALCdevice_DecRef(Device);
2411 break;
2413 case ALC_EXTENSIONS:
2414 if(!VerifyDevice(Device))
2415 value = alcNoDeviceExtList;
2416 else
2418 value = alcExtensionList;
2419 ALCdevice_DecRef(Device);
2421 break;
2423 default:
2424 Device = VerifyDevice(Device);
2425 alcSetError(Device, ALC_INVALID_ENUM);
2426 if(Device) ALCdevice_DecRef(Device);
2427 break;
2430 return value;
2434 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2436 ALCsizei i;
2438 if(size <= 0 || values == NULL)
2440 alcSetError(device, ALC_INVALID_VALUE);
2441 return 0;
2444 if(!device)
2446 switch(param)
2448 case ALC_MAJOR_VERSION:
2449 values[0] = alcMajorVersion;
2450 return 1;
2451 case ALC_MINOR_VERSION:
2452 values[0] = alcMinorVersion;
2453 return 1;
2455 case ALC_ATTRIBUTES_SIZE:
2456 case ALC_ALL_ATTRIBUTES:
2457 case ALC_FREQUENCY:
2458 case ALC_REFRESH:
2459 case ALC_SYNC:
2460 case ALC_MONO_SOURCES:
2461 case ALC_STEREO_SOURCES:
2462 case ALC_CAPTURE_SAMPLES:
2463 case ALC_FORMAT_CHANNELS_SOFT:
2464 case ALC_FORMAT_TYPE_SOFT:
2465 alcSetError(NULL, ALC_INVALID_DEVICE);
2466 return 0;
2468 default:
2469 alcSetError(NULL, ALC_INVALID_ENUM);
2470 return 0;
2472 return 0;
2475 if(device->Type == Capture)
2477 switch(param)
2479 case ALC_CAPTURE_SAMPLES:
2480 ALCdevice_Lock(device);
2481 values[0] = V0(device->Backend,availableSamples)();
2482 ALCdevice_Unlock(device);
2483 return 1;
2485 case ALC_CONNECTED:
2486 values[0] = device->Connected;
2487 return 1;
2489 default:
2490 alcSetError(device, ALC_INVALID_ENUM);
2491 return 0;
2493 return 0;
2496 /* render device */
2497 switch(param)
2499 case ALC_MAJOR_VERSION:
2500 values[0] = alcMajorVersion;
2501 return 1;
2503 case ALC_MINOR_VERSION:
2504 values[0] = alcMinorVersion;
2505 return 1;
2507 case ALC_EFX_MAJOR_VERSION:
2508 values[0] = alcEFXMajorVersion;
2509 return 1;
2511 case ALC_EFX_MINOR_VERSION:
2512 values[0] = alcEFXMinorVersion;
2513 return 1;
2515 case ALC_ATTRIBUTES_SIZE:
2516 values[0] = 15;
2517 return 1;
2519 case ALC_ALL_ATTRIBUTES:
2520 if(size < 15)
2522 alcSetError(device, ALC_INVALID_VALUE);
2523 return 0;
2526 i = 0;
2527 values[i++] = ALC_FREQUENCY;
2528 values[i++] = device->Frequency;
2530 if(device->Type != Loopback)
2532 values[i++] = ALC_REFRESH;
2533 values[i++] = device->Frequency / device->UpdateSize;
2535 values[i++] = ALC_SYNC;
2536 values[i++] = ALC_FALSE;
2538 else
2540 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2541 values[i++] = device->FmtChans;
2543 values[i++] = ALC_FORMAT_TYPE_SOFT;
2544 values[i++] = device->FmtType;
2547 values[i++] = ALC_MONO_SOURCES;
2548 values[i++] = device->NumMonoSources;
2550 values[i++] = ALC_STEREO_SOURCES;
2551 values[i++] = device->NumStereoSources;
2553 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2554 values[i++] = device->NumAuxSends;
2556 values[i++] = ALC_HRTF_SOFT;
2557 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2559 values[i++] = 0;
2560 return i;
2562 case ALC_FREQUENCY:
2563 values[0] = device->Frequency;
2564 return 1;
2566 case ALC_REFRESH:
2567 if(device->Type == Loopback)
2569 alcSetError(device, ALC_INVALID_DEVICE);
2570 return 0;
2572 values[0] = device->Frequency / device->UpdateSize;
2573 return 1;
2575 case ALC_SYNC:
2576 if(device->Type == Loopback)
2578 alcSetError(device, ALC_INVALID_DEVICE);
2579 return 0;
2581 values[0] = ALC_FALSE;
2582 return 1;
2584 case ALC_FORMAT_CHANNELS_SOFT:
2585 if(device->Type != Loopback)
2587 alcSetError(device, ALC_INVALID_DEVICE);
2588 return 0;
2590 values[0] = device->FmtChans;
2591 return 1;
2593 case ALC_FORMAT_TYPE_SOFT:
2594 if(device->Type != Loopback)
2596 alcSetError(device, ALC_INVALID_DEVICE);
2597 return 0;
2599 values[0] = device->FmtType;
2600 return 1;
2602 case ALC_MONO_SOURCES:
2603 values[0] = device->NumMonoSources;
2604 return 1;
2606 case ALC_STEREO_SOURCES:
2607 values[0] = device->NumStereoSources;
2608 return 1;
2610 case ALC_MAX_AUXILIARY_SENDS:
2611 values[0] = device->NumAuxSends;
2612 return 1;
2614 case ALC_CONNECTED:
2615 values[0] = device->Connected;
2616 return 1;
2618 case ALC_HRTF_SOFT:
2619 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2620 return 1;
2622 default:
2623 alcSetError(device, ALC_INVALID_ENUM);
2624 return 0;
2626 return 0;
2629 /* alcGetIntegerv
2631 * Returns information about the device and the version of OpenAL
2633 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2635 device = VerifyDevice(device);
2636 if(size <= 0 || values == NULL)
2637 alcSetError(device, ALC_INVALID_VALUE);
2638 else
2639 GetIntegerv(device, param, size, values);
2640 if(device) ALCdevice_DecRef(device);
2643 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2645 ALCint *ivals;
2646 ALsizei i;
2648 device = VerifyDevice(device);
2649 if(size <= 0 || values == NULL)
2650 alcSetError(device, ALC_INVALID_VALUE);
2651 else if(!device || device->Type == Capture)
2653 ivals = malloc(size * sizeof(ALCint));
2654 size = GetIntegerv(device, pname, size, ivals);
2655 for(i = 0;i < size;i++)
2656 values[i] = ivals[i];
2657 free(ivals);
2659 else /* render device */
2661 switch(pname)
2663 case ALC_ATTRIBUTES_SIZE:
2664 *values = 17;
2665 break;
2667 case ALC_ALL_ATTRIBUTES:
2668 if(size < 17)
2669 alcSetError(device, ALC_INVALID_VALUE);
2670 else
2672 int i = 0;
2674 V0(device->Backend,lock)();
2675 values[i++] = ALC_FREQUENCY;
2676 values[i++] = device->Frequency;
2678 if(device->Type != Loopback)
2680 values[i++] = ALC_REFRESH;
2681 values[i++] = device->Frequency / device->UpdateSize;
2683 values[i++] = ALC_SYNC;
2684 values[i++] = ALC_FALSE;
2686 else
2688 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2689 values[i++] = device->FmtChans;
2691 values[i++] = ALC_FORMAT_TYPE_SOFT;
2692 values[i++] = device->FmtType;
2695 values[i++] = ALC_MONO_SOURCES;
2696 values[i++] = device->NumMonoSources;
2698 values[i++] = ALC_STEREO_SOURCES;
2699 values[i++] = device->NumStereoSources;
2701 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2702 values[i++] = device->NumAuxSends;
2704 values[i++] = ALC_HRTF_SOFT;
2705 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2707 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2708 values[i++] = device->ClockBase +
2709 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2711 values[i++] = 0;
2712 V0(device->Backend,unlock)();
2714 break;
2716 case ALC_DEVICE_CLOCK_SOFT:
2717 V0(device->Backend,lock)();
2718 *values = device->ClockBase +
2719 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2720 V0(device->Backend,unlock)();
2721 break;
2723 default:
2724 ivals = malloc(size * sizeof(ALCint));
2725 size = GetIntegerv(device, pname, size, ivals);
2726 for(i = 0;i < size;i++)
2727 values[i] = ivals[i];
2728 free(ivals);
2729 break;
2732 if(device)
2733 ALCdevice_DecRef(device);
2737 /* alcIsExtensionPresent
2739 * Determines if there is support for a particular extension
2741 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2743 ALCboolean bResult = ALC_FALSE;
2745 device = VerifyDevice(device);
2747 if(!extName)
2748 alcSetError(device, ALC_INVALID_VALUE);
2749 else
2751 size_t len = strlen(extName);
2752 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2753 while(ptr && *ptr)
2755 if(strncasecmp(ptr, extName, len) == 0 &&
2756 (ptr[len] == '\0' || isspace(ptr[len])))
2758 bResult = ALC_TRUE;
2759 break;
2761 if((ptr=strchr(ptr, ' ')) != NULL)
2763 do {
2764 ++ptr;
2765 } while(isspace(*ptr));
2769 if(device)
2770 ALCdevice_DecRef(device);
2771 return bResult;
2775 /* alcGetProcAddress
2777 * Retrieves the function address for a particular extension function
2779 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2781 ALCvoid *ptr = NULL;
2783 if(!funcName)
2785 device = VerifyDevice(device);
2786 alcSetError(device, ALC_INVALID_VALUE);
2787 if(device) ALCdevice_DecRef(device);
2789 else
2791 ALsizei i = 0;
2792 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2793 i++;
2794 ptr = alcFunctions[i].address;
2797 return ptr;
2801 /* alcGetEnumValue
2803 * Get the value for a particular ALC enumeration name
2805 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2807 ALCenum val = 0;
2809 if(!enumName)
2811 device = VerifyDevice(device);
2812 alcSetError(device, ALC_INVALID_VALUE);
2813 if(device) ALCdevice_DecRef(device);
2815 else
2817 ALsizei i = 0;
2818 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2819 i++;
2820 val = enumeration[i].value;
2823 return val;
2827 /* alcCreateContext
2829 * Create and attach a context to the given device.
2831 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2833 ALCcontext *ALContext;
2834 ALCenum err;
2836 LockLists();
2837 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2839 UnlockLists();
2840 alcSetError(device, ALC_INVALID_DEVICE);
2841 if(device) ALCdevice_DecRef(device);
2842 return NULL;
2845 device->LastError = ALC_NO_ERROR;
2847 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2849 UnlockLists();
2850 alcSetError(device, err);
2851 if(err == ALC_INVALID_DEVICE)
2853 ALCdevice_Lock(device);
2854 aluHandleDisconnect(device);
2855 ALCdevice_Unlock(device);
2857 ALCdevice_DecRef(device);
2858 return NULL;
2861 ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener));
2862 if(ALContext)
2864 InitRef(&ALContext->ref, 1);
2865 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2867 VECTOR_INIT(ALContext->ActiveAuxSlots);
2869 ALContext->MaxActiveSources = 256;
2870 ALContext->ActiveSources = calloc(ALContext->MaxActiveSources,
2871 sizeof(ALContext->ActiveSources[0]));
2873 if(!ALContext || !ALContext->ActiveSources)
2875 if(!device->ContextList)
2877 V0(device->Backend,stop)();
2878 device->Flags &= ~DEVICE_RUNNING;
2880 UnlockLists();
2882 if(ALContext)
2884 free(ALContext->ActiveSources);
2885 ALContext->ActiveSources = NULL;
2887 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2889 free(ALContext);
2890 ALContext = NULL;
2893 alcSetError(device, ALC_OUT_OF_MEMORY);
2894 ALCdevice_DecRef(device);
2895 return NULL;
2898 ALContext->Device = device;
2899 ALCdevice_IncRef(device);
2900 InitContext(ALContext);
2902 do {
2903 ALContext->next = device->ContextList;
2904 } while(CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext) != ALContext->next);
2905 UnlockLists();
2907 ALCdevice_DecRef(device);
2909 TRACE("Created context %p\n", ALContext);
2910 return ALContext;
2913 /* alcDestroyContext
2915 * Remove a context from its device
2917 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2919 ALCdevice *Device;
2921 LockLists();
2922 /* alcGetContextsDevice sets an error for invalid contexts */
2923 Device = alcGetContextsDevice(context);
2924 if(Device)
2926 ReleaseContext(context, Device);
2927 if(!Device->ContextList)
2929 V0(Device->Backend,stop)();
2930 Device->Flags &= ~DEVICE_RUNNING;
2933 UnlockLists();
2937 /* alcGetCurrentContext
2939 * Returns the currently active context on the calling thread
2941 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2943 ALCcontext *Context;
2945 Context = altss_get(LocalContext);
2946 if(!Context) Context = GlobalContext;
2948 return Context;
2951 /* alcGetThreadContext
2953 * Returns the currently active thread-local context
2955 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2957 ALCcontext *Context;
2958 Context = altss_get(LocalContext);
2959 return Context;
2963 /* alcMakeContextCurrent
2965 * Makes the given context the active process-wide context, and removes the
2966 * thread-local context for the calling thread.
2968 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2970 /* context must be valid or NULL */
2971 if(context && !(context=VerifyContext(context)))
2973 alcSetError(NULL, ALC_INVALID_CONTEXT);
2974 return ALC_FALSE;
2976 /* context's reference count is already incremented */
2977 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2978 if(context) ALCcontext_DecRef(context);
2980 if((context=altss_get(LocalContext)) != NULL)
2982 altss_set(LocalContext, NULL);
2983 ALCcontext_DecRef(context);
2986 return ALC_TRUE;
2989 /* alcSetThreadContext
2991 * Makes the given context the active context for the current thread
2993 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2995 ALCcontext *old;
2997 /* context must be valid or NULL */
2998 if(context && !(context=VerifyContext(context)))
3000 alcSetError(NULL, ALC_INVALID_CONTEXT);
3001 return ALC_FALSE;
3003 /* context's reference count is already incremented */
3004 old = altss_get(LocalContext);
3005 altss_set(LocalContext, context);
3006 if(old) ALCcontext_DecRef(old);
3008 return ALC_TRUE;
3012 /* alcGetContextsDevice
3014 * Returns the device that a particular context is attached to
3016 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3018 ALCdevice *Device;
3020 if(!(Context=VerifyContext(Context)))
3022 alcSetError(NULL, ALC_INVALID_CONTEXT);
3023 return NULL;
3025 Device = Context->Device;
3026 ALCcontext_DecRef(Context);
3028 return Device;
3032 /* alcOpenDevice
3034 * Opens the named device.
3036 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3038 const ALCchar *fmt;
3039 ALCdevice *device;
3040 ALCenum err;
3042 DO_INITCONFIG();
3044 if(!PlaybackBackend.name)
3046 alcSetError(NULL, ALC_INVALID_VALUE);
3047 return NULL;
3050 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3051 deviceName = NULL;
3053 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3054 if(!device)
3056 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3057 return NULL;
3060 //Validate device
3061 InitRef(&device->ref, 1);
3062 device->Connected = ALC_TRUE;
3063 device->Type = Playback;
3064 device->LastError = ALC_NO_ERROR;
3066 device->Flags = 0;
3067 device->Bs2b = NULL;
3068 device->Bs2bLevel = 0;
3069 AL_STRING_INIT(device->DeviceName);
3071 device->ContextList = NULL;
3073 device->ClockBase = 0;
3074 device->SamplesDone = 0;
3076 device->MaxNoOfSources = 256;
3077 device->AuxiliaryEffectSlotMax = 4;
3078 device->NumAuxSends = MAX_SENDS;
3080 InitUIntMap(&device->BufferMap, ~0);
3081 InitUIntMap(&device->EffectMap, ~0);
3082 InitUIntMap(&device->FilterMap, ~0);
3083 InitUIntMap(&device->SfontMap, ~0);
3084 InitUIntMap(&device->PresetMap, ~0);
3085 InitUIntMap(&device->FontsoundMap, ~0);
3087 //Set output format
3088 device->FmtChans = DevFmtChannelsDefault;
3089 device->FmtType = DevFmtTypeDefault;
3090 device->Frequency = DEFAULT_OUTPUT_RATE;
3091 device->NumUpdates = 4;
3092 device->UpdateSize = 1024;
3094 if(!PlaybackBackend.getFactory)
3095 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3096 ALCbackend_Playback);
3097 else
3099 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3100 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3102 if(!device->Backend)
3104 al_free(device);
3105 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3106 return NULL;
3110 if(ConfigValueStr(NULL, "channels", &fmt))
3112 static const struct {
3113 const char name[16];
3114 enum DevFmtChannels chans;
3115 } chanlist[] = {
3116 { "mono", DevFmtMono },
3117 { "stereo", DevFmtStereo },
3118 { "quad", DevFmtQuad },
3119 { "surround51", DevFmtX51 },
3120 { "surround61", DevFmtX61 },
3121 { "surround71", DevFmtX71 },
3123 size_t i;
3125 for(i = 0;i < COUNTOF(chanlist);i++)
3127 if(strcasecmp(chanlist[i].name, fmt) == 0)
3129 device->FmtChans = chanlist[i].chans;
3130 device->Flags |= DEVICE_CHANNELS_REQUEST;
3131 break;
3134 if(i == COUNTOF(chanlist))
3135 ERR("Unsupported channels: %s\n", fmt);
3137 if(ConfigValueStr(NULL, "sample-type", &fmt))
3139 static const struct {
3140 const char name[16];
3141 enum DevFmtType type;
3142 } typelist[] = {
3143 { "int8", DevFmtByte },
3144 { "uint8", DevFmtUByte },
3145 { "int16", DevFmtShort },
3146 { "uint16", DevFmtUShort },
3147 { "int32", DevFmtInt },
3148 { "uint32", DevFmtUInt },
3149 { "float32", DevFmtFloat },
3151 size_t i;
3153 for(i = 0;i < COUNTOF(typelist);i++)
3155 if(strcasecmp(typelist[i].name, fmt) == 0)
3157 device->FmtType = typelist[i].type;
3158 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3159 break;
3162 if(i == COUNTOF(typelist))
3163 ERR("Unsupported sample-type: %s\n", fmt);
3165 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3166 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3167 ConfigValueStr(NULL, "format", &fmt))
3169 static const struct {
3170 const char name[32];
3171 enum DevFmtChannels channels;
3172 enum DevFmtType type;
3173 } formats[] = {
3174 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3175 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3176 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3177 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3178 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3179 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3181 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3182 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3183 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3184 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3185 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3186 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3188 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3189 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3190 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3191 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3192 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3193 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3195 size_t i;
3197 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3198 for(i = 0;i < COUNTOF(formats);i++)
3200 if(strcasecmp(fmt, formats[i].name) == 0)
3202 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3203 device->FmtChans = formats[i].channels;
3204 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3205 device->FmtType = formats[i].type;
3206 device->Flags |= DEVICE_FORMAT_REQUEST;
3207 break;
3210 if(i == COUNTOF(formats))
3211 ERR("Unsupported format: %s\n", fmt);
3213 #undef DEVICE_FORMAT_REQUEST
3215 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3217 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3218 if(device->Frequency < MIN_OUTPUT_RATE)
3219 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3220 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3223 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3224 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3226 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3227 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3228 if((CPUCapFlags&CPU_CAP_SSE))
3229 device->UpdateSize = (device->UpdateSize+3)&~3;
3231 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3232 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3234 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3235 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3237 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3238 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3240 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3242 device->NumStereoSources = 1;
3243 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3245 device->Synth = SynthCreate(device);
3246 if(!device->Synth)
3248 DELETE_OBJ(device->Backend);
3249 al_free(device);
3250 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3251 return NULL;
3254 // Find a playback device to open
3255 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3257 DELETE_OBJ(device->Synth);
3258 DELETE_OBJ(device->Backend);
3259 al_free(device);
3260 alcSetError(NULL, err);
3261 return NULL;
3264 if(DefaultEffect.type != AL_EFFECT_NULL)
3266 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3267 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3269 device->DefaultSlot = NULL;
3270 ERR("Failed to initialize the default effect slot\n");
3272 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3274 ALeffectState *state = device->DefaultSlot->EffectState;
3275 device->DefaultSlot = NULL;
3276 DELETE_OBJ(state);
3277 ERR("Failed to initialize the default effect\n");
3281 do {
3282 device->next = DeviceList;
3283 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3285 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3286 return device;
3289 /* alcCloseDevice
3291 * Closes the given device.
3293 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
3295 ALCdevice *volatile*list;
3296 ALCcontext *ctx;
3298 LockLists();
3299 list = &DeviceList;
3300 while(*list && *list != Device)
3301 list = &(*list)->next;
3303 if(!*list || (*list)->Type == Capture)
3305 alcSetError(*list, ALC_INVALID_DEVICE);
3306 UnlockLists();
3307 return ALC_FALSE;
3310 *list = (*list)->next;
3311 UnlockLists();
3313 while((ctx=Device->ContextList) != NULL)
3315 WARN("Releasing context %p\n", ctx);
3316 ReleaseContext(ctx, Device);
3318 if((Device->Flags&DEVICE_RUNNING))
3319 V0(Device->Backend,stop)();
3320 Device->Flags &= ~DEVICE_RUNNING;
3322 ALCdevice_DecRef(Device);
3324 return ALC_TRUE;
3328 /************************************************
3329 * ALC capture functions
3330 ************************************************/
3331 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3333 ALCdevice *device = NULL;
3334 ALCenum err;
3336 DO_INITCONFIG();
3338 if(!CaptureBackend.name)
3340 alcSetError(NULL, ALC_INVALID_VALUE);
3341 return NULL;
3344 if(samples <= 0)
3346 alcSetError(NULL, ALC_INVALID_VALUE);
3347 return NULL;
3350 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3351 deviceName = NULL;
3353 device = al_calloc(16, sizeof(ALCdevice));
3354 if(!device)
3356 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3357 return NULL;
3360 //Validate device
3361 InitRef(&device->ref, 1);
3362 device->Connected = ALC_TRUE;
3363 device->Type = Capture;
3365 AL_STRING_INIT(device->DeviceName);
3367 InitUIntMap(&device->BufferMap, ~0);
3368 InitUIntMap(&device->EffectMap, ~0);
3369 InitUIntMap(&device->FilterMap, ~0);
3370 InitUIntMap(&device->SfontMap, ~0);
3371 InitUIntMap(&device->PresetMap, ~0);
3372 InitUIntMap(&device->FontsoundMap, ~0);
3374 if(!CaptureBackend.getFactory)
3375 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3376 ALCbackend_Capture);
3377 else
3379 ALCbackendFactory *factory = CaptureBackend.getFactory();
3380 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3382 if(!device->Backend)
3384 al_free(device);
3385 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3386 return NULL;
3389 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3390 device->Frequency = frequency;
3392 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3393 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3395 al_free(device);
3396 alcSetError(NULL, ALC_INVALID_ENUM);
3397 return NULL;
3400 device->UpdateSize = samples;
3401 device->NumUpdates = 1;
3403 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3405 al_free(device);
3406 alcSetError(NULL, err);
3407 return NULL;
3410 do {
3411 device->next = DeviceList;
3412 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3414 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3415 return device;
3418 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
3420 ALCdevice *volatile*list;
3422 LockLists();
3423 list = &DeviceList;
3424 while(*list && *list != Device)
3425 list = &(*list)->next;
3427 if(!*list || (*list)->Type != Capture)
3429 alcSetError(*list, ALC_INVALID_DEVICE);
3430 UnlockLists();
3431 return ALC_FALSE;
3434 *list = (*list)->next;
3435 UnlockLists();
3437 ALCdevice_DecRef(Device);
3439 return ALC_TRUE;
3442 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3444 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3445 alcSetError(device, ALC_INVALID_DEVICE);
3446 else
3448 ALCdevice_Lock(device);
3449 if(device->Connected)
3451 if(!(device->Flags&DEVICE_RUNNING))
3452 V0(device->Backend,start)();
3453 device->Flags |= DEVICE_RUNNING;
3455 ALCdevice_Unlock(device);
3458 if(device) ALCdevice_DecRef(device);
3461 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3463 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3464 alcSetError(device, ALC_INVALID_DEVICE);
3465 else
3467 ALCdevice_Lock(device);
3468 if((device->Flags&DEVICE_RUNNING))
3469 V0(device->Backend,stop)();
3470 device->Flags &= ~DEVICE_RUNNING;
3471 ALCdevice_Unlock(device);
3474 if(device) ALCdevice_DecRef(device);
3477 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3479 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3480 alcSetError(device, ALC_INVALID_DEVICE);
3481 else
3483 ALCenum err = ALC_INVALID_VALUE;
3485 ALCdevice_Lock(device);
3486 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3487 err = V(device->Backend,captureSamples)(buffer, samples);
3488 ALCdevice_Unlock(device);
3490 if(err != ALC_NO_ERROR)
3491 alcSetError(device, err);
3493 if(device) ALCdevice_DecRef(device);
3497 /************************************************
3498 * ALC loopback functions
3499 ************************************************/
3501 /* alcLoopbackOpenDeviceSOFT
3503 * Open a loopback device, for manual rendering.
3505 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3507 ALCbackendFactory *factory;
3508 ALCdevice *device;
3510 DO_INITCONFIG();
3512 /* Make sure the device name, if specified, is us. */
3513 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3515 alcSetError(NULL, ALC_INVALID_VALUE);
3516 return NULL;
3519 device = al_calloc(16, sizeof(ALCdevice));
3520 if(!device)
3522 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3523 return NULL;
3526 //Validate device
3527 InitRef(&device->ref, 1);
3528 device->Connected = ALC_TRUE;
3529 device->Type = Loopback;
3530 device->LastError = ALC_NO_ERROR;
3532 device->Flags = 0;
3533 device->Bs2b = NULL;
3534 device->Bs2bLevel = 0;
3535 AL_STRING_INIT(device->DeviceName);
3537 device->ContextList = NULL;
3539 device->ClockBase = 0;
3540 device->SamplesDone = 0;
3542 device->MaxNoOfSources = 256;
3543 device->AuxiliaryEffectSlotMax = 4;
3544 device->NumAuxSends = MAX_SENDS;
3546 InitUIntMap(&device->BufferMap, ~0);
3547 InitUIntMap(&device->EffectMap, ~0);
3548 InitUIntMap(&device->FilterMap, ~0);
3549 InitUIntMap(&device->SfontMap, ~0);
3550 InitUIntMap(&device->PresetMap, ~0);
3551 InitUIntMap(&device->FontsoundMap, ~0);
3553 factory = ALCloopbackFactory_getFactory();
3554 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3555 if(!device->Backend)
3557 al_free(device);
3558 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3559 return NULL;
3562 //Set output format
3563 device->NumUpdates = 0;
3564 device->UpdateSize = 0;
3566 device->Frequency = DEFAULT_OUTPUT_RATE;
3567 device->FmtChans = DevFmtChannelsDefault;
3568 device->FmtType = DevFmtTypeDefault;
3570 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3571 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3573 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3574 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3576 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3577 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3579 device->NumStereoSources = 1;
3580 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3582 device->Synth = SynthCreate(device);
3583 if(!device->Synth)
3585 DELETE_OBJ(device->Backend);
3586 al_free(device);
3587 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3588 return NULL;
3591 // Open the "backend"
3592 V(device->Backend,open)("Loopback");
3593 do {
3594 device->next = DeviceList;
3595 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3597 TRACE("Created device %p\n", device);
3598 return device;
3601 /* alcIsRenderFormatSupportedSOFT
3603 * Determines if the loopback device supports the given format for rendering.
3605 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3607 ALCboolean ret = ALC_FALSE;
3609 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3610 alcSetError(device, ALC_INVALID_DEVICE);
3611 else if(freq <= 0)
3612 alcSetError(device, ALC_INVALID_VALUE);
3613 else
3615 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3616 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3617 freq >= MIN_OUTPUT_RATE)
3618 ret = ALC_TRUE;
3620 if(device) ALCdevice_DecRef(device);
3622 return ret;
3625 /* alcRenderSamplesSOFT
3627 * Renders some samples into a buffer, using the format last set by the
3628 * attributes given to alcCreateContext.
3630 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3632 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3633 alcSetError(device, ALC_INVALID_DEVICE);
3634 else if(samples < 0 || (samples > 0 && buffer == NULL))
3635 alcSetError(device, ALC_INVALID_VALUE);
3636 else
3637 aluMixData(device, buffer, samples);
3638 if(device) ALCdevice_DecRef(device);
3642 /************************************************
3643 * ALC DSP pause/resume functions
3644 ************************************************/
3646 /* alcDevicePauseSOFT
3648 * Pause the DSP to stop audio processing.
3650 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3652 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3653 alcSetError(device, ALC_INVALID_DEVICE);
3654 else
3656 LockLists();
3657 if((device->Flags&DEVICE_RUNNING))
3658 V0(device->Backend,stop)();
3659 device->Flags &= ~DEVICE_RUNNING;
3660 device->Flags |= DEVICE_PAUSED;
3661 UnlockLists();
3663 if(device) ALCdevice_DecRef(device);
3666 /* alcDeviceResumeSOFT
3668 * Resume the DSP to restart audio processing.
3670 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3672 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3673 alcSetError(device, ALC_INVALID_DEVICE);
3674 else
3676 LockLists();
3677 if((device->Flags&DEVICE_PAUSED))
3679 device->Flags &= ~DEVICE_PAUSED;
3680 if(device->ContextList != NULL)
3682 if(V0(device->Backend,start)() != ALC_FALSE)
3683 device->Flags |= DEVICE_RUNNING;
3684 else
3686 alcSetError(device, ALC_INVALID_DEVICE);
3687 ALCdevice_Lock(device);
3688 aluHandleDisconnect(device);
3689 ALCdevice_Unlock(device);
3693 UnlockLists();
3695 if(device) ALCdevice_DecRef(device);