Add macros for generic atomic functionality
[openal-soft.git] / Alc / ALc.c
blob2cc4043978c7b95a0b5ddb14a1860f0d10b69949
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_PULSEAUDIO
65 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_ALSA
68 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_COREAUDIO
71 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
72 #endif
73 #ifdef HAVE_OSS
74 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
75 #endif
76 #ifdef HAVE_SOLARIS
77 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SNDIO
80 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_QSA
83 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_MMDEVAPI
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
87 #endif
88 #ifdef HAVE_DSOUND
89 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_WINMM
92 { "winmm", NULL, alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
93 #endif
94 #ifdef HAVE_PORTAUDIO
95 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
96 #endif
97 #ifdef HAVE_OPENSL
98 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
99 #endif
101 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
102 #ifdef HAVE_WAVE
103 { "wave", NULL, alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
104 #endif
106 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
108 #undef EmptyFuncs
110 static struct BackendInfo PlaybackBackend;
111 static struct BackendInfo CaptureBackend;
114 /************************************************
115 * Functions, enums, and errors
116 ************************************************/
117 typedef struct ALCfunction {
118 const ALCchar *funcName;
119 ALCvoid *address;
120 } ALCfunction;
122 typedef struct ALCenums {
123 const ALCchar *enumName;
124 ALCenum value;
125 } ALCenums;
127 #define DECL(x) { #x, (ALCvoid*)(x) }
128 static const ALCfunction alcFunctions[] = {
129 DECL(alcCreateContext),
130 DECL(alcMakeContextCurrent),
131 DECL(alcProcessContext),
132 DECL(alcSuspendContext),
133 DECL(alcDestroyContext),
134 DECL(alcGetCurrentContext),
135 DECL(alcGetContextsDevice),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
143 DECL(alcGetIntegerv),
144 DECL(alcCaptureOpenDevice),
145 DECL(alcCaptureCloseDevice),
146 DECL(alcCaptureStart),
147 DECL(alcCaptureStop),
148 DECL(alcCaptureSamples),
150 DECL(alcSetThreadContext),
151 DECL(alcGetThreadContext),
153 DECL(alcLoopbackOpenDeviceSOFT),
154 DECL(alcIsRenderFormatSupportedSOFT),
155 DECL(alcRenderSamplesSOFT),
157 DECL(alcDevicePauseSOFT),
158 DECL(alcDeviceResumeSOFT),
160 DECL(alcGetInteger64vSOFT),
162 DECL(alEnable),
163 DECL(alDisable),
164 DECL(alIsEnabled),
165 DECL(alGetString),
166 DECL(alGetBooleanv),
167 DECL(alGetIntegerv),
168 DECL(alGetFloatv),
169 DECL(alGetDoublev),
170 DECL(alGetBoolean),
171 DECL(alGetInteger),
172 DECL(alGetFloat),
173 DECL(alGetDouble),
174 DECL(alGetError),
175 DECL(alIsExtensionPresent),
176 DECL(alGetProcAddress),
177 DECL(alGetEnumValue),
178 DECL(alListenerf),
179 DECL(alListener3f),
180 DECL(alListenerfv),
181 DECL(alListeneri),
182 DECL(alListener3i),
183 DECL(alListeneriv),
184 DECL(alGetListenerf),
185 DECL(alGetListener3f),
186 DECL(alGetListenerfv),
187 DECL(alGetListeneri),
188 DECL(alGetListener3i),
189 DECL(alGetListeneriv),
190 DECL(alGenSources),
191 DECL(alDeleteSources),
192 DECL(alIsSource),
193 DECL(alSourcef),
194 DECL(alSource3f),
195 DECL(alSourcefv),
196 DECL(alSourcei),
197 DECL(alSource3i),
198 DECL(alSourceiv),
199 DECL(alGetSourcef),
200 DECL(alGetSource3f),
201 DECL(alGetSourcefv),
202 DECL(alGetSourcei),
203 DECL(alGetSource3i),
204 DECL(alGetSourceiv),
205 DECL(alSourcePlayv),
206 DECL(alSourceStopv),
207 DECL(alSourceRewindv),
208 DECL(alSourcePausev),
209 DECL(alSourcePlay),
210 DECL(alSourceStop),
211 DECL(alSourceRewind),
212 DECL(alSourcePause),
213 DECL(alSourceQueueBuffers),
214 DECL(alSourceUnqueueBuffers),
215 DECL(alGenBuffers),
216 DECL(alDeleteBuffers),
217 DECL(alIsBuffer),
218 DECL(alBufferData),
219 DECL(alBufferf),
220 DECL(alBuffer3f),
221 DECL(alBufferfv),
222 DECL(alBufferi),
223 DECL(alBuffer3i),
224 DECL(alBufferiv),
225 DECL(alGetBufferf),
226 DECL(alGetBuffer3f),
227 DECL(alGetBufferfv),
228 DECL(alGetBufferi),
229 DECL(alGetBuffer3i),
230 DECL(alGetBufferiv),
231 DECL(alDopplerFactor),
232 DECL(alDopplerVelocity),
233 DECL(alSpeedOfSound),
234 DECL(alDistanceModel),
236 DECL(alGenFilters),
237 DECL(alDeleteFilters),
238 DECL(alIsFilter),
239 DECL(alFilteri),
240 DECL(alFilteriv),
241 DECL(alFilterf),
242 DECL(alFilterfv),
243 DECL(alGetFilteri),
244 DECL(alGetFilteriv),
245 DECL(alGetFilterf),
246 DECL(alGetFilterfv),
247 DECL(alGenEffects),
248 DECL(alDeleteEffects),
249 DECL(alIsEffect),
250 DECL(alEffecti),
251 DECL(alEffectiv),
252 DECL(alEffectf),
253 DECL(alEffectfv),
254 DECL(alGetEffecti),
255 DECL(alGetEffectiv),
256 DECL(alGetEffectf),
257 DECL(alGetEffectfv),
258 DECL(alGenAuxiliaryEffectSlots),
259 DECL(alDeleteAuxiliaryEffectSlots),
260 DECL(alIsAuxiliaryEffectSlot),
261 DECL(alAuxiliaryEffectSloti),
262 DECL(alAuxiliaryEffectSlotiv),
263 DECL(alAuxiliaryEffectSlotf),
264 DECL(alAuxiliaryEffectSlotfv),
265 DECL(alGetAuxiliaryEffectSloti),
266 DECL(alGetAuxiliaryEffectSlotiv),
267 DECL(alGetAuxiliaryEffectSlotf),
268 DECL(alGetAuxiliaryEffectSlotfv),
270 DECL(alBufferSubDataSOFT),
272 DECL(alBufferSamplesSOFT),
273 DECL(alBufferSubSamplesSOFT),
274 DECL(alGetBufferSamplesSOFT),
275 DECL(alIsBufferFormatSupportedSOFT),
277 DECL(alDeferUpdatesSOFT),
278 DECL(alProcessUpdatesSOFT),
280 DECL(alSourcedSOFT),
281 DECL(alSource3dSOFT),
282 DECL(alSourcedvSOFT),
283 DECL(alGetSourcedSOFT),
284 DECL(alGetSource3dSOFT),
285 DECL(alGetSourcedvSOFT),
286 DECL(alSourcei64SOFT),
287 DECL(alSource3i64SOFT),
288 DECL(alSourcei64vSOFT),
289 DECL(alGetSourcei64SOFT),
290 DECL(alGetSource3i64SOFT),
291 DECL(alGetSourcei64vSOFT),
293 DECL(alGenSoundfontsSOFT),
294 DECL(alDeleteSoundfontsSOFT),
295 DECL(alIsSoundfontSOFT),
296 DECL(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 DECL(AL_EFFECT_AUTOWAH),
592 DECL(AL_EFFECT_COMPRESSOR),
593 DECL(AL_EFFECT_EQUALIZER),
594 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
595 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
597 DECL(AL_EAXREVERB_DENSITY),
598 DECL(AL_EAXREVERB_DIFFUSION),
599 DECL(AL_EAXREVERB_GAIN),
600 DECL(AL_EAXREVERB_GAINHF),
601 DECL(AL_EAXREVERB_GAINLF),
602 DECL(AL_EAXREVERB_DECAY_TIME),
603 DECL(AL_EAXREVERB_DECAY_HFRATIO),
604 DECL(AL_EAXREVERB_DECAY_LFRATIO),
605 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
606 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
607 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
608 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
609 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
610 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
611 DECL(AL_EAXREVERB_ECHO_TIME),
612 DECL(AL_EAXREVERB_ECHO_DEPTH),
613 DECL(AL_EAXREVERB_MODULATION_TIME),
614 DECL(AL_EAXREVERB_MODULATION_DEPTH),
615 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
616 DECL(AL_EAXREVERB_HFREFERENCE),
617 DECL(AL_EAXREVERB_LFREFERENCE),
618 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
619 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
621 DECL(AL_REVERB_DENSITY),
622 DECL(AL_REVERB_DIFFUSION),
623 DECL(AL_REVERB_GAIN),
624 DECL(AL_REVERB_GAINHF),
625 DECL(AL_REVERB_DECAY_TIME),
626 DECL(AL_REVERB_DECAY_HFRATIO),
627 DECL(AL_REVERB_REFLECTIONS_GAIN),
628 DECL(AL_REVERB_REFLECTIONS_DELAY),
629 DECL(AL_REVERB_LATE_REVERB_GAIN),
630 DECL(AL_REVERB_LATE_REVERB_DELAY),
631 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
632 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
633 DECL(AL_REVERB_DECAY_HFLIMIT),
635 DECL(AL_CHORUS_WAVEFORM),
636 DECL(AL_CHORUS_PHASE),
637 DECL(AL_CHORUS_RATE),
638 DECL(AL_CHORUS_DEPTH),
639 DECL(AL_CHORUS_FEEDBACK),
640 DECL(AL_CHORUS_DELAY),
642 DECL(AL_DISTORTION_EDGE),
643 DECL(AL_DISTORTION_GAIN),
644 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
645 DECL(AL_DISTORTION_EQCENTER),
646 DECL(AL_DISTORTION_EQBANDWIDTH),
648 DECL(AL_ECHO_DELAY),
649 DECL(AL_ECHO_LRDELAY),
650 DECL(AL_ECHO_DAMPING),
651 DECL(AL_ECHO_FEEDBACK),
652 DECL(AL_ECHO_SPREAD),
654 DECL(AL_FLANGER_WAVEFORM),
655 DECL(AL_FLANGER_PHASE),
656 DECL(AL_FLANGER_RATE),
657 DECL(AL_FLANGER_DEPTH),
658 DECL(AL_FLANGER_FEEDBACK),
659 DECL(AL_FLANGER_DELAY),
661 DECL(AL_RING_MODULATOR_FREQUENCY),
662 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
663 DECL(AL_RING_MODULATOR_WAVEFORM),
665 DECL(AL_AUTOWAH_ATTACK_TIME),
666 DECL(AL_AUTOWAH_PEAK_GAIN),
667 DECL(AL_AUTOWAH_RELEASE_TIME),
668 DECL(AL_AUTOWAH_RESONANCE),
670 DECL(AL_COMPRESSOR_ONOFF),
672 DECL(AL_EQUALIZER_LOW_GAIN),
673 DECL(AL_EQUALIZER_LOW_CUTOFF),
674 DECL(AL_EQUALIZER_MID1_GAIN),
675 DECL(AL_EQUALIZER_MID1_CENTER),
676 DECL(AL_EQUALIZER_MID1_WIDTH),
677 DECL(AL_EQUALIZER_MID2_GAIN),
678 DECL(AL_EQUALIZER_MID2_CENTER),
679 DECL(AL_EQUALIZER_MID2_WIDTH),
680 DECL(AL_EQUALIZER_HIGH_GAIN),
681 DECL(AL_EQUALIZER_HIGH_CUTOFF),
683 DECL(AL_DEDICATED_GAIN),
685 { NULL, (ALCenum)0 }
687 #undef DECL
689 static const ALCchar alcNoError[] = "No Error";
690 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
691 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
692 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
693 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
694 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
697 /************************************************
698 * Global variables
699 ************************************************/
701 /* Enumerated device names */
702 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
704 static al_string alcAllDevicesList;
705 static al_string alcCaptureDeviceList;
707 /* Default is always the first in the list */
708 static ALCchar *alcDefaultAllDevicesSpecifier;
709 static ALCchar *alcCaptureDefaultDeviceSpecifier;
711 /* Default context extensions */
712 static const ALchar alExtList[] =
713 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
714 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
715 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
716 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples "
717 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
718 "AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency "
719 "AL_SOFT_source_length";
721 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
723 /* Thread-local current context */
724 static altss_t LocalContext;
725 /* Process-wide current context */
726 static ALCcontext *volatile GlobalContext = NULL;
728 /* Mixing thread piority level */
729 ALint RTPrioLevel;
731 FILE *LogFile;
732 #ifdef _DEBUG
733 enum LogLevel LogLevel = LogWarning;
734 #else
735 enum LogLevel LogLevel = LogError;
736 #endif
738 /* Flag to trap ALC device errors */
739 static ALCboolean TrapALCError = ALC_FALSE;
741 /* One-time configuration init control */
742 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
744 /* Default effect that applies to sources that don't have an effect on send 0 */
745 static ALeffect DefaultEffect;
748 /************************************************
749 * ALC information
750 ************************************************/
751 static const ALCchar alcNoDeviceExtList[] =
752 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
753 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
754 static const ALCchar alcExtensionList[] =
755 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
756 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
757 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
758 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
759 static const ALCint alcMajorVersion = 1;
760 static const ALCint alcMinorVersion = 1;
762 static const ALCint alcEFXMajorVersion = 1;
763 static const ALCint alcEFXMinorVersion = 0;
766 /************************************************
767 * Device lists
768 ************************************************/
769 static ALCdevice *volatile DeviceList = NULL;
771 static almtx_t ListLock;
772 static inline void LockLists(void)
774 int lockret = almtx_lock(&ListLock);
775 assert(lockret == althrd_success);
777 static inline void UnlockLists(void)
779 int unlockret = almtx_unlock(&ListLock);
780 assert(unlockret == althrd_success);
783 /************************************************
784 * Library initialization
785 ************************************************/
786 #if defined(_WIN32)
787 static void alc_init(void);
788 static void alc_deinit(void);
789 static void alc_deinit_safe(void);
791 #ifndef AL_LIBTYPE_STATIC
792 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
794 switch(reason)
796 case DLL_PROCESS_ATTACH:
797 /* Pin the DLL so we won't get unloaded until the process terminates */
798 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
799 (WCHAR*)hModule, &hModule);
800 alc_init();
801 break;
803 case DLL_THREAD_DETACH:
804 break;
806 case DLL_PROCESS_DETACH:
807 if(!lpReserved)
808 alc_deinit();
809 else
810 alc_deinit_safe();
811 break;
813 return TRUE;
815 #elif defined(_MSC_VER)
816 #pragma section(".CRT$XCU",read)
817 static void alc_constructor(void);
818 static void alc_destructor(void);
819 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
821 static void alc_constructor(void)
823 atexit(alc_destructor);
824 alc_init();
827 static void alc_destructor(void)
829 alc_deinit();
831 #elif defined(HAVE_GCC_DESTRUCTOR)
832 static void alc_init(void) __attribute__((constructor));
833 static void alc_deinit(void) __attribute__((destructor));
834 #else
835 #error "No static initialization available on this platform!"
836 #endif
838 #elif defined(HAVE_GCC_DESTRUCTOR)
840 static void alc_init(void) __attribute__((constructor));
841 static void alc_deinit(void) __attribute__((destructor));
843 #else
844 #error "No global initialization available on this platform!"
845 #endif
847 static void ReleaseThreadCtx(void *ptr);
848 static void alc_init(void)
850 const char *str;
851 int ret;
853 LogFile = stderr;
855 AL_STRING_INIT(alcAllDevicesList);
856 AL_STRING_INIT(alcCaptureDeviceList);
858 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
859 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
860 ConeScale *= 0.5f;
862 str = getenv("__ALSOFT_REVERSE_Z");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ZScale *= -1.0f;
866 ret = altss_create(&LocalContext, ReleaseThreadCtx);
867 assert(ret == althrd_success);
869 ret = almtx_init(&ListLock, almtx_recursive);
870 assert(ret == althrd_success);
872 ThunkInit();
875 static void alc_initconfig(void)
877 const char *devs, *str;
878 ALuint capfilter;
879 float valf;
880 int i, n;
882 str = getenv("ALSOFT_LOGLEVEL");
883 if(str)
885 long lvl = strtol(str, NULL, 0);
886 if(lvl >= NoLog && lvl <= LogRef)
887 LogLevel = lvl;
890 str = getenv("ALSOFT_LOGFILE");
891 if(str && str[0])
893 FILE *logfile = al_fopen(str, "wt");
894 if(logfile) LogFile = logfile;
895 else ERR("Failed to open log file '%s'\n", str);
899 char buf[1024] = "";
900 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
901 for(i = 1;BackendList[i].name;i++)
902 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
903 TRACE("Supported backends: %s\n", buf);
905 ReadALConfig();
907 capfilter = 0;
908 #if defined(HAVE_SSE4_1)
909 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
910 #elif defined(HAVE_SSE2)
911 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
912 #elif defined(HAVE_SSE)
913 capfilter |= CPU_CAP_SSE;
914 #endif
915 #ifdef HAVE_NEON
916 capfilter |= CPU_CAP_NEON;
917 #endif
918 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
920 if(strcasecmp(str, "all") == 0)
921 capfilter = 0;
922 else
924 size_t len;
925 const char *next = str;
927 do {
928 str = next;
929 while(isspace(str[0]))
930 str++;
931 next = strchr(str, ',');
933 if(!str[0] || str[0] == ',')
934 continue;
936 len = (next ? ((size_t)(next-str)) : strlen(str));
937 while(len > 0 && isspace(str[len-1]))
938 len--;
939 if(len == 3 && strncasecmp(str, "sse", len) == 0)
940 capfilter &= ~CPU_CAP_SSE;
941 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
942 capfilter &= ~CPU_CAP_SSE2;
943 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
944 capfilter &= ~CPU_CAP_SSE4_1;
945 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
946 capfilter &= ~CPU_CAP_NEON;
947 else
948 WARN("Invalid CPU extension \"%s\"\n", str);
949 } while(next++);
952 FillCPUCaps(capfilter);
954 #ifdef _WIN32
955 RTPrioLevel = 1;
956 #else
957 RTPrioLevel = 0;
958 #endif
959 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
961 if(ConfigValueStr(NULL, "resampler", &str))
963 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
964 DefaultResampler = PointResampler;
965 else if(strcasecmp(str, "linear") == 0)
966 DefaultResampler = LinearResampler;
967 else if(strcasecmp(str, "cubic") == 0)
968 DefaultResampler = CubicResampler;
969 else
971 char *end;
973 n = strtol(str, &end, 0);
974 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
975 DefaultResampler = n;
976 else
977 WARN("Invalid resampler: %s\n", str);
981 str = getenv("ALSOFT_TRAP_ERROR");
982 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
984 TrapALError = AL_TRUE;
985 TrapALCError = AL_TRUE;
987 else
989 str = getenv("ALSOFT_TRAP_AL_ERROR");
990 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
991 TrapALError = AL_TRUE;
992 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
994 str = getenv("ALSOFT_TRAP_ALC_ERROR");
995 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
996 TrapALCError = ALC_TRUE;
997 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1000 if(ConfigValueFloat("reverb", "boost", &valf))
1001 ReverbBoost *= powf(10.0f, valf / 20.0f);
1003 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1005 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1006 ConfigValueStr(NULL, "drivers", &devs))
1008 int n;
1009 size_t len;
1010 const char *next = devs;
1011 int endlist, delitem;
1013 i = 0;
1014 do {
1015 devs = next;
1016 while(isspace(devs[0]))
1017 devs++;
1018 next = strchr(devs, ',');
1020 delitem = (devs[0] == '-');
1021 if(devs[0] == '-') devs++;
1023 if(!devs[0] || devs[0] == ',')
1025 endlist = 0;
1026 continue;
1028 endlist = 1;
1030 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1031 while(len > 0 && isspace(devs[len-1]))
1032 len--;
1033 for(n = i;BackendList[n].name;n++)
1035 if(len == strlen(BackendList[n].name) &&
1036 strncmp(BackendList[n].name, devs, len) == 0)
1038 if(delitem)
1040 do {
1041 BackendList[n] = BackendList[n+1];
1042 ++n;
1043 } while(BackendList[n].name);
1045 else
1047 struct BackendInfo Bkp = BackendList[n];
1048 while(n > i)
1050 BackendList[n] = BackendList[n-1];
1051 --n;
1053 BackendList[n] = Bkp;
1055 i++;
1057 break;
1060 } while(next++);
1062 if(endlist)
1064 BackendList[i].name = NULL;
1065 BackendList[i].getFactory = NULL;
1066 BackendList[i].Init = NULL;
1067 BackendList[i].Deinit = NULL;
1068 BackendList[i].Probe = NULL;
1072 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1074 if(BackendList[i].getFactory)
1076 ALCbackendFactory *factory = BackendList[i].getFactory();
1077 if(!V0(factory,init)())
1079 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1080 continue;
1083 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1084 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1086 PlaybackBackend = BackendList[i];
1087 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1089 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1091 CaptureBackend = BackendList[i];
1092 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1095 continue;
1098 if(!BackendList[i].Init(&BackendList[i].Funcs))
1100 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1101 continue;
1104 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1105 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1107 PlaybackBackend = BackendList[i];
1108 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1110 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1112 CaptureBackend = BackendList[i];
1113 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1117 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1118 V0(factory,init)();
1121 if(ConfigValueStr(NULL, "excludefx", &str))
1123 size_t len;
1124 const char *next = str;
1126 do {
1127 str = next;
1128 next = strchr(str, ',');
1130 if(!str[0] || next == str)
1131 continue;
1133 len = (next ? ((size_t)(next-str)) : strlen(str));
1134 for(n = 0;EffectList[n].name;n++)
1136 if(len == strlen(EffectList[n].name) &&
1137 strncmp(EffectList[n].name, str, len) == 0)
1138 DisabledEffects[EffectList[n].type] = AL_TRUE;
1140 } while(next++);
1143 InitEffectFactoryMap();
1145 InitEffect(&DefaultEffect);
1146 str = getenv("ALSOFT_DEFAULT_REVERB");
1147 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1148 LoadReverbPreset(str, &DefaultEffect);
1150 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1153 /************************************************
1154 * Library deinitialization
1155 ************************************************/
1156 static void alc_cleanup(void)
1158 ALCdevice *dev;
1160 AL_STRING_DEINIT(alcAllDevicesList);
1161 AL_STRING_DEINIT(alcCaptureDeviceList);
1163 free(alcDefaultAllDevicesSpecifier);
1164 alcDefaultAllDevicesSpecifier = NULL;
1165 free(alcCaptureDefaultDeviceSpecifier);
1166 alcCaptureDefaultDeviceSpecifier = NULL;
1168 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1170 ALCuint num = 0;
1171 do {
1172 num++;
1173 } while((dev=dev->next) != NULL);
1174 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1177 DeinitEffectFactoryMap();
1180 static void alc_deinit_safe(void)
1182 alc_cleanup();
1184 FreeHrtfs();
1185 FreeALConfig();
1187 ThunkExit();
1188 almtx_destroy(&ListLock);
1189 altss_delete(LocalContext);
1191 if(LogFile != stderr)
1192 fclose(LogFile);
1193 LogFile = NULL;
1196 static void alc_deinit(void)
1198 int i;
1200 alc_cleanup();
1202 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1203 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1205 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1207 if(!BackendList[i].getFactory)
1208 BackendList[i].Deinit();
1209 else
1211 ALCbackendFactory *factory = BackendList[i].getFactory();
1212 V0(factory,deinit)();
1216 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1217 V0(factory,deinit)();
1220 alc_deinit_safe();
1224 /************************************************
1225 * Device enumeration
1226 ************************************************/
1227 static void ProbeDevices(al_string *list, enum DevProbe type)
1229 DO_INITCONFIG();
1231 LockLists();
1232 al_string_clear(list);
1234 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1236 if(!PlaybackBackend.getFactory)
1237 PlaybackBackend.Probe(type);
1238 else
1240 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1241 V(factory,probe)(type);
1244 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1246 if(!CaptureBackend.getFactory)
1247 CaptureBackend.Probe(type);
1248 else
1250 ALCbackendFactory *factory = CaptureBackend.getFactory();
1251 V(factory,probe)(type);
1254 UnlockLists();
1256 static void ProbeAllDevicesList(void)
1257 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1258 static void ProbeCaptureDeviceList(void)
1259 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1261 static void AppendDevice(const ALCchar *name, al_string *devnames)
1263 size_t len = strlen(name);
1264 if(len > 0)
1266 al_string_append_range(devnames, name, name+len);
1267 al_string_append_char(devnames, '\0');
1270 void AppendAllDevicesList(const ALCchar *name)
1271 { AppendDevice(name, &alcAllDevicesList); }
1272 void AppendCaptureDeviceList(const ALCchar *name)
1273 { AppendDevice(name, &alcCaptureDeviceList); }
1276 /************************************************
1277 * Device format information
1278 ************************************************/
1279 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1281 switch(type)
1283 case DevFmtByte: return "Signed Byte";
1284 case DevFmtUByte: return "Unsigned Byte";
1285 case DevFmtShort: return "Signed Short";
1286 case DevFmtUShort: return "Unsigned Short";
1287 case DevFmtInt: return "Signed Int";
1288 case DevFmtUInt: return "Unsigned Int";
1289 case DevFmtFloat: return "Float";
1291 return "(unknown type)";
1293 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1295 switch(chans)
1297 case DevFmtMono: return "Mono";
1298 case DevFmtStereo: return "Stereo";
1299 case DevFmtQuad: return "Quadraphonic";
1300 case DevFmtX51: return "5.1 Surround";
1301 case DevFmtX51Side: return "5.1 Side";
1302 case DevFmtX61: return "6.1 Surround";
1303 case DevFmtX71: return "7.1 Surround";
1305 return "(unknown channels)";
1308 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1309 ALuint BytesFromDevFmt(enum DevFmtType type)
1311 switch(type)
1313 case DevFmtByte: return sizeof(ALbyte);
1314 case DevFmtUByte: return sizeof(ALubyte);
1315 case DevFmtShort: return sizeof(ALshort);
1316 case DevFmtUShort: return sizeof(ALushort);
1317 case DevFmtInt: return sizeof(ALint);
1318 case DevFmtUInt: return sizeof(ALuint);
1319 case DevFmtFloat: return sizeof(ALfloat);
1321 return 0;
1323 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1325 switch(chans)
1327 case DevFmtMono: return 1;
1328 case DevFmtStereo: return 2;
1329 case DevFmtQuad: return 4;
1330 case DevFmtX51: return 6;
1331 case DevFmtX51Side: return 6;
1332 case DevFmtX61: return 7;
1333 case DevFmtX71: return 8;
1335 return 0;
1338 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1339 enum DevFmtChannels *chans, enum DevFmtType *type)
1341 static const struct {
1342 ALenum format;
1343 enum DevFmtChannels channels;
1344 enum DevFmtType type;
1345 } list[] = {
1346 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1347 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1348 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1350 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1351 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1352 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1354 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1355 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1356 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1358 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1359 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1360 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1362 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1363 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1364 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1366 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1367 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1368 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1370 ALuint i;
1372 for(i = 0;i < COUNTOF(list);i++)
1374 if(list[i].format == format)
1376 *chans = list[i].channels;
1377 *type = list[i].type;
1378 return AL_TRUE;
1382 return AL_FALSE;
1385 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1387 switch(type)
1389 case ALC_BYTE_SOFT:
1390 case ALC_UNSIGNED_BYTE_SOFT:
1391 case ALC_SHORT_SOFT:
1392 case ALC_UNSIGNED_SHORT_SOFT:
1393 case ALC_INT_SOFT:
1394 case ALC_UNSIGNED_INT_SOFT:
1395 case ALC_FLOAT_SOFT:
1396 return ALC_TRUE;
1398 return ALC_FALSE;
1401 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1403 switch(channels)
1405 case ALC_MONO_SOFT:
1406 case ALC_STEREO_SOFT:
1407 case ALC_QUAD_SOFT:
1408 case ALC_5POINT1_SOFT:
1409 case ALC_6POINT1_SOFT:
1410 case ALC_7POINT1_SOFT:
1411 return ALC_TRUE;
1413 return ALC_FALSE;
1417 /************************************************
1418 * Miscellaneous ALC helpers
1419 ************************************************/
1420 extern inline void LockContext(ALCcontext *context);
1421 extern inline void UnlockContext(ALCcontext *context);
1423 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *UNUSED(device))
1425 return 0;
1428 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1430 return V0(device->Backend,getLatency)();
1433 void ALCdevice_Lock(ALCdevice *device)
1435 V0(device->Backend,lock)();
1438 void ALCdevice_Unlock(ALCdevice *device)
1440 V0(device->Backend,unlock)();
1444 /* SetDefaultWFXChannelOrder
1446 * Sets the default channel order used by WaveFormatEx.
1448 void SetDefaultWFXChannelOrder(ALCdevice *device)
1450 ALuint i;
1452 for(i = 0;i < MaxChannels;i++)
1453 device->ChannelOffsets[i] = INVALID_OFFSET;
1455 switch(device->FmtChans)
1457 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1458 break;
1459 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1460 device->ChannelOffsets[FrontRight] = 1;
1461 break;
1462 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1463 device->ChannelOffsets[FrontRight] = 1;
1464 device->ChannelOffsets[BackLeft] = 2;
1465 device->ChannelOffsets[BackRight] = 3;
1466 break;
1467 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1468 device->ChannelOffsets[FrontRight] = 1;
1469 device->ChannelOffsets[FrontCenter] = 2;
1470 device->ChannelOffsets[LFE] = 3;
1471 device->ChannelOffsets[BackLeft] = 4;
1472 device->ChannelOffsets[BackRight] = 5;
1473 break;
1474 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1475 device->ChannelOffsets[FrontRight] = 1;
1476 device->ChannelOffsets[FrontCenter] = 2;
1477 device->ChannelOffsets[LFE] = 3;
1478 device->ChannelOffsets[SideLeft] = 4;
1479 device->ChannelOffsets[SideRight] = 5;
1480 break;
1481 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1482 device->ChannelOffsets[FrontRight] = 1;
1483 device->ChannelOffsets[FrontCenter] = 2;
1484 device->ChannelOffsets[LFE] = 3;
1485 device->ChannelOffsets[BackCenter] = 4;
1486 device->ChannelOffsets[SideLeft] = 5;
1487 device->ChannelOffsets[SideRight] = 6;
1488 break;
1489 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1490 device->ChannelOffsets[FrontRight] = 1;
1491 device->ChannelOffsets[FrontCenter] = 2;
1492 device->ChannelOffsets[LFE] = 3;
1493 device->ChannelOffsets[BackLeft] = 4;
1494 device->ChannelOffsets[BackRight] = 5;
1495 device->ChannelOffsets[SideLeft] = 6;
1496 device->ChannelOffsets[SideRight] = 7;
1497 break;
1501 /* SetDefaultChannelOrder
1503 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1505 void SetDefaultChannelOrder(ALCdevice *device)
1507 ALuint i;
1509 for(i = 0;i < MaxChannels;i++)
1510 device->ChannelOffsets[i] = INVALID_OFFSET;
1512 switch(device->FmtChans)
1514 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1515 device->ChannelOffsets[FrontRight] = 1;
1516 device->ChannelOffsets[BackLeft] = 2;
1517 device->ChannelOffsets[BackRight] = 3;
1518 device->ChannelOffsets[FrontCenter] = 4;
1519 device->ChannelOffsets[LFE] = 5;
1520 return;
1521 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1522 device->ChannelOffsets[FrontRight] = 1;
1523 device->ChannelOffsets[BackLeft] = 2;
1524 device->ChannelOffsets[BackRight] = 3;
1525 device->ChannelOffsets[FrontCenter] = 4;
1526 device->ChannelOffsets[LFE] = 5;
1527 device->ChannelOffsets[SideLeft] = 6;
1528 device->ChannelOffsets[SideRight] = 7;
1529 return;
1531 /* Same as WFX order */
1532 case DevFmtMono:
1533 case DevFmtStereo:
1534 case DevFmtQuad:
1535 case DevFmtX51Side:
1536 case DevFmtX61:
1537 break;
1539 SetDefaultWFXChannelOrder(device);
1543 /* alcSetError
1545 * Stores the latest ALC device error
1547 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1549 if(TrapALCError)
1551 #ifdef _WIN32
1552 /* DebugBreak() will cause an exception if there is no debugger */
1553 if(IsDebuggerPresent())
1554 DebugBreak();
1555 #elif defined(SIGTRAP)
1556 raise(SIGTRAP);
1557 #endif
1560 if(device)
1561 device->LastError = errorCode;
1562 else
1563 LastNullDeviceError = errorCode;
1567 /* UpdateClockBase
1569 * Updates the device's base clock time with however many samples have been
1570 * done. This is used so frequency changes on the device don't cause the time
1571 * to jump forward or back.
1573 static inline void UpdateClockBase(ALCdevice *device)
1575 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1576 device->SamplesDone = 0;
1579 /* UpdateDeviceParams
1581 * Updates device parameters according to the attribute list (caller is
1582 * responsible for holding the list lock).
1584 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1586 ALCcontext *context;
1587 enum DevFmtChannels oldChans;
1588 enum DevFmtType oldType;
1589 ALCuint oldFreq;
1590 FPUCtl oldMode;
1592 // Check for attributes
1593 if(device->Type == Loopback)
1595 enum {
1596 GotFreq = 1<<0,
1597 GotChans = 1<<1,
1598 GotType = 1<<2,
1599 GotAll = GotFreq|GotChans|GotType
1601 ALCuint freq, numMono, numStereo, numSends, flags;
1602 enum DevFmtChannels schans;
1603 enum DevFmtType stype;
1604 ALCuint attrIdx = 0;
1605 ALCint gotFmt = 0;
1607 if(!attrList)
1609 WARN("Missing attributes for loopback device\n");
1610 return ALC_INVALID_VALUE;
1613 numMono = device->NumMonoSources;
1614 numStereo = device->NumStereoSources;
1615 numSends = device->NumAuxSends;
1616 schans = device->FmtChans;
1617 stype = device->FmtType;
1618 freq = device->Frequency;
1619 flags = device->Flags;
1621 while(attrList[attrIdx])
1623 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1625 ALCint val = attrList[attrIdx + 1];
1626 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1627 return ALC_INVALID_VALUE;
1628 schans = val;
1629 gotFmt |= GotChans;
1632 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1634 ALCint val = attrList[attrIdx + 1];
1635 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1636 return ALC_INVALID_VALUE;
1637 stype = val;
1638 gotFmt |= GotType;
1641 if(attrList[attrIdx] == ALC_FREQUENCY)
1643 freq = attrList[attrIdx + 1];
1644 if(freq < MIN_OUTPUT_RATE)
1645 return ALC_INVALID_VALUE;
1646 gotFmt |= GotFreq;
1649 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1651 numStereo = attrList[attrIdx + 1];
1652 if(numStereo > device->MaxNoOfSources)
1653 numStereo = device->MaxNoOfSources;
1655 numMono = device->MaxNoOfSources - numStereo;
1658 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1659 numSends = attrList[attrIdx + 1];
1661 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1663 if(attrList[attrIdx + 1] != ALC_FALSE)
1664 flags |= DEVICE_HRTF_REQUEST;
1665 else
1666 flags &= ~DEVICE_HRTF_REQUEST;
1669 attrIdx += 2;
1672 if(gotFmt != GotAll)
1674 WARN("Missing format for loopback device\n");
1675 return ALC_INVALID_VALUE;
1678 ConfigValueUInt(NULL, "sends", &numSends);
1679 numSends = minu(MAX_SENDS, numSends);
1681 if((device->Flags&DEVICE_RUNNING))
1682 V0(device->Backend,stop)();
1683 device->Flags = (flags & ~DEVICE_RUNNING);
1685 if(freq != device->Frequency)
1686 UpdateClockBase(device);
1687 device->Frequency = freq;
1688 device->FmtChans = schans;
1689 device->FmtType = stype;
1690 device->NumMonoSources = numMono;
1691 device->NumStereoSources = numStereo;
1692 device->NumAuxSends = numSends;
1694 else if(attrList && attrList[0])
1696 ALCuint freq, numMono, numStereo, numSends;
1697 ALCuint attrIdx = 0;
1699 /* If a context is already running on the device, stop playback so the
1700 * device attributes can be updated. */
1701 if((device->Flags&DEVICE_RUNNING))
1702 V0(device->Backend,stop)();
1703 device->Flags &= ~DEVICE_RUNNING;
1705 freq = device->Frequency;
1706 numMono = device->NumMonoSources;
1707 numStereo = device->NumStereoSources;
1708 numSends = device->NumAuxSends;
1710 while(attrList[attrIdx])
1712 if(attrList[attrIdx] == ALC_FREQUENCY)
1714 freq = attrList[attrIdx + 1];
1715 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1718 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1720 numStereo = attrList[attrIdx + 1];
1721 if(numStereo > device->MaxNoOfSources)
1722 numStereo = device->MaxNoOfSources;
1724 numMono = device->MaxNoOfSources - numStereo;
1727 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1728 numSends = attrList[attrIdx + 1];
1730 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1732 if(attrList[attrIdx + 1] != ALC_FALSE)
1733 device->Flags |= DEVICE_HRTF_REQUEST;
1734 else
1735 device->Flags &= ~DEVICE_HRTF_REQUEST;
1738 attrIdx += 2;
1741 ConfigValueUInt(NULL, "frequency", &freq);
1742 freq = maxu(freq, MIN_OUTPUT_RATE);
1744 ConfigValueUInt(NULL, "sends", &numSends);
1745 numSends = minu(MAX_SENDS, numSends);
1747 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1748 device->Frequency;
1749 /* SSE and Neon do best with the update size being a multiple of 4 */
1750 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1751 device->UpdateSize = (device->UpdateSize+3)&~3;
1753 if(freq != device->Frequency)
1754 UpdateClockBase(device);
1755 device->Frequency = freq;
1756 device->NumMonoSources = numMono;
1757 device->NumStereoSources = numStereo;
1758 device->NumAuxSends = numSends;
1761 if((device->Flags&DEVICE_RUNNING))
1762 return ALC_NO_ERROR;
1764 UpdateClockBase(device);
1766 oldFreq = device->Frequency;
1767 oldChans = device->FmtChans;
1768 oldType = device->FmtType;
1770 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1771 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1772 DevFmtChannelsString(device->FmtChans),
1773 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1774 DevFmtTypeString(device->FmtType),
1775 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1776 device->Frequency,
1777 device->UpdateSize, device->NumUpdates);
1779 if(device->Type != Loopback)
1781 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1782 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1783 device->Flags |= DEVICE_HRTF_REQUEST;
1784 else
1785 device->Flags &= ~DEVICE_HRTF_REQUEST;
1787 if((device->Flags&DEVICE_HRTF_REQUEST))
1789 enum DevFmtChannels chans = device->FmtChans;
1790 ALCuint freq = device->Frequency;
1791 if(FindHrtfFormat(&chans, &freq))
1793 if(device->Type != Loopback)
1795 device->Frequency = freq;
1796 device->FmtChans = chans;
1797 device->Flags |= DEVICE_CHANNELS_REQUEST |
1798 DEVICE_FREQUENCY_REQUEST;
1800 else if(device->Frequency != freq || device->FmtChans != chans)
1802 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1803 DevFmtChannelsString(device->FmtChans), device->Frequency);
1804 device->Flags &= ~DEVICE_HRTF_REQUEST;
1809 if(V0(device->Backend,reset)() == ALC_FALSE)
1810 return ALC_INVALID_DEVICE;
1812 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1814 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1815 DevFmtChannelsString(device->FmtChans));
1816 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1818 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1820 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1821 DevFmtTypeString(device->FmtType));
1822 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1824 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1826 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1827 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1830 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1831 DevFmtChannelsString(device->FmtChans),
1832 DevFmtTypeString(device->FmtType), device->Frequency,
1833 device->UpdateSize, device->NumUpdates);
1835 aluInitPanning(device);
1837 V(device->Synth,update)(device);
1839 device->Hrtf = NULL;
1840 if((device->Flags&DEVICE_HRTF_REQUEST))
1842 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1843 if(!device->Hrtf)
1844 device->Flags &= ~DEVICE_HRTF_REQUEST;
1846 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1848 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1850 if(!device->Bs2b)
1852 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1853 bs2b_clear(device->Bs2b);
1855 bs2b_set_srate(device->Bs2b, device->Frequency);
1856 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1857 TRACE("BS2B level %d\n", device->Bs2bLevel);
1859 else
1861 free(device->Bs2b);
1862 device->Bs2b = NULL;
1863 TRACE("BS2B disabled\n");
1866 device->Flags &= ~DEVICE_WIDE_STEREO;
1867 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1868 device->Flags |= DEVICE_WIDE_STEREO;
1870 if(!device->Hrtf && (device->UpdateSize&3))
1872 if((CPUCapFlags&CPU_CAP_SSE))
1873 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1874 if((CPUCapFlags&CPU_CAP_NEON))
1875 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1878 SetMixerFPUMode(&oldMode);
1879 ALCdevice_Lock(device);
1880 context = device->ContextList;
1881 while(context)
1883 ALsizei pos;
1885 ATOMIC_STORE_UNSAFE(context->UpdateSources, AL_FALSE);
1886 LockUIntMapRead(&context->EffectSlotMap);
1887 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1889 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1891 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1893 UnlockUIntMapRead(&context->EffectSlotMap);
1894 ALCdevice_Unlock(device);
1895 RestoreFPUMode(&oldMode);
1896 return ALC_INVALID_DEVICE;
1898 slot->NeedsUpdate = AL_FALSE;
1899 V(slot->EffectState,update)(device, slot);
1901 UnlockUIntMapRead(&context->EffectSlotMap);
1903 LockUIntMapRead(&context->SourceMap);
1904 for(pos = 0;pos < context->SourceMap.size;pos++)
1906 ALsource *source = context->SourceMap.array[pos].value;
1907 ALuint s = device->NumAuxSends;
1908 while(s < MAX_SENDS)
1910 if(source->Send[s].Slot)
1911 DecrementRef(&source->Send[s].Slot->ref);
1912 source->Send[s].Slot = NULL;
1913 source->Send[s].Gain = 1.0f;
1914 source->Send[s].GainHF = 1.0f;
1915 s++;
1917 ATOMIC_STORE_UNSAFE(source->NeedsUpdate, AL_TRUE);
1919 UnlockUIntMapRead(&context->SourceMap);
1921 for(pos = 0;pos < context->ActiveSourceCount;pos++)
1923 ALactivesource *src = context->ActiveSources[pos];
1924 ALsource *source = src->Source;
1925 ALuint s = device->NumAuxSends;
1926 while(s < MAX_SENDS)
1928 src->Send[s].Moving = AL_FALSE;
1929 src->Send[s].Counter = 0;
1930 s++;
1933 src->Update(src, context);
1934 ATOMIC_STORE_UNSAFE(source->NeedsUpdate, AL_FALSE);
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 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 = 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 Context->LastError = AL_NO_ERROR;
2114 ATOMIC_STORE_UNSAFE(Context->UpdateSources, AL_FALSE);
2115 Context->ActiveSourceCount = 0;
2116 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2117 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2119 //Set globals
2120 Context->DistanceModel = DefaultDistanceModel;
2121 Context->SourceDistanceModel = AL_FALSE;
2122 Context->DopplerFactor = 1.0f;
2123 Context->DopplerVelocity = 1.0f;
2124 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2125 Context->DeferUpdates = AL_FALSE;
2127 Context->ExtensionList = alExtList;
2131 /* FreeContext
2133 * Cleans up the context, and destroys any remaining objects the app failed to
2134 * delete. Called once there's no more references on the context.
2136 static ALCvoid FreeContext(ALCcontext *context)
2138 ALsizei i;
2140 TRACE("%p\n", context);
2142 if(context->SourceMap.size > 0)
2144 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2145 ReleaseALSources(context);
2147 ResetUIntMap(&context->SourceMap);
2149 if(context->EffectSlotMap.size > 0)
2151 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2152 ReleaseALAuxiliaryEffectSlots(context);
2154 ResetUIntMap(&context->EffectSlotMap);
2156 for(i = 0;i < context->MaxActiveSources;i++)
2158 al_free(context->ActiveSources[i]);
2159 context->ActiveSources[i] = NULL;
2161 free(context->ActiveSources);
2162 context->ActiveSources = NULL;
2163 context->ActiveSourceCount = 0;
2164 context->MaxActiveSources = 0;
2166 VECTOR_DEINIT(context->ActiveAuxSlots);
2168 ALCdevice_DecRef(context->Device);
2169 context->Device = NULL;
2171 //Invalidate context
2172 memset(context, 0, sizeof(ALCcontext));
2173 free(context);
2176 /* ReleaseContext
2178 * Removes the context reference from the given device and removes it from
2179 * being current on the running thread or globally.
2181 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2183 ALCcontext *volatile*tmp_ctx;
2185 if(altss_get(LocalContext) == context)
2187 WARN("%p released while current on thread\n", context);
2188 altss_set(LocalContext, NULL);
2189 ALCcontext_DecRef(context);
2192 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL) == context)
2193 ALCcontext_DecRef(context);
2195 ALCdevice_Lock(device);
2196 tmp_ctx = &device->ContextList;
2197 while(*tmp_ctx)
2199 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next) == context)
2200 break;
2201 tmp_ctx = &(*tmp_ctx)->next;
2203 ALCdevice_Unlock(device);
2205 ALCcontext_DecRef(context);
2208 void ALCcontext_IncRef(ALCcontext *context)
2210 uint ref;
2211 ref = IncrementRef(&context->ref);
2212 TRACEREF("%p increasing refcount to %u\n", context, ref);
2215 void ALCcontext_DecRef(ALCcontext *context)
2217 uint ref;
2218 ref = DecrementRef(&context->ref);
2219 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2220 if(ref == 0) FreeContext(context);
2223 static void ReleaseThreadCtx(void *ptr)
2225 WARN("%p current for thread being destroyed\n", ptr);
2226 ALCcontext_DecRef(ptr);
2229 /* VerifyContext
2231 * Checks that the given context is valid, and increments its reference count.
2233 static ALCcontext *VerifyContext(ALCcontext *context)
2235 ALCdevice *dev;
2237 LockLists();
2238 dev = DeviceList;
2239 while(dev)
2241 ALCcontext *tmp_ctx = dev->ContextList;
2242 while(tmp_ctx)
2244 if(tmp_ctx == context)
2246 ALCcontext_IncRef(tmp_ctx);
2247 UnlockLists();
2248 return tmp_ctx;
2250 tmp_ctx = tmp_ctx->next;
2252 dev = dev->next;
2254 UnlockLists();
2256 return NULL;
2260 /* GetContextRef
2262 * Returns the currently active context for this thread, and adds a reference
2263 * without locking it.
2265 ALCcontext *GetContextRef(void)
2267 ALCcontext *context;
2269 context = altss_get(LocalContext);
2270 if(context)
2271 ALCcontext_IncRef(context);
2272 else
2274 LockLists();
2275 context = GlobalContext;
2276 if(context)
2277 ALCcontext_IncRef(context);
2278 UnlockLists();
2281 return context;
2285 /************************************************
2286 * Standard ALC functions
2287 ************************************************/
2289 /* alcGetError
2291 * Return last ALC generated error code for the given device
2293 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2295 ALCenum errorCode;
2297 if(VerifyDevice(device))
2299 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2300 ALCdevice_DecRef(device);
2302 else
2303 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2305 return errorCode;
2309 /* alcSuspendContext
2311 * Not functional
2313 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2317 /* alcProcessContext
2319 * Not functional
2321 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2326 /* alcGetString
2328 * Returns information about the device, and error strings
2330 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2332 const ALCchar *value = NULL;
2334 switch(param)
2336 case ALC_NO_ERROR:
2337 value = alcNoError;
2338 break;
2340 case ALC_INVALID_ENUM:
2341 value = alcErrInvalidEnum;
2342 break;
2344 case ALC_INVALID_VALUE:
2345 value = alcErrInvalidValue;
2346 break;
2348 case ALC_INVALID_DEVICE:
2349 value = alcErrInvalidDevice;
2350 break;
2352 case ALC_INVALID_CONTEXT:
2353 value = alcErrInvalidContext;
2354 break;
2356 case ALC_OUT_OF_MEMORY:
2357 value = alcErrOutOfMemory;
2358 break;
2360 case ALC_DEVICE_SPECIFIER:
2361 value = alcDefaultName;
2362 break;
2364 case ALC_ALL_DEVICES_SPECIFIER:
2365 if(VerifyDevice(Device))
2367 value = al_string_get_cstr(Device->DeviceName);
2368 ALCdevice_DecRef(Device);
2370 else
2372 ProbeAllDevicesList();
2373 value = al_string_get_cstr(alcAllDevicesList);
2375 break;
2377 case ALC_CAPTURE_DEVICE_SPECIFIER:
2378 if(VerifyDevice(Device))
2380 value = al_string_get_cstr(Device->DeviceName);
2381 ALCdevice_DecRef(Device);
2383 else
2385 ProbeCaptureDeviceList();
2386 value = al_string_get_cstr(alcCaptureDeviceList);
2388 break;
2390 /* Default devices are always first in the list */
2391 case ALC_DEFAULT_DEVICE_SPECIFIER:
2392 value = alcDefaultName;
2393 break;
2395 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2396 if(al_string_empty(alcAllDevicesList))
2397 ProbeAllDevicesList();
2399 Device = VerifyDevice(Device);
2401 free(alcDefaultAllDevicesSpecifier);
2402 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2403 if(!alcDefaultAllDevicesSpecifier)
2404 alcSetError(Device, ALC_OUT_OF_MEMORY);
2406 value = alcDefaultAllDevicesSpecifier;
2407 if(Device) ALCdevice_DecRef(Device);
2408 break;
2410 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2411 if(al_string_empty(alcCaptureDeviceList))
2412 ProbeCaptureDeviceList();
2414 Device = VerifyDevice(Device);
2416 free(alcCaptureDefaultDeviceSpecifier);
2417 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2418 if(!alcCaptureDefaultDeviceSpecifier)
2419 alcSetError(Device, ALC_OUT_OF_MEMORY);
2421 value = alcCaptureDefaultDeviceSpecifier;
2422 if(Device) ALCdevice_DecRef(Device);
2423 break;
2425 case ALC_EXTENSIONS:
2426 if(!VerifyDevice(Device))
2427 value = alcNoDeviceExtList;
2428 else
2430 value = alcExtensionList;
2431 ALCdevice_DecRef(Device);
2433 break;
2435 default:
2436 Device = VerifyDevice(Device);
2437 alcSetError(Device, ALC_INVALID_ENUM);
2438 if(Device) ALCdevice_DecRef(Device);
2439 break;
2442 return value;
2446 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2448 ALCsizei i;
2450 if(size <= 0 || values == NULL)
2452 alcSetError(device, ALC_INVALID_VALUE);
2453 return 0;
2456 if(!device)
2458 switch(param)
2460 case ALC_MAJOR_VERSION:
2461 values[0] = alcMajorVersion;
2462 return 1;
2463 case ALC_MINOR_VERSION:
2464 values[0] = alcMinorVersion;
2465 return 1;
2467 case ALC_ATTRIBUTES_SIZE:
2468 case ALC_ALL_ATTRIBUTES:
2469 case ALC_FREQUENCY:
2470 case ALC_REFRESH:
2471 case ALC_SYNC:
2472 case ALC_MONO_SOURCES:
2473 case ALC_STEREO_SOURCES:
2474 case ALC_CAPTURE_SAMPLES:
2475 case ALC_FORMAT_CHANNELS_SOFT:
2476 case ALC_FORMAT_TYPE_SOFT:
2477 alcSetError(NULL, ALC_INVALID_DEVICE);
2478 return 0;
2480 default:
2481 alcSetError(NULL, ALC_INVALID_ENUM);
2482 return 0;
2484 return 0;
2487 if(device->Type == Capture)
2489 switch(param)
2491 case ALC_CAPTURE_SAMPLES:
2492 ALCdevice_Lock(device);
2493 values[0] = V0(device->Backend,availableSamples)();
2494 ALCdevice_Unlock(device);
2495 return 1;
2497 case ALC_CONNECTED:
2498 values[0] = device->Connected;
2499 return 1;
2501 default:
2502 alcSetError(device, ALC_INVALID_ENUM);
2503 return 0;
2505 return 0;
2508 /* render device */
2509 switch(param)
2511 case ALC_MAJOR_VERSION:
2512 values[0] = alcMajorVersion;
2513 return 1;
2515 case ALC_MINOR_VERSION:
2516 values[0] = alcMinorVersion;
2517 return 1;
2519 case ALC_EFX_MAJOR_VERSION:
2520 values[0] = alcEFXMajorVersion;
2521 return 1;
2523 case ALC_EFX_MINOR_VERSION:
2524 values[0] = alcEFXMinorVersion;
2525 return 1;
2527 case ALC_ATTRIBUTES_SIZE:
2528 values[0] = 15;
2529 return 1;
2531 case ALC_ALL_ATTRIBUTES:
2532 if(size < 15)
2534 alcSetError(device, ALC_INVALID_VALUE);
2535 return 0;
2538 i = 0;
2539 values[i++] = ALC_FREQUENCY;
2540 values[i++] = device->Frequency;
2542 if(device->Type != Loopback)
2544 values[i++] = ALC_REFRESH;
2545 values[i++] = device->Frequency / device->UpdateSize;
2547 values[i++] = ALC_SYNC;
2548 values[i++] = ALC_FALSE;
2550 else
2552 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2553 values[i++] = device->FmtChans;
2555 values[i++] = ALC_FORMAT_TYPE_SOFT;
2556 values[i++] = device->FmtType;
2559 values[i++] = ALC_MONO_SOURCES;
2560 values[i++] = device->NumMonoSources;
2562 values[i++] = ALC_STEREO_SOURCES;
2563 values[i++] = device->NumStereoSources;
2565 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2566 values[i++] = device->NumAuxSends;
2568 values[i++] = ALC_HRTF_SOFT;
2569 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2571 values[i++] = 0;
2572 return i;
2574 case ALC_FREQUENCY:
2575 values[0] = device->Frequency;
2576 return 1;
2578 case ALC_REFRESH:
2579 if(device->Type == Loopback)
2581 alcSetError(device, ALC_INVALID_DEVICE);
2582 return 0;
2584 values[0] = device->Frequency / device->UpdateSize;
2585 return 1;
2587 case ALC_SYNC:
2588 if(device->Type == Loopback)
2590 alcSetError(device, ALC_INVALID_DEVICE);
2591 return 0;
2593 values[0] = ALC_FALSE;
2594 return 1;
2596 case ALC_FORMAT_CHANNELS_SOFT:
2597 if(device->Type != Loopback)
2599 alcSetError(device, ALC_INVALID_DEVICE);
2600 return 0;
2602 values[0] = device->FmtChans;
2603 return 1;
2605 case ALC_FORMAT_TYPE_SOFT:
2606 if(device->Type != Loopback)
2608 alcSetError(device, ALC_INVALID_DEVICE);
2609 return 0;
2611 values[0] = device->FmtType;
2612 return 1;
2614 case ALC_MONO_SOURCES:
2615 values[0] = device->NumMonoSources;
2616 return 1;
2618 case ALC_STEREO_SOURCES:
2619 values[0] = device->NumStereoSources;
2620 return 1;
2622 case ALC_MAX_AUXILIARY_SENDS:
2623 values[0] = device->NumAuxSends;
2624 return 1;
2626 case ALC_CONNECTED:
2627 values[0] = device->Connected;
2628 return 1;
2630 case ALC_HRTF_SOFT:
2631 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2632 return 1;
2634 default:
2635 alcSetError(device, ALC_INVALID_ENUM);
2636 return 0;
2638 return 0;
2641 /* alcGetIntegerv
2643 * Returns information about the device and the version of OpenAL
2645 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2647 device = VerifyDevice(device);
2648 if(size <= 0 || values == NULL)
2649 alcSetError(device, ALC_INVALID_VALUE);
2650 else
2651 GetIntegerv(device, param, size, values);
2652 if(device) ALCdevice_DecRef(device);
2655 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2657 ALCint *ivals;
2658 ALsizei i;
2660 device = VerifyDevice(device);
2661 if(size <= 0 || values == NULL)
2662 alcSetError(device, ALC_INVALID_VALUE);
2663 else if(!device || device->Type == Capture)
2665 ivals = malloc(size * sizeof(ALCint));
2666 size = GetIntegerv(device, pname, size, ivals);
2667 for(i = 0;i < size;i++)
2668 values[i] = ivals[i];
2669 free(ivals);
2671 else /* render device */
2673 switch(pname)
2675 case ALC_ATTRIBUTES_SIZE:
2676 *values = 17;
2677 break;
2679 case ALC_ALL_ATTRIBUTES:
2680 if(size < 17)
2681 alcSetError(device, ALC_INVALID_VALUE);
2682 else
2684 int i = 0;
2686 V0(device->Backend,lock)();
2687 values[i++] = ALC_FREQUENCY;
2688 values[i++] = device->Frequency;
2690 if(device->Type != Loopback)
2692 values[i++] = ALC_REFRESH;
2693 values[i++] = device->Frequency / device->UpdateSize;
2695 values[i++] = ALC_SYNC;
2696 values[i++] = ALC_FALSE;
2698 else
2700 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2701 values[i++] = device->FmtChans;
2703 values[i++] = ALC_FORMAT_TYPE_SOFT;
2704 values[i++] = device->FmtType;
2707 values[i++] = ALC_MONO_SOURCES;
2708 values[i++] = device->NumMonoSources;
2710 values[i++] = ALC_STEREO_SOURCES;
2711 values[i++] = device->NumStereoSources;
2713 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2714 values[i++] = device->NumAuxSends;
2716 values[i++] = ALC_HRTF_SOFT;
2717 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2719 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2720 values[i++] = device->ClockBase +
2721 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2723 values[i++] = 0;
2724 V0(device->Backend,unlock)();
2726 break;
2728 case ALC_DEVICE_CLOCK_SOFT:
2729 V0(device->Backend,lock)();
2730 *values = device->ClockBase +
2731 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2732 V0(device->Backend,unlock)();
2733 break;
2735 default:
2736 ivals = malloc(size * sizeof(ALCint));
2737 size = GetIntegerv(device, pname, size, ivals);
2738 for(i = 0;i < size;i++)
2739 values[i] = ivals[i];
2740 free(ivals);
2741 break;
2744 if(device)
2745 ALCdevice_DecRef(device);
2749 /* alcIsExtensionPresent
2751 * Determines if there is support for a particular extension
2753 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2755 ALCboolean bResult = ALC_FALSE;
2757 device = VerifyDevice(device);
2759 if(!extName)
2760 alcSetError(device, ALC_INVALID_VALUE);
2761 else
2763 size_t len = strlen(extName);
2764 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2765 while(ptr && *ptr)
2767 if(strncasecmp(ptr, extName, len) == 0 &&
2768 (ptr[len] == '\0' || isspace(ptr[len])))
2770 bResult = ALC_TRUE;
2771 break;
2773 if((ptr=strchr(ptr, ' ')) != NULL)
2775 do {
2776 ++ptr;
2777 } while(isspace(*ptr));
2781 if(device)
2782 ALCdevice_DecRef(device);
2783 return bResult;
2787 /* alcGetProcAddress
2789 * Retrieves the function address for a particular extension function
2791 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2793 ALCvoid *ptr = NULL;
2795 if(!funcName)
2797 device = VerifyDevice(device);
2798 alcSetError(device, ALC_INVALID_VALUE);
2799 if(device) ALCdevice_DecRef(device);
2801 else
2803 ALsizei i = 0;
2804 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2805 i++;
2806 ptr = alcFunctions[i].address;
2809 return ptr;
2813 /* alcGetEnumValue
2815 * Get the value for a particular ALC enumeration name
2817 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2819 ALCenum val = 0;
2821 if(!enumName)
2823 device = VerifyDevice(device);
2824 alcSetError(device, ALC_INVALID_VALUE);
2825 if(device) ALCdevice_DecRef(device);
2827 else
2829 ALsizei i = 0;
2830 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2831 i++;
2832 val = enumeration[i].value;
2835 return val;
2839 /* alcCreateContext
2841 * Create and attach a context to the given device.
2843 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2845 ALCcontext *ALContext;
2846 ALCenum err;
2848 LockLists();
2849 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2851 UnlockLists();
2852 alcSetError(device, ALC_INVALID_DEVICE);
2853 if(device) ALCdevice_DecRef(device);
2854 return NULL;
2857 device->LastError = ALC_NO_ERROR;
2859 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2861 UnlockLists();
2862 alcSetError(device, err);
2863 if(err == ALC_INVALID_DEVICE)
2865 ALCdevice_Lock(device);
2866 aluHandleDisconnect(device);
2867 ALCdevice_Unlock(device);
2869 ALCdevice_DecRef(device);
2870 return NULL;
2873 ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener));
2874 if(ALContext)
2876 InitRef(&ALContext->ref, 1);
2877 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2879 VECTOR_INIT(ALContext->ActiveAuxSlots);
2881 ALContext->MaxActiveSources = 256;
2882 ALContext->ActiveSources = calloc(ALContext->MaxActiveSources,
2883 sizeof(ALContext->ActiveSources[0]));
2885 if(!ALContext || !ALContext->ActiveSources)
2887 if(!device->ContextList)
2889 V0(device->Backend,stop)();
2890 device->Flags &= ~DEVICE_RUNNING;
2892 UnlockLists();
2894 if(ALContext)
2896 free(ALContext->ActiveSources);
2897 ALContext->ActiveSources = NULL;
2899 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2901 free(ALContext);
2902 ALContext = NULL;
2905 alcSetError(device, ALC_OUT_OF_MEMORY);
2906 ALCdevice_DecRef(device);
2907 return NULL;
2910 ALContext->Device = device;
2911 ALCdevice_IncRef(device);
2912 InitContext(ALContext);
2914 do {
2915 ALContext->next = device->ContextList;
2916 } while(CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext) != ALContext->next);
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(!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;
2957 Context = altss_get(LocalContext);
2958 if(!Context) Context = GlobalContext;
2960 return Context;
2963 /* alcGetThreadContext
2965 * Returns the currently active thread-local context
2967 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2969 ALCcontext *Context;
2970 Context = altss_get(LocalContext);
2971 return Context;
2975 /* alcMakeContextCurrent
2977 * Makes the given context the active process-wide context, and removes the
2978 * thread-local context for the calling thread.
2980 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2982 /* context must be valid or NULL */
2983 if(context && !(context=VerifyContext(context)))
2985 alcSetError(NULL, ALC_INVALID_CONTEXT);
2986 return ALC_FALSE;
2988 /* context's reference count is already incremented */
2989 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
2990 if(context) ALCcontext_DecRef(context);
2992 if((context=altss_get(LocalContext)) != NULL)
2994 altss_set(LocalContext, NULL);
2995 ALCcontext_DecRef(context);
2998 return ALC_TRUE;
3001 /* alcSetThreadContext
3003 * Makes the given context the active context for the current thread
3005 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3007 ALCcontext *old;
3009 /* context must be valid or NULL */
3010 if(context && !(context=VerifyContext(context)))
3012 alcSetError(NULL, ALC_INVALID_CONTEXT);
3013 return ALC_FALSE;
3015 /* context's reference count is already incremented */
3016 old = altss_get(LocalContext);
3017 altss_set(LocalContext, context);
3018 if(old) ALCcontext_DecRef(old);
3020 return ALC_TRUE;
3024 /* alcGetContextsDevice
3026 * Returns the device that a particular context is attached to
3028 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3030 ALCdevice *Device;
3032 if(!(Context=VerifyContext(Context)))
3034 alcSetError(NULL, ALC_INVALID_CONTEXT);
3035 return NULL;
3037 Device = Context->Device;
3038 ALCcontext_DecRef(Context);
3040 return Device;
3044 /* alcOpenDevice
3046 * Opens the named device.
3048 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3050 const ALCchar *fmt;
3051 ALCdevice *device;
3052 ALCenum err;
3054 DO_INITCONFIG();
3056 if(!PlaybackBackend.name)
3058 alcSetError(NULL, ALC_INVALID_VALUE);
3059 return NULL;
3062 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3063 deviceName = NULL;
3065 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3066 if(!device)
3068 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3069 return NULL;
3072 //Validate device
3073 InitRef(&device->ref, 1);
3074 device->Connected = ALC_TRUE;
3075 device->Type = Playback;
3076 device->LastError = ALC_NO_ERROR;
3078 device->Flags = 0;
3079 device->Bs2b = NULL;
3080 device->Bs2bLevel = 0;
3081 AL_STRING_INIT(device->DeviceName);
3083 device->ContextList = NULL;
3085 device->ClockBase = 0;
3086 device->SamplesDone = 0;
3088 device->MaxNoOfSources = 256;
3089 device->AuxiliaryEffectSlotMax = 4;
3090 device->NumAuxSends = MAX_SENDS;
3092 InitUIntMap(&device->BufferMap, ~0);
3093 InitUIntMap(&device->EffectMap, ~0);
3094 InitUIntMap(&device->FilterMap, ~0);
3095 InitUIntMap(&device->SfontMap, ~0);
3096 InitUIntMap(&device->PresetMap, ~0);
3097 InitUIntMap(&device->FontsoundMap, ~0);
3099 //Set output format
3100 device->FmtChans = DevFmtChannelsDefault;
3101 device->FmtType = DevFmtTypeDefault;
3102 device->Frequency = DEFAULT_OUTPUT_RATE;
3103 device->NumUpdates = 4;
3104 device->UpdateSize = 1024;
3106 if(!PlaybackBackend.getFactory)
3107 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3108 ALCbackend_Playback);
3109 else
3111 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3112 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3114 if(!device->Backend)
3116 al_free(device);
3117 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3118 return NULL;
3122 if(ConfigValueStr(NULL, "channels", &fmt))
3124 static const struct {
3125 const char name[16];
3126 enum DevFmtChannels chans;
3127 } chanlist[] = {
3128 { "mono", DevFmtMono },
3129 { "stereo", DevFmtStereo },
3130 { "quad", DevFmtQuad },
3131 { "surround51", DevFmtX51 },
3132 { "surround61", DevFmtX61 },
3133 { "surround71", DevFmtX71 },
3135 size_t i;
3137 for(i = 0;i < COUNTOF(chanlist);i++)
3139 if(strcasecmp(chanlist[i].name, fmt) == 0)
3141 device->FmtChans = chanlist[i].chans;
3142 device->Flags |= DEVICE_CHANNELS_REQUEST;
3143 break;
3146 if(i == COUNTOF(chanlist))
3147 ERR("Unsupported channels: %s\n", fmt);
3149 if(ConfigValueStr(NULL, "sample-type", &fmt))
3151 static const struct {
3152 const char name[16];
3153 enum DevFmtType type;
3154 } typelist[] = {
3155 { "int8", DevFmtByte },
3156 { "uint8", DevFmtUByte },
3157 { "int16", DevFmtShort },
3158 { "uint16", DevFmtUShort },
3159 { "int32", DevFmtInt },
3160 { "uint32", DevFmtUInt },
3161 { "float32", DevFmtFloat },
3163 size_t i;
3165 for(i = 0;i < COUNTOF(typelist);i++)
3167 if(strcasecmp(typelist[i].name, fmt) == 0)
3169 device->FmtType = typelist[i].type;
3170 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3171 break;
3174 if(i == COUNTOF(typelist))
3175 ERR("Unsupported sample-type: %s\n", fmt);
3177 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3178 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3179 ConfigValueStr(NULL, "format", &fmt))
3181 static const struct {
3182 const char name[32];
3183 enum DevFmtChannels channels;
3184 enum DevFmtType type;
3185 } formats[] = {
3186 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3187 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3188 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3189 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3190 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3191 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3193 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3194 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3195 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3196 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3197 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3198 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3200 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3201 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3202 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3203 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3204 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3205 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3207 size_t i;
3209 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3210 for(i = 0;i < COUNTOF(formats);i++)
3212 if(strcasecmp(fmt, formats[i].name) == 0)
3214 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3215 device->FmtChans = formats[i].channels;
3216 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3217 device->FmtType = formats[i].type;
3218 device->Flags |= DEVICE_FORMAT_REQUEST;
3219 break;
3222 if(i == COUNTOF(formats))
3223 ERR("Unsupported format: %s\n", fmt);
3225 #undef DEVICE_FORMAT_REQUEST
3227 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3229 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3230 if(device->Frequency < MIN_OUTPUT_RATE)
3231 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3232 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3235 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3236 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3238 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3239 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3240 if((CPUCapFlags&CPU_CAP_SSE))
3241 device->UpdateSize = (device->UpdateSize+3)&~3;
3243 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3244 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3246 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3247 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3249 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3250 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3252 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3254 device->NumStereoSources = 1;
3255 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3257 device->Synth = SynthCreate(device);
3258 if(!device->Synth)
3260 DELETE_OBJ(device->Backend);
3261 al_free(device);
3262 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3263 return NULL;
3266 // Find a playback device to open
3267 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3269 DELETE_OBJ(device->Synth);
3270 DELETE_OBJ(device->Backend);
3271 al_free(device);
3272 alcSetError(NULL, err);
3273 return NULL;
3276 if(DefaultEffect.type != AL_EFFECT_NULL)
3278 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3279 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3281 device->DefaultSlot = NULL;
3282 ERR("Failed to initialize the default effect slot\n");
3284 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3286 ALeffectState *state = device->DefaultSlot->EffectState;
3287 device->DefaultSlot = NULL;
3288 DELETE_OBJ(state);
3289 ERR("Failed to initialize the default effect\n");
3293 do {
3294 device->next = DeviceList;
3295 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3297 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3298 return device;
3301 /* alcCloseDevice
3303 * Closes the given device.
3305 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
3307 ALCdevice *volatile*list;
3308 ALCcontext *ctx;
3310 LockLists();
3311 list = &DeviceList;
3312 while(*list && *list != Device)
3313 list = &(*list)->next;
3315 if(!*list || (*list)->Type == Capture)
3317 alcSetError(*list, ALC_INVALID_DEVICE);
3318 UnlockLists();
3319 return ALC_FALSE;
3322 *list = (*list)->next;
3323 UnlockLists();
3325 while((ctx=Device->ContextList) != NULL)
3327 WARN("Releasing context %p\n", ctx);
3328 ReleaseContext(ctx, Device);
3330 if((Device->Flags&DEVICE_RUNNING))
3331 V0(Device->Backend,stop)();
3332 Device->Flags &= ~DEVICE_RUNNING;
3334 ALCdevice_DecRef(Device);
3336 return ALC_TRUE;
3340 /************************************************
3341 * ALC capture functions
3342 ************************************************/
3343 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3345 ALCdevice *device = NULL;
3346 ALCenum err;
3348 DO_INITCONFIG();
3350 if(!CaptureBackend.name)
3352 alcSetError(NULL, ALC_INVALID_VALUE);
3353 return NULL;
3356 if(samples <= 0)
3358 alcSetError(NULL, ALC_INVALID_VALUE);
3359 return NULL;
3362 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3363 deviceName = NULL;
3365 device = al_calloc(16, sizeof(ALCdevice));
3366 if(!device)
3368 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3369 return NULL;
3372 //Validate device
3373 InitRef(&device->ref, 1);
3374 device->Connected = ALC_TRUE;
3375 device->Type = Capture;
3377 AL_STRING_INIT(device->DeviceName);
3379 InitUIntMap(&device->BufferMap, ~0);
3380 InitUIntMap(&device->EffectMap, ~0);
3381 InitUIntMap(&device->FilterMap, ~0);
3382 InitUIntMap(&device->SfontMap, ~0);
3383 InitUIntMap(&device->PresetMap, ~0);
3384 InitUIntMap(&device->FontsoundMap, ~0);
3386 if(!CaptureBackend.getFactory)
3387 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3388 ALCbackend_Capture);
3389 else
3391 ALCbackendFactory *factory = CaptureBackend.getFactory();
3392 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3394 if(!device->Backend)
3396 al_free(device);
3397 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3398 return NULL;
3401 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3402 device->Frequency = frequency;
3404 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3405 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3407 al_free(device);
3408 alcSetError(NULL, ALC_INVALID_ENUM);
3409 return NULL;
3412 device->UpdateSize = samples;
3413 device->NumUpdates = 1;
3415 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3417 al_free(device);
3418 alcSetError(NULL, err);
3419 return NULL;
3422 do {
3423 device->next = DeviceList;
3424 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3426 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3427 return device;
3430 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
3432 ALCdevice *volatile*list;
3434 LockLists();
3435 list = &DeviceList;
3436 while(*list && *list != Device)
3437 list = &(*list)->next;
3439 if(!*list || (*list)->Type != Capture)
3441 alcSetError(*list, ALC_INVALID_DEVICE);
3442 UnlockLists();
3443 return ALC_FALSE;
3446 *list = (*list)->next;
3447 UnlockLists();
3449 ALCdevice_DecRef(Device);
3451 return ALC_TRUE;
3454 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3456 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3457 alcSetError(device, ALC_INVALID_DEVICE);
3458 else
3460 ALCdevice_Lock(device);
3461 if(device->Connected)
3463 if(!(device->Flags&DEVICE_RUNNING))
3464 V0(device->Backend,start)();
3465 device->Flags |= DEVICE_RUNNING;
3467 ALCdevice_Unlock(device);
3470 if(device) ALCdevice_DecRef(device);
3473 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3475 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3476 alcSetError(device, ALC_INVALID_DEVICE);
3477 else
3479 ALCdevice_Lock(device);
3480 if((device->Flags&DEVICE_RUNNING))
3481 V0(device->Backend,stop)();
3482 device->Flags &= ~DEVICE_RUNNING;
3483 ALCdevice_Unlock(device);
3486 if(device) ALCdevice_DecRef(device);
3489 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3491 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3492 alcSetError(device, ALC_INVALID_DEVICE);
3493 else
3495 ALCenum err = ALC_INVALID_VALUE;
3497 ALCdevice_Lock(device);
3498 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3499 err = V(device->Backend,captureSamples)(buffer, samples);
3500 ALCdevice_Unlock(device);
3502 if(err != ALC_NO_ERROR)
3503 alcSetError(device, err);
3505 if(device) ALCdevice_DecRef(device);
3509 /************************************************
3510 * ALC loopback functions
3511 ************************************************/
3513 /* alcLoopbackOpenDeviceSOFT
3515 * Open a loopback device, for manual rendering.
3517 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3519 ALCbackendFactory *factory;
3520 ALCdevice *device;
3522 DO_INITCONFIG();
3524 /* Make sure the device name, if specified, is us. */
3525 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3527 alcSetError(NULL, ALC_INVALID_VALUE);
3528 return NULL;
3531 device = al_calloc(16, sizeof(ALCdevice));
3532 if(!device)
3534 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3535 return NULL;
3538 //Validate device
3539 InitRef(&device->ref, 1);
3540 device->Connected = ALC_TRUE;
3541 device->Type = Loopback;
3542 device->LastError = ALC_NO_ERROR;
3544 device->Flags = 0;
3545 device->Bs2b = NULL;
3546 device->Bs2bLevel = 0;
3547 AL_STRING_INIT(device->DeviceName);
3549 device->ContextList = NULL;
3551 device->ClockBase = 0;
3552 device->SamplesDone = 0;
3554 device->MaxNoOfSources = 256;
3555 device->AuxiliaryEffectSlotMax = 4;
3556 device->NumAuxSends = MAX_SENDS;
3558 InitUIntMap(&device->BufferMap, ~0);
3559 InitUIntMap(&device->EffectMap, ~0);
3560 InitUIntMap(&device->FilterMap, ~0);
3561 InitUIntMap(&device->SfontMap, ~0);
3562 InitUIntMap(&device->PresetMap, ~0);
3563 InitUIntMap(&device->FontsoundMap, ~0);
3565 factory = ALCloopbackFactory_getFactory();
3566 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3567 if(!device->Backend)
3569 al_free(device);
3570 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3571 return NULL;
3574 //Set output format
3575 device->NumUpdates = 0;
3576 device->UpdateSize = 0;
3578 device->Frequency = DEFAULT_OUTPUT_RATE;
3579 device->FmtChans = DevFmtChannelsDefault;
3580 device->FmtType = DevFmtTypeDefault;
3582 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3583 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3585 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3586 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3588 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3589 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3591 device->NumStereoSources = 1;
3592 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3594 device->Synth = SynthCreate(device);
3595 if(!device->Synth)
3597 DELETE_OBJ(device->Backend);
3598 al_free(device);
3599 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3600 return NULL;
3603 // Open the "backend"
3604 V(device->Backend,open)("Loopback");
3605 do {
3606 device->next = DeviceList;
3607 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3609 TRACE("Created device %p\n", device);
3610 return device;
3613 /* alcIsRenderFormatSupportedSOFT
3615 * Determines if the loopback device supports the given format for rendering.
3617 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3619 ALCboolean ret = ALC_FALSE;
3621 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3622 alcSetError(device, ALC_INVALID_DEVICE);
3623 else if(freq <= 0)
3624 alcSetError(device, ALC_INVALID_VALUE);
3625 else
3627 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3628 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3629 freq >= MIN_OUTPUT_RATE)
3630 ret = ALC_TRUE;
3632 if(device) ALCdevice_DecRef(device);
3634 return ret;
3637 /* alcRenderSamplesSOFT
3639 * Renders some samples into a buffer, using the format last set by the
3640 * attributes given to alcCreateContext.
3642 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3644 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3645 alcSetError(device, ALC_INVALID_DEVICE);
3646 else if(samples < 0 || (samples > 0 && buffer == NULL))
3647 alcSetError(device, ALC_INVALID_VALUE);
3648 else
3649 aluMixData(device, buffer, samples);
3650 if(device) ALCdevice_DecRef(device);
3654 /************************************************
3655 * ALC DSP pause/resume functions
3656 ************************************************/
3658 /* alcDevicePauseSOFT
3660 * Pause the DSP to stop audio processing.
3662 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3664 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3665 alcSetError(device, ALC_INVALID_DEVICE);
3666 else
3668 LockLists();
3669 if((device->Flags&DEVICE_RUNNING))
3670 V0(device->Backend,stop)();
3671 device->Flags &= ~DEVICE_RUNNING;
3672 device->Flags |= DEVICE_PAUSED;
3673 UnlockLists();
3675 if(device) ALCdevice_DecRef(device);
3678 /* alcDeviceResumeSOFT
3680 * Resume the DSP to restart audio processing.
3682 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3684 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3685 alcSetError(device, ALC_INVALID_DEVICE);
3686 else
3688 LockLists();
3689 if((device->Flags&DEVICE_PAUSED))
3691 device->Flags &= ~DEVICE_PAUSED;
3692 if(device->ContextList != NULL)
3694 if(V0(device->Backend,start)() != ALC_FALSE)
3695 device->Flags |= DEVICE_RUNNING;
3696 else
3698 alcSetError(device, ALC_INVALID_DEVICE);
3699 ALCdevice_Lock(device);
3700 aluHandleDisconnect(device);
3701 ALCdevice_Unlock(device);
3705 UnlockLists();
3707 if(device) ALCdevice_DecRef(device);