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
32 #include "alListener.h"
36 #include "alAuxEffectSlot.h"
42 /************************************************
44 ************************************************/
45 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
46 static struct BackendInfo BackendList
[] = {
47 #ifdef HAVE_PULSEAUDIO
48 { "pulse", alc_pulse_init
, alc_pulse_deinit
, alc_pulse_probe
, EmptyFuncs
},
51 { "alsa", alc_alsa_init
, alc_alsa_deinit
, alc_alsa_probe
, EmptyFuncs
},
54 { "core", alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, EmptyFuncs
},
57 { "oss", alc_oss_init
, alc_oss_deinit
, alc_oss_probe
, EmptyFuncs
},
60 { "solaris", alc_solaris_init
, alc_solaris_deinit
, alc_solaris_probe
, EmptyFuncs
},
63 { "sndio", alc_sndio_init
, alc_sndio_deinit
, alc_sndio_probe
, EmptyFuncs
},
66 { "mmdevapi", alcMMDevApiInit
, alcMMDevApiDeinit
, alcMMDevApiProbe
, EmptyFuncs
},
69 { "dsound", alcDSoundInit
, alcDSoundDeinit
, alcDSoundProbe
, EmptyFuncs
},
72 { "winmm", alcWinMMInit
, alcWinMMDeinit
, alcWinMMProbe
, EmptyFuncs
},
75 { "port", alc_pa_init
, alc_pa_deinit
, alc_pa_probe
, EmptyFuncs
},
78 { "opensl", alc_opensl_init
, alc_opensl_deinit
, alc_opensl_probe
, EmptyFuncs
},
81 { "null", alc_null_init
, alc_null_deinit
, alc_null_probe
, EmptyFuncs
},
83 { "wave", alc_wave_init
, alc_wave_deinit
, alc_wave_probe
, EmptyFuncs
},
86 { NULL
, NULL
, NULL
, NULL
, EmptyFuncs
}
88 static struct BackendInfo BackendLoopback
= {
89 "loopback", alc_loopback_init
, alc_loopback_deinit
, alc_loopback_probe
, EmptyFuncs
93 static struct BackendInfo PlaybackBackend
;
94 static struct BackendInfo CaptureBackend
;
96 /************************************************
97 * Functions, enums, and errors
98 ************************************************/
99 typedef struct ALCfunction
{
100 const ALCchar
*funcName
;
104 typedef struct ALCenums
{
105 const ALCchar
*enumName
;
109 #define DECL(x) { #x, (ALCvoid*)(x) }
110 static const ALCfunction alcFunctions
[] = {
111 DECL(alcCreateContext
),
112 DECL(alcMakeContextCurrent
),
113 DECL(alcProcessContext
),
114 DECL(alcSuspendContext
),
115 DECL(alcDestroyContext
),
116 DECL(alcGetCurrentContext
),
117 DECL(alcGetContextsDevice
),
119 DECL(alcCloseDevice
),
121 DECL(alcIsExtensionPresent
),
122 DECL(alcGetProcAddress
),
123 DECL(alcGetEnumValue
),
125 DECL(alcGetIntegerv
),
126 DECL(alcCaptureOpenDevice
),
127 DECL(alcCaptureCloseDevice
),
128 DECL(alcCaptureStart
),
129 DECL(alcCaptureStop
),
130 DECL(alcCaptureSamples
),
132 DECL(alcSetThreadContext
),
133 DECL(alcGetThreadContext
),
135 DECL(alcLoopbackOpenDeviceSOFT
),
136 DECL(alcIsRenderFormatSupportedSOFT
),
137 DECL(alcRenderSamplesSOFT
),
152 DECL(alIsExtensionPresent
),
153 DECL(alGetProcAddress
),
154 DECL(alGetEnumValue
),
161 DECL(alGetListenerf
),
162 DECL(alGetListener3f
),
163 DECL(alGetListenerfv
),
164 DECL(alGetListeneri
),
165 DECL(alGetListener3i
),
166 DECL(alGetListeneriv
),
168 DECL(alDeleteSources
),
184 DECL(alSourceRewindv
),
185 DECL(alSourcePausev
),
188 DECL(alSourceRewind
),
190 DECL(alSourceQueueBuffers
),
191 DECL(alSourceUnqueueBuffers
),
193 DECL(alDeleteBuffers
),
208 DECL(alDopplerFactor
),
209 DECL(alDopplerVelocity
),
210 DECL(alSpeedOfSound
),
211 DECL(alDistanceModel
),
214 DECL(alDeleteFilters
),
225 DECL(alDeleteEffects
),
235 DECL(alGenAuxiliaryEffectSlots
),
236 DECL(alDeleteAuxiliaryEffectSlots
),
237 DECL(alIsAuxiliaryEffectSlot
),
238 DECL(alAuxiliaryEffectSloti
),
239 DECL(alAuxiliaryEffectSlotiv
),
240 DECL(alAuxiliaryEffectSlotf
),
241 DECL(alAuxiliaryEffectSlotfv
),
242 DECL(alGetAuxiliaryEffectSloti
),
243 DECL(alGetAuxiliaryEffectSlotiv
),
244 DECL(alGetAuxiliaryEffectSlotf
),
245 DECL(alGetAuxiliaryEffectSlotfv
),
247 DECL(alBufferSubDataSOFT
),
249 DECL(alBufferSamplesSOFT
),
250 DECL(alBufferSubSamplesSOFT
),
251 DECL(alGetBufferSamplesSOFT
),
252 DECL(alIsBufferFormatSupportedSOFT
),
254 DECL(alDeferUpdatesSOFT
),
255 DECL(alProcessUpdatesSOFT
),
258 DECL(alSource3dSOFT
),
259 DECL(alSourcedvSOFT
),
260 DECL(alGetSourcedSOFT
),
261 DECL(alGetSource3dSOFT
),
262 DECL(alGetSourcedvSOFT
),
263 DECL(alSourcei64SOFT
),
264 DECL(alSource3i64SOFT
),
265 DECL(alSourcei64vSOFT
),
266 DECL(alGetSourcei64SOFT
),
267 DECL(alGetSource3i64SOFT
),
268 DECL(alGetSourcei64vSOFT
),
274 #define DECL(x) { #x, (x) }
275 static const ALCenums enumeration
[] = {
280 DECL(ALC_MAJOR_VERSION
),
281 DECL(ALC_MINOR_VERSION
),
282 DECL(ALC_ATTRIBUTES_SIZE
),
283 DECL(ALC_ALL_ATTRIBUTES
),
284 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
285 DECL(ALC_DEVICE_SPECIFIER
),
286 DECL(ALC_ALL_DEVICES_SPECIFIER
),
287 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
288 DECL(ALC_EXTENSIONS
),
292 DECL(ALC_MONO_SOURCES
),
293 DECL(ALC_STEREO_SOURCES
),
294 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
295 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
296 DECL(ALC_CAPTURE_SAMPLES
),
299 DECL(ALC_EFX_MAJOR_VERSION
),
300 DECL(ALC_EFX_MINOR_VERSION
),
301 DECL(ALC_MAX_AUXILIARY_SENDS
),
303 DECL(ALC_FORMAT_CHANNELS_SOFT
),
304 DECL(ALC_FORMAT_TYPE_SOFT
),
307 DECL(ALC_STEREO_SOFT
),
309 DECL(ALC_5POINT1_SOFT
),
310 DECL(ALC_6POINT1_SOFT
),
311 DECL(ALC_7POINT1_SOFT
),
314 DECL(ALC_UNSIGNED_BYTE_SOFT
),
315 DECL(ALC_SHORT_SOFT
),
316 DECL(ALC_UNSIGNED_SHORT_SOFT
),
318 DECL(ALC_UNSIGNED_INT_SOFT
),
319 DECL(ALC_FLOAT_SOFT
),
322 DECL(ALC_INVALID_DEVICE
),
323 DECL(ALC_INVALID_CONTEXT
),
324 DECL(ALC_INVALID_ENUM
),
325 DECL(ALC_INVALID_VALUE
),
326 DECL(ALC_OUT_OF_MEMORY
),
334 DECL(AL_SOURCE_RELATIVE
),
335 DECL(AL_CONE_INNER_ANGLE
),
336 DECL(AL_CONE_OUTER_ANGLE
),
346 DECL(AL_ORIENTATION
),
347 DECL(AL_REFERENCE_DISTANCE
),
348 DECL(AL_ROLLOFF_FACTOR
),
349 DECL(AL_CONE_OUTER_GAIN
),
350 DECL(AL_MAX_DISTANCE
),
352 DECL(AL_SAMPLE_OFFSET
),
353 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
354 DECL(AL_BYTE_OFFSET
),
355 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
356 DECL(AL_SOURCE_TYPE
),
359 DECL(AL_UNDETERMINED
),
360 DECL(AL_METERS_PER_UNIT
),
361 DECL(AL_DIRECT_CHANNELS_SOFT
),
363 DECL(AL_DIRECT_FILTER
),
364 DECL(AL_AUXILIARY_SEND_FILTER
),
365 DECL(AL_AIR_ABSORPTION_FACTOR
),
366 DECL(AL_ROOM_ROLLOFF_FACTOR
),
367 DECL(AL_CONE_OUTER_GAINHF
),
368 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
369 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
370 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
372 DECL(AL_SOURCE_STATE
),
378 DECL(AL_BUFFERS_QUEUED
),
379 DECL(AL_BUFFERS_PROCESSED
),
381 DECL(AL_FORMAT_MONO8
),
382 DECL(AL_FORMAT_MONO16
),
383 DECL(AL_FORMAT_MONO_FLOAT32
),
384 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
385 DECL(AL_FORMAT_STEREO8
),
386 DECL(AL_FORMAT_STEREO16
),
387 DECL(AL_FORMAT_STEREO_FLOAT32
),
388 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
389 DECL(AL_FORMAT_MONO_IMA4
),
390 DECL(AL_FORMAT_STEREO_IMA4
),
391 DECL(AL_FORMAT_QUAD8_LOKI
),
392 DECL(AL_FORMAT_QUAD16_LOKI
),
393 DECL(AL_FORMAT_QUAD8
),
394 DECL(AL_FORMAT_QUAD16
),
395 DECL(AL_FORMAT_QUAD32
),
396 DECL(AL_FORMAT_51CHN8
),
397 DECL(AL_FORMAT_51CHN16
),
398 DECL(AL_FORMAT_51CHN32
),
399 DECL(AL_FORMAT_61CHN8
),
400 DECL(AL_FORMAT_61CHN16
),
401 DECL(AL_FORMAT_61CHN32
),
402 DECL(AL_FORMAT_71CHN8
),
403 DECL(AL_FORMAT_71CHN16
),
404 DECL(AL_FORMAT_71CHN32
),
405 DECL(AL_FORMAT_REAR8
),
406 DECL(AL_FORMAT_REAR16
),
407 DECL(AL_FORMAT_REAR32
),
408 DECL(AL_FORMAT_MONO_MULAW
),
409 DECL(AL_FORMAT_MONO_MULAW_EXT
),
410 DECL(AL_FORMAT_STEREO_MULAW
),
411 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
412 DECL(AL_FORMAT_QUAD_MULAW
),
413 DECL(AL_FORMAT_51CHN_MULAW
),
414 DECL(AL_FORMAT_61CHN_MULAW
),
415 DECL(AL_FORMAT_71CHN_MULAW
),
416 DECL(AL_FORMAT_REAR_MULAW
),
417 DECL(AL_FORMAT_MONO_ALAW_EXT
),
418 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
421 DECL(AL_MONO16_SOFT
),
422 DECL(AL_MONO32F_SOFT
),
423 DECL(AL_STEREO8_SOFT
),
424 DECL(AL_STEREO16_SOFT
),
425 DECL(AL_STEREO32F_SOFT
),
427 DECL(AL_QUAD16_SOFT
),
428 DECL(AL_QUAD32F_SOFT
),
430 DECL(AL_REAR16_SOFT
),
431 DECL(AL_REAR32F_SOFT
),
432 DECL(AL_5POINT1_8_SOFT
),
433 DECL(AL_5POINT1_16_SOFT
),
434 DECL(AL_5POINT1_32F_SOFT
),
435 DECL(AL_6POINT1_8_SOFT
),
436 DECL(AL_6POINT1_16_SOFT
),
437 DECL(AL_6POINT1_32F_SOFT
),
438 DECL(AL_7POINT1_8_SOFT
),
439 DECL(AL_7POINT1_16_SOFT
),
440 DECL(AL_7POINT1_32F_SOFT
),
443 DECL(AL_STEREO_SOFT
),
446 DECL(AL_5POINT1_SOFT
),
447 DECL(AL_6POINT1_SOFT
),
448 DECL(AL_7POINT1_SOFT
),
451 DECL(AL_UNSIGNED_BYTE_SOFT
),
453 DECL(AL_UNSIGNED_SHORT_SOFT
),
455 DECL(AL_UNSIGNED_INT_SOFT
),
457 DECL(AL_DOUBLE_SOFT
),
459 DECL(AL_UNSIGNED_BYTE3_SOFT
),
465 DECL(AL_INTERNAL_FORMAT_SOFT
),
466 DECL(AL_BYTE_LENGTH_SOFT
),
467 DECL(AL_SAMPLE_LENGTH_SOFT
),
468 DECL(AL_SEC_LENGTH_SOFT
),
475 DECL(AL_INVALID_NAME
),
476 DECL(AL_INVALID_ENUM
),
477 DECL(AL_INVALID_VALUE
),
478 DECL(AL_INVALID_OPERATION
),
479 DECL(AL_OUT_OF_MEMORY
),
486 DECL(AL_DOPPLER_FACTOR
),
487 DECL(AL_DOPPLER_VELOCITY
),
488 DECL(AL_DISTANCE_MODEL
),
489 DECL(AL_SPEED_OF_SOUND
),
490 DECL(AL_SOURCE_DISTANCE_MODEL
),
491 DECL(AL_DEFERRED_UPDATES_SOFT
),
493 DECL(AL_INVERSE_DISTANCE
),
494 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
495 DECL(AL_LINEAR_DISTANCE
),
496 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
497 DECL(AL_EXPONENT_DISTANCE
),
498 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
500 DECL(AL_FILTER_TYPE
),
501 DECL(AL_FILTER_NULL
),
502 DECL(AL_FILTER_LOWPASS
),
504 DECL(AL_FILTER_HIGHPASS
),
505 DECL(AL_FILTER_BANDPASS
),
508 DECL(AL_LOWPASS_GAIN
),
509 DECL(AL_LOWPASS_GAINHF
),
511 DECL(AL_EFFECT_TYPE
),
512 DECL(AL_EFFECT_NULL
),
513 DECL(AL_EFFECT_REVERB
),
514 DECL(AL_EFFECT_EAXREVERB
),
516 DECL(AL_EFFECT_CHORUS
),
517 DECL(AL_EFFECT_DISTORTION
),
519 DECL(AL_EFFECT_ECHO
),
521 DECL(AL_EFFECT_FLANGER
),
522 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
523 DECL(AL_EFFECT_VOCAL_MORPHER
),
524 DECL(AL_EFFECT_PITCH_SHIFTER
),
526 DECL(AL_EFFECT_RING_MODULATOR
),
528 DECL(AL_EFFECT_AUTOWAH
),
529 DECL(AL_EFFECT_COMPRESSOR
),
530 DECL(AL_EFFECT_EQUALIZER
),
532 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
533 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
535 DECL(AL_EAXREVERB_DENSITY
),
536 DECL(AL_EAXREVERB_DIFFUSION
),
537 DECL(AL_EAXREVERB_GAIN
),
538 DECL(AL_EAXREVERB_GAINHF
),
539 DECL(AL_EAXREVERB_GAINLF
),
540 DECL(AL_EAXREVERB_DECAY_TIME
),
541 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
542 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
543 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
544 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
545 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
546 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
547 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
548 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
549 DECL(AL_EAXREVERB_ECHO_TIME
),
550 DECL(AL_EAXREVERB_ECHO_DEPTH
),
551 DECL(AL_EAXREVERB_MODULATION_TIME
),
552 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
553 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
554 DECL(AL_EAXREVERB_HFREFERENCE
),
555 DECL(AL_EAXREVERB_LFREFERENCE
),
556 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
557 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
559 DECL(AL_REVERB_DENSITY
),
560 DECL(AL_REVERB_DIFFUSION
),
561 DECL(AL_REVERB_GAIN
),
562 DECL(AL_REVERB_GAINHF
),
563 DECL(AL_REVERB_DECAY_TIME
),
564 DECL(AL_REVERB_DECAY_HFRATIO
),
565 DECL(AL_REVERB_REFLECTIONS_GAIN
),
566 DECL(AL_REVERB_REFLECTIONS_DELAY
),
567 DECL(AL_REVERB_LATE_REVERB_GAIN
),
568 DECL(AL_REVERB_LATE_REVERB_DELAY
),
569 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
570 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
571 DECL(AL_REVERB_DECAY_HFLIMIT
),
574 DECL(AL_ECHO_LRDELAY
),
575 DECL(AL_ECHO_DAMPING
),
576 DECL(AL_ECHO_FEEDBACK
),
577 DECL(AL_ECHO_SPREAD
),
579 DECL(AL_RING_MODULATOR_FREQUENCY
),
580 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
581 DECL(AL_RING_MODULATOR_WAVEFORM
),
583 DECL(AL_DEDICATED_GAIN
),
589 static const ALCchar alcNoError
[] = "No Error";
590 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
591 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
592 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
593 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
594 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
597 /************************************************
599 ************************************************/
601 /* Enumerated device names */
602 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
603 static ALCchar
*alcAllDevicesList
;
604 static ALCchar
*alcCaptureDeviceList
;
605 /* Sizes only include the first ending null character, not the second */
606 static size_t alcAllDevicesListSize
;
607 static size_t alcCaptureDeviceListSize
;
609 /* Default is always the first in the list */
610 static ALCchar
*alcDefaultAllDevicesSpecifier
;
611 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
613 /* Default context extensions */
614 static const ALchar alExtList
[] =
615 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
616 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
617 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
618 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
619 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points "
620 "AL_SOFT_source_latency";
622 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
624 /* Thread-local current context */
625 static pthread_key_t LocalContext
;
626 /* Process-wide current context */
627 static ALCcontext
*volatile GlobalContext
= NULL
;
629 /* Mixing thread piority level */
634 enum LogLevel LogLevel
= LogWarning
;
636 enum LogLevel LogLevel
= LogError
;
639 /* Flag to trap ALC device errors */
640 static ALCboolean TrapALCError
= ALC_FALSE
;
642 /* One-time configuration init control */
643 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
645 /* Default effect that applies to sources that don't have an effect on send 0 */
646 static ALeffect DefaultEffect
;
649 /************************************************
651 ************************************************/
652 static const ALCchar alcNoDeviceExtList
[] =
653 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
654 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
655 static const ALCchar alcExtensionList
[] =
656 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
657 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
658 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
659 static const ALCint alcMajorVersion
= 1;
660 static const ALCint alcMinorVersion
= 1;
662 static const ALCint alcEFXMajorVersion
= 1;
663 static const ALCint alcEFXMinorVersion
= 0;
666 /************************************************
668 ************************************************/
669 static ALCdevice
*volatile DeviceList
= NULL
;
671 static CRITICAL_SECTION ListLock
;
673 static void LockLists(void)
675 EnterCriticalSection(&ListLock
);
677 static void UnlockLists(void)
679 LeaveCriticalSection(&ListLock
);
682 /************************************************
683 * Library initialization
684 ************************************************/
686 static void alc_init(void);
687 static void alc_deinit(void);
688 static void alc_deinit_safe(void);
690 UIntMap TlsDestructor
;
692 #ifndef AL_LIBTYPE_STATIC
693 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
697 // Perform actions based on the reason for calling.
698 switch(ul_reason_for_call
)
700 case DLL_PROCESS_ATTACH
:
701 /* Pin the DLL so we won't get unloaded until the process terminates */
702 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
703 (WCHAR
*)hModule
, &hModule
);
704 InitUIntMap(&TlsDestructor
, ~0);
708 case DLL_THREAD_DETACH
:
709 LockUIntMapRead(&TlsDestructor
);
710 for(i
= 0;i
< TlsDestructor
.size
;i
++)
712 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
713 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
717 UnlockUIntMapRead(&TlsDestructor
);
720 case DLL_PROCESS_DETACH
:
725 ResetUIntMap(&TlsDestructor
);
730 #elif defined(_MSC_VER)
731 #pragma section(".CRT$XCU",read)
732 static void alc_constructor(void);
733 static void alc_destructor(void);
734 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
736 static void alc_constructor(void)
738 atexit(alc_destructor
);
742 static void alc_destructor(void)
746 #elif defined(HAVE_GCC_DESTRUCTOR)
747 static void alc_init(void) __attribute__((constructor
));
748 static void alc_deinit(void) __attribute__((destructor
));
750 #error "No static initialization available on this platform!"
753 #elif defined(HAVE_GCC_DESTRUCTOR)
755 static void alc_init(void) __attribute__((constructor
));
756 static void alc_deinit(void) __attribute__((destructor
));
759 #error "No global initialization available on this platform!"
762 static void ReleaseThreadCtx(void *ptr
);
763 static void alc_init(void)
769 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
770 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
773 str
= getenv("__ALSOFT_REVERSE_Z");
774 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
777 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
778 InitializeCriticalSection(&ListLock
);
782 static void alc_initconfig(void)
784 const char *devs
, *str
;
789 str
= getenv("ALSOFT_LOGLEVEL");
792 long lvl
= strtol(str
, NULL
, 0);
793 if(lvl
>= NoLog
&& lvl
<= LogRef
)
797 str
= getenv("ALSOFT_LOGFILE");
800 FILE *logfile
= fopen(str
, "wat");
801 if(logfile
) LogFile
= logfile
;
802 else ERR("Failed to open log file '%s'\n", str
);
809 capfilter
|= CPU_CAP_SSE
;
812 capfilter
|= CPU_CAP_NEON
;
814 if(ConfigValueStr(NULL
, "disable-cpu-exts", &str
))
816 if(strcasecmp(str
, "all") == 0)
821 const char *next
= str
;
826 next
= strchr(str
, ',');
828 while(isspace(str
[0]))
830 if(!str
[0] || str
[0] == ',')
833 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
834 if(strncasecmp(str
, "sse", len
) == 0)
835 capfilter
&= ~CPU_CAP_SSE
;
836 else if(strncasecmp(str
, "neon", len
) == 0)
837 capfilter
&= ~CPU_CAP_NEON
;
839 WARN("Invalid CPU extension \"%s\"\n", str
);
843 FillCPUCaps(capfilter
);
850 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
852 if(ConfigValueStr(NULL
, "resampler", &str
))
854 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
855 DefaultResampler
= PointResampler
;
856 else if(strcasecmp(str
, "linear") == 0)
857 DefaultResampler
= LinearResampler
;
858 else if(strcasecmp(str
, "cubic") == 0)
859 DefaultResampler
= CubicResampler
;
864 n
= strtol(str
, &end
, 0);
865 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
866 DefaultResampler
= n
;
868 WARN("Invalid resampler: %s\n", str
);
872 str
= getenv("ALSOFT_TRAP_ERROR");
873 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
875 TrapALError
= AL_TRUE
;
876 TrapALCError
= AL_TRUE
;
880 str
= getenv("ALSOFT_TRAP_AL_ERROR");
881 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
882 TrapALError
= AL_TRUE
;
883 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
885 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
886 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
887 TrapALCError
= ALC_TRUE
;
888 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
891 if(ConfigValueFloat("reverb", "boost", &valf
))
892 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
894 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
896 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
897 ConfigValueStr(NULL
, "drivers", &devs
))
901 const char *next
= devs
;
902 int endlist
, delitem
;
907 next
= strchr(devs
, ',');
909 delitem
= (devs
[0] == '-');
910 if(devs
[0] == '-') devs
++;
912 if(!devs
[0] || devs
[0] == ',')
919 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
920 for(n
= i
;BackendList
[n
].Init
;n
++)
922 if(len
== strlen(BackendList
[n
].name
) &&
923 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
928 BackendList
[n
] = BackendList
[n
+1];
930 } while(BackendList
[n
].Init
);
934 struct BackendInfo Bkp
= BackendList
[n
];
937 BackendList
[n
] = BackendList
[n
-1];
940 BackendList
[n
] = Bkp
;
951 BackendList
[i
].name
= NULL
;
952 BackendList
[i
].Init
= NULL
;
953 BackendList
[i
].Deinit
= NULL
;
954 BackendList
[i
].Probe
= NULL
;
958 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
960 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
962 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
966 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
967 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
969 PlaybackBackend
= BackendList
[i
];
970 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
972 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
974 CaptureBackend
= BackendList
[i
];
975 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
978 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
980 if(ConfigValueStr(NULL
, "excludefx", &str
))
983 const char *next
= str
;
987 next
= strchr(str
, ',');
989 if(!str
[0] || next
== str
)
992 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
993 for(n
= 0;EffectList
[n
].name
;n
++)
995 if(len
== strlen(EffectList
[n
].name
) &&
996 strncmp(EffectList
[n
].name
, str
, len
) == 0)
997 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1002 InitEffect(&DefaultEffect
);
1003 str
= getenv("ALSOFT_DEFAULT_REVERB");
1004 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
1005 LoadReverbPreset(str
, &DefaultEffect
);
1007 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
1010 /************************************************
1011 * Library deinitialization
1012 ************************************************/
1013 static void alc_cleanup(void)
1017 free(alcAllDevicesList
); alcAllDevicesList
= NULL
;
1018 alcAllDevicesListSize
= 0;
1019 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
1020 alcCaptureDeviceListSize
= 0;
1022 free(alcDefaultAllDevicesSpecifier
);
1023 alcDefaultAllDevicesSpecifier
= NULL
;
1024 free(alcCaptureDefaultDeviceSpecifier
);
1025 alcCaptureDefaultDeviceSpecifier
= NULL
;
1027 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
1032 } while((dev
=dev
->next
) != NULL
);
1033 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1037 static void alc_deinit_safe(void)
1045 DeleteCriticalSection(&ListLock
);
1046 pthread_key_delete(LocalContext
);
1048 if(LogFile
!= stderr
)
1053 static void alc_deinit(void)
1059 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1060 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1062 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1063 BackendList
[i
].Deinit();
1064 BackendLoopback
.Deinit();
1070 /************************************************
1071 * Device enumeration
1072 ************************************************/
1073 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1082 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1083 PlaybackBackend
.Probe(type
);
1084 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1085 CaptureBackend
.Probe(type
);
1089 static void ProbeAllDevicesList(void)
1090 { ProbeList(&alcAllDevicesList
, &alcAllDevicesListSize
, ALL_DEVICE_PROBE
); }
1091 static void ProbeCaptureDeviceList(void)
1092 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1095 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1097 size_t len
= strlen(name
);
1103 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1106 ERR("Realloc failed to add %s!\n", name
);
1111 memcpy((*List
)+(*ListSize
), name
, len
+1);
1113 (*List
)[*ListSize
] = 0;
1116 #define DECL_APPEND_LIST_FUNC(type) \
1117 void Append##type##List(const ALCchar *name) \
1118 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1120 DECL_APPEND_LIST_FUNC(AllDevices
)
1121 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1123 #undef DECL_APPEND_LIST_FUNC
1126 /************************************************
1127 * Device format information
1128 ************************************************/
1129 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1133 case DevFmtByte
: return "Signed Byte";
1134 case DevFmtUByte
: return "Unsigned Byte";
1135 case DevFmtShort
: return "Signed Short";
1136 case DevFmtUShort
: return "Unsigned Short";
1137 case DevFmtInt
: return "Signed Int";
1138 case DevFmtUInt
: return "Unsigned Int";
1139 case DevFmtFloat
: return "Float";
1141 return "(unknown type)";
1143 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1147 case DevFmtMono
: return "Mono";
1148 case DevFmtStereo
: return "Stereo";
1149 case DevFmtQuad
: return "Quadraphonic";
1150 case DevFmtX51
: return "5.1 Surround";
1151 case DevFmtX51Side
: return "5.1 Side";
1152 case DevFmtX61
: return "6.1 Surround";
1153 case DevFmtX71
: return "7.1 Surround";
1155 return "(unknown channels)";
1158 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1162 case DevFmtByte
: return sizeof(ALbyte
);
1163 case DevFmtUByte
: return sizeof(ALubyte
);
1164 case DevFmtShort
: return sizeof(ALshort
);
1165 case DevFmtUShort
: return sizeof(ALushort
);
1166 case DevFmtInt
: return sizeof(ALint
);
1167 case DevFmtUInt
: return sizeof(ALuint
);
1168 case DevFmtFloat
: return sizeof(ALfloat
);
1172 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1176 case DevFmtMono
: return 1;
1177 case DevFmtStereo
: return 2;
1178 case DevFmtQuad
: return 4;
1179 case DevFmtX51
: return 6;
1180 case DevFmtX51Side
: return 6;
1181 case DevFmtX61
: return 7;
1182 case DevFmtX71
: return 8;
1187 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1188 enum DevFmtType
*type
)
1190 static const struct {
1192 enum DevFmtChannels channels
;
1193 enum DevFmtType type
;
1195 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1196 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1197 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1199 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1200 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1201 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1203 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1204 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1205 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1207 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1208 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1209 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1211 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1212 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1213 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1215 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1216 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1217 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1221 for(i
= 0;i
< COUNTOF(list
);i
++)
1223 if(list
[i
].format
== format
)
1225 *chans
= list
[i
].channels
;
1226 *type
= list
[i
].type
;
1234 static ALCboolean
IsValidALCType(ALCenum type
)
1239 case ALC_UNSIGNED_BYTE_SOFT
:
1240 case ALC_SHORT_SOFT
:
1241 case ALC_UNSIGNED_SHORT_SOFT
:
1243 case ALC_UNSIGNED_INT_SOFT
:
1244 case ALC_FLOAT_SOFT
:
1250 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1255 case ALC_STEREO_SOFT
:
1257 case ALC_5POINT1_SOFT
:
1258 case ALC_6POINT1_SOFT
:
1259 case ALC_7POINT1_SOFT
:
1266 /************************************************
1267 * Miscellaneous ALC helpers
1268 ************************************************/
1270 void ALCdevice_LockDefault(ALCdevice
*device
)
1272 EnterCriticalSection(&device
->Mutex
);
1274 void ALCdevice_UnlockDefault(ALCdevice
*device
)
1276 LeaveCriticalSection(&device
->Mutex
);
1278 ALint64
ALCdevice_GetLatencyDefault(ALCdevice
*device
)
1284 /* SetDefaultWFXChannelOrder
1286 * Sets the default channel order used by WaveFormatEx.
1288 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1290 switch(device
->FmtChans
)
1292 case DevFmtMono
: device
->DevChannels
[0] = FrontCenter
; break;
1294 case DevFmtStereo
: device
->DevChannels
[0] = FrontLeft
;
1295 device
->DevChannels
[1] = FrontRight
; break;
1297 case DevFmtQuad
: device
->DevChannels
[0] = FrontLeft
;
1298 device
->DevChannels
[1] = FrontRight
;
1299 device
->DevChannels
[2] = BackLeft
;
1300 device
->DevChannels
[3] = BackRight
; break;
1302 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1303 device
->DevChannels
[1] = FrontRight
;
1304 device
->DevChannels
[2] = FrontCenter
;
1305 device
->DevChannels
[3] = LFE
;
1306 device
->DevChannels
[4] = BackLeft
;
1307 device
->DevChannels
[5] = BackRight
; break;
1309 case DevFmtX51Side
: device
->DevChannels
[0] = FrontLeft
;
1310 device
->DevChannels
[1] = FrontRight
;
1311 device
->DevChannels
[2] = FrontCenter
;
1312 device
->DevChannels
[3] = LFE
;
1313 device
->DevChannels
[4] = SideLeft
;
1314 device
->DevChannels
[5] = SideRight
; break;
1316 case DevFmtX61
: device
->DevChannels
[0] = FrontLeft
;
1317 device
->DevChannels
[1] = FrontRight
;
1318 device
->DevChannels
[2] = FrontCenter
;
1319 device
->DevChannels
[3] = LFE
;
1320 device
->DevChannels
[4] = BackCenter
;
1321 device
->DevChannels
[5] = SideLeft
;
1322 device
->DevChannels
[6] = SideRight
; break;
1324 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1325 device
->DevChannels
[1] = FrontRight
;
1326 device
->DevChannels
[2] = FrontCenter
;
1327 device
->DevChannels
[3] = LFE
;
1328 device
->DevChannels
[4] = BackLeft
;
1329 device
->DevChannels
[5] = BackRight
;
1330 device
->DevChannels
[6] = SideLeft
;
1331 device
->DevChannels
[7] = SideRight
; break;
1335 /* SetDefaultChannelOrder
1337 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1339 void SetDefaultChannelOrder(ALCdevice
*device
)
1341 switch(device
->FmtChans
)
1343 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1344 device
->DevChannels
[1] = FrontRight
;
1345 device
->DevChannels
[2] = BackLeft
;
1346 device
->DevChannels
[3] = BackRight
;
1347 device
->DevChannels
[4] = FrontCenter
;
1348 device
->DevChannels
[5] = LFE
;
1351 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1352 device
->DevChannels
[1] = FrontRight
;
1353 device
->DevChannels
[2] = BackLeft
;
1354 device
->DevChannels
[3] = BackRight
;
1355 device
->DevChannels
[4] = FrontCenter
;
1356 device
->DevChannels
[5] = LFE
;
1357 device
->DevChannels
[6] = SideLeft
;
1358 device
->DevChannels
[7] = SideRight
;
1361 /* Same as WFX order */
1369 SetDefaultWFXChannelOrder(device
);
1375 * Stores the latest ALC device error
1377 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1382 /* DebugBreak() will cause an exception if there is no debugger */
1383 if(IsDebuggerPresent())
1385 #elif defined(SIGTRAP)
1391 device
->LastError
= errorCode
;
1393 LastNullDeviceError
= errorCode
;
1397 /* UpdateDeviceParams
1399 * Updates device parameters according to the attribute list (caller is
1400 * responsible for holding the list lock).
1402 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1404 ALCcontext
*context
;
1405 enum DevFmtChannels oldChans
;
1406 enum DevFmtType oldType
;
1411 // Check for attributes
1412 if(device
->Type
== Loopback
)
1418 GotAll
= GotFreq
|GotChans
|GotType
1420 ALCuint freq
, numMono
, numStereo
, numSends
;
1421 enum DevFmtChannels schans
;
1422 enum DevFmtType stype
;
1423 ALCuint attrIdx
= 0;
1428 WARN("Missing attributes for loopback device\n");
1429 return ALC_INVALID_VALUE
;
1432 numMono
= device
->NumMonoSources
;
1433 numStereo
= device
->NumStereoSources
;
1434 numSends
= device
->NumAuxSends
;
1435 schans
= device
->FmtChans
;
1436 stype
= device
->FmtType
;
1437 freq
= device
->Frequency
;
1439 while(attrList
[attrIdx
])
1441 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1443 ALCint val
= attrList
[attrIdx
+ 1];
1444 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1445 return ALC_INVALID_VALUE
;
1450 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1452 ALCint val
= attrList
[attrIdx
+ 1];
1453 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1454 return ALC_INVALID_VALUE
;
1459 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1461 freq
= attrList
[attrIdx
+ 1];
1462 if(freq
< MIN_OUTPUT_RATE
)
1463 return ALC_INVALID_VALUE
;
1467 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1469 numStereo
= attrList
[attrIdx
+ 1];
1470 if(numStereo
> device
->MaxNoOfSources
)
1471 numStereo
= device
->MaxNoOfSources
;
1473 numMono
= device
->MaxNoOfSources
- numStereo
;
1476 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1477 numSends
= attrList
[attrIdx
+ 1];
1482 if(gotFmt
!= GotAll
)
1484 WARN("Missing format for loopback device\n");
1485 return ALC_INVALID_VALUE
;
1488 ConfigValueUInt(NULL
, "sends", &numSends
);
1489 numSends
= minu(MAX_SENDS
, numSends
);
1491 if((device
->Flags
&DEVICE_RUNNING
))
1492 ALCdevice_StopPlayback(device
);
1493 device
->Flags
&= ~DEVICE_RUNNING
;
1495 device
->Frequency
= freq
;
1496 device
->FmtChans
= schans
;
1497 device
->FmtType
= stype
;
1498 device
->NumMonoSources
= numMono
;
1499 device
->NumStereoSources
= numStereo
;
1500 device
->NumAuxSends
= numSends
;
1502 else if(attrList
&& attrList
[0])
1504 ALCuint freq
, numMono
, numStereo
, numSends
;
1505 ALCuint attrIdx
= 0;
1507 /* If a context is already running on the device, stop playback so the
1508 * device attributes can be updated. */
1509 if((device
->Flags
&DEVICE_RUNNING
))
1510 ALCdevice_StopPlayback(device
);
1511 device
->Flags
&= ~DEVICE_RUNNING
;
1513 freq
= device
->Frequency
;
1514 numMono
= device
->NumMonoSources
;
1515 numStereo
= device
->NumStereoSources
;
1516 numSends
= device
->NumAuxSends
;
1518 while(attrList
[attrIdx
])
1520 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1522 freq
= attrList
[attrIdx
+ 1];
1523 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1526 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1528 numStereo
= attrList
[attrIdx
+ 1];
1529 if(numStereo
> device
->MaxNoOfSources
)
1530 numStereo
= device
->MaxNoOfSources
;
1532 numMono
= device
->MaxNoOfSources
- numStereo
;
1535 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1536 numSends
= attrList
[attrIdx
+ 1];
1541 ConfigValueUInt(NULL
, "frequency", &freq
);
1542 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1544 ConfigValueUInt(NULL
, "sends", &numSends
);
1545 numSends
= minu(MAX_SENDS
, numSends
);
1547 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1549 /* SSE does best with the update size being a multiple of 4 */
1550 if((CPUCapFlags
&CPU_CAP_SSE
))
1551 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1553 device
->Frequency
= freq
;
1554 device
->NumMonoSources
= numMono
;
1555 device
->NumStereoSources
= numStereo
;
1556 device
->NumAuxSends
= numSends
;
1559 if((device
->Flags
&DEVICE_RUNNING
))
1560 return ALC_NO_ERROR
;
1562 oldFreq
= device
->Frequency
;
1563 oldChans
= device
->FmtChans
;
1564 oldType
= device
->FmtType
;
1566 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1567 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"",
1568 DevFmtChannelsString(device
->FmtChans
),
1569 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"",
1570 DevFmtTypeString(device
->FmtType
),
1571 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"",
1573 device
->UpdateSize
, device
->NumUpdates
);
1575 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1576 return ALC_INVALID_DEVICE
;
1578 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1580 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1581 DevFmtChannelsString(device
->FmtChans
));
1582 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1584 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1586 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1587 DevFmtTypeString(device
->FmtType
));
1588 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1590 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1592 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1593 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1596 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1597 DevFmtChannelsString(device
->FmtChans
),
1598 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1599 device
->UpdateSize
, device
->NumUpdates
);
1601 aluInitPanning(device
);
1603 for(i
= 0;i
< MaxChannels
;i
++)
1605 device
->ClickRemoval
[i
] = 0.0f
;
1606 device
->PendingClicks
[i
] = 0.0f
;
1609 device
->Hrtf
= NULL
;
1610 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1611 device
->Hrtf
= GetHrtf(device
);
1612 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1614 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1618 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1619 bs2b_clear(device
->Bs2b
);
1621 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1622 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1623 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1628 device
->Bs2b
= NULL
;
1629 TRACE("BS2B disabled\n");
1632 device
->Flags
&= ~DEVICE_WIDE_STEREO
;
1633 if(device
->Type
!= Loopback
&& !device
->Hrtf
&& GetConfigValueBool(NULL
, "wide-stereo", AL_FALSE
))
1634 device
->Flags
|= DEVICE_WIDE_STEREO
;
1636 if(!device
->Hrtf
&& (device
->UpdateSize
&3))
1638 if((CPUCapFlags
&CPU_CAP_SSE
))
1639 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
1642 SetMixerFPUMode(&oldMode
);
1643 ALCdevice_Lock(device
);
1644 context
= device
->ContextList
;
1649 context
->UpdateSources
= AL_FALSE
;
1650 LockUIntMapRead(&context
->EffectSlotMap
);
1651 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1653 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1655 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1657 UnlockUIntMapRead(&context
->EffectSlotMap
);
1658 ALCdevice_Unlock(device
);
1659 RestoreFPUMode(&oldMode
);
1660 return ALC_INVALID_DEVICE
;
1662 slot
->NeedsUpdate
= AL_FALSE
;
1663 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1665 UnlockUIntMapRead(&context
->EffectSlotMap
);
1667 LockUIntMapRead(&context
->SourceMap
);
1668 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1670 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1671 ALuint s
= device
->NumAuxSends
;
1672 while(s
< MAX_SENDS
)
1674 if(source
->Send
[s
].Slot
)
1675 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1676 source
->Send
[s
].Slot
= NULL
;
1677 source
->Send
[s
].Gain
= 1.0f
;
1678 source
->Send
[s
].GainHF
= 1.0f
;
1681 source
->NeedsUpdate
= AL_FALSE
;
1682 ALsource_Update(source
, context
);
1684 UnlockUIntMapRead(&context
->SourceMap
);
1686 context
= context
->next
;
1688 if(device
->DefaultSlot
)
1690 ALeffectslot
*slot
= device
->DefaultSlot
;
1692 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1694 ALCdevice_Unlock(device
);
1695 RestoreFPUMode(&oldMode
);
1696 return ALC_INVALID_DEVICE
;
1698 slot
->NeedsUpdate
= AL_FALSE
;
1699 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1701 ALCdevice_Unlock(device
);
1702 RestoreFPUMode(&oldMode
);
1704 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1705 return ALC_INVALID_DEVICE
;
1706 device
->Flags
|= DEVICE_RUNNING
;
1708 return ALC_NO_ERROR
;
1713 * Frees the device structure, and destroys any objects the app failed to
1714 * delete. Called once there's no more references on the device.
1716 static ALCvoid
FreeDevice(ALCdevice
*device
)
1718 TRACE("%p\n", device
);
1720 if(device
->Type
!= Capture
)
1721 ALCdevice_ClosePlayback(device
);
1723 ALCdevice_CloseCapture(device
);
1725 if(device
->DefaultSlot
)
1727 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1728 device
->DefaultSlot
->EffectState
= NULL
;
1731 if(device
->BufferMap
.size
> 0)
1733 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1734 ReleaseALBuffers(device
);
1736 ResetUIntMap(&device
->BufferMap
);
1738 if(device
->EffectMap
.size
> 0)
1740 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1741 ReleaseALEffects(device
);
1743 ResetUIntMap(&device
->EffectMap
);
1745 if(device
->FilterMap
.size
> 0)
1747 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1748 ReleaseALFilters(device
);
1750 ResetUIntMap(&device
->FilterMap
);
1753 device
->Bs2b
= NULL
;
1755 free(device
->DeviceName
);
1756 device
->DeviceName
= NULL
;
1758 DeleteCriticalSection(&device
->Mutex
);
1764 void ALCdevice_IncRef(ALCdevice
*device
)
1767 ref
= IncrementRef(&device
->ref
);
1768 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1771 void ALCdevice_DecRef(ALCdevice
*device
)
1774 ref
= DecrementRef(&device
->ref
);
1775 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1776 if(ref
== 0) FreeDevice(device
);
1781 * Checks if the device handle is valid, and increments its ref count if so.
1783 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1785 ALCdevice
*tmpDevice
;
1791 tmpDevice
= DeviceList
;
1792 while(tmpDevice
&& tmpDevice
!= device
)
1793 tmpDevice
= tmpDevice
->next
;
1796 ALCdevice_IncRef(tmpDevice
);
1804 * Initializes context fields
1806 static ALvoid
InitContext(ALCcontext
*Context
)
1810 //Initialise listener
1811 Context
->Listener
->Gain
= 1.0f
;
1812 Context
->Listener
->MetersPerUnit
= 1.0f
;
1813 Context
->Listener
->Position
[0] = 0.0f
;
1814 Context
->Listener
->Position
[1] = 0.0f
;
1815 Context
->Listener
->Position
[2] = 0.0f
;
1816 Context
->Listener
->Velocity
[0] = 0.0f
;
1817 Context
->Listener
->Velocity
[1] = 0.0f
;
1818 Context
->Listener
->Velocity
[2] = 0.0f
;
1819 Context
->Listener
->Forward
[0] = 0.0f
;
1820 Context
->Listener
->Forward
[1] = 0.0f
;
1821 Context
->Listener
->Forward
[2] = -1.0f
;
1822 Context
->Listener
->Up
[0] = 0.0f
;
1823 Context
->Listener
->Up
[1] = 1.0f
;
1824 Context
->Listener
->Up
[2] = 0.0f
;
1825 for(i
= 0;i
< 4;i
++)
1827 for(j
= 0;j
< 4;j
++)
1828 Context
->Listener
->Params
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1830 for(i
= 0;i
< 3;i
++)
1831 Context
->Listener
->Params
.Velocity
[i
] = 0.0f
;
1834 Context
->LastError
= AL_NO_ERROR
;
1835 Context
->UpdateSources
= AL_FALSE
;
1836 Context
->ActiveSourceCount
= 0;
1837 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1838 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1841 Context
->DistanceModel
= DefaultDistanceModel
;
1842 Context
->SourceDistanceModel
= AL_FALSE
;
1843 Context
->DopplerFactor
= 1.0f
;
1844 Context
->DopplerVelocity
= 1.0f
;
1845 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1846 Context
->DeferUpdates
= AL_FALSE
;
1848 Context
->ExtensionList
= alExtList
;
1854 * Cleans up the context, and destroys any remaining objects the app failed to
1855 * delete. Called once there's no more references on the context.
1857 static ALCvoid
FreeContext(ALCcontext
*context
)
1859 TRACE("%p\n", context
);
1861 if(context
->SourceMap
.size
> 0)
1863 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1864 ReleaseALSources(context
);
1866 ResetUIntMap(&context
->SourceMap
);
1868 if(context
->EffectSlotMap
.size
> 0)
1870 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1871 ReleaseALAuxiliaryEffectSlots(context
);
1873 ResetUIntMap(&context
->EffectSlotMap
);
1875 context
->ActiveSourceCount
= 0;
1876 free(context
->ActiveSources
);
1877 context
->ActiveSources
= NULL
;
1878 context
->MaxActiveSources
= 0;
1880 context
->ActiveEffectSlotCount
= 0;
1881 free(context
->ActiveEffectSlots
);
1882 context
->ActiveEffectSlots
= NULL
;
1883 context
->MaxActiveEffectSlots
= 0;
1885 ALCdevice_DecRef(context
->Device
);
1886 context
->Device
= NULL
;
1888 //Invalidate context
1889 memset(context
, 0, sizeof(ALCcontext
));
1895 * Removes the context reference from the given device and removes it from
1896 * being current on the running thread or globally.
1898 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1900 ALCcontext
*volatile*tmp_ctx
;
1902 if(pthread_getspecific(LocalContext
) == context
)
1904 WARN("%p released while current on thread\n", context
);
1905 pthread_setspecific(LocalContext
, NULL
);
1906 ALCcontext_DecRef(context
);
1909 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1910 ALCcontext_DecRef(context
);
1912 ALCdevice_Lock(device
);
1913 tmp_ctx
= &device
->ContextList
;
1916 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1918 tmp_ctx
= &(*tmp_ctx
)->next
;
1920 ALCdevice_Unlock(device
);
1922 ALCcontext_DecRef(context
);
1925 void ALCcontext_IncRef(ALCcontext
*context
)
1928 ref
= IncrementRef(&context
->ref
);
1929 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1932 void ALCcontext_DecRef(ALCcontext
*context
)
1935 ref
= DecrementRef(&context
->ref
);
1936 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1937 if(ref
== 0) FreeContext(context
);
1940 static void ReleaseThreadCtx(void *ptr
)
1942 WARN("%p current for thread being destroyed\n", ptr
);
1943 ALCcontext_DecRef(ptr
);
1948 * Checks that the given context is valid, and increments its reference count.
1950 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1958 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1961 if(tmp_ctx
== context
)
1963 ALCcontext_IncRef(tmp_ctx
);
1967 tmp_ctx
= tmp_ctx
->next
;
1979 * Returns the currently active context for this thread, and adds a reference
1980 * without locking it.
1982 ALCcontext
*GetContextRef(void)
1984 ALCcontext
*context
;
1986 context
= pthread_getspecific(LocalContext
);
1988 ALCcontext_IncRef(context
);
1992 context
= GlobalContext
;
1994 ALCcontext_IncRef(context
);
2002 /************************************************
2003 * Standard ALC functions
2004 ************************************************/
2008 * Return last ALC generated error code for the given device
2010 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2014 if(VerifyDevice(device
))
2016 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
2017 ALCdevice_DecRef(device
);
2020 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
2026 /* alcSuspendContext
2030 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
2035 /* alcProcessContext
2039 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
2047 * Returns information about the device, and error strings
2049 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2051 const ALCchar
*value
= NULL
;
2059 case ALC_INVALID_ENUM
:
2060 value
= alcErrInvalidEnum
;
2063 case ALC_INVALID_VALUE
:
2064 value
= alcErrInvalidValue
;
2067 case ALC_INVALID_DEVICE
:
2068 value
= alcErrInvalidDevice
;
2071 case ALC_INVALID_CONTEXT
:
2072 value
= alcErrInvalidContext
;
2075 case ALC_OUT_OF_MEMORY
:
2076 value
= alcErrOutOfMemory
;
2079 case ALC_DEVICE_SPECIFIER
:
2080 value
= alcDefaultName
;
2083 case ALC_ALL_DEVICES_SPECIFIER
:
2084 if(VerifyDevice(Device
))
2086 value
= Device
->DeviceName
;
2087 ALCdevice_DecRef(Device
);
2091 ProbeAllDevicesList();
2092 value
= alcAllDevicesList
;
2096 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2097 if(VerifyDevice(Device
))
2099 value
= Device
->DeviceName
;
2100 ALCdevice_DecRef(Device
);
2104 ProbeCaptureDeviceList();
2105 value
= alcCaptureDeviceList
;
2109 /* Default devices are always first in the list */
2110 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2111 value
= alcDefaultName
;
2114 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2115 if(!alcAllDevicesList
)
2116 ProbeAllDevicesList();
2118 Device
= VerifyDevice(Device
);
2120 free(alcDefaultAllDevicesSpecifier
);
2121 alcDefaultAllDevicesSpecifier
= strdup(alcAllDevicesList
?
2122 alcAllDevicesList
: "");
2123 if(!alcDefaultAllDevicesSpecifier
)
2124 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2126 value
= alcDefaultAllDevicesSpecifier
;
2127 if(Device
) ALCdevice_DecRef(Device
);
2130 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2131 if(!alcCaptureDeviceList
)
2132 ProbeCaptureDeviceList();
2134 Device
= VerifyDevice(Device
);
2136 free(alcCaptureDefaultDeviceSpecifier
);
2137 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2138 alcCaptureDeviceList
: "");
2139 if(!alcCaptureDefaultDeviceSpecifier
)
2140 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2142 value
= alcCaptureDefaultDeviceSpecifier
;
2143 if(Device
) ALCdevice_DecRef(Device
);
2146 case ALC_EXTENSIONS
:
2147 if(!VerifyDevice(Device
))
2148 value
= alcNoDeviceExtList
;
2151 value
= alcExtensionList
;
2152 ALCdevice_DecRef(Device
);
2157 Device
= VerifyDevice(Device
);
2158 alcSetError(Device
, ALC_INVALID_ENUM
);
2159 if(Device
) ALCdevice_DecRef(Device
);
2169 * Returns information about the device and the version of OpenAL
2171 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2173 device
= VerifyDevice(device
);
2175 if(size
== 0 || data
== NULL
)
2177 alcSetError(device
, ALC_INVALID_VALUE
);
2178 if(device
) ALCdevice_DecRef(device
);
2186 case ALC_MAJOR_VERSION
:
2187 *data
= alcMajorVersion
;
2189 case ALC_MINOR_VERSION
:
2190 *data
= alcMinorVersion
;
2193 case ALC_ATTRIBUTES_SIZE
:
2194 case ALC_ALL_ATTRIBUTES
:
2198 case ALC_MONO_SOURCES
:
2199 case ALC_STEREO_SOURCES
:
2200 case ALC_CAPTURE_SAMPLES
:
2201 case ALC_FORMAT_CHANNELS_SOFT
:
2202 case ALC_FORMAT_TYPE_SOFT
:
2203 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2207 alcSetError(NULL
, ALC_INVALID_ENUM
);
2211 else if(device
->Type
== Capture
)
2215 case ALC_CAPTURE_SAMPLES
:
2216 ALCdevice_Lock(device
);
2217 *data
= ALCdevice_AvailableSamples(device
);
2218 ALCdevice_Unlock(device
);
2222 *data
= device
->Connected
;
2226 alcSetError(device
, ALC_INVALID_ENUM
);
2230 else /* render device */
2234 case ALC_MAJOR_VERSION
:
2235 *data
= alcMajorVersion
;
2238 case ALC_MINOR_VERSION
:
2239 *data
= alcMinorVersion
;
2242 case ALC_EFX_MAJOR_VERSION
:
2243 *data
= alcEFXMajorVersion
;
2246 case ALC_EFX_MINOR_VERSION
:
2247 *data
= alcEFXMinorVersion
;
2250 case ALC_ATTRIBUTES_SIZE
:
2254 case ALC_ALL_ATTRIBUTES
:
2256 alcSetError(device
, ALC_INVALID_VALUE
);
2261 data
[i
++] = ALC_FREQUENCY
;
2262 data
[i
++] = device
->Frequency
;
2264 if(device
->Type
!= Loopback
)
2266 data
[i
++] = ALC_REFRESH
;
2267 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2269 data
[i
++] = ALC_SYNC
;
2270 data
[i
++] = ALC_FALSE
;
2274 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2275 data
[i
++] = device
->FmtChans
;
2277 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2278 data
[i
++] = device
->FmtType
;
2281 data
[i
++] = ALC_MONO_SOURCES
;
2282 data
[i
++] = device
->NumMonoSources
;
2284 data
[i
++] = ALC_STEREO_SOURCES
;
2285 data
[i
++] = device
->NumStereoSources
;
2287 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2288 data
[i
++] = device
->NumAuxSends
;
2295 *data
= device
->Frequency
;
2299 if(device
->Type
== Loopback
)
2300 alcSetError(device
, ALC_INVALID_DEVICE
);
2302 *data
= device
->Frequency
/ device
->UpdateSize
;
2306 if(device
->Type
== Loopback
)
2307 alcSetError(device
, ALC_INVALID_DEVICE
);
2312 case ALC_FORMAT_CHANNELS_SOFT
:
2313 if(device
->Type
!= Loopback
)
2314 alcSetError(device
, ALC_INVALID_DEVICE
);
2316 *data
= device
->FmtChans
;
2319 case ALC_FORMAT_TYPE_SOFT
:
2320 if(device
->Type
!= Loopback
)
2321 alcSetError(device
, ALC_INVALID_DEVICE
);
2323 *data
= device
->FmtType
;
2326 case ALC_MONO_SOURCES
:
2327 *data
= device
->NumMonoSources
;
2330 case ALC_STEREO_SOURCES
:
2331 *data
= device
->NumStereoSources
;
2334 case ALC_MAX_AUXILIARY_SENDS
:
2335 *data
= device
->NumAuxSends
;
2339 *data
= device
->Connected
;
2343 alcSetError(device
, ALC_INVALID_ENUM
);
2348 ALCdevice_DecRef(device
);
2352 /* alcIsExtensionPresent
2354 * Determines if there is support for a particular extension
2356 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2358 ALCboolean bResult
= ALC_FALSE
;
2360 device
= VerifyDevice(device
);
2363 alcSetError(device
, ALC_INVALID_VALUE
);
2366 size_t len
= strlen(extName
);
2367 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2370 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2371 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2376 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2380 } while(isspace(*ptr
));
2385 ALCdevice_DecRef(device
);
2390 /* alcGetProcAddress
2392 * Retrieves the function address for a particular extension function
2394 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2396 ALCvoid
*ptr
= NULL
;
2400 device
= VerifyDevice(device
);
2401 alcSetError(device
, ALC_INVALID_VALUE
);
2402 if(device
) ALCdevice_DecRef(device
);
2407 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2409 ptr
= alcFunctions
[i
].address
;
2418 * Get the value for a particular ALC enumeration name
2420 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2426 device
= VerifyDevice(device
);
2427 alcSetError(device
, ALC_INVALID_VALUE
);
2428 if(device
) ALCdevice_DecRef(device
);
2433 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2435 val
= enumeration
[i
].value
;
2444 * Create and attach a context to the given device.
2446 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2448 ALCcontext
*ALContext
;
2452 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2455 alcSetError(device
, ALC_INVALID_DEVICE
);
2456 if(device
) ALCdevice_DecRef(device
);
2460 device
->LastError
= ALC_NO_ERROR
;
2462 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2465 alcSetError(device
, err
);
2466 if(err
== ALC_INVALID_DEVICE
)
2467 aluHandleDisconnect(device
);
2468 ALCdevice_DecRef(device
);
2472 ALContext
= calloc(1, sizeof(ALCcontext
)+15+sizeof(ALlistener
));
2476 ALContext
->Listener
= (ALlistener
*)(((ALintptrEXT
)(ALContext
+1)+15)&~15);
2478 ALContext
->MaxActiveSources
= 256;
2479 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2480 ALContext
->MaxActiveSources
);
2482 if(!ALContext
|| !ALContext
->ActiveSources
)
2484 if(!device
->ContextList
)
2486 ALCdevice_StopPlayback(device
);
2487 device
->Flags
&= ~DEVICE_RUNNING
;
2494 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2495 ALCdevice_DecRef(device
);
2499 ALContext
->Device
= device
;
2500 ALCdevice_IncRef(device
);
2501 InitContext(ALContext
);
2504 ALContext
->next
= device
->ContextList
;
2505 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2508 ALCdevice_DecRef(device
);
2510 TRACE("Created context %p\n", ALContext
);
2514 /* alcDestroyContext
2516 * Remove a context from its device
2518 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2523 /* alcGetContextsDevice sets an error for invalid contexts */
2524 Device
= alcGetContextsDevice(context
);
2527 ReleaseContext(context
, Device
);
2528 if(!Device
->ContextList
)
2530 ALCdevice_StopPlayback(Device
);
2531 Device
->Flags
&= ~DEVICE_RUNNING
;
2538 /* alcGetCurrentContext
2540 * Returns the currently active context on the calling thread
2542 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2544 ALCcontext
*Context
;
2546 Context
= pthread_getspecific(LocalContext
);
2547 if(!Context
) Context
= GlobalContext
;
2552 /* alcGetThreadContext
2554 * Returns the currently active thread-local context
2556 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2558 ALCcontext
*Context
;
2559 Context
= pthread_getspecific(LocalContext
);
2564 /* alcMakeContextCurrent
2566 * Makes the given context the active process-wide context, and removes the
2567 * thread-local context for the calling thread.
2569 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2571 /* context must be valid or NULL */
2572 if(context
&& !(context
=VerifyContext(context
)))
2574 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2577 /* context's reference count is already incremented */
2578 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2579 if(context
) ALCcontext_DecRef(context
);
2581 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2583 pthread_setspecific(LocalContext
, NULL
);
2584 ALCcontext_DecRef(context
);
2590 /* alcSetThreadContext
2592 * Makes the given context the active context for the current thread
2594 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2598 /* context must be valid or NULL */
2599 if(context
&& !(context
=VerifyContext(context
)))
2601 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2604 /* context's reference count is already incremented */
2605 old
= pthread_getspecific(LocalContext
);
2606 pthread_setspecific(LocalContext
, context
);
2607 if(old
) ALCcontext_DecRef(old
);
2613 /* alcGetContextsDevice
2615 * Returns the device that a particular context is attached to
2617 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2621 if(!(Context
=VerifyContext(Context
)))
2623 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2626 Device
= Context
->Device
;
2627 ALCcontext_DecRef(Context
);
2635 * Opens the named device.
2637 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2645 if(!PlaybackBackend
.name
)
2647 alcSetError(NULL
, ALC_INVALID_VALUE
);
2651 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2654 device
= al_calloc(16, sizeof(ALCdevice
)+15+sizeof(ALeffectslot
));
2657 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2662 device
->Funcs
= &PlaybackBackend
.Funcs
;
2664 device
->Connected
= ALC_TRUE
;
2665 device
->Type
= Playback
;
2666 InitializeCriticalSection(&device
->Mutex
);
2667 device
->LastError
= ALC_NO_ERROR
;
2670 device
->Bs2b
= NULL
;
2671 device
->Bs2bLevel
= 0;
2672 device
->DeviceName
= NULL
;
2674 device
->ContextList
= NULL
;
2676 device
->MaxNoOfSources
= 256;
2677 device
->AuxiliaryEffectSlotMax
= 4;
2678 device
->NumAuxSends
= MAX_SENDS
;
2680 InitUIntMap(&device
->BufferMap
, ~0);
2681 InitUIntMap(&device
->EffectMap
, ~0);
2682 InitUIntMap(&device
->FilterMap
, ~0);
2685 device
->FmtChans
= DevFmtChannelsDefault
;
2686 device
->FmtType
= DevFmtTypeDefault
;
2687 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2688 device
->NumUpdates
= 4;
2689 device
->UpdateSize
= 1024;
2691 if(ConfigValueStr(NULL
, "channels", &fmt
))
2693 static const struct {
2694 const char name
[16];
2695 enum DevFmtChannels chans
;
2697 { "mono", DevFmtMono
},
2698 { "stereo", DevFmtStereo
},
2699 { "quad", DevFmtQuad
},
2700 { "surround51", DevFmtX51
},
2701 { "surround61", DevFmtX61
},
2702 { "surround71", DevFmtX71
},
2706 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2708 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2710 device
->FmtChans
= chanlist
[i
].chans
;
2711 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2715 if(i
== COUNTOF(chanlist
))
2716 ERR("Unsupported channels: %s\n", fmt
);
2718 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2720 static const struct {
2721 const char name
[16];
2722 enum DevFmtType type
;
2724 { "int8", DevFmtByte
},
2725 { "uint8", DevFmtUByte
},
2726 { "int16", DevFmtShort
},
2727 { "uint16", DevFmtUShort
},
2728 { "int32", DevFmtInt
},
2729 { "uint32", DevFmtUInt
},
2730 { "float32", DevFmtFloat
},
2734 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2736 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2738 device
->FmtType
= typelist
[i
].type
;
2739 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2743 if(i
== COUNTOF(typelist
))
2744 ERR("Unsupported sample-type: %s\n", fmt
);
2746 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2747 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2748 ConfigValueStr(NULL
, "format", &fmt
))
2750 static const struct {
2751 const char name
[32];
2752 enum DevFmtChannels channels
;
2753 enum DevFmtType type
;
2755 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2756 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2757 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2758 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2759 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2760 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2762 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2763 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2764 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2765 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2766 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2767 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2769 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2770 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2771 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2772 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2773 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2774 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2778 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2779 for(i
= 0;i
< COUNTOF(formats
);i
++)
2781 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2783 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2784 device
->FmtChans
= formats
[i
].channels
;
2785 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2786 device
->FmtType
= formats
[i
].type
;
2787 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2791 if(i
== COUNTOF(formats
))
2792 ERR("Unsupported format: %s\n", fmt
);
2794 #undef DEVICE_FORMAT_REQUEST
2796 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2798 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2799 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2800 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2801 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2804 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2805 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2807 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2808 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2809 if((CPUCapFlags
&CPU_CAP_SSE
))
2810 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2812 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2813 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2815 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2816 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2818 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2819 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2821 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2823 device
->NumStereoSources
= 1;
2824 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2826 // Find a playback device to open
2827 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2829 DeleteCriticalSection(&device
->Mutex
);
2831 alcSetError(NULL
, err
);
2835 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2837 device
->DefaultSlot
= (ALeffectslot
*)(((ALintptrEXT
)(device
+1)+15)&~15);
2838 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2840 device
->DefaultSlot
= NULL
;
2841 ERR("Failed to initialize the default effect slot\n");
2843 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2845 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2846 device
->DefaultSlot
= NULL
;
2847 ERR("Failed to initialize the default effect\n");
2852 device
->next
= DeviceList
;
2853 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2855 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2861 * Closes the given device.
2863 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2865 ALCdevice
*volatile*list
;
2870 while(*list
&& *list
!= Device
)
2871 list
= &(*list
)->next
;
2873 if(!*list
|| (*list
)->Type
== Capture
)
2875 alcSetError(*list
, ALC_INVALID_DEVICE
);
2880 *list
= (*list
)->next
;
2883 while((ctx
=Device
->ContextList
) != NULL
)
2885 WARN("Releasing context %p\n", ctx
);
2886 ReleaseContext(ctx
, Device
);
2888 if((Device
->Flags
&DEVICE_RUNNING
))
2889 ALCdevice_StopPlayback(Device
);
2890 Device
->Flags
&= ~DEVICE_RUNNING
;
2892 ALCdevice_DecRef(Device
);
2898 /************************************************
2899 * ALC capture functions
2900 ************************************************/
2901 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2903 ALCdevice
*device
= NULL
;
2908 if(!CaptureBackend
.name
)
2910 alcSetError(NULL
, ALC_INVALID_VALUE
);
2916 alcSetError(NULL
, ALC_INVALID_VALUE
);
2920 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2923 device
= al_calloc(16, sizeof(ALCdevice
));
2926 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2931 device
->Funcs
= &CaptureBackend
.Funcs
;
2933 device
->Connected
= ALC_TRUE
;
2934 device
->Type
= Capture
;
2935 InitializeCriticalSection(&device
->Mutex
);
2937 InitUIntMap(&device
->BufferMap
, ~0);
2938 InitUIntMap(&device
->EffectMap
, ~0);
2939 InitUIntMap(&device
->FilterMap
, ~0);
2941 device
->DeviceName
= NULL
;
2943 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2944 device
->Frequency
= frequency
;
2946 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2947 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2949 DeleteCriticalSection(&device
->Mutex
);
2951 alcSetError(NULL
, ALC_INVALID_ENUM
);
2955 device
->UpdateSize
= samples
;
2956 device
->NumUpdates
= 1;
2958 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2960 DeleteCriticalSection(&device
->Mutex
);
2962 alcSetError(NULL
, err
);
2967 device
->next
= DeviceList
;
2968 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2970 TRACE("Created device %p\n", device
);
2974 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2976 ALCdevice
*volatile*list
;
2980 while(*list
&& *list
!= Device
)
2981 list
= &(*list
)->next
;
2983 if(!*list
|| (*list
)->Type
!= Capture
)
2985 alcSetError(*list
, ALC_INVALID_DEVICE
);
2990 *list
= (*list
)->next
;
2993 ALCdevice_DecRef(Device
);
2998 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3000 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3001 alcSetError(device
, ALC_INVALID_DEVICE
);
3004 ALCdevice_Lock(device
);
3005 if(device
->Connected
)
3007 if(!(device
->Flags
&DEVICE_RUNNING
))
3008 ALCdevice_StartCapture(device
);
3009 device
->Flags
|= DEVICE_RUNNING
;
3011 ALCdevice_Unlock(device
);
3014 if(device
) ALCdevice_DecRef(device
);
3017 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3019 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3020 alcSetError(device
, ALC_INVALID_DEVICE
);
3023 ALCdevice_Lock(device
);
3024 if((device
->Flags
&DEVICE_RUNNING
))
3025 ALCdevice_StopCapture(device
);
3026 device
->Flags
&= ~DEVICE_RUNNING
;
3027 ALCdevice_Unlock(device
);
3030 if(device
) ALCdevice_DecRef(device
);
3033 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3035 if(!(device
=VerifyDevice(device
)) && device
->Type
!= Capture
)
3036 alcSetError(device
, ALC_INVALID_DEVICE
);
3039 ALCenum err
= ALC_INVALID_VALUE
;
3041 ALCdevice_Lock(device
);
3042 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
3043 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
3044 ALCdevice_Unlock(device
);
3046 if(err
!= ALC_NO_ERROR
)
3047 alcSetError(device
, err
);
3049 if(device
) ALCdevice_DecRef(device
);
3053 /************************************************
3054 * ALC loopback functions
3055 ************************************************/
3057 /* alcLoopbackOpenDeviceSOFT
3059 * Open a loopback device, for manual rendering.
3061 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3067 /* Make sure the device name, if specified, is us. */
3068 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3070 alcSetError(NULL
, ALC_INVALID_VALUE
);
3074 device
= al_calloc(16, sizeof(ALCdevice
));
3077 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3082 device
->Funcs
= &BackendLoopback
.Funcs
;
3084 device
->Connected
= ALC_TRUE
;
3085 device
->Type
= Loopback
;
3086 InitializeCriticalSection(&device
->Mutex
);
3087 device
->LastError
= ALC_NO_ERROR
;
3090 device
->Bs2b
= NULL
;
3091 device
->Bs2bLevel
= 0;
3092 device
->DeviceName
= NULL
;
3094 device
->ContextList
= NULL
;
3096 device
->MaxNoOfSources
= 256;
3097 device
->AuxiliaryEffectSlotMax
= 4;
3098 device
->NumAuxSends
= MAX_SENDS
;
3100 InitUIntMap(&device
->BufferMap
, ~0);
3101 InitUIntMap(&device
->EffectMap
, ~0);
3102 InitUIntMap(&device
->FilterMap
, ~0);
3105 device
->NumUpdates
= 0;
3106 device
->UpdateSize
= 0;
3108 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3109 device
->FmtChans
= DevFmtChannelsDefault
;
3110 device
->FmtType
= DevFmtTypeDefault
;
3112 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3113 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3115 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3116 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3118 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3119 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3121 device
->NumStereoSources
= 1;
3122 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3124 // Open the "backend"
3125 ALCdevice_OpenPlayback(device
, "Loopback");
3127 device
->next
= DeviceList
;
3128 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
3130 TRACE("Created device %p\n", device
);
3134 /* alcIsRenderFormatSupportedSOFT
3136 * Determines if the loopback device supports the given format for rendering.
3138 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3140 ALCboolean ret
= ALC_FALSE
;
3142 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3143 alcSetError(device
, ALC_INVALID_DEVICE
);
3145 alcSetError(device
, ALC_INVALID_VALUE
);
3148 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3149 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3150 freq
>= MIN_OUTPUT_RATE
)
3153 if(device
) ALCdevice_DecRef(device
);
3158 /* alcRenderSamplesSOFT
3160 * Renders some samples into a buffer, using the format last set by the
3161 * attributes given to alcCreateContext.
3163 ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3165 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3166 alcSetError(device
, ALC_INVALID_DEVICE
);
3167 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3168 alcSetError(device
, ALC_INVALID_VALUE
);
3170 aluMixData(device
, buffer
, samples
);
3171 if(device
) ALCdevice_DecRef(device
);