Mercurial > audio-send
view Alc/ALc.c @ 4:ed256a687dfe
removed very old crufty java program
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:17:37 -0700 |
parents | 96298d83959c |
children | 99df34265b40 |
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 devs = GetConfigValue(NULL, "drivers", "");531 //printf("these are the devices: %s\n", devs);533 if(devs[0])534 {535 int n;536 size_t len;537 const char *next = devs;538 int endlist, delitem;540 i = 0;541 do {542 devs = next;543 //printf("AURELLEM: devs is %s\n",devs);544 next = strchr(devs, ',');546 delitem = (devs[0] == '-');547 if(devs[0] == '-') devs++;549 if(!devs[0] || devs[0] == ',')550 {551 endlist = 0;552 continue;553 }554 endlist = 1;556 len = (next ? ((size_t)(next-devs)) : strlen(devs));557 for(n = i;BackendList[n].Init;n++)558 {559 //printf("AURELLEM: device-name -- %s\n",BackendList[n].name);560 if(len == strlen(BackendList[n].name) &&561 strncmp(BackendList[n].name, devs, len) == 0)562 {563 if(delitem)564 {565 do {566 BackendList[n] = BackendList[n+1];567 ++n;568 }569 // this relies on the last entry being terminated by an570 // entry with all nulls.571 while(BackendList[n].Init);572 }573 else574 {575 struct BackendInfo Bkp = BackendList[n];576 while(n > i)577 {578 BackendList[n] = BackendList[n-1];579 --n;580 }581 BackendList[n] = Bkp;583 i++;584 }585 break;586 }587 }588 } while(next++);590 if(endlist)591 {592 BackendList[i].name = NULL;593 BackendList[i].Init = NULL;594 BackendList[i].Deinit = NULL;595 BackendList[i].Probe = NULL;596 }597 }599 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)600 {601 if(!BackendList[i].Init(&BackendList[i].Funcs))602 {603 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);604 continue;605 }607 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);608 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)609 {610 PlaybackBackend = BackendList[i];611 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);612 }613 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)614 {615 CaptureBackend = BackendList[i];616 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);617 }618 }619 BackendLoopback.Init(&BackendLoopback.Funcs);621 str = GetConfigValue(NULL, "excludefx", "");622 if(str[0])623 {624 size_t len;625 const char *next = str;627 do {628 str = next;629 next = strchr(str, ',');631 if(!str[0] || next == str)632 continue;634 len = (next ? ((size_t)(next-str)) : strlen(str));635 for(n = 0;EffectList[n].name;n++)636 {637 if(len == strlen(EffectList[n].name) &&638 strncmp(EffectList[n].name, str, len) == 0)639 DisabledEffects[EffectList[n].type] = AL_TRUE;640 }641 } while(next++);642 }643 }646 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)647 {648 free(*list);649 *list = NULL;650 *listsize = 0;652 DO_INITCONFIG();653 if(type == CAPTURE_DEVICE_PROBE)654 CaptureBackend.Probe(type);655 else656 PlaybackBackend.Probe(type);657 }659 static void ProbeDeviceList(void)660 { ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }661 static void ProbeAllDeviceList(void)662 { ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }663 static void ProbeCaptureDeviceList(void)664 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }667 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)668 {669 size_t len = strlen(name);670 void *temp;672 if(len == 0)673 return;675 temp = realloc(*List, (*ListSize) + len + 2);676 if(!temp)677 {678 ERR("Realloc failed to add %s!\n", name);679 return;680 }681 *List = temp;683 memcpy((*List)+(*ListSize), name, len+1);684 *ListSize += len+1;685 (*List)[*ListSize] = 0;686 }688 #define DECL_APPEND_LIST_FUNC(type) \689 void Append##type##List(const ALCchar *name) \690 { AppendList(name, &alc##type##List, &alc##type##ListSize); }692 DECL_APPEND_LIST_FUNC(Device)693 DECL_APPEND_LIST_FUNC(AllDevice)694 DECL_APPEND_LIST_FUNC(CaptureDevice)696 #undef DECL_APPEND_LIST_FUNC699 /* Sets the default channel order used by most non-WaveFormatEx-based APIs */700 void SetDefaultChannelOrder(ALCdevice *device)701 {702 switch(device->FmtChans)703 {704 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;705 device->DevChannels[1] = FRONT_RIGHT;706 device->DevChannels[2] = BACK_LEFT;707 device->DevChannels[3] = BACK_RIGHT;708 device->DevChannels[4] = FRONT_CENTER;709 device->DevChannels[5] = LFE;710 return;712 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;713 device->DevChannels[1] = FRONT_RIGHT;714 device->DevChannels[2] = BACK_LEFT;715 device->DevChannels[3] = BACK_RIGHT;716 device->DevChannels[4] = FRONT_CENTER;717 device->DevChannels[5] = LFE;718 device->DevChannels[6] = SIDE_LEFT;719 device->DevChannels[7] = SIDE_RIGHT;720 return;722 /* Same as WFX order */723 case DevFmtMono:724 case DevFmtStereo:725 case DevFmtQuad:726 case DevFmtX51Side:727 case DevFmtX61:728 break;729 }730 SetDefaultWFXChannelOrder(device);731 }732 /* Sets the default order used by WaveFormatEx */733 void SetDefaultWFXChannelOrder(ALCdevice *device)734 {735 switch(device->FmtChans)736 {737 case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;739 case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;740 device->DevChannels[1] = FRONT_RIGHT; break;742 case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;743 device->DevChannels[1] = FRONT_RIGHT;744 device->DevChannels[2] = BACK_LEFT;745 device->DevChannels[3] = BACK_RIGHT; break;747 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;748 device->DevChannels[1] = FRONT_RIGHT;749 device->DevChannels[2] = FRONT_CENTER;750 device->DevChannels[3] = LFE;751 device->DevChannels[4] = BACK_LEFT;752 device->DevChannels[5] = BACK_RIGHT; break;754 case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;755 device->DevChannels[1] = FRONT_RIGHT;756 device->DevChannels[2] = FRONT_CENTER;757 device->DevChannels[3] = LFE;758 device->DevChannels[4] = SIDE_LEFT;759 device->DevChannels[5] = SIDE_RIGHT; break;761 case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;762 device->DevChannels[1] = FRONT_RIGHT;763 device->DevChannels[2] = FRONT_CENTER;764 device->DevChannels[3] = LFE;765 device->DevChannels[4] = BACK_CENTER;766 device->DevChannels[5] = SIDE_LEFT;767 device->DevChannels[6] = SIDE_RIGHT; break;769 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;770 device->DevChannels[1] = FRONT_RIGHT;771 device->DevChannels[2] = FRONT_CENTER;772 device->DevChannels[3] = LFE;773 device->DevChannels[4] = BACK_LEFT;774 device->DevChannels[5] = BACK_RIGHT;775 device->DevChannels[6] = SIDE_LEFT;776 device->DevChannels[7] = SIDE_RIGHT; break;777 }778 }781 const ALCchar *DevFmtTypeString(enum DevFmtType type)782 {783 switch(type)784 {785 case DevFmtByte: return "Signed Byte";786 case DevFmtUByte: return "Unsigned Byte";787 case DevFmtShort: return "Signed Short";788 case DevFmtUShort: return "Unsigned Short";789 case DevFmtFloat: return "Float";790 }791 return "(unknown type)";792 }793 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)794 {795 switch(chans)796 {797 case DevFmtMono: return "Mono";798 case DevFmtStereo: return "Stereo";799 case DevFmtQuad: return "Quadraphonic";800 case DevFmtX51: return "5.1 Surround";801 case DevFmtX51Side: return "5.1 Side";802 case DevFmtX61: return "6.1 Surround";803 case DevFmtX71: return "7.1 Surround";804 }805 return "(unknown channels)";806 }808 ALuint BytesFromDevFmt(enum DevFmtType type)809 {810 switch(type)811 {812 case DevFmtByte: return sizeof(ALbyte);813 case DevFmtUByte: return sizeof(ALubyte);814 case DevFmtShort: return sizeof(ALshort);815 case DevFmtUShort: return sizeof(ALushort);816 case DevFmtFloat: return sizeof(ALfloat);817 }818 return 0;819 }820 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)821 {822 switch(chans)823 {824 case DevFmtMono: return 1;825 case DevFmtStereo: return 2;826 case DevFmtQuad: return 4;827 case DevFmtX51: return 6;828 case DevFmtX51Side: return 6;829 case DevFmtX61: return 7;830 case DevFmtX71: return 8;831 }832 return 0;833 }834 ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,835 enum DevFmtType *type)836 {837 switch(format)838 {839 case AL_FORMAT_MONO8:840 *chans = DevFmtMono;841 *type = DevFmtUByte;842 return AL_TRUE;843 case AL_FORMAT_MONO16:844 *chans = DevFmtMono;845 *type = DevFmtShort;846 return AL_TRUE;847 case AL_FORMAT_MONO_FLOAT32:848 *chans = DevFmtMono;849 *type = DevFmtFloat;850 return AL_TRUE;851 case AL_FORMAT_STEREO8:852 *chans = DevFmtStereo;853 *type = DevFmtUByte;854 return AL_TRUE;855 case AL_FORMAT_STEREO16:856 *chans = DevFmtStereo;857 *type = DevFmtShort;858 return AL_TRUE;859 case AL_FORMAT_STEREO_FLOAT32:860 *chans = DevFmtStereo;861 *type = DevFmtFloat;862 return AL_TRUE;863 case AL_FORMAT_QUAD8:864 *chans = DevFmtQuad;865 *type = DevFmtUByte;866 return AL_TRUE;867 case AL_FORMAT_QUAD16:868 *chans = DevFmtQuad;869 *type = DevFmtShort;870 return AL_TRUE;871 case AL_FORMAT_QUAD32:872 *chans = DevFmtQuad;873 *type = DevFmtFloat;874 return AL_TRUE;875 case AL_FORMAT_51CHN8:876 *chans = DevFmtX51;877 *type = DevFmtUByte;878 return AL_TRUE;879 case AL_FORMAT_51CHN16:880 *chans = DevFmtX51;881 *type = DevFmtShort;882 return AL_TRUE;883 case AL_FORMAT_51CHN32:884 *chans = DevFmtX51;885 *type = DevFmtFloat;886 return AL_TRUE;887 case AL_FORMAT_61CHN8:888 *chans = DevFmtX61;889 *type = DevFmtUByte;890 return AL_TRUE;891 case AL_FORMAT_61CHN16:892 *chans = DevFmtX61;893 *type = DevFmtShort;894 return AL_TRUE;895 case AL_FORMAT_61CHN32:896 *chans = DevFmtX61;897 *type = DevFmtFloat;898 return AL_TRUE;899 case AL_FORMAT_71CHN8:900 *chans = DevFmtX71;901 *type = DevFmtUByte;902 return AL_TRUE;903 case AL_FORMAT_71CHN16:904 *chans = DevFmtX71;905 *type = DevFmtShort;906 return AL_TRUE;907 case AL_FORMAT_71CHN32:908 *chans = DevFmtX71;909 *type = DevFmtFloat;910 return AL_TRUE;911 }912 return AL_FALSE;913 }915 static ALCboolean IsValidALCType(ALCenum type)916 {917 switch(type)918 {919 case ALC_BYTE:920 case ALC_UNSIGNED_BYTE:921 case ALC_SHORT:922 case ALC_UNSIGNED_SHORT:923 case ALC_INT:924 case ALC_UNSIGNED_INT:925 case ALC_FLOAT:926 return ALC_TRUE;927 }928 return ALC_FALSE;929 }931 static ALCboolean IsValidALCChannels(ALCenum channels)932 {933 switch(channels)934 {935 case ALC_MONO:936 case ALC_STEREO:937 case ALC_QUAD:938 case ALC_5POINT1:939 case ALC_6POINT1:940 case ALC_7POINT1:941 return ALC_TRUE;942 }943 return ALC_FALSE;944 }947 static void LockLists(void)948 {949 EnterCriticalSection(&ListLock);950 }952 static void UnlockLists(void)953 {954 LeaveCriticalSection(&ListLock);955 }957 /*958 IsDevice960 Check pDevice is a valid Device pointer961 */962 static ALCboolean IsDevice(ALCdevice *pDevice)963 {964 ALCdevice *pTempDevice;966 pTempDevice = g_pDeviceList;967 while(pTempDevice && pTempDevice != pDevice)968 pTempDevice = pTempDevice->next;970 return (pTempDevice ? ALC_TRUE : ALC_FALSE);971 }973 /*974 IsContext976 Check pContext is a valid Context pointer977 */978 static ALCboolean IsContext(ALCcontext *pContext)979 {980 ALCcontext *pTempContext;982 pTempContext = g_pContextList;983 while (pTempContext && pTempContext != pContext)984 pTempContext = pTempContext->next;986 return (pTempContext ? ALC_TRUE : ALC_FALSE);987 }990 /*991 alcSetError993 Store latest ALC Error994 */995 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)996 {997 LockLists();998 if(IsDevice(device))999 device->LastError = errorCode;1000 else1001 g_eLastNullDeviceError = errorCode;1002 UnlockLists();1003 }1006 /* UpdateDeviceParams:1007 *1008 * Updates device parameters according to the attribute list.1009 */1010 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)1011 {1012 ALuint i;1014 // Check for attributes1015 if(attrList && attrList[0])1016 {1017 ALCuint freq, numMono, numStereo, numSends;1018 enum DevFmtChannels schans;1019 enum DevFmtType stype;1020 ALuint attrIdx;1022 // If a context is already running on the device, stop playback so the1023 // device attributes can be updated1024 if((device->Flags&DEVICE_RUNNING))1025 ALCdevice_StopPlayback(device);1026 device->Flags &= ~DEVICE_RUNNING;1028 freq = device->Frequency;1029 schans = device->FmtChans;1030 stype = device->FmtType;1031 numMono = device->NumMonoSources;1032 numStereo = device->NumStereoSources;1033 numSends = device->NumAuxSends;1035 freq = GetConfigValueInt(NULL, "frequency", freq);1036 if(freq < 8000) freq = 8000;1038 attrIdx = 0;1039 while(attrList[attrIdx])1040 {1041 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT &&1042 device->IsLoopbackDevice)1043 {1044 ALCint val = attrList[attrIdx + 1];1045 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))1046 {1047 alcSetError(device, ALC_INVALID_VALUE);1048 return ALC_FALSE;1049 }1050 schans = val;1051 }1053 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT &&1054 device->IsLoopbackDevice)1055 {1056 ALCint val = attrList[attrIdx + 1];1057 if(!IsValidALCType(val) || !BytesFromDevFmt(val))1058 {1059 alcSetError(device, ALC_INVALID_VALUE);1060 return ALC_FALSE;1061 }1062 stype = val;1063 }1065 if(attrList[attrIdx] == ALC_FREQUENCY)1066 {1067 if(device->IsLoopbackDevice)1068 {1069 freq = attrList[attrIdx + 1];1070 if(freq < 8000)1071 {1072 alcSetError(device, ALC_INVALID_VALUE);1073 return ALC_FALSE;1074 }1075 }1076 else if(!ConfigValueExists(NULL, "frequency"))1077 {1078 freq = attrList[attrIdx + 1];1079 if(freq < 8000) freq = 8000;1080 device->Flags |= DEVICE_FREQUENCY_REQUEST;1081 }1082 }1084 if(attrList[attrIdx] == ALC_STEREO_SOURCES)1085 {1086 numStereo = attrList[attrIdx + 1];1087 if(numStereo > device->MaxNoOfSources)1088 numStereo = device->MaxNoOfSources;1090 numMono = device->MaxNoOfSources - numStereo;1091 }1093 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&1094 !ConfigValueExists(NULL, "sends"))1095 {1096 numSends = attrList[attrIdx + 1];1097 if(numSends > MAX_SENDS)1098 numSends = MAX_SENDS;1099 }1101 attrIdx += 2;1102 }1104 device->UpdateSize = (ALuint64)device->UpdateSize * freq /1105 device->Frequency;1107 device->Frequency = freq;1108 device->FmtChans = schans;1109 device->FmtType = stype;1110 device->NumMonoSources = numMono;1111 device->NumStereoSources = numStereo;1112 device->NumAuxSends = numSends;1113 }1115 if((device->Flags&DEVICE_RUNNING))1116 return ALC_TRUE;1118 LockDevice(device);1119 TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1120 DevFmtChannelsString(device->FmtChans),1121 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1122 DevFmtTypeString(device->FmtType), device->Frequency,1123 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1124 device->UpdateSize, device->NumUpdates);1125 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)1126 {1127 UnlockDevice(device);1128 return ALC_FALSE;1129 }1130 device->Flags |= DEVICE_RUNNING;1131 TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n",1132 DevFmtChannelsString(device->FmtChans),1133 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",1134 DevFmtTypeString(device->FmtType), device->Frequency,1135 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",1136 device->UpdateSize, device->NumUpdates);1138 aluInitPanning(device);1140 for(i = 0;i < MAXCHANNELS;i++)1141 {1142 device->ClickRemoval[i] = 0.0f;1143 device->PendingClicks[i] = 0.0f;1144 }1146 if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE))1147 device->Flags |= DEVICE_USE_HRTF;1148 if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device))1149 device->Flags &= ~DEVICE_USE_HRTF;1150 TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled");1152 if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)1153 {1154 if(!device->Bs2b)1155 {1156 device->Bs2b = calloc(1, sizeof(*device->Bs2b));1157 bs2b_clear(device->Bs2b);1158 }1159 bs2b_set_srate(device->Bs2b, device->Frequency);1160 bs2b_set_level(device->Bs2b, device->Bs2bLevel);1161 TRACE("BS2B level %d\n", device->Bs2bLevel);1162 }1163 else1164 {1165 free(device->Bs2b);1166 device->Bs2b = NULL;1167 TRACE("BS2B disabled\n");1168 }1170 device->Flags &= ~DEVICE_DUPLICATE_STEREO;1171 switch(device->FmtChans)1172 {1173 case DevFmtMono:1174 case DevFmtStereo:1175 break;1176 case DevFmtQuad:1177 case DevFmtX51:1178 case DevFmtX51Side:1179 case DevFmtX61:1180 case DevFmtX71:1181 if(GetConfigValueBool(NULL, "stereodup", AL_TRUE))1182 device->Flags |= DEVICE_DUPLICATE_STEREO;1183 break;1184 }1185 TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");1187 for(i = 0;i < device->NumContexts;i++)1188 {1189 ALCcontext *context = device->Contexts[i];1190 ALsizei pos;1192 context->UpdateSources = AL_FALSE;1193 for(pos = 0;pos < context->EffectSlotMap.size;pos++)1194 {1195 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;1197 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)1198 {1199 UnlockDevice(device);1200 ALCdevice_StopPlayback(device);1201 device->Flags &= ~DEVICE_RUNNING;1202 return ALC_FALSE;1203 }1204 slot->NeedsUpdate = AL_FALSE;1205 ALEffect_Update(slot->EffectState, context, slot);1206 }1208 for(pos = 0;pos < context->SourceMap.size;pos++)1209 {1210 ALsource *source = context->SourceMap.array[pos].value;1211 ALuint s = device->NumAuxSends;1212 while(s < MAX_SENDS)1213 {1214 if(source->Send[s].Slot)1215 source->Send[s].Slot->refcount--;1216 source->Send[s].Slot = NULL;1217 source->Send[s].WetFilter.type = 0;1218 source->Send[s].WetFilter.filter = 0;1219 s++;1220 }1221 source->NeedsUpdate = AL_FALSE;1222 ALsource_Update(source, context);1223 }1224 }1225 UnlockDevice(device);1227 return ALC_TRUE;1228 }1231 ALCvoid LockDevice(ALCdevice *device)1232 {1233 EnterCriticalSection(&device->Mutex);1234 }1236 ALCvoid UnlockDevice(ALCdevice *device)1237 {1238 LeaveCriticalSection(&device->Mutex);1239 }1241 /*1242 LockContext1244 Thread-safe entry1245 */1246 ALCvoid LockContext(ALCcontext *context)1247 {1248 EnterCriticalSection(&context->Device->Mutex);1249 }1252 /*1253 UnlockContext1255 Thread-safe exit1256 */1257 ALCvoid UnlockContext(ALCcontext *context)1258 {1259 LeaveCriticalSection(&context->Device->Mutex);1260 }1263 /*1264 GetLockedContext1266 Returns the currently active Context, in a locked state1267 */1268 ALCcontext *GetLockedContext(void)1269 {1270 ALCcontext *pContext = NULL;1272 LockLists();1274 pContext = tls_get(LocalContext);1275 if(pContext && !IsContext(pContext))1276 {1277 tls_set(LocalContext, NULL);1278 pContext = NULL;1279 }1280 if(!pContext)1281 pContext = GlobalContext;1282 if(pContext)1283 LockContext(pContext);1285 UnlockLists();1287 return pContext;1288 }1291 /*1292 InitContext1294 Initialize Context variables1295 */1296 static ALvoid InitContext(ALCcontext *pContext)1297 {1298 //Initialise listener1299 pContext->Listener.Gain = 1.0f;1300 pContext->Listener.MetersPerUnit = 1.0f;1301 pContext->Listener.Position[0] = 0.0f;1302 pContext->Listener.Position[1] = 0.0f;1303 pContext->Listener.Position[2] = 0.0f;1304 pContext->Listener.Velocity[0] = 0.0f;1305 pContext->Listener.Velocity[1] = 0.0f;1306 pContext->Listener.Velocity[2] = 0.0f;1307 pContext->Listener.Forward[0] = 0.0f;1308 pContext->Listener.Forward[1] = 0.0f;1309 pContext->Listener.Forward[2] = -1.0f;1310 pContext->Listener.Up[0] = 0.0f;1311 pContext->Listener.Up[1] = 1.0f;1312 pContext->Listener.Up[2] = 0.0f;1314 //Validate pContext1315 pContext->LastError = AL_NO_ERROR;1316 pContext->UpdateSources = AL_FALSE;1317 pContext->ActiveSourceCount = 0;1318 InitUIntMap(&pContext->SourceMap);1319 InitUIntMap(&pContext->EffectSlotMap);1321 //Set globals1322 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;1323 pContext->SourceDistanceModel = AL_FALSE;1324 pContext->DopplerFactor = 1.0f;1325 pContext->DopplerVelocity = 1.0f;1326 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;1327 pContext->DeferUpdates = AL_FALSE;1329 pContext->ExtensionList = alExtList;1330 }1333 /*1334 FreeContext1336 Clean up Context, destroy any remaining Sources1337 */1338 static ALCvoid FreeContext(ALCcontext *context)1339 {1340 //Invalidate context1341 memset(context, 0, sizeof(ALCcontext));1342 free(context);1343 }1345 ///////////////////////////////////////////////////////1348 ///////////////////////////////////////////////////////1349 // ALC Functions calls1352 // This should probably move to another c file but for now ...1353 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)1354 {1355 ALCdevice *device = NULL;1357 DO_INITCONFIG();1359 if(!CaptureBackend.name)1360 {1361 alcSetError(NULL, ALC_INVALID_VALUE);1362 return NULL;1363 }1365 if(SampleSize <= 0)1366 {1367 alcSetError(NULL, ALC_INVALID_VALUE);1368 return NULL;1369 }1371 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))1372 deviceName = NULL;1374 device = calloc(1, sizeof(ALCdevice));1375 if(!device)1376 {1377 alcSetError(NULL, ALC_OUT_OF_MEMORY);1378 return NULL;1379 }1381 //Validate device1382 device->Funcs = &CaptureBackend.Funcs;1383 device->Connected = ALC_TRUE;1384 device->IsCaptureDevice = AL_TRUE;1385 device->IsLoopbackDevice = AL_FALSE;1386 InitializeCriticalSection(&device->Mutex);1388 device->szDeviceName = NULL;1390 device->Flags |= DEVICE_FREQUENCY_REQUEST;1391 device->Frequency = frequency;1393 device->Flags |= DEVICE_CHANNELS_REQUEST;1394 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)1395 {1396 free(device);1397 alcSetError(NULL, ALC_INVALID_ENUM);1398 return NULL;1399 }1401 device->UpdateSize = SampleSize;1402 device->NumUpdates = 1;1404 LockLists();1405 if(ALCdevice_OpenCapture(device, deviceName))1406 {1407 device->next = g_pDeviceList;1408 g_pDeviceList = device;1409 g_ulDeviceCount++;1410 }1411 else1412 {1413 DeleteCriticalSection(&device->Mutex);1414 free(device);1415 device = NULL;1416 alcSetError(NULL, ALC_INVALID_VALUE);1417 }1418 UnlockLists();1420 return device;1421 }1423 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)1424 {1425 ALCdevice **list;1427 LockLists();1428 list = &g_pDeviceList;1429 while(*list && *list != pDevice)1430 list = &(*list)->next;1432 if(!*list || !(*list)->IsCaptureDevice)1433 {1434 alcSetError(*list, ALC_INVALID_DEVICE);1435 UnlockLists();1436 return ALC_FALSE;1437 }1439 *list = (*list)->next;1440 g_ulDeviceCount--;1442 UnlockLists();1444 LockDevice(pDevice);1445 ALCdevice_CloseCapture(pDevice);1446 UnlockDevice(pDevice);1448 free(pDevice->szDeviceName);1449 pDevice->szDeviceName = NULL;1451 DeleteCriticalSection(&pDevice->Mutex);1453 free(pDevice);1455 return ALC_TRUE;1456 }1458 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)1459 {1460 LockLists();1461 if(!IsDevice(device) || !device->IsCaptureDevice)1462 {1463 alcSetError(device, ALC_INVALID_DEVICE);1464 UnlockLists();1465 return;1466 }1467 LockDevice(device);1468 UnlockLists();1469 if(device->Connected)1470 ALCdevice_StartCapture(device);1471 UnlockDevice(device);1472 }1474 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)1475 {1476 LockLists();1477 if(!IsDevice(device) || !device->IsCaptureDevice)1478 {1479 alcSetError(device, ALC_INVALID_DEVICE);1480 UnlockLists();1481 return;1482 }1483 LockDevice(device);1484 UnlockLists();1485 if(device->Connected)1486 ALCdevice_StopCapture(device);1487 UnlockDevice(device);1488 }1490 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)1491 {1492 LockLists();1493 if(!IsDevice(device) || !device->IsCaptureDevice)1494 {1495 alcSetError(device, ALC_INVALID_DEVICE);1496 UnlockLists();1497 return;1498 }1499 LockDevice(device);1500 UnlockLists();1501 if(device->Connected)1502 ALCdevice_CaptureSamples(device, buffer, samples);1503 UnlockDevice(device);1504 }1506 /*1507 alcGetError1509 Return last ALC generated error code1510 */1511 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)1512 {1513 ALCenum errorCode;1515 LockLists();1516 if(IsDevice(device))1517 {1518 errorCode = device->LastError;1519 device->LastError = ALC_NO_ERROR;1520 }1521 else1522 {1523 errorCode = g_eLastNullDeviceError;1524 g_eLastNullDeviceError = ALC_NO_ERROR;1525 }1526 UnlockLists();1527 return errorCode;1528 }1531 /*1532 alcSuspendContext1534 Not functional1535 */1536 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)1537 {1538 (void)Context;1539 }1542 /*1543 alcProcessContext1545 Not functional1546 */1547 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)1548 {1549 (void)Context;1550 }1553 /*1554 alcGetString1556 Returns information about the Device, and error strings1557 */1558 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)1559 {1560 const ALCchar *value = NULL;1562 switch(param)1563 {1564 case ALC_NO_ERROR:1565 value = alcNoError;1566 break;1568 case ALC_INVALID_ENUM:1569 value = alcErrInvalidEnum;1570 break;1572 case ALC_INVALID_VALUE:1573 value = alcErrInvalidValue;1574 break;1576 case ALC_INVALID_DEVICE:1577 value = alcErrInvalidDevice;1578 break;1580 case ALC_INVALID_CONTEXT:1581 value = alcErrInvalidContext;1582 break;1584 case ALC_OUT_OF_MEMORY:1585 value = alcErrOutOfMemory;1586 break;1588 case ALC_DEVICE_SPECIFIER:1589 LockLists();1590 if(IsDevice(pDevice))1591 value = pDevice->szDeviceName;1592 else1593 {1594 ProbeDeviceList();1595 value = alcDeviceList;1596 }1597 UnlockLists();1598 break;1600 case ALC_ALL_DEVICES_SPECIFIER:1601 ProbeAllDeviceList();1602 value = alcAllDeviceList;1603 break;1605 case ALC_CAPTURE_DEVICE_SPECIFIER:1606 LockLists();1607 if(IsDevice(pDevice))1608 value = pDevice->szDeviceName;1609 else1610 {1611 ProbeCaptureDeviceList();1612 value = alcCaptureDeviceList;1613 }1614 UnlockLists();1615 break;1617 /* Default devices are always first in the list */1618 case ALC_DEFAULT_DEVICE_SPECIFIER:1619 if(!alcDeviceList)1620 ProbeDeviceList();1622 free(alcDefaultDeviceSpecifier);1623 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");1624 if(!alcDefaultDeviceSpecifier)1625 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1626 value = alcDefaultDeviceSpecifier;1627 break;1629 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:1630 if(!alcAllDeviceList)1631 ProbeAllDeviceList();1633 free(alcDefaultAllDeviceSpecifier);1634 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?1635 alcAllDeviceList : "");1636 if(!alcDefaultAllDeviceSpecifier)1637 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1638 value = alcDefaultAllDeviceSpecifier;1639 break;1641 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:1642 if(!alcCaptureDeviceList)1643 ProbeCaptureDeviceList();1645 free(alcCaptureDefaultDeviceSpecifier);1646 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?1647 alcCaptureDeviceList : "");1648 if(!alcCaptureDefaultDeviceSpecifier)1649 alcSetError(pDevice, ALC_OUT_OF_MEMORY);1650 value = alcCaptureDefaultDeviceSpecifier;1651 break;1653 case ALC_EXTENSIONS:1654 LockLists();1655 if(IsDevice(pDevice))1656 value = alcExtensionList;1657 else1658 value = alcNoDeviceExtList;1659 UnlockLists();1660 break;1662 default:1663 alcSetError(pDevice, ALC_INVALID_ENUM);1664 break;1665 }1667 return value;1668 }1671 /*1672 alcGetIntegerv1674 Returns information about the Device and the version of Open AL1675 */1676 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)1677 {1678 if(size == 0 || data == NULL)1679 {1680 alcSetError(device, ALC_INVALID_VALUE);1681 return;1682 }1684 LockLists();1685 if(!IsDevice(device))1686 {1687 switch(param)1688 {1689 case ALC_MAJOR_VERSION:1690 *data = alcMajorVersion;1691 break;1692 case ALC_MINOR_VERSION:1693 *data = alcMinorVersion;1694 break;1696 case ALC_ATTRIBUTES_SIZE:1697 case ALC_ALL_ATTRIBUTES:1698 case ALC_FREQUENCY:1699 case ALC_REFRESH:1700 case ALC_SYNC:1701 case ALC_MONO_SOURCES:1702 case ALC_STEREO_SOURCES:1703 case ALC_CAPTURE_SAMPLES:1704 case ALC_FORMAT_CHANNELS_SOFT:1705 case ALC_FORMAT_TYPE_SOFT:1706 alcSetError(NULL, ALC_INVALID_DEVICE);1707 break;1709 default:1710 alcSetError(NULL, ALC_INVALID_ENUM);1711 break;1712 }1713 }1714 else if(device->IsCaptureDevice)1715 {1716 switch(param)1717 {1718 case ALC_CAPTURE_SAMPLES:1719 LockDevice(device);1720 *data = ALCdevice_AvailableSamples(device);1721 UnlockDevice(device);1722 break;1724 case ALC_CONNECTED:1725 *data = device->Connected;1726 break;1728 default:1729 alcSetError(device, ALC_INVALID_ENUM);1730 break;1731 }1732 }1733 else /* render device */1734 {1735 switch(param)1736 {1737 case ALC_MAJOR_VERSION:1738 *data = alcMajorVersion;1739 break;1741 case ALC_MINOR_VERSION:1742 *data = alcMinorVersion;1743 break;1745 case ALC_EFX_MAJOR_VERSION:1746 *data = alcEFXMajorVersion;1747 break;1749 case ALC_EFX_MINOR_VERSION:1750 *data = alcEFXMinorVersion;1751 break;1753 case ALC_ATTRIBUTES_SIZE:1754 *data = 13;1755 break;1757 case ALC_ALL_ATTRIBUTES:1758 if(size < 13)1759 alcSetError(device, ALC_INVALID_VALUE);1760 else1761 {1762 int i = 0;1764 data[i++] = ALC_FREQUENCY;1765 data[i++] = device->Frequency;1767 if(!device->IsLoopbackDevice)1768 {1769 data[i++] = ALC_REFRESH;1770 data[i++] = device->Frequency / device->UpdateSize;1772 data[i++] = ALC_SYNC;1773 data[i++] = ALC_FALSE;1774 }1775 else1776 {1777 data[i++] = ALC_FORMAT_CHANNELS_SOFT;1778 data[i++] = device->FmtChans;1780 data[i++] = ALC_FORMAT_TYPE_SOFT;1781 data[i++] = device->FmtType;1782 }1784 data[i++] = ALC_MONO_SOURCES;1785 data[i++] = device->NumMonoSources;1787 data[i++] = ALC_STEREO_SOURCES;1788 data[i++] = device->NumStereoSources;1790 data[i++] = ALC_MAX_AUXILIARY_SENDS;1791 data[i++] = device->NumAuxSends;1793 data[i++] = 0;1794 }1795 break;1797 case ALC_FREQUENCY:1798 *data = device->Frequency;1799 break;1801 case ALC_REFRESH:1802 if(device->IsLoopbackDevice)1803 alcSetError(device, ALC_INVALID_DEVICE);1804 else1805 *data = device->Frequency / device->UpdateSize;1806 break;1808 case ALC_SYNC:1809 if(device->IsLoopbackDevice)1810 alcSetError(device, ALC_INVALID_DEVICE);1811 else1812 *data = ALC_FALSE;1813 break;1815 case ALC_FORMAT_CHANNELS_SOFT:1816 if(!device->IsLoopbackDevice)1817 alcSetError(device, ALC_INVALID_DEVICE);1818 else1819 *data = device->FmtChans;1820 break;1822 case ALC_FORMAT_TYPE_SOFT:1823 if(!device->IsLoopbackDevice)1824 alcSetError(device, ALC_INVALID_DEVICE);1825 else1826 *data = device->FmtType;1827 break;1829 case ALC_MONO_SOURCES:1830 *data = device->NumMonoSources;1831 break;1833 case ALC_STEREO_SOURCES:1834 *data = device->NumStereoSources;1835 break;1837 case ALC_MAX_AUXILIARY_SENDS:1838 *data = device->NumAuxSends;1839 break;1841 case ALC_CONNECTED:1842 *data = device->Connected;1843 break;1845 default:1846 alcSetError(device, ALC_INVALID_ENUM);1847 break;1848 }1849 }1850 UnlockLists();1851 }1854 /*1855 alcIsExtensionPresent1857 Determines if there is support for a particular extension1858 */1859 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)1860 {1861 ALCboolean bResult = ALC_FALSE;1862 const char *ptr;1863 size_t len;1865 if(!extName)1866 {1867 alcSetError(device, ALC_INVALID_VALUE);1868 return ALC_FALSE;1869 }1871 len = strlen(extName);1872 LockLists();1873 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);1874 UnlockLists();1875 while(ptr && *ptr)1876 {1877 if(strncasecmp(ptr, extName, len) == 0 &&1878 (ptr[len] == '\0' || isspace(ptr[len])))1879 {1880 bResult = ALC_TRUE;1881 break;1882 }1883 if((ptr=strchr(ptr, ' ')) != NULL)1884 {1885 do {1886 ++ptr;1887 } while(isspace(*ptr));1888 }1889 }1891 return bResult;1892 }1895 /*1896 alcGetProcAddress1898 Retrieves the function address for a particular extension function1899 */1900 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)1901 {1902 ALsizei i = 0;1904 if(!funcName)1905 {1906 alcSetError(device, ALC_INVALID_VALUE);1907 return NULL;1908 }1910 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)1911 i++;1912 return alcFunctions[i].address;1913 }1916 /*1917 alcGetEnumValue1919 Get the value for a particular ALC Enumerated Value1920 */1921 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)1922 {1923 ALsizei i = 0;1925 if(!enumName)1926 {1927 alcSetError(device, ALC_INVALID_VALUE);1928 return (ALCenum)0;1929 }1931 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)1932 i++;1933 return enumeration[i].value;1934 }1937 /*1938 alcCreateContext1940 Create and attach a Context to a particular Device.1941 */1942 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)1943 {1944 ALCcontext *ALContext;1945 void *temp;1947 LockLists();1948 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)1949 {1950 alcSetError(device, ALC_INVALID_DEVICE);1951 UnlockLists();1952 return NULL;1953 }1955 // Reset Context Last Error code1956 device->LastError = ALC_NO_ERROR;1958 if(UpdateDeviceParams(device, attrList) == ALC_FALSE)1959 {1960 alcSetError(device, ALC_INVALID_DEVICE);1961 aluHandleDisconnect(device);1962 UnlockLists();1963 return NULL;1964 }1966 LockDevice(device);1967 ALContext = NULL;1968 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));1969 if(temp)1970 {1971 device->Contexts = temp;1973 ALContext = calloc(1, sizeof(ALCcontext));1974 if(ALContext)1975 {1976 ALContext->MaxActiveSources = 256;1977 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *1978 ALContext->MaxActiveSources);1979 }1980 }1981 if(!ALContext || !ALContext->ActiveSources)1982 {1983 free(ALContext);1984 alcSetError(device, ALC_OUT_OF_MEMORY);1985 UnlockDevice(device);1986 if(device->NumContexts == 0)1987 {1988 ALCdevice_StopPlayback(device);1989 device->Flags &= ~DEVICE_RUNNING;1990 }1991 UnlockLists();1992 return NULL;1993 }1995 device->Contexts[device->NumContexts++] = ALContext;1996 ALContext->Device = device;1998 InitContext(ALContext);1999 UnlockDevice(device);2001 ALContext->next = g_pContextList;2002 g_pContextList = ALContext;2003 g_ulContextCount++;2005 UnlockLists();2007 return ALContext;2008 }2011 /*2012 alcDestroyContext2014 Remove a Context2015 */2016 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)2017 {2018 ALCdevice *Device;2019 ALCcontext **list;2020 ALuint i;2022 LockLists();2023 list = &g_pContextList;2024 while(*list && *list != context)2025 list = &(*list)->next;2027 if(!*list)2028 {2029 alcSetError(NULL, ALC_INVALID_CONTEXT);2030 UnlockLists();2031 return;2032 }2034 *list = (*list)->next;2035 g_ulContextCount--;2037 if(context == tls_get(LocalContext))2038 tls_set(LocalContext, NULL);2039 if(context == GlobalContext)2040 GlobalContext = NULL;2042 Device = context->Device;2043 LockDevice(Device);2044 for(i = 0;i < Device->NumContexts;i++)2045 {2046 if(Device->Contexts[i] == context)2047 {2048 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];2049 Device->NumContexts--;2050 break;2051 }2052 }2053 UnlockDevice(Device);2055 if(Device->NumContexts == 0)2056 {2057 ALCdevice_StopPlayback(Device);2058 Device->Flags &= ~DEVICE_RUNNING;2059 }2060 UnlockLists();2062 if(context->SourceMap.size > 0)2063 {2064 ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);2065 ReleaseALSources(context);2066 }2067 ResetUIntMap(&context->SourceMap);2069 if(context->EffectSlotMap.size > 0)2070 {2071 ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);2072 ReleaseALAuxiliaryEffectSlots(context);2073 }2074 ResetUIntMap(&context->EffectSlotMap);2076 free(context->ActiveSources);2077 context->ActiveSources = NULL;2078 context->MaxActiveSources = 0;2079 context->ActiveSourceCount = 0;2081 FreeContext(context);2082 }2085 /*2086 alcGetCurrentContext2088 Returns the currently active Context2089 */2090 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)2091 {2092 ALCcontext *Context;2094 LockLists();2095 Context = tls_get(LocalContext);2096 if(Context && !IsContext(Context))2097 {2098 tls_set(LocalContext, NULL);2099 Context = NULL;2100 }2101 if(!Context)2102 Context = GlobalContext;2103 UnlockLists();2105 return Context;2106 }2108 /*2109 alcGetThreadContext2111 Returns the currently active thread-local Context2112 */2113 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)2114 {2115 ALCcontext *pContext = NULL;2117 LockLists();2119 pContext = tls_get(LocalContext);2120 if(pContext && !IsContext(pContext))2121 {2122 tls_set(LocalContext, NULL);2123 pContext = NULL;2124 }2126 UnlockLists();2128 return pContext;2129 }2132 /*2133 alcGetContextsDevice2135 Returns the Device that a particular Context is attached to2136 */2137 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)2138 {2139 ALCdevice *pDevice = NULL;2141 LockLists();2142 if(IsContext(pContext))2143 pDevice = pContext->Device;2144 else2145 alcSetError(NULL, ALC_INVALID_CONTEXT);2146 UnlockLists();2148 return pDevice;2149 }2152 /*2153 alcMakeContextCurrent2155 Makes the given Context the active Context2156 */2157 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)2158 {2159 ALboolean bReturn = AL_TRUE;2161 LockLists();2163 // context must be a valid Context or NULL2164 if(context == NULL || IsContext(context))2165 {2166 GlobalContext = context;2167 tls_set(LocalContext, NULL);2168 }2169 else2170 {2171 alcSetError(NULL, ALC_INVALID_CONTEXT);2172 bReturn = AL_FALSE;2173 }2175 UnlockLists();2177 return bReturn;2178 }2180 /*2181 alcSetThreadContext2183 Makes the given Context the active Context for the current thread2184 */2185 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)2186 {2187 ALboolean bReturn = AL_TRUE;2189 LockLists();2191 // context must be a valid Context or NULL2192 if(context == NULL || IsContext(context))2193 tls_set(LocalContext, context);2194 else2195 {2196 alcSetError(NULL, ALC_INVALID_CONTEXT);2197 bReturn = AL_FALSE;2198 }2200 UnlockLists();2202 return bReturn;2203 }2206 static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)2207 {2208 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)2209 {2210 *chans = DevFmtMono;2211 *type = DevFmtFloat;2212 return;2213 }2214 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0)2215 {2216 *chans = DevFmtStereo;2217 *type = DevFmtFloat;2218 return;2219 }2220 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0)2221 {2222 *chans = DevFmtQuad;2223 *type = DevFmtFloat;2224 return;2225 }2226 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0)2227 {2228 *chans = DevFmtX51;2229 *type = DevFmtFloat;2230 return;2231 }2232 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0)2233 {2234 *chans = DevFmtX61;2235 *type = DevFmtFloat;2236 return;2237 }2238 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0)2239 {2240 *chans = DevFmtX71;2241 *type = DevFmtFloat;2242 return;2243 }2245 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0)2246 {2247 *chans = DevFmtMono;2248 *type = DevFmtShort;2249 return;2250 }2251 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0)2252 {2253 *chans = DevFmtStereo;2254 *type = DevFmtShort;2255 return;2256 }2257 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0)2258 {2259 *chans = DevFmtQuad;2260 *type = DevFmtShort;2261 return;2262 }2263 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0)2264 {2265 *chans = DevFmtX51;2266 *type = DevFmtShort;2267 return;2268 }2269 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0)2270 {2271 *chans = DevFmtX61;2272 *type = DevFmtShort;2273 return;2274 }2275 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0)2276 {2277 *chans = DevFmtX71;2278 *type = DevFmtShort;2279 return;2280 }2282 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0)2283 {2284 *chans = DevFmtMono;2285 *type = DevFmtByte;2286 return;2287 }2288 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0)2289 {2290 *chans = DevFmtStereo;2291 *type = DevFmtByte;2292 return;2293 }2294 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0)2295 {2296 *chans = DevFmtQuad;2297 *type = DevFmtByte;2298 return;2299 }2300 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0)2301 {2302 *chans = DevFmtX51;2303 *type = DevFmtByte;2304 return;2305 }2306 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0)2307 {2308 *chans = DevFmtX61;2309 *type = DevFmtByte;2310 return;2311 }2312 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0)2313 {2314 *chans = DevFmtX71;2315 *type = DevFmtByte;2316 return;2317 }2319 ERR("Unknown format: \"%s\"\n", str);2320 *chans = DevFmtStereo;2321 *type = DevFmtShort;2322 }2324 /*2325 alcOpenDevice2327 Open the Device specified.2328 */2329 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)2330 {2331 const ALCchar *fmt;2332 ALCdevice *device;2334 DO_INITCONFIG();2336 if(!PlaybackBackend.name)2337 {2338 alcSetError(NULL, ALC_INVALID_VALUE);2339 return NULL;2340 }2342 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))2343 deviceName = NULL;2345 device = calloc(1, sizeof(ALCdevice));2346 if(!device)2347 {2348 alcSetError(NULL, ALC_OUT_OF_MEMORY);2349 return NULL;2350 }2352 //Validate device2353 device->Funcs = &PlaybackBackend.Funcs;2354 device->Connected = ALC_TRUE;2355 device->IsCaptureDevice = AL_FALSE;2356 device->IsLoopbackDevice = AL_FALSE;2357 InitializeCriticalSection(&device->Mutex);2358 device->LastError = ALC_NO_ERROR;2360 device->Flags = 0;2361 device->Bs2b = NULL;2362 device->szDeviceName = NULL;2364 device->Contexts = NULL;2365 device->NumContexts = 0;2367 InitUIntMap(&device->BufferMap);2368 InitUIntMap(&device->EffectMap);2369 InitUIntMap(&device->FilterMap);2371 //Set output format2372 if(ConfigValueExists(NULL, "frequency"))2373 device->Flags |= DEVICE_FREQUENCY_REQUEST;2374 device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE);2375 if(device->Frequency < 8000)2376 device->Frequency = 8000;2378 if(ConfigValueExists(NULL, "format"))2379 device->Flags |= DEVICE_CHANNELS_REQUEST;2380 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");2381 GetFormatFromString(fmt, &device->FmtChans, &device->FmtType);2383 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);2384 if(device->NumUpdates < 2)2385 device->NumUpdates = 4;2387 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);2388 if(device->UpdateSize <= 0)2389 device->UpdateSize = 1024;2391 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2392 if(device->MaxNoOfSources <= 0)2393 device->MaxNoOfSources = 256;2395 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2396 if(device->AuxiliaryEffectSlotMax <= 0)2397 device->AuxiliaryEffectSlotMax = 4;2399 device->NumStereoSources = 1;2400 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2402 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2403 if(device->NumAuxSends > MAX_SENDS)2404 device->NumAuxSends = MAX_SENDS;2406 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2408 // Find a playback device to open2409 LockLists();2410 if(ALCdevice_OpenPlayback(device, deviceName))2411 {2412 device->next = g_pDeviceList;2413 g_pDeviceList = device;2414 g_ulDeviceCount++;2415 }2416 else2417 {2418 // No suitable output device found2419 DeleteCriticalSection(&device->Mutex);2420 free(device);2421 device = NULL;2422 alcSetError(NULL, ALC_INVALID_VALUE);2423 }2424 UnlockLists();2426 return device;2427 }2430 /*2431 alcCloseDevice2433 Close the specified Device2434 */2435 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)2436 {2437 ALCdevice **list;2439 LockLists();2440 list = &g_pDeviceList;2441 while(*list && *list != pDevice)2442 list = &(*list)->next;2444 if(!*list || (*list)->IsCaptureDevice)2445 {2446 alcSetError(*list, ALC_INVALID_DEVICE);2447 UnlockLists();2448 return ALC_FALSE;2449 }2451 *list = (*list)->next;2452 g_ulDeviceCount--;2454 UnlockLists();2456 if(pDevice->NumContexts > 0)2457 {2458 WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);2459 while(pDevice->NumContexts > 0)2460 alcDestroyContext(pDevice->Contexts[0]);2461 }2462 ALCdevice_ClosePlayback(pDevice);2464 if(pDevice->BufferMap.size > 0)2465 {2466 WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);2467 ReleaseALBuffers(pDevice);2468 }2469 ResetUIntMap(&pDevice->BufferMap);2471 if(pDevice->EffectMap.size > 0)2472 {2473 WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);2474 ReleaseALEffects(pDevice);2475 }2476 ResetUIntMap(&pDevice->EffectMap);2478 if(pDevice->FilterMap.size > 0)2479 {2480 WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);2481 ReleaseALFilters(pDevice);2482 }2483 ResetUIntMap(&pDevice->FilterMap);2485 free(pDevice->Bs2b);2486 pDevice->Bs2b = NULL;2488 free(pDevice->szDeviceName);2489 pDevice->szDeviceName = NULL;2491 free(pDevice->Contexts);2492 pDevice->Contexts = NULL;2494 DeleteCriticalSection(&pDevice->Mutex);2496 //Release device structure2497 memset(pDevice, 0, sizeof(ALCdevice));2498 free(pDevice);2500 return ALC_TRUE;2501 }2504 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void)2505 {2506 ALCdevice *device;2508 DO_INITCONFIG();2510 device = calloc(1, sizeof(ALCdevice));2511 if(!device)2512 {2513 alcSetError(NULL, ALC_OUT_OF_MEMORY);2514 return NULL;2515 }2517 //Validate device2518 device->Funcs = &BackendLoopback.Funcs;2519 device->Connected = ALC_TRUE;2520 device->IsCaptureDevice = AL_FALSE;2521 device->IsLoopbackDevice = AL_TRUE;2522 InitializeCriticalSection(&device->Mutex);2523 device->LastError = ALC_NO_ERROR;2525 device->Flags = 0;2526 device->Bs2b = NULL;2527 device->szDeviceName = NULL;2529 device->Contexts = NULL;2530 device->NumContexts = 0;2532 InitUIntMap(&device->BufferMap);2533 InitUIntMap(&device->EffectMap);2534 InitUIntMap(&device->FilterMap);2536 //Set output format2537 device->Frequency = 44100;2538 device->FmtChans = DevFmtStereo;2539 device->FmtType = DevFmtShort;2541 device->NumUpdates = 0;2542 device->UpdateSize = 0;2544 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);2545 if(device->MaxNoOfSources <= 0)2546 device->MaxNoOfSources = 256;2548 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);2549 if(device->AuxiliaryEffectSlotMax <= 0)2550 device->AuxiliaryEffectSlotMax = 4;2552 device->NumStereoSources = 1;2553 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;2555 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);2556 if(device->NumAuxSends > MAX_SENDS)2557 device->NumAuxSends = MAX_SENDS;2559 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);2561 // Open the "backend"2562 LockLists();2563 ALCdevice_OpenPlayback(device, "Loopback");2565 device->next = g_pDeviceList;2566 g_pDeviceList = device;2567 g_ulDeviceCount++;2568 UnlockLists();2570 return device;2571 }2573 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)2574 {2575 ALCboolean ret = ALC_FALSE;2577 LockLists();2578 if(!IsDevice(device) || !device->IsLoopbackDevice)2579 alcSetError(device, ALC_INVALID_DEVICE);2580 else if(freq <= 0)2581 alcSetError(device, ALC_INVALID_VALUE);2582 else if(!IsValidALCType(type) || !IsValidALCChannels(channels))2583 alcSetError(device, ALC_INVALID_ENUM);2584 else2585 {2586 if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 &&2587 freq >= 8000)2588 ret = ALC_TRUE;2589 }2590 UnlockLists();2592 return ret;2593 }2595 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)2596 {2597 LockLists();2598 if(!IsDevice(device) || !device->IsLoopbackDevice)2599 alcSetError(device, ALC_INVALID_DEVICE);2600 else if(samples < 0 || (samples > 0 && buffer == NULL))2601 alcSetError(device, ALC_INVALID_VALUE);2602 else2603 aluMixData(device, buffer, samples);2604 UnlockLists();2605 }2608 static void ReleaseALC(ALCboolean doclose)2609 {2610 free(alcDeviceList); alcDeviceList = NULL;2611 alcDeviceListSize = 0;2612 free(alcAllDeviceList); alcAllDeviceList = NULL;2613 alcAllDeviceListSize = 0;2614 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;2615 alcCaptureDeviceListSize = 0;2617 free(alcDefaultDeviceSpecifier);2618 alcDefaultDeviceSpecifier = NULL;2619 free(alcDefaultAllDeviceSpecifier);2620 alcDefaultAllDeviceSpecifier = NULL;2621 free(alcCaptureDefaultDeviceSpecifier);2622 alcCaptureDefaultDeviceSpecifier = NULL;2624 if(doclose)2625 {2626 if(g_ulDeviceCount > 0)2627 WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2629 while(g_pDeviceList)2630 {2631 if(g_pDeviceList->IsCaptureDevice)2632 alcCaptureCloseDevice(g_pDeviceList);2633 else2634 alcCloseDevice(g_pDeviceList);2635 }2636 }2637 else2638 {2639 if(g_ulDeviceCount > 0)2640 WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");2641 }2642 }2644 ///////////////////////////////////////////////////////