Mercurial > audio-send
view Alc/ALc.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children | 96298d83959c |
line wrap: on
line source
1 /**2 * OpenAL cross platform audio library3 * Copyright (C) 1999-2007 by authors.4 * This library is free software; you can redistribute it and/or5 * modify it under the terms of the GNU Library General Public6 * License as published by the Free Software Foundation; either7 * version 2 of the License, or (at your option) any later version.8 *9 * This library is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * Library General Public License for more details.13 *14 * You should have received a copy of the GNU Library General Public15 * License along with this library; if not, write to the16 * 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.html19 */21 #include "config.h"23 #include <math.h>24 #include <stdlib.h>25 #include <stdio.h>26 #include <memory.h>27 #include <ctype.h>29 #include "alMain.h"30 #include "alSource.h"31 #include "AL/al.h"32 #include "AL/alc.h"33 #include "alThunk.h"34 #include "alSource.h"35 #include "alBuffer.h"36 #include "alAuxEffectSlot.h"37 #include "bs2b.h"38 #include "alu.h"40 // RLM: try to include the file here.44 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }45 static struct BackendInfo BackendList[] = {46 #ifdef HAVE_PULSEAUDIO47 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },48 #endif49 #ifdef HAVE_ALSA50 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },51 #endif52 #ifdef HAVE_COREAUDIO53 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },54 #endif55 #ifdef HAVE_OSS56 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },57 #endif58 #ifdef HAVE_SOLARIS59 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },60 #endif61 #ifdef HAVE_SNDIO62 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },63 #endif64 #ifdef HAVE_MMDEVAPI65 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },66 #endif67 #ifdef HAVE_DSOUND68 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },69 #endif70 #ifdef HAVE_WINMM71 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },72 #endif73 #ifdef HAVE_PORTAUDIO74 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },75 #endif76 #ifdef HAVE_OPENSL77 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },78 #endif80 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },81 #ifdef HAVE_WAVE82 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },83 #endif84 { "send", alc_send_init, alc_send_deinit, alc_send_probe, EmptyFuncs },85 // this entry is so that the list is terminated by a "null" object,86 // and helps things to tell when they've reached the end of the list.87 { NULL, NULL, NULL, NULL, EmptyFuncs }88 };89 static struct BackendInfo BackendLoopback = {90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs91 };92 #undef EmptyFuncs94 static struct BackendInfo PlaybackBackend;95 static struct BackendInfo CaptureBackend;97 ///////////////////////////////////////////////////////98 // STRING and EXTENSIONS100 typedef struct ALCfunction {101 const ALCchar *funcName;102 ALCvoid *address;103 } ALCfunction;105 typedef struct ALCenums {106 const ALCchar *enumName;107 ALCenum value;108 } ALCenums;111 static const ALCfunction alcFunctions[] = {112 { "alcCreateContext", (ALCvoid *) alcCreateContext },113 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },114 { "alcProcessContext", (ALCvoid *) alcProcessContext },115 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },116 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },117 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },118 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },119 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },120 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },121 { "alcGetError", (ALCvoid *) alcGetError },122 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },123 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },124 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },125 { "alcGetString", (ALCvoid *) alcGetString },126 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },127 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },128 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },129 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },130 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },131 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },133 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },134 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },136 { "alcLoopbackOpenDeviceSOFT", (ALCvoid *) alcLoopbackOpenDeviceSOFT},137 { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT},138 { "alcRenderSamplesSOFT", (ALCvoid *) alcRenderSamplesSOFT },140 { "alEnable", (ALCvoid *) alEnable },141 { "alDisable", (ALCvoid *) alDisable },142 { "alIsEnabled", (ALCvoid *) alIsEnabled },143 { "alGetString", (ALCvoid *) alGetString },144 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },145 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },146 { "alGetFloatv", (ALCvoid *) alGetFloatv },147 { "alGetDoublev", (ALCvoid *) alGetDoublev },148 { "alGetBoolean", (ALCvoid *) alGetBoolean },149 { "alGetInteger", (ALCvoid *) alGetInteger },150 { "alGetFloat", (ALCvoid *) alGetFloat },151 { "alGetDouble", (ALCvoid *) alGetDouble },152 { "alGetError", (ALCvoid *) alGetError },153 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },154 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },155 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },156 { "alListenerf", (ALCvoid *) alListenerf },157 { "alListener3f", (ALCvoid *) alListener3f },158 { "alListenerfv", (ALCvoid *) alListenerfv },159 { "alListeneri", (ALCvoid *) alListeneri },160 { "alListener3i", (ALCvoid *) alListener3i },161 { "alListeneriv", (ALCvoid *) alListeneriv },162 { "alGetListenerf", (ALCvoid *) alGetListenerf },163 { "alGetListener3f", (ALCvoid *) alGetListener3f },164 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },165 { "alGetListeneri", (ALCvoid *) alGetListeneri },166 { "alGetListener3i", (ALCvoid *) alGetListener3i },167 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },168 { "alGenSources", (ALCvoid *) alGenSources },169 { "alDeleteSources", (ALCvoid *) alDeleteSources },170 { "alIsSource", (ALCvoid *) alIsSource },171 { "alSourcef", (ALCvoid *) alSourcef },172 { "alSource3f", (ALCvoid *) alSource3f },173 { "alSourcefv", (ALCvoid *) alSourcefv },174 { "alSourcei", (ALCvoid *) alSourcei },175 { "alSource3i", (ALCvoid *) alSource3i },176 { "alSourceiv", (ALCvoid *) alSourceiv },177 { "alGetSourcef", (ALCvoid *) alGetSourcef },178 { "alGetSource3f", (ALCvoid *) alGetSource3f },179 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },180 { "alGetSourcei", (ALCvoid *) alGetSourcei },181 { "alGetSource3i", (ALCvoid *) alGetSource3i },182 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },183 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },184 { "alSourceStopv", (ALCvoid *) alSourceStopv },185 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },186 { "alSourcePausev", (ALCvoid *) alSourcePausev },187 { "alSourcePlay", (ALCvoid *) alSourcePlay },188 { "alSourceStop", (ALCvoid *) alSourceStop },189 { "alSourceRewind", (ALCvoid *) alSourceRewind },190 { "alSourcePause", (ALCvoid *) alSourcePause },191 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },192 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },193 { "alGenBuffers", (ALCvoid *) alGenBuffers },194 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },195 { "alIsBuffer", (ALCvoid *) alIsBuffer },196 { "alBufferData", (ALCvoid *) alBufferData },197 { "alBufferf", (ALCvoid *) alBufferf },198 { "alBuffer3f", (ALCvoid *) alBuffer3f },199 { "alBufferfv", (ALCvoid *) alBufferfv },200 { "alBufferi", (ALCvoid *) alBufferi },201 { "alBuffer3i", (ALCvoid *) alBuffer3i },202 { "alBufferiv", (ALCvoid *) alBufferiv },203 { "alGetBufferf", (ALCvoid *) alGetBufferf },204 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },205 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },206 { "alGetBufferi", (ALCvoid *) alGetBufferi },207 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },208 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },209 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },210 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },211 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },212 { "alDistanceModel", (ALCvoid *) alDistanceModel },214 { "alGenFilters", (ALCvoid *) alGenFilters },215 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },216 { "alIsFilter", (ALCvoid *) alIsFilter },217 { "alFilteri", (ALCvoid *) alFilteri },218 { "alFilteriv", (ALCvoid *) alFilteriv },219 { "alFilterf", (ALCvoid *) alFilterf },220 { "alFilterfv", (ALCvoid *) alFilterfv },221 { "alGetFilteri", (ALCvoid *) alGetFilteri },222 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },223 { "alGetFilterf", (ALCvoid *) alGetFilterf },224 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },225 { "alGenEffects", (ALCvoid *) alGenEffects },226 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },227 { "alIsEffect", (ALCvoid *) alIsEffect },228 { "alEffecti", (ALCvoid *) alEffecti },229 { "alEffectiv", (ALCvoid *) alEffectiv },230 { "alEffectf", (ALCvoid *) alEffectf },231 { "alEffectfv", (ALCvoid *) alEffectfv },232 { "alGetEffecti", (ALCvoid *) alGetEffecti },233 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },234 { "alGetEffectf", (ALCvoid *) alGetEffectf },235 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },236 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},237 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},238 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },239 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },240 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },241 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },242 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },243 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},244 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},245 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},246 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},248 { "alBufferSubDataSOFT", (ALCvoid *) alBufferSubDataSOFT },250 { "alBufferSamplesSOFT", (ALCvoid *) alBufferSamplesSOFT },251 { "alBufferSubSamplesSOFT", (ALCvoid *) alBufferSubSamplesSOFT },252 { "alGetBufferSamplesSOFT", (ALCvoid *) alGetBufferSamplesSOFT },253 { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT},255 { "alDeferUpdatesSOFT", (ALCvoid *) alDeferUpdatesSOFT },256 { "alProcessUpdatesSOFT", (ALCvoid *) alProcessUpdatesSOFT },258 { NULL, (ALCvoid *) NULL }259 };261 static const ALCenums enumeration[] = {262 // Types263 { "ALC_INVALID", ALC_INVALID },264 { "ALC_FALSE", ALC_FALSE },265 { "ALC_TRUE", ALC_TRUE },267 // ALC Properties268 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },269 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },270 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },271 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },272 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },273 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },274 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },275 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },276 { "ALC_EXTENSIONS", ALC_EXTENSIONS },277 { "ALC_FREQUENCY", ALC_FREQUENCY },278 { "ALC_REFRESH", ALC_REFRESH },279 { "ALC_SYNC", ALC_SYNC },280 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },281 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },282 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },283 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},284 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },285 { "ALC_CONNECTED", ALC_CONNECTED },287 // EFX Properties288 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },289 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },290 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },292 // Loopback device Properties293 { "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT },294 { "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT },296 // Buffer Channel Configurations297 { "ALC_MONO", ALC_MONO },298 { "ALC_STEREO", ALC_STEREO },299 { "ALC_QUAD", ALC_QUAD },300 { "ALC_5POINT1", ALC_5POINT1 },301 { "ALC_6POINT1", ALC_6POINT1 },302 { "ALC_7POINT1", ALC_7POINT1 },304 // Buffer Sample Types305 { "ALC_BYTE", ALC_BYTE },306 { "ALC_UNSIGNED_BYTE", ALC_UNSIGNED_BYTE },307 { "ALC_SHORT", ALC_SHORT },308 { "ALC_UNSIGNED_SHORT", ALC_UNSIGNED_SHORT },309 { "ALC_INT", ALC_INT },310 { "ALC_UNSIGNED_INT", ALC_UNSIGNED_INT },311 { "ALC_FLOAT", ALC_FLOAT },313 // ALC Error Message314 { "ALC_NO_ERROR", ALC_NO_ERROR },315 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },316 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },317 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },318 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },319 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },321 { NULL, (ALCenum)0 }322 };323 // Error strings324 static const ALCchar alcNoError[] = "No Error";325 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";326 static const ALCchar alcErrInvalidContext[] = "Invalid Context";327 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";328 static const ALCchar alcErrInvalidValue[] = "Invalid Value";329 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";331 /* Device lists. Sizes only include the first ending null character, not the332 * second */333 static ALCchar *alcDeviceList;334 static size_t alcDeviceListSize;335 static ALCchar *alcAllDeviceList;336 static size_t alcAllDeviceListSize;337 static ALCchar *alcCaptureDeviceList;338 static size_t alcCaptureDeviceListSize;339 /* Default is always the first in the list */340 static ALCchar *alcDefaultDeviceSpecifier;341 static ALCchar *alcDefaultAllDeviceSpecifier;342 static ALCchar *alcCaptureDefaultDeviceSpecifier;345 static const ALCchar alcNoDeviceExtList[] =346 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "347 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";348 static const ALCchar alcExtensionList[] =349 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "350 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "351 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";352 static const ALCint alcMajorVersion = 1;353 static const ALCint alcMinorVersion = 1;355 static const ALCint alcEFXMajorVersion = 1;356 static const ALCint alcEFXMinorVersion = 0;358 ///////////////////////////////////////////////////////361 ///////////////////////////////////////////////////////362 // Global Variables364 static CRITICAL_SECTION ListLock;366 /* Device List */367 static ALCdevice *g_pDeviceList = NULL;368 static ALCuint g_ulDeviceCount = 0;370 // Context List371 static ALCcontext *g_pContextList = NULL;372 static ALCuint g_ulContextCount = 0;374 // Thread-local current context375 static tls_type LocalContext;376 // Process-wide current context377 static ALCcontext *GlobalContext;379 // Context Error380 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;382 // Default context extensions383 static const ALchar alExtList[] =384 "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 "385 "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "386 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "387 "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data "388 "AL_SOFTX_deferred_updates AL_SOFT_loop_points "389 "AL_SOFTX_non_virtual_channels";391 // Mixing Priority Level392 ALint RTPrioLevel;394 // Output Log File395 FILE *LogFile;397 // Output Log Level398 #ifdef _DEBUG399 enum LogLevel LogLevel = LogWarning;400 #else401 enum LogLevel LogLevel = LogError;402 #endif404 // Cone scalar405 ALdouble ConeScale = 0.5;407 // Localized Z scalar for mono sources408 ALdouble ZScale = 1.0;410 /* One-time configuration init control */411 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;413 ///////////////////////////////////////////////////////416 ///////////////////////////////////////////////////////417 // ALC Related helper functions418 static void ReleaseALC(ALCboolean doclose);420 static void alc_initconfig(void);421 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)423 #if defined(_WIN32)424 static void alc_init(void);425 static void alc_deinit(void);426 static void alc_deinit_safe(void);428 #ifndef AL_LIBTYPE_STATIC429 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)430 {431 // Perform actions based on the reason for calling.432 switch(ul_reason_for_call)433 {434 case DLL_PROCESS_ATTACH:435 DisableThreadLibraryCalls(hModule);436 alc_init();437 break;439 case DLL_PROCESS_DETACH:440 if(!lpReserved)441 alc_deinit();442 else443 alc_deinit_safe();444 break;445 }446 return TRUE;447 }448 #elif defined(_MSC_VER)449 #pragma section(".CRT$XCU",read)450 static void alc_constructor(void);451 static void alc_destructor(void);452 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;454 static void alc_constructor(void)455 {456 atexit(alc_destructor);457 alc_init();458 }460 static void alc_destructor(void)461 {462 alc_deinit();463 }464 #elif defined(HAVE_GCC_DESTRUCTOR)465 static void alc_init(void) __attribute__((constructor));466 static void alc_deinit(void) __attribute__((destructor));467 #else468 #error "No static initialization available on this platform!"469 #endif470 #elif defined(HAVE_GCC_DESTRUCTOR)471 static void alc_init(void) __attribute__((constructor));472 static void alc_deinit(void) __attribute__((destructor));473 #else474 #error "No global initialization available on this platform!"475 #endif477 static void alc_init(void)478 {479 const char *str;481 LogFile = stderr;483 str = getenv("__ALSOFT_HALF_ANGLE_CONES");484 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))485 ConeScale = 1.0;487 str = getenv("__ALSOFT_REVERSE_Z");488 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))489 ZScale = -1.0;491 tls_create(&LocalContext);492 InitializeCriticalSection(&ListLock);493 ThunkInit();494 }496 static void alc_deinit_safe(void)497 {498 ReleaseALC(ALC_FALSE);500 FreeALConfig();502 ThunkExit();503 DeleteCriticalSection(&ListLock);504 tls_delete(LocalContext);506 if(LogFile != stderr)507 fclose(LogFile);508 LogFile = NULL;509 }511 static void alc_deinit(void)512 {513 int i;515 ReleaseALC(ALC_TRUE);517 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));518 memset(&CaptureBackend, 0, sizeof(CaptureBackend));520 for(i = 0;BackendList[i].Deinit;i++)521 BackendList[i].Deinit();522 BackendLoopback.Deinit();524 alc_deinit_safe();525 }527 static void alc_initconfig(void)528 {529 printf("OPENAL-AURELLEM: alc_init_config!!\n");530 const char *devs, *str;531 int i, n;533 str = getenv("ALSOFT_LOGLEVEL");534 if(str)535 {536 long lvl = strtol(str, NULL, 0);537 if(lvl >= NoLog && lvl <= LogTrace)538 LogLevel = lvl;539 }541 str = getenv("ALSOFT_LOGFILE");542 if(str && str[0])543 {544 FILE *logfile = fopen(str, "wat");545 if(logfile) LogFile = logfile;546 else ERR("Failed to open log file '%s'\n", str);547 }549 ReadALConfig();551 InitHrtf();553 #ifdef _WIN32554 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 1);555 #else556 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);557 #endif559 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);560 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)561 DefaultResampler = RESAMPLER_DEFAULT;563 ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) /564 20.0f);565 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);567 devs = GetConfigValue(NULL, "drivers", "");568 //printf("these are the devices: %s\n", devs);570 if(devs[0])571 {572 int n;573 size_t len;574 const char *next = devs;575 int endlist, delitem;577 i = 0;578 do {579 devs = next;580 //printf("AURELLEM: devs is %s\n",devs);581 next = strchr(devs, ',');583 delitem = (devs[0] == '-');584 if(devs[0] == '-') devs++;586 if(!devs[0] || devs[0] == ',')587 {588 endlist = 0;589 continue;590 }591 endlist = 1;593 len = (next ? ((size_t)(next-devs)) : strlen(devs));594 for(n = i;BackendList[n].Init;n++)595 {596 //printf("AURELLEM: device-name -- %s\n",BackendList[n].name);597 if(len == strlen(BackendList[n].name) &&598 strncmp(BackendList[n].name, devs, len) == 0)599 {600 if(delitem)601 {602 do {603 BackendList[n] = BackendList[n+1];604 ++n;605 }606 // this relies on the last entry being terminated by an607 // entry with all nulls.608 while(BackendList[n].Init);609 }610 else611 {612 struct BackendInfo Bkp = BackendList[n];613 while(n > i)614 {615 BackendList[n] = BackendList[n-1];616 --n;617 }618 BackendList[n] = Bkp;620 i++;621 }622 break;623 }624 }625 } while(next++);627 if(endlist)628 {629 BackendList[i].name = NULL;630 BackendList[i].Init = NULL;631 BackendList[i].Deinit = NULL;632 BackendList[i].Probe = NULL;633 }634 }636 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)637 {638 if(!BackendList[i].Init(&BackendList[i].Funcs))639 {640 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);641 continue;642 }644 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);645 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)646 {647 PlaybackBackend = BackendList[i];648 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);649 }650 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)651 {652 CaptureBackend = BackendList[i];653 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);654 }655 }656 BackendLoopback.Init(&BackendLoopback.Funcs);658 str = GetConfigValue(NULL, "excludefx", "");659 if(str[0])660 {661 size_t len;662 const char *next = str;664 do {665 str = next;666 next = strchr(str, ',');668 if(!str[0] || next == str)669 continue;671 len = (next ? ((size_t)(next-str)) : strlen(str));672 for(n = 0;EffectList[n].name;n++)673 {674 if(len == strlen(EffectList[n].name) &&675 strncmp(EffectList[n].name, str, len) == 0)676 DisabledEffects[EffectList[n].type] = AL_TRUE;677 }678 } while(next++);679 }680 }683 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)684 {685 free(*list);686 *list = NULL;687 *listsize = 0;689 DO_INITCONFIG();690 if(type == CAPTURE_DEVICE_PROBE)691 CaptureBackend.Probe(type);692 else693 PlaybackBackend.Probe(type);694 }696 static void ProbeDeviceList(void)697 { ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }698 static void ProbeAllDeviceList(void)699 { ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }700 static void ProbeCaptureDeviceList(void)701 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }704 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)705 {706 size_t len = strlen(name);707 void *temp;709 if(len == 0)710 return;712 temp = realloc(*List, (*ListSize) + len + 2);713 if(!temp)714 {715 ERR("Realloc failed to add %s!\n", name);716 return;717 }718 *List = temp;720 memcpy((*List)+(*ListSize), name, len+1);721 *ListSize += len+1;722 (*List)[*ListSize] = 0;723 }725 #define DECL_APPEND_LIST_FUNC(type) \726 void Append##type##List(const ALCchar *name) \727 { AppendList(name, &alc##type##List, &alc##type##ListSize); }729 DECL_APPEND_LIST_FUNC(Device)730 DECL_APPEND_LIST_FUNC(AllDevice)731 DECL_APPEND_LIST_FUNC(CaptureDevice)733 #undef DECL_APPEND_LIST_FUNC736 /* Sets the default channel order used by most non-WaveFormatEx-based APIs */737 void SetDefaultChannelOrder(ALCdevice *device)738 {739 switch(device->FmtChans)740 {741 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;742 device->DevChannels[1] = FRONT_RIGHT;743 device->DevChannels[2] = BACK_LEFT;744 device->DevChannels[3] = BACK_RIGHT;745 device->DevChannels[4] = FRONT_CENTER;746 device->DevChannels[5] = LFE;747 return;749 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;750 device->DevChannels[1] = FRONT_RIGHT;751 device->DevChannels[2] = BACK_LEFT;752 device->DevChannels[3] = BACK_RIGHT;753 device->DevChannels[4] = FRONT_CENTER;754 device->DevChannels[5] = LFE;755 device->DevChannels[6] = SIDE_LEFT;756 device->DevChannels[7] = SIDE_RIGHT;757 return;759 /* Same as WFX order */760 case DevFmtMono:761 case DevFmtStereo:762 case DevFmtQuad:763 case DevFmtX51Side:764 case DevFmtX61:765 break;766 }767 SetDefaultWFXChannelOrder(device);768 }769 /* Sets the default order used by WaveFormatEx */770 void SetDefaultWFXChannelOrder(ALCdevice *device)771 {772 switch(device->FmtChans)773 {774 case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;776 case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;777 device->DevChannels[1] = FRONT_RIGHT; break;779 case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;780 device->DevChannels[1] = FRONT_RIGHT;781 device->DevChannels[2] = BACK_LEFT;782 device->DevChannels[3] = BACK_RIGHT; break;784 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;785 device->DevChannels[1] = FRONT_RIGHT;786 device->DevChannels[2] = FRONT_CENTER;787 device->DevChannels[3] = LFE;788 device->DevChannels[4] = BACK_LEFT;789 device->DevChannels[5] = BACK_RIGHT; break;791 case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;792 device->DevChannels[1] = FRONT_RIGHT;793 device->DevChannels[2] = FRONT_CENTER;794 device->DevChannels[3] = LFE;795 device->DevChannels[4] = SIDE_LEFT;796 device->DevChannels[5] = SIDE_RIGHT; break;798 case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;799 device->DevChannels[1] = FRONT_RIGHT;800 device->DevChannels[2] = FRONT_CENTER;801 device->DevChannels[3] = LFE;802 device->DevChannels[4] = BACK_CENTER;803 device->DevChannels[5] = SIDE_LEFT;804 device->DevChannels[6] = SIDE_RIGHT; break;806 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;807 device->DevChannels[1] = FRONT_RIGHT;808 device->DevChannels[2] = FRONT_CENTER;809 device->DevChannels[3] = LFE;810 device->DevChannels[4] = BACK_LEFT;811 device->DevChannels[5] = BACK_RIGHT;812 device->DevChannels[6] = SIDE_LEFT;813 device->DevChannels[7] = SIDE_RIGHT; break;814 }815 }818 const ALCchar *DevFmtTypeString(enum DevFmtType type)819 {820 switch(type)821 {822 case DevFmtByte: return "Signed Byte";823 case DevFmtUByte: return "Unsigned Byte";824 case DevFmtShort: return "Signed Short";825 case DevFmtUShort: return "Unsigned Short";826 case DevFmtFloat: return "Float";827 }828 return "(unknown type)";829 }830 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)831 {832 switch(chans)833 {834 case DevFmtMono: return "Mono";835 case DevFmtStereo: return "Stereo";836 case DevFmtQuad: return "Quadraphonic";837 case DevFmtX51: return "5.1 Surround";838 case DevFmtX51Side: return "5.1 Side";839 case DevFmtX61: return "6.1 Surround";840 case DevFmtX71: return "7.1 Surround";841 }842 return "(unknown channels)";843 }845 ALuint BytesFromDevFmt(enum DevFmtType type)846 {847 switch(type)848 {849 case DevFmtByte: return sizeof(ALbyte);850 case DevFmtUByte: return sizeof(ALubyte);851 case DevFmtShort: return sizeof(ALshort);852 case DevFmtUShort: return sizeof(ALushort);853 case DevFmtFloat: return sizeof(ALfloat);854 }855 return 0;856 }857 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)858 {859 switch(chans)860 {861 case DevFmtMono: return 1;862 case DevFmtStereo: return 2;863 case DevFmtQuad: return 4;864 case DevFmtX51: return 6;865 case DevFmtX51Side: return 6;866 case DevFmtX61: return 7;867 case DevFmtX71: return 8;868 }869 return 0;870 }871 ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,872 enum DevFmtType *type)873 {874 switch(format)875 {876 case AL_FORMAT_MONO8:877 *chans = DevFmtMono;878 *type = DevFmtUByte;879 return AL_TRUE;880 case AL_FORMAT_MONO16:881 *chans = DevFmtMono;882 *type = DevFmtShort;883 return AL_TRUE;884 case AL_FORMAT_MONO_FLOAT32:885 *chans = DevFmtMono;886 *type = DevFmtFloat;887 return AL_TRUE;888 case AL_FORMAT_STEREO8:889 *chans = DevFmtStereo;890 *type = DevFmtUByte;891 return AL_TRUE;892 case AL_FORMAT_STEREO16:893 *chans = DevFmtStereo;894 *type = DevFmtShort;895 return AL_TRUE;896 case AL_FORMAT_STEREO_FLOAT32:897 *chans = DevFmtStereo;898 *type = DevFmtFloat;899 return AL_TRUE;900 case AL_FORMAT_QUAD8:901 *chans = DevFmtQuad;902 *type = DevFmtUByte;903 return AL_TRUE;904 case AL_FORMAT_QUAD16:905 *chans = DevFmtQuad;906 *type = DevFmtShort;907 return AL_TRUE;908 case AL_FORMAT_QUAD32:909 *chans = DevFmtQuad;910 *type = DevFmtFloat;911 return AL_TRUE;912 case AL_FORMAT_51CHN8:913 *chans = DevFmtX51;914 *type = DevFmtUByte;915 return AL_TRUE;916 case AL_FORMAT_51CHN16:917 *chans = DevFmtX51;918 *type = DevFmtShort;919 return AL_TRUE;920 case AL_FORMAT_51CHN32:921 *chans = DevFmtX51;922 *type = DevFmtFloat;923 return AL_TRUE;924 case AL_FORMAT_61CHN8:925 *chans = DevFmtX61;926 *type = DevFmtUByte;927 return AL_TRUE;928 case AL_FORMAT_61CHN16:929 *chans = DevFmtX61;930 *type = DevFmtShort;931 return AL_TRUE;932 case AL_FORMAT_61CHN32:933 *chans = DevFmtX61;934 *type = DevFmtFloat;935 return AL_TRUE;936 case AL_FORMAT_71CHN8:937 *chans = DevFmtX71;938 *type = DevFmtUByte;939 return AL_TRUE;940 case AL_FORMAT_71CHN16:941 *chans = DevFmtX71;942 *type = DevFmtShort;943 return AL_TRUE;944 case AL_FORMAT_71CHN32:945 *chans = DevFmtX71;946 *type = DevFmtFloat;947 return AL_TRUE;948 }949 return AL_FALSE;950 }952 static ALCboolean IsValidALCType(ALCenum type)953 {954 switch(type)955 {956 case ALC_BYTE:957 case ALC_UNSIGNED_BYTE:958 case ALC_SHORT:959 case ALC_UNSIGNED_SHORT:960 case ALC_INT:961 case ALC_UNSIGNED_INT:962 case ALC_FLOAT:963 return ALC_TRUE;964 }965 return ALC_FALSE;966 }968 static ALCboolean IsValidALCChannels(ALCenum channels)969 {970 switch(channels)971 {972 case ALC_MONO:973 case ALC_STEREO:974 case ALC_QUAD:975 case ALC_5POINT1:976 case ALC_6POINT1:977 case ALC_7POINT1:978 return ALC_TRUE;979 }980 return ALC_FALSE;981 }984 static void LockLists(void)985 {986 EnterCriticalSection(&ListLock);987 }989 static void UnlockLists(void)990 {991 LeaveCriticalSection(&ListLock);992 }994 /*995 IsDevice997 Check pDevice is a valid Device pointer998 */999 static ALCboolean IsDevice(ALCdevice *pDevice)1000 {1001 ALCdevice *pTempDevice;1003 pTempDevice = g_pDeviceList;1004 while(pTempDevice && pTempDevice != pDevice)1005 pTempDevice = pTempDevice->next;1007 return (pTempDevice ? ALC_TRUE : ALC_FALSE);1008 }1010 /*1011 IsContext1013 Check pContext is a valid Context pointer1014 */1015 static ALCboolean IsContext(ALCcontext *pContext)1016 {1017 ALCcontext *pTempContext;1019 pTempContext = g_pContextList;1020 while (pTempContext && pTempContext != pContext)1021 pTempContext = pTempContext->next;1023 return (pTempContext ? ALC_TRUE : ALC_FALSE);1024 }1027 /*1028 alcSetError1030 Store latest ALC Error1031 */1032 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)1033 {1034 LockLists();1035 if(IsDevice(device))1036 device->LastError = errorCode;1037 else1038 g_eLastNullDeviceError = errorCode;1039 UnlockLists();1040 }1043 /* UpdateDeviceParams:1044 *1045 * Updates device parameters according to the attribute list.1046 */1047 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)1048 {1049 ALuint i;1051 // Check for attributes1052 if(attrList && attrList[0])1053 {1054 ALCuint freq, numMono, numStereo, numSends;1055 enum DevFmtChannels schans;1056 enum DevFmtType stype;1057 ALuint attrIdx;1059 // If a context is already running on the device, stop playback so the1060 // device attributes can be updated1061 if((device->Flags&DEVICE_RUNNING))1062 ALCdevice_StopPlayback(device);1063 device->Flags &= ~DEVICE_RUNNING;1065 freq = device->Frequency;1066 schans = device->FmtChans;1067 stype = device->FmtType;1068 numMono = device->NumMonoSources;1069 numStereo = device->NumStereoSources;1070 numSends = device->NumAuxSends;1072 freq = GetConfigValueInt(NULL, "frequency", freq);1073 if(freq < 8000) freq = 8000;1075 attrIdx = 0;1076 while(attrList[attrIdx])1077 {1078 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT &&1079 device->IsLoopbackDevice)1080 {1081 ALCint val = attrList[attrIdx + 1];1082 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))1083 {1084 alcSetError(device, ALC_INVALID_VALUE);1085 return ALC_FALSE;1086 }1087 schans = val;1088 }1090 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT &&1091 device->IsLoopbackDevice)1092 {1093 ALCint val = attrList[attrIdx + 1];1094 if(!IsValidALCType(val) || !BytesFromDevFmt(val))1095 {1096 alcSetError(device, ALC_INVALID_VALUE);1097 return ALC_FALSE;1098 }1099 stype = val;1100 }1102 if(attrList[attrIdx] == ALC_FREQUENCY)1103 {1104 if(device->IsLoopbackDevice)1105 {1106 freq = attrList[attrIdx + 1];1107 if(freq < 8000)1108 {1109 alcSetError(device, ALC_INVALID_VALUE);1110 return ALC_FALSE;1111 }1112 }1113 else if(!ConfigValueExists(NULL, "frequency"))1114 {1115 freq = attrList[attrIdx + 1];1116 if(freq < 8000) freq = 8000;1117 device->Flags |= DEVICE_FREQUENCY_REQUEST;1118 }1119 }1121 if(attrList[attrIdx] == ALC_STEREO_SOURCES)1122 {1123 numStereo = attrList[attrIdx + 1];1124 if(numStereo > device->MaxNoOfSources)1125 numStereo = device->MaxNoOfSources;1127 numMono = device->MaxNoOfSources - numStereo;1128 }1130 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&1131 !ConfigValueExists(NULL, "sends"))1132 {1133 numSends = attrList[attrIdx + 1];1134 if(numSends > MAX_SENDS)1135 numSends = MAX_SENDS;1136 }1138 attrIdx += 2;1139 }1141 device->UpdateSize = (ALuint64)device->UpdateSize * freq /1142 device->Frequency;1144 device->Frequency = freq;1145 device->FmtChans = schans;1146 device->FmtType = stype;1147 device->NumMonoSources = numMono;1148 device->NumStereoSources = numStereo;1149 device->NumAuxSends = numSends;1150 }1152 if((device->Flags&DEVICE_RUNNING))1153 return ALC_TRUE;1155 LockDevice(device);1156 TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1157 DevFmtChannelsString(device->FmtChans),1158 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1159 DevFmtTypeString(device->FmtType), device->Frequency,1160 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1161 device->UpdateSize, device->NumUpdates);1162 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)1163 {1164 UnlockDevice(device);1165 return ALC_FALSE;1166 }1167 device->Flags |= DEVICE_RUNNING;1168 TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1169 DevFmtChannelsString(device->FmtChans),1170 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1171 DevFmtTypeString(device->FmtType), device->Frequency,1172 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1173 device->UpdateSize, device->NumUpdates);1175 aluInitPanning(device);1177 for(i = 0;i < MAXCHANNELS;i++)1178 {1179 device->ClickRemoval[i] = 0.0f;1180 device->PendingClicks[i] = 0.0f;1181 }1183 if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE))1184 device->Flags |= DEVICE_USE_HRTF;1185 if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device))1186 device->Flags &= ~DEVICE_USE_HRTF;1187 TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled");1189 if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)1190 {1191 if(!device->Bs2b)1192 {1193 device->Bs2b = calloc(1, sizeof(*device->Bs2b));1194 bs2b_clear(device->Bs2b);1195 }1196 bs2b_set_srate(device->Bs2b, device->Frequency);1197 bs2b_set_level(device->Bs2b, device->Bs2bLevel);1198 TRACE("BS2B level %d\n", device->Bs2bLevel);1199 }1200 else1201 {1202 free(device->Bs2b);1203 device->Bs2b = NULL;1204 TRACE("BS2B disabled\n");1205 }1207 device->Flags &= ~DEVICE_DUPLICATE_STEREO;1208 switch(device->FmtChans)1209 {1210 case DevFmtMono:1211 case DevFmtStereo:1212 break;1213 case DevFmtQuad:1214 case DevFmtX51:1215 case DevFmtX51Side:1216 case DevFmtX61:1217 case DevFmtX71:1218 if(GetConfigValueBool(NULL, "stereodup", AL_TRUE))1219 device->Flags |= DEVICE_DUPLICATE_STEREO;1220 break;1221 }1222 TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");1224 for(i = 0;i < device->NumContexts;i++)1225 {1226 ALCcontext *context = device->Contexts[i];1227 ALsizei pos;1229 context->UpdateSources = AL_FALSE;1230 for(pos = 0;pos < context->EffectSlotMap.size;pos++)1231 {1232 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;1234 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)1235 {1236 UnlockDevice(device);1237 ALCdevice_StopPlayback(device);1238 device->Flags &= ~DEVICE_RUNNING;1239 return ALC_FALSE;1240 }1241 slot->NeedsUpdate = AL_FALSE;1242 ALEffect_Update(slot->EffectState, context, slot);1243 }1245 for(pos = 0;pos < context->SourceMap.size;pos++)1246 {1247 ALsource *source = context->SourceMap.array[pos].value;1248 ALuint s = device->NumAuxSends;1249 while(s < MAX_SENDS)1250 {1251 if(source->Send[s].Slot)1252 source->Send[s].Slot->refcount--;1253 source->Send[s].Slot = NULL;1254 source->Send[s].WetFilter.type = 0;1255 source->Send[s].WetFilter.filter = 0;1256 s++;1257 }1258 source->NeedsUpdate = AL_FALSE;1259 ALsource_Update(source, context);1260 }1261 }1262 UnlockDevice(device);1264 return ALC_TRUE;1265 }1268 ALCvoid LockDevice(ALCdevice *device)1269 {1270 EnterCriticalSection(&device->Mutex);1271 }1273 ALCvoid UnlockDevice(ALCdevice *device)1274 {1275 LeaveCriticalSection(&device->Mutex);1276 }1278 /*1279 LockContext1281 Thread-safe entry1282 */1283 ALCvoid LockContext(ALCcontext *context)1284 {1285 EnterCriticalSection(&context->Device->Mutex);1286 }1289 /*1290 UnlockContext1292 Thread-safe exit1293 */1294 ALCvoid UnlockContext(ALCcontext *context)1295 {1296 LeaveCriticalSection(&context->Device->Mutex);1297 }1300 /*1301 GetLockedContext1303 Returns the currently active Context, in a locked state1304 */1305 ALCcontext *GetLockedContext(void)1306 {1307 ALCcontext *pContext = NULL;1309 LockLists();1311 pContext = tls_get(LocalContext);1312 if(pContext && !IsContext(pContext))1313 {1314 tls_set(LocalContext, NULL);1315 pContext = NULL;1316 }1317 if(!pContext)1318 pContext = GlobalContext;1319 if(pContext)1320 LockContext(pContext);1322 UnlockLists();1324 return pContext;1325 }1328 /*1329 InitContext1331 Initialize Context variables1332 */1333 static ALvoid InitContext(ALCcontext *pContext)1334 {1335 //Initialise listener1336 pContext->Listener.Gain = 1.0f;1337 pContext->Listener.MetersPerUnit = 1.0f;1338 pContext->Listener.Position[0] = 0.0f;1339 pContext->Listener.Position[1] = 0.0f;1340 pContext->Listener.Position[2] = 0.0f;1341 pContext->Listener.Velocity[0] = 0.0f;1342 pContext->Listener.Velocity[1] = 0.0f;1343 pContext->Listener.Velocity[2] = 0.0f;1344 pContext->Listener.Forward[0] = 0.0f;1345 pContext->Listener.Forward[1] = 0.0f;1346 pContext->Listener.Forward[2] = -1.0f;1347 pContext->Listener.Up[0] = 0.0f;1348 pContext->Listener.Up[1] = 1.0f;1349 pContext->Listener.Up[2] = 0.0f;1351 //Validate pContext1352 pContext->LastError = AL_NO_ERROR;1353 pContext->UpdateSources = AL_FALSE;1354 pContext->ActiveSourceCount = 0;1355 InitUIntMap(&pContext->SourceMap);1356 InitUIntMap(&pContext->EffectSlotMap);1358 //Set globals1359 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;1360 pContext->SourceDistanceModel = AL_FALSE;1361 pContext->DopplerFactor = 1.0f;1362 pContext->DopplerVelocity = 1.0f;1363 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;1364 pContext->DeferUpdates = AL_FALSE;1366 pContext->ExtensionList = alExtList;1367 }1370 /*1371 FreeContext1373 Clean up Context, destroy any remaining Sources1374 */1375 static ALCvoid FreeContext(ALCcontext *context)1376 {1377 //Invalidate context1378 memset(context, 0, sizeof(ALCcontext));1379 free(context);1380 }1382 ///////////////////////////////////////////////////////1385 ///////////////////////////////////////////////////////1386 // ALC Functions calls1389 // This should probably move to another c file but for now ...1390 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)1391 {1392 ALCdevice *device = NULL;1394 DO_INITCONFIG();1396 if(!CaptureBackend.name)1397 {1398 alcSetError(NULL, ALC_INVALID_VALUE);1399 return NULL;1400 }1402 if(SampleSize <= 0)1403 {1404 alcSetError(NULL, ALC_INVALID_VALUE);1405 return NULL;1406 }1408 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))1409 deviceName = NULL;1411 device = calloc(1, sizeof(ALCdevice));1412 if(!device)1413 {1414 alcSetError(NULL, ALC_OUT_OF_MEMORY);1415 return NULL;1416 }1418 //Validate device1419 device->Funcs = &CaptureBackend.Funcs;1420 device->Connected = ALC_TRUE;1421 device->IsCaptureDevice = AL_TRUE;1422 device->IsLoopbackDevice = AL_FALSE;1423 InitializeCriticalSection(&device->Mutex);1425 device->szDeviceName = NULL;1427 device->Flags |= DEVICE_FREQUENCY_REQUEST;1428 device->Frequency = frequency;1430 device->Flags |= DEVICE_CHANNELS_REQUEST;1431 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)1432 {1433 free(device);1434 alcSetError(NULL, ALC_INVALID_ENUM);1435 return NULL;1436 }1438 device->UpdateSize = SampleSize;1439 device->NumUpdates = 1;1441 LockLists();1442 if(ALCdevice_OpenCapture(device, deviceName))1443 {1444 device->next = g_pDeviceList;1445 g_pDeviceList = device;1446 g_ulDeviceCount++;1447 }1448 else1449 {1450 DeleteCriticalSection(&device->Mutex);1451 free(device);1452 device = NULL;1453 alcSetError(NULL, ALC_INVALID_VALUE);1454 }1455 UnlockLists();1457 return device;1458 }1460 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)1461 {1462 ALCdevice **list;1464 LockLists();1465 list = &g_pDeviceList;1466 while(*list && *list != pDevice)1467 list = &(*list)->next;1469 if(!*list || !(*list)->IsCaptureDevice)1470 {1471 alcSetError(*list, ALC_INVALID_DEVICE);1472 UnlockLists();1473 return ALC_FALSE;1474 }1476 *list = (*list)->next;1477 g_ulDeviceCount--;1479 UnlockLists();1481 LockDevice(pDevice);1482 ALCdevice_CloseCapture(pDevice);1483 UnlockDevice(pDevice);1485 free(pDevice->szDeviceName);1486 pDevice->szDeviceName = NULL;1488 DeleteCriticalSection(&pDevice->Mutex);1490 free(pDevice);1492 return ALC_TRUE;1493 }1495 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)1496 {1497 LockLists();1498 if(!IsDevice(device) || !device->IsCaptureDevice)1499 {1500 alcSetError(device, ALC_INVALID_DEVICE);1501 UnlockLists();1502 return;1503 }1504 LockDevice(device);1505 UnlockLists();1506 if(device->Connected)1507 ALCdevice_StartCapture(device);1508 UnlockDevice(device);1509 }1511 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)1512 {1513 LockLists();1514 if(!IsDevice(device) || !device->IsCaptureDevice)1515 {1516 alcSetError(device, ALC_INVALID_DEVICE);1517 UnlockLists();1518 return;1519 }1520 LockDevice(device);1521 UnlockLists();1522 if(device->Connected)1523 ALCdevice_StopCapture(device);1524 UnlockDevice(device);1525 }1527 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)1528 {1529 LockLists();1530 if(!IsDevice(device) || !device->IsCaptureDevice)1531 {1532 alcSetError(device, ALC_INVALID_DEVICE);1533 UnlockLists();1534 return;1535 }1536 LockDevice(device);1537 UnlockLists();1538 if(device->Connected)1539 ALCdevice_CaptureSamples(device, buffer, samples);1540 UnlockDevice(device);1541 }1543 /*1544 alcGetError1546 Return last ALC generated error code1547 */1548 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)1549 {1550 ALCenum errorCode;1552 LockLists();1553 if(IsDevice(device))1554 {1555 errorCode = device->LastError;1556 device->LastError = ALC_NO_ERROR;1557 }1558 else1559 {1560 errorCode = g_eLastNullDeviceError;1561 g_eLastNullDeviceError = ALC_NO_ERROR;1562 }1563 UnlockLists();1564 return errorCode;1565 }1568 /*1569 alcSuspendContext1571 Not functional1572 */1573 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)1574 {1575 (void)Context;1576 }1579 /*1580 alcProcessContext1582 Not functional1583 */1584 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)1585 {1586 (void)Context;1587 }1590 /*1591 alcGetString1593 Returns information about the Device, and error strings1594 */1595 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)1596 {1597 const ALCchar *value = NULL;1599 switch(param)1600 {1601 case ALC_NO_ERROR:1602 value = alcNoError;1603 break;1605 case ALC_INVALID_ENUM:1606 value = alcErrInvalidEnum;1607 break;1609 case ALC_INVALID_VALUE:1610 value = alcErrInvalidValue;1611 break;1613 case ALC_INVALID_DEVICE:1614 value = alcErrInvalidDevice;1615 break;1617 case ALC_INVALID_CONTEXT:1618 value = alcErrInvalidContext;1619 break;1621 case ALC_OUT_OF_MEMORY:1622 value = alcErrOutOfMemory;1623 break;1625 case ALC_DEVICE_SPECIFIER:1626 LockLists();1627 if(IsDevice(pDevice))1628 value = pDevice->szDeviceName;1629 else1630 {1631 ProbeDeviceList();1632 value = alcDeviceList;1633 }1634 UnlockLists();1635 break;1637 case ALC_ALL_DEVICES_SPECIFIER:1638 ProbeAllDeviceList();1639 value = alcAllDeviceList;1640 break;1642 case ALC_CAPTURE_DEVICE_SPECIFIER:1643 LockLists();1644 if(IsDevice(pDevice))1645 value = pDevice->szDeviceName;1646 else1647 {1648 ProbeCaptureDeviceList();1649 value = alcCaptureDeviceList;1650 }1651 UnlockLists();1652 break;1654 /* Default devices are always first in the list */1655 case ALC_DEFAULT_DEVICE_SPECIFIER:1656 if(!alcDeviceList)1657 ProbeDeviceList();1659 free(alcDefaultDeviceSpecifier);1660 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");1661 if(!alcDefaultDeviceSpecifier)1662 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1663 value = alcDefaultDeviceSpecifier;1664 break;1666 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:1667 if(!alcAllDeviceList)1668 ProbeAllDeviceList();1670 free(alcDefaultAllDeviceSpecifier);1671 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?1672 alcAllDeviceList : "");1673 if(!alcDefaultAllDeviceSpecifier)1674 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1675 value = alcDefaultAllDeviceSpecifier;1676 break;1678 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:1679 if(!alcCaptureDeviceList)1680 ProbeCaptureDeviceList();1682 free(alcCaptureDefaultDeviceSpecifier);1683 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?1684 alcCaptureDeviceList : "");1685 if(!alcCaptureDefaultDeviceSpecifier)1686 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1687 value = alcCaptureDefaultDeviceSpecifier;1688 break;1690 case ALC_EXTENSIONS:1691 LockLists();1692 if(IsDevice(pDevice))1693 value = alcExtensionList;1694 else1695 value = alcNoDeviceExtList;1696 UnlockLists();1697 break;1699 default:1700 alcSetError(pDevice, ALC_INVALID_ENUM);1701 break;1702 }1704 return value;1705 }1708 /*1709 alcGetIntegerv1711 Returns information about the Device and the version of Open AL1712 */1713 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)1714 {1715 if(size == 0 || data == NULL)1716 {1717 alcSetError(device, ALC_INVALID_VALUE);1718 return;1719 }1721 LockLists();1722 if(!IsDevice(device))1723 {1724 switch(param)1725 {1726 case ALC_MAJOR_VERSION:1727 *data = alcMajorVersion;1728 break;1729 case ALC_MINOR_VERSION:1730 *data = alcMinorVersion;1731 break;1733 case ALC_ATTRIBUTES_SIZE:1734 case ALC_ALL_ATTRIBUTES:1735 case ALC_FREQUENCY:1736 case ALC_REFRESH:1737 case ALC_SYNC:1738 case ALC_MONO_SOURCES:1739 case ALC_STEREO_SOURCES:1740 case ALC_CAPTURE_SAMPLES:1741 case ALC_FORMAT_CHANNELS_SOFT:1742 case ALC_FORMAT_TYPE_SOFT:1743 alcSetError(NULL, ALC_INVALID_DEVICE);1744 break;1746 default:1747 alcSetError(NULL, ALC_INVALID_ENUM);1748 break;1749 }1750 }1751 else if(device->IsCaptureDevice)1752 {1753 switch(param)1754 {1755 case ALC_CAPTURE_SAMPLES:1756 LockDevice(device);1757 *data = ALCdevice_AvailableSamples(device);1758 UnlockDevice(device);1759 break;1761 case ALC_CONNECTED:1762 *data = device->Connected;1763 break;1765 default:1766 alcSetError(device, ALC_INVALID_ENUM);1767 break;1768 }1769 }1770 else /* render device */1771 {1772 switch(param)1773 {1774 case ALC_MAJOR_VERSION:1775 *data = alcMajorVersion;1776 break;1778 case ALC_MINOR_VERSION:1779 *data = alcMinorVersion;1780 break;1782 case ALC_EFX_MAJOR_VERSION:1783 *data = alcEFXMajorVersion;1784 break;1786 case ALC_EFX_MINOR_VERSION:1787 *data = alcEFXMinorVersion;1788 break;1790 case ALC_ATTRIBUTES_SIZE:1791 *data = 13;1792 break;1794 case ALC_ALL_ATTRIBUTES:1795 if(size < 13)1796 alcSetError(device, ALC_INVALID_VALUE);1797 else1798 {1799 int i = 0;1801 data[i++] = ALC_FREQUENCY;1802 data[i++] = device->Frequency;1804 if(!device->IsLoopbackDevice)1805 {1806 data[i++] = ALC_REFRESH;1807 data[i++] = device->Frequency / device->UpdateSize;1809 data[i++] = ALC_SYNC;1810 data[i++] = ALC_FALSE;1811 }1812 else1813 {1814 data[i++] = ALC_FORMAT_CHANNELS_SOFT;1815 data[i++] = device->FmtChans;1817 data[i++] = ALC_FORMAT_TYPE_SOFT;1818 data[i++] = device->FmtType;1819 }1821 data[i++] = ALC_MONO_SOURCES;1822 data[i++] = device->NumMonoSources;1824 data[i++] = ALC_STEREO_SOURCES;1825 data[i++] = device->NumStereoSources;1827 data[i++] = ALC_MAX_AUXILIARY_SENDS;1828 data[i++] = device->NumAuxSends;1830 data[i++] = 0;1831 }1832 break;1834 case ALC_FREQUENCY:1835 *data = device->Frequency;1836 break;1838 case ALC_REFRESH:1839 if(device->IsLoopbackDevice)1840 alcSetError(device, ALC_INVALID_DEVICE);1841 else1842 *data = device->Frequency / device->UpdateSize;1843 break;1845 case ALC_SYNC:1846 if(device->IsLoopbackDevice)1847 alcSetError(device, ALC_INVALID_DEVICE);1848 else1849 *data = ALC_FALSE;1850 break;1852 case ALC_FORMAT_CHANNELS_SOFT:1853 if(!device->IsLoopbackDevice)1854 alcSetError(device, ALC_INVALID_DEVICE);1855 else1856 *data = device->FmtChans;1857 break;1859 case ALC_FORMAT_TYPE_SOFT:1860 if(!device->IsLoopbackDevice)1861 alcSetError(device, ALC_INVALID_DEVICE);1862 else1863 *data = device->FmtType;1864 break;1866 case ALC_MONO_SOURCES:1867 *data = device->NumMonoSources;1868 break;1870 case ALC_STEREO_SOURCES:1871 *data = device->NumStereoSources;1872 break;1874 case ALC_MAX_AUXILIARY_SENDS:1875 *data = device->NumAuxSends;1876 break;1878 case ALC_CONNECTED:1879 *data = device->Connected;1880 break;1882 default:1883 alcSetError(device, ALC_INVALID_ENUM);1884 break;1885 }1886 }1887 UnlockLists();1888 }1891 /*1892 alcIsExtensionPresent1894 Determines if there is support for a particular extension1895 */1896 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)1897 {1898 ALCboolean bResult = ALC_FALSE;1899 const char *ptr;1900 size_t len;1902 if(!extName)1903 {1904 alcSetError(device, ALC_INVALID_VALUE);1905 return ALC_FALSE;1906 }1908 len = strlen(extName);1909 LockLists();1910 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);1911 UnlockLists();1912 while(ptr && *ptr)1913 {1914 if(strncasecmp(ptr, extName, len) == 0 &&1915 (ptr[len] == '\0' || isspace(ptr[len])))1916 {1917 bResult = ALC_TRUE;1918 break;1919 }1920 if((ptr=strchr(ptr, ' ')) != NULL)1921 {1922 do {1923 ++ptr;1924 } while(isspace(*ptr));1925 }1926 }1928 return bResult;1929 }1932 /*1933 alcGetProcAddress1935 Retrieves the function address for a particular extension function1936 */1937 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)1938 {1939 ALsizei i = 0;1941 if(!funcName)1942 {1943 alcSetError(device, ALC_INVALID_VALUE);1944 return NULL;1945 }1947 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)1948 i++;1949 return alcFunctions[i].address;1950 }1953 /*1954 alcGetEnumValue1956 Get the value for a particular ALC Enumerated Value1957 */1958 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)1959 {1960 ALsizei i = 0;1962 if(!enumName)1963 {1964 alcSetError(device, ALC_INVALID_VALUE);1965 return (ALCenum)0;1966 }1968 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)1969 i++;1970 return enumeration[i].value;1971 }1974 /*1975 alcCreateContext1977 Create and attach a Context to a particular Device.1978 */1979 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)1980 {1981 ALCcontext *ALContext;1982 void *temp;1984 LockLists();1985 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)1986 {1987 alcSetError(device, ALC_INVALID_DEVICE);1988 UnlockLists();1989 return NULL;1990 }1992 // Reset Context Last Error code1993 device->LastError = ALC_NO_ERROR;1995 if(UpdateDeviceParams(device, attrList) == ALC_FALSE)1996 {1997 alcSetError(device, ALC_INVALID_DEVICE);1998 aluHandleDisconnect(device);1999 UnlockLists();2000 return NULL;2001 }2003 LockDevice(device);2004 ALContext = NULL;2005 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));2006 if(temp)2007 {2008 device->Contexts = temp;2010 ALContext = calloc(1, sizeof(ALCcontext));2011 if(ALContext)2012 {2013 ALContext->MaxActiveSources = 256;2014 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *2015 ALContext->MaxActiveSources);2016 }2017 }2018 if(!ALContext || !ALContext->ActiveSources)2019 {2020 free(ALContext);2021 alcSetError(device, ALC_OUT_OF_MEMORY);2022 UnlockDevice(device);2023 if(device->NumContexts == 0)2024 {2025 ALCdevice_StopPlayback(device);2026 device->Flags &= ~DEVICE_RUNNING;2027 }2028 UnlockLists();2029 return NULL;2030 }2032 device->Contexts[device->NumContexts++] = ALContext;2033 ALContext->Device = device;2035 InitContext(ALContext);2036 UnlockDevice(device);2038 ALContext->next = g_pContextList;2039 g_pContextList = ALContext;2040 g_ulContextCount++;2042 UnlockLists();2044 return ALContext;2045 }2048 /*2049 alcDestroyContext2051 Remove a Context2052 */2053 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)2054 {2055 ALCdevice *Device;2056 ALCcontext **list;2057 ALuint i;2059 LockLists();2060 list = &g_pContextList;2061 while(*list && *list != context)2062 list = &(*list)->next;2064 if(!*list)2065 {2066 alcSetError(NULL, ALC_INVALID_CONTEXT);2067 UnlockLists();2068 return;2069 }2071 *list = (*list)->next;2072 g_ulContextCount--;2074 if(context == tls_get(LocalContext))2075 tls_set(LocalContext, NULL);2076 if(context == GlobalContext)2077 GlobalContext = NULL;2079 Device = context->Device;2080 LockDevice(Device);2081 for(i = 0;i < Device->NumContexts;i++)2082 {2083 if(Device->Contexts[i] == context)2084 {2085 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];2086 Device->NumContexts--;2087 break;2088 }2089 }2090 UnlockDevice(Device);2092 if(Device->NumContexts == 0)2093 {2094 ALCdevice_StopPlayback(Device);2095 Device->Flags &= ~DEVICE_RUNNING;2096 }2097 UnlockLists();2099 if(context->SourceMap.size > 0)2100 {2101 ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);2102 ReleaseALSources(context);2103 }2104 ResetUIntMap(&context->SourceMap);2106 if(context->EffectSlotMap.size > 0)2107 {2108 ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);2109 ReleaseALAuxiliaryEffectSlots(context);2110 }2111 ResetUIntMap(&context->EffectSlotMap);2113 free(context->ActiveSources);2114 context->ActiveSources = NULL;2115 context->MaxActiveSources = 0;2116 context->ActiveSourceCount = 0;2118 FreeContext(context);2119 }2122 /*2123 alcGetCurrentContext2125 Returns the currently active Context2126 */2127 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)2128 {2129 ALCcontext *Context;2131 LockLists();2132 Context = tls_get(LocalContext);2133 if(Context && !IsContext(Context))2134 {2135 tls_set(LocalContext, NULL);2136 Context = NULL;2137 }2138 if(!Context)2139 Context = GlobalContext;2140 UnlockLists();2142 return Context;2143 }2145 /*2146 alcGetThreadContext2148 Returns the currently active thread-local Context2149 */2150 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)2151 {2152 ALCcontext *pContext = NULL;2154 LockLists();2156 pContext = tls_get(LocalContext);2157 if(pContext && !IsContext(pContext))2158 {2159 tls_set(LocalContext, NULL);2160 pContext = NULL;2161 }2163 UnlockLists();2165 return pContext;2166 }2169 /*2170 alcGetContextsDevice2172 Returns the Device that a particular Context is attached to2173 */2174 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)2175 {2176 ALCdevice *pDevice = NULL;2178 LockLists();2179 if(IsContext(pContext))2180 pDevice = pContext->Device;2181 else2182 alcSetError(NULL, ALC_INVALID_CONTEXT);2183 UnlockLists();2185 return pDevice;2186 }2189 /*2190 alcMakeContextCurrent2192 Makes the given Context the active Context2193 */2194 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)2195 {2196 ALboolean bReturn = AL_TRUE;2198 LockLists();2200 // context must be a valid Context or NULL2201 if(context == NULL || IsContext(context))2202 {2203 GlobalContext = context;2204 tls_set(LocalContext, NULL);2205 }2206 else2207 {2208 alcSetError(NULL, ALC_INVALID_CONTEXT);2209 bReturn = AL_FALSE;2210 }2212 UnlockLists();2214 return bReturn;2215 }2217 /*2218 alcSetThreadContext2220 Makes the given Context the active Context for the current thread2221 */2222 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)2223 {2224 ALboolean bReturn = AL_TRUE;2226 LockLists();2228 // context must be a valid Context or NULL2229 if(context == NULL || IsContext(context))2230 tls_set(LocalContext, context);2231 else2232 {2233 alcSetError(NULL, ALC_INVALID_CONTEXT);2234 bReturn = AL_FALSE;2235 }2237 UnlockLists();2239 return bReturn;2240 }2243 static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)2244 {2245 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)2246 {2247 *chans = DevFmtMono;2248 *type = DevFmtFloat;2249 return;2250 }2251 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0)2252 {2253 *chans = DevFmtStereo;2254 *type = DevFmtFloat;2255 return;2256 }2257 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0)2258 {2259 *chans = DevFmtQuad;2260 *type = DevFmtFloat;2261 return;2262 }2263 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0)2264 {2265 *chans = DevFmtX51;2266 *type = DevFmtFloat;2267 return;2268 }2269 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0)2270 {2271 *chans = DevFmtX61;2272 *type = DevFmtFloat;2273 return;2274 }2275 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0)2276 {2277 *chans = DevFmtX71;2278 *type = DevFmtFloat;2279 return;2280 }2282 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0)2283 {2284 *chans = DevFmtMono;2285 *type = DevFmtShort;2286 return;2287 }2288 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0)2289 {2290 *chans = DevFmtStereo;2291 *type = DevFmtShort;2292 return;2293 }2294 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0)2295 {2296 *chans = DevFmtQuad;2297 *type = DevFmtShort;2298 return;2299 }2300 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0)2301 {2302 *chans = DevFmtX51;2303 *type = DevFmtShort;2304 return;2305 }2306 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0)2307 {2308 *chans = DevFmtX61;2309 *type = DevFmtShort;2310 return;2311 }2312 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0)2313 {2314 *chans = DevFmtX71;2315 *type = DevFmtShort;2316 return;2317 }2319 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0)2320 {2321 *chans = DevFmtMono;2322 *type = DevFmtByte;2323 return;2324 }2325 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0)2326 {2327 *chans = DevFmtStereo;2328 *type = DevFmtByte;2329 return;2330 }2331 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0)2332 {2333 *chans = DevFmtQuad;2334 *type = DevFmtByte;2335 return;2336 }2337 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0)2338 {2339 *chans = DevFmtX51;2340 *type = DevFmtByte;2341 return;2342 }2343 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0)2344 {2345 *chans = DevFmtX61;2346 *type = DevFmtByte;2347 return;2348 }2349 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0)2350 {2351 *chans = DevFmtX71;2352 *type = DevFmtByte;2353 return;2354 }2356 ERR("Unknown format: \"%s\"\n", str);2357 *chans = DevFmtStereo;2358 *type = DevFmtShort;2359 }2361 /*2362 alcOpenDevice2364 Open the Device specified.2365 */2366 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)2367 {2368 const ALCchar *fmt;2369 ALCdevice *device;2371 DO_INITCONFIG();2373 if(!PlaybackBackend.name)2374 {2375 alcSetError(NULL, ALC_INVALID_VALUE);2376 return NULL;2377 }2379 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))2380 deviceName = NULL;2382 device = calloc(1, sizeof(ALCdevice));2383 if(!device)2384 {2385 alcSetError(NULL, ALC_OUT_OF_MEMORY);2386 return NULL;2387 }2389 //Validate device2390 device->Funcs = &PlaybackBackend.Funcs;2391 device->Connected = ALC_TRUE;2392 device->IsCaptureDevice = AL_FALSE;2393 device->IsLoopbackDevice = AL_FALSE;2394 InitializeCriticalSection(&device->Mutex);2395 device->LastError = ALC_NO_ERROR;2397 device->Flags = 0;2398 device->Bs2b = NULL;2399 device->szDeviceName = NULL;2401 device->Contexts = NULL;2402 device->NumContexts = 0;2404 InitUIntMap(&device->BufferMap);2405 InitUIntMap(&device->EffectMap);2406 InitUIntMap(&device->FilterMap);2408 //Set output format2409 if(ConfigValueExists(NULL, "frequency"))2410 device->Flags |= DEVICE_FREQUENCY_REQUEST;2411 device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE);2412 if(device->Frequency < 8000)2413 device->Frequency = 8000;2415 if(ConfigValueExists(NULL, "format"))2416 device->Flags |= DEVICE_CHANNELS_REQUEST;2417 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");2418 GetFormatFromString(fmt, &device->FmtChans, &device->FmtType);2420 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);2421 if(device->NumUpdates < 2)2422 device->NumUpdates = 4;2424 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);2425 if(device->UpdateSize <= 0)2426 device->UpdateSize = 1024;2428 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2429 if(device->MaxNoOfSources <= 0)2430 device->MaxNoOfSources = 256;2432 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2433 if(device->AuxiliaryEffectSlotMax <= 0)2434 device->AuxiliaryEffectSlotMax = 4;2436 device->NumStereoSources = 1;2437 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2439 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2440 if(device->NumAuxSends > MAX_SENDS)2441 device->NumAuxSends = MAX_SENDS;2443 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2445 // Find a playback device to open2446 LockLists();2447 if(ALCdevice_OpenPlayback(device, deviceName))2448 {2449 device->next = g_pDeviceList;2450 g_pDeviceList = device;2451 g_ulDeviceCount++;2452 }2453 else2454 {2455 // No suitable output device found2456 DeleteCriticalSection(&device->Mutex);2457 free(device);2458 device = NULL;2459 alcSetError(NULL, ALC_INVALID_VALUE);2460 }2461 UnlockLists();2463 return device;2464 }2467 /*2468 alcCloseDevice2470 Close the specified Device2471 */2472 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)2473 {2474 ALCdevice **list;2476 LockLists();2477 list = &g_pDeviceList;2478 while(*list && *list != pDevice)2479 list = &(*list)->next;2481 if(!*list || (*list)->IsCaptureDevice)2482 {2483 alcSetError(*list, ALC_INVALID_DEVICE);2484 UnlockLists();2485 return ALC_FALSE;2486 }2488 *list = (*list)->next;2489 g_ulDeviceCount--;2491 UnlockLists();2493 if(pDevice->NumContexts > 0)2494 {2495 WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);2496 while(pDevice->NumContexts > 0)2497 alcDestroyContext(pDevice->Contexts[0]);2498 }2499 ALCdevice_ClosePlayback(pDevice);2501 if(pDevice->BufferMap.size > 0)2502 {2503 WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);2504 ReleaseALBuffers(pDevice);2505 }2506 ResetUIntMap(&pDevice->BufferMap);2508 if(pDevice->EffectMap.size > 0)2509 {2510 WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);2511 ReleaseALEffects(pDevice);2512 }2513 ResetUIntMap(&pDevice->EffectMap);2515 if(pDevice->FilterMap.size > 0)2516 {2517 WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);2518 ReleaseALFilters(pDevice);2519 }2520 ResetUIntMap(&pDevice->FilterMap);2522 free(pDevice->Bs2b);2523 pDevice->Bs2b = NULL;2525 free(pDevice->szDeviceName);2526 pDevice->szDeviceName = NULL;2528 free(pDevice->Contexts);2529 pDevice->Contexts = NULL;2531 DeleteCriticalSection(&pDevice->Mutex);2533 //Release device structure2534 memset(pDevice, 0, sizeof(ALCdevice));2535 free(pDevice);2537 return ALC_TRUE;2538 }2541 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void)2542 {2543 ALCdevice *device;2545 DO_INITCONFIG();2547 device = calloc(1, sizeof(ALCdevice));2548 if(!device)2549 {2550 alcSetError(NULL, ALC_OUT_OF_MEMORY);2551 return NULL;2552 }2554 //Validate device2555 device->Funcs = &BackendLoopback.Funcs;2556 device->Connected = ALC_TRUE;2557 device->IsCaptureDevice = AL_FALSE;2558 device->IsLoopbackDevice = AL_TRUE;2559 InitializeCriticalSection(&device->Mutex);2560 device->LastError = ALC_NO_ERROR;2562 device->Flags = 0;2563 device->Bs2b = NULL;2564 device->szDeviceName = NULL;2566 device->Contexts = NULL;2567 device->NumContexts = 0;2569 InitUIntMap(&device->BufferMap);2570 InitUIntMap(&device->EffectMap);2571 InitUIntMap(&device->FilterMap);2573 //Set output format2574 device->Frequency = 44100;2575 device->FmtChans = DevFmtStereo;2576 device->FmtType = DevFmtShort;2578 device->NumUpdates = 0;2579 device->UpdateSize = 0;2581 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2582 if(device->MaxNoOfSources <= 0)2583 device->MaxNoOfSources = 256;2585 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2586 if(device->AuxiliaryEffectSlotMax <= 0)2587 device->AuxiliaryEffectSlotMax = 4;2589 device->NumStereoSources = 1;2590 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2592 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2593 if(device->NumAuxSends > MAX_SENDS)2594 device->NumAuxSends = MAX_SENDS;2596 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2598 // Open the "backend"2599 LockLists();2600 ALCdevice_OpenPlayback(device, "Loopback");2602 device->next = g_pDeviceList;2603 g_pDeviceList = device;2604 g_ulDeviceCount++;2605 UnlockLists();2607 return device;2608 }2610 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)2611 {2612 ALCboolean ret = ALC_FALSE;2614 LockLists();2615 if(!IsDevice(device) || !device->IsLoopbackDevice)2616 alcSetError(device, ALC_INVALID_DEVICE);2617 else if(freq <= 0)2618 alcSetError(device, ALC_INVALID_VALUE);2619 else if(!IsValidALCType(type) || !IsValidALCChannels(channels))2620 alcSetError(device, ALC_INVALID_ENUM);2621 else2622 {2623 if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 &&2624 freq >= 8000)2625 ret = ALC_TRUE;2626 }2627 UnlockLists();2629 return ret;2630 }2632 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)2633 {2634 LockLists();2635 if(!IsDevice(device) || !device->IsLoopbackDevice)2636 alcSetError(device, ALC_INVALID_DEVICE);2637 else if(samples < 0 || (samples > 0 && buffer == NULL))2638 alcSetError(device, ALC_INVALID_VALUE);2639 else2640 aluMixData(device, buffer, samples);2641 UnlockLists();2642 }2645 static void ReleaseALC(ALCboolean doclose)2646 {2647 free(alcDeviceList); alcDeviceList = NULL;2648 alcDeviceListSize = 0;2649 free(alcAllDeviceList); alcAllDeviceList = NULL;2650 alcAllDeviceListSize = 0;2651 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;2652 alcCaptureDeviceListSize = 0;2654 free(alcDefaultDeviceSpecifier);2655 alcDefaultDeviceSpecifier = NULL;2656 free(alcDefaultAllDeviceSpecifier);2657 alcDefaultAllDeviceSpecifier = NULL;2658 free(alcCaptureDefaultDeviceSpecifier);2659 alcCaptureDefaultDeviceSpecifier = NULL;2661 if(doclose)2662 {2663 if(g_ulDeviceCount > 0)2664 WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2666 while(g_pDeviceList)2667 {2668 if(g_pDeviceList->IsCaptureDevice)2669 alcCaptureCloseDevice(g_pDeviceList);2670 else2671 alcCloseDevice(g_pDeviceList);2672 }2673 }2674 else2675 {2676 if(g_ulDeviceCount > 0)2677 WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2678 }2679 }2681 ///////////////////////////////////////////////////////