Wrap fopen calls under Windows
[openal-soft.git] / Alc / ALc.c
blob5ebe020550d37f126b4cf69d6311b8698820fc11
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "backends/base.h"
43 #include "midi/base.h"
46 /************************************************
47 * Backends
48 ************************************************/
49 struct BackendInfo {
50 const char *name;
51 ALCbackendFactory* (*getFactory)(void);
52 ALCboolean (*Init)(BackendFuncs*);
53 void (*Deinit)(void);
54 void (*Probe)(enum DevProbe);
55 BackendFuncs Funcs;
58 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
59 static struct BackendInfo BackendList[] = {
60 #ifdef HAVE_PULSEAUDIO
61 { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
62 #endif
63 #ifdef HAVE_ALSA
64 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
65 #endif
66 #ifdef HAVE_COREAUDIO
67 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_OSS
70 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
71 #endif
72 #ifdef HAVE_SOLARIS
73 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
74 #endif
75 #ifdef HAVE_SNDIO
76 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
77 #endif
78 #ifdef HAVE_QSA
79 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
80 #endif
81 #ifdef HAVE_MMDEVAPI
82 { "mmdevapi", NULL, alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
83 #endif
84 #ifdef HAVE_DSOUND
85 { "dsound", NULL, alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
86 #endif
87 #ifdef HAVE_WINMM
88 { "winmm", NULL, alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
89 #endif
90 #ifdef HAVE_PORTAUDIO
91 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
92 #endif
93 #ifdef HAVE_OPENSL
94 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
95 #endif
97 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
98 #ifdef HAVE_WAVE
99 { "wave", NULL, alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
100 #endif
102 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
104 #undef EmptyFuncs
106 static struct BackendInfo PlaybackBackend;
107 static struct BackendInfo CaptureBackend;
110 /************************************************
111 * Functions, enums, and errors
112 ************************************************/
113 typedef struct ALCfunction {
114 const ALCchar *funcName;
115 ALCvoid *address;
116 } ALCfunction;
118 typedef struct ALCenums {
119 const ALCchar *enumName;
120 ALCenum value;
121 } ALCenums;
123 #define DECL(x) { #x, (ALCvoid*)(x) }
124 static const ALCfunction alcFunctions[] = {
125 DECL(alcCreateContext),
126 DECL(alcMakeContextCurrent),
127 DECL(alcProcessContext),
128 DECL(alcSuspendContext),
129 DECL(alcDestroyContext),
130 DECL(alcGetCurrentContext),
131 DECL(alcGetContextsDevice),
132 DECL(alcOpenDevice),
133 DECL(alcCloseDevice),
134 DECL(alcGetError),
135 DECL(alcIsExtensionPresent),
136 DECL(alcGetProcAddress),
137 DECL(alcGetEnumValue),
138 DECL(alcGetString),
139 DECL(alcGetIntegerv),
140 DECL(alcCaptureOpenDevice),
141 DECL(alcCaptureCloseDevice),
142 DECL(alcCaptureStart),
143 DECL(alcCaptureStop),
144 DECL(alcCaptureSamples),
146 DECL(alcSetThreadContext),
147 DECL(alcGetThreadContext),
149 DECL(alcLoopbackOpenDeviceSOFT),
150 DECL(alcIsRenderFormatSupportedSOFT),
151 DECL(alcRenderSamplesSOFT),
153 DECL(alcDevicePauseSOFT),
154 DECL(alcDeviceResumeSOFT),
156 DECL(alcGetInteger64vSOFT),
158 DECL(alEnable),
159 DECL(alDisable),
160 DECL(alIsEnabled),
161 DECL(alGetString),
162 DECL(alGetBooleanv),
163 DECL(alGetIntegerv),
164 DECL(alGetFloatv),
165 DECL(alGetDoublev),
166 DECL(alGetBoolean),
167 DECL(alGetInteger),
168 DECL(alGetFloat),
169 DECL(alGetDouble),
170 DECL(alGetError),
171 DECL(alIsExtensionPresent),
172 DECL(alGetProcAddress),
173 DECL(alGetEnumValue),
174 DECL(alListenerf),
175 DECL(alListener3f),
176 DECL(alListenerfv),
177 DECL(alListeneri),
178 DECL(alListener3i),
179 DECL(alListeneriv),
180 DECL(alGetListenerf),
181 DECL(alGetListener3f),
182 DECL(alGetListenerfv),
183 DECL(alGetListeneri),
184 DECL(alGetListener3i),
185 DECL(alGetListeneriv),
186 DECL(alGenSources),
187 DECL(alDeleteSources),
188 DECL(alIsSource),
189 DECL(alSourcef),
190 DECL(alSource3f),
191 DECL(alSourcefv),
192 DECL(alSourcei),
193 DECL(alSource3i),
194 DECL(alSourceiv),
195 DECL(alGetSourcef),
196 DECL(alGetSource3f),
197 DECL(alGetSourcefv),
198 DECL(alGetSourcei),
199 DECL(alGetSource3i),
200 DECL(alGetSourceiv),
201 DECL(alSourcePlayv),
202 DECL(alSourceStopv),
203 DECL(alSourceRewindv),
204 DECL(alSourcePausev),
205 DECL(alSourcePlay),
206 DECL(alSourceStop),
207 DECL(alSourceRewind),
208 DECL(alSourcePause),
209 DECL(alSourceQueueBuffers),
210 DECL(alSourceUnqueueBuffers),
211 DECL(alGenBuffers),
212 DECL(alDeleteBuffers),
213 DECL(alIsBuffer),
214 DECL(alBufferData),
215 DECL(alBufferf),
216 DECL(alBuffer3f),
217 DECL(alBufferfv),
218 DECL(alBufferi),
219 DECL(alBuffer3i),
220 DECL(alBufferiv),
221 DECL(alGetBufferf),
222 DECL(alGetBuffer3f),
223 DECL(alGetBufferfv),
224 DECL(alGetBufferi),
225 DECL(alGetBuffer3i),
226 DECL(alGetBufferiv),
227 DECL(alDopplerFactor),
228 DECL(alDopplerVelocity),
229 DECL(alSpeedOfSound),
230 DECL(alDistanceModel),
232 DECL(alGenFilters),
233 DECL(alDeleteFilters),
234 DECL(alIsFilter),
235 DECL(alFilteri),
236 DECL(alFilteriv),
237 DECL(alFilterf),
238 DECL(alFilterfv),
239 DECL(alGetFilteri),
240 DECL(alGetFilteriv),
241 DECL(alGetFilterf),
242 DECL(alGetFilterfv),
243 DECL(alGenEffects),
244 DECL(alDeleteEffects),
245 DECL(alIsEffect),
246 DECL(alEffecti),
247 DECL(alEffectiv),
248 DECL(alEffectf),
249 DECL(alEffectfv),
250 DECL(alGetEffecti),
251 DECL(alGetEffectiv),
252 DECL(alGetEffectf),
253 DECL(alGetEffectfv),
254 DECL(alGenAuxiliaryEffectSlots),
255 DECL(alDeleteAuxiliaryEffectSlots),
256 DECL(alIsAuxiliaryEffectSlot),
257 DECL(alAuxiliaryEffectSloti),
258 DECL(alAuxiliaryEffectSlotiv),
259 DECL(alAuxiliaryEffectSlotf),
260 DECL(alAuxiliaryEffectSlotfv),
261 DECL(alGetAuxiliaryEffectSloti),
262 DECL(alGetAuxiliaryEffectSlotiv),
263 DECL(alGetAuxiliaryEffectSlotf),
264 DECL(alGetAuxiliaryEffectSlotfv),
266 DECL(alBufferSubDataSOFT),
268 DECL(alBufferSamplesSOFT),
269 DECL(alBufferSubSamplesSOFT),
270 DECL(alGetBufferSamplesSOFT),
271 DECL(alIsBufferFormatSupportedSOFT),
273 DECL(alDeferUpdatesSOFT),
274 DECL(alProcessUpdatesSOFT),
276 DECL(alSourcedSOFT),
277 DECL(alSource3dSOFT),
278 DECL(alSourcedvSOFT),
279 DECL(alGetSourcedSOFT),
280 DECL(alGetSource3dSOFT),
281 DECL(alGetSourcedvSOFT),
282 DECL(alSourcei64SOFT),
283 DECL(alSource3i64SOFT),
284 DECL(alSourcei64vSOFT),
285 DECL(alGetSourcei64SOFT),
286 DECL(alGetSource3i64SOFT),
287 DECL(alGetSourcei64vSOFT),
289 DECL(alGenSoundfontsSOFT),
290 DECL(alDeleteSoundfontsSOFT),
291 DECL(alIsSoundfontSOFT),
292 DECL(alSoundfontSamplesSOFT),
293 DECL(alGetSoundfontSamplesSOFT),
294 DECL(alSoundfontMapSamplesSOFT),
295 DECL(alSoundfontUnmapSamplesSOFT),
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 #if 0
565 DECL(AL_FILTER_HIGHPASS),
566 DECL(AL_FILTER_BANDPASS),
567 #endif
569 DECL(AL_LOWPASS_GAIN),
570 DECL(AL_LOWPASS_GAINHF),
572 DECL(AL_EFFECT_TYPE),
573 DECL(AL_EFFECT_NULL),
574 DECL(AL_EFFECT_REVERB),
575 DECL(AL_EFFECT_EAXREVERB),
576 DECL(AL_EFFECT_CHORUS),
577 DECL(AL_EFFECT_DISTORTION),
578 DECL(AL_EFFECT_ECHO),
579 DECL(AL_EFFECT_FLANGER),
580 #if 0
581 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
582 DECL(AL_EFFECT_VOCAL_MORPHER),
583 DECL(AL_EFFECT_PITCH_SHIFTER),
584 #endif
585 DECL(AL_EFFECT_RING_MODULATOR),
586 DECL(AL_EFFECT_AUTOWAH),
587 DECL(AL_EFFECT_COMPRESSOR),
588 DECL(AL_EFFECT_EQUALIZER),
589 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT),
590 DECL(AL_EFFECT_DEDICATED_DIALOGUE),
592 DECL(AL_EAXREVERB_DENSITY),
593 DECL(AL_EAXREVERB_DIFFUSION),
594 DECL(AL_EAXREVERB_GAIN),
595 DECL(AL_EAXREVERB_GAINHF),
596 DECL(AL_EAXREVERB_GAINLF),
597 DECL(AL_EAXREVERB_DECAY_TIME),
598 DECL(AL_EAXREVERB_DECAY_HFRATIO),
599 DECL(AL_EAXREVERB_DECAY_LFRATIO),
600 DECL(AL_EAXREVERB_REFLECTIONS_GAIN),
601 DECL(AL_EAXREVERB_REFLECTIONS_DELAY),
602 DECL(AL_EAXREVERB_REFLECTIONS_PAN),
603 DECL(AL_EAXREVERB_LATE_REVERB_GAIN),
604 DECL(AL_EAXREVERB_LATE_REVERB_DELAY),
605 DECL(AL_EAXREVERB_LATE_REVERB_PAN),
606 DECL(AL_EAXREVERB_ECHO_TIME),
607 DECL(AL_EAXREVERB_ECHO_DEPTH),
608 DECL(AL_EAXREVERB_MODULATION_TIME),
609 DECL(AL_EAXREVERB_MODULATION_DEPTH),
610 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF),
611 DECL(AL_EAXREVERB_HFREFERENCE),
612 DECL(AL_EAXREVERB_LFREFERENCE),
613 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR),
614 DECL(AL_EAXREVERB_DECAY_HFLIMIT),
616 DECL(AL_REVERB_DENSITY),
617 DECL(AL_REVERB_DIFFUSION),
618 DECL(AL_REVERB_GAIN),
619 DECL(AL_REVERB_GAINHF),
620 DECL(AL_REVERB_DECAY_TIME),
621 DECL(AL_REVERB_DECAY_HFRATIO),
622 DECL(AL_REVERB_REFLECTIONS_GAIN),
623 DECL(AL_REVERB_REFLECTIONS_DELAY),
624 DECL(AL_REVERB_LATE_REVERB_GAIN),
625 DECL(AL_REVERB_LATE_REVERB_DELAY),
626 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF),
627 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR),
628 DECL(AL_REVERB_DECAY_HFLIMIT),
630 DECL(AL_CHORUS_WAVEFORM),
631 DECL(AL_CHORUS_PHASE),
632 DECL(AL_CHORUS_RATE),
633 DECL(AL_CHORUS_DEPTH),
634 DECL(AL_CHORUS_FEEDBACK),
635 DECL(AL_CHORUS_DELAY),
637 DECL(AL_DISTORTION_EDGE),
638 DECL(AL_DISTORTION_GAIN),
639 DECL(AL_DISTORTION_LOWPASS_CUTOFF),
640 DECL(AL_DISTORTION_EQCENTER),
641 DECL(AL_DISTORTION_EQBANDWIDTH),
643 DECL(AL_ECHO_DELAY),
644 DECL(AL_ECHO_LRDELAY),
645 DECL(AL_ECHO_DAMPING),
646 DECL(AL_ECHO_FEEDBACK),
647 DECL(AL_ECHO_SPREAD),
649 DECL(AL_FLANGER_WAVEFORM),
650 DECL(AL_FLANGER_PHASE),
651 DECL(AL_FLANGER_RATE),
652 DECL(AL_FLANGER_DEPTH),
653 DECL(AL_FLANGER_FEEDBACK),
654 DECL(AL_FLANGER_DELAY),
656 DECL(AL_RING_MODULATOR_FREQUENCY),
657 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF),
658 DECL(AL_RING_MODULATOR_WAVEFORM),
660 DECL(AL_AUTOWAH_ATTACK_TIME),
661 DECL(AL_AUTOWAH_PEAK_GAIN),
662 DECL(AL_AUTOWAH_RELEASE_TIME),
663 DECL(AL_AUTOWAH_RESONANCE),
665 DECL(AL_COMPRESSOR_ONOFF),
667 DECL(AL_EQUALIZER_LOW_GAIN),
668 DECL(AL_EQUALIZER_LOW_CUTOFF),
669 DECL(AL_EQUALIZER_MID1_GAIN),
670 DECL(AL_EQUALIZER_MID1_CENTER),
671 DECL(AL_EQUALIZER_MID1_WIDTH),
672 DECL(AL_EQUALIZER_MID2_GAIN),
673 DECL(AL_EQUALIZER_MID2_CENTER),
674 DECL(AL_EQUALIZER_MID2_WIDTH),
675 DECL(AL_EQUALIZER_HIGH_GAIN),
676 DECL(AL_EQUALIZER_HIGH_CUTOFF),
678 DECL(AL_DEDICATED_GAIN),
680 { NULL, (ALCenum)0 }
682 #undef DECL
684 static const ALCchar alcNoError[] = "No Error";
685 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
686 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
687 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
688 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
689 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
692 /************************************************
693 * Global variables
694 ************************************************/
696 /* Enumerated device names */
697 static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
698 static ALCchar *alcAllDevicesList;
699 static ALCchar *alcCaptureDeviceList;
700 /* Sizes only include the first ending null character, not the second */
701 static size_t alcAllDevicesListSize;
702 static size_t alcCaptureDeviceListSize;
704 /* Default is always the first in the list */
705 static ALCchar *alcDefaultAllDevicesSpecifier;
706 static ALCchar *alcCaptureDefaultDeviceSpecifier;
708 /* Default context extensions */
709 static const ALchar alExtList[] =
710 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
711 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
712 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
713 "AL_LOKI_quadriphonic AL_SOFTX_block_alignment AL_SOFT_buffer_samples "
714 "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
715 "AL_SOFT_loop_points AL_SOFTX_MSADPCM AL_SOFT_source_latency";
717 static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
719 /* Thread-local current context */
720 static althread_key_t LocalContext;
721 /* Process-wide current context */
722 static ALCcontext *volatile GlobalContext = NULL;
724 /* Mixing thread piority level */
725 ALint RTPrioLevel;
727 FILE *LogFile;
728 #ifdef _DEBUG
729 enum LogLevel LogLevel = LogWarning;
730 #else
731 enum LogLevel LogLevel = LogError;
732 #endif
734 /* Flag to trap ALC device errors */
735 static ALCboolean TrapALCError = ALC_FALSE;
737 /* One-time configuration init control */
738 static althread_once_t alc_config_once = ALTHREAD_ONCE_INIT;
740 /* Default effect that applies to sources that don't have an effect on send 0 */
741 static ALeffect DefaultEffect;
744 /************************************************
745 * ALC information
746 ************************************************/
747 static const ALCchar alcNoDeviceExtList[] =
748 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
749 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
750 static const ALCchar alcExtensionList[] =
751 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
752 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
753 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
754 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
755 static const ALCint alcMajorVersion = 1;
756 static const ALCint alcMinorVersion = 1;
758 static const ALCint alcEFXMajorVersion = 1;
759 static const ALCint alcEFXMinorVersion = 0;
762 /************************************************
763 * Device lists
764 ************************************************/
765 static ALCdevice *volatile DeviceList = NULL;
767 static CRITICAL_SECTION ListLock;
769 static void LockLists(void)
771 EnterCriticalSection(&ListLock);
773 static void UnlockLists(void)
775 LeaveCriticalSection(&ListLock);
778 /************************************************
779 * Library initialization
780 ************************************************/
781 #if defined(_WIN32)
782 static void alc_init(void);
783 static void alc_deinit(void);
784 static void alc_deinit_safe(void);
786 UIntMap TlsDestructor;
788 #ifndef AL_LIBTYPE_STATIC
789 BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
791 ALsizei i;
793 // Perform actions based on the reason for calling.
794 switch(ul_reason_for_call)
796 case DLL_PROCESS_ATTACH:
797 /* Pin the DLL so we won't get unloaded until the process terminates */
798 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
799 (WCHAR*)hModule, &hModule);
800 InitUIntMap(&TlsDestructor, ~0);
801 alc_init();
802 break;
804 case DLL_THREAD_DETACH:
805 LockUIntMapRead(&TlsDestructor);
806 for(i = 0;i < TlsDestructor.size;i++)
808 void *ptr = althread_getspecific(TlsDestructor.array[i].key);
809 void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value;
810 if(ptr && callback)
811 callback(ptr);
813 UnlockUIntMapRead(&TlsDestructor);
814 break;
816 case DLL_PROCESS_DETACH:
817 if(!lpReserved)
818 alc_deinit();
819 else
820 alc_deinit_safe();
821 ResetUIntMap(&TlsDestructor);
822 break;
824 return TRUE;
826 #elif defined(_MSC_VER)
827 #pragma section(".CRT$XCU",read)
828 static void alc_constructor(void);
829 static void alc_destructor(void);
830 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
832 static void alc_constructor(void)
834 atexit(alc_destructor);
835 alc_init();
838 static void alc_destructor(void)
840 alc_deinit();
842 #elif defined(HAVE_GCC_DESTRUCTOR)
843 static void alc_init(void) __attribute__((constructor));
844 static void alc_deinit(void) __attribute__((destructor));
845 #else
846 #error "No static initialization available on this platform!"
847 #endif
849 #elif defined(HAVE_GCC_DESTRUCTOR)
851 static void alc_init(void) __attribute__((constructor));
852 static void alc_deinit(void) __attribute__((destructor));
854 #else
855 #error "No global initialization available on this platform!"
856 #endif
858 static void ReleaseThreadCtx(void *ptr);
859 static void alc_init(void)
861 const char *str;
863 LogFile = stderr;
865 str = getenv("__ALSOFT_HALF_ANGLE_CONES");
866 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
867 ConeScale *= 0.5f;
869 str = getenv("__ALSOFT_REVERSE_Z");
870 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
871 ZScale *= -1.0f;
873 althread_key_create(&LocalContext, ReleaseThreadCtx);
874 InitializeCriticalSection(&ListLock);
875 ThunkInit();
878 static void alc_initconfig(void)
880 const char *devs, *str;
881 ALuint capfilter;
882 float valf;
883 int i, n;
885 str = getenv("ALSOFT_LOGLEVEL");
886 if(str)
888 long lvl = strtol(str, NULL, 0);
889 if(lvl >= NoLog && lvl <= LogRef)
890 LogLevel = lvl;
893 str = getenv("ALSOFT_LOGFILE");
894 if(str && str[0])
896 FILE *logfile = al_fopen(str, "wt");
897 if(logfile) LogFile = logfile;
898 else ERR("Failed to open log file '%s'\n", str);
902 char buf[1024] = "";
903 int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name);
904 for(i = 1;BackendList[i].name;i++)
905 len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name);
906 TRACE("Supported backends: %s\n", buf);
908 ReadALConfig();
910 capfilter = 0;
911 #ifdef HAVE_SSE
912 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
913 #endif
914 #ifdef HAVE_NEON
915 capfilter |= CPU_CAP_NEON;
916 #endif
917 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
919 if(strcasecmp(str, "all") == 0)
920 capfilter = 0;
921 else
923 size_t len;
924 const char *next = str;
926 do {
927 str = next;
928 while(isspace(str[0]))
929 str++;
930 next = strchr(str, ',');
932 if(!str[0] || str[0] == ',')
933 continue;
935 len = (next ? ((size_t)(next-str)) : strlen(str));
936 while(len > 0 && isspace(str[len-1]))
937 len--;
938 if(len == 3 && strncasecmp(str, "sse", len) == 0)
939 capfilter &= ~CPU_CAP_SSE;
940 else if(len == 4 && strncasecmp(str, "sse2", len) == 0)
941 capfilter &= ~CPU_CAP_SSE2;
942 else if(len == 4 && strncasecmp(str, "neon", len) == 0)
943 capfilter &= ~CPU_CAP_NEON;
944 else
945 WARN("Invalid CPU extension \"%s\"\n", str);
946 } while(next++);
949 FillCPUCaps(capfilter);
951 #ifdef _WIN32
952 RTPrioLevel = 1;
953 #else
954 RTPrioLevel = 0;
955 #endif
956 ConfigValueInt(NULL, "rt-prio", &RTPrioLevel);
958 if(ConfigValueStr(NULL, "resampler", &str))
960 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
961 DefaultResampler = PointResampler;
962 else if(strcasecmp(str, "linear") == 0)
963 DefaultResampler = LinearResampler;
964 else if(strcasecmp(str, "cubic") == 0)
965 DefaultResampler = CubicResampler;
966 else
968 char *end;
970 n = strtol(str, &end, 0);
971 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
972 DefaultResampler = n;
973 else
974 WARN("Invalid resampler: %s\n", str);
978 str = getenv("ALSOFT_TRAP_ERROR");
979 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
981 TrapALError = AL_TRUE;
982 TrapALCError = AL_TRUE;
984 else
986 str = getenv("ALSOFT_TRAP_AL_ERROR");
987 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
988 TrapALError = AL_TRUE;
989 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
991 str = getenv("ALSOFT_TRAP_ALC_ERROR");
992 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
993 TrapALCError = ALC_TRUE;
994 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
997 if(ConfigValueFloat("reverb", "boost", &valf))
998 ReverbBoost *= powf(10.0f, valf / 20.0f);
1000 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1002 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1003 ConfigValueStr(NULL, "drivers", &devs))
1005 int n;
1006 size_t len;
1007 const char *next = devs;
1008 int endlist, delitem;
1010 i = 0;
1011 do {
1012 devs = next;
1013 while(isspace(devs[0]))
1014 devs++;
1015 next = strchr(devs, ',');
1017 delitem = (devs[0] == '-');
1018 if(devs[0] == '-') devs++;
1020 if(!devs[0] || devs[0] == ',')
1022 endlist = 0;
1023 continue;
1025 endlist = 1;
1027 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1028 while(len > 0 && isspace(devs[len-1]))
1029 len--;
1030 for(n = i;BackendList[n].name;n++)
1032 if(len == strlen(BackendList[n].name) &&
1033 strncmp(BackendList[n].name, devs, len) == 0)
1035 if(delitem)
1037 do {
1038 BackendList[n] = BackendList[n+1];
1039 ++n;
1040 } while(BackendList[n].name);
1042 else
1044 struct BackendInfo Bkp = BackendList[n];
1045 while(n > i)
1047 BackendList[n] = BackendList[n-1];
1048 --n;
1050 BackendList[n] = Bkp;
1052 i++;
1054 break;
1057 } while(next++);
1059 if(endlist)
1061 BackendList[i].name = NULL;
1062 BackendList[i].getFactory = NULL;
1063 BackendList[i].Init = NULL;
1064 BackendList[i].Deinit = NULL;
1065 BackendList[i].Probe = NULL;
1069 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1071 if(BackendList[i].getFactory)
1073 ALCbackendFactory *factory = BackendList[i].getFactory();
1074 if(!V0(factory,init)())
1076 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1077 continue;
1080 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1081 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1083 PlaybackBackend = BackendList[i];
1084 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1086 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1088 CaptureBackend = BackendList[i];
1089 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1092 continue;
1095 if(!BackendList[i].Init(&BackendList[i].Funcs))
1097 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1098 continue;
1101 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1102 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1104 PlaybackBackend = BackendList[i];
1105 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1107 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1109 CaptureBackend = BackendList[i];
1110 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1114 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1115 V0(factory,init)();
1118 if(ConfigValueStr(NULL, "excludefx", &str))
1120 size_t len;
1121 const char *next = str;
1123 do {
1124 str = next;
1125 next = strchr(str, ',');
1127 if(!str[0] || next == str)
1128 continue;
1130 len = (next ? ((size_t)(next-str)) : strlen(str));
1131 for(n = 0;EffectList[n].name;n++)
1133 if(len == strlen(EffectList[n].name) &&
1134 strncmp(EffectList[n].name, str, len) == 0)
1135 DisabledEffects[EffectList[n].type] = AL_TRUE;
1137 } while(next++);
1140 InitEffectFactoryMap();
1142 InitEffect(&DefaultEffect);
1143 str = getenv("ALSOFT_DEFAULT_REVERB");
1144 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1145 LoadReverbPreset(str, &DefaultEffect);
1147 #define DO_INITCONFIG() althread_once(&alc_config_once, alc_initconfig)
1150 /************************************************
1151 * Library deinitialization
1152 ************************************************/
1153 static void alc_cleanup(void)
1155 ALCdevice *dev;
1157 free(alcAllDevicesList); alcAllDevicesList = NULL;
1158 alcAllDevicesListSize = 0;
1159 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1160 alcCaptureDeviceListSize = 0;
1162 free(alcDefaultAllDevicesSpecifier);
1163 alcDefaultAllDevicesSpecifier = NULL;
1164 free(alcCaptureDefaultDeviceSpecifier);
1165 alcCaptureDefaultDeviceSpecifier = NULL;
1167 if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
1169 ALCuint num = 0;
1170 do {
1171 num++;
1172 } while((dev=dev->next) != NULL);
1173 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1176 DeinitEffectFactoryMap();
1179 static void alc_deinit_safe(void)
1181 alc_cleanup();
1183 FreeHrtfs();
1184 FreeALConfig();
1186 ThunkExit();
1187 DeleteCriticalSection(&ListLock);
1188 althread_key_delete(LocalContext);
1190 if(LogFile != stderr)
1191 fclose(LogFile);
1192 LogFile = NULL;
1195 static void alc_deinit(void)
1197 int i;
1199 alc_cleanup();
1201 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1202 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1204 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1206 if(!BackendList[i].getFactory)
1207 BackendList[i].Deinit();
1208 else
1210 ALCbackendFactory *factory = BackendList[i].getFactory();
1211 V0(factory,deinit)();
1215 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1216 V0(factory,deinit)();
1219 alc_deinit_safe();
1223 /************************************************
1224 * Device enumeration
1225 ************************************************/
1226 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
1228 DO_INITCONFIG();
1230 LockLists();
1231 free(*list);
1232 *list = NULL;
1233 *listsize = 0;
1235 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1237 if(!PlaybackBackend.getFactory)
1238 PlaybackBackend.Probe(type);
1239 else
1241 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1242 V(factory,probe)(type);
1245 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1247 if(!CaptureBackend.getFactory)
1248 CaptureBackend.Probe(type);
1249 else
1251 ALCbackendFactory *factory = CaptureBackend.getFactory();
1252 V(factory,probe)(type);
1255 UnlockLists();
1258 static void ProbeAllDevicesList(void)
1259 { ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); }
1260 static void ProbeCaptureDeviceList(void)
1261 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
1264 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
1266 size_t len = strlen(name);
1267 void *temp;
1269 if(len == 0)
1270 return;
1272 temp = realloc(*List, (*ListSize) + len + 2);
1273 if(!temp)
1275 ERR("Realloc failed to add %s!\n", name);
1276 return;
1278 *List = temp;
1280 memcpy((*List)+(*ListSize), name, len+1);
1281 *ListSize += len+1;
1282 (*List)[*ListSize] = 0;
1285 #define DECL_APPEND_LIST_FUNC(type) \
1286 void Append##type##List(const ALCchar *name) \
1287 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1289 DECL_APPEND_LIST_FUNC(AllDevices)
1290 DECL_APPEND_LIST_FUNC(CaptureDevice)
1292 #undef DECL_APPEND_LIST_FUNC
1295 /************************************************
1296 * Device format information
1297 ************************************************/
1298 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1300 switch(type)
1302 case DevFmtByte: return "Signed Byte";
1303 case DevFmtUByte: return "Unsigned Byte";
1304 case DevFmtShort: return "Signed Short";
1305 case DevFmtUShort: return "Unsigned Short";
1306 case DevFmtInt: return "Signed Int";
1307 case DevFmtUInt: return "Unsigned Int";
1308 case DevFmtFloat: return "Float";
1310 return "(unknown type)";
1312 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1314 switch(chans)
1316 case DevFmtMono: return "Mono";
1317 case DevFmtStereo: return "Stereo";
1318 case DevFmtQuad: return "Quadraphonic";
1319 case DevFmtX51: return "5.1 Surround";
1320 case DevFmtX51Side: return "5.1 Side";
1321 case DevFmtX61: return "6.1 Surround";
1322 case DevFmtX71: return "7.1 Surround";
1324 return "(unknown channels)";
1327 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1328 ALuint BytesFromDevFmt(enum DevFmtType type)
1330 switch(type)
1332 case DevFmtByte: return sizeof(ALbyte);
1333 case DevFmtUByte: return sizeof(ALubyte);
1334 case DevFmtShort: return sizeof(ALshort);
1335 case DevFmtUShort: return sizeof(ALushort);
1336 case DevFmtInt: return sizeof(ALint);
1337 case DevFmtUInt: return sizeof(ALuint);
1338 case DevFmtFloat: return sizeof(ALfloat);
1340 return 0;
1342 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1344 switch(chans)
1346 case DevFmtMono: return 1;
1347 case DevFmtStereo: return 2;
1348 case DevFmtQuad: return 4;
1349 case DevFmtX51: return 6;
1350 case DevFmtX51Side: return 6;
1351 case DevFmtX61: return 7;
1352 case DevFmtX71: return 8;
1354 return 0;
1357 static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
1358 enum DevFmtType *type)
1360 static const struct {
1361 ALenum format;
1362 enum DevFmtChannels channels;
1363 enum DevFmtType type;
1364 } list[] = {
1365 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1366 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1367 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1369 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1370 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1371 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1373 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1374 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1375 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1377 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1378 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1379 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1381 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1382 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1383 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1385 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1386 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1387 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1389 ALuint i;
1391 for(i = 0;i < COUNTOF(list);i++)
1393 if(list[i].format == format)
1395 *chans = list[i].channels;
1396 *type = list[i].type;
1397 return AL_TRUE;
1401 return AL_FALSE;
1404 static ALCboolean IsValidALCType(ALCenum type)
1406 switch(type)
1408 case ALC_BYTE_SOFT:
1409 case ALC_UNSIGNED_BYTE_SOFT:
1410 case ALC_SHORT_SOFT:
1411 case ALC_UNSIGNED_SHORT_SOFT:
1412 case ALC_INT_SOFT:
1413 case ALC_UNSIGNED_INT_SOFT:
1414 case ALC_FLOAT_SOFT:
1415 return ALC_TRUE;
1417 return ALC_FALSE;
1420 static ALCboolean IsValidALCChannels(ALCenum channels)
1422 switch(channels)
1424 case ALC_MONO_SOFT:
1425 case ALC_STEREO_SOFT:
1426 case ALC_QUAD_SOFT:
1427 case ALC_5POINT1_SOFT:
1428 case ALC_6POINT1_SOFT:
1429 case ALC_7POINT1_SOFT:
1430 return ALC_TRUE;
1432 return ALC_FALSE;
1436 /************************************************
1437 * Miscellaneous ALC helpers
1438 ************************************************/
1439 extern inline void LockContext(ALCcontext *context);
1440 extern inline void UnlockContext(ALCcontext *context);
1442 ALint64 ALCdevice_GetLatencyDefault(ALCdevice *UNUSED(device))
1444 return 0;
1447 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1449 return V0(device->Backend,getLatency)();
1452 void ALCdevice_Lock(ALCdevice *device)
1454 V0(device->Backend,lock)();
1457 void ALCdevice_Unlock(ALCdevice *device)
1459 V0(device->Backend,unlock)();
1463 /* SetDefaultWFXChannelOrder
1465 * Sets the default channel order used by WaveFormatEx.
1467 void SetDefaultWFXChannelOrder(ALCdevice *device)
1469 ALuint i;
1471 for(i = 0;i < MaxChannels;i++)
1472 device->ChannelOffsets[i] = INVALID_OFFSET;
1474 switch(device->FmtChans)
1476 case DevFmtMono: device->ChannelOffsets[FrontCenter] = 0;
1477 break;
1478 case DevFmtStereo: device->ChannelOffsets[FrontLeft] = 0;
1479 device->ChannelOffsets[FrontRight] = 1;
1480 break;
1481 case DevFmtQuad: device->ChannelOffsets[FrontLeft] = 0;
1482 device->ChannelOffsets[FrontRight] = 1;
1483 device->ChannelOffsets[BackLeft] = 2;
1484 device->ChannelOffsets[BackRight] = 3;
1485 break;
1486 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1487 device->ChannelOffsets[FrontRight] = 1;
1488 device->ChannelOffsets[FrontCenter] = 2;
1489 device->ChannelOffsets[LFE] = 3;
1490 device->ChannelOffsets[BackLeft] = 4;
1491 device->ChannelOffsets[BackRight] = 5;
1492 break;
1493 case DevFmtX51Side: device->ChannelOffsets[FrontLeft] = 0;
1494 device->ChannelOffsets[FrontRight] = 1;
1495 device->ChannelOffsets[FrontCenter] = 2;
1496 device->ChannelOffsets[LFE] = 3;
1497 device->ChannelOffsets[SideLeft] = 4;
1498 device->ChannelOffsets[SideRight] = 5;
1499 break;
1500 case DevFmtX61: device->ChannelOffsets[FrontLeft] = 0;
1501 device->ChannelOffsets[FrontRight] = 1;
1502 device->ChannelOffsets[FrontCenter] = 2;
1503 device->ChannelOffsets[LFE] = 3;
1504 device->ChannelOffsets[BackCenter] = 4;
1505 device->ChannelOffsets[SideLeft] = 5;
1506 device->ChannelOffsets[SideRight] = 6;
1507 break;
1508 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1509 device->ChannelOffsets[FrontRight] = 1;
1510 device->ChannelOffsets[FrontCenter] = 2;
1511 device->ChannelOffsets[LFE] = 3;
1512 device->ChannelOffsets[BackLeft] = 4;
1513 device->ChannelOffsets[BackRight] = 5;
1514 device->ChannelOffsets[SideLeft] = 6;
1515 device->ChannelOffsets[SideRight] = 7;
1516 break;
1520 /* SetDefaultChannelOrder
1522 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1524 void SetDefaultChannelOrder(ALCdevice *device)
1526 ALuint i;
1528 for(i = 0;i < MaxChannels;i++)
1529 device->ChannelOffsets[i] = INVALID_OFFSET;
1531 switch(device->FmtChans)
1533 case DevFmtX51: device->ChannelOffsets[FrontLeft] = 0;
1534 device->ChannelOffsets[FrontRight] = 1;
1535 device->ChannelOffsets[BackLeft] = 2;
1536 device->ChannelOffsets[BackRight] = 3;
1537 device->ChannelOffsets[FrontCenter] = 4;
1538 device->ChannelOffsets[LFE] = 5;
1539 return;
1540 case DevFmtX71: device->ChannelOffsets[FrontLeft] = 0;
1541 device->ChannelOffsets[FrontRight] = 1;
1542 device->ChannelOffsets[BackLeft] = 2;
1543 device->ChannelOffsets[BackRight] = 3;
1544 device->ChannelOffsets[FrontCenter] = 4;
1545 device->ChannelOffsets[LFE] = 5;
1546 device->ChannelOffsets[SideLeft] = 6;
1547 device->ChannelOffsets[SideRight] = 7;
1548 return;
1550 /* Same as WFX order */
1551 case DevFmtMono:
1552 case DevFmtStereo:
1553 case DevFmtQuad:
1554 case DevFmtX51Side:
1555 case DevFmtX61:
1556 break;
1558 SetDefaultWFXChannelOrder(device);
1562 /* alcSetError
1564 * Stores the latest ALC device error
1566 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1568 if(TrapALCError)
1570 #ifdef _WIN32
1571 /* DebugBreak() will cause an exception if there is no debugger */
1572 if(IsDebuggerPresent())
1573 DebugBreak();
1574 #elif defined(SIGTRAP)
1575 raise(SIGTRAP);
1576 #endif
1579 if(device)
1580 device->LastError = errorCode;
1581 else
1582 LastNullDeviceError = errorCode;
1586 /* UpdateClockBase
1588 * Updates the device's base clock time with however many samples have been
1589 * done. This is used so frequency changes on the device don't cause the time
1590 * to jump forward or back.
1592 static inline void UpdateClockBase(ALCdevice *device)
1594 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1595 device->SamplesDone = 0;
1598 /* UpdateDeviceParams
1600 * Updates device parameters according to the attribute list (caller is
1601 * responsible for holding the list lock).
1603 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1605 ALCcontext *context;
1606 enum DevFmtChannels oldChans;
1607 enum DevFmtType oldType;
1608 ALCuint oldFreq;
1609 FPUCtl oldMode;
1611 // Check for attributes
1612 if(device->Type == Loopback)
1614 enum {
1615 GotFreq = 1<<0,
1616 GotChans = 1<<1,
1617 GotType = 1<<2,
1618 GotAll = GotFreq|GotChans|GotType
1620 ALCuint freq, numMono, numStereo, numSends;
1621 enum DevFmtChannels schans;
1622 enum DevFmtType stype;
1623 ALCuint attrIdx = 0;
1624 ALCint gotFmt = 0;
1626 if(!attrList)
1628 WARN("Missing attributes for loopback device\n");
1629 return ALC_INVALID_VALUE;
1632 numMono = device->NumMonoSources;
1633 numStereo = device->NumStereoSources;
1634 numSends = device->NumAuxSends;
1635 schans = device->FmtChans;
1636 stype = device->FmtType;
1637 freq = device->Frequency;
1639 while(attrList[attrIdx])
1641 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1643 ALCint val = attrList[attrIdx + 1];
1644 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1645 return ALC_INVALID_VALUE;
1646 schans = val;
1647 gotFmt |= GotChans;
1650 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1652 ALCint val = attrList[attrIdx + 1];
1653 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1654 return ALC_INVALID_VALUE;
1655 stype = val;
1656 gotFmt |= GotType;
1659 if(attrList[attrIdx] == ALC_FREQUENCY)
1661 freq = attrList[attrIdx + 1];
1662 if(freq < MIN_OUTPUT_RATE)
1663 return ALC_INVALID_VALUE;
1664 gotFmt |= GotFreq;
1667 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1669 numStereo = attrList[attrIdx + 1];
1670 if(numStereo > device->MaxNoOfSources)
1671 numStereo = device->MaxNoOfSources;
1673 numMono = device->MaxNoOfSources - numStereo;
1676 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1677 numSends = attrList[attrIdx + 1];
1679 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1681 if(attrList[attrIdx + 1] != ALC_FALSE)
1682 device->Flags |= DEVICE_HRTF_REQUEST;
1683 else
1684 device->Flags &= ~DEVICE_HRTF_REQUEST;
1687 attrIdx += 2;
1690 if(gotFmt != GotAll)
1692 WARN("Missing format for loopback device\n");
1693 return ALC_INVALID_VALUE;
1696 ConfigValueUInt(NULL, "sends", &numSends);
1697 numSends = minu(MAX_SENDS, numSends);
1699 if((device->Flags&DEVICE_RUNNING))
1700 V0(device->Backend,stop)();
1701 device->Flags &= ~DEVICE_RUNNING;
1703 if(freq != device->Frequency)
1704 UpdateClockBase(device);
1705 device->Frequency = freq;
1706 device->FmtChans = schans;
1707 device->FmtType = stype;
1708 device->NumMonoSources = numMono;
1709 device->NumStereoSources = numStereo;
1710 device->NumAuxSends = numSends;
1712 else if(attrList && attrList[0])
1714 ALCuint freq, numMono, numStereo, numSends;
1715 ALCuint attrIdx = 0;
1717 /* If a context is already running on the device, stop playback so the
1718 * device attributes can be updated. */
1719 if((device->Flags&DEVICE_RUNNING))
1720 V0(device->Backend,stop)();
1721 device->Flags &= ~DEVICE_RUNNING;
1723 freq = device->Frequency;
1724 numMono = device->NumMonoSources;
1725 numStereo = device->NumStereoSources;
1726 numSends = device->NumAuxSends;
1728 while(attrList[attrIdx])
1730 if(attrList[attrIdx] == ALC_FREQUENCY)
1732 freq = attrList[attrIdx + 1];
1733 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1736 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1738 numStereo = attrList[attrIdx + 1];
1739 if(numStereo > device->MaxNoOfSources)
1740 numStereo = device->MaxNoOfSources;
1742 numMono = device->MaxNoOfSources - numStereo;
1745 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1746 numSends = attrList[attrIdx + 1];
1748 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1750 if(attrList[attrIdx + 1] != ALC_FALSE)
1751 device->Flags |= DEVICE_HRTF_REQUEST;
1752 else
1753 device->Flags &= ~DEVICE_HRTF_REQUEST;
1756 attrIdx += 2;
1759 ConfigValueUInt(NULL, "frequency", &freq);
1760 freq = maxu(freq, MIN_OUTPUT_RATE);
1762 ConfigValueUInt(NULL, "sends", &numSends);
1763 numSends = minu(MAX_SENDS, numSends);
1765 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1766 device->Frequency;
1767 /* SSE and Neon do best with the update size being a multiple of 4 */
1768 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1769 device->UpdateSize = (device->UpdateSize+3)&~3;
1771 if(freq != device->Frequency)
1772 UpdateClockBase(device);
1773 device->Frequency = freq;
1774 device->NumMonoSources = numMono;
1775 device->NumStereoSources = numStereo;
1776 device->NumAuxSends = numSends;
1779 if((device->Flags&DEVICE_RUNNING))
1780 return ALC_NO_ERROR;
1782 UpdateClockBase(device);
1784 oldFreq = device->Frequency;
1785 oldChans = device->FmtChans;
1786 oldType = device->FmtType;
1788 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1789 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"",
1790 DevFmtChannelsString(device->FmtChans),
1791 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"",
1792 DevFmtTypeString(device->FmtType),
1793 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"",
1794 device->Frequency,
1795 device->UpdateSize, device->NumUpdates);
1797 if(device->Type != Loopback)
1799 int nohrtf = !(device->Flags&DEVICE_HRTF_REQUEST);
1800 if(GetConfigValueBool(NULL, "hrtf", !nohrtf))
1801 device->Flags |= DEVICE_HRTF_REQUEST;
1802 else
1803 device->Flags &= ~DEVICE_HRTF_REQUEST;
1805 if((device->Flags&DEVICE_HRTF_REQUEST))
1807 enum DevFmtChannels chans;
1808 ALCuint freq;
1809 if(FindHrtfFormat(device, &chans, &freq))
1811 device->Frequency = freq;
1812 device->FmtChans = chans;
1813 device->Flags |= DEVICE_CHANNELS_REQUEST |
1814 DEVICE_FREQUENCY_REQUEST;
1818 if(V0(device->Backend,reset)() == ALC_FALSE)
1819 return ALC_INVALID_DEVICE;
1821 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1823 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1824 DevFmtChannelsString(device->FmtChans));
1825 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1827 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1829 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1830 DevFmtTypeString(device->FmtType));
1831 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1833 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1835 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1836 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1839 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1840 DevFmtChannelsString(device->FmtChans),
1841 DevFmtTypeString(device->FmtType), device->Frequency,
1842 device->UpdateSize, device->NumUpdates);
1844 aluInitPanning(device);
1846 V(device->Synth,update)(device);
1848 device->Hrtf = NULL;
1849 if((device->Flags&DEVICE_HRTF_REQUEST))
1851 device->Hrtf = GetHrtf(device);
1852 if(!device->Hrtf)
1853 device->Flags &= ~DEVICE_HRTF_REQUEST;
1855 TRACE("HRTF %s\n", device->Hrtf?"enabled":"disabled");
1857 if(!device->Hrtf && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1859 if(!device->Bs2b)
1861 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1862 bs2b_clear(device->Bs2b);
1864 bs2b_set_srate(device->Bs2b, device->Frequency);
1865 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1866 TRACE("BS2B level %d\n", device->Bs2bLevel);
1868 else
1870 free(device->Bs2b);
1871 device->Bs2b = NULL;
1872 TRACE("BS2B disabled\n");
1875 device->Flags &= ~DEVICE_WIDE_STEREO;
1876 if(device->Type != Loopback && !device->Hrtf && GetConfigValueBool(NULL, "wide-stereo", AL_FALSE))
1877 device->Flags |= DEVICE_WIDE_STEREO;
1879 if(!device->Hrtf && (device->UpdateSize&3))
1881 if((CPUCapFlags&CPU_CAP_SSE))
1882 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1883 if((CPUCapFlags&CPU_CAP_NEON))
1884 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1887 SetMixerFPUMode(&oldMode);
1888 ALCdevice_Lock(device);
1889 context = device->ContextList;
1890 while(context)
1892 ALsizei pos;
1894 context->UpdateSources = AL_FALSE;
1895 LockUIntMapRead(&context->EffectSlotMap);
1896 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
1898 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
1900 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1902 UnlockUIntMapRead(&context->EffectSlotMap);
1903 ALCdevice_Unlock(device);
1904 RestoreFPUMode(&oldMode);
1905 return ALC_INVALID_DEVICE;
1907 slot->NeedsUpdate = AL_FALSE;
1908 V(slot->EffectState,update)(device, slot);
1910 UnlockUIntMapRead(&context->EffectSlotMap);
1912 LockUIntMapRead(&context->SourceMap);
1913 for(pos = 0;pos < context->SourceMap.size;pos++)
1915 ALsource *source = context->SourceMap.array[pos].value;
1916 ALuint s = device->NumAuxSends;
1917 while(s < MAX_SENDS)
1919 if(source->Send[s].Slot)
1920 DecrementRef(&source->Send[s].Slot->ref);
1921 source->Send[s].Slot = NULL;
1922 source->Send[s].Gain = 1.0f;
1923 source->Send[s].GainHF = 1.0f;
1924 s++;
1926 source->NeedsUpdate = AL_TRUE;
1928 UnlockUIntMapRead(&context->SourceMap);
1930 for(pos = 0;pos < context->ActiveSourceCount;pos++)
1932 ALactivesource *src = context->ActiveSources[pos];
1933 ALsource *source = src->Source;
1934 ALuint s = device->NumAuxSends;
1935 while(s < MAX_SENDS)
1937 src->Send[s].Moving = AL_FALSE;
1938 src->Send[s].Counter = 0;
1939 s++;
1942 src->Update(src, context);
1943 source->NeedsUpdate = AL_FALSE;
1946 context = context->next;
1948 if(device->DefaultSlot)
1950 ALeffectslot *slot = device->DefaultSlot;
1952 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
1954 ALCdevice_Unlock(device);
1955 RestoreFPUMode(&oldMode);
1956 return ALC_INVALID_DEVICE;
1958 slot->NeedsUpdate = AL_FALSE;
1959 V(slot->EffectState,update)(device, slot);
1961 ALCdevice_Unlock(device);
1962 RestoreFPUMode(&oldMode);
1964 if(!(device->Flags&DEVICE_PAUSED))
1966 if(V0(device->Backend,start)() == ALC_FALSE)
1967 return ALC_INVALID_DEVICE;
1968 device->Flags |= DEVICE_RUNNING;
1971 return ALC_NO_ERROR;
1974 /* FreeDevice
1976 * Frees the device structure, and destroys any objects the app failed to
1977 * delete. Called once there's no more references on the device.
1979 static ALCvoid FreeDevice(ALCdevice *device)
1981 TRACE("%p\n", device);
1983 V0(device->Backend,close)();
1984 DELETE_OBJ(device->Backend);
1985 device->Backend = NULL;
1987 DELETE_OBJ(device->Synth);
1988 device->Synth = NULL;
1990 if(device->DefaultSlot)
1992 ALeffectState *state = device->DefaultSlot->EffectState;
1993 device->DefaultSlot = NULL;
1994 DELETE_OBJ(state);
1997 if(device->DefaultSfont)
1998 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
1999 device->DefaultSfont = NULL;
2001 if(device->BufferMap.size > 0)
2003 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2004 ReleaseALBuffers(device);
2006 ResetUIntMap(&device->BufferMap);
2008 if(device->EffectMap.size > 0)
2010 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2011 ReleaseALEffects(device);
2013 ResetUIntMap(&device->EffectMap);
2015 if(device->FilterMap.size > 0)
2017 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2018 ReleaseALFilters(device);
2020 ResetUIntMap(&device->FilterMap);
2022 if(device->SfontMap.size > 0)
2024 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2025 ReleaseALSoundfonts(device);
2027 ResetUIntMap(&device->SfontMap);
2029 if(device->PresetMap.size > 0)
2031 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2032 ReleaseALPresets(device);
2034 ResetUIntMap(&device->PresetMap);
2036 if(device->FontsoundMap.size > 0)
2038 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2039 ReleaseALFontsounds(device);
2041 ResetUIntMap(&device->FontsoundMap);
2043 free(device->Bs2b);
2044 device->Bs2b = NULL;
2046 free(device->DeviceName);
2047 device->DeviceName = NULL;
2049 al_free(device);
2053 void ALCdevice_IncRef(ALCdevice *device)
2055 RefCount ref;
2056 ref = IncrementRef(&device->ref);
2057 TRACEREF("%p increasing refcount to %u\n", device, ref);
2060 void ALCdevice_DecRef(ALCdevice *device)
2062 RefCount ref;
2063 ref = DecrementRef(&device->ref);
2064 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2065 if(ref == 0) FreeDevice(device);
2068 /* VerifyDevice
2070 * Checks if the device handle is valid, and increments its ref count if so.
2072 static ALCdevice *VerifyDevice(ALCdevice *device)
2074 ALCdevice *tmpDevice;
2076 if(!device)
2077 return NULL;
2079 LockLists();
2080 tmpDevice = DeviceList;
2081 while(tmpDevice && tmpDevice != device)
2082 tmpDevice = tmpDevice->next;
2084 if(tmpDevice)
2085 ALCdevice_IncRef(tmpDevice);
2086 UnlockLists();
2087 return tmpDevice;
2091 /* InitContext
2093 * Initializes context fields
2095 static ALvoid InitContext(ALCcontext *Context)
2097 ALint i, j;
2099 //Initialise listener
2100 Context->Listener->Gain = 1.0f;
2101 Context->Listener->MetersPerUnit = 1.0f;
2102 Context->Listener->Position[0] = 0.0f;
2103 Context->Listener->Position[1] = 0.0f;
2104 Context->Listener->Position[2] = 0.0f;
2105 Context->Listener->Velocity[0] = 0.0f;
2106 Context->Listener->Velocity[1] = 0.0f;
2107 Context->Listener->Velocity[2] = 0.0f;
2108 Context->Listener->Forward[0] = 0.0f;
2109 Context->Listener->Forward[1] = 0.0f;
2110 Context->Listener->Forward[2] = -1.0f;
2111 Context->Listener->Up[0] = 0.0f;
2112 Context->Listener->Up[1] = 1.0f;
2113 Context->Listener->Up[2] = 0.0f;
2114 for(i = 0;i < 4;i++)
2116 for(j = 0;j < 4;j++)
2117 Context->Listener->Params.Matrix[i][j] = ((i==j) ? 1.0f : 0.0f);
2119 for(i = 0;i < 3;i++)
2120 Context->Listener->Params.Velocity[i] = 0.0f;
2122 //Validate Context
2123 Context->LastError = AL_NO_ERROR;
2124 Context->UpdateSources = AL_FALSE;
2125 Context->ActiveSourceCount = 0;
2126 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2127 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2129 //Set globals
2130 Context->DistanceModel = DefaultDistanceModel;
2131 Context->SourceDistanceModel = AL_FALSE;
2132 Context->DopplerFactor = 1.0f;
2133 Context->DopplerVelocity = 1.0f;
2134 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2135 Context->DeferUpdates = AL_FALSE;
2137 Context->ExtensionList = alExtList;
2141 /* FreeContext
2143 * Cleans up the context, and destroys any remaining objects the app failed to
2144 * delete. Called once there's no more references on the context.
2146 static ALCvoid FreeContext(ALCcontext *context)
2148 ALsizei i;
2150 TRACE("%p\n", context);
2152 if(context->SourceMap.size > 0)
2154 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2155 ReleaseALSources(context);
2157 ResetUIntMap(&context->SourceMap);
2159 if(context->EffectSlotMap.size > 0)
2161 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2162 ReleaseALAuxiliaryEffectSlots(context);
2164 ResetUIntMap(&context->EffectSlotMap);
2166 for(i = 0;i < context->MaxActiveSources;i++)
2168 al_free(context->ActiveSources[i]);
2169 context->ActiveSources[i] = NULL;
2171 free(context->ActiveSources);
2172 context->ActiveSources = NULL;
2173 context->ActiveSourceCount = 0;
2174 context->MaxActiveSources = 0;
2176 VECTOR_DEINIT(context->ActiveAuxSlots);
2178 ALCdevice_DecRef(context->Device);
2179 context->Device = NULL;
2181 //Invalidate context
2182 memset(context, 0, sizeof(ALCcontext));
2183 free(context);
2186 /* ReleaseContext
2188 * Removes the context reference from the given device and removes it from
2189 * being current on the running thread or globally.
2191 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2193 ALCcontext *volatile*tmp_ctx;
2195 if(althread_getspecific(LocalContext) == context)
2197 WARN("%p released while current on thread\n", context);
2198 althread_setspecific(LocalContext, NULL);
2199 ALCcontext_DecRef(context);
2202 if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL) == context)
2203 ALCcontext_DecRef(context);
2205 ALCdevice_Lock(device);
2206 tmp_ctx = &device->ContextList;
2207 while(*tmp_ctx)
2209 if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next) == context)
2210 break;
2211 tmp_ctx = &(*tmp_ctx)->next;
2213 ALCdevice_Unlock(device);
2215 ALCcontext_DecRef(context);
2218 void ALCcontext_IncRef(ALCcontext *context)
2220 RefCount ref;
2221 ref = IncrementRef(&context->ref);
2222 TRACEREF("%p increasing refcount to %u\n", context, ref);
2225 void ALCcontext_DecRef(ALCcontext *context)
2227 RefCount ref;
2228 ref = DecrementRef(&context->ref);
2229 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2230 if(ref == 0) FreeContext(context);
2233 static void ReleaseThreadCtx(void *ptr)
2235 WARN("%p current for thread being destroyed\n", ptr);
2236 ALCcontext_DecRef(ptr);
2239 /* VerifyContext
2241 * Checks that the given context is valid, and increments its reference count.
2243 static ALCcontext *VerifyContext(ALCcontext *context)
2245 ALCdevice *dev;
2247 LockLists();
2248 dev = DeviceList;
2249 while(dev)
2251 ALCcontext *tmp_ctx = dev->ContextList;
2252 while(tmp_ctx)
2254 if(tmp_ctx == context)
2256 ALCcontext_IncRef(tmp_ctx);
2257 UnlockLists();
2258 return tmp_ctx;
2260 tmp_ctx = tmp_ctx->next;
2262 dev = dev->next;
2264 UnlockLists();
2266 return NULL;
2270 /* GetContextRef
2272 * Returns the currently active context for this thread, and adds a reference
2273 * without locking it.
2275 ALCcontext *GetContextRef(void)
2277 ALCcontext *context;
2279 context = althread_getspecific(LocalContext);
2280 if(context)
2281 ALCcontext_IncRef(context);
2282 else
2284 LockLists();
2285 context = GlobalContext;
2286 if(context)
2287 ALCcontext_IncRef(context);
2288 UnlockLists();
2291 return context;
2295 /************************************************
2296 * Standard ALC functions
2297 ************************************************/
2299 /* alcGetError
2301 * Return last ALC generated error code for the given device
2303 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2305 ALCenum errorCode;
2307 if(VerifyDevice(device))
2309 errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR);
2310 ALCdevice_DecRef(device);
2312 else
2313 errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR);
2315 return errorCode;
2319 /* alcSuspendContext
2321 * Not functional
2323 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *UNUSED(context))
2327 /* alcProcessContext
2329 * Not functional
2331 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *UNUSED(context))
2336 /* alcGetString
2338 * Returns information about the device, and error strings
2340 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2342 const ALCchar *value = NULL;
2344 switch(param)
2346 case ALC_NO_ERROR:
2347 value = alcNoError;
2348 break;
2350 case ALC_INVALID_ENUM:
2351 value = alcErrInvalidEnum;
2352 break;
2354 case ALC_INVALID_VALUE:
2355 value = alcErrInvalidValue;
2356 break;
2358 case ALC_INVALID_DEVICE:
2359 value = alcErrInvalidDevice;
2360 break;
2362 case ALC_INVALID_CONTEXT:
2363 value = alcErrInvalidContext;
2364 break;
2366 case ALC_OUT_OF_MEMORY:
2367 value = alcErrOutOfMemory;
2368 break;
2370 case ALC_DEVICE_SPECIFIER:
2371 value = alcDefaultName;
2372 break;
2374 case ALC_ALL_DEVICES_SPECIFIER:
2375 if(VerifyDevice(Device))
2377 value = Device->DeviceName;
2378 ALCdevice_DecRef(Device);
2380 else
2382 ProbeAllDevicesList();
2383 value = alcAllDevicesList;
2385 break;
2387 case ALC_CAPTURE_DEVICE_SPECIFIER:
2388 if(VerifyDevice(Device))
2390 value = Device->DeviceName;
2391 ALCdevice_DecRef(Device);
2393 else
2395 ProbeCaptureDeviceList();
2396 value = alcCaptureDeviceList;
2398 break;
2400 /* Default devices are always first in the list */
2401 case ALC_DEFAULT_DEVICE_SPECIFIER:
2402 value = alcDefaultName;
2403 break;
2405 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2406 if(!alcAllDevicesList)
2407 ProbeAllDevicesList();
2409 Device = VerifyDevice(Device);
2411 free(alcDefaultAllDevicesSpecifier);
2412 alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ?
2413 alcAllDevicesList : "");
2414 if(!alcDefaultAllDevicesSpecifier)
2415 alcSetError(Device, ALC_OUT_OF_MEMORY);
2417 value = alcDefaultAllDevicesSpecifier;
2418 if(Device) ALCdevice_DecRef(Device);
2419 break;
2421 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2422 if(!alcCaptureDeviceList)
2423 ProbeCaptureDeviceList();
2425 Device = VerifyDevice(Device);
2427 free(alcCaptureDefaultDeviceSpecifier);
2428 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
2429 alcCaptureDeviceList : "");
2430 if(!alcCaptureDefaultDeviceSpecifier)
2431 alcSetError(Device, ALC_OUT_OF_MEMORY);
2433 value = alcCaptureDefaultDeviceSpecifier;
2434 if(Device) ALCdevice_DecRef(Device);
2435 break;
2437 case ALC_EXTENSIONS:
2438 if(!VerifyDevice(Device))
2439 value = alcNoDeviceExtList;
2440 else
2442 value = alcExtensionList;
2443 ALCdevice_DecRef(Device);
2445 break;
2447 default:
2448 Device = VerifyDevice(Device);
2449 alcSetError(Device, ALC_INVALID_ENUM);
2450 if(Device) ALCdevice_DecRef(Device);
2451 break;
2454 return value;
2458 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2460 ALCsizei i;
2462 if(size <= 0 || values == NULL)
2464 alcSetError(device, ALC_INVALID_VALUE);
2465 return 0;
2468 if(!device)
2470 switch(param)
2472 case ALC_MAJOR_VERSION:
2473 values[0] = alcMajorVersion;
2474 return 1;
2475 case ALC_MINOR_VERSION:
2476 values[0] = alcMinorVersion;
2477 return 1;
2479 case ALC_ATTRIBUTES_SIZE:
2480 case ALC_ALL_ATTRIBUTES:
2481 case ALC_FREQUENCY:
2482 case ALC_REFRESH:
2483 case ALC_SYNC:
2484 case ALC_MONO_SOURCES:
2485 case ALC_STEREO_SOURCES:
2486 case ALC_CAPTURE_SAMPLES:
2487 case ALC_FORMAT_CHANNELS_SOFT:
2488 case ALC_FORMAT_TYPE_SOFT:
2489 alcSetError(NULL, ALC_INVALID_DEVICE);
2490 return 0;
2492 default:
2493 alcSetError(NULL, ALC_INVALID_ENUM);
2494 return 0;
2496 return 0;
2499 if(device->Type == Capture)
2501 switch(param)
2503 case ALC_CAPTURE_SAMPLES:
2504 ALCdevice_Lock(device);
2505 values[0] = V0(device->Backend,availableSamples)();
2506 ALCdevice_Unlock(device);
2507 return 1;
2509 case ALC_CONNECTED:
2510 values[0] = device->Connected;
2511 return 1;
2513 default:
2514 alcSetError(device, ALC_INVALID_ENUM);
2515 return 0;
2517 return 0;
2520 /* render device */
2521 switch(param)
2523 case ALC_MAJOR_VERSION:
2524 values[0] = alcMajorVersion;
2525 return 1;
2527 case ALC_MINOR_VERSION:
2528 values[0] = alcMinorVersion;
2529 return 1;
2531 case ALC_EFX_MAJOR_VERSION:
2532 values[0] = alcEFXMajorVersion;
2533 return 1;
2535 case ALC_EFX_MINOR_VERSION:
2536 values[0] = alcEFXMinorVersion;
2537 return 1;
2539 case ALC_ATTRIBUTES_SIZE:
2540 values[0] = 15;
2541 return 1;
2543 case ALC_ALL_ATTRIBUTES:
2544 if(size < 15)
2546 alcSetError(device, ALC_INVALID_VALUE);
2547 return 0;
2550 i = 0;
2551 values[i++] = ALC_FREQUENCY;
2552 values[i++] = device->Frequency;
2554 if(device->Type != Loopback)
2556 values[i++] = ALC_REFRESH;
2557 values[i++] = device->Frequency / device->UpdateSize;
2559 values[i++] = ALC_SYNC;
2560 values[i++] = ALC_FALSE;
2562 else
2564 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2565 values[i++] = device->FmtChans;
2567 values[i++] = ALC_FORMAT_TYPE_SOFT;
2568 values[i++] = device->FmtType;
2571 values[i++] = ALC_MONO_SOURCES;
2572 values[i++] = device->NumMonoSources;
2574 values[i++] = ALC_STEREO_SOURCES;
2575 values[i++] = device->NumStereoSources;
2577 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2578 values[i++] = device->NumAuxSends;
2580 values[i++] = ALC_HRTF_SOFT;
2581 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2583 values[i++] = 0;
2584 return i;
2586 case ALC_FREQUENCY:
2587 values[0] = device->Frequency;
2588 return 1;
2590 case ALC_REFRESH:
2591 if(device->Type == Loopback)
2593 alcSetError(device, ALC_INVALID_DEVICE);
2594 return 0;
2596 values[0] = device->Frequency / device->UpdateSize;
2597 return 1;
2599 case ALC_SYNC:
2600 if(device->Type == Loopback)
2602 alcSetError(device, ALC_INVALID_DEVICE);
2603 return 0;
2605 values[0] = ALC_FALSE;
2606 return 1;
2608 case ALC_FORMAT_CHANNELS_SOFT:
2609 if(device->Type != Loopback)
2611 alcSetError(device, ALC_INVALID_DEVICE);
2612 return 0;
2614 values[0] = device->FmtChans;
2615 return 1;
2617 case ALC_FORMAT_TYPE_SOFT:
2618 if(device->Type != Loopback)
2620 alcSetError(device, ALC_INVALID_DEVICE);
2621 return 0;
2623 values[0] = device->FmtType;
2624 return 1;
2626 case ALC_MONO_SOURCES:
2627 values[0] = device->NumMonoSources;
2628 return 1;
2630 case ALC_STEREO_SOURCES:
2631 values[0] = device->NumStereoSources;
2632 return 1;
2634 case ALC_MAX_AUXILIARY_SENDS:
2635 values[0] = device->NumAuxSends;
2636 return 1;
2638 case ALC_CONNECTED:
2639 values[0] = device->Connected;
2640 return 1;
2642 case ALC_HRTF_SOFT:
2643 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2644 return 1;
2646 default:
2647 alcSetError(device, ALC_INVALID_ENUM);
2648 return 0;
2650 return 0;
2653 /* alcGetIntegerv
2655 * Returns information about the device and the version of OpenAL
2657 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2659 device = VerifyDevice(device);
2660 if(size <= 0 || values == NULL)
2661 alcSetError(device, ALC_INVALID_VALUE);
2662 else
2663 GetIntegerv(device, param, size, values);
2664 if(device) ALCdevice_DecRef(device);
2667 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2669 ALCint *ivals;
2670 ALsizei i;
2672 device = VerifyDevice(device);
2673 if(size <= 0 || values == NULL)
2674 alcSetError(device, ALC_INVALID_VALUE);
2675 else if(!device || device->Type == Capture)
2677 ivals = malloc(size * sizeof(ALCint));
2678 size = GetIntegerv(device, pname, size, ivals);
2679 for(i = 0;i < size;i++)
2680 values[i] = ivals[i];
2681 free(ivals);
2683 else /* render device */
2685 switch(pname)
2687 case ALC_ATTRIBUTES_SIZE:
2688 *values = 17;
2689 break;
2691 case ALC_ALL_ATTRIBUTES:
2692 if(size < 17)
2693 alcSetError(device, ALC_INVALID_VALUE);
2694 else
2696 int i = 0;
2698 V0(device->Backend,lock)();
2699 values[i++] = ALC_FREQUENCY;
2700 values[i++] = device->Frequency;
2702 if(device->Type != Loopback)
2704 values[i++] = ALC_REFRESH;
2705 values[i++] = device->Frequency / device->UpdateSize;
2707 values[i++] = ALC_SYNC;
2708 values[i++] = ALC_FALSE;
2710 else
2712 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2713 values[i++] = device->FmtChans;
2715 values[i++] = ALC_FORMAT_TYPE_SOFT;
2716 values[i++] = device->FmtType;
2719 values[i++] = ALC_MONO_SOURCES;
2720 values[i++] = device->NumMonoSources;
2722 values[i++] = ALC_STEREO_SOURCES;
2723 values[i++] = device->NumStereoSources;
2725 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2726 values[i++] = device->NumAuxSends;
2728 values[i++] = ALC_HRTF_SOFT;
2729 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2731 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2732 values[i++] = device->ClockBase +
2733 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2735 values[i++] = 0;
2736 V0(device->Backend,unlock)();
2738 break;
2740 case ALC_DEVICE_CLOCK_SOFT:
2741 V0(device->Backend,lock)();
2742 *values = device->ClockBase +
2743 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2744 V0(device->Backend,unlock)();
2745 break;
2747 default:
2748 ivals = malloc(size * sizeof(ALCint));
2749 size = GetIntegerv(device, pname, size, ivals);
2750 for(i = 0;i < size;i++)
2751 values[i] = ivals[i];
2752 free(ivals);
2753 break;
2756 if(device)
2757 ALCdevice_DecRef(device);
2761 /* alcIsExtensionPresent
2763 * Determines if there is support for a particular extension
2765 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2767 ALCboolean bResult = ALC_FALSE;
2769 device = VerifyDevice(device);
2771 if(!extName)
2772 alcSetError(device, ALC_INVALID_VALUE);
2773 else
2775 size_t len = strlen(extName);
2776 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2777 while(ptr && *ptr)
2779 if(strncasecmp(ptr, extName, len) == 0 &&
2780 (ptr[len] == '\0' || isspace(ptr[len])))
2782 bResult = ALC_TRUE;
2783 break;
2785 if((ptr=strchr(ptr, ' ')) != NULL)
2787 do {
2788 ++ptr;
2789 } while(isspace(*ptr));
2793 if(device)
2794 ALCdevice_DecRef(device);
2795 return bResult;
2799 /* alcGetProcAddress
2801 * Retrieves the function address for a particular extension function
2803 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2805 ALCvoid *ptr = NULL;
2807 if(!funcName)
2809 device = VerifyDevice(device);
2810 alcSetError(device, ALC_INVALID_VALUE);
2811 if(device) ALCdevice_DecRef(device);
2813 else
2815 ALsizei i = 0;
2816 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2817 i++;
2818 ptr = alcFunctions[i].address;
2821 return ptr;
2825 /* alcGetEnumValue
2827 * Get the value for a particular ALC enumeration name
2829 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
2831 ALCenum val = 0;
2833 if(!enumName)
2835 device = VerifyDevice(device);
2836 alcSetError(device, ALC_INVALID_VALUE);
2837 if(device) ALCdevice_DecRef(device);
2839 else
2841 ALsizei i = 0;
2842 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
2843 i++;
2844 val = enumeration[i].value;
2847 return val;
2851 /* alcCreateContext
2853 * Create and attach a context to the given device.
2855 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
2857 ALCcontext *ALContext;
2858 ALCenum err;
2860 LockLists();
2861 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
2863 UnlockLists();
2864 alcSetError(device, ALC_INVALID_DEVICE);
2865 if(device) ALCdevice_DecRef(device);
2866 return NULL;
2869 device->LastError = ALC_NO_ERROR;
2871 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
2873 UnlockLists();
2874 alcSetError(device, err);
2875 if(err == ALC_INVALID_DEVICE)
2877 ALCdevice_Lock(device);
2878 aluHandleDisconnect(device);
2879 ALCdevice_Unlock(device);
2881 ALCdevice_DecRef(device);
2882 return NULL;
2885 ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener));
2886 if(ALContext)
2888 ALContext->ref = 1;
2889 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
2891 VECTOR_INIT(ALContext->ActiveAuxSlots);
2893 ALContext->MaxActiveSources = 256;
2894 ALContext->ActiveSources = calloc(ALContext->MaxActiveSources,
2895 sizeof(ALContext->ActiveSources[0]));
2897 if(!ALContext || !ALContext->ActiveAuxSlots || !ALContext->ActiveSources)
2899 if(!device->ContextList)
2901 V0(device->Backend,stop)();
2902 device->Flags &= ~DEVICE_RUNNING;
2904 UnlockLists();
2906 if(ALContext)
2908 free(ALContext->ActiveSources);
2909 ALContext->ActiveSources = NULL;
2911 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
2913 free(ALContext);
2914 ALContext = NULL;
2917 alcSetError(device, ALC_OUT_OF_MEMORY);
2918 ALCdevice_DecRef(device);
2919 return NULL;
2922 ALContext->Device = device;
2923 ALCdevice_IncRef(device);
2924 InitContext(ALContext);
2926 do {
2927 ALContext->next = device->ContextList;
2928 } while(CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext) != ALContext->next);
2929 UnlockLists();
2931 ALCdevice_DecRef(device);
2933 TRACE("Created context %p\n", ALContext);
2934 return ALContext;
2937 /* alcDestroyContext
2939 * Remove a context from its device
2941 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
2943 ALCdevice *Device;
2945 LockLists();
2946 /* alcGetContextsDevice sets an error for invalid contexts */
2947 Device = alcGetContextsDevice(context);
2948 if(Device)
2950 ReleaseContext(context, Device);
2951 if(!Device->ContextList)
2953 V0(Device->Backend,stop)();
2954 Device->Flags &= ~DEVICE_RUNNING;
2957 UnlockLists();
2961 /* alcGetCurrentContext
2963 * Returns the currently active context on the calling thread
2965 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
2967 ALCcontext *Context;
2969 Context = althread_getspecific(LocalContext);
2970 if(!Context) Context = GlobalContext;
2972 return Context;
2975 /* alcGetThreadContext
2977 * Returns the currently active thread-local context
2979 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
2981 ALCcontext *Context;
2982 Context = althread_getspecific(LocalContext);
2983 return Context;
2987 /* alcMakeContextCurrent
2989 * Makes the given context the active process-wide context, and removes the
2990 * thread-local context for the calling thread.
2992 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
2994 /* context must be valid or NULL */
2995 if(context && !(context=VerifyContext(context)))
2997 alcSetError(NULL, ALC_INVALID_CONTEXT);
2998 return ALC_FALSE;
3000 /* context's reference count is already incremented */
3001 context = ExchangePtr((XchgPtr*)&GlobalContext, context);
3002 if(context) ALCcontext_DecRef(context);
3004 if((context=althread_getspecific(LocalContext)) != NULL)
3006 althread_setspecific(LocalContext, NULL);
3007 ALCcontext_DecRef(context);
3010 return ALC_TRUE;
3013 /* alcSetThreadContext
3015 * Makes the given context the active context for the current thread
3017 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3019 ALCcontext *old;
3021 /* context must be valid or NULL */
3022 if(context && !(context=VerifyContext(context)))
3024 alcSetError(NULL, ALC_INVALID_CONTEXT);
3025 return ALC_FALSE;
3027 /* context's reference count is already incremented */
3028 old = althread_getspecific(LocalContext);
3029 althread_setspecific(LocalContext, context);
3030 if(old) ALCcontext_DecRef(old);
3032 return ALC_TRUE;
3036 /* alcGetContextsDevice
3038 * Returns the device that a particular context is attached to
3040 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3042 ALCdevice *Device;
3044 if(!(Context=VerifyContext(Context)))
3046 alcSetError(NULL, ALC_INVALID_CONTEXT);
3047 return NULL;
3049 Device = Context->Device;
3050 ALCcontext_DecRef(Context);
3052 return Device;
3056 /* alcOpenDevice
3058 * Opens the named device.
3060 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3062 const ALCchar *fmt;
3063 ALCdevice *device;
3064 ALCenum err;
3066 DO_INITCONFIG();
3068 if(!PlaybackBackend.name)
3070 alcSetError(NULL, ALC_INVALID_VALUE);
3071 return NULL;
3074 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3075 deviceName = NULL;
3077 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3078 if(!device)
3080 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3081 return NULL;
3084 //Validate device
3085 device->ref = 1;
3086 device->Connected = ALC_TRUE;
3087 device->Type = Playback;
3088 device->LastError = ALC_NO_ERROR;
3090 device->Flags = 0;
3091 device->Bs2b = NULL;
3092 device->Bs2bLevel = 0;
3093 device->DeviceName = NULL;
3095 device->ContextList = NULL;
3097 device->ClockBase = 0;
3098 device->SamplesDone = 0;
3100 device->MaxNoOfSources = 256;
3101 device->AuxiliaryEffectSlotMax = 4;
3102 device->NumAuxSends = MAX_SENDS;
3104 InitUIntMap(&device->BufferMap, ~0);
3105 InitUIntMap(&device->EffectMap, ~0);
3106 InitUIntMap(&device->FilterMap, ~0);
3107 InitUIntMap(&device->SfontMap, ~0);
3108 InitUIntMap(&device->PresetMap, ~0);
3109 InitUIntMap(&device->FontsoundMap, ~0);
3111 //Set output format
3112 device->FmtChans = DevFmtChannelsDefault;
3113 device->FmtType = DevFmtTypeDefault;
3114 device->Frequency = DEFAULT_OUTPUT_RATE;
3115 device->NumUpdates = 4;
3116 device->UpdateSize = 1024;
3118 if(!PlaybackBackend.getFactory)
3119 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3120 ALCbackend_Playback);
3121 else
3123 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3124 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3126 if(!device->Backend)
3128 al_free(device);
3129 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3130 return NULL;
3134 if(ConfigValueStr(NULL, "channels", &fmt))
3136 static const struct {
3137 const char name[16];
3138 enum DevFmtChannels chans;
3139 } chanlist[] = {
3140 { "mono", DevFmtMono },
3141 { "stereo", DevFmtStereo },
3142 { "quad", DevFmtQuad },
3143 { "surround51", DevFmtX51 },
3144 { "surround61", DevFmtX61 },
3145 { "surround71", DevFmtX71 },
3147 size_t i;
3149 for(i = 0;i < COUNTOF(chanlist);i++)
3151 if(strcasecmp(chanlist[i].name, fmt) == 0)
3153 device->FmtChans = chanlist[i].chans;
3154 device->Flags |= DEVICE_CHANNELS_REQUEST;
3155 break;
3158 if(i == COUNTOF(chanlist))
3159 ERR("Unsupported channels: %s\n", fmt);
3161 if(ConfigValueStr(NULL, "sample-type", &fmt))
3163 static const struct {
3164 const char name[16];
3165 enum DevFmtType type;
3166 } typelist[] = {
3167 { "int8", DevFmtByte },
3168 { "uint8", DevFmtUByte },
3169 { "int16", DevFmtShort },
3170 { "uint16", DevFmtUShort },
3171 { "int32", DevFmtInt },
3172 { "uint32", DevFmtUInt },
3173 { "float32", DevFmtFloat },
3175 size_t i;
3177 for(i = 0;i < COUNTOF(typelist);i++)
3179 if(strcasecmp(typelist[i].name, fmt) == 0)
3181 device->FmtType = typelist[i].type;
3182 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3183 break;
3186 if(i == COUNTOF(typelist))
3187 ERR("Unsupported sample-type: %s\n", fmt);
3189 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
3190 if((device->Flags&DEVICE_FORMAT_REQUEST) != DEVICE_FORMAT_REQUEST &&
3191 ConfigValueStr(NULL, "format", &fmt))
3193 static const struct {
3194 const char name[32];
3195 enum DevFmtChannels channels;
3196 enum DevFmtType type;
3197 } formats[] = {
3198 { "AL_FORMAT_MONO32", DevFmtMono, DevFmtFloat },
3199 { "AL_FORMAT_STEREO32", DevFmtStereo, DevFmtFloat },
3200 { "AL_FORMAT_QUAD32", DevFmtQuad, DevFmtFloat },
3201 { "AL_FORMAT_51CHN32", DevFmtX51, DevFmtFloat },
3202 { "AL_FORMAT_61CHN32", DevFmtX61, DevFmtFloat },
3203 { "AL_FORMAT_71CHN32", DevFmtX71, DevFmtFloat },
3205 { "AL_FORMAT_MONO16", DevFmtMono, DevFmtShort },
3206 { "AL_FORMAT_STEREO16", DevFmtStereo, DevFmtShort },
3207 { "AL_FORMAT_QUAD16", DevFmtQuad, DevFmtShort },
3208 { "AL_FORMAT_51CHN16", DevFmtX51, DevFmtShort },
3209 { "AL_FORMAT_61CHN16", DevFmtX61, DevFmtShort },
3210 { "AL_FORMAT_71CHN16", DevFmtX71, DevFmtShort },
3212 { "AL_FORMAT_MONO8", DevFmtMono, DevFmtByte },
3213 { "AL_FORMAT_STEREO8", DevFmtStereo, DevFmtByte },
3214 { "AL_FORMAT_QUAD8", DevFmtQuad, DevFmtByte },
3215 { "AL_FORMAT_51CHN8", DevFmtX51, DevFmtByte },
3216 { "AL_FORMAT_61CHN8", DevFmtX61, DevFmtByte },
3217 { "AL_FORMAT_71CHN8", DevFmtX71, DevFmtByte }
3219 size_t i;
3221 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
3222 for(i = 0;i < COUNTOF(formats);i++)
3224 if(strcasecmp(fmt, formats[i].name) == 0)
3226 if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
3227 device->FmtChans = formats[i].channels;
3228 if(!(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
3229 device->FmtType = formats[i].type;
3230 device->Flags |= DEVICE_FORMAT_REQUEST;
3231 break;
3234 if(i == COUNTOF(formats))
3235 ERR("Unsupported format: %s\n", fmt);
3237 #undef DEVICE_FORMAT_REQUEST
3239 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3241 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3242 if(device->Frequency < MIN_OUTPUT_RATE)
3243 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3244 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3247 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3248 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3250 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3251 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3252 if((CPUCapFlags&CPU_CAP_SSE))
3253 device->UpdateSize = (device->UpdateSize+3)&~3;
3255 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3256 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3258 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3259 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3261 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3262 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3264 ConfigValueInt(NULL, "cf_level", &device->Bs2bLevel);
3266 device->NumStereoSources = 1;
3267 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3269 device->Synth = SynthCreate(device);
3270 if(!device->Synth)
3272 DELETE_OBJ(device->Backend);
3273 al_free(device);
3274 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3275 return NULL;
3278 // Find a playback device to open
3279 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3281 DELETE_OBJ(device->Synth);
3282 DELETE_OBJ(device->Backend);
3283 al_free(device);
3284 alcSetError(NULL, err);
3285 return NULL;
3288 if(DefaultEffect.type != AL_EFFECT_NULL)
3290 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3291 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3293 device->DefaultSlot = NULL;
3294 ERR("Failed to initialize the default effect slot\n");
3296 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3298 ALeffectState *state = device->DefaultSlot->EffectState;
3299 device->DefaultSlot = NULL;
3300 DELETE_OBJ(state);
3301 ERR("Failed to initialize the default effect\n");
3305 do {
3306 device->next = DeviceList;
3307 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3309 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
3310 return device;
3313 /* alcCloseDevice
3315 * Closes the given device.
3317 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
3319 ALCdevice *volatile*list;
3320 ALCcontext *ctx;
3322 LockLists();
3323 list = &DeviceList;
3324 while(*list && *list != Device)
3325 list = &(*list)->next;
3327 if(!*list || (*list)->Type == Capture)
3329 alcSetError(*list, ALC_INVALID_DEVICE);
3330 UnlockLists();
3331 return ALC_FALSE;
3334 *list = (*list)->next;
3335 UnlockLists();
3337 while((ctx=Device->ContextList) != NULL)
3339 WARN("Releasing context %p\n", ctx);
3340 ReleaseContext(ctx, Device);
3342 if((Device->Flags&DEVICE_RUNNING))
3343 V0(Device->Backend,stop)();
3344 Device->Flags &= ~DEVICE_RUNNING;
3346 ALCdevice_DecRef(Device);
3348 return ALC_TRUE;
3352 /************************************************
3353 * ALC capture functions
3354 ************************************************/
3355 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3357 ALCdevice *device = NULL;
3358 ALCenum err;
3360 DO_INITCONFIG();
3362 if(!CaptureBackend.name)
3364 alcSetError(NULL, ALC_INVALID_VALUE);
3365 return NULL;
3368 if(samples <= 0)
3370 alcSetError(NULL, ALC_INVALID_VALUE);
3371 return NULL;
3374 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3375 deviceName = NULL;
3377 device = al_calloc(16, sizeof(ALCdevice));
3378 if(!device)
3380 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3381 return NULL;
3384 //Validate device
3385 device->ref = 1;
3386 device->Connected = ALC_TRUE;
3387 device->Type = Capture;
3389 InitUIntMap(&device->BufferMap, ~0);
3390 InitUIntMap(&device->EffectMap, ~0);
3391 InitUIntMap(&device->FilterMap, ~0);
3392 InitUIntMap(&device->SfontMap, ~0);
3393 InitUIntMap(&device->PresetMap, ~0);
3394 InitUIntMap(&device->FontsoundMap, ~0);
3396 device->DeviceName = NULL;
3398 if(!CaptureBackend.getFactory)
3399 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3400 ALCbackend_Capture);
3401 else
3403 ALCbackendFactory *factory = CaptureBackend.getFactory();
3404 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3406 if(!device->Backend)
3408 al_free(device);
3409 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3410 return NULL;
3413 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3414 device->Frequency = frequency;
3416 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3417 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3419 al_free(device);
3420 alcSetError(NULL, ALC_INVALID_ENUM);
3421 return NULL;
3424 device->UpdateSize = samples;
3425 device->NumUpdates = 1;
3427 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3429 al_free(device);
3430 alcSetError(NULL, err);
3431 return NULL;
3434 do {
3435 device->next = DeviceList;
3436 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3438 TRACE("Created device %p, \"%s\"\n", device, device->DeviceName);
3439 return device;
3442 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
3444 ALCdevice *volatile*list;
3446 LockLists();
3447 list = &DeviceList;
3448 while(*list && *list != Device)
3449 list = &(*list)->next;
3451 if(!*list || (*list)->Type != Capture)
3453 alcSetError(*list, ALC_INVALID_DEVICE);
3454 UnlockLists();
3455 return ALC_FALSE;
3458 *list = (*list)->next;
3459 UnlockLists();
3461 ALCdevice_DecRef(Device);
3463 return ALC_TRUE;
3466 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3468 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3469 alcSetError(device, ALC_INVALID_DEVICE);
3470 else
3472 ALCdevice_Lock(device);
3473 if(device->Connected)
3475 if(!(device->Flags&DEVICE_RUNNING))
3476 V0(device->Backend,start)();
3477 device->Flags |= DEVICE_RUNNING;
3479 ALCdevice_Unlock(device);
3482 if(device) ALCdevice_DecRef(device);
3485 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3487 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3488 alcSetError(device, ALC_INVALID_DEVICE);
3489 else
3491 ALCdevice_Lock(device);
3492 if((device->Flags&DEVICE_RUNNING))
3493 V0(device->Backend,stop)();
3494 device->Flags &= ~DEVICE_RUNNING;
3495 ALCdevice_Unlock(device);
3498 if(device) ALCdevice_DecRef(device);
3501 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3503 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3504 alcSetError(device, ALC_INVALID_DEVICE);
3505 else
3507 ALCenum err = ALC_INVALID_VALUE;
3509 ALCdevice_Lock(device);
3510 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3511 err = V(device->Backend,captureSamples)(buffer, samples);
3512 ALCdevice_Unlock(device);
3514 if(err != ALC_NO_ERROR)
3515 alcSetError(device, err);
3517 if(device) ALCdevice_DecRef(device);
3521 /************************************************
3522 * ALC loopback functions
3523 ************************************************/
3525 /* alcLoopbackOpenDeviceSOFT
3527 * Open a loopback device, for manual rendering.
3529 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3531 ALCbackendFactory *factory;
3532 ALCdevice *device;
3534 DO_INITCONFIG();
3536 /* Make sure the device name, if specified, is us. */
3537 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3539 alcSetError(NULL, ALC_INVALID_VALUE);
3540 return NULL;
3543 device = al_calloc(16, sizeof(ALCdevice));
3544 if(!device)
3546 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3547 return NULL;
3550 //Validate device
3551 device->ref = 1;
3552 device->Connected = ALC_TRUE;
3553 device->Type = Loopback;
3554 device->LastError = ALC_NO_ERROR;
3556 device->Flags = 0;
3557 device->Bs2b = NULL;
3558 device->Bs2bLevel = 0;
3559 device->DeviceName = NULL;
3561 device->ContextList = NULL;
3563 device->ClockBase = 0;
3564 device->SamplesDone = 0;
3566 device->MaxNoOfSources = 256;
3567 device->AuxiliaryEffectSlotMax = 4;
3568 device->NumAuxSends = MAX_SENDS;
3570 InitUIntMap(&device->BufferMap, ~0);
3571 InitUIntMap(&device->EffectMap, ~0);
3572 InitUIntMap(&device->FilterMap, ~0);
3573 InitUIntMap(&device->SfontMap, ~0);
3574 InitUIntMap(&device->PresetMap, ~0);
3575 InitUIntMap(&device->FontsoundMap, ~0);
3577 factory = ALCloopbackFactory_getFactory();
3578 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3579 if(!device->Backend)
3581 al_free(device);
3582 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3583 return NULL;
3586 //Set output format
3587 device->NumUpdates = 0;
3588 device->UpdateSize = 0;
3590 device->Frequency = DEFAULT_OUTPUT_RATE;
3591 device->FmtChans = DevFmtChannelsDefault;
3592 device->FmtType = DevFmtTypeDefault;
3594 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3595 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3597 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3598 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3600 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3601 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3603 device->NumStereoSources = 1;
3604 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3606 device->Synth = SynthCreate(device);
3607 if(!device->Synth)
3609 DELETE_OBJ(device->Backend);
3610 al_free(device);
3611 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3612 return NULL;
3615 // Open the "backend"
3616 V(device->Backend,open)("Loopback");
3617 do {
3618 device->next = DeviceList;
3619 } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next);
3621 TRACE("Created device %p\n", device);
3622 return device;
3625 /* alcIsRenderFormatSupportedSOFT
3627 * Determines if the loopback device supports the given format for rendering.
3629 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3631 ALCboolean ret = ALC_FALSE;
3633 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3634 alcSetError(device, ALC_INVALID_DEVICE);
3635 else if(freq <= 0)
3636 alcSetError(device, ALC_INVALID_VALUE);
3637 else
3639 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3640 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3641 freq >= MIN_OUTPUT_RATE)
3642 ret = ALC_TRUE;
3644 if(device) ALCdevice_DecRef(device);
3646 return ret;
3649 /* alcRenderSamplesSOFT
3651 * Renders some samples into a buffer, using the format last set by the
3652 * attributes given to alcCreateContext.
3654 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3656 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3657 alcSetError(device, ALC_INVALID_DEVICE);
3658 else if(samples < 0 || (samples > 0 && buffer == NULL))
3659 alcSetError(device, ALC_INVALID_VALUE);
3660 else
3661 aluMixData(device, buffer, samples);
3662 if(device) ALCdevice_DecRef(device);
3666 /************************************************
3667 * ALC DSP pause/resume functions
3668 ************************************************/
3670 /* alcDevicePauseSOFT
3672 * Pause the DSP to stop audio processing.
3674 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3676 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3677 alcSetError(device, ALC_INVALID_DEVICE);
3678 else
3680 LockLists();
3681 if((device->Flags&DEVICE_RUNNING))
3682 V0(device->Backend,stop)();
3683 device->Flags &= ~DEVICE_RUNNING;
3684 device->Flags |= DEVICE_PAUSED;
3685 UnlockLists();
3687 if(device) ALCdevice_DecRef(device);
3690 /* alcDeviceResumeSOFT
3692 * Resume the DSP to restart audio processing.
3694 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3696 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3697 alcSetError(device, ALC_INVALID_DEVICE);
3698 else
3700 LockLists();
3701 if((device->Flags&DEVICE_PAUSED))
3703 if(V0(device->Backend,start)() != ALC_FALSE)
3705 device->Flags |= DEVICE_RUNNING;
3706 device->Flags &= ~DEVICE_PAUSED;
3708 else
3710 alcSetError(device, ALC_INVALID_DEVICE);
3711 ALCdevice_Lock(device);
3712 aluHandleDisconnect(device);
3713 ALCdevice_Unlock(device);
3716 UnlockLists();
3718 if(device) ALCdevice_DecRef(device);