Mercurial > audio-send
diff Alc/helpers.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Alc/helpers.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,349 @@ 1.4 +/** 1.5 + * OpenAL cross platform audio library 1.6 + * Copyright (C) 2011 by authors. 1.7 + * This library is free software; you can redistribute it and/or 1.8 + * modify it under the terms of the GNU Library General Public 1.9 + * License as published by the Free Software Foundation; either 1.10 + * version 2 of the License, or (at your option) any later version. 1.11 + * 1.12 + * This library is distributed in the hope that it will be useful, 1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.15 + * Library General Public License for more details. 1.16 + * 1.17 + * You should have received a copy of the GNU Library General Public 1.18 + * License along with this library; if not, write to the 1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1.20 + * Boston, MA 02111-1307, USA. 1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 1.22 + */ 1.23 + 1.24 +#include "config.h" 1.25 + 1.26 +#include <stdlib.h> 1.27 +#ifdef HAVE_DLFCN_H 1.28 +#include <dlfcn.h> 1.29 +#endif 1.30 + 1.31 +#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H) 1.32 +#define INITGUID 1.33 +#include <windows.h> 1.34 +#ifdef HAVE_GUIDDEF_H 1.35 +#include <guiddef.h> 1.36 +#else 1.37 +#include <initguid.h> 1.38 +#endif 1.39 + 1.40 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); 1.41 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); 1.42 + 1.43 +DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16); 1.44 + 1.45 +DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); 1.46 +DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); 1.47 +DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2); 1.48 +DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); 1.49 + 1.50 +#endif 1.51 + 1.52 +#include "alMain.h" 1.53 + 1.54 +#ifdef _WIN32 1.55 +void pthread_once(pthread_once_t *once, void (*callback)(void)) 1.56 +{ 1.57 + LONG ret; 1.58 + while((ret=InterlockedExchange(once, 1)) == 1) 1.59 + Sleep(0); 1.60 + if(ret == 0) 1.61 + callback(); 1.62 + InterlockedExchange(once, 2); 1.63 +} 1.64 + 1.65 +void *LoadLib(const char *name) 1.66 +{ return LoadLibraryA(name); } 1.67 +void CloseLib(void *handle) 1.68 +{ FreeLibrary((HANDLE)handle); } 1.69 +void *GetSymbol(void *handle, const char *name) 1.70 +{ 1.71 + void *ret; 1.72 + 1.73 + ret = (void*)GetProcAddress((HANDLE)handle, name); 1.74 + if(ret == NULL) 1.75 + ERR("Failed to load %s\n", name); 1.76 + return ret; 1.77 +} 1.78 + 1.79 +#else 1.80 + 1.81 +void InitializeCriticalSection(CRITICAL_SECTION *cs) 1.82 +{ 1.83 + pthread_mutexattr_t attrib; 1.84 + int ret; 1.85 + 1.86 + ret = pthread_mutexattr_init(&attrib); 1.87 + assert(ret == 0); 1.88 + 1.89 + ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE); 1.90 +#ifdef HAVE_PTHREAD_NP_H 1.91 + if(ret != 0) 1.92 + ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE); 1.93 +#endif 1.94 + assert(ret == 0); 1.95 + ret = pthread_mutex_init(cs, &attrib); 1.96 + assert(ret == 0); 1.97 + 1.98 + pthread_mutexattr_destroy(&attrib); 1.99 +} 1.100 +void DeleteCriticalSection(CRITICAL_SECTION *cs) 1.101 +{ 1.102 + int ret; 1.103 + ret = pthread_mutex_destroy(cs); 1.104 + assert(ret == 0); 1.105 +} 1.106 +void EnterCriticalSection(CRITICAL_SECTION *cs) 1.107 +{ 1.108 + int ret; 1.109 + ret = pthread_mutex_lock(cs); 1.110 + assert(ret == 0); 1.111 +} 1.112 +void LeaveCriticalSection(CRITICAL_SECTION *cs) 1.113 +{ 1.114 + int ret; 1.115 + ret = pthread_mutex_unlock(cs); 1.116 + assert(ret == 0); 1.117 +} 1.118 + 1.119 +/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed 1.120 + * to the expected DWORD. Both are defined as unsigned 32-bit types, however. 1.121 + * Additionally, Win32 is supposed to measure the time since Windows started, 1.122 + * as opposed to the actual time. */ 1.123 +ALuint timeGetTime(void) 1.124 +{ 1.125 +#if _POSIX_TIMERS > 0 1.126 + struct timespec ts; 1.127 + int ret = -1; 1.128 + 1.129 +#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0) 1.130 +#if _POSIX_MONOTONIC_CLOCK == 0 1.131 + static int hasmono = 0; 1.132 + if(hasmono > 0 || (hasmono == 0 && 1.133 + (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0)) 1.134 +#endif 1.135 + ret = clock_gettime(CLOCK_MONOTONIC, &ts); 1.136 +#endif 1.137 + if(ret != 0) 1.138 + ret = clock_gettime(CLOCK_REALTIME, &ts); 1.139 + assert(ret == 0); 1.140 + 1.141 + return ts.tv_nsec/1000000 + ts.tv_sec*1000; 1.142 +#else 1.143 + struct timeval tv; 1.144 + int ret; 1.145 + 1.146 + ret = gettimeofday(&tv, NULL); 1.147 + assert(ret == 0); 1.148 + 1.149 + return tv.tv_usec/1000 + tv.tv_sec*1000; 1.150 +#endif 1.151 +} 1.152 + 1.153 +#ifdef HAVE_DLFCN_H 1.154 + 1.155 +void *LoadLib(const char *name) 1.156 +{ 1.157 + const char *err; 1.158 + void *handle; 1.159 + 1.160 + dlerror(); 1.161 + handle = dlopen(name, RTLD_NOW); 1.162 + if((err=dlerror()) != NULL) 1.163 + handle = NULL; 1.164 + return handle; 1.165 +} 1.166 +void CloseLib(void *handle) 1.167 +{ dlclose(handle); } 1.168 +void *GetSymbol(void *handle, const char *name) 1.169 +{ 1.170 + const char *err; 1.171 + void *sym; 1.172 + 1.173 + dlerror(); 1.174 + sym = dlsym(handle, name); 1.175 + if((err=dlerror()) != NULL) 1.176 + { 1.177 + ERR("Failed to load %s: %s\n", name, err); 1.178 + sym = NULL; 1.179 + } 1.180 + return sym; 1.181 +} 1.182 + 1.183 +#endif 1.184 +#endif 1.185 + 1.186 + 1.187 +void al_print(const char *fname, unsigned int line, const char *fmt, ...) 1.188 +{ 1.189 + const char *fn; 1.190 + char str[256]; 1.191 + int i; 1.192 + 1.193 + fn = strrchr(fname, '/'); 1.194 + if(!fn) fn = strrchr(fname, '\\'); 1.195 + if(!fn) fn = fname; 1.196 + else fn += 1; 1.197 + 1.198 + i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line); 1.199 + if(i < (int)sizeof(str) && i > 0) 1.200 + { 1.201 + va_list ap; 1.202 + va_start(ap, fmt); 1.203 + vsnprintf(str+i, sizeof(str)-i, fmt, ap); 1.204 + va_end(ap); 1.205 + } 1.206 + str[sizeof(str)-1] = 0; 1.207 + 1.208 + fprintf(LogFile, "%s", str); 1.209 + fflush(LogFile); 1.210 +} 1.211 + 1.212 + 1.213 +void SetRTPriority(void) 1.214 +{ 1.215 + ALboolean failed; 1.216 + 1.217 +#ifdef _WIN32 1.218 + if(RTPrioLevel > 0) 1.219 + failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 1.220 + else 1.221 + failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); 1.222 +#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__) 1.223 + struct sched_param param; 1.224 + 1.225 + if(RTPrioLevel > 0) 1.226 + { 1.227 + /* Use the minimum real-time priority possible for now (on Linux this 1.228 + * should be 1 for SCHED_RR) */ 1.229 + param.sched_priority = sched_get_priority_min(SCHED_RR); 1.230 + failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); 1.231 + } 1.232 + else 1.233 + { 1.234 + param.sched_priority = 0; 1.235 + failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m); 1.236 + } 1.237 +#else 1.238 + /* Real-time priority not available */ 1.239 + failed = (RTPrioLevel>0); 1.240 +#endif 1.241 + if(failed) 1.242 + ERR("Failed to set priority level for thread\n"); 1.243 +} 1.244 + 1.245 + 1.246 +void InitUIntMap(UIntMap *map) 1.247 +{ 1.248 + map->array = NULL; 1.249 + map->size = 0; 1.250 + map->maxsize = 0; 1.251 +} 1.252 + 1.253 +void ResetUIntMap(UIntMap *map) 1.254 +{ 1.255 + free(map->array); 1.256 + map->array = NULL; 1.257 + map->size = 0; 1.258 + map->maxsize = 0; 1.259 +} 1.260 + 1.261 +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) 1.262 +{ 1.263 + ALsizei pos = 0; 1.264 + 1.265 + if(map->size > 0) 1.266 + { 1.267 + ALsizei low = 0; 1.268 + ALsizei high = map->size - 1; 1.269 + while(low < high) 1.270 + { 1.271 + ALsizei mid = low + (high-low)/2; 1.272 + if(map->array[mid].key < key) 1.273 + low = mid + 1; 1.274 + else 1.275 + high = mid; 1.276 + } 1.277 + if(map->array[low].key < key) 1.278 + low++; 1.279 + pos = low; 1.280 + } 1.281 + 1.282 + if(pos == map->size || map->array[pos].key != key) 1.283 + { 1.284 + if(map->size == map->maxsize) 1.285 + { 1.286 + ALvoid *temp; 1.287 + ALsizei newsize; 1.288 + 1.289 + newsize = (map->maxsize ? (map->maxsize<<1) : 4); 1.290 + if(newsize < map->maxsize) 1.291 + return AL_OUT_OF_MEMORY; 1.292 + 1.293 + temp = realloc(map->array, newsize*sizeof(map->array[0])); 1.294 + if(!temp) return AL_OUT_OF_MEMORY; 1.295 + map->array = temp; 1.296 + map->maxsize = newsize; 1.297 + } 1.298 + 1.299 + map->size++; 1.300 + if(pos < map->size-1) 1.301 + memmove(&map->array[pos+1], &map->array[pos], 1.302 + (map->size-1-pos)*sizeof(map->array[0])); 1.303 + } 1.304 + map->array[pos].key = key; 1.305 + map->array[pos].value = value; 1.306 + 1.307 + return AL_NO_ERROR; 1.308 +} 1.309 + 1.310 +void RemoveUIntMapKey(UIntMap *map, ALuint key) 1.311 +{ 1.312 + if(map->size > 0) 1.313 + { 1.314 + ALsizei low = 0; 1.315 + ALsizei high = map->size - 1; 1.316 + while(low < high) 1.317 + { 1.318 + ALsizei mid = low + (high-low)/2; 1.319 + if(map->array[mid].key < key) 1.320 + low = mid + 1; 1.321 + else 1.322 + high = mid; 1.323 + } 1.324 + if(map->array[low].key == key) 1.325 + { 1.326 + if(low < map->size-1) 1.327 + memmove(&map->array[low], &map->array[low+1], 1.328 + (map->size-1-low)*sizeof(map->array[0])); 1.329 + map->size--; 1.330 + } 1.331 + } 1.332 +} 1.333 + 1.334 +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) 1.335 +{ 1.336 + if(map->size > 0) 1.337 + { 1.338 + ALsizei low = 0; 1.339 + ALsizei high = map->size - 1; 1.340 + while(low < high) 1.341 + { 1.342 + ALsizei mid = low + (high-low)/2; 1.343 + if(map->array[mid].key < key) 1.344 + low = mid + 1; 1.345 + else 1.346 + high = mid; 1.347 + } 1.348 + if(map->array[low].key == key) 1.349 + return map->array[low].value; 1.350 + } 1.351 + return NULL; 1.352 +}