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
37 #include "alAuxEffectSlot.h"
43 /************************************************
45 ************************************************/
46 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
47 static struct BackendInfo BackendList
[] = {
48 #ifdef HAVE_PULSEAUDIO
49 { "pulse", alc_pulse_init
, alc_pulse_deinit
, alc_pulse_probe
, EmptyFuncs
},
52 { "alsa", alc_alsa_init
, alc_alsa_deinit
, alc_alsa_probe
, EmptyFuncs
},
55 { "core", alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, EmptyFuncs
},
58 { "oss", alc_oss_init
, alc_oss_deinit
, alc_oss_probe
, EmptyFuncs
},
61 { "solaris", alc_solaris_init
, alc_solaris_deinit
, alc_solaris_probe
, EmptyFuncs
},
64 { "sndio", alc_sndio_init
, alc_sndio_deinit
, alc_sndio_probe
, EmptyFuncs
},
67 { "mmdevapi", alcMMDevApiInit
, alcMMDevApiDeinit
, alcMMDevApiProbe
, EmptyFuncs
},
70 { "dsound", alcDSoundInit
, alcDSoundDeinit
, alcDSoundProbe
, EmptyFuncs
},
73 { "winmm", alcWinMMInit
, alcWinMMDeinit
, alcWinMMProbe
, EmptyFuncs
},
76 { "port", alc_pa_init
, alc_pa_deinit
, alc_pa_probe
, EmptyFuncs
},
79 { "opensl", alc_opensl_init
, alc_opensl_deinit
, alc_opensl_probe
, EmptyFuncs
},
82 { "null", alc_null_init
, alc_null_deinit
, alc_null_probe
, EmptyFuncs
},
84 { "wave", alc_wave_init
, alc_wave_deinit
, alc_wave_probe
, EmptyFuncs
},
87 { NULL
, NULL
, NULL
, NULL
, EmptyFuncs
}
89 static struct BackendInfo BackendLoopback
= {
90 "loopback", alc_loopback_init
, alc_loopback_deinit
, alc_loopback_probe
, EmptyFuncs
94 static struct BackendInfo PlaybackBackend
;
95 static struct BackendInfo CaptureBackend
;
97 /************************************************
98 * Functions, enums, and errors
99 ************************************************/
100 typedef struct ALCfunction
{
101 const ALCchar
*funcName
;
105 typedef struct ALCenums
{
106 const ALCchar
*enumName
;
110 #define DECL(x) { #x, (ALCvoid*)(x) }
111 static const ALCfunction alcFunctions
[] = {
112 DECL(alcCreateContext
),
113 DECL(alcMakeContextCurrent
),
114 DECL(alcProcessContext
),
115 DECL(alcSuspendContext
),
116 DECL(alcDestroyContext
),
117 DECL(alcGetCurrentContext
),
118 DECL(alcGetContextsDevice
),
120 DECL(alcCloseDevice
),
122 DECL(alcIsExtensionPresent
),
123 DECL(alcGetProcAddress
),
124 DECL(alcGetEnumValue
),
126 DECL(alcGetIntegerv
),
127 DECL(alcCaptureOpenDevice
),
128 DECL(alcCaptureCloseDevice
),
129 DECL(alcCaptureStart
),
130 DECL(alcCaptureStop
),
131 DECL(alcCaptureSamples
),
133 DECL(alcSetThreadContext
),
134 DECL(alcGetThreadContext
),
136 DECL(alcLoopbackOpenDeviceSOFT
),
137 DECL(alcIsRenderFormatSupportedSOFT
),
138 DECL(alcRenderSamplesSOFT
),
153 DECL(alIsExtensionPresent
),
154 DECL(alGetProcAddress
),
155 DECL(alGetEnumValue
),
162 DECL(alGetListenerf
),
163 DECL(alGetListener3f
),
164 DECL(alGetListenerfv
),
165 DECL(alGetListeneri
),
166 DECL(alGetListener3i
),
167 DECL(alGetListeneriv
),
169 DECL(alDeleteSources
),
185 DECL(alSourceRewindv
),
186 DECL(alSourcePausev
),
189 DECL(alSourceRewind
),
191 DECL(alSourceQueueBuffers
),
192 DECL(alSourceUnqueueBuffers
),
194 DECL(alDeleteBuffers
),
209 DECL(alDopplerFactor
),
210 DECL(alDopplerVelocity
),
211 DECL(alSpeedOfSound
),
212 DECL(alDistanceModel
),
215 DECL(alDeleteFilters
),
226 DECL(alDeleteEffects
),
236 DECL(alGenAuxiliaryEffectSlots
),
237 DECL(alDeleteAuxiliaryEffectSlots
),
238 DECL(alIsAuxiliaryEffectSlot
),
239 DECL(alAuxiliaryEffectSloti
),
240 DECL(alAuxiliaryEffectSlotiv
),
241 DECL(alAuxiliaryEffectSlotf
),
242 DECL(alAuxiliaryEffectSlotfv
),
243 DECL(alGetAuxiliaryEffectSloti
),
244 DECL(alGetAuxiliaryEffectSlotiv
),
245 DECL(alGetAuxiliaryEffectSlotf
),
246 DECL(alGetAuxiliaryEffectSlotfv
),
248 DECL(alBufferSubDataSOFT
),
250 DECL(alBufferSamplesSOFT
),
251 DECL(alBufferSubSamplesSOFT
),
252 DECL(alGetBufferSamplesSOFT
),
253 DECL(alIsBufferFormatSupportedSOFT
),
255 DECL(alDeferUpdatesSOFT
),
256 DECL(alProcessUpdatesSOFT
),
262 #define DECL(x) { #x, (x) }
263 static const ALCenums enumeration
[] = {
268 DECL(ALC_MAJOR_VERSION
),
269 DECL(ALC_MINOR_VERSION
),
270 DECL(ALC_ATTRIBUTES_SIZE
),
271 DECL(ALC_ALL_ATTRIBUTES
),
272 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
273 DECL(ALC_DEVICE_SPECIFIER
),
274 DECL(ALC_ALL_DEVICES_SPECIFIER
),
275 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
276 DECL(ALC_EXTENSIONS
),
280 DECL(ALC_MONO_SOURCES
),
281 DECL(ALC_STEREO_SOURCES
),
282 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
283 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
284 DECL(ALC_CAPTURE_SAMPLES
),
287 DECL(ALC_EFX_MAJOR_VERSION
),
288 DECL(ALC_EFX_MINOR_VERSION
),
289 DECL(ALC_MAX_AUXILIARY_SENDS
),
291 DECL(ALC_FORMAT_CHANNELS_SOFT
),
292 DECL(ALC_FORMAT_TYPE_SOFT
),
295 DECL(ALC_STEREO_SOFT
),
297 DECL(ALC_5POINT1_SOFT
),
298 DECL(ALC_6POINT1_SOFT
),
299 DECL(ALC_7POINT1_SOFT
),
302 DECL(ALC_UNSIGNED_BYTE_SOFT
),
303 DECL(ALC_SHORT_SOFT
),
304 DECL(ALC_UNSIGNED_SHORT_SOFT
),
306 DECL(ALC_UNSIGNED_INT_SOFT
),
307 DECL(ALC_FLOAT_SOFT
),
310 DECL(ALC_INVALID_DEVICE
),
311 DECL(ALC_INVALID_CONTEXT
),
312 DECL(ALC_INVALID_ENUM
),
313 DECL(ALC_INVALID_VALUE
),
314 DECL(ALC_OUT_OF_MEMORY
),
322 DECL(AL_SOURCE_RELATIVE
),
323 DECL(AL_CONE_INNER_ANGLE
),
324 DECL(AL_CONE_OUTER_ANGLE
),
334 DECL(AL_ORIENTATION
),
335 DECL(AL_REFERENCE_DISTANCE
),
336 DECL(AL_ROLLOFF_FACTOR
),
337 DECL(AL_CONE_OUTER_GAIN
),
338 DECL(AL_MAX_DISTANCE
),
340 DECL(AL_SAMPLE_OFFSET
),
341 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
342 DECL(AL_BYTE_OFFSET
),
343 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
344 DECL(AL_SOURCE_TYPE
),
347 DECL(AL_UNDETERMINED
),
348 DECL(AL_METERS_PER_UNIT
),
349 DECL(AL_DIRECT_CHANNELS_SOFT
),
351 DECL(AL_DIRECT_FILTER
),
352 DECL(AL_AUXILIARY_SEND_FILTER
),
353 DECL(AL_AIR_ABSORPTION_FACTOR
),
354 DECL(AL_ROOM_ROLLOFF_FACTOR
),
355 DECL(AL_CONE_OUTER_GAINHF
),
356 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
357 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
358 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
360 DECL(AL_SOURCE_STATE
),
366 DECL(AL_BUFFERS_QUEUED
),
367 DECL(AL_BUFFERS_PROCESSED
),
369 DECL(AL_FORMAT_MONO8
),
370 DECL(AL_FORMAT_MONO16
),
371 DECL(AL_FORMAT_MONO_FLOAT32
),
372 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
373 DECL(AL_FORMAT_STEREO8
),
374 DECL(AL_FORMAT_STEREO16
),
375 DECL(AL_FORMAT_STEREO_FLOAT32
),
376 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
377 DECL(AL_FORMAT_MONO_IMA4
),
378 DECL(AL_FORMAT_STEREO_IMA4
),
379 DECL(AL_FORMAT_QUAD8_LOKI
),
380 DECL(AL_FORMAT_QUAD16_LOKI
),
381 DECL(AL_FORMAT_QUAD8
),
382 DECL(AL_FORMAT_QUAD16
),
383 DECL(AL_FORMAT_QUAD32
),
384 DECL(AL_FORMAT_51CHN8
),
385 DECL(AL_FORMAT_51CHN16
),
386 DECL(AL_FORMAT_51CHN32
),
387 DECL(AL_FORMAT_61CHN8
),
388 DECL(AL_FORMAT_61CHN16
),
389 DECL(AL_FORMAT_61CHN32
),
390 DECL(AL_FORMAT_71CHN8
),
391 DECL(AL_FORMAT_71CHN16
),
392 DECL(AL_FORMAT_71CHN32
),
393 DECL(AL_FORMAT_REAR8
),
394 DECL(AL_FORMAT_REAR16
),
395 DECL(AL_FORMAT_REAR32
),
396 DECL(AL_FORMAT_MONO_MULAW
),
397 DECL(AL_FORMAT_MONO_MULAW_EXT
),
398 DECL(AL_FORMAT_STEREO_MULAW
),
399 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
400 DECL(AL_FORMAT_QUAD_MULAW
),
401 DECL(AL_FORMAT_51CHN_MULAW
),
402 DECL(AL_FORMAT_61CHN_MULAW
),
403 DECL(AL_FORMAT_71CHN_MULAW
),
404 DECL(AL_FORMAT_REAR_MULAW
),
405 DECL(AL_FORMAT_MONO_ALAW_EXT
),
406 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
409 DECL(AL_MONO16_SOFT
),
410 DECL(AL_MONO32F_SOFT
),
411 DECL(AL_STEREO8_SOFT
),
412 DECL(AL_STEREO16_SOFT
),
413 DECL(AL_STEREO32F_SOFT
),
415 DECL(AL_QUAD16_SOFT
),
416 DECL(AL_QUAD32F_SOFT
),
418 DECL(AL_REAR16_SOFT
),
419 DECL(AL_REAR32F_SOFT
),
420 DECL(AL_5POINT1_8_SOFT
),
421 DECL(AL_5POINT1_16_SOFT
),
422 DECL(AL_5POINT1_32F_SOFT
),
423 DECL(AL_6POINT1_8_SOFT
),
424 DECL(AL_6POINT1_16_SOFT
),
425 DECL(AL_6POINT1_32F_SOFT
),
426 DECL(AL_7POINT1_8_SOFT
),
427 DECL(AL_7POINT1_16_SOFT
),
428 DECL(AL_7POINT1_32F_SOFT
),
431 DECL(AL_STEREO_SOFT
),
434 DECL(AL_5POINT1_SOFT
),
435 DECL(AL_6POINT1_SOFT
),
436 DECL(AL_7POINT1_SOFT
),
439 DECL(AL_UNSIGNED_BYTE_SOFT
),
441 DECL(AL_UNSIGNED_SHORT_SOFT
),
443 DECL(AL_UNSIGNED_INT_SOFT
),
445 DECL(AL_DOUBLE_SOFT
),
447 DECL(AL_UNSIGNED_BYTE3_SOFT
),
453 DECL(AL_INTERNAL_FORMAT_SOFT
),
454 DECL(AL_BYTE_LENGTH_SOFT
),
455 DECL(AL_SAMPLE_LENGTH_SOFT
),
456 DECL(AL_SEC_LENGTH_SOFT
),
463 DECL(AL_INVALID_NAME
),
464 DECL(AL_INVALID_ENUM
),
465 DECL(AL_INVALID_VALUE
),
466 DECL(AL_INVALID_OPERATION
),
467 DECL(AL_OUT_OF_MEMORY
),
474 DECL(AL_DOPPLER_FACTOR
),
475 DECL(AL_DOPPLER_VELOCITY
),
476 DECL(AL_DISTANCE_MODEL
),
477 DECL(AL_SPEED_OF_SOUND
),
478 DECL(AL_SOURCE_DISTANCE_MODEL
),
479 DECL(AL_DEFERRED_UPDATES_SOFT
),
481 DECL(AL_INVERSE_DISTANCE
),
482 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
483 DECL(AL_LINEAR_DISTANCE
),
484 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
485 DECL(AL_EXPONENT_DISTANCE
),
486 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
488 DECL(AL_FILTER_TYPE
),
489 DECL(AL_FILTER_NULL
),
490 DECL(AL_FILTER_LOWPASS
),
492 DECL(AL_FILTER_HIGHPASS
),
493 DECL(AL_FILTER_BANDPASS
),
496 DECL(AL_LOWPASS_GAIN
),
497 DECL(AL_LOWPASS_GAINHF
),
499 DECL(AL_EFFECT_TYPE
),
500 DECL(AL_EFFECT_NULL
),
501 DECL(AL_EFFECT_REVERB
),
502 DECL(AL_EFFECT_EAXREVERB
),
504 DECL(AL_EFFECT_CHORUS
),
505 DECL(AL_EFFECT_DISTORTION
),
507 DECL(AL_EFFECT_ECHO
),
509 DECL(AL_EFFECT_FLANGER
),
510 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
511 DECL(AL_EFFECT_VOCAL_MORPHER
),
512 DECL(AL_EFFECT_PITCH_SHIFTER
),
514 DECL(AL_EFFECT_RING_MODULATOR
),
516 DECL(AL_EFFECT_AUTOWAH
),
517 DECL(AL_EFFECT_COMPRESSOR
),
518 DECL(AL_EFFECT_EQUALIZER
),
520 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
521 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
523 DECL(AL_EAXREVERB_DENSITY
),
524 DECL(AL_EAXREVERB_DIFFUSION
),
525 DECL(AL_EAXREVERB_GAIN
),
526 DECL(AL_EAXREVERB_GAINHF
),
527 DECL(AL_EAXREVERB_GAINLF
),
528 DECL(AL_EAXREVERB_DECAY_TIME
),
529 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
530 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
531 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
532 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
533 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
534 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
535 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
536 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
537 DECL(AL_EAXREVERB_ECHO_TIME
),
538 DECL(AL_EAXREVERB_ECHO_DEPTH
),
539 DECL(AL_EAXREVERB_MODULATION_TIME
),
540 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
541 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
542 DECL(AL_EAXREVERB_HFREFERENCE
),
543 DECL(AL_EAXREVERB_LFREFERENCE
),
544 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
545 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
547 DECL(AL_REVERB_DENSITY
),
548 DECL(AL_REVERB_DIFFUSION
),
549 DECL(AL_REVERB_GAIN
),
550 DECL(AL_REVERB_GAINHF
),
551 DECL(AL_REVERB_DECAY_TIME
),
552 DECL(AL_REVERB_DECAY_HFRATIO
),
553 DECL(AL_REVERB_REFLECTIONS_GAIN
),
554 DECL(AL_REVERB_REFLECTIONS_DELAY
),
555 DECL(AL_REVERB_LATE_REVERB_GAIN
),
556 DECL(AL_REVERB_LATE_REVERB_DELAY
),
557 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
558 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
559 DECL(AL_REVERB_DECAY_HFLIMIT
),
562 DECL(AL_ECHO_LRDELAY
),
563 DECL(AL_ECHO_DAMPING
),
564 DECL(AL_ECHO_FEEDBACK
),
565 DECL(AL_ECHO_SPREAD
),
567 DECL(AL_RING_MODULATOR_FREQUENCY
),
568 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
569 DECL(AL_RING_MODULATOR_WAVEFORM
),
571 DECL(AL_DEDICATED_GAIN
),
577 static const ALCchar alcNoError
[] = "No Error";
578 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
579 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
580 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
581 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
582 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
585 /************************************************
587 ************************************************/
589 /* Enumerated device names */
590 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
591 static ALCchar
*alcAllDevicesList
;
592 static ALCchar
*alcCaptureDeviceList
;
593 /* Sizes only include the first ending null character, not the second */
594 static size_t alcAllDevicesListSize
;
595 static size_t alcCaptureDeviceListSize
;
597 /* Default is always the first in the list */
598 static ALCchar
*alcDefaultAllDevicesSpecifier
;
599 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
601 /* Default context extensions */
602 static const ALchar alExtList
[] =
603 "AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
604 "AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
605 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
606 "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
607 "AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
609 static volatile ALCenum LastNullDeviceError
= ALC_NO_ERROR
;
611 /* Thread-local current context */
612 static pthread_key_t LocalContext
;
613 /* Process-wide current context */
614 static ALCcontext
*volatile GlobalContext
= NULL
;
616 /* Mixing thread piority level */
621 enum LogLevel LogLevel
= LogWarning
;
623 enum LogLevel LogLevel
= LogError
;
626 /* Flag to trap ALC device errors */
627 static ALCboolean TrapALCError
= ALC_FALSE
;
629 /* One-time configuration init control */
630 static pthread_once_t alc_config_once
= PTHREAD_ONCE_INIT
;
632 /* Default effect that applies to sources that don't have an effect on send 0 */
633 static ALeffect DefaultEffect
;
636 /************************************************
638 ************************************************/
639 static const ALCchar alcNoDeviceExtList
[] =
640 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
641 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
642 static const ALCchar alcExtensionList
[] =
643 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
644 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
645 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
646 static const ALCint alcMajorVersion
= 1;
647 static const ALCint alcMinorVersion
= 1;
649 static const ALCint alcEFXMajorVersion
= 1;
650 static const ALCint alcEFXMinorVersion
= 0;
653 /************************************************
655 ************************************************/
656 static ALCdevice
*volatile DeviceList
= NULL
;
658 static CRITICAL_SECTION ListLock
;
660 static void LockLists(void)
662 EnterCriticalSection(&ListLock
);
664 static void UnlockLists(void)
666 LeaveCriticalSection(&ListLock
);
669 /************************************************
670 * Library initialization
671 ************************************************/
673 static void alc_init(void);
674 static void alc_deinit(void);
675 static void alc_deinit_safe(void);
677 UIntMap TlsDestructor
;
679 #ifndef AL_LIBTYPE_STATIC
680 BOOL APIENTRY
DllMain(HINSTANCE hModule
,DWORD ul_reason_for_call
,LPVOID lpReserved
)
684 // Perform actions based on the reason for calling.
685 switch(ul_reason_for_call
)
687 case DLL_PROCESS_ATTACH
:
688 /* Pin the DLL so we won't get unloaded until the process terminates */
689 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
690 (WCHAR
*)hModule
, &hModule
);
691 InitUIntMap(&TlsDestructor
, ~0);
695 case DLL_THREAD_DETACH
:
696 LockUIntMapRead(&TlsDestructor
);
697 for(i
= 0;i
< TlsDestructor
.size
;i
++)
699 void *ptr
= pthread_getspecific(TlsDestructor
.array
[i
].key
);
700 void (*callback
)(void*) = (void(*)(void*))TlsDestructor
.array
[i
].value
;
704 UnlockUIntMapRead(&TlsDestructor
);
707 case DLL_PROCESS_DETACH
:
712 ResetUIntMap(&TlsDestructor
);
717 #elif defined(_MSC_VER)
718 #pragma section(".CRT$XCU",read)
719 static void alc_constructor(void);
720 static void alc_destructor(void);
721 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
723 static void alc_constructor(void)
725 atexit(alc_destructor
);
729 static void alc_destructor(void)
733 #elif defined(HAVE_GCC_DESTRUCTOR)
734 static void alc_init(void) __attribute__((constructor
));
735 static void alc_deinit(void) __attribute__((destructor
));
737 #error "No static initialization available on this platform!"
740 #elif defined(HAVE_GCC_DESTRUCTOR)
742 static void alc_init(void) __attribute__((constructor
));
743 static void alc_deinit(void) __attribute__((destructor
));
746 #error "No global initialization available on this platform!"
749 static void ReleaseThreadCtx(void *ptr
);
750 static void alc_init(void)
756 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
757 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
760 str
= getenv("__ALSOFT_REVERSE_Z");
761 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
764 pthread_key_create(&LocalContext
, ReleaseThreadCtx
);
765 InitializeCriticalSection(&ListLock
);
769 static void alc_initconfig(void)
771 const char *devs
, *str
;
775 str
= getenv("ALSOFT_LOGLEVEL");
778 long lvl
= strtol(str
, NULL
, 0);
779 if(lvl
>= NoLog
&& lvl
<= LogRef
)
783 str
= getenv("ALSOFT_LOGFILE");
786 FILE *logfile
= fopen(str
, "wat");
787 if(logfile
) LogFile
= logfile
;
788 else ERR("Failed to open log file '%s'\n", str
);
801 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
803 if(ConfigValueStr(NULL
, "resampler", &str
))
805 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
806 DefaultResampler
= PointResampler
;
807 else if(strcasecmp(str
, "linear") == 0)
808 DefaultResampler
= LinearResampler
;
809 else if(strcasecmp(str
, "cubic") == 0)
810 DefaultResampler
= CubicResampler
;
815 n
= strtol(str
, &end
, 0);
816 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
817 DefaultResampler
= n
;
819 WARN("Invalid resampler: %s\n", str
);
823 str
= getenv("ALSOFT_TRAP_ERROR");
824 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
826 TrapALError
= AL_TRUE
;
827 TrapALCError
= AL_TRUE
;
831 str
= getenv("ALSOFT_TRAP_AL_ERROR");
832 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
833 TrapALError
= AL_TRUE
;
834 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
836 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
837 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
838 TrapALCError
= ALC_TRUE
;
839 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
842 if(ConfigValueFloat("reverb", "boost", &valf
))
843 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
845 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
847 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
848 ConfigValueStr(NULL
, "drivers", &devs
))
852 const char *next
= devs
;
853 int endlist
, delitem
;
858 next
= strchr(devs
, ',');
860 delitem
= (devs
[0] == '-');
861 if(devs
[0] == '-') devs
++;
863 if(!devs
[0] || devs
[0] == ',')
870 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
871 for(n
= i
;BackendList
[n
].Init
;n
++)
873 if(len
== strlen(BackendList
[n
].name
) &&
874 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
879 BackendList
[n
] = BackendList
[n
+1];
881 } while(BackendList
[n
].Init
);
885 struct BackendInfo Bkp
= BackendList
[n
];
888 BackendList
[n
] = BackendList
[n
-1];
891 BackendList
[n
] = Bkp
;
902 BackendList
[i
].name
= NULL
;
903 BackendList
[i
].Init
= NULL
;
904 BackendList
[i
].Deinit
= NULL
;
905 BackendList
[i
].Probe
= NULL
;
909 for(i
= 0;BackendList
[i
].Init
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
911 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
913 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
917 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
918 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
920 PlaybackBackend
= BackendList
[i
];
921 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
923 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
925 CaptureBackend
= BackendList
[i
];
926 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
929 BackendLoopback
.Init(&BackendLoopback
.Funcs
);
931 if(ConfigValueStr(NULL
, "excludefx", &str
))
934 const char *next
= str
;
938 next
= strchr(str
, ',');
940 if(!str
[0] || next
== str
)
943 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
944 for(n
= 0;EffectList
[n
].name
;n
++)
946 if(len
== strlen(EffectList
[n
].name
) &&
947 strncmp(EffectList
[n
].name
, str
, len
) == 0)
948 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
953 InitEffect(&DefaultEffect
);
954 str
= getenv("ALSOFT_DEFAULT_REVERB");
955 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
956 LoadReverbPreset(str
, &DefaultEffect
);
958 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
961 /************************************************
962 * Library deinitialization
963 ************************************************/
964 static void alc_cleanup(void)
968 free(alcAllDevicesList
); alcAllDevicesList
= NULL
;
969 alcAllDevicesListSize
= 0;
970 free(alcCaptureDeviceList
); alcCaptureDeviceList
= NULL
;
971 alcCaptureDeviceListSize
= 0;
973 free(alcDefaultAllDevicesSpecifier
);
974 alcDefaultAllDevicesSpecifier
= NULL
;
975 free(alcCaptureDefaultDeviceSpecifier
);
976 alcCaptureDefaultDeviceSpecifier
= NULL
;
978 if((dev
=ExchangePtr((XchgPtr
*)&DeviceList
, NULL
)) != NULL
)
983 } while((dev
=dev
->next
) != NULL
);
984 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
988 static void alc_deinit_safe(void)
996 DeleteCriticalSection(&ListLock
);
997 pthread_key_delete(LocalContext
);
999 if(LogFile
!= stderr
)
1004 static void alc_deinit(void)
1010 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1011 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1013 for(i
= 0;BackendList
[i
].Deinit
;i
++)
1014 BackendList
[i
].Deinit();
1015 BackendLoopback
.Deinit();
1021 /************************************************
1022 * Device enumeration
1023 ************************************************/
1024 static void ProbeList(ALCchar
**list
, size_t *listsize
, enum DevProbe type
)
1033 if(type
== ALL_DEVICE_PROBE
&& PlaybackBackend
.Probe
)
1034 PlaybackBackend
.Probe(type
);
1035 else if(type
== CAPTURE_DEVICE_PROBE
&& CaptureBackend
.Probe
)
1036 CaptureBackend
.Probe(type
);
1040 static void ProbeAllDevicesList(void)
1041 { ProbeList(&alcAllDevicesList
, &alcAllDevicesListSize
, ALL_DEVICE_PROBE
); }
1042 static void ProbeCaptureDeviceList(void)
1043 { ProbeList(&alcCaptureDeviceList
, &alcCaptureDeviceListSize
, CAPTURE_DEVICE_PROBE
); }
1046 static void AppendList(const ALCchar
*name
, ALCchar
**List
, size_t *ListSize
)
1048 size_t len
= strlen(name
);
1054 temp
= realloc(*List
, (*ListSize
) + len
+ 2);
1057 ERR("Realloc failed to add %s!\n", name
);
1062 memcpy((*List
)+(*ListSize
), name
, len
+1);
1064 (*List
)[*ListSize
] = 0;
1067 #define DECL_APPEND_LIST_FUNC(type) \
1068 void Append##type##List(const ALCchar *name) \
1069 { AppendList(name, &alc##type##List, &alc##type##ListSize); }
1071 DECL_APPEND_LIST_FUNC(AllDevices
)
1072 DECL_APPEND_LIST_FUNC(CaptureDevice
)
1074 #undef DECL_APPEND_LIST_FUNC
1077 /************************************************
1078 * Device format information
1079 ************************************************/
1080 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1084 case DevFmtByte
: return "Signed Byte";
1085 case DevFmtUByte
: return "Unsigned Byte";
1086 case DevFmtShort
: return "Signed Short";
1087 case DevFmtUShort
: return "Unsigned Short";
1088 case DevFmtInt
: return "Signed Int";
1089 case DevFmtUInt
: return "Unsigned Int";
1090 case DevFmtFloat
: return "Float";
1092 return "(unknown type)";
1094 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1098 case DevFmtMono
: return "Mono";
1099 case DevFmtStereo
: return "Stereo";
1100 case DevFmtQuad
: return "Quadraphonic";
1101 case DevFmtX51
: return "5.1 Surround";
1102 case DevFmtX51Side
: return "5.1 Side";
1103 case DevFmtX61
: return "6.1 Surround";
1104 case DevFmtX71
: return "7.1 Surround";
1106 return "(unknown channels)";
1109 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1113 case DevFmtByte
: return sizeof(ALbyte
);
1114 case DevFmtUByte
: return sizeof(ALubyte
);
1115 case DevFmtShort
: return sizeof(ALshort
);
1116 case DevFmtUShort
: return sizeof(ALushort
);
1117 case DevFmtInt
: return sizeof(ALint
);
1118 case DevFmtUInt
: return sizeof(ALuint
);
1119 case DevFmtFloat
: return sizeof(ALfloat
);
1123 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1127 case DevFmtMono
: return 1;
1128 case DevFmtStereo
: return 2;
1129 case DevFmtQuad
: return 4;
1130 case DevFmtX51
: return 6;
1131 case DevFmtX51Side
: return 6;
1132 case DevFmtX61
: return 7;
1133 case DevFmtX71
: return 8;
1138 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1139 enum DevFmtType
*type
)
1141 static const struct {
1143 enum DevFmtChannels channels
;
1144 enum DevFmtType type
;
1146 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1147 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1148 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1150 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1151 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1152 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1154 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1155 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1156 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1158 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1159 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1160 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1162 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1163 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1164 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1166 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1167 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1168 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1172 for(i
= 0;i
< COUNTOF(list
);i
++)
1174 if(list
[i
].format
== format
)
1176 *chans
= list
[i
].channels
;
1177 *type
= list
[i
].type
;
1185 static ALCboolean
IsValidALCType(ALCenum type
)
1190 case ALC_UNSIGNED_BYTE_SOFT
:
1191 case ALC_SHORT_SOFT
:
1192 case ALC_UNSIGNED_SHORT_SOFT
:
1194 case ALC_UNSIGNED_INT_SOFT
:
1195 case ALC_FLOAT_SOFT
:
1201 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1206 case ALC_STEREO_SOFT
:
1208 case ALC_5POINT1_SOFT
:
1209 case ALC_6POINT1_SOFT
:
1210 case ALC_7POINT1_SOFT
:
1217 /************************************************
1218 * Miscellaneous ALC helpers
1219 ************************************************/
1221 /* SetDefaultWFXChannelOrder
1223 * Sets the default channel order used by WaveFormatEx.
1225 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1227 switch(device
->FmtChans
)
1229 case DevFmtMono
: device
->DevChannels
[0] = FrontCenter
; break;
1231 case DevFmtStereo
: device
->DevChannels
[0] = FrontLeft
;
1232 device
->DevChannels
[1] = FrontRight
; break;
1234 case DevFmtQuad
: device
->DevChannels
[0] = FrontLeft
;
1235 device
->DevChannels
[1] = FrontRight
;
1236 device
->DevChannels
[2] = BackLeft
;
1237 device
->DevChannels
[3] = BackRight
; break;
1239 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1240 device
->DevChannels
[1] = FrontRight
;
1241 device
->DevChannels
[2] = FrontCenter
;
1242 device
->DevChannels
[3] = LFE
;
1243 device
->DevChannels
[4] = BackLeft
;
1244 device
->DevChannels
[5] = BackRight
; break;
1246 case DevFmtX51Side
: device
->DevChannels
[0] = FrontLeft
;
1247 device
->DevChannels
[1] = FrontRight
;
1248 device
->DevChannels
[2] = FrontCenter
;
1249 device
->DevChannels
[3] = LFE
;
1250 device
->DevChannels
[4] = SideLeft
;
1251 device
->DevChannels
[5] = SideRight
; break;
1253 case DevFmtX61
: device
->DevChannels
[0] = FrontLeft
;
1254 device
->DevChannels
[1] = FrontRight
;
1255 device
->DevChannels
[2] = FrontCenter
;
1256 device
->DevChannels
[3] = LFE
;
1257 device
->DevChannels
[4] = BackCenter
;
1258 device
->DevChannels
[5] = SideLeft
;
1259 device
->DevChannels
[6] = SideRight
; break;
1261 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1262 device
->DevChannels
[1] = FrontRight
;
1263 device
->DevChannels
[2] = FrontCenter
;
1264 device
->DevChannels
[3] = LFE
;
1265 device
->DevChannels
[4] = BackLeft
;
1266 device
->DevChannels
[5] = BackRight
;
1267 device
->DevChannels
[6] = SideLeft
;
1268 device
->DevChannels
[7] = SideRight
; break;
1272 /* SetDefaultChannelOrder
1274 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1276 void SetDefaultChannelOrder(ALCdevice
*device
)
1278 switch(device
->FmtChans
)
1280 case DevFmtX51
: device
->DevChannels
[0] = FrontLeft
;
1281 device
->DevChannels
[1] = FrontRight
;
1282 device
->DevChannels
[2] = BackLeft
;
1283 device
->DevChannels
[3] = BackRight
;
1284 device
->DevChannels
[4] = FrontCenter
;
1285 device
->DevChannels
[5] = LFE
;
1288 case DevFmtX71
: device
->DevChannels
[0] = FrontLeft
;
1289 device
->DevChannels
[1] = FrontRight
;
1290 device
->DevChannels
[2] = BackLeft
;
1291 device
->DevChannels
[3] = BackRight
;
1292 device
->DevChannels
[4] = FrontCenter
;
1293 device
->DevChannels
[5] = LFE
;
1294 device
->DevChannels
[6] = SideLeft
;
1295 device
->DevChannels
[7] = SideRight
;
1298 /* Same as WFX order */
1306 SetDefaultWFXChannelOrder(device
);
1312 * Stores the latest ALC device error
1314 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1319 /* DebugBreak() will cause an exception if there is no debugger */
1320 if(IsDebuggerPresent())
1322 #elif defined(SIGTRAP)
1328 device
->LastError
= errorCode
;
1330 LastNullDeviceError
= errorCode
;
1334 /* UpdateDeviceParams
1336 * Updates device parameters according to the attribute list (caller is
1337 * responsible for holding the list lock).
1339 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1341 ALCcontext
*context
;
1342 enum DevFmtChannels oldChans
;
1343 enum DevFmtType oldType
;
1348 // Check for attributes
1349 if(device
->Type
== Loopback
)
1355 GotAll
= GotFreq
|GotChans
|GotType
1357 ALCuint freq
, numMono
, numStereo
, numSends
;
1358 enum DevFmtChannels schans
;
1359 enum DevFmtType stype
;
1360 ALCuint attrIdx
= 0;
1365 WARN("Missing attributes for loopback device\n");
1366 return ALC_INVALID_VALUE
;
1369 numMono
= device
->NumMonoSources
;
1370 numStereo
= device
->NumStereoSources
;
1371 numSends
= device
->NumAuxSends
;
1372 schans
= device
->FmtChans
;
1373 stype
= device
->FmtType
;
1374 freq
= device
->Frequency
;
1376 while(attrList
[attrIdx
])
1378 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1380 ALCint val
= attrList
[attrIdx
+ 1];
1381 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1382 return ALC_INVALID_VALUE
;
1387 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1389 ALCint val
= attrList
[attrIdx
+ 1];
1390 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1391 return ALC_INVALID_VALUE
;
1396 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1398 freq
= attrList
[attrIdx
+ 1];
1399 if(freq
< MIN_OUTPUT_RATE
)
1400 return ALC_INVALID_VALUE
;
1404 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1406 numStereo
= attrList
[attrIdx
+ 1];
1407 if(numStereo
> device
->MaxNoOfSources
)
1408 numStereo
= device
->MaxNoOfSources
;
1410 numMono
= device
->MaxNoOfSources
- numStereo
;
1413 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1414 numSends
= attrList
[attrIdx
+ 1];
1419 if(gotFmt
!= GotAll
)
1421 WARN("Missing format for loopback device\n");
1422 return ALC_INVALID_VALUE
;
1425 ConfigValueUInt(NULL
, "sends", &numSends
);
1426 numSends
= minu(MAX_SENDS
, numSends
);
1428 if((device
->Flags
&DEVICE_RUNNING
))
1429 ALCdevice_StopPlayback(device
);
1430 device
->Flags
&= ~DEVICE_RUNNING
;
1432 device
->Frequency
= freq
;
1433 device
->FmtChans
= schans
;
1434 device
->FmtType
= stype
;
1435 device
->NumMonoSources
= numMono
;
1436 device
->NumStereoSources
= numStereo
;
1437 device
->NumAuxSends
= numSends
;
1439 else if(attrList
&& attrList
[0])
1441 ALCuint freq
, numMono
, numStereo
, numSends
;
1442 ALCuint attrIdx
= 0;
1444 /* If a context is already running on the device, stop playback so the
1445 * device attributes can be updated. */
1446 if((device
->Flags
&DEVICE_RUNNING
))
1447 ALCdevice_StopPlayback(device
);
1448 device
->Flags
&= ~DEVICE_RUNNING
;
1450 freq
= device
->Frequency
;
1451 numMono
= device
->NumMonoSources
;
1452 numStereo
= device
->NumStereoSources
;
1453 numSends
= device
->NumAuxSends
;
1455 while(attrList
[attrIdx
])
1457 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1459 freq
= attrList
[attrIdx
+ 1];
1460 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1463 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1465 numStereo
= attrList
[attrIdx
+ 1];
1466 if(numStereo
> device
->MaxNoOfSources
)
1467 numStereo
= device
->MaxNoOfSources
;
1469 numMono
= device
->MaxNoOfSources
- numStereo
;
1472 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1473 numSends
= attrList
[attrIdx
+ 1];
1478 ConfigValueUInt(NULL
, "frequency", &freq
);
1479 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1481 ConfigValueUInt(NULL
, "sends", &numSends
);
1482 numSends
= minu(MAX_SENDS
, numSends
);
1484 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1487 device
->Frequency
= freq
;
1488 device
->NumMonoSources
= numMono
;
1489 device
->NumStereoSources
= numStereo
;
1490 device
->NumAuxSends
= numSends
;
1493 if((device
->Flags
&DEVICE_RUNNING
))
1494 return ALC_NO_ERROR
;
1496 oldFreq
= device
->Frequency
;
1497 oldChans
= device
->FmtChans
;
1498 oldType
= device
->FmtType
;
1500 TRACE("Format pre-setup: %s%s, %s%s, %uhz%s, %u update size x%d\n",
1501 DevFmtChannelsString(device
->FmtChans
),
1502 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?" (requested)":"",
1503 DevFmtTypeString(device
->FmtType
),
1504 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?" (requested)":"",
1506 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?" (requested)":"",
1507 device
->UpdateSize
, device
->NumUpdates
);
1509 if(ALCdevice_ResetPlayback(device
) == ALC_FALSE
)
1510 return ALC_INVALID_DEVICE
;
1512 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1514 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1515 DevFmtChannelsString(device
->FmtChans
));
1516 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1518 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1520 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1521 DevFmtTypeString(device
->FmtType
));
1522 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1524 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1526 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1527 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1530 TRACE("Format post-setup: %s, %s, %uhz, %u update size x%d\n",
1531 DevFmtChannelsString(device
->FmtChans
),
1532 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1533 device
->UpdateSize
, device
->NumUpdates
);
1535 aluInitPanning(device
);
1537 for(i
= 0;i
< MaxChannels
;i
++)
1539 device
->ClickRemoval
[i
] = 0.0f
;
1540 device
->PendingClicks
[i
] = 0.0f
;
1543 device
->Hrtf
= NULL
;
1544 if(device
->Type
!= Loopback
&& GetConfigValueBool(NULL
, "hrtf", AL_FALSE
))
1545 device
->Hrtf
= GetHrtf(device
);
1546 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1548 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6)
1552 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1553 bs2b_clear(device
->Bs2b
);
1555 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1556 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1557 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1562 device
->Bs2b
= NULL
;
1563 TRACE("BS2B disabled\n");
1566 device
->Flags
&= ~DEVICE_WIDE_STEREO
;
1567 if(device
->Type
!= Loopback
&& !device
->Hrtf
&& GetConfigValueBool(NULL
, "wide-stereo", AL_FALSE
))
1568 device
->Flags
|= DEVICE_WIDE_STEREO
;
1570 oldMode
= SetMixerFPUMode();
1572 context
= device
->ContextList
;
1577 context
->UpdateSources
= AL_FALSE
;
1578 LockUIntMapRead(&context
->EffectSlotMap
);
1579 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
1581 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
1583 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1585 UnlockUIntMapRead(&context
->EffectSlotMap
);
1586 UnlockDevice(device
);
1587 RestoreFPUMode(oldMode
);
1588 return ALC_INVALID_DEVICE
;
1590 slot
->NeedsUpdate
= AL_FALSE
;
1591 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1593 UnlockUIntMapRead(&context
->EffectSlotMap
);
1595 LockUIntMapRead(&context
->SourceMap
);
1596 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1598 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
1599 ALuint s
= device
->NumAuxSends
;
1600 while(s
< MAX_SENDS
)
1602 if(source
->Send
[s
].Slot
)
1603 DecrementRef(&source
->Send
[s
].Slot
->ref
);
1604 source
->Send
[s
].Slot
= NULL
;
1605 source
->Send
[s
].Gain
= 1.0f
;
1606 source
->Send
[s
].GainHF
= 1.0f
;
1609 source
->NeedsUpdate
= AL_FALSE
;
1610 ALsource_Update(source
, context
);
1612 UnlockUIntMapRead(&context
->SourceMap
);
1614 context
= context
->next
;
1616 if(device
->DefaultSlot
)
1618 ALeffectslot
*slot
= device
->DefaultSlot
;
1620 if(ALeffectState_DeviceUpdate(slot
->EffectState
, device
) == AL_FALSE
)
1622 UnlockDevice(device
);
1623 RestoreFPUMode(oldMode
);
1624 return ALC_INVALID_DEVICE
;
1626 slot
->NeedsUpdate
= AL_FALSE
;
1627 ALeffectState_Update(slot
->EffectState
, device
, slot
);
1629 UnlockDevice(device
);
1630 RestoreFPUMode(oldMode
);
1632 if(ALCdevice_StartPlayback(device
) == ALC_FALSE
)
1633 return ALC_INVALID_DEVICE
;
1634 device
->Flags
|= DEVICE_RUNNING
;
1636 return ALC_NO_ERROR
;
1641 * Frees the device structure, and destroys any objects the app failed to
1642 * delete. Called once there's no more references on the device.
1644 static ALCvoid
FreeDevice(ALCdevice
*device
)
1646 TRACE("%p\n", device
);
1648 if(device
->DefaultSlot
)
1650 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
1651 device
->DefaultSlot
->EffectState
= NULL
;
1654 if(device
->BufferMap
.size
> 0)
1656 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
1657 ReleaseALBuffers(device
);
1659 ResetUIntMap(&device
->BufferMap
);
1661 if(device
->EffectMap
.size
> 0)
1663 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
1664 ReleaseALEffects(device
);
1666 ResetUIntMap(&device
->EffectMap
);
1668 if(device
->FilterMap
.size
> 0)
1670 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
1671 ReleaseALFilters(device
);
1673 ResetUIntMap(&device
->FilterMap
);
1676 device
->Bs2b
= NULL
;
1678 free(device
->DeviceName
);
1679 device
->DeviceName
= NULL
;
1681 DeleteCriticalSection(&device
->Mutex
);
1687 void ALCdevice_IncRef(ALCdevice
*device
)
1690 ref
= IncrementRef(&device
->ref
);
1691 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
1694 void ALCdevice_DecRef(ALCdevice
*device
)
1697 ref
= DecrementRef(&device
->ref
);
1698 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
1699 if(ref
== 0) FreeDevice(device
);
1704 * Checks if the device handle is valid, and increments its ref count if so.
1706 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
1708 ALCdevice
*tmpDevice
;
1714 tmpDevice
= DeviceList
;
1715 while(tmpDevice
&& tmpDevice
!= device
)
1716 tmpDevice
= tmpDevice
->next
;
1719 ALCdevice_IncRef(tmpDevice
);
1727 * Initializes context fields
1729 static ALvoid
InitContext(ALCcontext
*Context
)
1733 //Initialise listener
1734 Context
->Listener
.Gain
= 1.0f
;
1735 Context
->Listener
.MetersPerUnit
= 1.0f
;
1736 Context
->Listener
.Position
[0] = 0.0f
;
1737 Context
->Listener
.Position
[1] = 0.0f
;
1738 Context
->Listener
.Position
[2] = 0.0f
;
1739 Context
->Listener
.Velocity
[0] = 0.0f
;
1740 Context
->Listener
.Velocity
[1] = 0.0f
;
1741 Context
->Listener
.Velocity
[2] = 0.0f
;
1742 Context
->Listener
.Forward
[0] = 0.0f
;
1743 Context
->Listener
.Forward
[1] = 0.0f
;
1744 Context
->Listener
.Forward
[2] = -1.0f
;
1745 Context
->Listener
.Up
[0] = 0.0f
;
1746 Context
->Listener
.Up
[1] = 1.0f
;
1747 Context
->Listener
.Up
[2] = 0.0f
;
1748 for(i
= 0;i
< 4;i
++)
1750 for(j
= 0;j
< 4;j
++)
1751 Context
->Listener
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
1755 Context
->LastError
= AL_NO_ERROR
;
1756 Context
->UpdateSources
= AL_FALSE
;
1757 Context
->ActiveSourceCount
= 0;
1758 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
1759 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
1762 Context
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1763 Context
->SourceDistanceModel
= AL_FALSE
;
1764 Context
->DopplerFactor
= 1.0f
;
1765 Context
->DopplerVelocity
= 1.0f
;
1766 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
1767 Context
->DeferUpdates
= AL_FALSE
;
1769 Context
->ExtensionList
= alExtList
;
1775 * Cleans up the context, and destroys any remaining objects the app failed to
1776 * delete. Called once there's no more references on the context.
1778 static ALCvoid
FreeContext(ALCcontext
*context
)
1780 TRACE("%p\n", context
);
1782 if(context
->SourceMap
.size
> 0)
1784 ERR("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
1785 ReleaseALSources(context
);
1787 ResetUIntMap(&context
->SourceMap
);
1789 if(context
->EffectSlotMap
.size
> 0)
1791 ERR("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
1792 ReleaseALAuxiliaryEffectSlots(context
);
1794 ResetUIntMap(&context
->EffectSlotMap
);
1796 context
->ActiveSourceCount
= 0;
1797 free(context
->ActiveSources
);
1798 context
->ActiveSources
= NULL
;
1799 context
->MaxActiveSources
= 0;
1801 context
->ActiveEffectSlotCount
= 0;
1802 free(context
->ActiveEffectSlots
);
1803 context
->ActiveEffectSlots
= NULL
;
1804 context
->MaxActiveEffectSlots
= 0;
1806 ALCdevice_DecRef(context
->Device
);
1807 context
->Device
= NULL
;
1809 //Invalidate context
1810 memset(context
, 0, sizeof(ALCcontext
));
1816 * Removes the context reference from the given device and removes it from
1817 * being current on the running thread or globally.
1819 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
1821 ALCcontext
*volatile*tmp_ctx
;
1823 if(pthread_getspecific(LocalContext
) == context
)
1825 WARN("%p released while current on thread\n", context
);
1826 pthread_setspecific(LocalContext
, NULL
);
1827 ALCcontext_DecRef(context
);
1830 if(CompExchangePtr((XchgPtr
*)&GlobalContext
, context
, NULL
))
1831 ALCcontext_DecRef(context
);
1834 tmp_ctx
= &device
->ContextList
;
1837 if(CompExchangePtr((XchgPtr
*)tmp_ctx
, context
, context
->next
))
1839 tmp_ctx
= &(*tmp_ctx
)->next
;
1841 UnlockDevice(device
);
1843 ALCcontext_DecRef(context
);
1846 void ALCcontext_IncRef(ALCcontext
*context
)
1849 ref
= IncrementRef(&context
->ref
);
1850 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
1853 void ALCcontext_DecRef(ALCcontext
*context
)
1856 ref
= DecrementRef(&context
->ref
);
1857 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
1858 if(ref
== 0) FreeContext(context
);
1861 static void ReleaseThreadCtx(void *ptr
)
1863 WARN("%p current for thread being destroyed\n", ptr
);
1864 ALCcontext_DecRef(ptr
);
1869 * Checks that the given context is valid, and increments its reference count.
1871 static ALCcontext
*VerifyContext(ALCcontext
*context
)
1879 ALCcontext
*tmp_ctx
= dev
->ContextList
;
1882 if(tmp_ctx
== context
)
1884 ALCcontext_IncRef(tmp_ctx
);
1888 tmp_ctx
= tmp_ctx
->next
;
1900 * Returns the currently active context for this thread, and adds a reference
1901 * without locking it.
1903 ALCcontext
*GetContextRef(void)
1905 ALCcontext
*context
;
1907 context
= pthread_getspecific(LocalContext
);
1909 ALCcontext_IncRef(context
);
1913 context
= GlobalContext
;
1915 ALCcontext_IncRef(context
);
1923 /************************************************
1924 * Standard ALC functions
1925 ************************************************/
1929 * Return last ALC generated error code for the given device
1931 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
1935 if(VerifyDevice(device
))
1937 errorCode
= ExchangeInt(&device
->LastError
, ALC_NO_ERROR
);
1938 ALCdevice_DecRef(device
);
1941 errorCode
= ExchangeInt(&LastNullDeviceError
, ALC_NO_ERROR
);
1947 /* alcSuspendContext
1951 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*Context
)
1956 /* alcProcessContext
1960 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*Context
)
1968 * Returns information about the device, and error strings
1970 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
1972 const ALCchar
*value
= NULL
;
1980 case ALC_INVALID_ENUM
:
1981 value
= alcErrInvalidEnum
;
1984 case ALC_INVALID_VALUE
:
1985 value
= alcErrInvalidValue
;
1988 case ALC_INVALID_DEVICE
:
1989 value
= alcErrInvalidDevice
;
1992 case ALC_INVALID_CONTEXT
:
1993 value
= alcErrInvalidContext
;
1996 case ALC_OUT_OF_MEMORY
:
1997 value
= alcErrOutOfMemory
;
2000 case ALC_DEVICE_SPECIFIER
:
2001 value
= alcDefaultName
;
2004 case ALC_ALL_DEVICES_SPECIFIER
:
2005 if(VerifyDevice(Device
))
2007 value
= Device
->DeviceName
;
2008 ALCdevice_DecRef(Device
);
2012 ProbeAllDevicesList();
2013 value
= alcAllDevicesList
;
2017 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2018 if(VerifyDevice(Device
))
2020 value
= Device
->DeviceName
;
2021 ALCdevice_DecRef(Device
);
2025 ProbeCaptureDeviceList();
2026 value
= alcCaptureDeviceList
;
2030 /* Default devices are always first in the list */
2031 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2032 value
= alcDefaultName
;
2035 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2036 if(!alcAllDevicesList
)
2037 ProbeAllDevicesList();
2039 Device
= VerifyDevice(Device
);
2041 free(alcDefaultAllDevicesSpecifier
);
2042 alcDefaultAllDevicesSpecifier
= strdup(alcAllDevicesList
?
2043 alcAllDevicesList
: "");
2044 if(!alcDefaultAllDevicesSpecifier
)
2045 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2047 value
= alcDefaultAllDevicesSpecifier
;
2048 if(Device
) ALCdevice_DecRef(Device
);
2051 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2052 if(!alcCaptureDeviceList
)
2053 ProbeCaptureDeviceList();
2055 Device
= VerifyDevice(Device
);
2057 free(alcCaptureDefaultDeviceSpecifier
);
2058 alcCaptureDefaultDeviceSpecifier
= strdup(alcCaptureDeviceList
?
2059 alcCaptureDeviceList
: "");
2060 if(!alcCaptureDefaultDeviceSpecifier
)
2061 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2063 value
= alcCaptureDefaultDeviceSpecifier
;
2064 if(Device
) ALCdevice_DecRef(Device
);
2067 case ALC_EXTENSIONS
:
2068 if(!VerifyDevice(Device
))
2069 value
= alcNoDeviceExtList
;
2072 value
= alcExtensionList
;
2073 ALCdevice_DecRef(Device
);
2078 Device
= VerifyDevice(Device
);
2079 alcSetError(Device
, ALC_INVALID_ENUM
);
2080 if(Device
) ALCdevice_DecRef(Device
);
2090 * Returns information about the device and the version of OpenAL
2092 ALC_API ALCvoid ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
,ALCenum param
,ALsizei size
,ALCint
*data
)
2094 device
= VerifyDevice(device
);
2096 if(size
== 0 || data
== NULL
)
2098 alcSetError(device
, ALC_INVALID_VALUE
);
2099 if(device
) ALCdevice_DecRef(device
);
2107 case ALC_MAJOR_VERSION
:
2108 *data
= alcMajorVersion
;
2110 case ALC_MINOR_VERSION
:
2111 *data
= alcMinorVersion
;
2114 case ALC_ATTRIBUTES_SIZE
:
2115 case ALC_ALL_ATTRIBUTES
:
2119 case ALC_MONO_SOURCES
:
2120 case ALC_STEREO_SOURCES
:
2121 case ALC_CAPTURE_SAMPLES
:
2122 case ALC_FORMAT_CHANNELS_SOFT
:
2123 case ALC_FORMAT_TYPE_SOFT
:
2124 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2128 alcSetError(NULL
, ALC_INVALID_ENUM
);
2132 else if(device
->Type
== Capture
)
2136 case ALC_CAPTURE_SAMPLES
:
2138 /* Re-validate the device since it may have been closed */
2139 ALCdevice_DecRef(device
);
2140 if((device
=VerifyDevice(device
)) != NULL
)
2141 *data
= ALCdevice_AvailableSamples(device
);
2143 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2148 *data
= device
->Connected
;
2152 alcSetError(device
, ALC_INVALID_ENUM
);
2156 else /* render device */
2160 case ALC_MAJOR_VERSION
:
2161 *data
= alcMajorVersion
;
2164 case ALC_MINOR_VERSION
:
2165 *data
= alcMinorVersion
;
2168 case ALC_EFX_MAJOR_VERSION
:
2169 *data
= alcEFXMajorVersion
;
2172 case ALC_EFX_MINOR_VERSION
:
2173 *data
= alcEFXMinorVersion
;
2176 case ALC_ATTRIBUTES_SIZE
:
2180 case ALC_ALL_ATTRIBUTES
:
2182 alcSetError(device
, ALC_INVALID_VALUE
);
2187 data
[i
++] = ALC_FREQUENCY
;
2188 data
[i
++] = device
->Frequency
;
2190 if(device
->Type
!= Loopback
)
2192 data
[i
++] = ALC_REFRESH
;
2193 data
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2195 data
[i
++] = ALC_SYNC
;
2196 data
[i
++] = ALC_FALSE
;
2200 data
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2201 data
[i
++] = device
->FmtChans
;
2203 data
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2204 data
[i
++] = device
->FmtType
;
2207 data
[i
++] = ALC_MONO_SOURCES
;
2208 data
[i
++] = device
->NumMonoSources
;
2210 data
[i
++] = ALC_STEREO_SOURCES
;
2211 data
[i
++] = device
->NumStereoSources
;
2213 data
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2214 data
[i
++] = device
->NumAuxSends
;
2221 *data
= device
->Frequency
;
2225 if(device
->Type
== Loopback
)
2226 alcSetError(device
, ALC_INVALID_DEVICE
);
2228 *data
= device
->Frequency
/ device
->UpdateSize
;
2232 if(device
->Type
== Loopback
)
2233 alcSetError(device
, ALC_INVALID_DEVICE
);
2238 case ALC_FORMAT_CHANNELS_SOFT
:
2239 if(device
->Type
!= Loopback
)
2240 alcSetError(device
, ALC_INVALID_DEVICE
);
2242 *data
= device
->FmtChans
;
2245 case ALC_FORMAT_TYPE_SOFT
:
2246 if(device
->Type
!= Loopback
)
2247 alcSetError(device
, ALC_INVALID_DEVICE
);
2249 *data
= device
->FmtType
;
2252 case ALC_MONO_SOURCES
:
2253 *data
= device
->NumMonoSources
;
2256 case ALC_STEREO_SOURCES
:
2257 *data
= device
->NumStereoSources
;
2260 case ALC_MAX_AUXILIARY_SENDS
:
2261 *data
= device
->NumAuxSends
;
2265 *data
= device
->Connected
;
2269 alcSetError(device
, ALC_INVALID_ENUM
);
2274 ALCdevice_DecRef(device
);
2278 /* alcIsExtensionPresent
2280 * Determines if there is support for a particular extension
2282 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2284 ALCboolean bResult
= ALC_FALSE
;
2286 device
= VerifyDevice(device
);
2289 alcSetError(device
, ALC_INVALID_VALUE
);
2292 size_t len
= strlen(extName
);
2293 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2296 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2297 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2302 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2306 } while(isspace(*ptr
));
2311 ALCdevice_DecRef(device
);
2316 /* alcGetProcAddress
2318 * Retrieves the function address for a particular extension function
2320 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2322 ALCvoid
*ptr
= NULL
;
2326 device
= VerifyDevice(device
);
2327 alcSetError(device
, ALC_INVALID_VALUE
);
2328 if(device
) ALCdevice_DecRef(device
);
2333 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2335 ptr
= alcFunctions
[i
].address
;
2344 * Get the value for a particular ALC enumeration name
2346 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2352 device
= VerifyDevice(device
);
2353 alcSetError(device
, ALC_INVALID_VALUE
);
2354 if(device
) ALCdevice_DecRef(device
);
2359 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2361 val
= enumeration
[i
].value
;
2370 * Create and attach a context to the given device.
2372 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2374 ALCcontext
*ALContext
;
2378 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2381 alcSetError(device
, ALC_INVALID_DEVICE
);
2382 if(device
) ALCdevice_DecRef(device
);
2386 device
->LastError
= ALC_NO_ERROR
;
2388 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
2391 alcSetError(device
, err
);
2392 if(err
== ALC_INVALID_DEVICE
)
2393 aluHandleDisconnect(device
);
2394 ALCdevice_DecRef(device
);
2398 ALContext
= calloc(1, sizeof(ALCcontext
));
2403 ALContext
->MaxActiveSources
= 256;
2404 ALContext
->ActiveSources
= malloc(sizeof(ALContext
->ActiveSources
[0]) *
2405 ALContext
->MaxActiveSources
);
2407 if(!ALContext
|| !ALContext
->ActiveSources
)
2409 if(!device
->ContextList
)
2411 ALCdevice_StopPlayback(device
);
2412 device
->Flags
&= ~DEVICE_RUNNING
;
2419 alcSetError(device
, ALC_OUT_OF_MEMORY
);
2420 ALCdevice_DecRef(device
);
2424 ALContext
->Device
= device
;
2425 ALCdevice_IncRef(device
);
2426 InitContext(ALContext
);
2429 ALContext
->next
= device
->ContextList
;
2430 } while(!CompExchangePtr((XchgPtr
*)&device
->ContextList
, ALContext
->next
, ALContext
));
2433 ALCdevice_DecRef(device
);
2435 TRACE("Created context %p\n", ALContext
);
2439 /* alcDestroyContext
2441 * Remove a context from its device
2443 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
2448 /* alcGetContextsDevice sets an error for invalid contexts */
2449 Device
= alcGetContextsDevice(context
);
2452 ReleaseContext(context
, Device
);
2453 if(!Device
->ContextList
)
2455 ALCdevice_StopPlayback(Device
);
2456 Device
->Flags
&= ~DEVICE_RUNNING
;
2463 /* alcGetCurrentContext
2465 * Returns the currently active context on the calling thread
2467 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
2469 ALCcontext
*Context
;
2471 Context
= pthread_getspecific(LocalContext
);
2472 if(!Context
) Context
= GlobalContext
;
2477 /* alcGetThreadContext
2479 * Returns the currently active thread-local context
2481 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
2483 ALCcontext
*Context
;
2484 Context
= pthread_getspecific(LocalContext
);
2489 /* alcMakeContextCurrent
2491 * Makes the given context the active process-wide context, and removes the
2492 * thread-local context for the calling thread.
2494 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
2496 /* context must be valid or NULL */
2497 if(context
&& !(context
=VerifyContext(context
)))
2499 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2502 /* context's reference count is already incremented */
2503 context
= ExchangePtr((XchgPtr
*)&GlobalContext
, context
);
2504 if(context
) ALCcontext_DecRef(context
);
2506 if((context
=pthread_getspecific(LocalContext
)) != NULL
)
2508 pthread_setspecific(LocalContext
, NULL
);
2509 ALCcontext_DecRef(context
);
2515 /* alcSetThreadContext
2517 * Makes the given context the active context for the current thread
2519 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
2523 /* context must be valid or NULL */
2524 if(context
&& !(context
=VerifyContext(context
)))
2526 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2529 /* context's reference count is already incremented */
2530 old
= pthread_getspecific(LocalContext
);
2531 pthread_setspecific(LocalContext
, context
);
2532 if(old
) ALCcontext_DecRef(old
);
2538 /* alcGetContextsDevice
2540 * Returns the device that a particular context is attached to
2542 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
2546 if(!(Context
=VerifyContext(Context
)))
2548 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2551 Device
= Context
->Device
;
2552 ALCcontext_DecRef(Context
);
2560 * Opens the named device.
2562 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
2570 if(!PlaybackBackend
.name
)
2572 alcSetError(NULL
, ALC_INVALID_VALUE
);
2576 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2579 device
= calloc(1, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
2582 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2587 device
->Funcs
= &PlaybackBackend
.Funcs
;
2589 device
->Connected
= ALC_TRUE
;
2590 device
->Type
= Playback
;
2591 InitializeCriticalSection(&device
->Mutex
);
2592 device
->LastError
= ALC_NO_ERROR
;
2595 device
->Bs2b
= NULL
;
2596 device
->Bs2bLevel
= 0;
2597 device
->DeviceName
= NULL
;
2599 device
->ContextList
= NULL
;
2601 device
->MaxNoOfSources
= 256;
2602 device
->AuxiliaryEffectSlotMax
= 4;
2603 device
->NumAuxSends
= MAX_SENDS
;
2605 InitUIntMap(&device
->BufferMap
, ~0);
2606 InitUIntMap(&device
->EffectMap
, ~0);
2607 InitUIntMap(&device
->FilterMap
, ~0);
2610 device
->FmtChans
= DevFmtChannelsDefault
;
2611 device
->FmtType
= DevFmtTypeDefault
;
2612 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
2613 device
->NumUpdates
= 4;
2614 device
->UpdateSize
= 1024;
2616 if(ConfigValueStr(NULL
, "channels", &fmt
))
2618 static const struct {
2619 const char name
[16];
2620 enum DevFmtChannels chans
;
2622 { "mono", DevFmtMono
},
2623 { "stereo", DevFmtStereo
},
2624 { "quad", DevFmtQuad
},
2625 { "surround51", DevFmtX51
},
2626 { "surround61", DevFmtX61
},
2627 { "surround71", DevFmtX71
},
2631 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
2633 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
2635 device
->FmtChans
= chanlist
[i
].chans
;
2636 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
2640 if(i
== COUNTOF(chanlist
))
2641 ERR("Unsupported channels: %s\n", fmt
);
2643 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
2645 static const struct {
2646 const char name
[16];
2647 enum DevFmtType type
;
2649 { "int8", DevFmtByte
},
2650 { "uint8", DevFmtUByte
},
2651 { "int16", DevFmtShort
},
2652 { "uint16", DevFmtUShort
},
2653 { "int32", DevFmtInt
},
2654 { "uint32", DevFmtUInt
},
2655 { "float32", DevFmtFloat
},
2659 for(i
= 0;i
< COUNTOF(typelist
);i
++)
2661 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
2663 device
->FmtType
= typelist
[i
].type
;
2664 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
2668 if(i
== COUNTOF(typelist
))
2669 ERR("Unsupported sample-type: %s\n", fmt
);
2671 #define DEVICE_FORMAT_REQUEST (DEVICE_CHANNELS_REQUEST|DEVICE_SAMPLE_TYPE_REQUEST)
2672 if((device
->Flags
&DEVICE_FORMAT_REQUEST
) != DEVICE_FORMAT_REQUEST
&&
2673 ConfigValueStr(NULL
, "format", &fmt
))
2675 static const struct {
2676 const char name
[32];
2677 enum DevFmtChannels channels
;
2678 enum DevFmtType type
;
2680 { "AL_FORMAT_MONO32", DevFmtMono
, DevFmtFloat
},
2681 { "AL_FORMAT_STEREO32", DevFmtStereo
, DevFmtFloat
},
2682 { "AL_FORMAT_QUAD32", DevFmtQuad
, DevFmtFloat
},
2683 { "AL_FORMAT_51CHN32", DevFmtX51
, DevFmtFloat
},
2684 { "AL_FORMAT_61CHN32", DevFmtX61
, DevFmtFloat
},
2685 { "AL_FORMAT_71CHN32", DevFmtX71
, DevFmtFloat
},
2687 { "AL_FORMAT_MONO16", DevFmtMono
, DevFmtShort
},
2688 { "AL_FORMAT_STEREO16", DevFmtStereo
, DevFmtShort
},
2689 { "AL_FORMAT_QUAD16", DevFmtQuad
, DevFmtShort
},
2690 { "AL_FORMAT_51CHN16", DevFmtX51
, DevFmtShort
},
2691 { "AL_FORMAT_61CHN16", DevFmtX61
, DevFmtShort
},
2692 { "AL_FORMAT_71CHN16", DevFmtX71
, DevFmtShort
},
2694 { "AL_FORMAT_MONO8", DevFmtMono
, DevFmtByte
},
2695 { "AL_FORMAT_STEREO8", DevFmtStereo
, DevFmtByte
},
2696 { "AL_FORMAT_QUAD8", DevFmtQuad
, DevFmtByte
},
2697 { "AL_FORMAT_51CHN8", DevFmtX51
, DevFmtByte
},
2698 { "AL_FORMAT_61CHN8", DevFmtX61
, DevFmtByte
},
2699 { "AL_FORMAT_71CHN8", DevFmtX71
, DevFmtByte
}
2703 ERR("Option 'format' is deprecated, please use 'channels' and 'sample-type'\n");
2704 for(i
= 0;i
< COUNTOF(formats
);i
++)
2706 if(strcasecmp(fmt
, formats
[i
].name
) == 0)
2708 if(!(device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2709 device
->FmtChans
= formats
[i
].channels
;
2710 if(!(device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2711 device
->FmtType
= formats
[i
].type
;
2712 device
->Flags
|= DEVICE_FORMAT_REQUEST
;
2716 if(i
== COUNTOF(formats
))
2717 ERR("Unsupported format: %s\n", fmt
);
2719 #undef DEVICE_FORMAT_REQUEST
2721 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
2723 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2724 if(device
->Frequency
< MIN_OUTPUT_RATE
)
2725 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
2726 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
2729 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
2730 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
2732 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
2733 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
2735 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
2736 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
2738 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
2739 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
2741 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
2742 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
2744 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
2746 device
->NumStereoSources
= 1;
2747 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
2749 // Find a playback device to open
2751 if((err
=ALCdevice_OpenPlayback(device
, deviceName
)) != ALC_NO_ERROR
)
2754 DeleteCriticalSection(&device
->Mutex
);
2756 alcSetError(NULL
, err
);
2761 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
2763 device
->DefaultSlot
= (ALeffectslot
*)(device
+1);
2764 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
2766 device
->DefaultSlot
= NULL
;
2767 ERR("Failed to initialize the default effect slot\n");
2769 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
2771 ALeffectState_Destroy(device
->DefaultSlot
->EffectState
);
2772 device
->DefaultSlot
= NULL
;
2773 ERR("Failed to initialize the default effect\n");
2778 device
->next
= DeviceList
;
2779 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2781 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
2787 * Closes the given device.
2789 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*Device
)
2791 ALCdevice
*volatile*list
;
2796 while(*list
&& *list
!= Device
)
2797 list
= &(*list
)->next
;
2799 if(!*list
|| (*list
)->Type
== Capture
)
2801 alcSetError(*list
, ALC_INVALID_DEVICE
);
2806 *list
= (*list
)->next
;
2809 while((ctx
=Device
->ContextList
) != NULL
)
2811 WARN("Releasing context %p\n", ctx
);
2812 ReleaseContext(ctx
, Device
);
2814 if((Device
->Flags
&DEVICE_RUNNING
))
2815 ALCdevice_StopPlayback(Device
);
2816 Device
->Flags
&= ~DEVICE_RUNNING
;
2818 ALCdevice_ClosePlayback(Device
);
2820 ALCdevice_DecRef(Device
);
2826 /************************************************
2827 * ALC capture functions
2828 ************************************************/
2829 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
2831 ALCdevice
*device
= NULL
;
2836 if(!CaptureBackend
.name
)
2838 alcSetError(NULL
, ALC_INVALID_VALUE
);
2844 alcSetError(NULL
, ALC_INVALID_VALUE
);
2848 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
2851 device
= calloc(1, sizeof(ALCdevice
));
2854 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
2859 device
->Funcs
= &CaptureBackend
.Funcs
;
2861 device
->Connected
= ALC_TRUE
;
2862 device
->Type
= Capture
;
2863 InitializeCriticalSection(&device
->Mutex
);
2865 InitUIntMap(&device
->BufferMap
, ~0);
2866 InitUIntMap(&device
->EffectMap
, ~0);
2867 InitUIntMap(&device
->FilterMap
, ~0);
2869 device
->DeviceName
= NULL
;
2871 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
2872 device
->Frequency
= frequency
;
2874 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
2875 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
2877 DeleteCriticalSection(&device
->Mutex
);
2879 alcSetError(NULL
, ALC_INVALID_ENUM
);
2883 device
->UpdateSize
= samples
;
2884 device
->NumUpdates
= 1;
2887 if((err
=ALCdevice_OpenCapture(device
, deviceName
)) != ALC_NO_ERROR
)
2890 DeleteCriticalSection(&device
->Mutex
);
2892 alcSetError(NULL
, err
);
2898 device
->next
= DeviceList
;
2899 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
2901 TRACE("Created device %p\n", device
);
2905 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*Device
)
2907 ALCdevice
*volatile*list
;
2911 while(*list
&& *list
!= Device
)
2912 list
= &(*list
)->next
;
2914 if(!*list
|| (*list
)->Type
!= Capture
)
2916 alcSetError(*list
, ALC_INVALID_DEVICE
);
2921 *list
= (*list
)->next
;
2924 ALCdevice_CloseCapture(Device
);
2926 ALCdevice_DecRef(Device
);
2931 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
2934 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2937 alcSetError(device
, ALC_INVALID_DEVICE
);
2938 if(device
) ALCdevice_DecRef(device
);
2941 if(device
->Connected
)
2943 if(!(device
->Flags
&DEVICE_RUNNING
))
2944 ALCdevice_StartCapture(device
);
2945 device
->Flags
|= DEVICE_RUNNING
;
2949 ALCdevice_DecRef(device
);
2952 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
2955 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
2958 alcSetError(device
, ALC_INVALID_DEVICE
);
2959 if(device
) ALCdevice_DecRef(device
);
2962 if((device
->Flags
&DEVICE_RUNNING
))
2963 ALCdevice_StopCapture(device
);
2964 device
->Flags
&= ~DEVICE_RUNNING
;
2967 ALCdevice_DecRef(device
);
2970 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
2972 ALCenum err
= ALC_INVALID_DEVICE
;
2974 if((device
=VerifyDevice(device
)) != NULL
&& device
->Type
== Capture
)
2976 err
= ALC_INVALID_VALUE
;
2977 if(samples
>= 0 && ALCdevice_AvailableSamples(device
) >= (ALCuint
)samples
)
2978 err
= ALCdevice_CaptureSamples(device
, buffer
, samples
);
2981 if(err
!= ALC_NO_ERROR
)
2982 alcSetError(device
, err
);
2983 if(device
) ALCdevice_DecRef(device
);
2987 /************************************************
2988 * ALC loopback functions
2989 ************************************************/
2991 /* alcLoopbackOpenDeviceSOFT
2993 * Open a loopback device, for manual rendering.
2995 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3001 /* Make sure the device name, if specified, is us. */
3002 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3004 alcSetError(NULL
, ALC_INVALID_VALUE
);
3008 device
= calloc(1, sizeof(ALCdevice
));
3011 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3016 device
->Funcs
= &BackendLoopback
.Funcs
;
3018 device
->Connected
= ALC_TRUE
;
3019 device
->Type
= Loopback
;
3020 InitializeCriticalSection(&device
->Mutex
);
3021 device
->LastError
= ALC_NO_ERROR
;
3024 device
->Bs2b
= NULL
;
3025 device
->Bs2bLevel
= 0;
3026 device
->DeviceName
= NULL
;
3028 device
->ContextList
= NULL
;
3030 device
->MaxNoOfSources
= 256;
3031 device
->AuxiliaryEffectSlotMax
= 4;
3032 device
->NumAuxSends
= MAX_SENDS
;
3034 InitUIntMap(&device
->BufferMap
, ~0);
3035 InitUIntMap(&device
->EffectMap
, ~0);
3036 InitUIntMap(&device
->FilterMap
, ~0);
3039 device
->NumUpdates
= 0;
3040 device
->UpdateSize
= 0;
3042 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3043 device
->FmtChans
= DevFmtChannelsDefault
;
3044 device
->FmtType
= DevFmtTypeDefault
;
3046 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3047 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3049 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3050 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3052 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3053 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3055 device
->NumStereoSources
= 1;
3056 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3058 // Open the "backend"
3059 ALCdevice_OpenPlayback(device
, "Loopback");
3061 device
->next
= DeviceList
;
3062 } while(!CompExchangePtr((XchgPtr
*)&DeviceList
, device
->next
, device
));
3064 TRACE("Created device %p\n", device
);
3068 /* alcIsRenderFormatSupportedSOFT
3070 * Determines if the loopback device supports the given format for rendering.
3072 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3074 ALCboolean ret
= ALC_FALSE
;
3076 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3077 alcSetError(device
, ALC_INVALID_DEVICE
);
3079 alcSetError(device
, ALC_INVALID_VALUE
);
3082 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3083 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3084 freq
>= MIN_OUTPUT_RATE
)
3087 if(device
) ALCdevice_DecRef(device
);
3092 /* alcRenderSamplesSOFT
3094 * Renders some samples into a buffer, using the format last set by the
3095 * attributes given to alcCreateContext.
3097 ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3099 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3100 alcSetError(device
, ALC_INVALID_DEVICE
);
3101 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3102 alcSetError(device
, ALC_INVALID_VALUE
);
3104 aluMixData(device
, buffer
, samples
);
3105 if(device
) ALCdevice_DecRef(device
);