Use better GUI item names for the resampler option
[openal-soft.git] / Alc / ALc.c
blobfdc7bcbf81b5cf5e88cc7669fdf8fbe73dba00bd
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList[] = {
64 #ifdef HAVE_PULSEAUDIO
65 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
66 #endif
67 #ifdef HAVE_ALSA
68 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_COREAUDIO
71 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
72 #endif
73 #ifdef HAVE_OSS
74 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
75 #endif
76 #ifdef HAVE_SOLARIS
77 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SNDIO
80 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_QSA
83 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_MMDEVAPI
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
87 #endif
88 #ifdef HAVE_DSOUND
89 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_WINMM
92 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
93 #endif
94 #ifdef HAVE_PORTAUDIO
95 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
96 #endif
97 #ifdef HAVE_OPENSL
98 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
99 #endif
101 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
102 #ifdef HAVE_WAVE
103 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #endif
106 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
108 #undef EmptyFuncs
110 static struct BackendInfo PlaybackBackend;
111 static struct BackendInfo CaptureBackend;
114 /************************************************
115 * Functions, enums, and errors
116 ************************************************/
117 typedef struct ALCfunction {
118 const ALCchar *funcName;
119 ALCvoid *address;
120 } ALCfunction;
122 typedef struct ALCenums {
123 const ALCchar *enumName;
124 ALCenum value;
125 } ALCenums;
127 #define DECL(x) { #x, (ALCvoid*)(x) }
128 static const ALCfunction alcFunctions[] = {
129 DECL(alcCreateContext),
130 DECL(alcMakeContextCurrent),
131 DECL(alcProcessContext),
132 DECL(alcSuspendContext),
133 DECL(alcDestroyContext),
134 DECL(alcGetCurrentContext),
135 DECL(alcGetContextsDevice),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
143 DECL(alcGetIntegerv),
144 DECL(alcCaptureOpenDevice),
145 DECL(alcCaptureCloseDevice),
146 DECL(alcCaptureStart),
147 DECL(alcCaptureStop),
148 DECL(alcCaptureSamples),
150 DECL(alcSetThreadContext),
151 DECL(alcGetThreadContext),
153 DECL(alcLoopbackOpenDeviceSOFT),
154 DECL(alcIsRenderFormatSupportedSOFT),
155 DECL(alcRenderSamplesSOFT),
157 DECL(alcDevicePauseSOFT),
158 DECL(alcDeviceResumeSOFT),
160 DECL(alcGetInteger64vSOFT),
162 DECL(alEnable),
163 DECL(alDisable),
164 DECL(alIsEnabled),
165 DECL(alGetString),
166 DECL(alGetBooleanv),
167 DECL(alGetIntegerv),
168 DECL(alGetFloatv),
169 DECL(alGetDoublev),
170 DECL(alGetBoolean),
171 DECL(alGetInteger),
172 DECL(alGetFloat),
173 DECL(alGetDouble),
174 DECL(alGetError),
175 DECL(alIsExtensionPresent),
176 DECL(alGetProcAddress),
177 DECL(alGetEnumValue),
178 DECL(alListenerf),
179 DECL(alListener3f),
180 DECL(alListenerfv),
181 DECL(alListeneri),
182 DECL(alListener3i),
183 DECL(alListeneriv),
184 DECL(alGetListenerf),
185 DECL(alGetListener3f),
186 DECL(alGetListenerfv),
187 DECL(alGetListeneri),
188 DECL(alGetListener3i),
189 DECL(alGetListeneriv),
190 DECL(alGenSources),
191 DECL(alDeleteSources),
192 DECL(alIsSource),
193 DECL(alSourcef),
194 DECL(alSource3f),
195 DECL(alSourcefv),
196 DECL(alSourcei),
197 DECL(alSource3i),
198 DECL(alSourceiv),
199 DECL(alGetSourcef),
200 DECL(alGetSource3f),
201 DECL(alGetSourcefv),
202 DECL(alGetSourcei),
203 DECL(alGetSource3i),
204 DECL(alGetSourceiv),
205 DECL(alSourcePlayv),
206 DECL(alSourceStopv),
207 DECL(alSourceRewindv),
208 DECL(alSourcePausev),
209 DECL(alSourcePlay),
210 DECL(alSourceStop),
211 DECL(alSourceRewind),
212 DECL(alSourcePause),
213 DECL(alSourceQueueBuffers),
214 DECL(alSourceUnqueueBuffers),
215 DECL(alGenBuffers),
216 DECL(alDeleteBuffers),
217 DECL(alIsBuffer),
218 DECL(alBufferData),
219 DECL(alBufferf),
220 DECL(alBuffer3f),
221 DECL(alBufferfv),
222 DECL(alBufferi),
223 DECL(alBuffer3i),
224 DECL(alBufferiv),
225 DECL(alGetBufferf),
226 DECL(alGetBuffer3f),
227 DECL(alGetBufferfv),
228 DECL(alGetBufferi),
229 DECL(alGetBuffer3i),
230 DECL(alGetBufferiv),
231 DECL(alDopplerFactor),
232 DECL(alDopplerVelocity),
233 DECL(alSpeedOfSound),
234 DECL(alDistanceModel),
236 DECL(alGenFilters),
237 DECL(alDeleteFilters),
238 DECL(alIsFilter),
239 DECL(alFilteri),
240 DECL(alFilteriv),
241 DECL(alFilterf),
242 DECL(alFilterfv),
243 DECL(alGetFilteri),
244 DECL(alGetFilteriv),
245 DECL(alGetFilterf),
246 DECL(alGetFilterfv),
247 DECL(alGenEffects),
248 DECL(alDeleteEffects),
249 DECL(alIsEffect),
250 DECL(alEffecti),
251 DECL(alEffectiv),
252 DECL(alEffectf),
253 DECL(alEffectfv),
254 DECL(alGetEffecti),
255 DECL(alGetEffectiv),
256 DECL(alGetEffectf),
257 DECL(alGetEffectfv),
258 DECL(alGenAuxiliaryEffectSlots),
259 DECL(alDeleteAuxiliaryEffectSlots),
260 DECL(alIsAuxiliaryEffectSlot),
261 DECL(alAuxiliaryEffectSloti),
262 DECL(alAuxiliaryEffectSlotiv),
263 DECL(alAuxiliaryEffectSlotf),
264 DECL(alAuxiliaryEffectSlotfv),
265 DECL(alGetAuxiliaryEffectSloti),
266 DECL(alGetAuxiliaryEffectSlotiv),
267 DECL(alGetAuxiliaryEffectSlotf),
268 DECL(alGetAuxiliaryEffectSlotfv),
270 DECL(alBufferSubDataSOFT),
272 DECL(alBufferSamplesSOFT),
273 DECL(alBufferSubSamplesSOFT),
274 DECL(alGetBufferSamplesSOFT),
275 DECL(alIsBufferFormatSupportedSOFT),
277 DECL(alDeferUpdatesSOFT),
278 DECL(alProcessUpdatesSOFT),
280 DECL(alSourcedSOFT),
281 DECL(alSource3dSOFT),
282 DECL(alSourcedvSOFT),
283 DECL(alGetSourcedSOFT),
284 DECL(alGetSource3dSOFT),
285 DECL(alGetSourcedvSOFT),
286 DECL(alSourcei64SOFT),
287 DECL(alSource3i64SOFT),
288 DECL(alSourcei64vSOFT),
289 DECL(alGetSourcei64SOFT),
290 DECL(alGetSource3i64SOFT),
291 DECL(alGetSourcei64vSOFT),
293 DECL(alGenSoundfontsSOFT),
294 DECL(alDeleteSoundfontsSOFT),
295 DECL(alIsSoundfontSOFT),
296 DECL(alGetSoundfontivSOFT),
297 DECL(alSoundfontPresetsSOFT),
298 DECL(alGenPresetsSOFT),
299 DECL(alDeletePresetsSOFT),
300 DECL(alIsPresetSOFT),
301 DECL(alPresetiSOFT),
302 DECL(alPresetivSOFT),
303 DECL(alGetPresetivSOFT),
304 DECL(alPresetFontsoundsSOFT),
305 DECL(alGenFontsoundsSOFT),
306 DECL(alDeleteFontsoundsSOFT),
307 DECL(alIsFontsoundSOFT),
308 DECL(alFontsoundiSOFT),
309 DECL(alFontsound2iSOFT),
310 DECL(alFontsoundivSOFT),
311 DECL(alGetFontsoundivSOFT),
312 DECL(alFontsoundModulatoriSOFT),
313 DECL(alGetFontsoundModulatorivSOFT),
314 DECL(alMidiSoundfontSOFT),
315 DECL(alMidiSoundfontvSOFT),
316 DECL(alMidiEventSOFT),
317 DECL(alMidiSysExSOFT),
318 DECL(alMidiPlaySOFT),
319 DECL(alMidiPauseSOFT),
320 DECL(alMidiStopSOFT),
321 DECL(alMidiResetSOFT),
322 DECL(alMidiGainSOFT),
323 DECL(alGetInteger64SOFT),
324 DECL(alGetInteger64vSOFT),
325 DECL(alLoadSoundfontSOFT),
327 { NULL, NULL }
329 #undef DECL
331 #define DECL(x) { #x, (x) }
332 static const ALCenums enumeration[] = {
333 DECL(ALC_INVALID),
334 DECL(ALC_FALSE),
335 DECL(ALC_TRUE),
337 DECL(ALC_MAJOR_VERSION),
338 DECL(ALC_MINOR_VERSION),
339 DECL(ALC_ATTRIBUTES_SIZE),
340 DECL(ALC_ALL_ATTRIBUTES),
341 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
342 DECL(ALC_DEVICE_SPECIFIER),
343 DECL(ALC_ALL_DEVICES_SPECIFIER),
344 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
345 DECL(ALC_EXTENSIONS),
346 DECL(ALC_FREQUENCY),
347 DECL(ALC_REFRESH),
348 DECL(ALC_SYNC),
349 DECL(ALC_MONO_SOURCES),
350 DECL(ALC_STEREO_SOURCES),
351 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
352 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
353 DECL(ALC_CAPTURE_SAMPLES),
354 DECL(ALC_CONNECTED),
356 DECL(ALC_EFX_MAJOR_VERSION),
357 DECL(ALC_EFX_MINOR_VERSION),
358 DECL(ALC_MAX_AUXILIARY_SENDS),
360 DECL(ALC_FORMAT_CHANNELS_SOFT),
361 DECL(ALC_FORMAT_TYPE_SOFT),
363 DECL(ALC_MONO_SOFT),
364 DECL(ALC_STEREO_SOFT),
365 DECL(ALC_QUAD_SOFT),
366 DECL(ALC_5POINT1_SOFT),
367 DECL(ALC_6POINT1_SOFT),
368 DECL(ALC_7POINT1_SOFT),
370 DECL(ALC_BYTE_SOFT),
371 DECL(ALC_UNSIGNED_BYTE_SOFT),
372 DECL(ALC_SHORT_SOFT),
373 DECL(ALC_UNSIGNED_SHORT_SOFT),
374 DECL(ALC_INT_SOFT),
375 DECL(ALC_UNSIGNED_INT_SOFT),
376 DECL(ALC_FLOAT_SOFT),
378 DECL(ALC_NO_ERROR),
379 DECL(ALC_INVALID_DEVICE),
380 DECL(ALC_INVALID_CONTEXT),
381 DECL(ALC_INVALID_ENUM),
382 DECL(ALC_INVALID_VALUE),
383 DECL(ALC_OUT_OF_MEMORY),
386 DECL(AL_INVALID),
387 DECL(AL_NONE),
388 DECL(AL_FALSE),
389 DECL(AL_TRUE),
391 DECL(AL_SOURCE_RELATIVE),
392 DECL(AL_CONE_INNER_ANGLE),
393 DECL(AL_CONE_OUTER_ANGLE),
394 DECL(AL_PITCH),
395 DECL(AL_POSITION),
396 DECL(AL_DIRECTION),
397 DECL(AL_VELOCITY),
398 DECL(AL_LOOPING),
399 DECL(AL_BUFFER),
400 DECL(AL_GAIN),
401 DECL(AL_MIN_GAIN),
402 DECL(AL_MAX_GAIN),
403 DECL(AL_ORIENTATION),
404 DECL(AL_REFERENCE_DISTANCE),
405 DECL(AL_ROLLOFF_FACTOR),
406 DECL(AL_CONE_OUTER_GAIN),
407 DECL(AL_MAX_DISTANCE),
408 DECL(AL_SEC_OFFSET),
409 DECL(AL_SAMPLE_OFFSET),
410 DECL(AL_SAMPLE_RW_OFFSETS_SOFT),
411 DECL(AL_BYTE_OFFSET),
412 DECL(AL_BYTE_RW_OFFSETS_SOFT),
413 DECL(AL_SOURCE_TYPE),
414 DECL(AL_STATIC),
415 DECL(AL_STREAMING),
416 DECL(AL_UNDETERMINED),
417 DECL(AL_METERS_PER_UNIT),
418 DECL(AL_DIRECT_CHANNELS_SOFT),
420 DECL(AL_DIRECT_FILTER),
421 DECL(AL_AUXILIARY_SEND_FILTER),
422 DECL(AL_AIR_ABSORPTION_FACTOR),
423 DECL(AL_ROOM_ROLLOFF_FACTOR),
424 DECL(AL_CONE_OUTER_GAINHF),
425 DECL(AL_DIRECT_FILTER_GAINHF_AUTO),
426 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO),
427 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO),
429 DECL(AL_SOURCE_STATE),
430 DECL(AL_INITIAL),
431 DECL(AL_PLAYING),
432 DECL(AL_PAUSED),
433 DECL(AL_STOPPED),
435 DECL(AL_BUFFERS_QUEUED),
436 DECL(AL_BUFFERS_PROCESSED),
438 DECL(AL_FORMAT_MONO8),
439 DECL(AL_FORMAT_MONO16),
440 DECL(AL_FORMAT_MONO_FLOAT32),
441 DECL(AL_FORMAT_MONO_DOUBLE_EXT),
442 DECL(AL_FORMAT_STEREO8),
443 DECL(AL_FORMAT_STEREO16),
444 DECL(AL_FORMAT_STEREO_FLOAT32),
445 DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
446 DECL(AL_FORMAT_MONO_IMA4),
447 DECL(AL_FORMAT_STEREO_IMA4),
448 DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
449 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
450 DECL(AL_FORMAT_QUAD8_LOKI),
451 DECL(AL_FORMAT_QUAD16_LOKI),
452 DECL(AL_FORMAT_QUAD8),
453 DECL(AL_FORMAT_QUAD16),
454 DECL(AL_FORMAT_QUAD32),
455 DECL(AL_FORMAT_51CHN8),
456 DECL(AL_FORMAT_51CHN16),
457 DECL(AL_FORMAT_51CHN32),
458 DECL(AL_FORMAT_61CHN8),
459 DECL(AL_FORMAT_61CHN16),
460 DECL(AL_FORMAT_61CHN32),
461 DECL(AL_FORMAT_71CHN8),
462 DECL(AL_FORMAT_71CHN16),
463 DECL(AL_FORMAT_71CHN32),
464 DECL(AL_FORMAT_REAR8),
465 DECL(AL_FORMAT_REAR16),
466 DECL(AL_FORMAT_REAR32),
467 DECL(AL_FORMAT_MONO_MULAW),
468 DECL(AL_FORMAT_MONO_MULAW_EXT),
469 DECL(AL_FORMAT_STEREO_MULAW),
470 DECL(AL_FORMAT_STEREO_MULAW_EXT),
471 DECL(AL_FORMAT_QUAD_MULAW),
472 DECL(AL_FORMAT_51CHN_MULAW),
473 DECL(AL_FORMAT_61CHN_MULAW),
474 DECL(AL_FORMAT_71CHN_MULAW),
475 DECL(AL_FORMAT_REAR_MULAW),
476 DECL(AL_FORMAT_MONO_ALAW_EXT),
477 DECL(AL_FORMAT_STEREO_ALAW_EXT),
479 DECL(AL_MONO8_SOFT),
480 DECL(AL_MONO16_SOFT),
481 DECL(AL_MONO32F_SOFT),
482 DECL(AL_STEREO8_SOFT),
483 DECL(AL_STEREO16_SOFT),
484 DECL(AL_STEREO32F_SOFT),
485 DECL(AL_QUAD8_SOFT),
486 DECL(AL_QUAD16_SOFT),
487 DECL(AL_QUAD32F_SOFT),
488 DECL(AL_REAR8_SOFT),
489 DECL(AL_REAR16_SOFT),
490 DECL(AL_REAR32F_SOFT),
491 DECL(AL_5POINT1_8_SOFT),
492 DECL(AL_5POINT1_16_SOFT),
493 DECL(AL_5POINT1_32F_SOFT),
494 DECL(AL_6POINT1_8_SOFT),
495 DECL(AL_6POINT1_16_SOFT),
496 DECL(AL_6POINT1_32F_SOFT),
497 DECL(AL_7POINT1_8_SOFT),
498 DECL(AL_7POINT1_16_SOFT),
499 DECL(AL_7POINT1_32F_SOFT),
501 DECL(AL_MONO_SOFT),
502 DECL(AL_STEREO_SOFT),
503 DECL(AL_QUAD_SOFT),
504 DECL(AL_REAR_SOFT),
505 DECL(AL_5POINT1_SOFT),
506 DECL(AL_6POINT1_SOFT),
507 DECL(AL_7POINT1_SOFT),
509 DECL(AL_BYTE_SOFT),
510 DECL(AL_UNSIGNED_BYTE_SOFT),
511 DECL(AL_SHORT_SOFT),
512 DECL(AL_UNSIGNED_SHORT_SOFT),
513 DECL(AL_INT_SOFT),
514 DECL(AL_UNSIGNED_INT_SOFT),
515 DECL(AL_FLOAT_SOFT),
516 DECL(AL_DOUBLE_SOFT),
517 DECL(AL_BYTE3_SOFT),
518 DECL(AL_UNSIGNED_BYTE3_SOFT),
520 DECL(AL_FREQUENCY),
521 DECL(AL_BITS),
522 DECL(AL_CHANNELS),
523 DECL(AL_SIZE),
524 DECL(AL_INTERNAL_FORMAT_SOFT),
525 DECL(AL_BYTE_LENGTH_SOFT),
526 DECL(AL_SAMPLE_LENGTH_SOFT),
527 DECL(AL_SEC_LENGTH_SOFT),
528 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
529 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
531 DECL(AL_UNUSED),
532 DECL(AL_PENDING),
533 DECL(AL_PROCESSED),
535 DECL(AL_NO_ERROR),
536 DECL(AL_INVALID_NAME),
537 DECL(AL_INVALID_ENUM),
538 DECL(AL_INVALID_VALUE),
539 DECL(AL_INVALID_OPERATION),
540 DECL(AL_OUT_OF_MEMORY),
542 DECL(AL_VENDOR),
543 DECL(AL_VERSION),
544 DECL(AL_RENDERER),
545 DECL(AL_EXTENSIONS),
547 DECL(AL_DOPPLER_FACTOR),
548 DECL(AL_DOPPLER_VELOCITY),
549 DECL(AL_DISTANCE_MODEL),
550 DECL(AL_SPEED_OF_SOUND),
551 DECL(AL_SOURCE_DISTANCE_MODEL),
552 DECL(AL_DEFERRED_UPDATES_SOFT),
554 DECL(AL_INVERSE_DISTANCE),
555 DECL(AL_INVERSE_DISTANCE_CLAMPED),
556 DECL(AL_LINEAR_DISTANCE),
557 DECL(AL_LINEAR_DISTANCE_CLAMPED),
558 DECL(AL_EXPONENT_DISTANCE),
559 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
561 DECL(AL_FILTER_TYPE),
562 DECL(AL_FILTER_NULL),
563 DECL(AL_FILTER_LOWPASS),
564 DECL(AL_FILTER_HIGHPASS),
565 DECL(AL_FILTER_BANDPASS),
567 DECL(AL_LOWPASS_GAIN),
568 DECL(AL_LOWPASS_GAINHF),
570 DECL(AL_HIGHPASS_GAIN),
571 DECL(AL_HIGHPASS_GAINLF),
573 DECL(AL_BANDPASS_GAIN),
574 DECL(AL_BANDPASS_GAINHF),
575 DECL(AL_BANDPASS_GAINLF),
577 DECL(AL_EFFECT_TYPE),
578 DECL(AL_EFFECT_NULL),
579 DECL(AL_EFFECT_REVERB),
580 DECL(AL_EFFECT_EAXREVERB),
581 DECL(AL_EFFECT_CHORUS),
582 DECL(AL_EFFECT_DISTORTION),
583 DECL(AL_EFFECT_ECHO),
584 DECL(AL_EFFECT_FLANGER),
585 #if 0
586 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
587 DECL(AL_EFFECT_VOCAL_MORPHER),
588 DECL(AL_EFFECT_PITCH_SHIFTER),
589 #endif
590 DECL(AL_EFFECT_RING_MODULATOR),
591 #if 0
592 DECL(AL_EFFECT_AUTOWAH),
593 #endif
594 DECL(AL_EFFECT_COMPRESSOR),
595 DECL(AL_EFFECT_EQUALIZER),
596 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
597 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
599 DECL(AL_EAXREVERB_DENSITY),
600 DECL(AL_EAXREVERB_DIFFUSION),
601 DECL(AL_EAXREVERB_GAIN),
602 DECL(AL_EAXREVERB_GAINHF),
603 DECL(AL_EAXREVERB_GAINLF),
604 DECL(AL_EAXREVERB_DECAY_TIME),
605 DECL(AL_EAXREVERB_DECAY_HFRATIO),
606 DECL(AL_EAXREVERB_DECAY_LFRATIO),
607 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
608 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
609 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
610 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
611 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
612 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
613 DECL(AL_EAXREVERB_ECHO_TIME),
614 DECL(AL_EAXREVERB_ECHO_DEPTH),
615 DECL(AL_EAXREVERB_MODULATION_TIME),
616 DECL(AL_EAXREVERB_MODULATION_DEPTH),
617 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
618 DECL(AL_EAXREVERB_HFREFERENCE),
619 DECL(AL_EAXREVERB_LFREFERENCE),
620 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
621 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
623 DECL(AL_REVERB_DENSITY),
624 DECL(AL_REVERB_DIFFUSION),
625 DECL(AL_REVERB_GAIN),
626 DECL(AL_REVERB_GAINHF),
627 DECL(AL_REVERB_DECAY_TIME),
628 DECL(AL_REVERB_DECAY_HFRATIO),
629 DECL(AL_REVERB_REFLECTIONS_GAIN),
630 DECL(AL_REVERB_REFLECTIONS_DELAY),
631 DECL(AL_REVERB_LATE_REVERB_GAIN),
632 DECL(AL_REVERB_LATE_REVERB_DELAY),
633 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
634 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
635 DECL(AL_REVERB_DECAY_HFLIMIT),
637 DECL(AL_CHORUS_WAVEFORM),
638 DECL(AL_CHORUS_PHASE),
639 DECL(AL_CHORUS_RATE),
640 DECL(AL_CHORUS_DEPTH),
641 DECL(AL_CHORUS_FEEDBACK),
642 DECL(AL_CHORUS_DELAY),
644 DECL(AL_DISTORTION_EDGE),
645 DECL(AL_DISTORTION_GAIN),
646 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
647 DECL(AL_DISTORTION_EQCENTER),
648 DECL(AL_DISTORTION_EQBANDWIDTH),
650 DECL(AL_ECHO_DELAY),
651 DECL(AL_ECHO_LRDELAY),
652 DECL(AL_ECHO_DAMPING),
653 DECL(AL_ECHO_FEEDBACK),
654 DECL(AL_ECHO_SPREAD),
656 DECL(AL_FLANGER_WAVEFORM),
657 DECL(AL_FLANGER_PHASE),
658 DECL(AL_FLANGER_RATE),
659 DECL(AL_FLANGER_DEPTH),
660 DECL(AL_FLANGER_FEEDBACK),
661 DECL(AL_FLANGER_DELAY),
663 DECL(AL_RING_MODULATOR_FREQUENCY),
664 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
665 DECL(AL_RING_MODULATOR_WAVEFORM),
667 #if 0
668 DECL(AL_AUTOWAH_ATTACK_TIME),
669 DECL(AL_AUTOWAH_PEAK_GAIN),
670 DECL(AL_AUTOWAH_RELEASE_TIME),
671 DECL(AL_AUTOWAH_RESONANCE),
672 #endif
674 DECL(AL_COMPRESSOR_ONOFF),
676 DECL(AL_EQUALIZER_LOW_GAIN),
677 DECL(AL_EQUALIZER_LOW_CUTOFF),
678 DECL(AL_EQUALIZER_MID1_GAIN),
679 DECL(AL_EQUALIZER_MID1_CENTER),
680 DECL(AL_EQUALIZER_MID1_WIDTH),
681 DECL(AL_EQUALIZER_MID2_GAIN),
682 DECL(AL_EQUALIZER_MID2_CENTER),
683 DECL(AL_EQUALIZER_MID2_WIDTH),
684 DECL(AL_EQUALIZER_HIGH_GAIN),
685 DECL(AL_EQUALIZER_HIGH_CUTOFF),
687 DECL(AL_DEDICATED_GAIN),
689 { NULL, (ALCenum)0 }
691 #undef DECL
693 static const ALCchar alcNoError[] = "No Error";
694 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
695 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
696 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
697 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
698 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
701 /************************************************
702 * Global variables
703 ************************************************/
705 /* Enumerated device names */
706 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
708 static al_string alcAllDevicesList;
709 static al_string alcCaptureDeviceList;
711 /* Default is always the first in the list */
712 static ALCchar *alcDefaultAllDevicesSpecifier;
713 static ALCchar *alcCaptureDefaultDeviceSpecifier;
715 /* Default context extensions */
716 static const ALchar alExtList[] =
717 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
718 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
719 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
720 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples "
721 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
722 "AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency "
723 "AL_SOFT_source_length";
725 static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
727 /* Thread-local current context */
728 static altss_t LocalContext;
729 /* Process-wide current context */
730 static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL);
732 /* Mixing thread piority level */
733 ALint RTPrioLevel;
735 FILE *LogFile;
736 #ifdef _DEBUG
737 enum LogLevel LogLevel = LogWarning;
738 #else
739 enum LogLevel LogLevel = LogError;
740 #endif
742 /* Flag to trap ALC device errors */
743 static ALCboolean TrapALCError = ALC_FALSE;
745 /* One-time configuration init control */
746 static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT;
748 /* Default effect that applies to sources that don't have an effect on send 0 */
749 static ALeffect DefaultEffect;
752 /************************************************
753 * ALC information
754 ************************************************/
755 static const ALCchar alcNoDeviceExtList[] =
756 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
757 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
758 static const ALCchar alcExtensionList[] =
759 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
760 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
761 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
762 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
763 static const ALCint alcMajorVersion = 1;
764 static const ALCint alcMinorVersion = 1;
766 static const ALCint alcEFXMajorVersion = 1;
767 static const ALCint alcEFXMinorVersion = 0;
770 /************************************************
771 * Device lists
772 ************************************************/
773 static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL);
775 static almtx_t ListLock;
776 static inline void LockLists(void)
778 int lockret = almtx_lock(&ListLock);
779 assert(lockret == althrd_success);
781 static inline void UnlockLists(void)
783 int unlockret = almtx_unlock(&ListLock);
784 assert(unlockret == althrd_success);
787 /************************************************
788 * Library initialization
789 ************************************************/
790 #if defined(_WIN32)
791 static void alc_init(void);
792 static void alc_deinit(void);
793 static void alc_deinit_safe(void);
795 #ifndef AL_LIBTYPE_STATIC
796 BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
798 switch(reason)
800 case DLL_PROCESS_ATTACH:
801 /* Pin the DLL so we won't get unloaded until the process terminates */
802 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 (WCHAR*)hModule, &hModule);
804 alc_init();
805 break;
807 case DLL_THREAD_DETACH:
808 break;
810 case DLL_PROCESS_DETACH:
811 if(!lpReserved)
812 alc_deinit();
813 else
814 alc_deinit_safe();
815 break;
817 return TRUE;
819 #elif defined(_MSC_VER)
820 #pragma section(".CRT$XCU",read)
821 static void alc_constructor(void);
822 static void alc_destructor(void);
823 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
825 static void alc_constructor(void)
827 atexit(alc_destructor);
828 alc_init();
831 static void alc_destructor(void)
833 alc_deinit();
835 #elif defined(HAVE_GCC_DESTRUCTOR)
836 static void alc_init(void) __attribute__((constructor));
837 static void alc_deinit(void) __attribute__((destructor));
838 #else
839 #error "No static initialization available on this platform!"
840 #endif
842 #elif defined(HAVE_GCC_DESTRUCTOR)
844 static void alc_init(void) __attribute__((constructor));
845 static void alc_deinit(void) __attribute__((destructor));
847 #else
848 #error "No global initialization available on this platform!"
849 #endif
851 static void ReleaseThreadCtx(void *ptr);
852 static void alc_init(void)
854 const char *str;
855 int ret;
857 LogFile = stderr;
859 AL_STRING_INIT(alcAllDevicesList);
860 AL_STRING_INIT(alcCaptureDeviceList);
862 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
863 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
864 ConeScale *= 0.5f;
866 str = getenv("__ALSOFT_REVERSE_Z");
867 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
868 ZScale *= -1.0f;
870 ret = altss_create(&LocalContext, ReleaseThreadCtx);
871 assert(ret == althrd_success);
873 ret = almtx_init(&ListLock, almtx_recursive);
874 assert(ret == althrd_success);
876 ThunkInit();
879 static void alc_initconfig(void)
881 const char *devs, *str;
882 ALuint capfilter;
883 float valf;
884 int i, n;
886 str = getenv("ALSOFT_LOGLEVEL");
887 if(str)
889 long lvl = strtol(str, NULL, 0);
890 if(lvl >= NoLog && lvl <= LogRef)
891 LogLevel = lvl;
894 str = getenv("ALSOFT_LOGFILE");
895 if(str && str[0])
897 FILE *logfile = al_fopen(str, "wt");
898 if(logfile) LogFile = logfile;
899 else ERR("Failed to open log file '%s'\n", str);
903 char buf[1024] = "";
904 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
905 for(i = 1;BackendList[i].name;i++)
906 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
907 TRACE("Supported backends: %s\n", buf);
909 ReadALConfig();
911 capfilter = 0;
912 #if defined(HAVE_SSE4_1)
913 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
914 #elif defined(HAVE_SSE2)
915 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
916 #elif defined(HAVE_SSE)
917 capfilter |= CPU_CAP_SSE;
918 #endif
919 #ifdef HAVE_NEON
920 capfilter |= CPU_CAP_NEON;
921 #endif
922 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
924 if(strcasecmp(str, "all") == 0)
925 capfilter = 0;
926 else
928 size_t len;
929 const char *next = str;
931 do {
932 str = next;
933 while(isspace(str[0]))
934 str++;
935 next = strchr(str, ',');
937 if(!str[0] || str[0] == ',')
938 continue;
940 len = (next ? ((size_t)(next-str)) : strlen(str));
941 while(len > 0 && isspace(str[len-1]))
942 len--;
943 if(len == 3 && strncasecmp(str, "sse", len) == 0)
944 capfilter &= ~CPU_CAP_SSE;
945 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
946 capfilter &= ~CPU_CAP_SSE2;
947 else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0)
948 capfilter &= ~CPU_CAP_SSE4_1;
949 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
950 capfilter &= ~CPU_CAP_NEON;
951 else
952 WARN("Invalid CPU extension \"%s\"\n", str);
953 } while(next++);
956 FillCPUCaps(capfilter);
958 #ifdef _WIN32
959 RTPrioLevel = 1;
960 #else
961 RTPrioLevel = 0;
962 #endif
963 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
965 if(ConfigValueStr(NULL, "resampler", &str))
967 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
968 DefaultResampler = PointResampler;
969 else if(strcasecmp(str, "linear") == 0)
970 DefaultResampler = LinearResampler;
971 else if(strcasecmp(str, "cubic") == 0)
972 DefaultResampler = CubicResampler;
973 else
975 char *end;
977 n = strtol(str, &end, 0);
978 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
979 DefaultResampler = n;
980 else
981 WARN("Invalid resampler: %s\n", str);
985 str = getenv("ALSOFT_TRAP_ERROR");
986 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALError = AL_TRUE;
989 TrapALCError = AL_TRUE;
991 else
993 str = getenv("ALSOFT_TRAP_AL_ERROR");
994 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
995 TrapALError = AL_TRUE;
996 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
998 str = getenv("ALSOFT_TRAP_ALC_ERROR");
999 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1000 TrapALCError = ALC_TRUE;
1001 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1004 if(ConfigValueFloat("reverb", "boost", &valf))
1005 ReverbBoost *= powf(10.0f, valf / 20.0f);
1007 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1009 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1010 ConfigValueStr(NULL, "drivers", &devs))
1012 int n;
1013 size_t len;
1014 const char *next = devs;
1015 int endlist, delitem;
1017 i = 0;
1018 do {
1019 devs = next;
1020 while(isspace(devs[0]))
1021 devs++;
1022 next = strchr(devs, ',');
1024 delitem = (devs[0] == '-');
1025 if(devs[0] == '-') devs++;
1027 if(!devs[0] || devs[0] == ',')
1029 endlist = 0;
1030 continue;
1032 endlist = 1;
1034 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1035 while(len > 0 && isspace(devs[len-1]))
1036 len--;
1037 for(n = i;BackendList[n].name;n++)
1039 if(len == strlen(BackendList[n].name) &&
1040 strncmp(BackendList[n].name, devs, len) == 0)
1042 if(delitem)
1044 do {
1045 BackendList[n] = BackendList[n+1];
1046 ++n;
1047 } while(BackendList[n].name);
1049 else
1051 struct BackendInfo Bkp = BackendList[n];
1052 while(n > i)
1054 BackendList[n] = BackendList[n-1];
1055 --n;
1057 BackendList[n] = Bkp;
1059 i++;
1061 break;
1064 } while(next++);
1066 if(endlist)
1068 BackendList[i].name = NULL;
1069 BackendList[i].getFactory = NULL;
1070 BackendList[i].Init = NULL;
1071 BackendList[i].Deinit = NULL;
1072 BackendList[i].Probe = NULL;
1076 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1078 if(BackendList[i].getFactory)
1080 ALCbackendFactory *factory = BackendList[i].getFactory();
1081 if(!V0(factory,init)())
1083 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1084 continue;
1087 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1088 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1090 PlaybackBackend = BackendList[i];
1091 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1093 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1095 CaptureBackend = BackendList[i];
1096 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1099 continue;
1102 if(!BackendList[i].Init(&BackendList[i].Funcs))
1104 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1105 continue;
1108 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1109 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1111 PlaybackBackend = BackendList[i];
1112 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1114 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1116 CaptureBackend = BackendList[i];
1117 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1121 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1122 V0(factory,init)();
1125 if(ConfigValueStr(NULL, "excludefx", &str))
1127 size_t len;
1128 const char *next = str;
1130 do {
1131 str = next;
1132 next = strchr(str, ',');
1134 if(!str[0] || next == str)
1135 continue;
1137 len = (next ? ((size_t)(next-str)) : strlen(str));
1138 for(n = 0;EffectList[n].name;n++)
1140 if(len == strlen(EffectList[n].name) &&
1141 strncmp(EffectList[n].name, str, len) == 0)
1142 DisabledEffects[EffectList[n].type] = AL_TRUE;
1144 } while(next++);
1147 InitEffectFactoryMap();
1149 InitEffect(&DefaultEffect);
1150 str = getenv("ALSOFT_DEFAULT_REVERB");
1151 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1152 LoadReverbPreset(str, &DefaultEffect);
1154 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1157 /************************************************
1158 * Library deinitialization
1159 ************************************************/
1160 static void alc_cleanup(void)
1162 ALCdevice *dev;
1164 AL_STRING_DEINIT(alcAllDevicesList);
1165 AL_STRING_DEINIT(alcCaptureDeviceList);
1167 free(alcDefaultAllDevicesSpecifier);
1168 alcDefaultAllDevicesSpecifier = NULL;
1169 free(alcCaptureDefaultDeviceSpecifier);
1170 alcCaptureDefaultDeviceSpecifier = NULL;
1172 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1174 ALCuint num = 0;
1175 do {
1176 num++;
1177 } while((dev=dev->next) != NULL);
1178 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1181 DeinitEffectFactoryMap();
1184 static void alc_deinit_safe(void)
1186 alc_cleanup();
1188 FreeHrtfs();
1189 FreeALConfig();
1191 ThunkExit();
1192 almtx_destroy(&ListLock);
1193 altss_delete(LocalContext);
1195 if(LogFile != stderr)
1196 fclose(LogFile);
1197 LogFile = NULL;
1200 static void alc_deinit(void)
1202 int i;
1204 alc_cleanup();
1206 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1207 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1209 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1211 if(!BackendList[i].getFactory)
1212 BackendList[i].Deinit();
1213 else
1215 ALCbackendFactory *factory = BackendList[i].getFactory();
1216 V0(factory,deinit)();
1220 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1221 V0(factory,deinit)();
1224 alc_deinit_safe();
1228 /************************************************
1229 * Device enumeration
1230 ************************************************/
1231 static void ProbeDevices(al_string *list, enum DevProbe type)
1233 DO_INITCONFIG();
1235 LockLists();
1236 al_string_clear(list);
1238 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1240 if(!PlaybackBackend.getFactory)
1241 PlaybackBackend.Probe(type);
1242 else
1244 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1245 V(factory,probe)(type);
1248 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1250 if(!CaptureBackend.getFactory)
1251 CaptureBackend.Probe(type);
1252 else
1254 ALCbackendFactory *factory = CaptureBackend.getFactory();
1255 V(factory,probe)(type);
1258 UnlockLists();
1260 static void ProbeAllDevicesList(void)
1261 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1262 static void ProbeCaptureDeviceList(void)
1263 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1265 static void AppendDevice(const ALCchar *name, al_string *devnames)
1267 size_t len = strlen(name);
1268 if(len > 0)
1270 al_string_append_range(devnames, name, name+len);
1271 al_string_append_char(devnames, '\0');
1274 void AppendAllDevicesList(const ALCchar *name)
1275 { AppendDevice(name, &alcAllDevicesList); }
1276 void AppendCaptureDeviceList(const ALCchar *name)
1277 { AppendDevice(name, &alcCaptureDeviceList); }
1280 /************************************************
1281 * Device format information
1282 ************************************************/
1283 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1285 switch(type)
1287 case DevFmtByte: return "Signed Byte";
1288 case DevFmtUByte: return "Unsigned Byte";
1289 case DevFmtShort: return "Signed Short";
1290 case DevFmtUShort: return "Unsigned Short";
1291 case DevFmtInt: return "Signed Int";
1292 case DevFmtUInt: return "Unsigned Int";
1293 case DevFmtFloat: return "Float";
1295 return "(unknown type)";
1297 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1299 switch(chans)
1301 case DevFmtMono: return "Mono";
1302 case DevFmtStereo: return "Stereo";
1303 case DevFmtQuad: return "Quadraphonic";
1304 case DevFmtX51: return "5.1 Surround";
1305 case DevFmtX51Side: return "5.1 Side";
1306 case DevFmtX61: return "6.1 Surround";
1307 case DevFmtX71: return "7.1 Surround";
1309 return "(unknown channels)";
1312 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1313 ALuint BytesFromDevFmt(enum DevFmtType type)
1315 switch(type)
1317 case DevFmtByte: return sizeof(ALbyte);
1318 case DevFmtUByte: return sizeof(ALubyte);
1319 case DevFmtShort: return sizeof(ALshort);
1320 case DevFmtUShort: return sizeof(ALushort);
1321 case DevFmtInt: return sizeof(ALint);
1322 case DevFmtUInt: return sizeof(ALuint);
1323 case DevFmtFloat: return sizeof(ALfloat);
1325 return 0;
1327 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1329 switch(chans)
1331 case DevFmtMono: return 1;
1332 case DevFmtStereo: return 2;
1333 case DevFmtQuad: return 4;
1334 case DevFmtX51: return 6;
1335 case DevFmtX51Side: return 6;
1336 case DevFmtX61: return 7;
1337 case DevFmtX71: return 8;
1339 return 0;
1342 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1343 enum DevFmtChannels *chans, enum DevFmtType *type)
1345 static const struct {
1346 ALenum format;
1347 enum DevFmtChannels channels;
1348 enum DevFmtType type;
1349 } list[] = {
1350 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1351 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1352 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1354 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1355 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1356 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1358 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1359 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1360 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1362 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1363 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1364 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1366 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1367 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1368 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1370 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1371 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1372 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1374 ALuint i;
1376 for(i = 0;i < COUNTOF(list);i++)
1378 if(list[i].format == format)
1380 *chans = list[i].channels;
1381 *type = list[i].type;
1382 return AL_TRUE;
1386 return AL_FALSE;
1389 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1391 switch(type)
1393 case ALC_BYTE_SOFT:
1394 case ALC_UNSIGNED_BYTE_SOFT:
1395 case ALC_SHORT_SOFT:
1396 case ALC_UNSIGNED_SHORT_SOFT:
1397 case ALC_INT_SOFT:
1398 case ALC_UNSIGNED_INT_SOFT:
1399 case ALC_FLOAT_SOFT:
1400 return ALC_TRUE;
1402 return ALC_FALSE;
1405 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1407 switch(channels)
1409 case ALC_MONO_SOFT:
1410 case ALC_STEREO_SOFT:
1411 case ALC_QUAD_SOFT:
1412 case ALC_5POINT1_SOFT:
1413 case ALC_6POINT1_SOFT:
1414 case ALC_7POINT1_SOFT:
1415 return ALC_TRUE;
1417 return ALC_FALSE;
1421 /************************************************
1422 * Miscellaneous ALC helpers
1423 ************************************************/
1424 extern inline void LockContext(ALCcontext *context);
1425 extern inline void UnlockContext(ALCcontext *context);
1427 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1429 return V0(device->Backend,getLatency)();
1432 void ALCdevice_Lock(ALCdevice *device)
1434 V0(device->Backend,lock)();
1437 void ALCdevice_Unlock(ALCdevice *device)
1439 V0(device->Backend,unlock)();
1443 /* SetDefaultWFXChannelOrder
1445 * Sets the default channel order used by WaveFormatEx.
1447 void SetDefaultWFXChannelOrder(ALCdevice *device)
1449 ALuint i;
1451 for(i = 0;i < MaxChannels;i++)
1452 device->ChannelName[i] = InvalidChannel;
1454 switch(device->FmtChans)
1456 case DevFmtMono: device->ChannelName[0] = FrontCenter;
1457 break;
1458 case DevFmtStereo: device->ChannelName[0] = FrontLeft;
1459 device->ChannelName[1] = FrontRight;
1460 break;
1461 case DevFmtQuad: device->ChannelName[0] = FrontLeft;
1462 device->ChannelName[1] = FrontRight;
1463 device->ChannelName[2] = BackLeft;
1464 device->ChannelName[3] = BackRight;
1465 break;
1466 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1467 device->ChannelName[1] = FrontRight;
1468 device->ChannelName[2] = FrontCenter;
1469 device->ChannelName[3] = LFE;
1470 device->ChannelName[4] = BackLeft;
1471 device->ChannelName[5] = BackRight;
1472 break;
1473 case DevFmtX51Side: device->ChannelName[0] = FrontLeft;
1474 device->ChannelName[1] = FrontRight;
1475 device->ChannelName[2] = FrontCenter;
1476 device->ChannelName[3] = LFE;
1477 device->ChannelName[4] = SideLeft;
1478 device->ChannelName[5] = SideRight;
1479 break;
1480 case DevFmtX61: device->ChannelName[0] = FrontLeft;
1481 device->ChannelName[1] = FrontRight;
1482 device->ChannelName[2] = FrontCenter;
1483 device->ChannelName[3] = LFE;
1484 device->ChannelName[4] = BackCenter;
1485 device->ChannelName[5] = SideLeft;
1486 device->ChannelName[6] = SideRight;
1487 break;
1488 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1489 device->ChannelName[1] = FrontRight;
1490 device->ChannelName[2] = FrontCenter;
1491 device->ChannelName[3] = LFE;
1492 device->ChannelName[4] = BackLeft;
1493 device->ChannelName[5] = BackRight;
1494 device->ChannelName[6] = SideLeft;
1495 device->ChannelName[7] = SideRight;
1496 break;
1500 /* SetDefaultChannelOrder
1502 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1504 void SetDefaultChannelOrder(ALCdevice *device)
1506 ALuint i;
1508 for(i = 0;i < MaxChannels;i++)
1509 device->ChannelName[i] = InvalidChannel;
1511 switch(device->FmtChans)
1513 case DevFmtX51: device->ChannelName[0] = FrontLeft;
1514 device->ChannelName[1] = FrontRight;
1515 device->ChannelName[2] = BackLeft;
1516 device->ChannelName[3] = BackRight;
1517 device->ChannelName[4] = FrontCenter;
1518 device->ChannelName[5] = LFE;
1519 return;
1520 case DevFmtX71: device->ChannelName[0] = FrontLeft;
1521 device->ChannelName[1] = FrontRight;
1522 device->ChannelName[2] = BackLeft;
1523 device->ChannelName[3] = BackRight;
1524 device->ChannelName[4] = FrontCenter;
1525 device->ChannelName[5] = LFE;
1526 device->ChannelName[6] = SideLeft;
1527 device->ChannelName[7] = SideRight;
1528 return;
1530 /* Same as WFX order */
1531 case DevFmtMono:
1532 case DevFmtStereo:
1533 case DevFmtQuad:
1534 case DevFmtX51Side:
1535 case DevFmtX61:
1536 SetDefaultWFXChannelOrder(device);
1537 break;
1542 /* alcSetError
1544 * Stores the latest ALC device error
1546 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1548 if(TrapALCError)
1550 #ifdef _WIN32
1551 /* DebugBreak() will cause an exception if there is no debugger */
1552 if(IsDebuggerPresent())
1553 DebugBreak();
1554 #elif defined(SIGTRAP)
1555 raise(SIGTRAP);
1556 #endif
1559 if(device)
1560 ATOMIC_STORE(&device->LastError, errorCode);
1561 else
1562 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1566 /* UpdateClockBase
1568 * Updates the device's base clock time with however many samples have been
1569 * done. This is used so frequency changes on the device don't cause the time
1570 * to jump forward or back.
1572 static inline void UpdateClockBase(ALCdevice *device)
1574 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1575 device->SamplesDone = 0;
1578 /* UpdateDeviceParams
1580 * Updates device parameters according to the attribute list (caller is
1581 * responsible for holding the list lock).
1583 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1585 ALCcontext *context;
1586 enum DevFmtChannels oldChans;
1587 enum DevFmtType oldType;
1588 ALCuint oldFreq;
1589 FPUCtl oldMode;
1591 // Check for attributes
1592 if(device->Type == Loopback)
1594 enum {
1595 GotFreq = 1<<0,
1596 GotChans = 1<<1,
1597 GotType = 1<<2,
1598 GotAll = GotFreq|GotChans|GotType
1600 ALCuint freq, numMono, numStereo, numSends, flags;
1601 enum DevFmtChannels schans;
1602 enum DevFmtType stype;
1603 ALCuint attrIdx = 0;
1604 ALCint gotFmt = 0;
1606 if(!attrList)
1608 WARN("Missing attributes for loopback device\n");
1609 return ALC_INVALID_VALUE;
1612 numMono = device->NumMonoSources;
1613 numStereo = device->NumStereoSources;
1614 numSends = device->NumAuxSends;
1615 schans = device->FmtChans;
1616 stype = device->FmtType;
1617 freq = device->Frequency;
1618 flags = device->Flags;
1620 while(attrList[attrIdx])
1622 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1624 ALCint val = attrList[attrIdx + 1];
1625 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1626 return ALC_INVALID_VALUE;
1627 schans = val;
1628 gotFmt |= GotChans;
1631 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1633 ALCint val = attrList[attrIdx + 1];
1634 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1635 return ALC_INVALID_VALUE;
1636 stype = val;
1637 gotFmt |= GotType;
1640 if(attrList[attrIdx] == ALC_FREQUENCY)
1642 freq = attrList[attrIdx + 1];
1643 if(freq < MIN_OUTPUT_RATE)
1644 return ALC_INVALID_VALUE;
1645 gotFmt |= GotFreq;
1648 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1650 numStereo = attrList[attrIdx + 1];
1651 if(numStereo > device->MaxNoOfSources)
1652 numStereo = device->MaxNoOfSources;
1654 numMono = device->MaxNoOfSources - numStereo;
1657 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1658 numSends = attrList[attrIdx + 1];
1660 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1662 if(attrList[attrIdx + 1] != ALC_FALSE)
1663 flags |= DEVICE_HRTF_REQUEST;
1664 else
1665 flags &= ~DEVICE_HRTF_REQUEST;
1668 attrIdx += 2;
1671 if(gotFmt != GotAll)
1673 WARN("Missing format for loopback device\n");
1674 return ALC_INVALID_VALUE;
1677 ConfigValueUInt(NULL, "sends", &numSends);
1678 numSends = minu(MAX_SENDS, numSends);
1680 if((device->Flags&DEVICE_RUNNING))
1681 V0(device->Backend,stop)();
1682 device->Flags = (flags & ~DEVICE_RUNNING);
1684 UpdateClockBase(device);
1686 device->Frequency = freq;
1687 device->FmtChans = schans;
1688 device->FmtType = stype;
1689 device->NumMonoSources = numMono;
1690 device->NumStereoSources = numStereo;
1691 device->NumAuxSends = numSends;
1693 else if(attrList && attrList[0])
1695 ALCuint freq, numMono, numStereo, numSends;
1696 ALCuint attrIdx = 0;
1698 /* If a context is already running on the device, stop playback so the
1699 * device attributes can be updated. */
1700 if((device->Flags&DEVICE_RUNNING))
1701 V0(device->Backend,stop)();
1702 device->Flags &= ~DEVICE_RUNNING;
1704 freq = device->Frequency;
1705 numMono = device->NumMonoSources;
1706 numStereo = device->NumStereoSources;
1707 numSends = device->NumAuxSends;
1709 while(attrList[attrIdx])
1711 if(attrList[attrIdx] == ALC_FREQUENCY)
1713 freq = attrList[attrIdx + 1];
1714 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1717 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1719 numStereo = attrList[attrIdx + 1];
1720 if(numStereo > device->MaxNoOfSources)
1721 numStereo = device->MaxNoOfSources;
1723 numMono = device->MaxNoOfSources - numStereo;
1726 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1727 numSends = attrList[attrIdx + 1];
1729 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1731 if(attrList[attrIdx + 1] != ALC_FALSE)
1732 device->Flags |= DEVICE_HRTF_REQUEST;
1733 else
1734 device->Flags &= ~DEVICE_HRTF_REQUEST;
1737 attrIdx += 2;
1740 ConfigValueUInt(NULL, "frequency", &freq);
1741 freq = maxu(freq, MIN_OUTPUT_RATE);
1743 ConfigValueUInt(NULL, "sends", &numSends);
1744 numSends = minu(MAX_SENDS, numSends);
1746 UpdateClockBase(device);
1748 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1749 device->Frequency;
1750 /* SSE and Neon do best with the update size being a multiple of 4 */
1751 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1752 device->UpdateSize = (device->UpdateSize+3)&~3;
1754 device->Frequency = freq;
1755 device->NumMonoSources = numMono;
1756 device->NumStereoSources = numStereo;
1757 device->NumAuxSends = numSends;
1760 if((device->Flags&DEVICE_RUNNING))
1761 return ALC_NO_ERROR;
1763 UpdateClockBase(device);
1765 if(device->Type != Loopback)
1767 bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST);
1768 if(GetConfigValueBool(NULL, "hrtf", usehrtf))
1769 device->Flags |= DEVICE_HRTF_REQUEST;
1770 else
1771 device->Flags &= ~DEVICE_HRTF_REQUEST;
1773 if((device->Flags&DEVICE_HRTF_REQUEST))
1775 enum DevFmtChannels chans = device->FmtChans;
1776 ALCuint freq = device->Frequency;
1777 if(FindHrtfFormat(&chans, &freq))
1779 if(device->Type != Loopback)
1781 device->Frequency = freq;
1782 device->FmtChans = chans;
1783 device->Flags |= DEVICE_CHANNELS_REQUEST |
1784 DEVICE_FREQUENCY_REQUEST;
1786 else if(device->Frequency != freq || device->FmtChans != chans)
1788 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1789 DevFmtChannelsString(device->FmtChans), device->Frequency);
1790 device->Flags &= ~DEVICE_HRTF_REQUEST;
1795 oldFreq = device->Frequency;
1796 oldChans = device->FmtChans;
1797 oldType = device->FmtType;
1799 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1800 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1801 DevFmtChannelsString(device->FmtChans),
1802 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1803 DevFmtTypeString(device->FmtType),
1804 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1805 device->Frequency,
1806 device->UpdateSize, device->NumUpdates);
1808 if(V0(device->Backend,reset)() == ALC_FALSE)
1809 return ALC_INVALID_DEVICE;
1811 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1813 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1814 DevFmtChannelsString(device->FmtChans));
1815 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1817 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1819 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1820 DevFmtTypeString(device->FmtType));
1821 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1823 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1825 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1826 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1829 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1830 DevFmtChannelsString(device->FmtChans),
1831 DevFmtTypeString(device->FmtType), device->Frequency,
1832 device->UpdateSize, device->NumUpdates);
1834 aluInitPanning(device);
1836 V(device->Synth,update)(device);
1838 device->Hrtf = NULL;
1839 if((device->Flags&DEVICE_HRTF_REQUEST))
1841 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1842 if(!device->Hrtf)
1843 device->Flags &= ~DEVICE_HRTF_REQUEST;
1845 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1847 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1849 if(!device->Bs2b)
1851 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1852 bs2b_clear(device->Bs2b);
1854 bs2b_set_srate(device->Bs2b, device->Frequency);
1855 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1856 TRACE("BS2B level %d\n", device->Bs2bLevel);
1858 else
1860 free(device->Bs2b);
1861 device->Bs2b = NULL;
1862 TRACE("BS2B disabled\n");
1865 device->Flags &= ~DEVICE_WIDE_STEREO;
1866 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1867 device->Flags |= DEVICE_WIDE_STEREO;
1869 if(!device->Hrtf && (device->UpdateSize&3))
1871 if((CPUCapFlags&CPU_CAP_SSE))
1872 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1873 if((CPUCapFlags&CPU_CAP_NEON))
1874 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1877 SetMixerFPUMode(&oldMode);
1878 ALCdevice_Lock(device);
1879 context = ATOMIC_LOAD(&device->ContextList);
1880 while(context)
1882 ALsizei pos;
1884 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
1885 LockUIntMapRead(&context->EffectSlotMap);
1886 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1888 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1890 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1892 UnlockUIntMapRead(&context->EffectSlotMap);
1893 ALCdevice_Unlock(device);
1894 RestoreFPUMode(&oldMode);
1895 return ALC_INVALID_DEVICE;
1897 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1898 V(slot->EffectState,update)(device, slot);
1900 UnlockUIntMapRead(&context->EffectSlotMap);
1902 LockUIntMapRead(&context->SourceMap);
1903 for(pos = 0;pos < context->SourceMap.size;pos++)
1905 ALsource *source = context->SourceMap.array[pos].value;
1906 ALuint s = device->NumAuxSends;
1907 while(s < MAX_SENDS)
1909 if(source->Send[s].Slot)
1910 DecrementRef(&source->Send[s].Slot->ref);
1911 source->Send[s].Slot = NULL;
1912 source->Send[s].Gain = 1.0f;
1913 source->Send[s].GainHF = 1.0f;
1914 s++;
1916 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
1918 UnlockUIntMapRead(&context->SourceMap);
1920 for(pos = 0;pos < context->VoiceCount;pos++)
1922 ALvoice *voice = &context->Voices[pos];
1923 ALsource *source = voice->Source;
1924 ALuint s = device->NumAuxSends;
1926 while(s < MAX_SENDS)
1928 voice->Send[s].Moving = AL_FALSE;
1929 voice->Send[s].Counter = 0;
1930 s++;
1933 if(source)
1935 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
1936 voice->Update(voice, source, context);
1940 context = context->next;
1942 if(device->DefaultSlot)
1944 ALeffectslot *slot = device->DefaultSlot;
1946 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1948 ALCdevice_Unlock(device);
1949 RestoreFPUMode(&oldMode);
1950 return ALC_INVALID_DEVICE;
1952 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
1953 V(slot->EffectState,update)(device, slot);
1955 ALCdevice_Unlock(device);
1956 RestoreFPUMode(&oldMode);
1958 if(!(device->Flags&DEVICE_PAUSED))
1960 if(V0(device->Backend,start)() == ALC_FALSE)
1961 return ALC_INVALID_DEVICE;
1962 device->Flags |= DEVICE_RUNNING;
1965 return ALC_NO_ERROR;
1968 /* FreeDevice
1970 * Frees the device structure, and destroys any objects the app failed to
1971 * delete. Called once there's no more references on the device.
1973 static ALCvoid FreeDevice(ALCdevice *device)
1975 TRACE("%p\n", device);
1977 V0(device->Backend,close)();
1978 DELETE_OBJ(device->Backend);
1979 device->Backend = NULL;
1981 DELETE_OBJ(device->Synth);
1982 device->Synth = NULL;
1984 if(device->DefaultSlot)
1986 ALeffectState *state = device->DefaultSlot->EffectState;
1987 device->DefaultSlot = NULL;
1988 DELETE_OBJ(state);
1991 if(device->DefaultSfont)
1992 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1993 device->DefaultSfont = NULL;
1995 if(device->BufferMap.size > 0)
1997 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
1998 ReleaseALBuffers(device);
2000 ResetUIntMap(&device->BufferMap);
2002 if(device->EffectMap.size > 0)
2004 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2005 ReleaseALEffects(device);
2007 ResetUIntMap(&device->EffectMap);
2009 if(device->FilterMap.size > 0)
2011 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2012 ReleaseALFilters(device);
2014 ResetUIntMap(&device->FilterMap);
2016 if(device->SfontMap.size > 0)
2018 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2019 ReleaseALSoundfonts(device);
2021 ResetUIntMap(&device->SfontMap);
2023 if(device->PresetMap.size > 0)
2025 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2026 ReleaseALPresets(device);
2028 ResetUIntMap(&device->PresetMap);
2030 if(device->FontsoundMap.size > 0)
2032 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2033 ReleaseALFontsounds(device);
2035 ResetUIntMap(&device->FontsoundMap);
2037 free(device->Bs2b);
2038 device->Bs2b = NULL;
2040 AL_STRING_DEINIT(device->DeviceName);
2042 al_free(device);
2046 void ALCdevice_IncRef(ALCdevice *device)
2048 uint ref;
2049 ref = IncrementRef(&device->ref);
2050 TRACEREF("%p increasing refcount to %u\n", device, ref);
2053 void ALCdevice_DecRef(ALCdevice *device)
2055 uint ref;
2056 ref = DecrementRef(&device->ref);
2057 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2058 if(ref == 0) FreeDevice(device);
2061 /* VerifyDevice
2063 * Checks if the device handle is valid, and increments its ref count if so.
2065 static ALCdevice *VerifyDevice(ALCdevice *device)
2067 ALCdevice *tmpDevice;
2069 if(!device)
2070 return NULL;
2072 LockLists();
2073 tmpDevice = ATOMIC_LOAD(&DeviceList);
2074 while(tmpDevice && tmpDevice != device)
2075 tmpDevice = tmpDevice->next;
2077 if(tmpDevice)
2078 ALCdevice_IncRef(tmpDevice);
2079 UnlockLists();
2080 return tmpDevice;
2084 /* InitContext
2086 * Initializes context fields
2088 static ALvoid InitContext(ALCcontext *Context)
2090 ALint i, j;
2092 //Initialise listener
2093 Context->Listener->Gain = 1.0f;
2094 Context->Listener->MetersPerUnit = 1.0f;
2095 Context->Listener->Position[0] = 0.0f;
2096 Context->Listener->Position[1] = 0.0f;
2097 Context->Listener->Position[2] = 0.0f;
2098 Context->Listener->Velocity[0] = 0.0f;
2099 Context->Listener->Velocity[1] = 0.0f;
2100 Context->Listener->Velocity[2] = 0.0f;
2101 Context->Listener->Forward[0] = 0.0f;
2102 Context->Listener->Forward[1] = 0.0f;
2103 Context->Listener->Forward[2] = -1.0f;
2104 Context->Listener->Up[0] = 0.0f;
2105 Context->Listener->Up[1] = 1.0f;
2106 Context->Listener->Up[2] = 0.0f;
2107 for(i = 0;i < 4;i++)
2109 for(j = 0;j < 4;j++)
2110 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2112 for(i = 0;i < 3;i++)
2113 Context->Listener->Params.Velocity[i] = 0.0f;
2115 //Validate Context
2116 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2117 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2118 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2119 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2121 //Set globals
2122 Context->DistanceModel = DefaultDistanceModel;
2123 Context->SourceDistanceModel = AL_FALSE;
2124 Context->DopplerFactor = 1.0f;
2125 Context->DopplerVelocity = 1.0f;
2126 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2127 Context->DeferUpdates = AL_FALSE;
2129 Context->ExtensionList = alExtList;
2133 /* FreeContext
2135 * Cleans up the context, and destroys any remaining objects the app failed to
2136 * delete. Called once there's no more references on the context.
2138 static void FreeContext(ALCcontext *context)
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 al_free(context->Voices);
2157 context->Voices = NULL;
2158 context->VoiceCount = 0;
2159 context->MaxVoices = 0;
2161 VECTOR_DEINIT(context->ActiveAuxSlots);
2163 ALCdevice_DecRef(context->Device);
2164 context->Device = NULL;
2166 //Invalidate context
2167 memset(context, 0, sizeof(ALCcontext));
2168 al_free(context);
2171 /* ReleaseContext
2173 * Removes the context reference from the given device and removes it from
2174 * being current on the running thread or globally.
2176 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2178 ALCcontext *nextctx;
2179 ALCcontext *origctx;
2181 if(altss_get(LocalContext) == context)
2183 WARN("%p released while current on thread\n", context);
2184 altss_set(LocalContext, NULL);
2185 ALCcontext_DecRef(context);
2188 origctx = context;
2189 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2190 ALCcontext_DecRef(context);
2192 ALCdevice_Lock(device);
2193 origctx = context;
2194 nextctx = context->next;
2195 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2197 ALCcontext *list;
2198 do {
2199 list = origctx;
2200 origctx = context;
2201 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
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 = ATOMIC_LOAD(&DeviceList);
2239 while(dev)
2241 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2242 while(ctx)
2244 if(ctx == context)
2246 ALCcontext_IncRef(ctx);
2247 UnlockLists();
2248 return ctx;
2250 ctx = 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 = ATOMIC_LOAD(&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 = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2300 ALCdevice_DecRef(device);
2302 else
2303 errorCode = ATOMIC_EXCHANGE(ALCenum, &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(alcCaptureDeviceList));
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 ATOMIC_STORE(&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 = al_calloc(16, 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->VoiceCount = 0;
2882 ALContext->MaxVoices = 256;
2883 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
2885 if(!ALContext || !ALContext->Voices)
2887 if(!ATOMIC_LOAD(&device->ContextList))
2889 V0(device->Backend,stop)();
2890 device->Flags &= ~DEVICE_RUNNING;
2892 UnlockLists();
2894 if(ALContext)
2896 al_free(ALContext->Voices);
2897 ALContext->Voices = NULL;
2899 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2901 al_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);
2915 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
2916 do {
2917 ALContext->next = head;
2918 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
2920 UnlockLists();
2922 ALCdevice_DecRef(device);
2924 TRACE("Created context %p\n", ALContext);
2925 return ALContext;
2928 /* alcDestroyContext
2930 * Remove a context from its device
2932 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2934 ALCdevice *Device;
2936 LockLists();
2937 /* alcGetContextsDevice sets an error for invalid contexts */
2938 Device = alcGetContextsDevice(context);
2939 if(Device)
2941 ReleaseContext(context, Device);
2942 if(!ATOMIC_LOAD(&Device->ContextList))
2944 V0(Device->Backend,stop)();
2945 Device->Flags &= ~DEVICE_RUNNING;
2948 UnlockLists();
2952 /* alcGetCurrentContext
2954 * Returns the currently active context on the calling thread
2956 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2958 ALCcontext *Context = altss_get(LocalContext);
2959 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
2960 return Context;
2963 /* alcGetThreadContext
2965 * Returns the currently active thread-local context
2967 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2969 return altss_get(LocalContext);
2973 /* alcMakeContextCurrent
2975 * Makes the given context the active process-wide context, and removes the
2976 * thread-local context for the calling thread.
2978 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2980 /* context must be valid or NULL */
2981 if(context && !(context=VerifyContext(context)))
2983 alcSetError(NULL, ALC_INVALID_CONTEXT);
2984 return ALC_FALSE;
2986 /* context's reference count is already incremented */
2987 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
2988 if(context) ALCcontext_DecRef(context);
2990 if((context=altss_get(LocalContext)) != NULL)
2992 altss_set(LocalContext, NULL);
2993 ALCcontext_DecRef(context);
2996 return ALC_TRUE;
2999 /* alcSetThreadContext
3001 * Makes the given context the active context for the current thread
3003 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3005 ALCcontext *old;
3007 /* context must be valid or NULL */
3008 if(context && !(context=VerifyContext(context)))
3010 alcSetError(NULL, ALC_INVALID_CONTEXT);
3011 return ALC_FALSE;
3013 /* context's reference count is already incremented */
3014 old = altss_get(LocalContext);
3015 altss_set(LocalContext, context);
3016 if(old) ALCcontext_DecRef(old);
3018 return ALC_TRUE;
3022 /* alcGetContextsDevice
3024 * Returns the device that a particular context is attached to
3026 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3028 ALCdevice *Device;
3030 if(!(Context=VerifyContext(Context)))
3032 alcSetError(NULL, ALC_INVALID_CONTEXT);
3033 return NULL;
3035 Device = Context->Device;
3036 ALCcontext_DecRef(Context);
3038 return Device;
3042 /* alcOpenDevice
3044 * Opens the named device.
3046 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3048 const ALCchar *fmt;
3049 ALCdevice *device;
3050 ALCenum err;
3052 DO_INITCONFIG();
3054 if(!PlaybackBackend.name)
3056 alcSetError(NULL, ALC_INVALID_VALUE);
3057 return NULL;
3060 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3061 deviceName = NULL;
3063 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3064 if(!device)
3066 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3067 return NULL;
3070 //Validate device
3071 InitRef(&device->ref, 1);
3072 device->Connected = ALC_TRUE;
3073 device->Type = Playback;
3074 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3076 device->Flags = 0;
3077 device->Bs2b = NULL;
3078 device->Bs2bLevel = 0;
3079 AL_STRING_INIT(device->DeviceName);
3081 ATOMIC_INIT(&device->ContextList, NULL);
3083 device->ClockBase = 0;
3084 device->SamplesDone = 0;
3086 device->MaxNoOfSources = 256;
3087 device->AuxiliaryEffectSlotMax = 4;
3088 device->NumAuxSends = MAX_SENDS;
3090 InitUIntMap(&device->BufferMap, ~0);
3091 InitUIntMap(&device->EffectMap, ~0);
3092 InitUIntMap(&device->FilterMap, ~0);
3093 InitUIntMap(&device->SfontMap, ~0);
3094 InitUIntMap(&device->PresetMap, ~0);
3095 InitUIntMap(&device->FontsoundMap, ~0);
3097 //Set output format
3098 device->FmtChans = DevFmtChannelsDefault;
3099 device->FmtType = DevFmtTypeDefault;
3100 device->Frequency = DEFAULT_OUTPUT_RATE;
3101 device->NumUpdates = 4;
3102 device->UpdateSize = 1024;
3104 if(!PlaybackBackend.getFactory)
3105 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3106 ALCbackend_Playback);
3107 else
3109 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3110 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3112 if(!device->Backend)
3114 al_free(device);
3115 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3116 return NULL;
3120 if(ConfigValueStr(NULL, "channels", &fmt))
3122 static const struct {
3123 const char name[16];
3124 enum DevFmtChannels chans;
3125 } chanlist[] = {
3126 { "mono", DevFmtMono },
3127 { "stereo", DevFmtStereo },
3128 { "quad", DevFmtQuad },
3129 { "surround51", DevFmtX51 },
3130 { "surround61", DevFmtX61 },
3131 { "surround71", DevFmtX71 },
3133 size_t i;
3135 for(i = 0;i < COUNTOF(chanlist);i++)
3137 if(strcasecmp(chanlist[i].name, fmt) == 0)
3139 device->FmtChans = chanlist[i].chans;
3140 device->Flags |= DEVICE_CHANNELS_REQUEST;
3141 break;
3144 if(i == COUNTOF(chanlist))
3145 ERR("Unsupported channels: %s\n", fmt);
3147 if(ConfigValueStr(NULL, "sample-type", &fmt))
3149 static const struct {
3150 const char name[16];
3151 enum DevFmtType type;
3152 } typelist[] = {
3153 { "int8", DevFmtByte },
3154 { "uint8", DevFmtUByte },
3155 { "int16", DevFmtShort },
3156 { "uint16", DevFmtUShort },
3157 { "int32", DevFmtInt },
3158 { "uint32", DevFmtUInt },
3159 { "float32", DevFmtFloat },
3161 size_t i;
3163 for(i = 0;i < COUNTOF(typelist);i++)
3165 if(strcasecmp(typelist[i].name, fmt) == 0)
3167 device->FmtType = typelist[i].type;
3168 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3169 break;
3172 if(i == COUNTOF(typelist))
3173 ERR("Unsupported sample-type: %s\n", fmt);
3175 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3176 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3177 ConfigValueStr(NULL, "format", &fmt))
3179 static const struct {
3180 const char name[32];
3181 enum DevFmtChannels channels;
3182 enum DevFmtType type;
3183 } formats[] = {
3184 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3185 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3186 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3187 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3188 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3189 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3191 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3192 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3193 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3194 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3195 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3196 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3198 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3199 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3200 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3201 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3202 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3203 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3205 size_t i;
3207 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3208 for(i = 0;i < COUNTOF(formats);i++)
3210 if(strcasecmp(fmt, formats[i].name) == 0)
3212 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3213 device->FmtChans = formats[i].channels;
3214 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3215 device->FmtType = formats[i].type;
3216 device->Flags |= DEVICE_FORMAT_REQUEST;
3217 break;
3220 if(i == COUNTOF(formats))
3221 ERR("Unsupported format: %s\n", fmt);
3223 #undef DEVICE_FORMAT_REQUEST
3225 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3227 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3228 if(device->Frequency < MIN_OUTPUT_RATE)
3229 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3230 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3233 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3234 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3236 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3237 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3238 if((CPUCapFlags&CPU_CAP_SSE))
3239 device->UpdateSize = (device->UpdateSize+3)&~3;
3241 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3242 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3244 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3245 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3247 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3248 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3250 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3252 device->NumStereoSources = 1;
3253 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3255 device->Synth = SynthCreate(device);
3256 if(!device->Synth)
3258 DELETE_OBJ(device->Backend);
3259 al_free(device);
3260 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3261 return NULL;
3264 // Find a playback device to open
3265 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3267 DELETE_OBJ(device->Synth);
3268 DELETE_OBJ(device->Backend);
3269 al_free(device);
3270 alcSetError(NULL, err);
3271 return NULL;
3274 if(DefaultEffect.type != AL_EFFECT_NULL)
3276 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3277 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3279 device->DefaultSlot = NULL;
3280 ERR("Failed to initialize the default effect slot\n");
3282 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3284 ALeffectState *state = device->DefaultSlot->EffectState;
3285 device->DefaultSlot = NULL;
3286 DELETE_OBJ(state);
3287 ERR("Failed to initialize the default effect\n");
3292 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3293 do {
3294 device->next = head;
3295 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3298 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3299 return device;
3302 /* alcCloseDevice
3304 * Closes the given device.
3306 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3308 ALCdevice *list, *origdev, *nextdev;
3309 ALCcontext *ctx;
3311 LockLists();
3312 list = ATOMIC_LOAD(&DeviceList);
3313 do {
3314 if(list == device)
3315 break;
3316 } while((list=list->next) != NULL);
3317 if(!list || list->Type == Capture)
3319 alcSetError(list, ALC_INVALID_DEVICE);
3320 UnlockLists();
3321 return ALC_FALSE;
3324 origdev = device;
3325 nextdev = device->next;
3326 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3328 do {
3329 list = origdev;
3330 origdev = device;
3331 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3333 UnlockLists();
3335 ctx = ATOMIC_LOAD(&device->ContextList);
3336 while(ctx != NULL)
3338 ALCcontext *next = ctx->next;
3339 WARN("Releasing context %p\n", ctx);
3340 ReleaseContext(ctx, device);
3341 ctx = next;
3343 if((device->Flags&DEVICE_RUNNING))
3344 V0(device->Backend,stop)();
3345 device->Flags &= ~DEVICE_RUNNING;
3347 ALCdevice_DecRef(device);
3349 return ALC_TRUE;
3353 /************************************************
3354 * ALC capture functions
3355 ************************************************/
3356 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3358 ALCdevice *device = NULL;
3359 ALCenum err;
3361 DO_INITCONFIG();
3363 if(!CaptureBackend.name)
3365 alcSetError(NULL, ALC_INVALID_VALUE);
3366 return NULL;
3369 if(samples <= 0)
3371 alcSetError(NULL, ALC_INVALID_VALUE);
3372 return NULL;
3375 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3376 deviceName = NULL;
3378 device = al_calloc(16, sizeof(ALCdevice));
3379 if(!device)
3381 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3382 return NULL;
3385 //Validate device
3386 InitRef(&device->ref, 1);
3387 device->Connected = ALC_TRUE;
3388 device->Type = Capture;
3390 AL_STRING_INIT(device->DeviceName);
3392 InitUIntMap(&device->BufferMap, ~0);
3393 InitUIntMap(&device->EffectMap, ~0);
3394 InitUIntMap(&device->FilterMap, ~0);
3395 InitUIntMap(&device->SfontMap, ~0);
3396 InitUIntMap(&device->PresetMap, ~0);
3397 InitUIntMap(&device->FontsoundMap, ~0);
3399 if(!CaptureBackend.getFactory)
3400 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3401 ALCbackend_Capture);
3402 else
3404 ALCbackendFactory *factory = CaptureBackend.getFactory();
3405 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3407 if(!device->Backend)
3409 al_free(device);
3410 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3411 return NULL;
3414 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3415 device->Frequency = frequency;
3417 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3418 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3420 al_free(device);
3421 alcSetError(NULL, ALC_INVALID_ENUM);
3422 return NULL;
3425 device->UpdateSize = samples;
3426 device->NumUpdates = 1;
3428 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3430 al_free(device);
3431 alcSetError(NULL, err);
3432 return NULL;
3436 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3437 do {
3438 device->next = head;
3439 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3442 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3443 return device;
3446 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3448 ALCdevice *list, *next, *nextdev;
3450 LockLists();
3451 list = ATOMIC_LOAD(&DeviceList);
3452 do {
3453 if(list == device)
3454 break;
3455 } while((list=list->next) != NULL);
3456 if(!list || list->Type != Capture)
3458 alcSetError(list, ALC_INVALID_DEVICE);
3459 UnlockLists();
3460 return ALC_FALSE;
3463 next = device;
3464 nextdev = device->next;
3465 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3467 do {
3468 list = next;
3469 next = device;
3470 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3472 UnlockLists();
3474 ALCdevice_DecRef(device);
3476 return ALC_TRUE;
3479 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3481 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3482 alcSetError(device, ALC_INVALID_DEVICE);
3483 else
3485 ALCdevice_Lock(device);
3486 if(device->Connected)
3488 if(!(device->Flags&DEVICE_RUNNING))
3489 V0(device->Backend,start)();
3490 device->Flags |= DEVICE_RUNNING;
3492 ALCdevice_Unlock(device);
3495 if(device) ALCdevice_DecRef(device);
3498 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3500 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3501 alcSetError(device, ALC_INVALID_DEVICE);
3502 else
3504 ALCdevice_Lock(device);
3505 if((device->Flags&DEVICE_RUNNING))
3506 V0(device->Backend,stop)();
3507 device->Flags &= ~DEVICE_RUNNING;
3508 ALCdevice_Unlock(device);
3511 if(device) ALCdevice_DecRef(device);
3514 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3516 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3517 alcSetError(device, ALC_INVALID_DEVICE);
3518 else
3520 ALCenum err = ALC_INVALID_VALUE;
3522 ALCdevice_Lock(device);
3523 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3524 err = V(device->Backend,captureSamples)(buffer, samples);
3525 ALCdevice_Unlock(device);
3527 if(err != ALC_NO_ERROR)
3528 alcSetError(device, err);
3530 if(device) ALCdevice_DecRef(device);
3534 /************************************************
3535 * ALC loopback functions
3536 ************************************************/
3538 /* alcLoopbackOpenDeviceSOFT
3540 * Open a loopback device, for manual rendering.
3542 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3544 ALCbackendFactory *factory;
3545 ALCdevice *device;
3547 DO_INITCONFIG();
3549 /* Make sure the device name, if specified, is us. */
3550 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3552 alcSetError(NULL, ALC_INVALID_VALUE);
3553 return NULL;
3556 device = al_calloc(16, sizeof(ALCdevice));
3557 if(!device)
3559 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3560 return NULL;
3563 //Validate device
3564 InitRef(&device->ref, 1);
3565 device->Connected = ALC_TRUE;
3566 device->Type = Loopback;
3567 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3569 device->Flags = 0;
3570 device->Bs2b = NULL;
3571 device->Bs2bLevel = 0;
3572 AL_STRING_INIT(device->DeviceName);
3574 ATOMIC_INIT(&device->ContextList, NULL);
3576 device->ClockBase = 0;
3577 device->SamplesDone = 0;
3579 device->MaxNoOfSources = 256;
3580 device->AuxiliaryEffectSlotMax = 4;
3581 device->NumAuxSends = MAX_SENDS;
3583 InitUIntMap(&device->BufferMap, ~0);
3584 InitUIntMap(&device->EffectMap, ~0);
3585 InitUIntMap(&device->FilterMap, ~0);
3586 InitUIntMap(&device->SfontMap, ~0);
3587 InitUIntMap(&device->PresetMap, ~0);
3588 InitUIntMap(&device->FontsoundMap, ~0);
3590 factory = ALCloopbackFactory_getFactory();
3591 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3592 if(!device->Backend)
3594 al_free(device);
3595 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3596 return NULL;
3599 //Set output format
3600 device->NumUpdates = 0;
3601 device->UpdateSize = 0;
3603 device->Frequency = DEFAULT_OUTPUT_RATE;
3604 device->FmtChans = DevFmtChannelsDefault;
3605 device->FmtType = DevFmtTypeDefault;
3607 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3608 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3610 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3611 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3613 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3614 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3616 device->NumStereoSources = 1;
3617 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3619 device->Synth = SynthCreate(device);
3620 if(!device->Synth)
3622 DELETE_OBJ(device->Backend);
3623 al_free(device);
3624 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3625 return NULL;
3628 // Open the "backend"
3629 V(device->Backend,open)("Loopback");
3632 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3633 do {
3634 device->next = head;
3635 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3638 TRACE("Created device %p\n", device);
3639 return device;
3642 /* alcIsRenderFormatSupportedSOFT
3644 * Determines if the loopback device supports the given format for rendering.
3646 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3648 ALCboolean ret = ALC_FALSE;
3650 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3651 alcSetError(device, ALC_INVALID_DEVICE);
3652 else if(freq <= 0)
3653 alcSetError(device, ALC_INVALID_VALUE);
3654 else
3656 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3657 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3658 freq >= MIN_OUTPUT_RATE)
3659 ret = ALC_TRUE;
3661 if(device) ALCdevice_DecRef(device);
3663 return ret;
3666 /* alcRenderSamplesSOFT
3668 * Renders some samples into a buffer, using the format last set by the
3669 * attributes given to alcCreateContext.
3671 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3673 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3674 alcSetError(device, ALC_INVALID_DEVICE);
3675 else if(samples < 0 || (samples > 0 && buffer == NULL))
3676 alcSetError(device, ALC_INVALID_VALUE);
3677 else
3678 aluMixData(device, buffer, samples);
3679 if(device) ALCdevice_DecRef(device);
3683 /************************************************
3684 * ALC DSP pause/resume functions
3685 ************************************************/
3687 /* alcDevicePauseSOFT
3689 * Pause the DSP to stop audio processing.
3691 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3693 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3694 alcSetError(device, ALC_INVALID_DEVICE);
3695 else
3697 LockLists();
3698 if((device->Flags&DEVICE_RUNNING))
3699 V0(device->Backend,stop)();
3700 device->Flags &= ~DEVICE_RUNNING;
3701 device->Flags |= DEVICE_PAUSED;
3702 UnlockLists();
3704 if(device) ALCdevice_DecRef(device);
3707 /* alcDeviceResumeSOFT
3709 * Resume the DSP to restart audio processing.
3711 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3713 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3714 alcSetError(device, ALC_INVALID_DEVICE);
3715 else
3717 LockLists();
3718 if((device->Flags&DEVICE_PAUSED))
3720 device->Flags &= ~DEVICE_PAUSED;
3721 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3723 if(V0(device->Backend,start)() != ALC_FALSE)
3724 device->Flags |= DEVICE_RUNNING;
3725 else
3727 alcSetError(device, ALC_INVALID_DEVICE);
3728 ALCdevice_Lock(device);
3729 aluHandleDisconnect(device);
3730 ALCdevice_Unlock(device);
3734 UnlockLists();
3736 if(device) ALCdevice_DecRef(device);