Add a cast for MSVC
[openal-soft.git] / Alc / ALc.c
blob6a0a1ed04a2ee0a8ac94016e8f3d0ee84f5ad7d9
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 }
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", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, 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", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, 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(alGetSoundfontivSOFT),
297 DECL(alSoundfontPresetsSOFT),
298 DECL(alGenPresetsSOFT),
299 DECL(alDeletePresetsSOFT),
300 DECL(alIsPresetSOFT),
301 DECL(alPresetiSOFT),
302 DECL(alPresetivSOFT),
303 DECL(alGetPresetivSOFT),
304 DECL(alPresetFontsoundsSOFT),
305 DECL(alGenFontsoundsSOFT),
306 DECL(alDeleteFontsoundsSOFT),
307 DECL(alIsFontsoundSOFT),
308 DECL(alFontsoundiSOFT),
309 DECL(alFontsound2iSOFT),
310 DECL(alFontsoundivSOFT),
311 DECL(alGetFontsoundivSOFT),
312 DECL(alFontsoundModulatoriSOFT),
313 DECL(alGetFontsoundModulatorivSOFT),
314 DECL(alMidiSoundfontSOFT),
315 DECL(alMidiSoundfontvSOFT),
316 DECL(alMidiEventSOFT),
317 DECL(alMidiSysExSOFT),
318 DECL(alMidiPlaySOFT),
319 DECL(alMidiPauseSOFT),
320 DECL(alMidiStopSOFT),
321 DECL(alMidiResetSOFT),
322 DECL(alMidiGainSOFT),
323 DECL(alGetInteger64SOFT),
324 DECL(alGetInteger64vSOFT),
325 DECL(alLoadSoundfontSOFT),
327 { NULL, NULL }
329 #undef DECL
331 #define DECL(x) { #x, (x) }
332 static const ALCenums enumeration[] = {
333 DECL(ALC_INVALID),
334 DECL(ALC_FALSE),
335 DECL(ALC_TRUE),
337 DECL(ALC_MAJOR_VERSION),
338 DECL(ALC_MINOR_VERSION),
339 DECL(ALC_ATTRIBUTES_SIZE),
340 DECL(ALC_ALL_ATTRIBUTES),
341 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
342 DECL(ALC_DEVICE_SPECIFIER),
343 DECL(ALC_ALL_DEVICES_SPECIFIER),
344 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
345 DECL(ALC_EXTENSIONS),
346 DECL(ALC_FREQUENCY),
347 DECL(ALC_REFRESH),
348 DECL(ALC_SYNC),
349 DECL(ALC_MONO_SOURCES),
350 DECL(ALC_STEREO_SOURCES),
351 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
352 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
353 DECL(ALC_CAPTURE_SAMPLES),
354 DECL(ALC_CONNECTED),
356 DECL(ALC_EFX_MAJOR_VERSION),
357 DECL(ALC_EFX_MINOR_VERSION),
358 DECL(ALC_MAX_AUXILIARY_SENDS),
360 DECL(ALC_FORMAT_CHANNELS_SOFT),
361 DECL(ALC_FORMAT_TYPE_SOFT),
363 DECL(ALC_MONO_SOFT),
364 DECL(ALC_STEREO_SOFT),
365 DECL(ALC_QUAD_SOFT),
366 DECL(ALC_5POINT1_SOFT),
367 DECL(ALC_6POINT1_SOFT),
368 DECL(ALC_7POINT1_SOFT),
370 DECL(ALC_BYTE_SOFT),
371 DECL(ALC_UNSIGNED_BYTE_SOFT),
372 DECL(ALC_SHORT_SOFT),
373 DECL(ALC_UNSIGNED_SHORT_SOFT),
374 DECL(ALC_INT_SOFT),
375 DECL(ALC_UNSIGNED_INT_SOFT),
376 DECL(ALC_FLOAT_SOFT),
378 DECL(ALC_NO_ERROR),
379 DECL(ALC_INVALID_DEVICE),
380 DECL(ALC_INVALID_CONTEXT),
381 DECL(ALC_INVALID_ENUM),
382 DECL(ALC_INVALID_VALUE),
383 DECL(ALC_OUT_OF_MEMORY),
386 DECL(AL_INVALID),
387 DECL(AL_NONE),
388 DECL(AL_FALSE),
389 DECL(AL_TRUE),
391 DECL(AL_SOURCE_RELATIVE),
392 DECL(AL_CONE_INNER_ANGLE),
393 DECL(AL_CONE_OUTER_ANGLE),
394 DECL(AL_PITCH),
395 DECL(AL_POSITION),
396 DECL(AL_DIRECTION),
397 DECL(AL_VELOCITY),
398 DECL(AL_LOOPING),
399 DECL(AL_BUFFER),
400 DECL(AL_GAIN),
401 DECL(AL_MIN_GAIN),
402 DECL(AL_MAX_GAIN),
403 DECL(AL_ORIENTATION),
404 DECL(AL_REFERENCE_DISTANCE),
405 DECL(AL_ROLLOFF_FACTOR),
406 DECL(AL_CONE_OUTER_GAIN),
407 DECL(AL_MAX_DISTANCE),
408 DECL(AL_SEC_OFFSET),
409 DECL(AL_SAMPLE_OFFSET),
410 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
411 DECL(AL_BYTE_OFFSET),
412 DECL(AL_BYTE_RW_OFFSETS_SOFT),
413 DECL(AL_SOURCE_TYPE),
414 DECL(AL_STATIC),
415 DECL(AL_STREAMING),
416 DECL(AL_UNDETERMINED),
417 DECL(AL_METERS_PER_UNIT),
418 DECL(AL_DIRECT_CHANNELS_SOFT),
420 DECL(AL_DIRECT_FILTER),
421 DECL(AL_AUXILIARY_SEND_FILTER),
422 DECL(AL_AIR_ABSORPTION_FACTOR),
423 DECL(AL_ROOM_ROLLOFF_FACTOR),
424 DECL(AL_CONE_OUTER_GAINHF),
425 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
426 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
427 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
429 DECL(AL_SOURCE_STATE),
430 DECL(AL_INITIAL),
431 DECL(AL_PLAYING),
432 DECL(AL_PAUSED),
433 DECL(AL_STOPPED),
435 DECL(AL_BUFFERS_QUEUED),
436 DECL(AL_BUFFERS_PROCESSED),
438 DECL(AL_FORMAT_MONO8),
439 DECL(AL_FORMAT_MONO16),
440 DECL(AL_FORMAT_MONO_FLOAT32),
441 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
442 DECL(AL_FORMAT_STEREO8),
443 DECL(AL_FORMAT_STEREO16),
444 DECL(AL_FORMAT_STEREO_FLOAT32),
445 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
446 DECL(AL_FORMAT_MONO_IMA4),
447 DECL(AL_FORMAT_STEREO_IMA4),
448 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
449 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
450 DECL(AL_FORMAT_QUAD8_LOKI),
451 DECL(AL_FORMAT_QUAD16_LOKI),
452 DECL(AL_FORMAT_QUAD8),
453 DECL(AL_FORMAT_QUAD16),
454 DECL(AL_FORMAT_QUAD32),
455 DECL(AL_FORMAT_51CHN8),
456 DECL(AL_FORMAT_51CHN16),
457 DECL(AL_FORMAT_51CHN32),
458 DECL(AL_FORMAT_61CHN8),
459 DECL(AL_FORMAT_61CHN16),
460 DECL(AL_FORMAT_61CHN32),
461 DECL(AL_FORMAT_71CHN8),
462 DECL(AL_FORMAT_71CHN16),
463 DECL(AL_FORMAT_71CHN32),
464 DECL(AL_FORMAT_REAR8),
465 DECL(AL_FORMAT_REAR16),
466 DECL(AL_FORMAT_REAR32),
467 DECL(AL_FORMAT_MONO_MULAW),
468 DECL(AL_FORMAT_MONO_MULAW_EXT),
469 DECL(AL_FORMAT_STEREO_MULAW),
470 DECL(AL_FORMAT_STEREO_MULAW_EXT),
471 DECL(AL_FORMAT_QUAD_MULAW),
472 DECL(AL_FORMAT_51CHN_MULAW),
473 DECL(AL_FORMAT_61CHN_MULAW),
474 DECL(AL_FORMAT_71CHN_MULAW),
475 DECL(AL_FORMAT_REAR_MULAW),
476 DECL(AL_FORMAT_MONO_ALAW_EXT),
477 DECL(AL_FORMAT_STEREO_ALAW_EXT),
479 DECL(AL_MONO8_SOFT),
480 DECL(AL_MONO16_SOFT),
481 DECL(AL_MONO32F_SOFT),
482 DECL(AL_STEREO8_SOFT),
483 DECL(AL_STEREO16_SOFT),
484 DECL(AL_STEREO32F_SOFT),
485 DECL(AL_QUAD8_SOFT),
486 DECL(AL_QUAD16_SOFT),
487 DECL(AL_QUAD32F_SOFT),
488 DECL(AL_REAR8_SOFT),
489 DECL(AL_REAR16_SOFT),
490 DECL(AL_REAR32F_SOFT),
491 DECL(AL_5POINT1_8_SOFT),
492 DECL(AL_5POINT1_16_SOFT),
493 DECL(AL_5POINT1_32F_SOFT),
494 DECL(AL_6POINT1_8_SOFT),
495 DECL(AL_6POINT1_16_SOFT),
496 DECL(AL_6POINT1_32F_SOFT),
497 DECL(AL_7POINT1_8_SOFT),
498 DECL(AL_7POINT1_16_SOFT),
499 DECL(AL_7POINT1_32F_SOFT),
501 DECL(AL_MONO_SOFT),
502 DECL(AL_STEREO_SOFT),
503 DECL(AL_QUAD_SOFT),
504 DECL(AL_REAR_SOFT),
505 DECL(AL_5POINT1_SOFT),
506 DECL(AL_6POINT1_SOFT),
507 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BYTE_SOFT),
510 DECL(AL_UNSIGNED_BYTE_SOFT),
511 DECL(AL_SHORT_SOFT),
512 DECL(AL_UNSIGNED_SHORT_SOFT),
513 DECL(AL_INT_SOFT),
514 DECL(AL_UNSIGNED_INT_SOFT),
515 DECL(AL_FLOAT_SOFT),
516 DECL(AL_DOUBLE_SOFT),
517 DECL(AL_BYTE3_SOFT),
518 DECL(AL_UNSIGNED_BYTE3_SOFT),
520 DECL(AL_FREQUENCY),
521 DECL(AL_BITS),
522 DECL(AL_CHANNELS),
523 DECL(AL_SIZE),
524 DECL(AL_INTERNAL_FORMAT_SOFT),
525 DECL(AL_BYTE_LENGTH_SOFT),
526 DECL(AL_SAMPLE_LENGTH_SOFT),
527 DECL(AL_SEC_LENGTH_SOFT),
528 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
531 DECL(AL_UNUSED),
532 DECL(AL_PENDING),
533 DECL(AL_PROCESSED),
535 DECL(AL_NO_ERROR),
536 DECL(AL_INVALID_NAME),
537 DECL(AL_INVALID_ENUM),
538 DECL(AL_INVALID_VALUE),
539 DECL(AL_INVALID_OPERATION),
540 DECL(AL_OUT_OF_MEMORY),
542 DECL(AL_VENDOR),
543 DECL(AL_VERSION),
544 DECL(AL_RENDERER),
545 DECL(AL_EXTENSIONS),
547 DECL(AL_DOPPLER_FACTOR),
548 DECL(AL_DOPPLER_VELOCITY),
549 DECL(AL_DISTANCE_MODEL),
550 DECL(AL_SPEED_OF_SOUND),
551 DECL(AL_SOURCE_DISTANCE_MODEL),
552 DECL(AL_DEFERRED_UPDATES_SOFT),
554 DECL(AL_INVERSE_DISTANCE),
555 DECL(AL_INVERSE_DISTANCE_CLAMPED),
556 DECL(AL_LINEAR_DISTANCE),
557 DECL(AL_LINEAR_DISTANCE_CLAMPED),
558 DECL(AL_EXPONENT_DISTANCE),
559 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
561 DECL(AL_FILTER_TYPE),
562 DECL(AL_FILTER_NULL),
563 DECL(AL_FILTER_LOWPASS),
564 DECL(AL_FILTER_HIGHPASS),
565 DECL(AL_FILTER_BANDPASS),
567 DECL(AL_LOWPASS_GAIN),
568 DECL(AL_LOWPASS_GAINHF),
570 DECL(AL_HIGHPASS_GAIN),
571 DECL(AL_HIGHPASS_GAINLF),
573 DECL(AL_BANDPASS_GAIN),
574 DECL(AL_BANDPASS_GAINHF),
575 DECL(AL_BANDPASS_GAINLF),
577 DECL(AL_EFFECT_TYPE),
578 DECL(AL_EFFECT_NULL),
579 DECL(AL_EFFECT_REVERB),
580 DECL(AL_EFFECT_EAXREVERB),
581 DECL(AL_EFFECT_CHORUS),
582 DECL(AL_EFFECT_DISTORTION),
583 DECL(AL_EFFECT_ECHO),
584 DECL(AL_EFFECT_FLANGER),
585 #if 0
586 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
587 DECL(AL_EFFECT_VOCAL_MORPHER),
588 DECL(AL_EFFECT_PITCH_SHIFTER),
589 #endif
590 DECL(AL_EFFECT_RING_MODULATOR),
591 #if 0
592 DECL(AL_EFFECT_AUTOWAH),
593 #endif
594 DECL(AL_EFFECT_COMPRESSOR),
595 DECL(AL_EFFECT_EQUALIZER),
596 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
597 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
599 DECL(AL_EAXREVERB_DENSITY),
600 DECL(AL_EAXREVERB_DIFFUSION),
601 DECL(AL_EAXREVERB_GAIN),
602 DECL(AL_EAXREVERB_GAINHF),
603 DECL(AL_EAXREVERB_GAINLF),
604 DECL(AL_EAXREVERB_DECAY_TIME),
605 DECL(AL_EAXREVERB_DECAY_HFRATIO),
606 DECL(AL_EAXREVERB_DECAY_LFRATIO),
607 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
608 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
609 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
610 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
611 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
612 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
613 DECL(AL_EAXREVERB_ECHO_TIME),
614 DECL(AL_EAXREVERB_ECHO_DEPTH),
615 DECL(AL_EAXREVERB_MODULATION_TIME),
616 DECL(AL_EAXREVERB_MODULATION_DEPTH),
617 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
618 DECL(AL_EAXREVERB_HFREFERENCE),
619 DECL(AL_EAXREVERB_LFREFERENCE),
620 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
621 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
623 DECL(AL_REVERB_DENSITY),
624 DECL(AL_REVERB_DIFFUSION),
625 DECL(AL_REVERB_GAIN),
626 DECL(AL_REVERB_GAINHF),
627 DECL(AL_REVERB_DECAY_TIME),
628 DECL(AL_REVERB_DECAY_HFRATIO),
629 DECL(AL_REVERB_REFLECTIONS_GAIN),
630 DECL(AL_REVERB_REFLECTIONS_DELAY),
631 DECL(AL_REVERB_LATE_REVERB_GAIN),
632 DECL(AL_REVERB_LATE_REVERB_DELAY),
633 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
634 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_REVERB_DECAY_HFLIMIT),
637 DECL(AL_CHORUS_WAVEFORM),
638 DECL(AL_CHORUS_PHASE),
639 DECL(AL_CHORUS_RATE),
640 DECL(AL_CHORUS_DEPTH),
641 DECL(AL_CHORUS_FEEDBACK),
642 DECL(AL_CHORUS_DELAY),
644 DECL(AL_DISTORTION_EDGE),
645 DECL(AL_DISTORTION_GAIN),
646 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
647 DECL(AL_DISTORTION_EQCENTER),
648 DECL(AL_DISTORTION_EQBANDWIDTH),
650 DECL(AL_ECHO_DELAY),
651 DECL(AL_ECHO_LRDELAY),
652 DECL(AL_ECHO_DAMPING),
653 DECL(AL_ECHO_FEEDBACK),
654 DECL(AL_ECHO_SPREAD),
656 DECL(AL_FLANGER_WAVEFORM),
657 DECL(AL_FLANGER_PHASE),
658 DECL(AL_FLANGER_RATE),
659 DECL(AL_FLANGER_DEPTH),
660 DECL(AL_FLANGER_FEEDBACK),
661 DECL(AL_FLANGER_DELAY),
663 DECL(AL_RING_MODULATOR_FREQUENCY),
664 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
665 DECL(AL_RING_MODULATOR_WAVEFORM),
667 #if 0
668 DECL(AL_AUTOWAH_ATTACK_TIME),
669 DECL(AL_AUTOWAH_PEAK_GAIN),
670 DECL(AL_AUTOWAH_RELEASE_TIME),
671 DECL(AL_AUTOWAH_RESONANCE),
672 #endif
674 DECL(AL_COMPRESSOR_ONOFF),
676 DECL(AL_EQUALIZER_LOW_GAIN),
677 DECL(AL_EQUALIZER_LOW_CUTOFF),
678 DECL(AL_EQUALIZER_MID1_GAIN),
679 DECL(AL_EQUALIZER_MID1_CENTER),
680 DECL(AL_EQUALIZER_MID1_WIDTH),
681 DECL(AL_EQUALIZER_MID2_GAIN),
682 DECL(AL_EQUALIZER_MID2_CENTER),
683 DECL(AL_EQUALIZER_MID2_WIDTH),
684 DECL(AL_EQUALIZER_HIGH_GAIN),
685 DECL(AL_EQUALIZER_HIGH_CUTOFF),
687 DECL(AL_DEDICATED_GAIN),
689 { NULL, (ALCenum)0 }
691 #undef DECL
693 static const ALCchar alcNoError[] = "No Error";
694 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
695 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
696 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
697 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
698 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
701 /************************************************
702 * Global variables
703 ************************************************/
705 /* Enumerated device names */
706 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
708 static al_string alcAllDevicesList;
709 static al_string alcCaptureDeviceList;
711 /* Default is always the first in the list */
712 static ALCchar *alcDefaultAllDevicesSpecifier;
713 static ALCchar *alcCaptureDefaultDeviceSpecifier;
715 /* Default context extensions */
716 static const ALchar alExtList[] =
717 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
718 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
719 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
720 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples "
721 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
722 "AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency "
723 "AL_SOFT_source_length";
725 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
727 /* Thread-local current context */
728 static altss_t LocalContext;
729 /* Process-wide current context */
730 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
732 /* Mixing thread piority level */
733 ALint RTPrioLevel;
735 FILE *LogFile;
736 #ifdef _DEBUG
737 enum LogLevel LogLevel = LogWarning;
738 #else
739 enum LogLevel LogLevel = LogError;
740 #endif
742 /* Flag to trap ALC device errors */
743 static ALCboolean TrapALCError = ALC_FALSE;
745 /* One-time configuration init control */
746 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
748 /* Default effect that applies to sources that don't have an effect on send 0 */
749 static ALeffect DefaultEffect;
752 /************************************************
753 * ALC information
754 ************************************************/
755 static const ALCchar alcNoDeviceExtList[] =
756 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
757 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
758 static const ALCchar alcExtensionList[] =
759 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
760 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
761 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
762 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
763 static const ALCint alcMajorVersion = 1;
764 static const ALCint alcMinorVersion = 1;
766 static const ALCint alcEFXMajorVersion = 1;
767 static const ALCint alcEFXMinorVersion = 0;
770 /************************************************
771 * Device lists
772 ************************************************/
773 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
775 static almtx_t ListLock;
776 static inline void LockLists(void)
778 int lockret = almtx_lock(&ListLock);
779 assert(lockret == althrd_success);
781 static inline void UnlockLists(void)
783 int unlockret = almtx_unlock(&ListLock);
784 assert(unlockret == althrd_success);
787 /************************************************
788 * Library initialization
789 ************************************************/
790 #if defined(_WIN32)
791 static void alc_init(void);
792 static void alc_deinit(void);
793 static void alc_deinit_safe(void);
795 #ifndef AL_LIBTYPE_STATIC
796 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
798 switch(reason)
800 case DLL_PROCESS_ATTACH:
801 /* Pin the DLL so we won't get unloaded until the process terminates */
802 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 (WCHAR*)hModule, &hModule);
804 alc_init();
805 break;
807 case DLL_THREAD_DETACH:
808 break;
810 case DLL_PROCESS_DETACH:
811 if(!lpReserved)
812 alc_deinit();
813 else
814 alc_deinit_safe();
815 break;
817 return TRUE;
819 #elif defined(_MSC_VER)
820 #pragma section(".CRT$XCU",read)
821 static void alc_constructor(void);
822 static void alc_destructor(void);
823 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
825 static void alc_constructor(void)
827 atexit(alc_destructor);
828 alc_init();
831 static void alc_destructor(void)
833 alc_deinit();
835 #elif defined(HAVE_GCC_DESTRUCTOR)
836 static void alc_init(void) __attribute__((constructor));
837 static void alc_deinit(void) __attribute__((destructor));
838 #else
839 #error "No static initialization available on this platform!"
840 #endif
842 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No global initialization available on this platform!"
849 #endif
851 static void ReleaseThreadCtx(void *ptr);
852 static void alc_init(void)
854 const char *str;
855 int ret;
857 LogFile = stderr;
859 AL_STRING_INIT(alcAllDevicesList);
860 AL_STRING_INIT(alcCaptureDeviceList);
862 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ConeScale *= 0.5f;
866 str = getenv("__ALSOFT_REVERSE_Z");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 ZScale *= -1.0f;
870 ret = altss_create(&LocalContext, ReleaseThreadCtx);
871 assert(ret == althrd_success);
873 ret = almtx_init(&ListLock, almtx_recursive);
874 assert(ret == althrd_success);
876 ThunkInit();
879 static void alc_initconfig(void)
881 const char *devs, *str;
882 ALuint capfilter;
883 float valf;
884 int i, n;
886 str = getenv("ALSOFT_LOGLEVEL");
887 if(str)
889 long lvl = strtol(str, NULL, 0);
890 if(lvl >= NoLog && lvl <= LogRef)
891 LogLevel = lvl;
894 str = getenv("ALSOFT_LOGFILE");
895 if(str && str[0])
897 FILE *logfile = al_fopen(str, "wt");
898 if(logfile) LogFile = logfile;
899 else ERR("Failed to open log file '%s'\n", str);
903 char buf[1024] = "";
904 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
905 for(i = 1;BackendList[i].name;i++)
906 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
907 TRACE("Supported backends: %s\n", buf);
909 ReadALConfig();
911 capfilter = 0;
912 #if defined(HAVE_SSE4_1)
913 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
914 #elif defined(HAVE_SSE2)
915 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
916 #elif defined(HAVE_SSE)
917 capfilter |= CPU_CAP_SSE;
918 #endif
919 #ifdef HAVE_NEON
920 capfilter |= CPU_CAP_NEON;
921 #endif
922 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
924 if(strcasecmp(str, "all") == 0)
925 capfilter = 0;
926 else
928 size_t len;
929 const char *next = str;
931 do {
932 str = next;
933 while(isspace(str[0]))
934 str++;
935 next = strchr(str, ',');
937 if(!str[0] || str[0] == ',')
938 continue;
940 len = (next ? ((size_t)(next-str)) : strlen(str));
941 while(len > 0 && isspace(str[len-1]))
942 len--;
943 if(len == 3 && strncasecmp(str, "sse", len) == 0)
944 capfilter &= ~CPU_CAP_SSE;
945 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
946 capfilter &= ~CPU_CAP_SSE2;
947 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
948 capfilter &= ~CPU_CAP_SSE4_1;
949 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
950 capfilter &= ~CPU_CAP_NEON;
951 else
952 WARN("Invalid CPU extension \"%s\"\n", str);
953 } while(next++);
956 FillCPUCaps(capfilter);
958 #ifdef _WIN32
959 RTPrioLevel = 1;
960 #else
961 RTPrioLevel = 0;
962 #endif
963 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
965 if(ConfigValueStr(NULL, "resampler", &str))
967 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
968 DefaultResampler = PointResampler;
969 else if(strcasecmp(str, "linear") == 0)
970 DefaultResampler = LinearResampler;
971 else if(strcasecmp(str, "cubic") == 0)
972 DefaultResampler = CubicResampler;
973 else
975 char *end;
977 n = strtol(str, &end, 0);
978 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
979 DefaultResampler = n;
980 else
981 WARN("Invalid resampler: %s\n", str);
985 str = getenv("ALSOFT_TRAP_ERROR");
986 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALError = AL_TRUE;
989 TrapALCError = AL_TRUE;
991 else
993 str = getenv("ALSOFT_TRAP_AL_ERROR");
994 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
995 TrapALError = AL_TRUE;
996 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
998 str = getenv("ALSOFT_TRAP_ALC_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1000 TrapALCError = ALC_TRUE;
1001 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1004 if(ConfigValueFloat("reverb", "boost", &valf))
1005 ReverbBoost *= powf(10.0f, valf / 20.0f);
1007 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1009 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1010 ConfigValueStr(NULL, "drivers", &devs))
1012 int n;
1013 size_t len;
1014 const char *next = devs;
1015 int endlist, delitem;
1017 i = 0;
1018 do {
1019 devs = next;
1020 while(isspace(devs[0]))
1021 devs++;
1022 next = strchr(devs, ',');
1024 delitem = (devs[0] == '-');
1025 if(devs[0] == '-') devs++;
1027 if(!devs[0] || devs[0] == ',')
1029 endlist = 0;
1030 continue;
1032 endlist = 1;
1034 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1035 while(len > 0 && isspace(devs[len-1]))
1036 len--;
1037 for(n = i;BackendList[n].name;n++)
1039 if(len == strlen(BackendList[n].name) &&
1040 strncmp(BackendList[n].name, devs, len) == 0)
1042 if(delitem)
1044 do {
1045 BackendList[n] = BackendList[n+1];
1046 ++n;
1047 } while(BackendList[n].name);
1049 else
1051 struct BackendInfo Bkp = BackendList[n];
1052 while(n > i)
1054 BackendList[n] = BackendList[n-1];
1055 --n;
1057 BackendList[n] = Bkp;
1059 i++;
1061 break;
1064 } while(next++);
1066 if(endlist)
1068 BackendList[i].name = NULL;
1069 BackendList[i].getFactory = NULL;
1070 BackendList[i].Init = NULL;
1071 BackendList[i].Deinit = NULL;
1072 BackendList[i].Probe = NULL;
1076 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1078 if(BackendList[i].getFactory)
1080 ALCbackendFactory *factory = BackendList[i].getFactory();
1081 if(!V0(factory,init)())
1083 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1084 continue;
1087 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1088 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1090 PlaybackBackend = BackendList[i];
1091 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1093 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1095 CaptureBackend = BackendList[i];
1096 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1099 continue;
1102 if(!BackendList[i].Init(&BackendList[i].Funcs))
1104 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1105 continue;
1108 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1109 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1111 PlaybackBackend = BackendList[i];
1112 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1114 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1116 CaptureBackend = BackendList[i];
1117 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1121 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1122 V0(factory,init)();
1125 if(ConfigValueStr(NULL, "excludefx", &str))
1127 size_t len;
1128 const char *next = str;
1130 do {
1131 str = next;
1132 next = strchr(str, ',');
1134 if(!str[0] || next == str)
1135 continue;
1137 len = (next ? ((size_t)(next-str)) : strlen(str));
1138 for(n = 0;EffectList[n].name;n++)
1140 if(len == strlen(EffectList[n].name) &&
1141 strncmp(EffectList[n].name, str, len) == 0)
1142 DisabledEffects[EffectList[n].type] = AL_TRUE;
1144 } while(next++);
1147 InitEffectFactoryMap();
1149 InitEffect(&DefaultEffect);
1150 str = getenv("ALSOFT_DEFAULT_REVERB");
1151 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1152 LoadReverbPreset(str, &DefaultEffect);
1154 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1157 /************************************************
1158 * Library deinitialization
1159 ************************************************/
1160 static void alc_cleanup(void)
1162 ALCdevice *dev;
1164 AL_STRING_DEINIT(alcAllDevicesList);
1165 AL_STRING_DEINIT(alcCaptureDeviceList);
1167 free(alcDefaultAllDevicesSpecifier);
1168 alcDefaultAllDevicesSpecifier = NULL;
1169 free(alcCaptureDefaultDeviceSpecifier);
1170 alcCaptureDefaultDeviceSpecifier = NULL;
1172 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1174 ALCuint num = 0;
1175 do {
1176 num++;
1177 } while((dev=dev->next) != NULL);
1178 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1181 DeinitEffectFactoryMap();
1184 static void alc_deinit_safe(void)
1186 alc_cleanup();
1188 FreeHrtfs();
1189 FreeALConfig();
1191 ThunkExit();
1192 almtx_destroy(&ListLock);
1193 altss_delete(LocalContext);
1195 if(LogFile != stderr)
1196 fclose(LogFile);
1197 LogFile = NULL;
1200 static void alc_deinit(void)
1202 int i;
1204 alc_cleanup();
1206 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1207 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1209 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1211 if(!BackendList[i].getFactory)
1212 BackendList[i].Deinit();
1213 else
1215 ALCbackendFactory *factory = BackendList[i].getFactory();
1216 V0(factory,deinit)();
1220 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1221 V0(factory,deinit)();
1224 alc_deinit_safe();
1228 /************************************************
1229 * Device enumeration
1230 ************************************************/
1231 static void ProbeDevices(al_string *list, enum DevProbe type)
1233 DO_INITCONFIG();
1235 LockLists();
1236 al_string_clear(list);
1238 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1240 if(!PlaybackBackend.getFactory)
1241 PlaybackBackend.Probe(type);
1242 else
1244 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1245 V(factory,probe)(type);
1248 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1250 if(!CaptureBackend.getFactory)
1251 CaptureBackend.Probe(type);
1252 else
1254 ALCbackendFactory *factory = CaptureBackend.getFactory();
1255 V(factory,probe)(type);
1258 UnlockLists();
1260 static void ProbeAllDevicesList(void)
1261 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1262 static void ProbeCaptureDeviceList(void)
1263 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1265 static void AppendDevice(const ALCchar *name, al_string *devnames)
1267 size_t len = strlen(name);
1268 if(len > 0)
1269 al_string_append_range(devnames, name, name+len+1);
1271 void AppendAllDevicesList(const ALCchar *name)
1272 { AppendDevice(name, &alcAllDevicesList); }
1273 void AppendCaptureDeviceList(const ALCchar *name)
1274 { AppendDevice(name, &alcCaptureDeviceList); }
1277 /************************************************
1278 * Device format information
1279 ************************************************/
1280 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1282 switch(type)
1284 case DevFmtByte: return "Signed Byte";
1285 case DevFmtUByte: return "Unsigned Byte";
1286 case DevFmtShort: return "Signed Short";
1287 case DevFmtUShort: return "Unsigned Short";
1288 case DevFmtInt: return "Signed Int";
1289 case DevFmtUInt: return "Unsigned Int";
1290 case DevFmtFloat: return "Float";
1292 return "(unknown type)";
1294 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1296 switch(chans)
1298 case DevFmtMono: return "Mono";
1299 case DevFmtStereo: return "Stereo";
1300 case DevFmtQuad: return "Quadraphonic";
1301 case DevFmtX51: return "5.1 Surround";
1302 case DevFmtX51Side: return "5.1 Side";
1303 case DevFmtX61: return "6.1 Surround";
1304 case DevFmtX71: return "7.1 Surround";
1306 return "(unknown channels)";
1309 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1310 ALuint BytesFromDevFmt(enum DevFmtType type)
1312 switch(type)
1314 case DevFmtByte: return sizeof(ALbyte);
1315 case DevFmtUByte: return sizeof(ALubyte);
1316 case DevFmtShort: return sizeof(ALshort);
1317 case DevFmtUShort: return sizeof(ALushort);
1318 case DevFmtInt: return sizeof(ALint);
1319 case DevFmtUInt: return sizeof(ALuint);
1320 case DevFmtFloat: return sizeof(ALfloat);
1322 return 0;
1324 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1326 switch(chans)
1328 case DevFmtMono: return 1;
1329 case DevFmtStereo: return 2;
1330 case DevFmtQuad: return 4;
1331 case DevFmtX51: return 6;
1332 case DevFmtX51Side: return 6;
1333 case DevFmtX61: return 7;
1334 case DevFmtX71: return 8;
1336 return 0;
1339 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1340 enum DevFmtChannels *chans, enum DevFmtType *type)
1342 static const struct {
1343 ALenum format;
1344 enum DevFmtChannels channels;
1345 enum DevFmtType type;
1346 } list[] = {
1347 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1348 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1349 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1351 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1352 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1353 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1355 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1356 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1357 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1359 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1360 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1361 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1363 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1364 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1365 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1367 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1368 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1369 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1371 ALuint i;
1373 for(i = 0;i < COUNTOF(list);i++)
1375 if(list[i].format == format)
1377 *chans = list[i].channels;
1378 *type = list[i].type;
1379 return AL_TRUE;
1383 return AL_FALSE;
1386 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1388 switch(type)
1390 case ALC_BYTE_SOFT:
1391 case ALC_UNSIGNED_BYTE_SOFT:
1392 case ALC_SHORT_SOFT:
1393 case ALC_UNSIGNED_SHORT_SOFT:
1394 case ALC_INT_SOFT:
1395 case ALC_UNSIGNED_INT_SOFT:
1396 case ALC_FLOAT_SOFT:
1397 return ALC_TRUE;
1399 return ALC_FALSE;
1402 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1404 switch(channels)
1406 case ALC_MONO_SOFT:
1407 case ALC_STEREO_SOFT:
1408 case ALC_QUAD_SOFT:
1409 case ALC_5POINT1_SOFT:
1410 case ALC_6POINT1_SOFT:
1411 case ALC_7POINT1_SOFT:
1412 return ALC_TRUE;
1414 return ALC_FALSE;
1418 /************************************************
1419 * Miscellaneous ALC helpers
1420 ************************************************/
1421 extern inline void LockContext(ALCcontext *context);
1422 extern inline void UnlockContext(ALCcontext *context);
1424 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1426 return V0(device->Backend,getLatency)();
1429 void ALCdevice_Lock(ALCdevice *device)
1431 V0(device->Backend,lock)();
1434 void ALCdevice_Unlock(ALCdevice *device)
1436 V0(device->Backend,unlock)();
1440 /* SetDefaultWFXChannelOrder
1442 * Sets the default channel order used by WaveFormatEx.
1444 void SetDefaultWFXChannelOrder(ALCdevice *device)
1446 ALuint i;
1448 for(i = 0;i < MaxChannels;i++)
1449 device->ChannelName[i] = InvalidChannel;
1451 switch(device->FmtChans)
1453 case DevFmtMono: device->ChannelName[0] = FrontCenter;
1454 break;
1455 case DevFmtStereo: device->ChannelName[0] = FrontLeft;
1456 device->ChannelName[1] = FrontRight;
1457 break;
1458 case DevFmtQuad: device->ChannelName[0] = FrontLeft;
1459 device->ChannelName[1] = FrontRight;
1460 device->ChannelName[2] = BackLeft;
1461 device->ChannelName[3] = BackRight;
1462 break;
1463 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1464 device->ChannelName[1] = FrontRight;
1465 device->ChannelName[2] = FrontCenter;
1466 device->ChannelName[3] = LFE;
1467 device->ChannelName[4] = BackLeft;
1468 device->ChannelName[5] = BackRight;
1469 break;
1470 case DevFmtX51Side: device->ChannelName[0] = FrontLeft;
1471 device->ChannelName[1] = FrontRight;
1472 device->ChannelName[2] = FrontCenter;
1473 device->ChannelName[3] = LFE;
1474 device->ChannelName[4] = SideLeft;
1475 device->ChannelName[5] = SideRight;
1476 break;
1477 case DevFmtX61: device->ChannelName[0] = FrontLeft;
1478 device->ChannelName[1] = FrontRight;
1479 device->ChannelName[2] = FrontCenter;
1480 device->ChannelName[3] = LFE;
1481 device->ChannelName[4] = BackCenter;
1482 device->ChannelName[5] = SideLeft;
1483 device->ChannelName[6] = SideRight;
1484 break;
1485 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1486 device->ChannelName[1] = FrontRight;
1487 device->ChannelName[2] = FrontCenter;
1488 device->ChannelName[3] = LFE;
1489 device->ChannelName[4] = BackLeft;
1490 device->ChannelName[5] = BackRight;
1491 device->ChannelName[6] = SideLeft;
1492 device->ChannelName[7] = SideRight;
1493 break;
1497 /* SetDefaultChannelOrder
1499 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1501 void SetDefaultChannelOrder(ALCdevice *device)
1503 ALuint i;
1505 for(i = 0;i < MaxChannels;i++)
1506 device->ChannelName[i] = InvalidChannel;
1508 switch(device->FmtChans)
1510 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1511 device->ChannelName[1] = FrontRight;
1512 device->ChannelName[2] = BackLeft;
1513 device->ChannelName[3] = BackRight;
1514 device->ChannelName[4] = FrontCenter;
1515 device->ChannelName[5] = LFE;
1516 return;
1517 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1518 device->ChannelName[1] = FrontRight;
1519 device->ChannelName[2] = BackLeft;
1520 device->ChannelName[3] = BackRight;
1521 device->ChannelName[4] = FrontCenter;
1522 device->ChannelName[5] = LFE;
1523 device->ChannelName[6] = SideLeft;
1524 device->ChannelName[7] = SideRight;
1525 return;
1527 /* Same as WFX order */
1528 case DevFmtMono:
1529 case DevFmtStereo:
1530 case DevFmtQuad:
1531 case DevFmtX51Side:
1532 case DevFmtX61:
1533 SetDefaultWFXChannelOrder(device);
1534 break;
1539 /* alcSetError
1541 * Stores the latest ALC device error
1543 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1545 if(TrapALCError)
1547 #ifdef _WIN32
1548 /* DebugBreak() will cause an exception if there is no debugger */
1549 if(IsDebuggerPresent())
1550 DebugBreak();
1551 #elif defined(SIGTRAP)
1552 raise(SIGTRAP);
1553 #endif
1556 if(device)
1557 ATOMIC_STORE(&device->LastError, errorCode);
1558 else
1559 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1563 /* UpdateClockBase
1565 * Updates the device's base clock time with however many samples have been
1566 * done. This is used so frequency changes on the device don't cause the time
1567 * to jump forward or back.
1569 static inline void UpdateClockBase(ALCdevice *device)
1571 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1572 device->SamplesDone = 0;
1575 /* UpdateDeviceParams
1577 * Updates device parameters according to the attribute list (caller is
1578 * responsible for holding the list lock).
1580 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1582 ALCcontext *context;
1583 enum DevFmtChannels oldChans;
1584 enum DevFmtType oldType;
1585 ALCuint oldFreq;
1586 FPUCtl oldMode;
1588 // Check for attributes
1589 if(device->Type == Loopback)
1591 enum {
1592 GotFreq = 1<<0,
1593 GotChans = 1<<1,
1594 GotType = 1<<2,
1595 GotAll = GotFreq|GotChans|GotType
1597 ALCuint freq, numMono, numStereo, numSends, flags;
1598 enum DevFmtChannels schans;
1599 enum DevFmtType stype;
1600 ALCuint attrIdx = 0;
1601 ALCint gotFmt = 0;
1603 if(!attrList)
1605 WARN("Missing attributes for loopback device\n");
1606 return ALC_INVALID_VALUE;
1609 numMono = device->NumMonoSources;
1610 numStereo = device->NumStereoSources;
1611 numSends = device->NumAuxSends;
1612 schans = device->FmtChans;
1613 stype = device->FmtType;
1614 freq = device->Frequency;
1615 flags = device->Flags;
1617 while(attrList[attrIdx])
1619 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1621 ALCint val = attrList[attrIdx + 1];
1622 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1623 return ALC_INVALID_VALUE;
1624 schans = val;
1625 gotFmt |= GotChans;
1628 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1630 ALCint val = attrList[attrIdx + 1];
1631 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1632 return ALC_INVALID_VALUE;
1633 stype = val;
1634 gotFmt |= GotType;
1637 if(attrList[attrIdx] == ALC_FREQUENCY)
1639 freq = attrList[attrIdx + 1];
1640 if(freq < MIN_OUTPUT_RATE)
1641 return ALC_INVALID_VALUE;
1642 gotFmt |= GotFreq;
1645 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1647 numStereo = attrList[attrIdx + 1];
1648 if(numStereo > device->MaxNoOfSources)
1649 numStereo = device->MaxNoOfSources;
1651 numMono = device->MaxNoOfSources - numStereo;
1654 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1655 numSends = attrList[attrIdx + 1];
1657 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1659 if(attrList[attrIdx + 1] != ALC_FALSE)
1660 flags |= DEVICE_HRTF_REQUEST;
1661 else
1662 flags &= ~DEVICE_HRTF_REQUEST;
1665 attrIdx += 2;
1668 if(gotFmt != GotAll)
1670 WARN("Missing format for loopback device\n");
1671 return ALC_INVALID_VALUE;
1674 ConfigValueUInt(NULL, "sends", &numSends);
1675 numSends = minu(MAX_SENDS, numSends);
1677 if((device->Flags&DEVICE_RUNNING))
1678 V0(device->Backend,stop)();
1679 device->Flags = (flags & ~DEVICE_RUNNING);
1681 UpdateClockBase(device);
1683 device->Frequency = freq;
1684 device->FmtChans = schans;
1685 device->FmtType = stype;
1686 device->NumMonoSources = numMono;
1687 device->NumStereoSources = numStereo;
1688 device->NumAuxSends = numSends;
1690 else if(attrList && attrList[0])
1692 ALCuint freq, numMono, numStereo, numSends;
1693 ALCuint attrIdx = 0;
1695 /* If a context is already running on the device, stop playback so the
1696 * device attributes can be updated. */
1697 if((device->Flags&DEVICE_RUNNING))
1698 V0(device->Backend,stop)();
1699 device->Flags &= ~DEVICE_RUNNING;
1701 freq = device->Frequency;
1702 numMono = device->NumMonoSources;
1703 numStereo = device->NumStereoSources;
1704 numSends = device->NumAuxSends;
1706 while(attrList[attrIdx])
1708 if(attrList[attrIdx] == ALC_FREQUENCY)
1710 freq = attrList[attrIdx + 1];
1711 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1714 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1716 numStereo = attrList[attrIdx + 1];
1717 if(numStereo > device->MaxNoOfSources)
1718 numStereo = device->MaxNoOfSources;
1720 numMono = device->MaxNoOfSources - numStereo;
1723 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1724 numSends = attrList[attrIdx + 1];
1726 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1728 if(attrList[attrIdx + 1] != ALC_FALSE)
1729 device->Flags |= DEVICE_HRTF_REQUEST;
1730 else
1731 device->Flags &= ~DEVICE_HRTF_REQUEST;
1734 attrIdx += 2;
1737 ConfigValueUInt(NULL, "frequency", &freq);
1738 freq = maxu(freq, MIN_OUTPUT_RATE);
1740 ConfigValueUInt(NULL, "sends", &numSends);
1741 numSends = minu(MAX_SENDS, numSends);
1743 UpdateClockBase(device);
1745 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1746 device->Frequency;
1747 /* SSE and Neon do best with the update size being a multiple of 4 */
1748 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1749 device->UpdateSize = (device->UpdateSize+3)&~3;
1751 device->Frequency = freq;
1752 device->NumMonoSources = numMono;
1753 device->NumStereoSources = numStereo;
1754 device->NumAuxSends = numSends;
1757 if((device->Flags&DEVICE_RUNNING))
1758 return ALC_NO_ERROR;
1760 UpdateClockBase(device);
1762 if(device->Type != Loopback)
1764 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1765 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1766 device->Flags |= DEVICE_HRTF_REQUEST;
1767 else
1768 device->Flags &= ~DEVICE_HRTF_REQUEST;
1770 if((device->Flags&DEVICE_HRTF_REQUEST))
1772 enum DevFmtChannels chans = device->FmtChans;
1773 ALCuint freq = device->Frequency;
1774 if(FindHrtfFormat(&chans, &freq))
1776 if(device->Type != Loopback)
1778 device->Frequency = freq;
1779 device->FmtChans = chans;
1780 device->Flags |= DEVICE_CHANNELS_REQUEST |
1781 DEVICE_FREQUENCY_REQUEST;
1783 else if(device->Frequency != freq || device->FmtChans != chans)
1785 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1786 DevFmtChannelsString(device->FmtChans), device->Frequency);
1787 device->Flags &= ~DEVICE_HRTF_REQUEST;
1792 oldFreq = device->Frequency;
1793 oldChans = device->FmtChans;
1794 oldType = device->FmtType;
1796 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1797 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1798 DevFmtChannelsString(device->FmtChans),
1799 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1800 DevFmtTypeString(device->FmtType),
1801 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1802 device->Frequency,
1803 device->UpdateSize, device->NumUpdates);
1805 if(V0(device->Backend,reset)() == ALC_FALSE)
1806 return ALC_INVALID_DEVICE;
1808 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1810 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1811 DevFmtChannelsString(device->FmtChans));
1812 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1814 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1816 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1817 DevFmtTypeString(device->FmtType));
1818 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1820 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1822 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1823 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1826 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1827 DevFmtChannelsString(device->FmtChans),
1828 DevFmtTypeString(device->FmtType), device->Frequency,
1829 device->UpdateSize, device->NumUpdates);
1831 aluInitPanning(device);
1833 V(device->Synth,update)(device);
1835 device->Hrtf = NULL;
1836 if((device->Flags&DEVICE_HRTF_REQUEST))
1838 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1839 if(!device->Hrtf)
1840 device->Flags &= ~DEVICE_HRTF_REQUEST;
1842 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1844 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1846 if(!device->Bs2b)
1848 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1849 bs2b_clear(device->Bs2b);
1851 bs2b_set_srate(device->Bs2b, device->Frequency);
1852 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1853 TRACE("BS2B level %d\n", device->Bs2bLevel);
1855 else
1857 free(device->Bs2b);
1858 device->Bs2b = NULL;
1859 TRACE("BS2B disabled\n");
1862 device->Flags &= ~DEVICE_WIDE_STEREO;
1863 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1864 device->Flags |= DEVICE_WIDE_STEREO;
1866 if(!device->Hrtf && (device->UpdateSize&3))
1868 if((CPUCapFlags&CPU_CAP_SSE))
1869 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1870 if((CPUCapFlags&CPU_CAP_NEON))
1871 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1874 SetMixerFPUMode(&oldMode);
1875 ALCdevice_Lock(device);
1876 context = ATOMIC_LOAD(&device->ContextList);
1877 while(context)
1879 ALsizei pos;
1881 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
1882 LockUIntMapRead(&context->EffectSlotMap);
1883 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1885 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1887 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1889 UnlockUIntMapRead(&context->EffectSlotMap);
1890 ALCdevice_Unlock(device);
1891 RestoreFPUMode(&oldMode);
1892 return ALC_INVALID_DEVICE;
1894 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1895 V(slot->EffectState,update)(device, slot);
1897 UnlockUIntMapRead(&context->EffectSlotMap);
1899 LockUIntMapRead(&context->SourceMap);
1900 for(pos = 0;pos < context->SourceMap.size;pos++)
1902 ALsource *source = context->SourceMap.array[pos].value;
1903 ALuint s = device->NumAuxSends;
1904 while(s < MAX_SENDS)
1906 if(source->Send[s].Slot)
1907 DecrementRef(&source->Send[s].Slot->ref);
1908 source->Send[s].Slot = NULL;
1909 source->Send[s].Gain = 1.0f;
1910 source->Send[s].GainHF = 1.0f;
1911 s++;
1913 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
1915 UnlockUIntMapRead(&context->SourceMap);
1917 for(pos = 0;pos < context->VoiceCount;pos++)
1919 ALvoice *voice = &context->Voices[pos];
1920 ALsource *source = voice->Source;
1921 ALuint s = device->NumAuxSends;
1923 while(s < MAX_SENDS)
1925 voice->Send[s].Moving = AL_FALSE;
1926 voice->Send[s].Counter = 0;
1927 s++;
1930 if(source)
1932 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
1933 voice->Update(voice, source, context);
1937 context = context->next;
1939 if(device->DefaultSlot)
1941 ALeffectslot *slot = device->DefaultSlot;
1943 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1945 ALCdevice_Unlock(device);
1946 RestoreFPUMode(&oldMode);
1947 return ALC_INVALID_DEVICE;
1949 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1950 V(slot->EffectState,update)(device, slot);
1952 ALCdevice_Unlock(device);
1953 RestoreFPUMode(&oldMode);
1955 if(!(device->Flags&DEVICE_PAUSED))
1957 if(V0(device->Backend,start)() == ALC_FALSE)
1958 return ALC_INVALID_DEVICE;
1959 device->Flags |= DEVICE_RUNNING;
1962 return ALC_NO_ERROR;
1965 /* FreeDevice
1967 * Frees the device structure, and destroys any objects the app failed to
1968 * delete. Called once there's no more references on the device.
1970 static ALCvoid FreeDevice(ALCdevice *device)
1972 TRACE("%p\n", device);
1974 V0(device->Backend,close)();
1975 DELETE_OBJ(device->Backend);
1976 device->Backend = NULL;
1978 DELETE_OBJ(device->Synth);
1979 device->Synth = NULL;
1981 if(device->DefaultSlot)
1983 ALeffectState *state = device->DefaultSlot->EffectState;
1984 device->DefaultSlot = NULL;
1985 DELETE_OBJ(state);
1988 if(device->DefaultSfont)
1989 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1990 device->DefaultSfont = NULL;
1992 if(device->BufferMap.size > 0)
1994 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1995 ReleaseALBuffers(device);
1997 ResetUIntMap(&device->BufferMap);
1999 if(device->EffectMap.size > 0)
2001 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2002 ReleaseALEffects(device);
2004 ResetUIntMap(&device->EffectMap);
2006 if(device->FilterMap.size > 0)
2008 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2009 ReleaseALFilters(device);
2011 ResetUIntMap(&device->FilterMap);
2013 if(device->SfontMap.size > 0)
2015 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2016 ReleaseALSoundfonts(device);
2018 ResetUIntMap(&device->SfontMap);
2020 if(device->PresetMap.size > 0)
2022 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2023 ReleaseALPresets(device);
2025 ResetUIntMap(&device->PresetMap);
2027 if(device->FontsoundMap.size > 0)
2029 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2030 ReleaseALFontsounds(device);
2032 ResetUIntMap(&device->FontsoundMap);
2034 free(device->Bs2b);
2035 device->Bs2b = NULL;
2037 AL_STRING_DEINIT(device->DeviceName);
2039 al_free(device);
2043 void ALCdevice_IncRef(ALCdevice *device)
2045 uint ref;
2046 ref = IncrementRef(&device->ref);
2047 TRACEREF("%p increasing refcount to %u\n", device, ref);
2050 void ALCdevice_DecRef(ALCdevice *device)
2052 uint ref;
2053 ref = DecrementRef(&device->ref);
2054 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2055 if(ref == 0) FreeDevice(device);
2058 /* VerifyDevice
2060 * Checks if the device handle is valid, and increments its ref count if so.
2062 static ALCdevice *VerifyDevice(ALCdevice *device)
2064 ALCdevice *tmpDevice;
2066 if(!device)
2067 return NULL;
2069 LockLists();
2070 tmpDevice = ATOMIC_LOAD(&DeviceList);
2071 while(tmpDevice && tmpDevice != device)
2072 tmpDevice = tmpDevice->next;
2074 if(tmpDevice)
2075 ALCdevice_IncRef(tmpDevice);
2076 UnlockLists();
2077 return tmpDevice;
2081 /* InitContext
2083 * Initializes context fields
2085 static ALvoid InitContext(ALCcontext *Context)
2087 ALint i, j;
2089 //Initialise listener
2090 Context->Listener->Gain = 1.0f;
2091 Context->Listener->MetersPerUnit = 1.0f;
2092 Context->Listener->Position[0] = 0.0f;
2093 Context->Listener->Position[1] = 0.0f;
2094 Context->Listener->Position[2] = 0.0f;
2095 Context->Listener->Velocity[0] = 0.0f;
2096 Context->Listener->Velocity[1] = 0.0f;
2097 Context->Listener->Velocity[2] = 0.0f;
2098 Context->Listener->Forward[0] = 0.0f;
2099 Context->Listener->Forward[1] = 0.0f;
2100 Context->Listener->Forward[2] = -1.0f;
2101 Context->Listener->Up[0] = 0.0f;
2102 Context->Listener->Up[1] = 1.0f;
2103 Context->Listener->Up[2] = 0.0f;
2104 for(i = 0;i < 4;i++)
2106 for(j = 0;j < 4;j++)
2107 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2109 for(i = 0;i < 3;i++)
2110 Context->Listener->Params.Velocity[i] = 0.0f;
2112 //Validate Context
2113 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2114 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2115 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2116 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2118 //Set globals
2119 Context->DistanceModel = DefaultDistanceModel;
2120 Context->SourceDistanceModel = AL_FALSE;
2121 Context->DopplerFactor = 1.0f;
2122 Context->DopplerVelocity = 1.0f;
2123 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2124 Context->DeferUpdates = AL_FALSE;
2126 Context->ExtensionList = alExtList;
2130 /* FreeContext
2132 * Cleans up the context, and destroys any remaining objects the app failed to
2133 * delete. Called once there's no more references on the context.
2135 static void FreeContext(ALCcontext *context)
2137 TRACE("%p\n", context);
2139 if(context->SourceMap.size > 0)
2141 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2142 ReleaseALSources(context);
2144 ResetUIntMap(&context->SourceMap);
2146 if(context->EffectSlotMap.size > 0)
2148 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2149 ReleaseALAuxiliaryEffectSlots(context);
2151 ResetUIntMap(&context->EffectSlotMap);
2153 al_free(context->Voices);
2154 context->Voices = NULL;
2155 context->VoiceCount = 0;
2156 context->MaxVoices = 0;
2158 VECTOR_DEINIT(context->ActiveAuxSlots);
2160 ALCdevice_DecRef(context->Device);
2161 context->Device = NULL;
2163 //Invalidate context
2164 memset(context, 0, sizeof(ALCcontext));
2165 al_free(context);
2168 /* ReleaseContext
2170 * Removes the context reference from the given device and removes it from
2171 * being current on the running thread or globally.
2173 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2175 ALCcontext *nextctx;
2176 ALCcontext *origctx;
2178 if(altss_get(LocalContext) == context)
2180 WARN("%p released while current on thread\n", context);
2181 altss_set(LocalContext, NULL);
2182 ALCcontext_DecRef(context);
2185 origctx = context;
2186 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2187 ALCcontext_DecRef(context);
2189 ALCdevice_Lock(device);
2190 origctx = context;
2191 nextctx = context->next;
2192 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2194 ALCcontext *list;
2195 do {
2196 list = origctx;
2197 origctx = context;
2198 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2200 ALCdevice_Unlock(device);
2202 ALCcontext_DecRef(context);
2205 void ALCcontext_IncRef(ALCcontext *context)
2207 uint ref;
2208 ref = IncrementRef(&context->ref);
2209 TRACEREF("%p increasing refcount to %u\n", context, ref);
2212 void ALCcontext_DecRef(ALCcontext *context)
2214 uint ref;
2215 ref = DecrementRef(&context->ref);
2216 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2217 if(ref == 0) FreeContext(context);
2220 static void ReleaseThreadCtx(void *ptr)
2222 WARN("%p current for thread being destroyed\n", ptr);
2223 ALCcontext_DecRef(ptr);
2226 /* VerifyContext
2228 * Checks that the given context is valid, and increments its reference count.
2230 static ALCcontext *VerifyContext(ALCcontext *context)
2232 ALCdevice *dev;
2234 LockLists();
2235 dev = ATOMIC_LOAD(&DeviceList);
2236 while(dev)
2238 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2239 while(ctx)
2241 if(ctx == context)
2243 ALCcontext_IncRef(ctx);
2244 UnlockLists();
2245 return ctx;
2247 ctx = ctx->next;
2249 dev = dev->next;
2251 UnlockLists();
2253 return NULL;
2257 /* GetContextRef
2259 * Returns the currently active context for this thread, and adds a reference
2260 * without locking it.
2262 ALCcontext *GetContextRef(void)
2264 ALCcontext *context;
2266 context = altss_get(LocalContext);
2267 if(context)
2268 ALCcontext_IncRef(context);
2269 else
2271 LockLists();
2272 context = ATOMIC_LOAD(&GlobalContext);
2273 if(context)
2274 ALCcontext_IncRef(context);
2275 UnlockLists();
2278 return context;
2282 /************************************************
2283 * Standard ALC functions
2284 ************************************************/
2286 /* alcGetError
2288 * Return last ALC generated error code for the given device
2290 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2292 ALCenum errorCode;
2294 if(VerifyDevice(device))
2296 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2297 ALCdevice_DecRef(device);
2299 else
2300 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2302 return errorCode;
2306 /* alcSuspendContext
2308 * Not functional
2310 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2314 /* alcProcessContext
2316 * Not functional
2318 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2323 /* alcGetString
2325 * Returns information about the device, and error strings
2327 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2329 const ALCchar *value = NULL;
2331 switch(param)
2333 case ALC_NO_ERROR:
2334 value = alcNoError;
2335 break;
2337 case ALC_INVALID_ENUM:
2338 value = alcErrInvalidEnum;
2339 break;
2341 case ALC_INVALID_VALUE:
2342 value = alcErrInvalidValue;
2343 break;
2345 case ALC_INVALID_DEVICE:
2346 value = alcErrInvalidDevice;
2347 break;
2349 case ALC_INVALID_CONTEXT:
2350 value = alcErrInvalidContext;
2351 break;
2353 case ALC_OUT_OF_MEMORY:
2354 value = alcErrOutOfMemory;
2355 break;
2357 case ALC_DEVICE_SPECIFIER:
2358 value = alcDefaultName;
2359 break;
2361 case ALC_ALL_DEVICES_SPECIFIER:
2362 if(VerifyDevice(Device))
2364 value = al_string_get_cstr(Device->DeviceName);
2365 ALCdevice_DecRef(Device);
2367 else
2369 ProbeAllDevicesList();
2370 value = al_string_get_cstr(alcAllDevicesList);
2372 break;
2374 case ALC_CAPTURE_DEVICE_SPECIFIER:
2375 if(VerifyDevice(Device))
2377 value = al_string_get_cstr(Device->DeviceName);
2378 ALCdevice_DecRef(Device);
2380 else
2382 ProbeCaptureDeviceList();
2383 value = al_string_get_cstr(alcCaptureDeviceList);
2385 break;
2387 /* Default devices are always first in the list */
2388 case ALC_DEFAULT_DEVICE_SPECIFIER:
2389 value = alcDefaultName;
2390 break;
2392 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2393 if(al_string_empty(alcAllDevicesList))
2394 ProbeAllDevicesList();
2396 Device = VerifyDevice(Device);
2398 free(alcDefaultAllDevicesSpecifier);
2399 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2400 if(!alcDefaultAllDevicesSpecifier)
2401 alcSetError(Device, ALC_OUT_OF_MEMORY);
2403 value = alcDefaultAllDevicesSpecifier;
2404 if(Device) ALCdevice_DecRef(Device);
2405 break;
2407 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2408 if(al_string_empty(alcCaptureDeviceList))
2409 ProbeCaptureDeviceList();
2411 Device = VerifyDevice(Device);
2413 free(alcCaptureDefaultDeviceSpecifier);
2414 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2415 if(!alcCaptureDefaultDeviceSpecifier)
2416 alcSetError(Device, ALC_OUT_OF_MEMORY);
2418 value = alcCaptureDefaultDeviceSpecifier;
2419 if(Device) ALCdevice_DecRef(Device);
2420 break;
2422 case ALC_EXTENSIONS:
2423 if(!VerifyDevice(Device))
2424 value = alcNoDeviceExtList;
2425 else
2427 value = alcExtensionList;
2428 ALCdevice_DecRef(Device);
2430 break;
2432 default:
2433 Device = VerifyDevice(Device);
2434 alcSetError(Device, ALC_INVALID_ENUM);
2435 if(Device) ALCdevice_DecRef(Device);
2436 break;
2439 return value;
2443 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2445 ALCsizei i;
2447 if(size <= 0 || values == NULL)
2449 alcSetError(device, ALC_INVALID_VALUE);
2450 return 0;
2453 if(!device)
2455 switch(param)
2457 case ALC_MAJOR_VERSION:
2458 values[0] = alcMajorVersion;
2459 return 1;
2460 case ALC_MINOR_VERSION:
2461 values[0] = alcMinorVersion;
2462 return 1;
2464 case ALC_ATTRIBUTES_SIZE:
2465 case ALC_ALL_ATTRIBUTES:
2466 case ALC_FREQUENCY:
2467 case ALC_REFRESH:
2468 case ALC_SYNC:
2469 case ALC_MONO_SOURCES:
2470 case ALC_STEREO_SOURCES:
2471 case ALC_CAPTURE_SAMPLES:
2472 case ALC_FORMAT_CHANNELS_SOFT:
2473 case ALC_FORMAT_TYPE_SOFT:
2474 alcSetError(NULL, ALC_INVALID_DEVICE);
2475 return 0;
2477 default:
2478 alcSetError(NULL, ALC_INVALID_ENUM);
2479 return 0;
2481 return 0;
2484 if(device->Type == Capture)
2486 switch(param)
2488 case ALC_CAPTURE_SAMPLES:
2489 ALCdevice_Lock(device);
2490 values[0] = V0(device->Backend,availableSamples)();
2491 ALCdevice_Unlock(device);
2492 return 1;
2494 case ALC_CONNECTED:
2495 values[0] = device->Connected;
2496 return 1;
2498 default:
2499 alcSetError(device, ALC_INVALID_ENUM);
2500 return 0;
2502 return 0;
2505 /* render device */
2506 switch(param)
2508 case ALC_MAJOR_VERSION:
2509 values[0] = alcMajorVersion;
2510 return 1;
2512 case ALC_MINOR_VERSION:
2513 values[0] = alcMinorVersion;
2514 return 1;
2516 case ALC_EFX_MAJOR_VERSION:
2517 values[0] = alcEFXMajorVersion;
2518 return 1;
2520 case ALC_EFX_MINOR_VERSION:
2521 values[0] = alcEFXMinorVersion;
2522 return 1;
2524 case ALC_ATTRIBUTES_SIZE:
2525 values[0] = 15;
2526 return 1;
2528 case ALC_ALL_ATTRIBUTES:
2529 if(size < 15)
2531 alcSetError(device, ALC_INVALID_VALUE);
2532 return 0;
2535 i = 0;
2536 values[i++] = ALC_FREQUENCY;
2537 values[i++] = device->Frequency;
2539 if(device->Type != Loopback)
2541 values[i++] = ALC_REFRESH;
2542 values[i++] = device->Frequency / device->UpdateSize;
2544 values[i++] = ALC_SYNC;
2545 values[i++] = ALC_FALSE;
2547 else
2549 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2550 values[i++] = device->FmtChans;
2552 values[i++] = ALC_FORMAT_TYPE_SOFT;
2553 values[i++] = device->FmtType;
2556 values[i++] = ALC_MONO_SOURCES;
2557 values[i++] = device->NumMonoSources;
2559 values[i++] = ALC_STEREO_SOURCES;
2560 values[i++] = device->NumStereoSources;
2562 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2563 values[i++] = device->NumAuxSends;
2565 values[i++] = ALC_HRTF_SOFT;
2566 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2568 values[i++] = 0;
2569 return i;
2571 case ALC_FREQUENCY:
2572 values[0] = device->Frequency;
2573 return 1;
2575 case ALC_REFRESH:
2576 if(device->Type == Loopback)
2578 alcSetError(device, ALC_INVALID_DEVICE);
2579 return 0;
2581 values[0] = device->Frequency / device->UpdateSize;
2582 return 1;
2584 case ALC_SYNC:
2585 if(device->Type == Loopback)
2587 alcSetError(device, ALC_INVALID_DEVICE);
2588 return 0;
2590 values[0] = ALC_FALSE;
2591 return 1;
2593 case ALC_FORMAT_CHANNELS_SOFT:
2594 if(device->Type != Loopback)
2596 alcSetError(device, ALC_INVALID_DEVICE);
2597 return 0;
2599 values[0] = device->FmtChans;
2600 return 1;
2602 case ALC_FORMAT_TYPE_SOFT:
2603 if(device->Type != Loopback)
2605 alcSetError(device, ALC_INVALID_DEVICE);
2606 return 0;
2608 values[0] = device->FmtType;
2609 return 1;
2611 case ALC_MONO_SOURCES:
2612 values[0] = device->NumMonoSources;
2613 return 1;
2615 case ALC_STEREO_SOURCES:
2616 values[0] = device->NumStereoSources;
2617 return 1;
2619 case ALC_MAX_AUXILIARY_SENDS:
2620 values[0] = device->NumAuxSends;
2621 return 1;
2623 case ALC_CONNECTED:
2624 values[0] = device->Connected;
2625 return 1;
2627 case ALC_HRTF_SOFT:
2628 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2629 return 1;
2631 default:
2632 alcSetError(device, ALC_INVALID_ENUM);
2633 return 0;
2635 return 0;
2638 /* alcGetIntegerv
2640 * Returns information about the device and the version of OpenAL
2642 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2644 device = VerifyDevice(device);
2645 if(size <= 0 || values == NULL)
2646 alcSetError(device, ALC_INVALID_VALUE);
2647 else
2648 GetIntegerv(device, param, size, values);
2649 if(device) ALCdevice_DecRef(device);
2652 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2654 ALCint *ivals;
2655 ALsizei i;
2657 device = VerifyDevice(device);
2658 if(size <= 0 || values == NULL)
2659 alcSetError(device, ALC_INVALID_VALUE);
2660 else if(!device || device->Type == Capture)
2662 ivals = malloc(size * sizeof(ALCint));
2663 size = GetIntegerv(device, pname, size, ivals);
2664 for(i = 0;i < size;i++)
2665 values[i] = ivals[i];
2666 free(ivals);
2668 else /* render device */
2670 switch(pname)
2672 case ALC_ATTRIBUTES_SIZE:
2673 *values = 17;
2674 break;
2676 case ALC_ALL_ATTRIBUTES:
2677 if(size < 17)
2678 alcSetError(device, ALC_INVALID_VALUE);
2679 else
2681 int i = 0;
2683 V0(device->Backend,lock)();
2684 values[i++] = ALC_FREQUENCY;
2685 values[i++] = device->Frequency;
2687 if(device->Type != Loopback)
2689 values[i++] = ALC_REFRESH;
2690 values[i++] = device->Frequency / device->UpdateSize;
2692 values[i++] = ALC_SYNC;
2693 values[i++] = ALC_FALSE;
2695 else
2697 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2698 values[i++] = device->FmtChans;
2700 values[i++] = ALC_FORMAT_TYPE_SOFT;
2701 values[i++] = device->FmtType;
2704 values[i++] = ALC_MONO_SOURCES;
2705 values[i++] = device->NumMonoSources;
2707 values[i++] = ALC_STEREO_SOURCES;
2708 values[i++] = device->NumStereoSources;
2710 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2711 values[i++] = device->NumAuxSends;
2713 values[i++] = ALC_HRTF_SOFT;
2714 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2716 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2717 values[i++] = device->ClockBase +
2718 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2720 values[i++] = 0;
2721 V0(device->Backend,unlock)();
2723 break;
2725 case ALC_DEVICE_CLOCK_SOFT:
2726 V0(device->Backend,lock)();
2727 *values = device->ClockBase +
2728 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2729 V0(device->Backend,unlock)();
2730 break;
2732 default:
2733 ivals = malloc(size * sizeof(ALCint));
2734 size = GetIntegerv(device, pname, size, ivals);
2735 for(i = 0;i < size;i++)
2736 values[i] = ivals[i];
2737 free(ivals);
2738 break;
2741 if(device)
2742 ALCdevice_DecRef(device);
2746 /* alcIsExtensionPresent
2748 * Determines if there is support for a particular extension
2750 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2752 ALCboolean bResult = ALC_FALSE;
2754 device = VerifyDevice(device);
2756 if(!extName)
2757 alcSetError(device, ALC_INVALID_VALUE);
2758 else
2760 size_t len = strlen(extName);
2761 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2762 while(ptr && *ptr)
2764 if(strncasecmp(ptr, extName, len) == 0 &&
2765 (ptr[len] == '\0' || isspace(ptr[len])))
2767 bResult = ALC_TRUE;
2768 break;
2770 if((ptr=strchr(ptr, ' ')) != NULL)
2772 do {
2773 ++ptr;
2774 } while(isspace(*ptr));
2778 if(device)
2779 ALCdevice_DecRef(device);
2780 return bResult;
2784 /* alcGetProcAddress
2786 * Retrieves the function address for a particular extension function
2788 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2790 ALCvoid *ptr = NULL;
2792 if(!funcName)
2794 device = VerifyDevice(device);
2795 alcSetError(device, ALC_INVALID_VALUE);
2796 if(device) ALCdevice_DecRef(device);
2798 else
2800 ALsizei i = 0;
2801 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2802 i++;
2803 ptr = alcFunctions[i].address;
2806 return ptr;
2810 /* alcGetEnumValue
2812 * Get the value for a particular ALC enumeration name
2814 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2816 ALCenum val = 0;
2818 if(!enumName)
2820 device = VerifyDevice(device);
2821 alcSetError(device, ALC_INVALID_VALUE);
2822 if(device) ALCdevice_DecRef(device);
2824 else
2826 ALsizei i = 0;
2827 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2828 i++;
2829 val = enumeration[i].value;
2832 return val;
2836 /* alcCreateContext
2838 * Create and attach a context to the given device.
2840 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2842 ALCcontext *ALContext;
2843 ALCenum err;
2845 LockLists();
2846 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2848 UnlockLists();
2849 alcSetError(device, ALC_INVALID_DEVICE);
2850 if(device) ALCdevice_DecRef(device);
2851 return NULL;
2854 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
2856 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2858 UnlockLists();
2859 alcSetError(device, err);
2860 if(err == ALC_INVALID_DEVICE)
2862 ALCdevice_Lock(device);
2863 aluHandleDisconnect(device);
2864 ALCdevice_Unlock(device);
2866 ALCdevice_DecRef(device);
2867 return NULL;
2870 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
2871 if(ALContext)
2873 InitRef(&ALContext->ref, 1);
2874 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2876 VECTOR_INIT(ALContext->ActiveAuxSlots);
2878 ALContext->VoiceCount = 0;
2879 ALContext->MaxVoices = 256;
2880 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
2882 if(!ALContext || !ALContext->Voices)
2884 if(!ATOMIC_LOAD(&device->ContextList))
2886 V0(device->Backend,stop)();
2887 device->Flags &= ~DEVICE_RUNNING;
2889 UnlockLists();
2891 if(ALContext)
2893 al_free(ALContext->Voices);
2894 ALContext->Voices = NULL;
2896 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2898 al_free(ALContext);
2899 ALContext = NULL;
2902 alcSetError(device, ALC_OUT_OF_MEMORY);
2903 ALCdevice_DecRef(device);
2904 return NULL;
2907 ALContext->Device = device;
2908 ALCdevice_IncRef(device);
2909 InitContext(ALContext);
2912 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
2913 do {
2914 ALContext->next = head;
2915 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
2917 UnlockLists();
2919 ALCdevice_DecRef(device);
2921 TRACE("Created context %p\n", ALContext);
2922 return ALContext;
2925 /* alcDestroyContext
2927 * Remove a context from its device
2929 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2931 ALCdevice *Device;
2933 LockLists();
2934 /* alcGetContextsDevice sets an error for invalid contexts */
2935 Device = alcGetContextsDevice(context);
2936 if(Device)
2938 ReleaseContext(context, Device);
2939 if(!ATOMIC_LOAD(&Device->ContextList))
2941 V0(Device->Backend,stop)();
2942 Device->Flags &= ~DEVICE_RUNNING;
2945 UnlockLists();
2949 /* alcGetCurrentContext
2951 * Returns the currently active context on the calling thread
2953 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2955 ALCcontext *Context = altss_get(LocalContext);
2956 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
2957 return Context;
2960 /* alcGetThreadContext
2962 * Returns the currently active thread-local context
2964 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2966 return altss_get(LocalContext);
2970 /* alcMakeContextCurrent
2972 * Makes the given context the active process-wide context, and removes the
2973 * thread-local context for the calling thread.
2975 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2977 /* context must be valid or NULL */
2978 if(context && !(context=VerifyContext(context)))
2980 alcSetError(NULL, ALC_INVALID_CONTEXT);
2981 return ALC_FALSE;
2983 /* context's reference count is already incremented */
2984 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
2985 if(context) ALCcontext_DecRef(context);
2987 if((context=altss_get(LocalContext)) != NULL)
2989 altss_set(LocalContext, NULL);
2990 ALCcontext_DecRef(context);
2993 return ALC_TRUE;
2996 /* alcSetThreadContext
2998 * Makes the given context the active context for the current thread
3000 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3002 ALCcontext *old;
3004 /* context must be valid or NULL */
3005 if(context && !(context=VerifyContext(context)))
3007 alcSetError(NULL, ALC_INVALID_CONTEXT);
3008 return ALC_FALSE;
3010 /* context's reference count is already incremented */
3011 old = altss_get(LocalContext);
3012 altss_set(LocalContext, context);
3013 if(old) ALCcontext_DecRef(old);
3015 return ALC_TRUE;
3019 /* alcGetContextsDevice
3021 * Returns the device that a particular context is attached to
3023 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3025 ALCdevice *Device;
3027 if(!(Context=VerifyContext(Context)))
3029 alcSetError(NULL, ALC_INVALID_CONTEXT);
3030 return NULL;
3032 Device = Context->Device;
3033 ALCcontext_DecRef(Context);
3035 return Device;
3039 /* alcOpenDevice
3041 * Opens the named device.
3043 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3045 const ALCchar *fmt;
3046 ALCdevice *device;
3047 ALCenum err;
3049 DO_INITCONFIG();
3051 if(!PlaybackBackend.name)
3053 alcSetError(NULL, ALC_INVALID_VALUE);
3054 return NULL;
3057 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3058 deviceName = NULL;
3060 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3061 if(!device)
3063 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3064 return NULL;
3067 //Validate device
3068 InitRef(&device->ref, 1);
3069 device->Connected = ALC_TRUE;
3070 device->Type = Playback;
3071 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3073 device->Flags = 0;
3074 device->Bs2b = NULL;
3075 device->Bs2bLevel = 0;
3076 AL_STRING_INIT(device->DeviceName);
3078 ATOMIC_INIT(&device->ContextList, NULL);
3080 device->ClockBase = 0;
3081 device->SamplesDone = 0;
3083 device->MaxNoOfSources = 256;
3084 device->AuxiliaryEffectSlotMax = 4;
3085 device->NumAuxSends = MAX_SENDS;
3087 InitUIntMap(&device->BufferMap, ~0);
3088 InitUIntMap(&device->EffectMap, ~0);
3089 InitUIntMap(&device->FilterMap, ~0);
3090 InitUIntMap(&device->SfontMap, ~0);
3091 InitUIntMap(&device->PresetMap, ~0);
3092 InitUIntMap(&device->FontsoundMap, ~0);
3094 //Set output format
3095 device->FmtChans = DevFmtChannelsDefault;
3096 device->FmtType = DevFmtTypeDefault;
3097 device->Frequency = DEFAULT_OUTPUT_RATE;
3098 device->NumUpdates = 4;
3099 device->UpdateSize = 1024;
3101 if(!PlaybackBackend.getFactory)
3102 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3103 ALCbackend_Playback);
3104 else
3106 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3107 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3109 if(!device->Backend)
3111 al_free(device);
3112 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3113 return NULL;
3117 if(ConfigValueStr(NULL, "channels", &fmt))
3119 static const struct {
3120 const char name[16];
3121 enum DevFmtChannels chans;
3122 } chanlist[] = {
3123 { "mono", DevFmtMono },
3124 { "stereo", DevFmtStereo },
3125 { "quad", DevFmtQuad },
3126 { "surround51", DevFmtX51 },
3127 { "surround61", DevFmtX61 },
3128 { "surround71", DevFmtX71 },
3130 size_t i;
3132 for(i = 0;i < COUNTOF(chanlist);i++)
3134 if(strcasecmp(chanlist[i].name, fmt) == 0)
3136 device->FmtChans = chanlist[i].chans;
3137 device->Flags |= DEVICE_CHANNELS_REQUEST;
3138 break;
3141 if(i == COUNTOF(chanlist))
3142 ERR("Unsupported channels: %s\n", fmt);
3144 if(ConfigValueStr(NULL, "sample-type", &fmt))
3146 static const struct {
3147 const char name[16];
3148 enum DevFmtType type;
3149 } typelist[] = {
3150 { "int8", DevFmtByte },
3151 { "uint8", DevFmtUByte },
3152 { "int16", DevFmtShort },
3153 { "uint16", DevFmtUShort },
3154 { "int32", DevFmtInt },
3155 { "uint32", DevFmtUInt },
3156 { "float32", DevFmtFloat },
3158 size_t i;
3160 for(i = 0;i < COUNTOF(typelist);i++)
3162 if(strcasecmp(typelist[i].name, fmt) == 0)
3164 device->FmtType = typelist[i].type;
3165 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3166 break;
3169 if(i == COUNTOF(typelist))
3170 ERR("Unsupported sample-type: %s\n", fmt);
3172 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3173 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3174 ConfigValueStr(NULL, "format", &fmt))
3176 static const struct {
3177 const char name[32];
3178 enum DevFmtChannels channels;
3179 enum DevFmtType type;
3180 } formats[] = {
3181 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3182 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3183 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3184 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3185 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3186 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3188 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3189 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3190 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3191 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3192 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3193 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3195 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3196 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3197 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3198 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3199 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3200 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3202 size_t i;
3204 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3205 for(i = 0;i < COUNTOF(formats);i++)
3207 if(strcasecmp(fmt, formats[i].name) == 0)
3209 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3210 device->FmtChans = formats[i].channels;
3211 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3212 device->FmtType = formats[i].type;
3213 device->Flags |= DEVICE_FORMAT_REQUEST;
3214 break;
3217 if(i == COUNTOF(formats))
3218 ERR("Unsupported format: %s\n", fmt);
3220 #undef DEVICE_FORMAT_REQUEST
3222 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3224 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3225 if(device->Frequency < MIN_OUTPUT_RATE)
3226 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3227 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3230 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3231 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3233 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3234 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3235 if((CPUCapFlags&CPU_CAP_SSE))
3236 device->UpdateSize = (device->UpdateSize+3)&~3;
3238 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3239 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3241 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3242 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3244 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3245 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3247 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3249 device->NumStereoSources = 1;
3250 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3252 device->Synth = SynthCreate(device);
3253 if(!device->Synth)
3255 DELETE_OBJ(device->Backend);
3256 al_free(device);
3257 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3258 return NULL;
3261 // Find a playback device to open
3262 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3264 DELETE_OBJ(device->Synth);
3265 DELETE_OBJ(device->Backend);
3266 al_free(device);
3267 alcSetError(NULL, err);
3268 return NULL;
3271 if(DefaultEffect.type != AL_EFFECT_NULL)
3273 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3274 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3276 device->DefaultSlot = NULL;
3277 ERR("Failed to initialize the default effect slot\n");
3279 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3281 ALeffectState *state = device->DefaultSlot->EffectState;
3282 device->DefaultSlot = NULL;
3283 DELETE_OBJ(state);
3284 ERR("Failed to initialize the default effect\n");
3289 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3290 do {
3291 device->next = head;
3292 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3295 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3296 return device;
3299 /* alcCloseDevice
3301 * Closes the given device.
3303 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3305 ALCdevice *list, *origdev, *nextdev;
3306 ALCcontext *ctx;
3308 LockLists();
3309 list = ATOMIC_LOAD(&DeviceList);
3310 do {
3311 if(list == device)
3312 break;
3313 } while((list=list->next) != NULL);
3314 if(!list || list->Type == Capture)
3316 alcSetError(list, ALC_INVALID_DEVICE);
3317 UnlockLists();
3318 return ALC_FALSE;
3321 origdev = device;
3322 nextdev = device->next;
3323 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3325 do {
3326 list = origdev;
3327 origdev = device;
3328 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3330 UnlockLists();
3332 ctx = ATOMIC_LOAD(&device->ContextList);
3333 while(ctx != NULL)
3335 ALCcontext *next = ctx->next;
3336 WARN("Releasing context %p\n", ctx);
3337 ReleaseContext(ctx, device);
3338 ctx = next;
3340 if((device->Flags&DEVICE_RUNNING))
3341 V0(device->Backend,stop)();
3342 device->Flags &= ~DEVICE_RUNNING;
3344 ALCdevice_DecRef(device);
3346 return ALC_TRUE;
3350 /************************************************
3351 * ALC capture functions
3352 ************************************************/
3353 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3355 ALCdevice *device = NULL;
3356 ALCenum err;
3358 DO_INITCONFIG();
3360 if(!CaptureBackend.name)
3362 alcSetError(NULL, ALC_INVALID_VALUE);
3363 return NULL;
3366 if(samples <= 0)
3368 alcSetError(NULL, ALC_INVALID_VALUE);
3369 return NULL;
3372 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3373 deviceName = NULL;
3375 device = al_calloc(16, sizeof(ALCdevice));
3376 if(!device)
3378 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3379 return NULL;
3382 //Validate device
3383 InitRef(&device->ref, 1);
3384 device->Connected = ALC_TRUE;
3385 device->Type = Capture;
3387 AL_STRING_INIT(device->DeviceName);
3389 InitUIntMap(&device->BufferMap, ~0);
3390 InitUIntMap(&device->EffectMap, ~0);
3391 InitUIntMap(&device->FilterMap, ~0);
3392 InitUIntMap(&device->SfontMap, ~0);
3393 InitUIntMap(&device->PresetMap, ~0);
3394 InitUIntMap(&device->FontsoundMap, ~0);
3396 if(!CaptureBackend.getFactory)
3397 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3398 ALCbackend_Capture);
3399 else
3401 ALCbackendFactory *factory = CaptureBackend.getFactory();
3402 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3404 if(!device->Backend)
3406 al_free(device);
3407 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3408 return NULL;
3411 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3412 device->Frequency = frequency;
3414 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3415 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3417 al_free(device);
3418 alcSetError(NULL, ALC_INVALID_ENUM);
3419 return NULL;
3422 device->UpdateSize = samples;
3423 device->NumUpdates = 1;
3425 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3427 al_free(device);
3428 alcSetError(NULL, err);
3429 return NULL;
3433 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3434 do {
3435 device->next = head;
3436 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3439 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3440 return device;
3443 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3445 ALCdevice *list, *next, *nextdev;
3447 LockLists();
3448 list = ATOMIC_LOAD(&DeviceList);
3449 do {
3450 if(list == device)
3451 break;
3452 } while((list=list->next) != NULL);
3453 if(!list || list->Type != Capture)
3455 alcSetError(list, ALC_INVALID_DEVICE);
3456 UnlockLists();
3457 return ALC_FALSE;
3460 next = device;
3461 nextdev = device->next;
3462 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3464 do {
3465 list = next;
3466 next = device;
3467 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3469 UnlockLists();
3471 ALCdevice_DecRef(device);
3473 return ALC_TRUE;
3476 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3478 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3479 alcSetError(device, ALC_INVALID_DEVICE);
3480 else
3482 ALCdevice_Lock(device);
3483 if(device->Connected)
3485 if(!(device->Flags&DEVICE_RUNNING))
3486 V0(device->Backend,start)();
3487 device->Flags |= DEVICE_RUNNING;
3489 ALCdevice_Unlock(device);
3492 if(device) ALCdevice_DecRef(device);
3495 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3497 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3498 alcSetError(device, ALC_INVALID_DEVICE);
3499 else
3501 ALCdevice_Lock(device);
3502 if((device->Flags&DEVICE_RUNNING))
3503 V0(device->Backend,stop)();
3504 device->Flags &= ~DEVICE_RUNNING;
3505 ALCdevice_Unlock(device);
3508 if(device) ALCdevice_DecRef(device);
3511 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3513 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3514 alcSetError(device, ALC_INVALID_DEVICE);
3515 else
3517 ALCenum err = ALC_INVALID_VALUE;
3519 ALCdevice_Lock(device);
3520 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3521 err = V(device->Backend,captureSamples)(buffer, samples);
3522 ALCdevice_Unlock(device);
3524 if(err != ALC_NO_ERROR)
3525 alcSetError(device, err);
3527 if(device) ALCdevice_DecRef(device);
3531 /************************************************
3532 * ALC loopback functions
3533 ************************************************/
3535 /* alcLoopbackOpenDeviceSOFT
3537 * Open a loopback device, for manual rendering.
3539 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3541 ALCbackendFactory *factory;
3542 ALCdevice *device;
3544 DO_INITCONFIG();
3546 /* Make sure the device name, if specified, is us. */
3547 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3549 alcSetError(NULL, ALC_INVALID_VALUE);
3550 return NULL;
3553 device = al_calloc(16, sizeof(ALCdevice));
3554 if(!device)
3556 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3557 return NULL;
3560 //Validate device
3561 InitRef(&device->ref, 1);
3562 device->Connected = ALC_TRUE;
3563 device->Type = Loopback;
3564 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3566 device->Flags = 0;
3567 device->Bs2b = NULL;
3568 device->Bs2bLevel = 0;
3569 AL_STRING_INIT(device->DeviceName);
3571 ATOMIC_INIT(&device->ContextList, NULL);
3573 device->ClockBase = 0;
3574 device->SamplesDone = 0;
3576 device->MaxNoOfSources = 256;
3577 device->AuxiliaryEffectSlotMax = 4;
3578 device->NumAuxSends = MAX_SENDS;
3580 InitUIntMap(&device->BufferMap, ~0);
3581 InitUIntMap(&device->EffectMap, ~0);
3582 InitUIntMap(&device->FilterMap, ~0);
3583 InitUIntMap(&device->SfontMap, ~0);
3584 InitUIntMap(&device->PresetMap, ~0);
3585 InitUIntMap(&device->FontsoundMap, ~0);
3587 factory = ALCloopbackFactory_getFactory();
3588 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3589 if(!device->Backend)
3591 al_free(device);
3592 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3593 return NULL;
3596 //Set output format
3597 device->NumUpdates = 0;
3598 device->UpdateSize = 0;
3600 device->Frequency = DEFAULT_OUTPUT_RATE;
3601 device->FmtChans = DevFmtChannelsDefault;
3602 device->FmtType = DevFmtTypeDefault;
3604 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3605 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3607 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3608 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3610 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3611 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3613 device->NumStereoSources = 1;
3614 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3616 device->Synth = SynthCreate(device);
3617 if(!device->Synth)
3619 DELETE_OBJ(device->Backend);
3620 al_free(device);
3621 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3622 return NULL;
3625 // Open the "backend"
3626 V(device->Backend,open)("Loopback");
3629 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3630 do {
3631 device->next = head;
3632 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3635 TRACE("Created device %p\n", device);
3636 return device;
3639 /* alcIsRenderFormatSupportedSOFT
3641 * Determines if the loopback device supports the given format for rendering.
3643 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3645 ALCboolean ret = ALC_FALSE;
3647 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3648 alcSetError(device, ALC_INVALID_DEVICE);
3649 else if(freq <= 0)
3650 alcSetError(device, ALC_INVALID_VALUE);
3651 else
3653 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3654 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3655 freq >= MIN_OUTPUT_RATE)
3656 ret = ALC_TRUE;
3658 if(device) ALCdevice_DecRef(device);
3660 return ret;
3663 /* alcRenderSamplesSOFT
3665 * Renders some samples into a buffer, using the format last set by the
3666 * attributes given to alcCreateContext.
3668 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3670 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3671 alcSetError(device, ALC_INVALID_DEVICE);
3672 else if(samples < 0 || (samples > 0 && buffer == NULL))
3673 alcSetError(device, ALC_INVALID_VALUE);
3674 else
3675 aluMixData(device, buffer, samples);
3676 if(device) ALCdevice_DecRef(device);
3680 /************************************************
3681 * ALC DSP pause/resume functions
3682 ************************************************/
3684 /* alcDevicePauseSOFT
3686 * Pause the DSP to stop audio processing.
3688 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3690 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3691 alcSetError(device, ALC_INVALID_DEVICE);
3692 else
3694 LockLists();
3695 if((device->Flags&DEVICE_RUNNING))
3696 V0(device->Backend,stop)();
3697 device->Flags &= ~DEVICE_RUNNING;
3698 device->Flags |= DEVICE_PAUSED;
3699 UnlockLists();
3701 if(device) ALCdevice_DecRef(device);
3704 /* alcDeviceResumeSOFT
3706 * Resume the DSP to restart audio processing.
3708 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3710 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3711 alcSetError(device, ALC_INVALID_DEVICE);
3712 else
3714 LockLists();
3715 if((device->Flags&DEVICE_PAUSED))
3717 device->Flags &= ~DEVICE_PAUSED;
3718 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3720 if(V0(device->Backend,start)() != ALC_FALSE)
3721 device->Flags |= DEVICE_RUNNING;
3722 else
3724 alcSetError(device, ALC_INVALID_DEVICE);
3725 ALCdevice_Lock(device);
3726 aluHandleDisconnect(device);
3727 ALCdevice_Unlock(device);
3731 UnlockLists();
3733 if(device) ALCdevice_DecRef(device);