Move atomic method definitions to a separate common source
[openal-soft.git] / Alc / ALc.c
blob5114942c3dfb8fbe712dc9935af709cafca722a5
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 #if 0
569 DECL(AL_FILTER_HIGHPASS),
570 DECL(AL_FILTER_BANDPASS),
571 #endif
573 DECL(AL_LOWPASS_GAIN),
574 DECL(AL_LOWPASS_GAINHF),
576 DECL(AL_EFFECT_TYPE),
577 DECL(AL_EFFECT_NULL),
578 DECL(AL_EFFECT_REVERB),
579 DECL(AL_EFFECT_EAXREVERB),
580 DECL(AL_EFFECT_CHORUS),
581 DECL(AL_EFFECT_DISTORTION),
582 DECL(AL_EFFECT_ECHO),
583 DECL(AL_EFFECT_FLANGER),
584 #if 0
585 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
586 DECL(AL_EFFECT_VOCAL_MORPHER),
587 DECL(AL_EFFECT_PITCH_SHIFTER),
588 #endif
589 DECL(AL_EFFECT_RING_MODULATOR),
590 DECL(AL_EFFECT_AUTOWAH),
591 DECL(AL_EFFECT_COMPRESSOR),
592 DECL(AL_EFFECT_EQUALIZER),
593 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
594 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
596 DECL(AL_EAXREVERB_DENSITY),
597 DECL(AL_EAXREVERB_DIFFUSION),
598 DECL(AL_EAXREVERB_GAIN),
599 DECL(AL_EAXREVERB_GAINHF),
600 DECL(AL_EAXREVERB_GAINLF),
601 DECL(AL_EAXREVERB_DECAY_TIME),
602 DECL(AL_EAXREVERB_DECAY_HFRATIO),
603 DECL(AL_EAXREVERB_DECAY_LFRATIO),
604 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
605 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
606 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
607 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
608 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
609 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
610 DECL(AL_EAXREVERB_ECHO_TIME),
611 DECL(AL_EAXREVERB_ECHO_DEPTH),
612 DECL(AL_EAXREVERB_MODULATION_TIME),
613 DECL(AL_EAXREVERB_MODULATION_DEPTH),
614 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
615 DECL(AL_EAXREVERB_HFREFERENCE),
616 DECL(AL_EAXREVERB_LFREFERENCE),
617 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
618 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
620 DECL(AL_REVERB_DENSITY),
621 DECL(AL_REVERB_DIFFUSION),
622 DECL(AL_REVERB_GAIN),
623 DECL(AL_REVERB_GAINHF),
624 DECL(AL_REVERB_DECAY_TIME),
625 DECL(AL_REVERB_DECAY_HFRATIO),
626 DECL(AL_REVERB_REFLECTIONS_GAIN),
627 DECL(AL_REVERB_REFLECTIONS_DELAY),
628 DECL(AL_REVERB_LATE_REVERB_GAIN),
629 DECL(AL_REVERB_LATE_REVERB_DELAY),
630 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
631 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
632 DECL(AL_REVERB_DECAY_HFLIMIT),
634 DECL(AL_CHORUS_WAVEFORM),
635 DECL(AL_CHORUS_PHASE),
636 DECL(AL_CHORUS_RATE),
637 DECL(AL_CHORUS_DEPTH),
638 DECL(AL_CHORUS_FEEDBACK),
639 DECL(AL_CHORUS_DELAY),
641 DECL(AL_DISTORTION_EDGE),
642 DECL(AL_DISTORTION_GAIN),
643 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
644 DECL(AL_DISTORTION_EQCENTER),
645 DECL(AL_DISTORTION_EQBANDWIDTH),
647 DECL(AL_ECHO_DELAY),
648 DECL(AL_ECHO_LRDELAY),
649 DECL(AL_ECHO_DAMPING),
650 DECL(AL_ECHO_FEEDBACK),
651 DECL(AL_ECHO_SPREAD),
653 DECL(AL_FLANGER_WAVEFORM),
654 DECL(AL_FLANGER_PHASE),
655 DECL(AL_FLANGER_RATE),
656 DECL(AL_FLANGER_DEPTH),
657 DECL(AL_FLANGER_FEEDBACK),
658 DECL(AL_FLANGER_DELAY),
660 DECL(AL_RING_MODULATOR_FREQUENCY),
661 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
662 DECL(AL_RING_MODULATOR_WAVEFORM),
664 DECL(AL_AUTOWAH_ATTACK_TIME),
665 DECL(AL_AUTOWAH_PEAK_GAIN),
666 DECL(AL_AUTOWAH_RELEASE_TIME),
667 DECL(AL_AUTOWAH_RESONANCE),
669 DECL(AL_COMPRESSOR_ONOFF),
671 DECL(AL_EQUALIZER_LOW_GAIN),
672 DECL(AL_EQUALIZER_LOW_CUTOFF),
673 DECL(AL_EQUALIZER_MID1_GAIN),
674 DECL(AL_EQUALIZER_MID1_CENTER),
675 DECL(AL_EQUALIZER_MID1_WIDTH),
676 DECL(AL_EQUALIZER_MID2_GAIN),
677 DECL(AL_EQUALIZER_MID2_CENTER),
678 DECL(AL_EQUALIZER_MID2_WIDTH),
679 DECL(AL_EQUALIZER_HIGH_GAIN),
680 DECL(AL_EQUALIZER_HIGH_CUTOFF),
682 DECL(AL_DEDICATED_GAIN),
684 { NULL, (ALCenum)0 }
686 #undef DECL
688 static const ALCchar alcNoError[] = "No Error";
689 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
690 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
691 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
692 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
693 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
696 /************************************************
697 * Global variables
698 ************************************************/
700 /* Enumerated device names */
701 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
703 static al_string alcAllDevicesList;
704 static al_string alcCaptureDeviceList;
706 /* Default is always the first in the list */
707 static ALCchar *alcDefaultAllDevicesSpecifier;
708 static ALCchar *alcCaptureDefaultDeviceSpecifier;
710 /* Default context extensions */
711 static const ALchar alExtList[] =
712 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
713 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
714 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
715 "AL_LOKI_quadriphonic AL_SOFTX_block_alignment AL_SOFT_buffer_samples "
716 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
717 "AL_SOFT_loop_points AL_SOFTX_MSADPCM AL_SOFT_source_latency";
719 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
721 /* Thread-local current context */
722 static altss_t LocalContext;
723 /* Process-wide current context */
724 static ALCcontext *volatile GlobalContext = NULL;
726 /* Mixing thread piority level */
727 ALint RTPrioLevel;
729 FILE *LogFile;
730 #ifdef _DEBUG
731 enum LogLevel LogLevel = LogWarning;
732 #else
733 enum LogLevel LogLevel = LogError;
734 #endif
736 /* Flag to trap ALC device errors */
737 static ALCboolean TrapALCError = ALC_FALSE;
739 /* One-time configuration init control */
740 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
742 /* Default effect that applies to sources that don't have an effect on send 0 */
743 static ALeffect DefaultEffect;
746 /************************************************
747 * ALC information
748 ************************************************/
749 static const ALCchar alcNoDeviceExtList[] =
750 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
751 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
752 static const ALCchar alcExtensionList[] =
753 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
754 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
755 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
756 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
757 static const ALCint alcMajorVersion = 1;
758 static const ALCint alcMinorVersion = 1;
760 static const ALCint alcEFXMajorVersion = 1;
761 static const ALCint alcEFXMinorVersion = 0;
764 /************************************************
765 * Device lists
766 ************************************************/
767 static ALCdevice *volatile DeviceList = NULL;
769 static almtx_t ListLock;
770 static inline void LockLists(void)
772 int lockret = almtx_lock(&ListLock);
773 assert(lockret == althrd_success);
775 static inline void UnlockLists(void)
777 int unlockret = almtx_unlock(&ListLock);
778 assert(unlockret == althrd_success);
781 /************************************************
782 * Library initialization
783 ************************************************/
784 #if defined(_WIN32)
785 static void alc_init(void);
786 static void alc_deinit(void);
787 static void alc_deinit_safe(void);
789 #ifndef AL_LIBTYPE_STATIC
790 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
792 switch(reason)
794 case DLL_PROCESS_ATTACH:
795 /* Pin the DLL so we won't get unloaded until the process terminates */
796 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
797 (WCHAR*)hModule, &hModule);
798 alc_init();
799 break;
801 case DLL_THREAD_DETACH:
802 break;
804 case DLL_PROCESS_DETACH:
805 if(!lpReserved)
806 alc_deinit();
807 else
808 alc_deinit_safe();
809 break;
811 return TRUE;
813 #elif defined(_MSC_VER)
814 #pragma section(".CRT$XCU",read)
815 static void alc_constructor(void);
816 static void alc_destructor(void);
817 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
819 static void alc_constructor(void)
821 atexit(alc_destructor);
822 alc_init();
825 static void alc_destructor(void)
827 alc_deinit();
829 #elif defined(HAVE_GCC_DESTRUCTOR)
830 static void alc_init(void) __attribute__((constructor));
831 static void alc_deinit(void) __attribute__((destructor));
832 #else
833 #error "No static initialization available on this platform!"
834 #endif
836 #elif defined(HAVE_GCC_DESTRUCTOR)
838 static void alc_init(void) __attribute__((constructor));
839 static void alc_deinit(void) __attribute__((destructor));
841 #else
842 #error "No global initialization available on this platform!"
843 #endif
845 static void ReleaseThreadCtx(void *ptr);
846 static void alc_init(void)
848 const char *str;
849 int ret;
851 LogFile = stderr;
853 AL_STRING_INIT(alcAllDevicesList);
854 AL_STRING_INIT(alcCaptureDeviceList);
856 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
857 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
858 ConeScale *= 0.5f;
860 str = getenv("__ALSOFT_REVERSE_Z");
861 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
862 ZScale *= -1.0f;
864 ret = altss_create(&LocalContext, ReleaseThreadCtx);
865 assert(ret == althrd_success);
867 ret = almtx_init(&ListLock, almtx_recursive);
868 assert(ret == althrd_success);
870 ThunkInit();
873 static void alc_initconfig(void)
875 const char *devs, *str;
876 ALuint capfilter;
877 float valf;
878 int i, n;
880 str = getenv("ALSOFT_LOGLEVEL");
881 if(str)
883 long lvl = strtol(str, NULL, 0);
884 if(lvl >= NoLog && lvl <= LogRef)
885 LogLevel = lvl;
888 str = getenv("ALSOFT_LOGFILE");
889 if(str && str[0])
891 FILE *logfile = al_fopen(str, "wt");
892 if(logfile) LogFile = logfile;
893 else ERR("Failed to open log file '%s'\n", str);
897 char buf[1024] = "";
898 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
899 for(i = 1;BackendList[i].name;i++)
900 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
901 TRACE("Supported backends: %s\n", buf);
903 ReadALConfig();
905 capfilter = 0;
906 #ifdef HAVE_SSE
907 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
908 #endif
909 #ifdef HAVE_NEON
910 capfilter |= CPU_CAP_NEON;
911 #endif
912 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
914 if(strcasecmp(str, "all") == 0)
915 capfilter = 0;
916 else
918 size_t len;
919 const char *next = str;
921 do {
922 str = next;
923 while(isspace(str[0]))
924 str++;
925 next = strchr(str, ',');
927 if(!str[0] || str[0] == ',')
928 continue;
930 len = (next ? ((size_t)(next-str)) : strlen(str));
931 while(len > 0 && isspace(str[len-1]))
932 len--;
933 if(len == 3 && strncasecmp(str, "sse", len) == 0)
934 capfilter &= ~CPU_CAP_SSE;
935 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
936 capfilter &= ~CPU_CAP_SSE2;
937 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
938 capfilter &= ~CPU_CAP_NEON;
939 else
940 WARN("Invalid CPU extension \"%s\"\n", str);
941 } while(next++);
944 FillCPUCaps(capfilter);
946 #ifdef _WIN32
947 RTPrioLevel = 1;
948 #else
949 RTPrioLevel = 0;
950 #endif
951 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
953 if(ConfigValueStr(NULL, "resampler", &str))
955 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
956 DefaultResampler = PointResampler;
957 else if(strcasecmp(str, "linear") == 0)
958 DefaultResampler = LinearResampler;
959 else if(strcasecmp(str, "cubic") == 0)
960 DefaultResampler = CubicResampler;
961 else
963 char *end;
965 n = strtol(str, &end, 0);
966 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
967 DefaultResampler = n;
968 else
969 WARN("Invalid resampler: %s\n", str);
973 str = getenv("ALSOFT_TRAP_ERROR");
974 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
976 TrapALError = AL_TRUE;
977 TrapALCError = AL_TRUE;
979 else
981 str = getenv("ALSOFT_TRAP_AL_ERROR");
982 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
983 TrapALError = AL_TRUE;
984 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
986 str = getenv("ALSOFT_TRAP_ALC_ERROR");
987 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALCError = ALC_TRUE;
989 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
992 if(ConfigValueFloat("reverb", "boost", &valf))
993 ReverbBoost *= powf(10.0f, valf / 20.0f);
995 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
997 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
998 ConfigValueStr(NULL, "drivers", &devs))
1000 int n;
1001 size_t len;
1002 const char *next = devs;
1003 int endlist, delitem;
1005 i = 0;
1006 do {
1007 devs = next;
1008 while(isspace(devs[0]))
1009 devs++;
1010 next = strchr(devs, ',');
1012 delitem = (devs[0] == '-');
1013 if(devs[0] == '-') devs++;
1015 if(!devs[0] || devs[0] == ',')
1017 endlist = 0;
1018 continue;
1020 endlist = 1;
1022 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1023 while(len > 0 && isspace(devs[len-1]))
1024 len--;
1025 for(n = i;BackendList[n].name;n++)
1027 if(len == strlen(BackendList[n].name) &&
1028 strncmp(BackendList[n].name, devs, len) == 0)
1030 if(delitem)
1032 do {
1033 BackendList[n] = BackendList[n+1];
1034 ++n;
1035 } while(BackendList[n].name);
1037 else
1039 struct BackendInfo Bkp = BackendList[n];
1040 while(n > i)
1042 BackendList[n] = BackendList[n-1];
1043 --n;
1045 BackendList[n] = Bkp;
1047 i++;
1049 break;
1052 } while(next++);
1054 if(endlist)
1056 BackendList[i].name = NULL;
1057 BackendList[i].getFactory = NULL;
1058 BackendList[i].Init = NULL;
1059 BackendList[i].Deinit = NULL;
1060 BackendList[i].Probe = NULL;
1064 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1066 if(BackendList[i].getFactory)
1068 ALCbackendFactory *factory = BackendList[i].getFactory();
1069 if(!V0(factory,init)())
1071 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1072 continue;
1075 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1076 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1078 PlaybackBackend = BackendList[i];
1079 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1081 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1083 CaptureBackend = BackendList[i];
1084 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1087 continue;
1090 if(!BackendList[i].Init(&BackendList[i].Funcs))
1092 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1093 continue;
1096 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1097 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1099 PlaybackBackend = BackendList[i];
1100 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1102 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1104 CaptureBackend = BackendList[i];
1105 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1109 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1110 V0(factory,init)();
1113 if(ConfigValueStr(NULL, "excludefx", &str))
1115 size_t len;
1116 const char *next = str;
1118 do {
1119 str = next;
1120 next = strchr(str, ',');
1122 if(!str[0] || next == str)
1123 continue;
1125 len = (next ? ((size_t)(next-str)) : strlen(str));
1126 for(n = 0;EffectList[n].name;n++)
1128 if(len == strlen(EffectList[n].name) &&
1129 strncmp(EffectList[n].name, str, len) == 0)
1130 DisabledEffects[EffectList[n].type] = AL_TRUE;
1132 } while(next++);
1135 InitEffectFactoryMap();
1137 InitEffect(&DefaultEffect);
1138 str = getenv("ALSOFT_DEFAULT_REVERB");
1139 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1140 LoadReverbPreset(str, &DefaultEffect);
1142 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1145 /************************************************
1146 * Library deinitialization
1147 ************************************************/
1148 static void alc_cleanup(void)
1150 ALCdevice *dev;
1152 AL_STRING_DEINIT(alcAllDevicesList);
1153 AL_STRING_DEINIT(alcCaptureDeviceList);
1155 free(alcDefaultAllDevicesSpecifier);
1156 alcDefaultAllDevicesSpecifier = NULL;
1157 free(alcCaptureDefaultDeviceSpecifier);
1158 alcCaptureDefaultDeviceSpecifier = NULL;
1160 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1162 ALCuint num = 0;
1163 do {
1164 num++;
1165 } while((dev=dev->next) != NULL);
1166 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1169 DeinitEffectFactoryMap();
1172 static void alc_deinit_safe(void)
1174 alc_cleanup();
1176 FreeHrtfs();
1177 FreeALConfig();
1179 ThunkExit();
1180 almtx_destroy(&ListLock);
1181 altss_delete(LocalContext);
1183 if(LogFile != stderr)
1184 fclose(LogFile);
1185 LogFile = NULL;
1188 static void alc_deinit(void)
1190 int i;
1192 alc_cleanup();
1194 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1195 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1197 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1199 if(!BackendList[i].getFactory)
1200 BackendList[i].Deinit();
1201 else
1203 ALCbackendFactory *factory = BackendList[i].getFactory();
1204 V0(factory,deinit)();
1208 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1209 V0(factory,deinit)();
1212 alc_deinit_safe();
1216 /************************************************
1217 * Device enumeration
1218 ************************************************/
1219 static void ProbeDevices(al_string *list, enum DevProbe type)
1221 DO_INITCONFIG();
1223 LockLists();
1224 al_string_clear(list);
1226 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1228 if(!PlaybackBackend.getFactory)
1229 PlaybackBackend.Probe(type);
1230 else
1232 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1233 V(factory,probe)(type);
1236 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1238 if(!CaptureBackend.getFactory)
1239 CaptureBackend.Probe(type);
1240 else
1242 ALCbackendFactory *factory = CaptureBackend.getFactory();
1243 V(factory,probe)(type);
1246 UnlockLists();
1248 static void ProbeAllDevicesList(void)
1249 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1250 static void ProbeCaptureDeviceList(void)
1251 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1253 static void AppendDevice(const ALCchar *name, al_string *devnames)
1255 size_t len = strlen(name);
1256 if(len > 0)
1258 al_string_append_range(devnames, name, name+len);
1259 al_string_append_char(devnames, '\0');
1262 void AppendAllDevicesList(const ALCchar *name)
1263 { AppendDevice(name, &alcAllDevicesList); }
1264 void AppendCaptureDeviceList(const ALCchar *name)
1265 { AppendDevice(name, &alcCaptureDeviceList); }
1268 /************************************************
1269 * Device format information
1270 ************************************************/
1271 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1273 switch(type)
1275 case DevFmtByte: return "Signed Byte";
1276 case DevFmtUByte: return "Unsigned Byte";
1277 case DevFmtShort: return "Signed Short";
1278 case DevFmtUShort: return "Unsigned Short";
1279 case DevFmtInt: return "Signed Int";
1280 case DevFmtUInt: return "Unsigned Int";
1281 case DevFmtFloat: return "Float";
1283 return "(unknown type)";
1285 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1287 switch(chans)
1289 case DevFmtMono: return "Mono";
1290 case DevFmtStereo: return "Stereo";
1291 case DevFmtQuad: return "Quadraphonic";
1292 case DevFmtX51: return "5.1 Surround";
1293 case DevFmtX51Side: return "5.1 Side";
1294 case DevFmtX61: return "6.1 Surround";
1295 case DevFmtX71: return "7.1 Surround";
1297 return "(unknown channels)";
1300 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1301 ALuint BytesFromDevFmt(enum DevFmtType type)
1303 switch(type)
1305 case DevFmtByte: return sizeof(ALbyte);
1306 case DevFmtUByte: return sizeof(ALubyte);
1307 case DevFmtShort: return sizeof(ALshort);
1308 case DevFmtUShort: return sizeof(ALushort);
1309 case DevFmtInt: return sizeof(ALint);
1310 case DevFmtUInt: return sizeof(ALuint);
1311 case DevFmtFloat: return sizeof(ALfloat);
1313 return 0;
1315 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1317 switch(chans)
1319 case DevFmtMono: return 1;
1320 case DevFmtStereo: return 2;
1321 case DevFmtQuad: return 4;
1322 case DevFmtX51: return 6;
1323 case DevFmtX51Side: return 6;
1324 case DevFmtX61: return 7;
1325 case DevFmtX71: return 8;
1327 return 0;
1330 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1331 enum DevFmtType *type)
1333 static const struct {
1334 ALenum format;
1335 enum DevFmtChannels channels;
1336 enum DevFmtType type;
1337 } list[] = {
1338 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1339 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1340 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1342 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1343 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1344 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1346 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1347 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1348 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1350 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1351 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1352 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1354 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1355 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1356 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1358 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1359 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1360 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1362 ALuint i;
1364 for(i = 0;i < COUNTOF(list);i++)
1366 if(list[i].format == format)
1368 *chans = list[i].channels;
1369 *type = list[i].type;
1370 return AL_TRUE;
1374 return AL_FALSE;
1377 static ALCboolean IsValidALCType(ALCenum type)
1379 switch(type)
1381 case ALC_BYTE_SOFT:
1382 case ALC_UNSIGNED_BYTE_SOFT:
1383 case ALC_SHORT_SOFT:
1384 case ALC_UNSIGNED_SHORT_SOFT:
1385 case ALC_INT_SOFT:
1386 case ALC_UNSIGNED_INT_SOFT:
1387 case ALC_FLOAT_SOFT:
1388 return ALC_TRUE;
1390 return ALC_FALSE;
1393 static ALCboolean IsValidALCChannels(ALCenum channels)
1395 switch(channels)
1397 case ALC_MONO_SOFT:
1398 case ALC_STEREO_SOFT:
1399 case ALC_QUAD_SOFT:
1400 case ALC_5POINT1_SOFT:
1401 case ALC_6POINT1_SOFT:
1402 case ALC_7POINT1_SOFT:
1403 return ALC_TRUE;
1405 return ALC_FALSE;
1409 /************************************************
1410 * Miscellaneous ALC helpers
1411 ************************************************/
1412 extern inline void LockContext(ALCcontext *context);
1413 extern inline void UnlockContext(ALCcontext *context);
1415 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *UNUSED(device))
1417 return 0;
1420 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1422 return V0(device->Backend,getLatency)();
1425 void ALCdevice_Lock(ALCdevice *device)
1427 V0(device->Backend,lock)();
1430 void ALCdevice_Unlock(ALCdevice *device)
1432 V0(device->Backend,unlock)();
1436 /* SetDefaultWFXChannelOrder
1438 * Sets the default channel order used by WaveFormatEx.
1440 void SetDefaultWFXChannelOrder(ALCdevice *device)
1442 ALuint i;
1444 for(i = 0;i < MaxChannels;i++)
1445 device->ChannelOffsets[i] = INVALID_OFFSET;
1447 switch(device->FmtChans)
1449 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1450 break;
1451 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1452 device->ChannelOffsets[FrontRight] = 1;
1453 break;
1454 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1455 device->ChannelOffsets[FrontRight] = 1;
1456 device->ChannelOffsets[BackLeft] = 2;
1457 device->ChannelOffsets[BackRight] = 3;
1458 break;
1459 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1460 device->ChannelOffsets[FrontRight] = 1;
1461 device->ChannelOffsets[FrontCenter] = 2;
1462 device->ChannelOffsets[LFE] = 3;
1463 device->ChannelOffsets[BackLeft] = 4;
1464 device->ChannelOffsets[BackRight] = 5;
1465 break;
1466 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1467 device->ChannelOffsets[FrontRight] = 1;
1468 device->ChannelOffsets[FrontCenter] = 2;
1469 device->ChannelOffsets[LFE] = 3;
1470 device->ChannelOffsets[SideLeft] = 4;
1471 device->ChannelOffsets[SideRight] = 5;
1472 break;
1473 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1474 device->ChannelOffsets[FrontRight] = 1;
1475 device->ChannelOffsets[FrontCenter] = 2;
1476 device->ChannelOffsets[LFE] = 3;
1477 device->ChannelOffsets[BackCenter] = 4;
1478 device->ChannelOffsets[SideLeft] = 5;
1479 device->ChannelOffsets[SideRight] = 6;
1480 break;
1481 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1482 device->ChannelOffsets[FrontRight] = 1;
1483 device->ChannelOffsets[FrontCenter] = 2;
1484 device->ChannelOffsets[LFE] = 3;
1485 device->ChannelOffsets[BackLeft] = 4;
1486 device->ChannelOffsets[BackRight] = 5;
1487 device->ChannelOffsets[SideLeft] = 6;
1488 device->ChannelOffsets[SideRight] = 7;
1489 break;
1493 /* SetDefaultChannelOrder
1495 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1497 void SetDefaultChannelOrder(ALCdevice *device)
1499 ALuint i;
1501 for(i = 0;i < MaxChannels;i++)
1502 device->ChannelOffsets[i] = INVALID_OFFSET;
1504 switch(device->FmtChans)
1506 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1507 device->ChannelOffsets[FrontRight] = 1;
1508 device->ChannelOffsets[BackLeft] = 2;
1509 device->ChannelOffsets[BackRight] = 3;
1510 device->ChannelOffsets[FrontCenter] = 4;
1511 device->ChannelOffsets[LFE] = 5;
1512 return;
1513 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1514 device->ChannelOffsets[FrontRight] = 1;
1515 device->ChannelOffsets[BackLeft] = 2;
1516 device->ChannelOffsets[BackRight] = 3;
1517 device->ChannelOffsets[FrontCenter] = 4;
1518 device->ChannelOffsets[LFE] = 5;
1519 device->ChannelOffsets[SideLeft] = 6;
1520 device->ChannelOffsets[SideRight] = 7;
1521 return;
1523 /* Same as WFX order */
1524 case DevFmtMono:
1525 case DevFmtStereo:
1526 case DevFmtQuad:
1527 case DevFmtX51Side:
1528 case DevFmtX61:
1529 break;
1531 SetDefaultWFXChannelOrder(device);
1535 /* alcSetError
1537 * Stores the latest ALC device error
1539 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1541 if(TrapALCError)
1543 #ifdef _WIN32
1544 /* DebugBreak() will cause an exception if there is no debugger */
1545 if(IsDebuggerPresent())
1546 DebugBreak();
1547 #elif defined(SIGTRAP)
1548 raise(SIGTRAP);
1549 #endif
1552 if(device)
1553 device->LastError = errorCode;
1554 else
1555 LastNullDeviceError = errorCode;
1559 /* UpdateClockBase
1561 * Updates the device's base clock time with however many samples have been
1562 * done. This is used so frequency changes on the device don't cause the time
1563 * to jump forward or back.
1565 static inline void UpdateClockBase(ALCdevice *device)
1567 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1568 device->SamplesDone = 0;
1571 /* UpdateDeviceParams
1573 * Updates device parameters according to the attribute list (caller is
1574 * responsible for holding the list lock).
1576 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1578 ALCcontext *context;
1579 enum DevFmtChannels oldChans;
1580 enum DevFmtType oldType;
1581 ALCuint oldFreq;
1582 FPUCtl oldMode;
1584 // Check for attributes
1585 if(device->Type == Loopback)
1587 enum {
1588 GotFreq = 1<<0,
1589 GotChans = 1<<1,
1590 GotType = 1<<2,
1591 GotAll = GotFreq|GotChans|GotType
1593 ALCuint freq, numMono, numStereo, numSends;
1594 enum DevFmtChannels schans;
1595 enum DevFmtType stype;
1596 ALCuint attrIdx = 0;
1597 ALCint gotFmt = 0;
1599 if(!attrList)
1601 WARN("Missing attributes for loopback device\n");
1602 return ALC_INVALID_VALUE;
1605 numMono = device->NumMonoSources;
1606 numStereo = device->NumStereoSources;
1607 numSends = device->NumAuxSends;
1608 schans = device->FmtChans;
1609 stype = device->FmtType;
1610 freq = device->Frequency;
1612 while(attrList[attrIdx])
1614 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1616 ALCint val = attrList[attrIdx + 1];
1617 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1618 return ALC_INVALID_VALUE;
1619 schans = val;
1620 gotFmt |= GotChans;
1623 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1625 ALCint val = attrList[attrIdx + 1];
1626 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1627 return ALC_INVALID_VALUE;
1628 stype = val;
1629 gotFmt |= GotType;
1632 if(attrList[attrIdx] == ALC_FREQUENCY)
1634 freq = attrList[attrIdx + 1];
1635 if(freq < MIN_OUTPUT_RATE)
1636 return ALC_INVALID_VALUE;
1637 gotFmt |= GotFreq;
1640 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1642 numStereo = attrList[attrIdx + 1];
1643 if(numStereo > device->MaxNoOfSources)
1644 numStereo = device->MaxNoOfSources;
1646 numMono = device->MaxNoOfSources - numStereo;
1649 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1650 numSends = attrList[attrIdx + 1];
1652 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1654 if(attrList[attrIdx + 1] != ALC_FALSE)
1655 device->Flags |= DEVICE_HRTF_REQUEST;
1656 else
1657 device->Flags &= ~DEVICE_HRTF_REQUEST;
1660 attrIdx += 2;
1663 if(gotFmt != GotAll)
1665 WARN("Missing format for loopback device\n");
1666 return ALC_INVALID_VALUE;
1669 ConfigValueUInt(NULL, "sends", &numSends);
1670 numSends = minu(MAX_SENDS, numSends);
1672 if((device->Flags&DEVICE_RUNNING))
1673 V0(device->Backend,stop)();
1674 device->Flags &= ~DEVICE_RUNNING;
1676 if(freq != device->Frequency)
1677 UpdateClockBase(device);
1678 device->Frequency = freq;
1679 device->FmtChans = schans;
1680 device->FmtType = stype;
1681 device->NumMonoSources = numMono;
1682 device->NumStereoSources = numStereo;
1683 device->NumAuxSends = numSends;
1685 else if(attrList && attrList[0])
1687 ALCuint freq, numMono, numStereo, numSends;
1688 ALCuint attrIdx = 0;
1690 /* If a context is already running on the device, stop playback so the
1691 * device attributes can be updated. */
1692 if((device->Flags&DEVICE_RUNNING))
1693 V0(device->Backend,stop)();
1694 device->Flags &= ~DEVICE_RUNNING;
1696 freq = device->Frequency;
1697 numMono = device->NumMonoSources;
1698 numStereo = device->NumStereoSources;
1699 numSends = device->NumAuxSends;
1701 while(attrList[attrIdx])
1703 if(attrList[attrIdx] == ALC_FREQUENCY)
1705 freq = attrList[attrIdx + 1];
1706 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1709 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1711 numStereo = attrList[attrIdx + 1];
1712 if(numStereo > device->MaxNoOfSources)
1713 numStereo = device->MaxNoOfSources;
1715 numMono = device->MaxNoOfSources - numStereo;
1718 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1719 numSends = attrList[attrIdx + 1];
1721 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1723 if(attrList[attrIdx + 1] != ALC_FALSE)
1724 device->Flags |= DEVICE_HRTF_REQUEST;
1725 else
1726 device->Flags &= ~DEVICE_HRTF_REQUEST;
1729 attrIdx += 2;
1732 ConfigValueUInt(NULL, "frequency", &freq);
1733 freq = maxu(freq, MIN_OUTPUT_RATE);
1735 ConfigValueUInt(NULL, "sends", &numSends);
1736 numSends = minu(MAX_SENDS, numSends);
1738 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1739 device->Frequency;
1740 /* SSE and Neon do best with the update size being a multiple of 4 */
1741 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1742 device->UpdateSize = (device->UpdateSize+3)&~3;
1744 if(freq != device->Frequency)
1745 UpdateClockBase(device);
1746 device->Frequency = freq;
1747 device->NumMonoSources = numMono;
1748 device->NumStereoSources = numStereo;
1749 device->NumAuxSends = numSends;
1752 if((device->Flags&DEVICE_RUNNING))
1753 return ALC_NO_ERROR;
1755 UpdateClockBase(device);
1757 oldFreq = device->Frequency;
1758 oldChans = device->FmtChans;
1759 oldType = device->FmtType;
1761 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1762 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1763 DevFmtChannelsString(device->FmtChans),
1764 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1765 DevFmtTypeString(device->FmtType),
1766 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1767 device->Frequency,
1768 device->UpdateSize, device->NumUpdates);
1770 if(device->Type != Loopback)
1772 int nohrtf = !(device->Flags&DEVICE_HRTF_REQUEST);
1773 if(GetConfigValueBool(NULL, "hrtf", !nohrtf))
1774 device->Flags |= DEVICE_HRTF_REQUEST;
1775 else
1776 device->Flags &= ~DEVICE_HRTF_REQUEST;
1778 if((device->Flags&DEVICE_HRTF_REQUEST))
1780 enum DevFmtChannels chans;
1781 ALCuint freq;
1782 if(FindHrtfFormat(device, &chans, &freq))
1784 device->Frequency = freq;
1785 device->FmtChans = chans;
1786 device->Flags |= DEVICE_CHANNELS_REQUEST |
1787 DEVICE_FREQUENCY_REQUEST;
1791 if(V0(device->Backend,reset)() == ALC_FALSE)
1792 return ALC_INVALID_DEVICE;
1794 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1796 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1797 DevFmtChannelsString(device->FmtChans));
1798 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1800 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1802 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1803 DevFmtTypeString(device->FmtType));
1804 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1806 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1808 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1809 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1812 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1813 DevFmtChannelsString(device->FmtChans),
1814 DevFmtTypeString(device->FmtType), device->Frequency,
1815 device->UpdateSize, device->NumUpdates);
1817 aluInitPanning(device);
1819 V(device->Synth,update)(device);
1821 device->Hrtf = NULL;
1822 if((device->Flags&DEVICE_HRTF_REQUEST))
1824 device->Hrtf = GetHrtf(device);
1825 if(!device->Hrtf)
1826 device->Flags &= ~DEVICE_HRTF_REQUEST;
1828 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1830 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1832 if(!device->Bs2b)
1834 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1835 bs2b_clear(device->Bs2b);
1837 bs2b_set_srate(device->Bs2b, device->Frequency);
1838 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1839 TRACE("BS2B level %d\n", device->Bs2bLevel);
1841 else
1843 free(device->Bs2b);
1844 device->Bs2b = NULL;
1845 TRACE("BS2B disabled\n");
1848 device->Flags &= ~DEVICE_WIDE_STEREO;
1849 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1850 device->Flags |= DEVICE_WIDE_STEREO;
1852 if(!device->Hrtf && (device->UpdateSize&3))
1854 if((CPUCapFlags&CPU_CAP_SSE))
1855 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1856 if((CPUCapFlags&CPU_CAP_NEON))
1857 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1860 SetMixerFPUMode(&oldMode);
1861 ALCdevice_Lock(device);
1862 context = device->ContextList;
1863 while(context)
1865 ALsizei pos;
1867 context->UpdateSources = AL_FALSE;
1868 LockUIntMapRead(&context->EffectSlotMap);
1869 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1871 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1873 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1875 UnlockUIntMapRead(&context->EffectSlotMap);
1876 ALCdevice_Unlock(device);
1877 RestoreFPUMode(&oldMode);
1878 return ALC_INVALID_DEVICE;
1880 slot->NeedsUpdate = AL_FALSE;
1881 V(slot->EffectState,update)(device, slot);
1883 UnlockUIntMapRead(&context->EffectSlotMap);
1885 LockUIntMapRead(&context->SourceMap);
1886 for(pos = 0;pos < context->SourceMap.size;pos++)
1888 ALsource *source = context->SourceMap.array[pos].value;
1889 ALuint s = device->NumAuxSends;
1890 while(s < MAX_SENDS)
1892 if(source->Send[s].Slot)
1893 DecrementRef(&source->Send[s].Slot->ref);
1894 source->Send[s].Slot = NULL;
1895 source->Send[s].Gain = 1.0f;
1896 source->Send[s].GainHF = 1.0f;
1897 s++;
1899 source->NeedsUpdate = AL_TRUE;
1901 UnlockUIntMapRead(&context->SourceMap);
1903 for(pos = 0;pos < context->ActiveSourceCount;pos++)
1905 ALactivesource *src = context->ActiveSources[pos];
1906 ALsource *source = src->Source;
1907 ALuint s = device->NumAuxSends;
1908 while(s < MAX_SENDS)
1910 src->Send[s].Moving = AL_FALSE;
1911 src->Send[s].Counter = 0;
1912 s++;
1915 src->Update(src, context);
1916 source->NeedsUpdate = AL_FALSE;
1919 context = context->next;
1921 if(device->DefaultSlot)
1923 ALeffectslot *slot = device->DefaultSlot;
1925 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1927 ALCdevice_Unlock(device);
1928 RestoreFPUMode(&oldMode);
1929 return ALC_INVALID_DEVICE;
1931 slot->NeedsUpdate = AL_FALSE;
1932 V(slot->EffectState,update)(device, slot);
1934 ALCdevice_Unlock(device);
1935 RestoreFPUMode(&oldMode);
1937 if(!(device->Flags&DEVICE_PAUSED))
1939 if(V0(device->Backend,start)() == ALC_FALSE)
1940 return ALC_INVALID_DEVICE;
1941 device->Flags |= DEVICE_RUNNING;
1944 return ALC_NO_ERROR;
1947 /* FreeDevice
1949 * Frees the device structure, and destroys any objects the app failed to
1950 * delete. Called once there's no more references on the device.
1952 static ALCvoid FreeDevice(ALCdevice *device)
1954 TRACE("%p\n", device);
1956 V0(device->Backend,close)();
1957 DELETE_OBJ(device->Backend);
1958 device->Backend = NULL;
1960 DELETE_OBJ(device->Synth);
1961 device->Synth = NULL;
1963 if(device->DefaultSlot)
1965 ALeffectState *state = device->DefaultSlot->EffectState;
1966 device->DefaultSlot = NULL;
1967 DELETE_OBJ(state);
1970 if(device->DefaultSfont)
1971 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1972 device->DefaultSfont = NULL;
1974 if(device->BufferMap.size > 0)
1976 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1977 ReleaseALBuffers(device);
1979 ResetUIntMap(&device->BufferMap);
1981 if(device->EffectMap.size > 0)
1983 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
1984 ReleaseALEffects(device);
1986 ResetUIntMap(&device->EffectMap);
1988 if(device->FilterMap.size > 0)
1990 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
1991 ReleaseALFilters(device);
1993 ResetUIntMap(&device->FilterMap);
1995 if(device->SfontMap.size > 0)
1997 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
1998 ReleaseALSoundfonts(device);
2000 ResetUIntMap(&device->SfontMap);
2002 if(device->PresetMap.size > 0)
2004 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2005 ReleaseALPresets(device);
2007 ResetUIntMap(&device->PresetMap);
2009 if(device->FontsoundMap.size > 0)
2011 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2012 ReleaseALFontsounds(device);
2014 ResetUIntMap(&device->FontsoundMap);
2016 free(device->Bs2b);
2017 device->Bs2b = NULL;
2019 AL_STRING_DEINIT(device->DeviceName);
2021 al_free(device);
2025 void ALCdevice_IncRef(ALCdevice *device)
2027 RefCount ref;
2028 ref = IncrementRef(&device->ref);
2029 TRACEREF("%p increasing refcount to %u\n", device, ref);
2032 void ALCdevice_DecRef(ALCdevice *device)
2034 RefCount ref;
2035 ref = DecrementRef(&device->ref);
2036 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2037 if(ref == 0) FreeDevice(device);
2040 /* VerifyDevice
2042 * Checks if the device handle is valid, and increments its ref count if so.
2044 static ALCdevice *VerifyDevice(ALCdevice *device)
2046 ALCdevice *tmpDevice;
2048 if(!device)
2049 return NULL;
2051 LockLists();
2052 tmpDevice = DeviceList;
2053 while(tmpDevice && tmpDevice != device)
2054 tmpDevice = tmpDevice->next;
2056 if(tmpDevice)
2057 ALCdevice_IncRef(tmpDevice);
2058 UnlockLists();
2059 return tmpDevice;
2063 /* InitContext
2065 * Initializes context fields
2067 static ALvoid InitContext(ALCcontext *Context)
2069 ALint i, j;
2071 //Initialise listener
2072 Context->Listener->Gain = 1.0f;
2073 Context->Listener->MetersPerUnit = 1.0f;
2074 Context->Listener->Position[0] = 0.0f;
2075 Context->Listener->Position[1] = 0.0f;
2076 Context->Listener->Position[2] = 0.0f;
2077 Context->Listener->Velocity[0] = 0.0f;
2078 Context->Listener->Velocity[1] = 0.0f;
2079 Context->Listener->Velocity[2] = 0.0f;
2080 Context->Listener->Forward[0] = 0.0f;
2081 Context->Listener->Forward[1] = 0.0f;
2082 Context->Listener->Forward[2] = -1.0f;
2083 Context->Listener->Up[0] = 0.0f;
2084 Context->Listener->Up[1] = 1.0f;
2085 Context->Listener->Up[2] = 0.0f;
2086 for(i = 0;i < 4;i++)
2088 for(j = 0;j < 4;j++)
2089 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2091 for(i = 0;i < 3;i++)
2092 Context->Listener->Params.Velocity[i] = 0.0f;
2094 //Validate Context
2095 Context->LastError = AL_NO_ERROR;
2096 Context->UpdateSources = AL_FALSE;
2097 Context->ActiveSourceCount = 0;
2098 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2099 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2101 //Set globals
2102 Context->DistanceModel = DefaultDistanceModel;
2103 Context->SourceDistanceModel = AL_FALSE;
2104 Context->DopplerFactor = 1.0f;
2105 Context->DopplerVelocity = 1.0f;
2106 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2107 Context->DeferUpdates = AL_FALSE;
2109 Context->ExtensionList = alExtList;
2113 /* FreeContext
2115 * Cleans up the context, and destroys any remaining objects the app failed to
2116 * delete. Called once there's no more references on the context.
2118 static ALCvoid FreeContext(ALCcontext *context)
2120 ALsizei i;
2122 TRACE("%p\n", context);
2124 if(context->SourceMap.size > 0)
2126 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2127 ReleaseALSources(context);
2129 ResetUIntMap(&context->SourceMap);
2131 if(context->EffectSlotMap.size > 0)
2133 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2134 ReleaseALAuxiliaryEffectSlots(context);
2136 ResetUIntMap(&context->EffectSlotMap);
2138 for(i = 0;i < context->MaxActiveSources;i++)
2140 al_free(context->ActiveSources[i]);
2141 context->ActiveSources[i] = NULL;
2143 free(context->ActiveSources);
2144 context->ActiveSources = NULL;
2145 context->ActiveSourceCount = 0;
2146 context->MaxActiveSources = 0;
2148 VECTOR_DEINIT(context->ActiveAuxSlots);
2150 ALCdevice_DecRef(context->Device);
2151 context->Device = NULL;
2153 //Invalidate context
2154 memset(context, 0, sizeof(ALCcontext));
2155 free(context);
2158 /* ReleaseContext
2160 * Removes the context reference from the given device and removes it from
2161 * being current on the running thread or globally.
2163 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2165 ALCcontext *volatile*tmp_ctx;
2167 if(altss_get(LocalContext) == context)
2169 WARN("%p released while current on thread\n", context);
2170 altss_set(LocalContext, NULL);
2171 ALCcontext_DecRef(context);
2174 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL) == context)
2175 ALCcontext_DecRef(context);
2177 ALCdevice_Lock(device);
2178 tmp_ctx = &device->ContextList;
2179 while(*tmp_ctx)
2181 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next) == context)
2182 break;
2183 tmp_ctx = &(*tmp_ctx)->next;
2185 ALCdevice_Unlock(device);
2187 ALCcontext_DecRef(context);
2190 void ALCcontext_IncRef(ALCcontext *context)
2192 RefCount ref;
2193 ref = IncrementRef(&context->ref);
2194 TRACEREF("%p increasing refcount to %u\n", context, ref);
2197 void ALCcontext_DecRef(ALCcontext *context)
2199 RefCount ref;
2200 ref = DecrementRef(&context->ref);
2201 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2202 if(ref == 0) FreeContext(context);
2205 static void ReleaseThreadCtx(void *ptr)
2207 WARN("%p current for thread being destroyed\n", ptr);
2208 ALCcontext_DecRef(ptr);
2211 /* VerifyContext
2213 * Checks that the given context is valid, and increments its reference count.
2215 static ALCcontext *VerifyContext(ALCcontext *context)
2217 ALCdevice *dev;
2219 LockLists();
2220 dev = DeviceList;
2221 while(dev)
2223 ALCcontext *tmp_ctx = dev->ContextList;
2224 while(tmp_ctx)
2226 if(tmp_ctx == context)
2228 ALCcontext_IncRef(tmp_ctx);
2229 UnlockLists();
2230 return tmp_ctx;
2232 tmp_ctx = tmp_ctx->next;
2234 dev = dev->next;
2236 UnlockLists();
2238 return NULL;
2242 /* GetContextRef
2244 * Returns the currently active context for this thread, and adds a reference
2245 * without locking it.
2247 ALCcontext *GetContextRef(void)
2249 ALCcontext *context;
2251 context = altss_get(LocalContext);
2252 if(context)
2253 ALCcontext_IncRef(context);
2254 else
2256 LockLists();
2257 context = GlobalContext;
2258 if(context)
2259 ALCcontext_IncRef(context);
2260 UnlockLists();
2263 return context;
2267 /************************************************
2268 * Standard ALC functions
2269 ************************************************/
2271 /* alcGetError
2273 * Return last ALC generated error code for the given device
2275 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2277 ALCenum errorCode;
2279 if(VerifyDevice(device))
2281 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2282 ALCdevice_DecRef(device);
2284 else
2285 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2287 return errorCode;
2291 /* alcSuspendContext
2293 * Not functional
2295 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2299 /* alcProcessContext
2301 * Not functional
2303 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2308 /* alcGetString
2310 * Returns information about the device, and error strings
2312 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2314 const ALCchar *value = NULL;
2316 switch(param)
2318 case ALC_NO_ERROR:
2319 value = alcNoError;
2320 break;
2322 case ALC_INVALID_ENUM:
2323 value = alcErrInvalidEnum;
2324 break;
2326 case ALC_INVALID_VALUE:
2327 value = alcErrInvalidValue;
2328 break;
2330 case ALC_INVALID_DEVICE:
2331 value = alcErrInvalidDevice;
2332 break;
2334 case ALC_INVALID_CONTEXT:
2335 value = alcErrInvalidContext;
2336 break;
2338 case ALC_OUT_OF_MEMORY:
2339 value = alcErrOutOfMemory;
2340 break;
2342 case ALC_DEVICE_SPECIFIER:
2343 value = alcDefaultName;
2344 break;
2346 case ALC_ALL_DEVICES_SPECIFIER:
2347 if(VerifyDevice(Device))
2349 value = al_string_get_cstr(Device->DeviceName);
2350 ALCdevice_DecRef(Device);
2352 else
2354 ProbeAllDevicesList();
2355 value = al_string_get_cstr(alcAllDevicesList);
2357 break;
2359 case ALC_CAPTURE_DEVICE_SPECIFIER:
2360 if(VerifyDevice(Device))
2362 value = al_string_get_cstr(Device->DeviceName);
2363 ALCdevice_DecRef(Device);
2365 else
2367 ProbeCaptureDeviceList();
2368 value = al_string_get_cstr(alcCaptureDeviceList);
2370 break;
2372 /* Default devices are always first in the list */
2373 case ALC_DEFAULT_DEVICE_SPECIFIER:
2374 value = alcDefaultName;
2375 break;
2377 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2378 if(al_string_empty(alcAllDevicesList))
2379 ProbeAllDevicesList();
2381 Device = VerifyDevice(Device);
2383 free(alcDefaultAllDevicesSpecifier);
2384 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2385 if(!alcDefaultAllDevicesSpecifier)
2386 alcSetError(Device, ALC_OUT_OF_MEMORY);
2388 value = alcDefaultAllDevicesSpecifier;
2389 if(Device) ALCdevice_DecRef(Device);
2390 break;
2392 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2393 if(al_string_empty(alcCaptureDeviceList))
2394 ProbeCaptureDeviceList();
2396 Device = VerifyDevice(Device);
2398 free(alcCaptureDefaultDeviceSpecifier);
2399 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2400 if(!alcCaptureDefaultDeviceSpecifier)
2401 alcSetError(Device, ALC_OUT_OF_MEMORY);
2403 value = alcCaptureDefaultDeviceSpecifier;
2404 if(Device) ALCdevice_DecRef(Device);
2405 break;
2407 case ALC_EXTENSIONS:
2408 if(!VerifyDevice(Device))
2409 value = alcNoDeviceExtList;
2410 else
2412 value = alcExtensionList;
2413 ALCdevice_DecRef(Device);
2415 break;
2417 default:
2418 Device = VerifyDevice(Device);
2419 alcSetError(Device, ALC_INVALID_ENUM);
2420 if(Device) ALCdevice_DecRef(Device);
2421 break;
2424 return value;
2428 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2430 ALCsizei i;
2432 if(size <= 0 || values == NULL)
2434 alcSetError(device, ALC_INVALID_VALUE);
2435 return 0;
2438 if(!device)
2440 switch(param)
2442 case ALC_MAJOR_VERSION:
2443 values[0] = alcMajorVersion;
2444 return 1;
2445 case ALC_MINOR_VERSION:
2446 values[0] = alcMinorVersion;
2447 return 1;
2449 case ALC_ATTRIBUTES_SIZE:
2450 case ALC_ALL_ATTRIBUTES:
2451 case ALC_FREQUENCY:
2452 case ALC_REFRESH:
2453 case ALC_SYNC:
2454 case ALC_MONO_SOURCES:
2455 case ALC_STEREO_SOURCES:
2456 case ALC_CAPTURE_SAMPLES:
2457 case ALC_FORMAT_CHANNELS_SOFT:
2458 case ALC_FORMAT_TYPE_SOFT:
2459 alcSetError(NULL, ALC_INVALID_DEVICE);
2460 return 0;
2462 default:
2463 alcSetError(NULL, ALC_INVALID_ENUM);
2464 return 0;
2466 return 0;
2469 if(device->Type == Capture)
2471 switch(param)
2473 case ALC_CAPTURE_SAMPLES:
2474 ALCdevice_Lock(device);
2475 values[0] = V0(device->Backend,availableSamples)();
2476 ALCdevice_Unlock(device);
2477 return 1;
2479 case ALC_CONNECTED:
2480 values[0] = device->Connected;
2481 return 1;
2483 default:
2484 alcSetError(device, ALC_INVALID_ENUM);
2485 return 0;
2487 return 0;
2490 /* render device */
2491 switch(param)
2493 case ALC_MAJOR_VERSION:
2494 values[0] = alcMajorVersion;
2495 return 1;
2497 case ALC_MINOR_VERSION:
2498 values[0] = alcMinorVersion;
2499 return 1;
2501 case ALC_EFX_MAJOR_VERSION:
2502 values[0] = alcEFXMajorVersion;
2503 return 1;
2505 case ALC_EFX_MINOR_VERSION:
2506 values[0] = alcEFXMinorVersion;
2507 return 1;
2509 case ALC_ATTRIBUTES_SIZE:
2510 values[0] = 15;
2511 return 1;
2513 case ALC_ALL_ATTRIBUTES:
2514 if(size < 15)
2516 alcSetError(device, ALC_INVALID_VALUE);
2517 return 0;
2520 i = 0;
2521 values[i++] = ALC_FREQUENCY;
2522 values[i++] = device->Frequency;
2524 if(device->Type != Loopback)
2526 values[i++] = ALC_REFRESH;
2527 values[i++] = device->Frequency / device->UpdateSize;
2529 values[i++] = ALC_SYNC;
2530 values[i++] = ALC_FALSE;
2532 else
2534 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2535 values[i++] = device->FmtChans;
2537 values[i++] = ALC_FORMAT_TYPE_SOFT;
2538 values[i++] = device->FmtType;
2541 values[i++] = ALC_MONO_SOURCES;
2542 values[i++] = device->NumMonoSources;
2544 values[i++] = ALC_STEREO_SOURCES;
2545 values[i++] = device->NumStereoSources;
2547 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2548 values[i++] = device->NumAuxSends;
2550 values[i++] = ALC_HRTF_SOFT;
2551 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2553 values[i++] = 0;
2554 return i;
2556 case ALC_FREQUENCY:
2557 values[0] = device->Frequency;
2558 return 1;
2560 case ALC_REFRESH:
2561 if(device->Type == Loopback)
2563 alcSetError(device, ALC_INVALID_DEVICE);
2564 return 0;
2566 values[0] = device->Frequency / device->UpdateSize;
2567 return 1;
2569 case ALC_SYNC:
2570 if(device->Type == Loopback)
2572 alcSetError(device, ALC_INVALID_DEVICE);
2573 return 0;
2575 values[0] = ALC_FALSE;
2576 return 1;
2578 case ALC_FORMAT_CHANNELS_SOFT:
2579 if(device->Type != Loopback)
2581 alcSetError(device, ALC_INVALID_DEVICE);
2582 return 0;
2584 values[0] = device->FmtChans;
2585 return 1;
2587 case ALC_FORMAT_TYPE_SOFT:
2588 if(device->Type != Loopback)
2590 alcSetError(device, ALC_INVALID_DEVICE);
2591 return 0;
2593 values[0] = device->FmtType;
2594 return 1;
2596 case ALC_MONO_SOURCES:
2597 values[0] = device->NumMonoSources;
2598 return 1;
2600 case ALC_STEREO_SOURCES:
2601 values[0] = device->NumStereoSources;
2602 return 1;
2604 case ALC_MAX_AUXILIARY_SENDS:
2605 values[0] = device->NumAuxSends;
2606 return 1;
2608 case ALC_CONNECTED:
2609 values[0] = device->Connected;
2610 return 1;
2612 case ALC_HRTF_SOFT:
2613 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2614 return 1;
2616 default:
2617 alcSetError(device, ALC_INVALID_ENUM);
2618 return 0;
2620 return 0;
2623 /* alcGetIntegerv
2625 * Returns information about the device and the version of OpenAL
2627 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2629 device = VerifyDevice(device);
2630 if(size <= 0 || values == NULL)
2631 alcSetError(device, ALC_INVALID_VALUE);
2632 else
2633 GetIntegerv(device, param, size, values);
2634 if(device) ALCdevice_DecRef(device);
2637 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2639 ALCint *ivals;
2640 ALsizei i;
2642 device = VerifyDevice(device);
2643 if(size <= 0 || values == NULL)
2644 alcSetError(device, ALC_INVALID_VALUE);
2645 else if(!device || device->Type == Capture)
2647 ivals = malloc(size * sizeof(ALCint));
2648 size = GetIntegerv(device, pname, size, ivals);
2649 for(i = 0;i < size;i++)
2650 values[i] = ivals[i];
2651 free(ivals);
2653 else /* render device */
2655 switch(pname)
2657 case ALC_ATTRIBUTES_SIZE:
2658 *values = 17;
2659 break;
2661 case ALC_ALL_ATTRIBUTES:
2662 if(size < 17)
2663 alcSetError(device, ALC_INVALID_VALUE);
2664 else
2666 int i = 0;
2668 V0(device->Backend,lock)();
2669 values[i++] = ALC_FREQUENCY;
2670 values[i++] = device->Frequency;
2672 if(device->Type != Loopback)
2674 values[i++] = ALC_REFRESH;
2675 values[i++] = device->Frequency / device->UpdateSize;
2677 values[i++] = ALC_SYNC;
2678 values[i++] = ALC_FALSE;
2680 else
2682 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2683 values[i++] = device->FmtChans;
2685 values[i++] = ALC_FORMAT_TYPE_SOFT;
2686 values[i++] = device->FmtType;
2689 values[i++] = ALC_MONO_SOURCES;
2690 values[i++] = device->NumMonoSources;
2692 values[i++] = ALC_STEREO_SOURCES;
2693 values[i++] = device->NumStereoSources;
2695 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2696 values[i++] = device->NumAuxSends;
2698 values[i++] = ALC_HRTF_SOFT;
2699 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2701 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2702 values[i++] = device->ClockBase +
2703 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2705 values[i++] = 0;
2706 V0(device->Backend,unlock)();
2708 break;
2710 case ALC_DEVICE_CLOCK_SOFT:
2711 V0(device->Backend,lock)();
2712 *values = device->ClockBase +
2713 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2714 V0(device->Backend,unlock)();
2715 break;
2717 default:
2718 ivals = malloc(size * sizeof(ALCint));
2719 size = GetIntegerv(device, pname, size, ivals);
2720 for(i = 0;i < size;i++)
2721 values[i] = ivals[i];
2722 free(ivals);
2723 break;
2726 if(device)
2727 ALCdevice_DecRef(device);
2731 /* alcIsExtensionPresent
2733 * Determines if there is support for a particular extension
2735 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2737 ALCboolean bResult = ALC_FALSE;
2739 device = VerifyDevice(device);
2741 if(!extName)
2742 alcSetError(device, ALC_INVALID_VALUE);
2743 else
2745 size_t len = strlen(extName);
2746 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2747 while(ptr && *ptr)
2749 if(strncasecmp(ptr, extName, len) == 0 &&
2750 (ptr[len] == '\0' || isspace(ptr[len])))
2752 bResult = ALC_TRUE;
2753 break;
2755 if((ptr=strchr(ptr, ' ')) != NULL)
2757 do {
2758 ++ptr;
2759 } while(isspace(*ptr));
2763 if(device)
2764 ALCdevice_DecRef(device);
2765 return bResult;
2769 /* alcGetProcAddress
2771 * Retrieves the function address for a particular extension function
2773 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2775 ALCvoid *ptr = NULL;
2777 if(!funcName)
2779 device = VerifyDevice(device);
2780 alcSetError(device, ALC_INVALID_VALUE);
2781 if(device) ALCdevice_DecRef(device);
2783 else
2785 ALsizei i = 0;
2786 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2787 i++;
2788 ptr = alcFunctions[i].address;
2791 return ptr;
2795 /* alcGetEnumValue
2797 * Get the value for a particular ALC enumeration name
2799 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2801 ALCenum val = 0;
2803 if(!enumName)
2805 device = VerifyDevice(device);
2806 alcSetError(device, ALC_INVALID_VALUE);
2807 if(device) ALCdevice_DecRef(device);
2809 else
2811 ALsizei i = 0;
2812 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2813 i++;
2814 val = enumeration[i].value;
2817 return val;
2821 /* alcCreateContext
2823 * Create and attach a context to the given device.
2825 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2827 ALCcontext *ALContext;
2828 ALCenum err;
2830 LockLists();
2831 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2833 UnlockLists();
2834 alcSetError(device, ALC_INVALID_DEVICE);
2835 if(device) ALCdevice_DecRef(device);
2836 return NULL;
2839 device->LastError = ALC_NO_ERROR;
2841 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2843 UnlockLists();
2844 alcSetError(device, err);
2845 if(err == ALC_INVALID_DEVICE)
2847 ALCdevice_Lock(device);
2848 aluHandleDisconnect(device);
2849 ALCdevice_Unlock(device);
2851 ALCdevice_DecRef(device);
2852 return NULL;
2855 ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener));
2856 if(ALContext)
2858 ALContext->ref = 1;
2859 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2861 VECTOR_INIT(ALContext->ActiveAuxSlots);
2863 ALContext->MaxActiveSources = 256;
2864 ALContext->ActiveSources = calloc(ALContext->MaxActiveSources,
2865 sizeof(ALContext->ActiveSources[0]));
2867 if(!ALContext || !ALContext->ActiveSources)
2869 if(!device->ContextList)
2871 V0(device->Backend,stop)();
2872 device->Flags &= ~DEVICE_RUNNING;
2874 UnlockLists();
2876 if(ALContext)
2878 free(ALContext->ActiveSources);
2879 ALContext->ActiveSources = NULL;
2881 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2883 free(ALContext);
2884 ALContext = NULL;
2887 alcSetError(device, ALC_OUT_OF_MEMORY);
2888 ALCdevice_DecRef(device);
2889 return NULL;
2892 ALContext->Device = device;
2893 ALCdevice_IncRef(device);
2894 InitContext(ALContext);
2896 do {
2897 ALContext->next = device->ContextList;
2898 } while(CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext) != ALContext->next);
2899 UnlockLists();
2901 ALCdevice_DecRef(device);
2903 TRACE("Created context %p\n", ALContext);
2904 return ALContext;
2907 /* alcDestroyContext
2909 * Remove a context from its device
2911 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2913 ALCdevice *Device;
2915 LockLists();
2916 /* alcGetContextsDevice sets an error for invalid contexts */
2917 Device = alcGetContextsDevice(context);
2918 if(Device)
2920 ReleaseContext(context, Device);
2921 if(!Device->ContextList)
2923 V0(Device->Backend,stop)();
2924 Device->Flags &= ~DEVICE_RUNNING;
2927 UnlockLists();
2931 /* alcGetCurrentContext
2933 * Returns the currently active context on the calling thread
2935 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2937 ALCcontext *Context;
2939 Context = altss_get(LocalContext);
2940 if(!Context) Context = GlobalContext;
2942 return Context;
2945 /* alcGetThreadContext
2947 * Returns the currently active thread-local context
2949 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2951 ALCcontext *Context;
2952 Context = altss_get(LocalContext);
2953 return Context;
2957 /* alcMakeContextCurrent
2959 * Makes the given context the active process-wide context, and removes the
2960 * thread-local context for the calling thread.
2962 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2964 /* context must be valid or NULL */
2965 if(context && !(context=VerifyContext(context)))
2967 alcSetError(NULL, ALC_INVALID_CONTEXT);
2968 return ALC_FALSE;
2970 /* context's reference count is already incremented */
2971 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2972 if(context) ALCcontext_DecRef(context);
2974 if((context=altss_get(LocalContext)) != NULL)
2976 altss_set(LocalContext, NULL);
2977 ALCcontext_DecRef(context);
2980 return ALC_TRUE;
2983 /* alcSetThreadContext
2985 * Makes the given context the active context for the current thread
2987 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
2989 ALCcontext *old;
2991 /* context must be valid or NULL */
2992 if(context && !(context=VerifyContext(context)))
2994 alcSetError(NULL, ALC_INVALID_CONTEXT);
2995 return ALC_FALSE;
2997 /* context's reference count is already incremented */
2998 old = altss_get(LocalContext);
2999 altss_set(LocalContext, context);
3000 if(old) ALCcontext_DecRef(old);
3002 return ALC_TRUE;
3006 /* alcGetContextsDevice
3008 * Returns the device that a particular context is attached to
3010 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3012 ALCdevice *Device;
3014 if(!(Context=VerifyContext(Context)))
3016 alcSetError(NULL, ALC_INVALID_CONTEXT);
3017 return NULL;
3019 Device = Context->Device;
3020 ALCcontext_DecRef(Context);
3022 return Device;
3026 /* alcOpenDevice
3028 * Opens the named device.
3030 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3032 const ALCchar *fmt;
3033 ALCdevice *device;
3034 ALCenum err;
3036 DO_INITCONFIG();
3038 if(!PlaybackBackend.name)
3040 alcSetError(NULL, ALC_INVALID_VALUE);
3041 return NULL;
3044 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3045 deviceName = NULL;
3047 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3048 if(!device)
3050 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3051 return NULL;
3054 //Validate device
3055 device->ref = 1;
3056 device->Connected = ALC_TRUE;
3057 device->Type = Playback;
3058 device->LastError = ALC_NO_ERROR;
3060 device->Flags = 0;
3061 device->Bs2b = NULL;
3062 device->Bs2bLevel = 0;
3063 AL_STRING_INIT(device->DeviceName);
3065 device->ContextList = NULL;
3067 device->ClockBase = 0;
3068 device->SamplesDone = 0;
3070 device->MaxNoOfSources = 256;
3071 device->AuxiliaryEffectSlotMax = 4;
3072 device->NumAuxSends = MAX_SENDS;
3074 InitUIntMap(&device->BufferMap, ~0);
3075 InitUIntMap(&device->EffectMap, ~0);
3076 InitUIntMap(&device->FilterMap, ~0);
3077 InitUIntMap(&device->SfontMap, ~0);
3078 InitUIntMap(&device->PresetMap, ~0);
3079 InitUIntMap(&device->FontsoundMap, ~0);
3081 //Set output format
3082 device->FmtChans = DevFmtChannelsDefault;
3083 device->FmtType = DevFmtTypeDefault;
3084 device->Frequency = DEFAULT_OUTPUT_RATE;
3085 device->NumUpdates = 4;
3086 device->UpdateSize = 1024;
3088 if(!PlaybackBackend.getFactory)
3089 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3090 ALCbackend_Playback);
3091 else
3093 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3094 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3096 if(!device->Backend)
3098 al_free(device);
3099 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3100 return NULL;
3104 if(ConfigValueStr(NULL, "channels", &fmt))
3106 static const struct {
3107 const char name[16];
3108 enum DevFmtChannels chans;
3109 } chanlist[] = {
3110 { "mono", DevFmtMono },
3111 { "stereo", DevFmtStereo },
3112 { "quad", DevFmtQuad },
3113 { "surround51", DevFmtX51 },
3114 { "surround61", DevFmtX61 },
3115 { "surround71", DevFmtX71 },
3117 size_t i;
3119 for(i = 0;i < COUNTOF(chanlist);i++)
3121 if(strcasecmp(chanlist[i].name, fmt) == 0)
3123 device->FmtChans = chanlist[i].chans;
3124 device->Flags |= DEVICE_CHANNELS_REQUEST;
3125 break;
3128 if(i == COUNTOF(chanlist))
3129 ERR("Unsupported channels: %s\n", fmt);
3131 if(ConfigValueStr(NULL, "sample-type", &fmt))
3133 static const struct {
3134 const char name[16];
3135 enum DevFmtType type;
3136 } typelist[] = {
3137 { "int8", DevFmtByte },
3138 { "uint8", DevFmtUByte },
3139 { "int16", DevFmtShort },
3140 { "uint16", DevFmtUShort },
3141 { "int32", DevFmtInt },
3142 { "uint32", DevFmtUInt },
3143 { "float32", DevFmtFloat },
3145 size_t i;
3147 for(i = 0;i < COUNTOF(typelist);i++)
3149 if(strcasecmp(typelist[i].name, fmt) == 0)
3151 device->FmtType = typelist[i].type;
3152 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3153 break;
3156 if(i == COUNTOF(typelist))
3157 ERR("Unsupported sample-type: %s\n", fmt);
3159 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3160 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3161 ConfigValueStr(NULL, "format", &fmt))
3163 static const struct {
3164 const char name[32];
3165 enum DevFmtChannels channels;
3166 enum DevFmtType type;
3167 } formats[] = {
3168 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3169 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3170 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3171 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3172 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3173 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3175 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3176 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3177 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3178 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3179 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3180 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3182 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3183 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3184 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3185 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3186 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3187 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3189 size_t i;
3191 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3192 for(i = 0;i < COUNTOF(formats);i++)
3194 if(strcasecmp(fmt, formats[i].name) == 0)
3196 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3197 device->FmtChans = formats[i].channels;
3198 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3199 device->FmtType = formats[i].type;
3200 device->Flags |= DEVICE_FORMAT_REQUEST;
3201 break;
3204 if(i == COUNTOF(formats))
3205 ERR("Unsupported format: %s\n", fmt);
3207 #undef DEVICE_FORMAT_REQUEST
3209 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3211 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3212 if(device->Frequency < MIN_OUTPUT_RATE)
3213 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3214 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3217 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3218 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3220 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3221 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3222 if((CPUCapFlags&CPU_CAP_SSE))
3223 device->UpdateSize = (device->UpdateSize+3)&~3;
3225 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3226 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3228 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3229 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3231 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3232 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3234 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3236 device->NumStereoSources = 1;
3237 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3239 device->Synth = SynthCreate(device);
3240 if(!device->Synth)
3242 DELETE_OBJ(device->Backend);
3243 al_free(device);
3244 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3245 return NULL;
3248 // Find a playback device to open
3249 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3251 DELETE_OBJ(device->Synth);
3252 DELETE_OBJ(device->Backend);
3253 al_free(device);
3254 alcSetError(NULL, err);
3255 return NULL;
3258 if(DefaultEffect.type != AL_EFFECT_NULL)
3260 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3261 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3263 device->DefaultSlot = NULL;
3264 ERR("Failed to initialize the default effect slot\n");
3266 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3268 ALeffectState *state = device->DefaultSlot->EffectState;
3269 device->DefaultSlot = NULL;
3270 DELETE_OBJ(state);
3271 ERR("Failed to initialize the default effect\n");
3275 do {
3276 device->next = DeviceList;
3277 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3279 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3280 return device;
3283 /* alcCloseDevice
3285 * Closes the given device.
3287 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
3289 ALCdevice *volatile*list;
3290 ALCcontext *ctx;
3292 LockLists();
3293 list = &DeviceList;
3294 while(*list && *list != Device)
3295 list = &(*list)->next;
3297 if(!*list || (*list)->Type == Capture)
3299 alcSetError(*list, ALC_INVALID_DEVICE);
3300 UnlockLists();
3301 return ALC_FALSE;
3304 *list = (*list)->next;
3305 UnlockLists();
3307 while((ctx=Device->ContextList) != NULL)
3309 WARN("Releasing context %p\n", ctx);
3310 ReleaseContext(ctx, Device);
3312 if((Device->Flags&DEVICE_RUNNING))
3313 V0(Device->Backend,stop)();
3314 Device->Flags &= ~DEVICE_RUNNING;
3316 ALCdevice_DecRef(Device);
3318 return ALC_TRUE;
3322 /************************************************
3323 * ALC capture functions
3324 ************************************************/
3325 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3327 ALCdevice *device = NULL;
3328 ALCenum err;
3330 DO_INITCONFIG();
3332 if(!CaptureBackend.name)
3334 alcSetError(NULL, ALC_INVALID_VALUE);
3335 return NULL;
3338 if(samples <= 0)
3340 alcSetError(NULL, ALC_INVALID_VALUE);
3341 return NULL;
3344 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3345 deviceName = NULL;
3347 device = al_calloc(16, sizeof(ALCdevice));
3348 if(!device)
3350 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3351 return NULL;
3354 //Validate device
3355 device->ref = 1;
3356 device->Connected = ALC_TRUE;
3357 device->Type = Capture;
3359 AL_STRING_INIT(device->DeviceName);
3361 InitUIntMap(&device->BufferMap, ~0);
3362 InitUIntMap(&device->EffectMap, ~0);
3363 InitUIntMap(&device->FilterMap, ~0);
3364 InitUIntMap(&device->SfontMap, ~0);
3365 InitUIntMap(&device->PresetMap, ~0);
3366 InitUIntMap(&device->FontsoundMap, ~0);
3368 if(!CaptureBackend.getFactory)
3369 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3370 ALCbackend_Capture);
3371 else
3373 ALCbackendFactory *factory = CaptureBackend.getFactory();
3374 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3376 if(!device->Backend)
3378 al_free(device);
3379 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3380 return NULL;
3383 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3384 device->Frequency = frequency;
3386 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3387 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3389 al_free(device);
3390 alcSetError(NULL, ALC_INVALID_ENUM);
3391 return NULL;
3394 device->UpdateSize = samples;
3395 device->NumUpdates = 1;
3397 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3399 al_free(device);
3400 alcSetError(NULL, err);
3401 return NULL;
3404 do {
3405 device->next = DeviceList;
3406 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3408 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3409 return device;
3412 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
3414 ALCdevice *volatile*list;
3416 LockLists();
3417 list = &DeviceList;
3418 while(*list && *list != Device)
3419 list = &(*list)->next;
3421 if(!*list || (*list)->Type != Capture)
3423 alcSetError(*list, ALC_INVALID_DEVICE);
3424 UnlockLists();
3425 return ALC_FALSE;
3428 *list = (*list)->next;
3429 UnlockLists();
3431 ALCdevice_DecRef(Device);
3433 return ALC_TRUE;
3436 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3438 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3439 alcSetError(device, ALC_INVALID_DEVICE);
3440 else
3442 ALCdevice_Lock(device);
3443 if(device->Connected)
3445 if(!(device->Flags&DEVICE_RUNNING))
3446 V0(device->Backend,start)();
3447 device->Flags |= DEVICE_RUNNING;
3449 ALCdevice_Unlock(device);
3452 if(device) ALCdevice_DecRef(device);
3455 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3457 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3458 alcSetError(device, ALC_INVALID_DEVICE);
3459 else
3461 ALCdevice_Lock(device);
3462 if((device->Flags&DEVICE_RUNNING))
3463 V0(device->Backend,stop)();
3464 device->Flags &= ~DEVICE_RUNNING;
3465 ALCdevice_Unlock(device);
3468 if(device) ALCdevice_DecRef(device);
3471 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3473 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3474 alcSetError(device, ALC_INVALID_DEVICE);
3475 else
3477 ALCenum err = ALC_INVALID_VALUE;
3479 ALCdevice_Lock(device);
3480 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3481 err = V(device->Backend,captureSamples)(buffer, samples);
3482 ALCdevice_Unlock(device);
3484 if(err != ALC_NO_ERROR)
3485 alcSetError(device, err);
3487 if(device) ALCdevice_DecRef(device);
3491 /************************************************
3492 * ALC loopback functions
3493 ************************************************/
3495 /* alcLoopbackOpenDeviceSOFT
3497 * Open a loopback device, for manual rendering.
3499 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3501 ALCbackendFactory *factory;
3502 ALCdevice *device;
3504 DO_INITCONFIG();
3506 /* Make sure the device name, if specified, is us. */
3507 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3509 alcSetError(NULL, ALC_INVALID_VALUE);
3510 return NULL;
3513 device = al_calloc(16, sizeof(ALCdevice));
3514 if(!device)
3516 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3517 return NULL;
3520 //Validate device
3521 device->ref = 1;
3522 device->Connected = ALC_TRUE;
3523 device->Type = Loopback;
3524 device->LastError = ALC_NO_ERROR;
3526 device->Flags = 0;
3527 device->Bs2b = NULL;
3528 device->Bs2bLevel = 0;
3529 AL_STRING_INIT(device->DeviceName);
3531 device->ContextList = NULL;
3533 device->ClockBase = 0;
3534 device->SamplesDone = 0;
3536 device->MaxNoOfSources = 256;
3537 device->AuxiliaryEffectSlotMax = 4;
3538 device->NumAuxSends = MAX_SENDS;
3540 InitUIntMap(&device->BufferMap, ~0);
3541 InitUIntMap(&device->EffectMap, ~0);
3542 InitUIntMap(&device->FilterMap, ~0);
3543 InitUIntMap(&device->SfontMap, ~0);
3544 InitUIntMap(&device->PresetMap, ~0);
3545 InitUIntMap(&device->FontsoundMap, ~0);
3547 factory = ALCloopbackFactory_getFactory();
3548 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3549 if(!device->Backend)
3551 al_free(device);
3552 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3553 return NULL;
3556 //Set output format
3557 device->NumUpdates = 0;
3558 device->UpdateSize = 0;
3560 device->Frequency = DEFAULT_OUTPUT_RATE;
3561 device->FmtChans = DevFmtChannelsDefault;
3562 device->FmtType = DevFmtTypeDefault;
3564 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3565 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3567 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3568 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3570 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3571 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3573 device->NumStereoSources = 1;
3574 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3576 device->Synth = SynthCreate(device);
3577 if(!device->Synth)
3579 DELETE_OBJ(device->Backend);
3580 al_free(device);
3581 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3582 return NULL;
3585 // Open the "backend"
3586 V(device->Backend,open)("Loopback");
3587 do {
3588 device->next = DeviceList;
3589 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3591 TRACE("Created device %p\n", device);
3592 return device;
3595 /* alcIsRenderFormatSupportedSOFT
3597 * Determines if the loopback device supports the given format for rendering.
3599 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3601 ALCboolean ret = ALC_FALSE;
3603 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3604 alcSetError(device, ALC_INVALID_DEVICE);
3605 else if(freq <= 0)
3606 alcSetError(device, ALC_INVALID_VALUE);
3607 else
3609 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3610 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3611 freq >= MIN_OUTPUT_RATE)
3612 ret = ALC_TRUE;
3614 if(device) ALCdevice_DecRef(device);
3616 return ret;
3619 /* alcRenderSamplesSOFT
3621 * Renders some samples into a buffer, using the format last set by the
3622 * attributes given to alcCreateContext.
3624 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3626 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3627 alcSetError(device, ALC_INVALID_DEVICE);
3628 else if(samples < 0 || (samples > 0 && buffer == NULL))
3629 alcSetError(device, ALC_INVALID_VALUE);
3630 else
3631 aluMixData(device, buffer, samples);
3632 if(device) ALCdevice_DecRef(device);
3636 /************************************************
3637 * ALC DSP pause/resume functions
3638 ************************************************/
3640 /* alcDevicePauseSOFT
3642 * Pause the DSP to stop audio processing.
3644 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3646 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3647 alcSetError(device, ALC_INVALID_DEVICE);
3648 else
3650 LockLists();
3651 if((device->Flags&DEVICE_RUNNING))
3652 V0(device->Backend,stop)();
3653 device->Flags &= ~DEVICE_RUNNING;
3654 device->Flags |= DEVICE_PAUSED;
3655 UnlockLists();
3657 if(device) ALCdevice_DecRef(device);
3660 /* alcDeviceResumeSOFT
3662 * Resume the DSP to restart audio processing.
3664 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3666 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3667 alcSetError(device, ALC_INVALID_DEVICE);
3668 else
3670 LockLists();
3671 if((device->Flags&DEVICE_PAUSED))
3673 if(V0(device->Backend,start)() != ALC_FALSE)
3675 device->Flags |= DEVICE_RUNNING;
3676 device->Flags &= ~DEVICE_PAUSED;
3678 else
3680 alcSetError(device, ALC_INVALID_DEVICE);
3681 ALCdevice_Lock(device);
3682 aluHandleDisconnect(device);
3683 ALCdevice_Unlock(device);
3686 UnlockLists();
3688 if(device) ALCdevice_DecRef(device);