Mercurial > audio-send
view Alc/ALc.c @ 14:63312ec4a2bf
limit to 16bit mono for now.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 31 Oct 2011 08:01:08 -0700 |
parents | 99df34265b40 |
children |
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 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },47 { "send", alc_send_init, alc_send_deinit, alc_send_probe, EmptyFuncs },48 // this entry is so that the list is terminated by a "null" object,49 // and helps things to tell when they've reached the end of the list.50 { NULL, NULL, NULL, NULL, EmptyFuncs }51 };52 static struct BackendInfo BackendLoopback = {53 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs54 };55 #undef EmptyFuncs57 static struct BackendInfo PlaybackBackend;58 static struct BackendInfo CaptureBackend;60 ///////////////////////////////////////////////////////61 // STRING and EXTENSIONS63 typedef struct ALCfunction {64 const ALCchar *funcName;65 ALCvoid *address;66 } ALCfunction;68 typedef struct ALCenums {69 const ALCchar *enumName;70 ALCenum value;71 } ALCenums;74 static const ALCfunction alcFunctions[] = {75 { "alcCreateContext", (ALCvoid *) alcCreateContext },76 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },77 { "alcProcessContext", (ALCvoid *) alcProcessContext },78 { "alcSuspendContext", (ALCvoid *) alcSuspendContext },79 { "alcDestroyContext", (ALCvoid *) alcDestroyContext },80 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext },81 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice },82 { "alcOpenDevice", (ALCvoid *) alcOpenDevice },83 { "alcCloseDevice", (ALCvoid *) alcCloseDevice },84 { "alcGetError", (ALCvoid *) alcGetError },85 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent },86 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress },87 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue },88 { "alcGetString", (ALCvoid *) alcGetString },89 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv },90 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice },91 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice },92 { "alcCaptureStart", (ALCvoid *) alcCaptureStart },93 { "alcCaptureStop", (ALCvoid *) alcCaptureStop },94 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples },96 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },97 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },99 { "alcLoopbackOpenDeviceSOFT", (ALCvoid *) alcLoopbackOpenDeviceSOFT},100 { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT},101 { "alcRenderSamplesSOFT", (ALCvoid *) alcRenderSamplesSOFT },103 { "alEnable", (ALCvoid *) alEnable },104 { "alDisable", (ALCvoid *) alDisable },105 { "alIsEnabled", (ALCvoid *) alIsEnabled },106 { "alGetString", (ALCvoid *) alGetString },107 { "alGetBooleanv", (ALCvoid *) alGetBooleanv },108 { "alGetIntegerv", (ALCvoid *) alGetIntegerv },109 { "alGetFloatv", (ALCvoid *) alGetFloatv },110 { "alGetDoublev", (ALCvoid *) alGetDoublev },111 { "alGetBoolean", (ALCvoid *) alGetBoolean },112 { "alGetInteger", (ALCvoid *) alGetInteger },113 { "alGetFloat", (ALCvoid *) alGetFloat },114 { "alGetDouble", (ALCvoid *) alGetDouble },115 { "alGetError", (ALCvoid *) alGetError },116 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent },117 { "alGetProcAddress", (ALCvoid *) alGetProcAddress },118 { "alGetEnumValue", (ALCvoid *) alGetEnumValue },119 { "alListenerf", (ALCvoid *) alListenerf },120 { "alListener3f", (ALCvoid *) alListener3f },121 { "alListenerfv", (ALCvoid *) alListenerfv },122 { "alListeneri", (ALCvoid *) alListeneri },123 { "alListener3i", (ALCvoid *) alListener3i },124 { "alListeneriv", (ALCvoid *) alListeneriv },125 { "alGetListenerf", (ALCvoid *) alGetListenerf },126 { "alGetListener3f", (ALCvoid *) alGetListener3f },127 { "alGetListenerfv", (ALCvoid *) alGetListenerfv },128 { "alGetListeneri", (ALCvoid *) alGetListeneri },129 { "alGetListener3i", (ALCvoid *) alGetListener3i },130 { "alGetListeneriv", (ALCvoid *) alGetListeneriv },131 { "alGenSources", (ALCvoid *) alGenSources },132 { "alDeleteSources", (ALCvoid *) alDeleteSources },133 { "alIsSource", (ALCvoid *) alIsSource },134 { "alSourcef", (ALCvoid *) alSourcef },135 { "alSource3f", (ALCvoid *) alSource3f },136 { "alSourcefv", (ALCvoid *) alSourcefv },137 { "alSourcei", (ALCvoid *) alSourcei },138 { "alSource3i", (ALCvoid *) alSource3i },139 { "alSourceiv", (ALCvoid *) alSourceiv },140 { "alGetSourcef", (ALCvoid *) alGetSourcef },141 { "alGetSource3f", (ALCvoid *) alGetSource3f },142 { "alGetSourcefv", (ALCvoid *) alGetSourcefv },143 { "alGetSourcei", (ALCvoid *) alGetSourcei },144 { "alGetSource3i", (ALCvoid *) alGetSource3i },145 { "alGetSourceiv", (ALCvoid *) alGetSourceiv },146 { "alSourcePlayv", (ALCvoid *) alSourcePlayv },147 { "alSourceStopv", (ALCvoid *) alSourceStopv },148 { "alSourceRewindv", (ALCvoid *) alSourceRewindv },149 { "alSourcePausev", (ALCvoid *) alSourcePausev },150 { "alSourcePlay", (ALCvoid *) alSourcePlay },151 { "alSourceStop", (ALCvoid *) alSourceStop },152 { "alSourceRewind", (ALCvoid *) alSourceRewind },153 { "alSourcePause", (ALCvoid *) alSourcePause },154 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers },155 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers },156 { "alGenBuffers", (ALCvoid *) alGenBuffers },157 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers },158 { "alIsBuffer", (ALCvoid *) alIsBuffer },159 { "alBufferData", (ALCvoid *) alBufferData },160 { "alBufferf", (ALCvoid *) alBufferf },161 { "alBuffer3f", (ALCvoid *) alBuffer3f },162 { "alBufferfv", (ALCvoid *) alBufferfv },163 { "alBufferi", (ALCvoid *) alBufferi },164 { "alBuffer3i", (ALCvoid *) alBuffer3i },165 { "alBufferiv", (ALCvoid *) alBufferiv },166 { "alGetBufferf", (ALCvoid *) alGetBufferf },167 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f },168 { "alGetBufferfv", (ALCvoid *) alGetBufferfv },169 { "alGetBufferi", (ALCvoid *) alGetBufferi },170 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i },171 { "alGetBufferiv", (ALCvoid *) alGetBufferiv },172 { "alDopplerFactor", (ALCvoid *) alDopplerFactor },173 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity },174 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound },175 { "alDistanceModel", (ALCvoid *) alDistanceModel },177 { "alGenFilters", (ALCvoid *) alGenFilters },178 { "alDeleteFilters", (ALCvoid *) alDeleteFilters },179 { "alIsFilter", (ALCvoid *) alIsFilter },180 { "alFilteri", (ALCvoid *) alFilteri },181 { "alFilteriv", (ALCvoid *) alFilteriv },182 { "alFilterf", (ALCvoid *) alFilterf },183 { "alFilterfv", (ALCvoid *) alFilterfv },184 { "alGetFilteri", (ALCvoid *) alGetFilteri },185 { "alGetFilteriv", (ALCvoid *) alGetFilteriv },186 { "alGetFilterf", (ALCvoid *) alGetFilterf },187 { "alGetFilterfv", (ALCvoid *) alGetFilterfv },188 { "alGenEffects", (ALCvoid *) alGenEffects },189 { "alDeleteEffects", (ALCvoid *) alDeleteEffects },190 { "alIsEffect", (ALCvoid *) alIsEffect },191 { "alEffecti", (ALCvoid *) alEffecti },192 { "alEffectiv", (ALCvoid *) alEffectiv },193 { "alEffectf", (ALCvoid *) alEffectf },194 { "alEffectfv", (ALCvoid *) alEffectfv },195 { "alGetEffecti", (ALCvoid *) alGetEffecti },196 { "alGetEffectiv", (ALCvoid *) alGetEffectiv },197 { "alGetEffectf", (ALCvoid *) alGetEffectf },198 { "alGetEffectfv", (ALCvoid *) alGetEffectfv },199 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots},200 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},201 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot },202 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti },203 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv },204 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf },205 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv },206 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti},207 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},208 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf},209 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},211 { "alBufferSubDataSOFT", (ALCvoid *) alBufferSubDataSOFT },213 { "alBufferSamplesSOFT", (ALCvoid *) alBufferSamplesSOFT },214 { "alBufferSubSamplesSOFT", (ALCvoid *) alBufferSubSamplesSOFT },215 { "alGetBufferSamplesSOFT", (ALCvoid *) alGetBufferSamplesSOFT },216 { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT},218 { "alDeferUpdatesSOFT", (ALCvoid *) alDeferUpdatesSOFT },219 { "alProcessUpdatesSOFT", (ALCvoid *) alProcessUpdatesSOFT },221 { NULL, (ALCvoid *) NULL }222 };224 static const ALCenums enumeration[] = {225 // Types226 { "ALC_INVALID", ALC_INVALID },227 { "ALC_FALSE", ALC_FALSE },228 { "ALC_TRUE", ALC_TRUE },230 // ALC Properties231 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },232 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION },233 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },234 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },235 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },236 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },237 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },238 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },239 { "ALC_EXTENSIONS", ALC_EXTENSIONS },240 { "ALC_FREQUENCY", ALC_FREQUENCY },241 { "ALC_REFRESH", ALC_REFRESH },242 { "ALC_SYNC", ALC_SYNC },243 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES },244 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },245 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },246 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},247 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },248 { "ALC_CONNECTED", ALC_CONNECTED },250 // EFX Properties251 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },252 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },253 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },255 // Loopback device Properties256 { "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT },257 { "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT },259 // Buffer Channel Configurations260 { "ALC_MONO", ALC_MONO },261 { "ALC_STEREO", ALC_STEREO },262 { "ALC_QUAD", ALC_QUAD },263 { "ALC_5POINT1", ALC_5POINT1 },264 { "ALC_6POINT1", ALC_6POINT1 },265 { "ALC_7POINT1", ALC_7POINT1 },267 // Buffer Sample Types268 { "ALC_BYTE", ALC_BYTE },269 { "ALC_UNSIGNED_BYTE", ALC_UNSIGNED_BYTE },270 { "ALC_SHORT", ALC_SHORT },271 { "ALC_UNSIGNED_SHORT", ALC_UNSIGNED_SHORT },272 { "ALC_INT", ALC_INT },273 { "ALC_UNSIGNED_INT", ALC_UNSIGNED_INT },274 { "ALC_FLOAT", ALC_FLOAT },276 // ALC Error Message277 { "ALC_NO_ERROR", ALC_NO_ERROR },278 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },279 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },280 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM },281 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE },282 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },284 { NULL, (ALCenum)0 }285 };286 // Error strings287 static const ALCchar alcNoError[] = "No Error";288 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";289 static const ALCchar alcErrInvalidContext[] = "Invalid Context";290 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";291 static const ALCchar alcErrInvalidValue[] = "Invalid Value";292 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";294 /* Device lists. Sizes only include the first ending null character, not the295 * second */296 static ALCchar *alcDeviceList;297 static size_t alcDeviceListSize;298 static ALCchar *alcAllDeviceList;299 static size_t alcAllDeviceListSize;300 static ALCchar *alcCaptureDeviceList;301 static size_t alcCaptureDeviceListSize;302 /* Default is always the first in the list */303 static ALCchar *alcDefaultDeviceSpecifier;304 static ALCchar *alcDefaultAllDeviceSpecifier;305 static ALCchar *alcCaptureDefaultDeviceSpecifier;308 static const ALCchar alcNoDeviceExtList[] =309 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "310 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";311 static const ALCchar alcExtensionList[] =312 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "313 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "314 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";315 static const ALCint alcMajorVersion = 1;316 static const ALCint alcMinorVersion = 1;318 static const ALCint alcEFXMajorVersion = 1;319 static const ALCint alcEFXMinorVersion = 0;321 ///////////////////////////////////////////////////////324 ///////////////////////////////////////////////////////325 // Global Variables327 static CRITICAL_SECTION ListLock;329 /* Device List */330 static ALCdevice *g_pDeviceList = NULL;331 static ALCuint g_ulDeviceCount = 0;333 // Context List334 static ALCcontext *g_pContextList = NULL;335 static ALCuint g_ulContextCount = 0;337 // Thread-local current context338 static tls_type LocalContext;339 // Process-wide current context340 static ALCcontext *GlobalContext;342 // Context Error343 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;345 // Default context extensions346 static const ALchar alExtList[] =347 "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 "348 "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "349 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "350 "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data "351 "AL_SOFTX_deferred_updates AL_SOFT_loop_points "352 "AL_SOFTX_non_virtual_channels";354 // Mixing Priority Level355 ALint RTPrioLevel;357 // Output Log File358 FILE *LogFile;360 // Output Log Level361 #ifdef _DEBUG362 enum LogLevel LogLevel = LogWarning;363 #else364 enum LogLevel LogLevel = LogError;365 #endif367 // Cone scalar368 ALdouble ConeScale = 0.5;370 // Localized Z scalar for mono sources371 ALdouble ZScale = 1.0;373 /* One-time configuration init control */374 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;376 ///////////////////////////////////////////////////////379 ///////////////////////////////////////////////////////380 // ALC Related helper functions381 static void ReleaseALC(ALCboolean doclose);383 static void alc_initconfig(void);384 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)386 #if defined(_WIN32)387 static void alc_init(void);388 static void alc_deinit(void);389 static void alc_deinit_safe(void);391 #ifndef AL_LIBTYPE_STATIC392 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)393 {394 // Perform actions based on the reason for calling.395 switch(ul_reason_for_call)396 {397 case DLL_PROCESS_ATTACH:398 DisableThreadLibraryCalls(hModule);399 alc_init();400 break;402 case DLL_PROCESS_DETACH:403 if(!lpReserved)404 alc_deinit();405 else406 alc_deinit_safe();407 break;408 }409 return TRUE;410 }411 #elif defined(_MSC_VER)412 #pragma section(".CRT$XCU",read)413 static void alc_constructor(void);414 static void alc_destructor(void);415 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;417 static void alc_constructor(void)418 {419 atexit(alc_destructor);420 alc_init();421 }423 static void alc_destructor(void)424 {425 alc_deinit();426 }427 #elif defined(HAVE_GCC_DESTRUCTOR)428 static void alc_init(void) __attribute__((constructor));429 static void alc_deinit(void) __attribute__((destructor));430 #else431 #error "No static initialization available on this platform!"432 #endif433 #elif defined(HAVE_GCC_DESTRUCTOR)434 static void alc_init(void) __attribute__((constructor));435 static void alc_deinit(void) __attribute__((destructor));436 #else437 #error "No global initialization available on this platform!"438 #endif440 static void alc_init(void)441 {442 const char *str;444 LogFile = stderr;446 str = getenv("__ALSOFT_HALF_ANGLE_CONES");447 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))448 ConeScale = 1.0;450 str = getenv("__ALSOFT_REVERSE_Z");451 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))452 ZScale = -1.0;454 tls_create(&LocalContext);455 InitializeCriticalSection(&ListLock);456 ThunkInit();457 }459 static void alc_deinit_safe(void)460 {461 ReleaseALC(ALC_FALSE);463 FreeALConfig();465 ThunkExit();466 DeleteCriticalSection(&ListLock);467 tls_delete(LocalContext);469 if(LogFile != stderr)470 fclose(LogFile);471 LogFile = NULL;472 }474 static void alc_deinit(void)475 {476 int i;478 ReleaseALC(ALC_TRUE);480 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));481 memset(&CaptureBackend, 0, sizeof(CaptureBackend));483 for(i = 0;BackendList[i].Deinit;i++)484 BackendList[i].Deinit();485 BackendLoopback.Deinit();487 alc_deinit_safe();488 }490 static void alc_initconfig(void)491 {492 printf("OPENAL-AURELLEM: alc_init_config!!\n");493 const char *devs, *str;494 int i, n;496 str = getenv("ALSOFT_LOGLEVEL");497 if(str)498 {499 long lvl = strtol(str, NULL, 0);500 if(lvl >= NoLog && lvl <= LogTrace)501 LogLevel = lvl;502 }504 str = getenv("ALSOFT_LOGFILE");505 if(str && str[0])506 {507 FILE *logfile = fopen(str, "wat");508 if(logfile) LogFile = logfile;509 else ERR("Failed to open log file '%s'\n", str);510 }512 ReadALConfig();514 InitHrtf();516 #ifdef _WIN32517 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 1);518 #else519 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);520 #endif522 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);523 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)524 DefaultResampler = RESAMPLER_DEFAULT;526 ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) /527 20.0f);528 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);530 // RLM: This was previously taken from the config file531 // where the user had their choice of backend532 // for this special version of open-al the option is533 // disabled since there is only the "send" device.534 devs = "send";536 //printf("these are the devices: %s\n", devs);538 if(devs[0])539 {540 int n;541 size_t len;542 const char *next = devs;543 int endlist, delitem;545 i = 0;546 do {547 devs = next;548 //printf("AURELLEM: devs is %s\n",devs);549 next = strchr(devs, ',');551 delitem = (devs[0] == '-');552 if(devs[0] == '-') devs++;554 if(!devs[0] || devs[0] == ',')555 {556 endlist = 0;557 continue;558 }559 endlist = 1;561 len = (next ? ((size_t)(next-devs)) : strlen(devs));562 for(n = i;BackendList[n].Init;n++)563 {564 //printf("AURELLEM: device-name -- %s\n",BackendList[n].name);565 if(len == strlen(BackendList[n].name) &&566 strncmp(BackendList[n].name, devs, len) == 0)567 {568 if(delitem)569 {570 do {571 BackendList[n] = BackendList[n+1];572 ++n;573 }574 // this relies on the last entry being terminated by an575 // entry with all nulls.576 while(BackendList[n].Init);577 }578 else579 {580 struct BackendInfo Bkp = BackendList[n];581 while(n > i)582 {583 BackendList[n] = BackendList[n-1];584 --n;585 }586 BackendList[n] = Bkp;588 i++;589 }590 break;591 }592 }593 } while(next++);595 if(endlist)596 {597 BackendList[i].name = NULL;598 BackendList[i].Init = NULL;599 BackendList[i].Deinit = NULL;600 BackendList[i].Probe = NULL;601 }602 }604 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)605 {606 if(!BackendList[i].Init(&BackendList[i].Funcs))607 {608 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);609 continue;610 }612 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);613 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)614 {615 PlaybackBackend = BackendList[i];616 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);617 }618 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)619 {620 CaptureBackend = BackendList[i];621 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);622 }623 }624 BackendLoopback.Init(&BackendLoopback.Funcs);626 str = GetConfigValue(NULL, "excludefx", "");627 if(str[0])628 {629 size_t len;630 const char *next = str;632 do {633 str = next;634 next = strchr(str, ',');636 if(!str[0] || next == str)637 continue;639 len = (next ? ((size_t)(next-str)) : strlen(str));640 for(n = 0;EffectList[n].name;n++)641 {642 if(len == strlen(EffectList[n].name) &&643 strncmp(EffectList[n].name, str, len) == 0)644 DisabledEffects[EffectList[n].type] = AL_TRUE;645 }646 } while(next++);647 }648 }651 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)652 {653 free(*list);654 *list = NULL;655 *listsize = 0;657 DO_INITCONFIG();658 if(type == CAPTURE_DEVICE_PROBE)659 CaptureBackend.Probe(type);660 else661 PlaybackBackend.Probe(type);662 }664 static void ProbeDeviceList(void)665 { ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }666 static void ProbeAllDeviceList(void)667 { ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }668 static void ProbeCaptureDeviceList(void)669 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }672 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)673 {674 size_t len = strlen(name);675 void *temp;677 if(len == 0)678 return;680 temp = realloc(*List, (*ListSize) + len + 2);681 if(!temp)682 {683 ERR("Realloc failed to add %s!\n", name);684 return;685 }686 *List = temp;688 memcpy((*List)+(*ListSize), name, len+1);689 *ListSize += len+1;690 (*List)[*ListSize] = 0;691 }693 #define DECL_APPEND_LIST_FUNC(type) \694 void Append##type##List(const ALCchar *name) \695 { AppendList(name, &alc##type##List, &alc##type##ListSize); }697 DECL_APPEND_LIST_FUNC(Device)698 DECL_APPEND_LIST_FUNC(AllDevice)699 DECL_APPEND_LIST_FUNC(CaptureDevice)701 #undef DECL_APPEND_LIST_FUNC704 /* Sets the default channel order used by most non-WaveFormatEx-based APIs */705 void SetDefaultChannelOrder(ALCdevice *device)706 {707 switch(device->FmtChans)708 {709 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;710 device->DevChannels[1] = FRONT_RIGHT;711 device->DevChannels[2] = BACK_LEFT;712 device->DevChannels[3] = BACK_RIGHT;713 device->DevChannels[4] = FRONT_CENTER;714 device->DevChannels[5] = LFE;715 return;717 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;718 device->DevChannels[1] = FRONT_RIGHT;719 device->DevChannels[2] = BACK_LEFT;720 device->DevChannels[3] = BACK_RIGHT;721 device->DevChannels[4] = FRONT_CENTER;722 device->DevChannels[5] = LFE;723 device->DevChannels[6] = SIDE_LEFT;724 device->DevChannels[7] = SIDE_RIGHT;725 return;727 /* Same as WFX order */728 case DevFmtMono:729 case DevFmtStereo:730 case DevFmtQuad:731 case DevFmtX51Side:732 case DevFmtX61:733 break;734 }735 SetDefaultWFXChannelOrder(device);736 }737 /* Sets the default order used by WaveFormatEx */738 void SetDefaultWFXChannelOrder(ALCdevice *device)739 {740 switch(device->FmtChans)741 {742 case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;744 case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;745 device->DevChannels[1] = FRONT_RIGHT; break;747 case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;748 device->DevChannels[1] = FRONT_RIGHT;749 device->DevChannels[2] = BACK_LEFT;750 device->DevChannels[3] = BACK_RIGHT; break;752 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;753 device->DevChannels[1] = FRONT_RIGHT;754 device->DevChannels[2] = FRONT_CENTER;755 device->DevChannels[3] = LFE;756 device->DevChannels[4] = BACK_LEFT;757 device->DevChannels[5] = BACK_RIGHT; break;759 case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;760 device->DevChannels[1] = FRONT_RIGHT;761 device->DevChannels[2] = FRONT_CENTER;762 device->DevChannels[3] = LFE;763 device->DevChannels[4] = SIDE_LEFT;764 device->DevChannels[5] = SIDE_RIGHT; break;766 case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;767 device->DevChannels[1] = FRONT_RIGHT;768 device->DevChannels[2] = FRONT_CENTER;769 device->DevChannels[3] = LFE;770 device->DevChannels[4] = BACK_CENTER;771 device->DevChannels[5] = SIDE_LEFT;772 device->DevChannels[6] = SIDE_RIGHT; break;774 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;775 device->DevChannels[1] = FRONT_RIGHT;776 device->DevChannels[2] = FRONT_CENTER;777 device->DevChannels[3] = LFE;778 device->DevChannels[4] = BACK_LEFT;779 device->DevChannels[5] = BACK_RIGHT;780 device->DevChannels[6] = SIDE_LEFT;781 device->DevChannels[7] = SIDE_RIGHT; break;782 }783 }786 const ALCchar *DevFmtTypeString(enum DevFmtType type)787 {788 switch(type)789 {790 case DevFmtByte: return "Signed Byte";791 case DevFmtUByte: return "Unsigned Byte";792 case DevFmtShort: return "Signed Short";793 case DevFmtUShort: return "Unsigned Short";794 case DevFmtFloat: return "Float";795 }796 return "(unknown type)";797 }798 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)799 {800 switch(chans)801 {802 case DevFmtMono: return "Mono";803 case DevFmtStereo: return "Stereo";804 case DevFmtQuad: return "Quadraphonic";805 case DevFmtX51: return "5.1 Surround";806 case DevFmtX51Side: return "5.1 Side";807 case DevFmtX61: return "6.1 Surround";808 case DevFmtX71: return "7.1 Surround";809 }810 return "(unknown channels)";811 }813 ALuint BytesFromDevFmt(enum DevFmtType type)814 {815 switch(type)816 {817 case DevFmtByte: return sizeof(ALbyte);818 case DevFmtUByte: return sizeof(ALubyte);819 case DevFmtShort: return sizeof(ALshort);820 case DevFmtUShort: return sizeof(ALushort);821 case DevFmtFloat: return sizeof(ALfloat);822 }823 return 0;824 }825 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)826 {827 switch(chans)828 {829 case DevFmtMono: return 1;830 case DevFmtStereo: return 2;831 case DevFmtQuad: return 4;832 case DevFmtX51: return 6;833 case DevFmtX51Side: return 6;834 case DevFmtX61: return 7;835 case DevFmtX71: return 8;836 }837 return 0;838 }839 ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,840 enum DevFmtType *type)841 {842 switch(format)843 {844 case AL_FORMAT_MONO8:845 *chans = DevFmtMono;846 *type = DevFmtUByte;847 return AL_TRUE;848 case AL_FORMAT_MONO16:849 *chans = DevFmtMono;850 *type = DevFmtShort;851 return AL_TRUE;852 case AL_FORMAT_MONO_FLOAT32:853 *chans = DevFmtMono;854 *type = DevFmtFloat;855 return AL_TRUE;856 case AL_FORMAT_STEREO8:857 *chans = DevFmtStereo;858 *type = DevFmtUByte;859 return AL_TRUE;860 case AL_FORMAT_STEREO16:861 *chans = DevFmtStereo;862 *type = DevFmtShort;863 return AL_TRUE;864 case AL_FORMAT_STEREO_FLOAT32:865 *chans = DevFmtStereo;866 *type = DevFmtFloat;867 return AL_TRUE;868 case AL_FORMAT_QUAD8:869 *chans = DevFmtQuad;870 *type = DevFmtUByte;871 return AL_TRUE;872 case AL_FORMAT_QUAD16:873 *chans = DevFmtQuad;874 *type = DevFmtShort;875 return AL_TRUE;876 case AL_FORMAT_QUAD32:877 *chans = DevFmtQuad;878 *type = DevFmtFloat;879 return AL_TRUE;880 case AL_FORMAT_51CHN8:881 *chans = DevFmtX51;882 *type = DevFmtUByte;883 return AL_TRUE;884 case AL_FORMAT_51CHN16:885 *chans = DevFmtX51;886 *type = DevFmtShort;887 return AL_TRUE;888 case AL_FORMAT_51CHN32:889 *chans = DevFmtX51;890 *type = DevFmtFloat;891 return AL_TRUE;892 case AL_FORMAT_61CHN8:893 *chans = DevFmtX61;894 *type = DevFmtUByte;895 return AL_TRUE;896 case AL_FORMAT_61CHN16:897 *chans = DevFmtX61;898 *type = DevFmtShort;899 return AL_TRUE;900 case AL_FORMAT_61CHN32:901 *chans = DevFmtX61;902 *type = DevFmtFloat;903 return AL_TRUE;904 case AL_FORMAT_71CHN8:905 *chans = DevFmtX71;906 *type = DevFmtUByte;907 return AL_TRUE;908 case AL_FORMAT_71CHN16:909 *chans = DevFmtX71;910 *type = DevFmtShort;911 return AL_TRUE;912 case AL_FORMAT_71CHN32:913 *chans = DevFmtX71;914 *type = DevFmtFloat;915 return AL_TRUE;916 }917 return AL_FALSE;918 }920 static ALCboolean IsValidALCType(ALCenum type)921 {922 switch(type)923 {924 case ALC_BYTE:925 case ALC_UNSIGNED_BYTE:926 case ALC_SHORT:927 case ALC_UNSIGNED_SHORT:928 case ALC_INT:929 case ALC_UNSIGNED_INT:930 case ALC_FLOAT:931 return ALC_TRUE;932 }933 return ALC_FALSE;934 }936 static ALCboolean IsValidALCChannels(ALCenum channels)937 {938 switch(channels)939 {940 case ALC_MONO:941 case ALC_STEREO:942 case ALC_QUAD:943 case ALC_5POINT1:944 case ALC_6POINT1:945 case ALC_7POINT1:946 return ALC_TRUE;947 }948 return ALC_FALSE;949 }952 static void LockLists(void)953 {954 EnterCriticalSection(&ListLock);955 }957 static void UnlockLists(void)958 {959 LeaveCriticalSection(&ListLock);960 }962 /*963 IsDevice965 Check pDevice is a valid Device pointer966 */967 static ALCboolean IsDevice(ALCdevice *pDevice)968 {969 ALCdevice *pTempDevice;971 pTempDevice = g_pDeviceList;972 while(pTempDevice && pTempDevice != pDevice)973 pTempDevice = pTempDevice->next;975 return (pTempDevice ? ALC_TRUE : ALC_FALSE);976 }978 /*979 IsContext981 Check pContext is a valid Context pointer982 */983 static ALCboolean IsContext(ALCcontext *pContext)984 {985 ALCcontext *pTempContext;987 pTempContext = g_pContextList;988 while (pTempContext && pTempContext != pContext)989 pTempContext = pTempContext->next;991 return (pTempContext ? ALC_TRUE : ALC_FALSE);992 }995 /*996 alcSetError998 Store latest ALC Error999 */1000 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)1001 {1002 LockLists();1003 if(IsDevice(device))1004 device->LastError = errorCode;1005 else1006 g_eLastNullDeviceError = errorCode;1007 UnlockLists();1008 }1011 /* UpdateDeviceParams:1012 *1013 * Updates device parameters according to the attribute list.1014 */1015 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)1016 {1017 ALuint i;1019 // Check for attributes1020 if(attrList && attrList[0])1021 {1022 ALCuint freq, numMono, numStereo, numSends;1023 enum DevFmtChannels schans;1024 enum DevFmtType stype;1025 ALuint attrIdx;1027 // If a context is already running on the device, stop playback so the1028 // device attributes can be updated1029 if((device->Flags&DEVICE_RUNNING))1030 ALCdevice_StopPlayback(device);1031 device->Flags &= ~DEVICE_RUNNING;1033 freq = device->Frequency;1034 schans = device->FmtChans;1035 stype = device->FmtType;1036 numMono = device->NumMonoSources;1037 numStereo = device->NumStereoSources;1038 numSends = device->NumAuxSends;1040 freq = GetConfigValueInt(NULL, "frequency", freq);1041 if(freq < 8000) freq = 8000;1043 attrIdx = 0;1044 while(attrList[attrIdx])1045 {1046 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT &&1047 device->IsLoopbackDevice)1048 {1049 ALCint val = attrList[attrIdx + 1];1050 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))1051 {1052 alcSetError(device, ALC_INVALID_VALUE);1053 return ALC_FALSE;1054 }1055 schans = val;1056 }1058 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT &&1059 device->IsLoopbackDevice)1060 {1061 ALCint val = attrList[attrIdx + 1];1062 if(!IsValidALCType(val) || !BytesFromDevFmt(val))1063 {1064 alcSetError(device, ALC_INVALID_VALUE);1065 return ALC_FALSE;1066 }1067 stype = val;1068 }1070 if(attrList[attrIdx] == ALC_FREQUENCY)1071 {1072 if(device->IsLoopbackDevice)1073 {1074 freq = attrList[attrIdx + 1];1075 if(freq < 8000)1076 {1077 alcSetError(device, ALC_INVALID_VALUE);1078 return ALC_FALSE;1079 }1080 }1081 else if(!ConfigValueExists(NULL, "frequency"))1082 {1083 freq = attrList[attrIdx + 1];1084 if(freq < 8000) freq = 8000;1085 device->Flags |= DEVICE_FREQUENCY_REQUEST;1086 }1087 }1089 if(attrList[attrIdx] == ALC_STEREO_SOURCES)1090 {1091 numStereo = attrList[attrIdx + 1];1092 if(numStereo > device->MaxNoOfSources)1093 numStereo = device->MaxNoOfSources;1095 numMono = device->MaxNoOfSources - numStereo;1096 }1098 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&1099 !ConfigValueExists(NULL, "sends"))1100 {1101 numSends = attrList[attrIdx + 1];1102 if(numSends > MAX_SENDS)1103 numSends = MAX_SENDS;1104 }1106 attrIdx += 2;1107 }1109 device->UpdateSize = (ALuint64)device->UpdateSize * freq /1110 device->Frequency;1112 device->Frequency = freq;1113 device->FmtChans = schans;1114 device->FmtType = stype;1115 device->NumMonoSources = numMono;1116 device->NumStereoSources = numStereo;1117 device->NumAuxSends = numSends;1118 }1120 if((device->Flags&DEVICE_RUNNING))1121 return ALC_TRUE;1123 LockDevice(device);1124 TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1125 DevFmtChannelsString(device->FmtChans),1126 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1127 DevFmtTypeString(device->FmtType), device->Frequency,1128 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1129 device->UpdateSize, device->NumUpdates);1130 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)1131 {1132 UnlockDevice(device);1133 return ALC_FALSE;1134 }1135 device->Flags |= DEVICE_RUNNING;1136 TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1137 DevFmtChannelsString(device->FmtChans),1138 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1139 DevFmtTypeString(device->FmtType), device->Frequency,1140 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1141 device->UpdateSize, device->NumUpdates);1143 aluInitPanning(device);1145 for(i = 0;i < MAXCHANNELS;i++)1146 {1147 device->ClickRemoval[i] = 0.0f;1148 device->PendingClicks[i] = 0.0f;1149 }1151 if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE))1152 device->Flags |= DEVICE_USE_HRTF;1153 if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device))1154 device->Flags &= ~DEVICE_USE_HRTF;1155 TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled");1157 if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)1158 {1159 if(!device->Bs2b)1160 {1161 device->Bs2b = calloc(1, sizeof(*device->Bs2b));1162 bs2b_clear(device->Bs2b);1163 }1164 bs2b_set_srate(device->Bs2b, device->Frequency);1165 bs2b_set_level(device->Bs2b, device->Bs2bLevel);1166 TRACE("BS2B level %d\n", device->Bs2bLevel);1167 }1168 else1169 {1170 free(device->Bs2b);1171 device->Bs2b = NULL;1172 TRACE("BS2B disabled\n");1173 }1175 device->Flags &= ~DEVICE_DUPLICATE_STEREO;1176 switch(device->FmtChans)1177 {1178 case DevFmtMono:1179 case DevFmtStereo:1180 break;1181 case DevFmtQuad:1182 case DevFmtX51:1183 case DevFmtX51Side:1184 case DevFmtX61:1185 case DevFmtX71:1186 if(GetConfigValueBool(NULL, "stereodup", AL_TRUE))1187 device->Flags |= DEVICE_DUPLICATE_STEREO;1188 break;1189 }1190 TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");1192 for(i = 0;i < device->NumContexts;i++)1193 {1194 ALCcontext *context = device->Contexts[i];1195 ALsizei pos;1197 context->UpdateSources = AL_FALSE;1198 for(pos = 0;pos < context->EffectSlotMap.size;pos++)1199 {1200 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;1202 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)1203 {1204 UnlockDevice(device);1205 ALCdevice_StopPlayback(device);1206 device->Flags &= ~DEVICE_RUNNING;1207 return ALC_FALSE;1208 }1209 slot->NeedsUpdate = AL_FALSE;1210 ALEffect_Update(slot->EffectState, context, slot);1211 }1213 for(pos = 0;pos < context->SourceMap.size;pos++)1214 {1215 ALsource *source = context->SourceMap.array[pos].value;1216 ALuint s = device->NumAuxSends;1217 while(s < MAX_SENDS)1218 {1219 if(source->Send[s].Slot)1220 source->Send[s].Slot->refcount--;1221 source->Send[s].Slot = NULL;1222 source->Send[s].WetFilter.type = 0;1223 source->Send[s].WetFilter.filter = 0;1224 s++;1225 }1226 source->NeedsUpdate = AL_FALSE;1227 ALsource_Update(source, context);1228 }1229 }1230 UnlockDevice(device);1232 return ALC_TRUE;1233 }1236 ALCvoid LockDevice(ALCdevice *device)1237 {1238 EnterCriticalSection(&device->Mutex);1239 }1241 ALCvoid UnlockDevice(ALCdevice *device)1242 {1243 LeaveCriticalSection(&device->Mutex);1244 }1246 /*1247 LockContext1249 Thread-safe entry1250 */1251 ALCvoid LockContext(ALCcontext *context)1252 {1253 EnterCriticalSection(&context->Device->Mutex);1254 }1257 /*1258 UnlockContext1260 Thread-safe exit1261 */1262 ALCvoid UnlockContext(ALCcontext *context)1263 {1264 LeaveCriticalSection(&context->Device->Mutex);1265 }1268 /*1269 GetLockedContext1271 Returns the currently active Context, in a locked state1272 */1273 ALCcontext *GetLockedContext(void)1274 {1275 ALCcontext *pContext = NULL;1277 LockLists();1279 pContext = tls_get(LocalContext);1280 if(pContext && !IsContext(pContext))1281 {1282 tls_set(LocalContext, NULL);1283 pContext = NULL;1284 }1285 if(!pContext)1286 pContext = GlobalContext;1287 if(pContext)1288 LockContext(pContext);1290 UnlockLists();1292 return pContext;1293 }1296 /*1297 InitContext1299 Initialize Context variables1300 */1301 static ALvoid InitContext(ALCcontext *pContext)1302 {1303 //Initialise listener1304 pContext->Listener.Gain = 1.0f;1305 pContext->Listener.MetersPerUnit = 1.0f;1306 pContext->Listener.Position[0] = 0.0f;1307 pContext->Listener.Position[1] = 0.0f;1308 pContext->Listener.Position[2] = 0.0f;1309 pContext->Listener.Velocity[0] = 0.0f;1310 pContext->Listener.Velocity[1] = 0.0f;1311 pContext->Listener.Velocity[2] = 0.0f;1312 pContext->Listener.Forward[0] = 0.0f;1313 pContext->Listener.Forward[1] = 0.0f;1314 pContext->Listener.Forward[2] = -1.0f;1315 pContext->Listener.Up[0] = 0.0f;1316 pContext->Listener.Up[1] = 1.0f;1317 pContext->Listener.Up[2] = 0.0f;1319 //Validate pContext1320 pContext->LastError = AL_NO_ERROR;1321 pContext->UpdateSources = AL_FALSE;1322 pContext->ActiveSourceCount = 0;1323 InitUIntMap(&pContext->SourceMap);1324 InitUIntMap(&pContext->EffectSlotMap);1326 //Set globals1327 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;1328 pContext->SourceDistanceModel = AL_FALSE;1329 pContext->DopplerFactor = 1.0f;1330 pContext->DopplerVelocity = 1.0f;1331 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;1332 pContext->DeferUpdates = AL_FALSE;1334 pContext->ExtensionList = alExtList;1335 }1338 /*1339 FreeContext1341 Clean up Context, destroy any remaining Sources1342 */1343 static ALCvoid FreeContext(ALCcontext *context)1344 {1345 //Invalidate context1346 memset(context, 0, sizeof(ALCcontext));1347 free(context);1348 }1350 ///////////////////////////////////////////////////////1353 ///////////////////////////////////////////////////////1354 // ALC Functions calls1357 // This should probably move to another c file but for now ...1358 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)1359 {1360 ALCdevice *device = NULL;1362 DO_INITCONFIG();1364 if(!CaptureBackend.name)1365 {1366 alcSetError(NULL, ALC_INVALID_VALUE);1367 return NULL;1368 }1370 if(SampleSize <= 0)1371 {1372 alcSetError(NULL, ALC_INVALID_VALUE);1373 return NULL;1374 }1376 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))1377 deviceName = NULL;1379 device = calloc(1, sizeof(ALCdevice));1380 if(!device)1381 {1382 alcSetError(NULL, ALC_OUT_OF_MEMORY);1383 return NULL;1384 }1386 //Validate device1387 device->Funcs = &CaptureBackend.Funcs;1388 device->Connected = ALC_TRUE;1389 device->IsCaptureDevice = AL_TRUE;1390 device->IsLoopbackDevice = AL_FALSE;1391 InitializeCriticalSection(&device->Mutex);1393 device->szDeviceName = NULL;1395 device->Flags |= DEVICE_FREQUENCY_REQUEST;1396 device->Frequency = frequency;1398 device->Flags |= DEVICE_CHANNELS_REQUEST;1399 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)1400 {1401 free(device);1402 alcSetError(NULL, ALC_INVALID_ENUM);1403 return NULL;1404 }1406 device->UpdateSize = SampleSize;1407 device->NumUpdates = 1;1409 LockLists();1410 if(ALCdevice_OpenCapture(device, deviceName))1411 {1412 device->next = g_pDeviceList;1413 g_pDeviceList = device;1414 g_ulDeviceCount++;1415 }1416 else1417 {1418 DeleteCriticalSection(&device->Mutex);1419 free(device);1420 device = NULL;1421 alcSetError(NULL, ALC_INVALID_VALUE);1422 }1423 UnlockLists();1425 return device;1426 }1428 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)1429 {1430 ALCdevice **list;1432 LockLists();1433 list = &g_pDeviceList;1434 while(*list && *list != pDevice)1435 list = &(*list)->next;1437 if(!*list || !(*list)->IsCaptureDevice)1438 {1439 alcSetError(*list, ALC_INVALID_DEVICE);1440 UnlockLists();1441 return ALC_FALSE;1442 }1444 *list = (*list)->next;1445 g_ulDeviceCount--;1447 UnlockLists();1449 LockDevice(pDevice);1450 ALCdevice_CloseCapture(pDevice);1451 UnlockDevice(pDevice);1453 free(pDevice->szDeviceName);1454 pDevice->szDeviceName = NULL;1456 DeleteCriticalSection(&pDevice->Mutex);1458 free(pDevice);1460 return ALC_TRUE;1461 }1463 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)1464 {1465 LockLists();1466 if(!IsDevice(device) || !device->IsCaptureDevice)1467 {1468 alcSetError(device, ALC_INVALID_DEVICE);1469 UnlockLists();1470 return;1471 }1472 LockDevice(device);1473 UnlockLists();1474 if(device->Connected)1475 ALCdevice_StartCapture(device);1476 UnlockDevice(device);1477 }1479 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)1480 {1481 LockLists();1482 if(!IsDevice(device) || !device->IsCaptureDevice)1483 {1484 alcSetError(device, ALC_INVALID_DEVICE);1485 UnlockLists();1486 return;1487 }1488 LockDevice(device);1489 UnlockLists();1490 if(device->Connected)1491 ALCdevice_StopCapture(device);1492 UnlockDevice(device);1493 }1495 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)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_CaptureSamples(device, buffer, samples);1508 UnlockDevice(device);1509 }1511 /*1512 alcGetError1514 Return last ALC generated error code1515 */1516 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)1517 {1518 ALCenum errorCode;1520 LockLists();1521 if(IsDevice(device))1522 {1523 errorCode = device->LastError;1524 device->LastError = ALC_NO_ERROR;1525 }1526 else1527 {1528 errorCode = g_eLastNullDeviceError;1529 g_eLastNullDeviceError = ALC_NO_ERROR;1530 }1531 UnlockLists();1532 return errorCode;1533 }1536 /*1537 alcSuspendContext1539 Not functional1540 */1541 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)1542 {1543 (void)Context;1544 }1547 /*1548 alcProcessContext1550 Not functional1551 */1552 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)1553 {1554 (void)Context;1555 }1558 /*1559 alcGetString1561 Returns information about the Device, and error strings1562 */1563 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)1564 {1565 const ALCchar *value = NULL;1567 switch(param)1568 {1569 case ALC_NO_ERROR:1570 value = alcNoError;1571 break;1573 case ALC_INVALID_ENUM:1574 value = alcErrInvalidEnum;1575 break;1577 case ALC_INVALID_VALUE:1578 value = alcErrInvalidValue;1579 break;1581 case ALC_INVALID_DEVICE:1582 value = alcErrInvalidDevice;1583 break;1585 case ALC_INVALID_CONTEXT:1586 value = alcErrInvalidContext;1587 break;1589 case ALC_OUT_OF_MEMORY:1590 value = alcErrOutOfMemory;1591 break;1593 case ALC_DEVICE_SPECIFIER:1594 LockLists();1595 if(IsDevice(pDevice))1596 value = pDevice->szDeviceName;1597 else1598 {1599 ProbeDeviceList();1600 value = alcDeviceList;1601 }1602 UnlockLists();1603 break;1605 case ALC_ALL_DEVICES_SPECIFIER:1606 ProbeAllDeviceList();1607 value = alcAllDeviceList;1608 break;1610 case ALC_CAPTURE_DEVICE_SPECIFIER:1611 LockLists();1612 if(IsDevice(pDevice))1613 value = pDevice->szDeviceName;1614 else1615 {1616 ProbeCaptureDeviceList();1617 value = alcCaptureDeviceList;1618 }1619 UnlockLists();1620 break;1622 /* Default devices are always first in the list */1623 case ALC_DEFAULT_DEVICE_SPECIFIER:1624 if(!alcDeviceList)1625 ProbeDeviceList();1627 free(alcDefaultDeviceSpecifier);1628 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");1629 if(!alcDefaultDeviceSpecifier)1630 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1631 value = alcDefaultDeviceSpecifier;1632 break;1634 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:1635 if(!alcAllDeviceList)1636 ProbeAllDeviceList();1638 free(alcDefaultAllDeviceSpecifier);1639 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?1640 alcAllDeviceList : "");1641 if(!alcDefaultAllDeviceSpecifier)1642 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1643 value = alcDefaultAllDeviceSpecifier;1644 break;1646 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:1647 if(!alcCaptureDeviceList)1648 ProbeCaptureDeviceList();1650 free(alcCaptureDefaultDeviceSpecifier);1651 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?1652 alcCaptureDeviceList : "");1653 if(!alcCaptureDefaultDeviceSpecifier)1654 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1655 value = alcCaptureDefaultDeviceSpecifier;1656 break;1658 case ALC_EXTENSIONS:1659 LockLists();1660 if(IsDevice(pDevice))1661 value = alcExtensionList;1662 else1663 value = alcNoDeviceExtList;1664 UnlockLists();1665 break;1667 default:1668 alcSetError(pDevice, ALC_INVALID_ENUM);1669 break;1670 }1672 return value;1673 }1676 /*1677 alcGetIntegerv1679 Returns information about the Device and the version of Open AL1680 */1681 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)1682 {1683 if(size == 0 || data == NULL)1684 {1685 alcSetError(device, ALC_INVALID_VALUE);1686 return;1687 }1689 LockLists();1690 if(!IsDevice(device))1691 {1692 switch(param)1693 {1694 case ALC_MAJOR_VERSION:1695 *data = alcMajorVersion;1696 break;1697 case ALC_MINOR_VERSION:1698 *data = alcMinorVersion;1699 break;1701 case ALC_ATTRIBUTES_SIZE:1702 case ALC_ALL_ATTRIBUTES:1703 case ALC_FREQUENCY:1704 case ALC_REFRESH:1705 case ALC_SYNC:1706 case ALC_MONO_SOURCES:1707 case ALC_STEREO_SOURCES:1708 case ALC_CAPTURE_SAMPLES:1709 case ALC_FORMAT_CHANNELS_SOFT:1710 case ALC_FORMAT_TYPE_SOFT:1711 alcSetError(NULL, ALC_INVALID_DEVICE);1712 break;1714 default:1715 alcSetError(NULL, ALC_INVALID_ENUM);1716 break;1717 }1718 }1719 else if(device->IsCaptureDevice)1720 {1721 switch(param)1722 {1723 case ALC_CAPTURE_SAMPLES:1724 LockDevice(device);1725 *data = ALCdevice_AvailableSamples(device);1726 UnlockDevice(device);1727 break;1729 case ALC_CONNECTED:1730 *data = device->Connected;1731 break;1733 default:1734 alcSetError(device, ALC_INVALID_ENUM);1735 break;1736 }1737 }1738 else /* render device */1739 {1740 switch(param)1741 {1742 case ALC_MAJOR_VERSION:1743 *data = alcMajorVersion;1744 break;1746 case ALC_MINOR_VERSION:1747 *data = alcMinorVersion;1748 break;1750 case ALC_EFX_MAJOR_VERSION:1751 *data = alcEFXMajorVersion;1752 break;1754 case ALC_EFX_MINOR_VERSION:1755 *data = alcEFXMinorVersion;1756 break;1758 case ALC_ATTRIBUTES_SIZE:1759 *data = 13;1760 break;1762 case ALC_ALL_ATTRIBUTES:1763 if(size < 13)1764 alcSetError(device, ALC_INVALID_VALUE);1765 else1766 {1767 int i = 0;1769 data[i++] = ALC_FREQUENCY;1770 data[i++] = device->Frequency;1772 if(!device->IsLoopbackDevice)1773 {1774 data[i++] = ALC_REFRESH;1775 data[i++] = device->Frequency / device->UpdateSize;1777 data[i++] = ALC_SYNC;1778 data[i++] = ALC_FALSE;1779 }1780 else1781 {1782 data[i++] = ALC_FORMAT_CHANNELS_SOFT;1783 data[i++] = device->FmtChans;1785 data[i++] = ALC_FORMAT_TYPE_SOFT;1786 data[i++] = device->FmtType;1787 }1789 data[i++] = ALC_MONO_SOURCES;1790 data[i++] = device->NumMonoSources;1792 data[i++] = ALC_STEREO_SOURCES;1793 data[i++] = device->NumStereoSources;1795 data[i++] = ALC_MAX_AUXILIARY_SENDS;1796 data[i++] = device->NumAuxSends;1798 data[i++] = 0;1799 }1800 break;1802 case ALC_FREQUENCY:1803 *data = device->Frequency;1804 break;1806 case ALC_REFRESH:1807 if(device->IsLoopbackDevice)1808 alcSetError(device, ALC_INVALID_DEVICE);1809 else1810 *data = device->Frequency / device->UpdateSize;1811 break;1813 case ALC_SYNC:1814 if(device->IsLoopbackDevice)1815 alcSetError(device, ALC_INVALID_DEVICE);1816 else1817 *data = ALC_FALSE;1818 break;1820 case ALC_FORMAT_CHANNELS_SOFT:1821 if(!device->IsLoopbackDevice)1822 alcSetError(device, ALC_INVALID_DEVICE);1823 else1824 *data = device->FmtChans;1825 break;1827 case ALC_FORMAT_TYPE_SOFT:1828 if(!device->IsLoopbackDevice)1829 alcSetError(device, ALC_INVALID_DEVICE);1830 else1831 *data = device->FmtType;1832 break;1834 case ALC_MONO_SOURCES:1835 *data = device->NumMonoSources;1836 break;1838 case ALC_STEREO_SOURCES:1839 *data = device->NumStereoSources;1840 break;1842 case ALC_MAX_AUXILIARY_SENDS:1843 *data = device->NumAuxSends;1844 break;1846 case ALC_CONNECTED:1847 *data = device->Connected;1848 break;1850 default:1851 alcSetError(device, ALC_INVALID_ENUM);1852 break;1853 }1854 }1855 UnlockLists();1856 }1859 /*1860 alcIsExtensionPresent1862 Determines if there is support for a particular extension1863 */1864 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)1865 {1866 ALCboolean bResult = ALC_FALSE;1867 const char *ptr;1868 size_t len;1870 if(!extName)1871 {1872 alcSetError(device, ALC_INVALID_VALUE);1873 return ALC_FALSE;1874 }1876 len = strlen(extName);1877 LockLists();1878 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);1879 UnlockLists();1880 while(ptr && *ptr)1881 {1882 if(strncasecmp(ptr, extName, len) == 0 &&1883 (ptr[len] == '\0' || isspace(ptr[len])))1884 {1885 bResult = ALC_TRUE;1886 break;1887 }1888 if((ptr=strchr(ptr, ' ')) != NULL)1889 {1890 do {1891 ++ptr;1892 } while(isspace(*ptr));1893 }1894 }1896 return bResult;1897 }1900 /*1901 alcGetProcAddress1903 Retrieves the function address for a particular extension function1904 */1905 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)1906 {1907 ALsizei i = 0;1909 if(!funcName)1910 {1911 alcSetError(device, ALC_INVALID_VALUE);1912 return NULL;1913 }1915 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)1916 i++;1917 return alcFunctions[i].address;1918 }1921 /*1922 alcGetEnumValue1924 Get the value for a particular ALC Enumerated Value1925 */1926 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)1927 {1928 ALsizei i = 0;1930 if(!enumName)1931 {1932 alcSetError(device, ALC_INVALID_VALUE);1933 return (ALCenum)0;1934 }1936 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)1937 i++;1938 return enumeration[i].value;1939 }1942 /*1943 alcCreateContext1945 Create and attach a Context to a particular Device.1946 */1947 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)1948 {1949 ALCcontext *ALContext;1950 void *temp;1952 LockLists();1953 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)1954 {1955 alcSetError(device, ALC_INVALID_DEVICE);1956 UnlockLists();1957 return NULL;1958 }1960 // Reset Context Last Error code1961 device->LastError = ALC_NO_ERROR;1963 if(UpdateDeviceParams(device, attrList) == ALC_FALSE)1964 {1965 alcSetError(device, ALC_INVALID_DEVICE);1966 aluHandleDisconnect(device);1967 UnlockLists();1968 return NULL;1969 }1971 LockDevice(device);1972 ALContext = NULL;1973 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));1974 if(temp)1975 {1976 device->Contexts = temp;1978 ALContext = calloc(1, sizeof(ALCcontext));1979 if(ALContext)1980 {1981 ALContext->MaxActiveSources = 256;1982 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *1983 ALContext->MaxActiveSources);1984 }1985 }1986 if(!ALContext || !ALContext->ActiveSources)1987 {1988 free(ALContext);1989 alcSetError(device, ALC_OUT_OF_MEMORY);1990 UnlockDevice(device);1991 if(device->NumContexts == 0)1992 {1993 ALCdevice_StopPlayback(device);1994 device->Flags &= ~DEVICE_RUNNING;1995 }1996 UnlockLists();1997 return NULL;1998 }2000 device->Contexts[device->NumContexts++] = ALContext;2001 ALContext->Device = device;2003 InitContext(ALContext);2004 UnlockDevice(device);2006 ALContext->next = g_pContextList;2007 g_pContextList = ALContext;2008 g_ulContextCount++;2010 UnlockLists();2012 return ALContext;2013 }2016 /*2017 alcDestroyContext2019 Remove a Context2020 */2021 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)2022 {2023 ALCdevice *Device;2024 ALCcontext **list;2025 ALuint i;2027 LockLists();2028 list = &g_pContextList;2029 while(*list && *list != context)2030 list = &(*list)->next;2032 if(!*list)2033 {2034 alcSetError(NULL, ALC_INVALID_CONTEXT);2035 UnlockLists();2036 return;2037 }2039 *list = (*list)->next;2040 g_ulContextCount--;2042 if(context == tls_get(LocalContext))2043 tls_set(LocalContext, NULL);2044 if(context == GlobalContext)2045 GlobalContext = NULL;2047 Device = context->Device;2048 LockDevice(Device);2049 for(i = 0;i < Device->NumContexts;i++)2050 {2051 if(Device->Contexts[i] == context)2052 {2053 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];2054 Device->NumContexts--;2055 break;2056 }2057 }2058 UnlockDevice(Device);2060 if(Device->NumContexts == 0)2061 {2062 ALCdevice_StopPlayback(Device);2063 Device->Flags &= ~DEVICE_RUNNING;2064 }2065 UnlockLists();2067 if(context->SourceMap.size > 0)2068 {2069 ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);2070 ReleaseALSources(context);2071 }2072 ResetUIntMap(&context->SourceMap);2074 if(context->EffectSlotMap.size > 0)2075 {2076 ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);2077 ReleaseALAuxiliaryEffectSlots(context);2078 }2079 ResetUIntMap(&context->EffectSlotMap);2081 free(context->ActiveSources);2082 context->ActiveSources = NULL;2083 context->MaxActiveSources = 0;2084 context->ActiveSourceCount = 0;2086 FreeContext(context);2087 }2090 /*2091 alcGetCurrentContext2093 Returns the currently active Context2094 */2095 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)2096 {2097 ALCcontext *Context;2099 LockLists();2100 Context = tls_get(LocalContext);2101 if(Context && !IsContext(Context))2102 {2103 tls_set(LocalContext, NULL);2104 Context = NULL;2105 }2106 if(!Context)2107 Context = GlobalContext;2108 UnlockLists();2110 return Context;2111 }2113 /*2114 alcGetThreadContext2116 Returns the currently active thread-local Context2117 */2118 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)2119 {2120 ALCcontext *pContext = NULL;2122 LockLists();2124 pContext = tls_get(LocalContext);2125 if(pContext && !IsContext(pContext))2126 {2127 tls_set(LocalContext, NULL);2128 pContext = NULL;2129 }2131 UnlockLists();2133 return pContext;2134 }2137 /*2138 alcGetContextsDevice2140 Returns the Device that a particular Context is attached to2141 */2142 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)2143 {2144 ALCdevice *pDevice = NULL;2146 LockLists();2147 if(IsContext(pContext))2148 pDevice = pContext->Device;2149 else2150 alcSetError(NULL, ALC_INVALID_CONTEXT);2151 UnlockLists();2153 return pDevice;2154 }2157 /*2158 alcMakeContextCurrent2160 Makes the given Context the active Context2161 */2162 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)2163 {2164 ALboolean bReturn = AL_TRUE;2166 LockLists();2168 // context must be a valid Context or NULL2169 if(context == NULL || IsContext(context))2170 {2171 GlobalContext = context;2172 tls_set(LocalContext, NULL);2173 }2174 else2175 {2176 alcSetError(NULL, ALC_INVALID_CONTEXT);2177 bReturn = AL_FALSE;2178 }2180 UnlockLists();2182 return bReturn;2183 }2185 /*2186 alcSetThreadContext2188 Makes the given Context the active Context for the current thread2189 */2190 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)2191 {2192 ALboolean bReturn = AL_TRUE;2194 LockLists();2196 // context must be a valid Context or NULL2197 if(context == NULL || IsContext(context))2198 tls_set(LocalContext, context);2199 else2200 {2201 alcSetError(NULL, ALC_INVALID_CONTEXT);2202 bReturn = AL_FALSE;2203 }2205 UnlockLists();2207 return bReturn;2208 }2211 static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)2212 {2213 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)2214 {2215 *chans = DevFmtMono;2216 *type = DevFmtFloat;2217 return;2218 }2219 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0)2220 {2221 *chans = DevFmtStereo;2222 *type = DevFmtFloat;2223 return;2224 }2225 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0)2226 {2227 *chans = DevFmtQuad;2228 *type = DevFmtFloat;2229 return;2230 }2231 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0)2232 {2233 *chans = DevFmtX51;2234 *type = DevFmtFloat;2235 return;2236 }2237 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0)2238 {2239 *chans = DevFmtX61;2240 *type = DevFmtFloat;2241 return;2242 }2243 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0)2244 {2245 *chans = DevFmtX71;2246 *type = DevFmtFloat;2247 return;2248 }2250 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0)2251 {2252 *chans = DevFmtMono;2253 *type = DevFmtShort;2254 return;2255 }2256 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0)2257 {2258 *chans = DevFmtStereo;2259 *type = DevFmtShort;2260 return;2261 }2262 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0)2263 {2264 *chans = DevFmtQuad;2265 *type = DevFmtShort;2266 return;2267 }2268 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0)2269 {2270 *chans = DevFmtX51;2271 *type = DevFmtShort;2272 return;2273 }2274 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0)2275 {2276 *chans = DevFmtX61;2277 *type = DevFmtShort;2278 return;2279 }2280 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0)2281 {2282 *chans = DevFmtX71;2283 *type = DevFmtShort;2284 return;2285 }2287 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0)2288 {2289 *chans = DevFmtMono;2290 *type = DevFmtByte;2291 return;2292 }2293 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0)2294 {2295 *chans = DevFmtStereo;2296 *type = DevFmtByte;2297 return;2298 }2299 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0)2300 {2301 *chans = DevFmtQuad;2302 *type = DevFmtByte;2303 return;2304 }2305 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0)2306 {2307 *chans = DevFmtX51;2308 *type = DevFmtByte;2309 return;2310 }2311 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0)2312 {2313 *chans = DevFmtX61;2314 *type = DevFmtByte;2315 return;2316 }2317 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0)2318 {2319 *chans = DevFmtX71;2320 *type = DevFmtByte;2321 return;2322 }2324 ERR("Unknown format: \"%s\"\n", str);2325 *chans = DevFmtStereo;2326 *type = DevFmtShort;2327 }2329 /*2330 alcOpenDevice2332 Open the Device specified.2333 */2334 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)2335 {2336 const ALCchar *fmt;2337 ALCdevice *device;2339 DO_INITCONFIG();2341 if(!PlaybackBackend.name)2342 {2343 alcSetError(NULL, ALC_INVALID_VALUE);2344 return NULL;2345 }2347 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))2348 deviceName = NULL;2350 device = calloc(1, sizeof(ALCdevice));2351 if(!device)2352 {2353 alcSetError(NULL, ALC_OUT_OF_MEMORY);2354 return NULL;2355 }2357 //Validate device2358 device->Funcs = &PlaybackBackend.Funcs;2359 device->Connected = ALC_TRUE;2360 device->IsCaptureDevice = AL_FALSE;2361 device->IsLoopbackDevice = AL_FALSE;2362 InitializeCriticalSection(&device->Mutex);2363 device->LastError = ALC_NO_ERROR;2365 device->Flags = 0;2366 device->Bs2b = NULL;2367 device->szDeviceName = NULL;2369 device->Contexts = NULL;2370 device->NumContexts = 0;2372 InitUIntMap(&device->BufferMap);2373 InitUIntMap(&device->EffectMap);2374 InitUIntMap(&device->FilterMap);2376 //Set output format2377 if(ConfigValueExists(NULL, "frequency"))2378 device->Flags |= DEVICE_FREQUENCY_REQUEST;2379 device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE);2380 if(device->Frequency < 8000)2381 device->Frequency = 8000;2383 if(ConfigValueExists(NULL, "format"))2384 device->Flags |= DEVICE_CHANNELS_REQUEST;2385 //fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");2386 //RLM: audio-send only supports 16 bit mono output for now,2387 //pending bug fixes.2388 fmt = "AL_FORMAT_MONO16";2389 GetFormatFromString(fmt, &device->FmtChans, &device->FmtType);2391 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);2392 if(device->NumUpdates < 2)2393 device->NumUpdates = 4;2395 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);2396 if(device->UpdateSize <= 0)2397 device->UpdateSize = 1024;2399 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2400 if(device->MaxNoOfSources <= 0)2401 device->MaxNoOfSources = 256;2403 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2404 if(device->AuxiliaryEffectSlotMax <= 0)2405 device->AuxiliaryEffectSlotMax = 4;2407 device->NumStereoSources = 1;2408 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2410 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2411 if(device->NumAuxSends > MAX_SENDS)2412 device->NumAuxSends = MAX_SENDS;2414 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2416 // Find a playback device to open2417 LockLists();2418 if(ALCdevice_OpenPlayback(device, deviceName))2419 {2420 device->next = g_pDeviceList;2421 g_pDeviceList = device;2422 g_ulDeviceCount++;2423 }2424 else2425 {2426 // No suitable output device found2427 DeleteCriticalSection(&device->Mutex);2428 free(device);2429 device = NULL;2430 alcSetError(NULL, ALC_INVALID_VALUE);2431 }2432 UnlockLists();2434 return device;2435 }2438 /*2439 alcCloseDevice2441 Close the specified Device2442 */2443 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)2444 {2445 ALCdevice **list;2447 LockLists();2448 list = &g_pDeviceList;2449 while(*list && *list != pDevice)2450 list = &(*list)->next;2452 if(!*list || (*list)->IsCaptureDevice)2453 {2454 alcSetError(*list, ALC_INVALID_DEVICE);2455 UnlockLists();2456 return ALC_FALSE;2457 }2459 *list = (*list)->next;2460 g_ulDeviceCount--;2462 UnlockLists();2464 if(pDevice->NumContexts > 0)2465 {2466 WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);2467 while(pDevice->NumContexts > 0)2468 alcDestroyContext(pDevice->Contexts[0]);2469 }2470 ALCdevice_ClosePlayback(pDevice);2472 if(pDevice->BufferMap.size > 0)2473 {2474 WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);2475 ReleaseALBuffers(pDevice);2476 }2477 ResetUIntMap(&pDevice->BufferMap);2479 if(pDevice->EffectMap.size > 0)2480 {2481 WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);2482 ReleaseALEffects(pDevice);2483 }2484 ResetUIntMap(&pDevice->EffectMap);2486 if(pDevice->FilterMap.size > 0)2487 {2488 WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);2489 ReleaseALFilters(pDevice);2490 }2491 ResetUIntMap(&pDevice->FilterMap);2493 free(pDevice->Bs2b);2494 pDevice->Bs2b = NULL;2496 free(pDevice->szDeviceName);2497 pDevice->szDeviceName = NULL;2499 free(pDevice->Contexts);2500 pDevice->Contexts = NULL;2502 DeleteCriticalSection(&pDevice->Mutex);2504 //Release device structure2505 memset(pDevice, 0, sizeof(ALCdevice));2506 free(pDevice);2508 return ALC_TRUE;2509 }2512 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void)2513 {2514 ALCdevice *device;2516 DO_INITCONFIG();2518 device = calloc(1, sizeof(ALCdevice));2519 if(!device)2520 {2521 alcSetError(NULL, ALC_OUT_OF_MEMORY);2522 return NULL;2523 }2525 //Validate device2526 device->Funcs = &BackendLoopback.Funcs;2527 device->Connected = ALC_TRUE;2528 device->IsCaptureDevice = AL_FALSE;2529 device->IsLoopbackDevice = AL_TRUE;2530 InitializeCriticalSection(&device->Mutex);2531 device->LastError = ALC_NO_ERROR;2533 device->Flags = 0;2534 device->Bs2b = NULL;2535 device->szDeviceName = NULL;2537 device->Contexts = NULL;2538 device->NumContexts = 0;2540 InitUIntMap(&device->BufferMap);2541 InitUIntMap(&device->EffectMap);2542 InitUIntMap(&device->FilterMap);2544 //Set output format2545 device->Frequency = 44100;2546 device->FmtChans = DevFmtStereo;2547 device->FmtType = DevFmtShort;2549 device->NumUpdates = 0;2550 device->UpdateSize = 0;2552 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2553 if(device->MaxNoOfSources <= 0)2554 device->MaxNoOfSources = 256;2556 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2557 if(device->AuxiliaryEffectSlotMax <= 0)2558 device->AuxiliaryEffectSlotMax = 4;2560 device->NumStereoSources = 1;2561 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2563 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2564 if(device->NumAuxSends > MAX_SENDS)2565 device->NumAuxSends = MAX_SENDS;2567 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2569 // Open the "backend"2570 LockLists();2571 ALCdevice_OpenPlayback(device, "Loopback");2573 device->next = g_pDeviceList;2574 g_pDeviceList = device;2575 g_ulDeviceCount++;2576 UnlockLists();2578 return device;2579 }2581 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)2582 {2583 ALCboolean ret = ALC_FALSE;2585 LockLists();2586 if(!IsDevice(device) || !device->IsLoopbackDevice)2587 alcSetError(device, ALC_INVALID_DEVICE);2588 else if(freq <= 0)2589 alcSetError(device, ALC_INVALID_VALUE);2590 else if(!IsValidALCType(type) || !IsValidALCChannels(channels))2591 alcSetError(device, ALC_INVALID_ENUM);2592 else2593 {2594 if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 &&2595 freq >= 8000)2596 ret = ALC_TRUE;2597 }2598 UnlockLists();2600 return ret;2601 }2603 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)2604 {2605 LockLists();2606 if(!IsDevice(device) || !device->IsLoopbackDevice)2607 alcSetError(device, ALC_INVALID_DEVICE);2608 else if(samples < 0 || (samples > 0 && buffer == NULL))2609 alcSetError(device, ALC_INVALID_VALUE);2610 else2611 aluMixData(device, buffer, samples);2612 UnlockLists();2613 }2616 static void ReleaseALC(ALCboolean doclose)2617 {2618 free(alcDeviceList); alcDeviceList = NULL;2619 alcDeviceListSize = 0;2620 free(alcAllDeviceList); alcAllDeviceList = NULL;2621 alcAllDeviceListSize = 0;2622 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;2623 alcCaptureDeviceListSize = 0;2625 free(alcDefaultDeviceSpecifier);2626 alcDefaultDeviceSpecifier = NULL;2627 free(alcDefaultAllDeviceSpecifier);2628 alcDefaultAllDeviceSpecifier = NULL;2629 free(alcCaptureDefaultDeviceSpecifier);2630 alcCaptureDefaultDeviceSpecifier = NULL;2632 if(doclose)2633 {2634 if(g_ulDeviceCount > 0)2635 WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2637 while(g_pDeviceList)2638 {2639 if(g_pDeviceList->IsCaptureDevice)2640 alcCaptureCloseDevice(g_pDeviceList);2641 else2642 alcCloseDevice(g_pDeviceList);2643 }2644 }2645 else2646 {2647 if(g_ulDeviceCount > 0)2648 WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2649 }2650 }2652 ///////////////////////////////////////////////////////