aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c462
-rw-r--r--Alc/helpers.c328
-rw-r--r--CMakeLists.txt1
-rw-r--r--OpenAL32/Include/alMain.h23
4 files changed, 422 insertions, 392 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 06294392..f766f726 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -46,9 +46,6 @@ DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,
#include <stdio.h>
#include <memory.h>
#include <ctype.h>
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
#include "alMain.h"
#include "alSource.h"
@@ -63,13 +60,6 @@ DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,
#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
-struct BackendInfo {
- const char *name;
- ALCboolean (*Init)(BackendFuncs*);
- void (*Deinit)(void);
- void (*Probe)(enum DevProbe);
- BackendFuncs Funcs;
-};
static struct BackendInfo BackendList[] = {
#ifdef HAVE_PULSEAUDIO
{ "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
@@ -364,7 +354,7 @@ static ALCchar *alcAllDeviceList;
static size_t alcAllDeviceListSize;
static ALCchar *alcCaptureDeviceList;
static size_t alcCaptureDeviceListSize;
-// Default is always the first in the list
+/* Default is always the first in the list */
static ALCchar *alcDefaultDeviceSpecifier;
static ALCchar *alcDefaultAllDeviceSpecifier;
static ALCchar *alcCaptureDefaultDeviceSpecifier;
@@ -416,10 +406,10 @@ static const ALchar alExtList[] =
"AL_SOFT_loop_points AL_SOFTX_non_virtual_channels";
// Mixing Priority Level
-static ALint RTPrioLevel;
+ALint RTPrioLevel;
// Output Log File
-static FILE *LogFile;
+FILE *LogFile;
// Output Log Level
#ifdef _DEBUG
@@ -434,6 +424,9 @@ ALdouble ConeScale = 0.5;
// Localized Z scalar for mono sources
ALdouble ZScale = 1.0;
+/* One-time configuration init control */
+static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
+
///////////////////////////////////////////////////////
@@ -442,6 +435,7 @@ ALdouble ZScale = 1.0;
static void ReleaseALC(ALCboolean doclose);
static void alc_initconfig(void);
+#define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
#if defined(_WIN32)
static void alc_init(void);
@@ -693,24 +687,6 @@ static void alc_initconfig(void)
}
}
-#ifdef _WIN32
-typedef LONG pthread_once_t;
-#define PTHREAD_ONCE_INIT 0
-
-static void pthread_once(pthread_once_t *once, void (*callback)(void))
-{
- LONG ret;
- while((ret=InterlockedExchange(once, 1)) == 1)
- Sleep(0);
- if(ret == 0)
- callback();
- InterlockedExchange(once, 2);
-}
-#endif
-
-static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-#define DO_INITCONFIG() pthread_once(&once_control, alc_initconfig)
-
static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
{
@@ -725,11 +701,11 @@ static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
PlaybackBackend.Probe(type);
}
-static void ProbeDeviceList()
+static void ProbeDeviceList(void)
{ ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }
-static void ProbeAllDeviceList()
+static void ProbeAllDeviceList(void)
{ ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }
-static void ProbeCaptureDeviceList()
+static void ProbeCaptureDeviceList(void)
{ ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
@@ -765,170 +741,85 @@ DECL_APPEND_LIST_FUNC(CaptureDevice)
#undef DECL_APPEND_LIST_FUNC
-void al_print(const char *fname, unsigned int line, const char *fmt, ...)
+/* Sets the default channel order used by most non-WaveFormatEx-based APIs */
+void SetDefaultChannelOrder(ALCdevice *device)
{
- const char *fn;
- char str[256];
- int i;
-
- fn = strrchr(fname, '/');
- if(!fn) fn = strrchr(fname, '\\');
- if(!fn) fn = fname;
- else fn += 1;
-
- i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
- if(i < (int)sizeof(str) && i > 0)
+ switch(device->FmtChans)
{
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(str+i, sizeof(str)-i, fmt, ap);
- va_end(ap);
- }
- str[sizeof(str)-1] = 0;
-
- fprintf(LogFile, "%s", str);
- fflush(LogFile);
-}
-
-void SetRTPriority(void)
-{
- ALboolean failed;
+ case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT;
+ device->DevChannels[4] = FRONT_CENTER;
+ device->DevChannels[5] = LFE;
+ return;
-#ifdef _WIN32
- if(RTPrioLevel > 0)
- failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- else
- failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
-#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__)
- struct sched_param param;
+ case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT;
+ device->DevChannels[4] = FRONT_CENTER;
+ device->DevChannels[5] = LFE;
+ device->DevChannels[6] = SIDE_LEFT;
+ device->DevChannels[7] = SIDE_RIGHT;
+ return;
- if(RTPrioLevel > 0)
- {
- /* Use the minimum real-time priority possible for now (on Linux this
- * should be 1 for SCHED_RR) */
- param.sched_priority = sched_get_priority_min(SCHED_RR);
- failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
- }
- else
- {
- param.sched_priority = 0;
- failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
+ /* Same as WFX order */
+ case DevFmtMono:
+ case DevFmtStereo:
+ case DevFmtQuad:
+ case DevFmtX51Side:
+ case DevFmtX61:
+ break;
}
-#else
- /* Real-time priority not available */
- failed = (RTPrioLevel>0);
-#endif
- if(failed)
- ERR("Failed to set priority level for thread\n");
-}
-
-
-void InitUIntMap(UIntMap *map)
-{
- map->array = NULL;
- map->size = 0;
- map->maxsize = 0;
-}
-
-void ResetUIntMap(UIntMap *map)
-{
- free(map->array);
- map->array = NULL;
- map->size = 0;
- map->maxsize = 0;
+ SetDefaultWFXChannelOrder(device);
}
-
-ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
+/* Sets the default order used by WaveFormatEx */
+void SetDefaultWFXChannelOrder(ALCdevice *device)
{
- ALsizei pos = 0;
-
- if(map->size > 0)
- {
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
- else
- high = mid;
- }
- if(map->array[low].key < key)
- low++;
- pos = low;
- }
-
- if(pos == map->size || map->array[pos].key != key)
+ switch(device->FmtChans)
{
- if(map->size == map->maxsize)
- {
- ALvoid *temp;
- ALsizei newsize;
+ case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
- newsize = (map->maxsize ? (map->maxsize<<1) : 4);
- if(newsize < map->maxsize)
- return AL_OUT_OF_MEMORY;
+ case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT; break;
- temp = realloc(map->array, newsize*sizeof(map->array[0]));
- if(!temp) return AL_OUT_OF_MEMORY;
- map->array = temp;
- map->maxsize = newsize;
- }
+ case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT; break;
- map->size++;
- if(pos < map->size-1)
- memmove(&map->array[pos+1], &map->array[pos],
- (map->size-1-pos)*sizeof(map->array[0]));
- }
- map->array[pos].key = key;
- map->array[pos].value = value;
+ case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_LEFT;
+ device->DevChannels[5] = BACK_RIGHT; break;
- return AL_NO_ERROR;
-}
+ case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = SIDE_LEFT;
+ device->DevChannels[5] = SIDE_RIGHT; break;
-void RemoveUIntMapKey(UIntMap *map, ALuint key)
-{
- if(map->size > 0)
- {
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
- else
- high = mid;
- }
- if(map->array[low].key == key)
- {
- if(low < map->size-1)
- memmove(&map->array[low], &map->array[low+1],
- (map->size-1-low)*sizeof(map->array[0]));
- map->size--;
- }
- }
-}
+ case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_CENTER;
+ device->DevChannels[5] = SIDE_LEFT;
+ device->DevChannels[6] = SIDE_RIGHT; break;
-ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
-{
- if(map->size > 0)
- {
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
- else
- high = mid;
- }
- if(map->array[low].key == key)
- return map->array[low].value;
+ case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_LEFT;
+ device->DevChannels[5] = BACK_RIGHT;
+ device->DevChannels[6] = SIDE_LEFT;
+ device->DevChannels[7] = SIDE_RIGHT; break;
}
- return NULL;
}
@@ -1098,130 +989,6 @@ static ALCboolean IsValidALCChannels(ALCenum channels)
}
-#ifndef _WIN32
-void InitializeCriticalSection(CRITICAL_SECTION *cs)
-{
- pthread_mutexattr_t attrib;
- int ret;
-
- ret = pthread_mutexattr_init(&attrib);
- assert(ret == 0);
-
- ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
-#ifdef HAVE_PTHREAD_NP_H
- if(ret != 0)
- ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
-#endif
- assert(ret == 0);
- ret = pthread_mutex_init(cs, &attrib);
- assert(ret == 0);
-
- pthread_mutexattr_destroy(&attrib);
-}
-void DeleteCriticalSection(CRITICAL_SECTION *cs)
-{
- int ret;
- ret = pthread_mutex_destroy(cs);
- assert(ret == 0);
-}
-void EnterCriticalSection(CRITICAL_SECTION *cs)
-{
- int ret;
- ret = pthread_mutex_lock(cs);
- assert(ret == 0);
-}
-void LeaveCriticalSection(CRITICAL_SECTION *cs)
-{
- int ret;
- ret = pthread_mutex_unlock(cs);
- assert(ret == 0);
-}
-
-/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
- * to the expected DWORD. Both are defined as unsigned 32-bit types, however.
- * Additionally, Win32 is supposed to measure the time since Windows started,
- * as opposed to the actual time. */
-ALuint timeGetTime(void)
-{
-#if _POSIX_TIMERS > 0
- struct timespec ts;
- int ret = -1;
-
-#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
-#if _POSIX_MONOTONIC_CLOCK == 0
- static int hasmono = 0;
- if(hasmono > 0 || (hasmono == 0 &&
- (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0))
-#endif
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
-#endif
- if(ret != 0)
- ret = clock_gettime(CLOCK_REALTIME, &ts);
- assert(ret == 0);
-
- return ts.tv_nsec/1000000 + ts.tv_sec*1000;
-#else
- struct timeval tv;
- int ret;
-
- ret = gettimeofday(&tv, NULL);
- assert(ret == 0);
-
- return tv.tv_usec/1000 + tv.tv_sec*1000;
-#endif
-}
-#endif
-
-#if defined(_WIN32)
-void *LoadLib(const char *name)
-{ return LoadLibraryA(name); }
-
-void CloseLib(void *handle)
-{ FreeLibrary((HANDLE)handle); }
-
-void *GetSymbol(void *handle, const char *name)
-{
- void *ret;
-
- ret = (void*)GetProcAddress((HANDLE)handle, name);
- if(ret == NULL)
- ERR("Failed to load %s\n", name);
- return ret;
-}
-
-#elif defined(HAVE_DLFCN_H)
-
-void *LoadLib(const char *name)
-{
- const char *err;
- void *handle;
-
- dlerror();
- handle = dlopen(name, RTLD_NOW);
- if((err=dlerror()) != NULL)
- handle = NULL;
- return handle;
-}
-
-void CloseLib(void *handle)
-{ dlclose(handle); }
-
-void *GetSymbol(void *handle, const char *name)
-{
- const char *err;
- void *sym;
-
- dlerror();
- sym = dlsym(handle, name);
- if((err=dlerror()) != NULL)
- {
- ERR("Failed to load %s: %s\n", name, err);
- sym = NULL;
- }
- return sym;
-}
-#endif
-
static void LockLists(void)
{
EnterCriticalSection(&ListLock);
@@ -2481,87 +2248,6 @@ ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
}
-// Sets the default channel order used by most non-WaveFormatEx-based APIs
-void SetDefaultChannelOrder(ALCdevice *device)
-{
- switch(device->FmtChans)
- {
- case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT;
- device->DevChannels[4] = FRONT_CENTER;
- device->DevChannels[5] = LFE;
- return;
-
- case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT;
- device->DevChannels[4] = FRONT_CENTER;
- device->DevChannels[5] = LFE;
- device->DevChannels[6] = SIDE_LEFT;
- device->DevChannels[7] = SIDE_RIGHT;
- return;
-
- /* Same as WFX order */
- case DevFmtMono:
- case DevFmtStereo:
- case DevFmtQuad:
- case DevFmtX51Side:
- case DevFmtX61:
- break;
- }
- SetDefaultWFXChannelOrder(device);
-}
-// Sets the default order used by WaveFormatEx
-void SetDefaultWFXChannelOrder(ALCdevice *device)
-{
- switch(device->FmtChans)
- {
- case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
-
- case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT; break;
-
- case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT; break;
-
- case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_LEFT;
- device->DevChannels[5] = BACK_RIGHT; break;
-
- case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = SIDE_LEFT;
- device->DevChannels[5] = SIDE_RIGHT; break;
-
- case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_CENTER;
- device->DevChannels[5] = SIDE_LEFT;
- device->DevChannels[6] = SIDE_RIGHT; break;
-
- case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_LEFT;
- device->DevChannels[5] = BACK_RIGHT;
- device->DevChannels[6] = SIDE_LEFT;
- device->DevChannels[7] = SIDE_RIGHT; break;
- }
-}
-
static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)
{
if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)
diff --git a/Alc/helpers.c b/Alc/helpers.c
new file mode 100644
index 00000000..f4a91c53
--- /dev/null
+++ b/Alc/helpers.c
@@ -0,0 +1,328 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2011 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include "alMain.h"
+
+#ifdef _WIN32
+void pthread_once(pthread_once_t *once, void (*callback)(void))
+{
+ LONG ret;
+ while((ret=InterlockedExchange(once, 1)) == 1)
+ Sleep(0);
+ if(ret == 0)
+ callback();
+ InterlockedExchange(once, 2);
+}
+
+void *LoadLib(const char *name)
+{ return LoadLibraryA(name); }
+void CloseLib(void *handle)
+{ FreeLibrary((HANDLE)handle); }
+void *GetSymbol(void *handle, const char *name)
+{
+ void *ret;
+
+ ret = (void*)GetProcAddress((HANDLE)handle, name);
+ if(ret == NULL)
+ ERR("Failed to load %s\n", name);
+ return ret;
+}
+
+#else
+
+void InitializeCriticalSection(CRITICAL_SECTION *cs)
+{
+ pthread_mutexattr_t attrib;
+ int ret;
+
+ ret = pthread_mutexattr_init(&attrib);
+ assert(ret == 0);
+
+ ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
+#ifdef HAVE_PTHREAD_NP_H
+ if(ret != 0)
+ ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
+#endif
+ assert(ret == 0);
+ ret = pthread_mutex_init(cs, &attrib);
+ assert(ret == 0);
+
+ pthread_mutexattr_destroy(&attrib);
+}
+void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+ int ret;
+ ret = pthread_mutex_destroy(cs);
+ assert(ret == 0);
+}
+void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ int ret;
+ ret = pthread_mutex_lock(cs);
+ assert(ret == 0);
+}
+void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+ int ret;
+ ret = pthread_mutex_unlock(cs);
+ assert(ret == 0);
+}
+
+/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
+ * to the expected DWORD. Both are defined as unsigned 32-bit types, however.
+ * Additionally, Win32 is supposed to measure the time since Windows started,
+ * as opposed to the actual time. */
+ALuint timeGetTime(void)
+{
+#if _POSIX_TIMERS > 0
+ struct timespec ts;
+ int ret = -1;
+
+#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
+#if _POSIX_MONOTONIC_CLOCK == 0
+ static int hasmono = 0;
+ if(hasmono > 0 || (hasmono == 0 &&
+ (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0))
+#endif
+ ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+#endif
+ if(ret != 0)
+ ret = clock_gettime(CLOCK_REALTIME, &ts);
+ assert(ret == 0);
+
+ return ts.tv_nsec/1000000 + ts.tv_sec*1000;
+#else
+ struct timeval tv;
+ int ret;
+
+ ret = gettimeofday(&tv, NULL);
+ assert(ret == 0);
+
+ return tv.tv_usec/1000 + tv.tv_sec*1000;
+#endif
+}
+
+#ifdef HAVE_DLFCN_H
+
+void *LoadLib(const char *name)
+{
+ const char *err;
+ void *handle;
+
+ dlerror();
+ handle = dlopen(name, RTLD_NOW);
+ if((err=dlerror()) != NULL)
+ handle = NULL;
+ return handle;
+}
+void CloseLib(void *handle)
+{ dlclose(handle); }
+void *GetSymbol(void *handle, const char *name)
+{
+ const char *err;
+ void *sym;
+
+ dlerror();
+ sym = dlsym(handle, name);
+ if((err=dlerror()) != NULL)
+ {
+ ERR("Failed to load %s: %s\n", name, err);
+ sym = NULL;
+ }
+ return sym;
+}
+
+#endif
+#endif
+
+
+void al_print(const char *fname, unsigned int line, const char *fmt, ...)
+{
+ const char *fn;
+ char str[256];
+ int i;
+
+ fn = strrchr(fname, '/');
+ if(!fn) fn = strrchr(fname, '\\');
+ if(!fn) fn = fname;
+ else fn += 1;
+
+ i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
+ if(i < (int)sizeof(str) && i > 0)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(str+i, sizeof(str)-i, fmt, ap);
+ va_end(ap);
+ }
+ str[sizeof(str)-1] = 0;
+
+ fprintf(LogFile, "%s", str);
+ fflush(LogFile);
+}
+
+
+void SetRTPriority(void)
+{
+ ALboolean failed;
+
+#ifdef _WIN32
+ if(RTPrioLevel > 0)
+ failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ else
+ failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__)
+ struct sched_param param;
+
+ if(RTPrioLevel > 0)
+ {
+ /* Use the minimum real-time priority possible for now (on Linux this
+ * should be 1 for SCHED_RR) */
+ param.sched_priority = sched_get_priority_min(SCHED_RR);
+ failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
+ }
+ else
+ {
+ param.sched_priority = 0;
+ failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
+ }
+#else
+ /* Real-time priority not available */
+ failed = (RTPrioLevel>0);
+#endif
+ if(failed)
+ ERR("Failed to set priority level for thread\n");
+}
+
+
+void InitUIntMap(UIntMap *map)
+{
+ map->array = NULL;
+ map->size = 0;
+ map->maxsize = 0;
+}
+
+void ResetUIntMap(UIntMap *map)
+{
+ free(map->array);
+ map->array = NULL;
+ map->size = 0;
+ map->maxsize = 0;
+}
+
+ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
+{
+ ALsizei pos = 0;
+
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key < key)
+ low++;
+ pos = low;
+ }
+
+ if(pos == map->size || map->array[pos].key != key)
+ {
+ if(map->size == map->maxsize)
+ {
+ ALvoid *temp;
+ ALsizei newsize;
+
+ newsize = (map->maxsize ? (map->maxsize<<1) : 4);
+ if(newsize < map->maxsize)
+ return AL_OUT_OF_MEMORY;
+
+ temp = realloc(map->array, newsize*sizeof(map->array[0]));
+ if(!temp) return AL_OUT_OF_MEMORY;
+ map->array = temp;
+ map->maxsize = newsize;
+ }
+
+ map->size++;
+ if(pos < map->size-1)
+ memmove(&map->array[pos+1], &map->array[pos],
+ (map->size-1-pos)*sizeof(map->array[0]));
+ }
+ map->array[pos].key = key;
+ map->array[pos].value = value;
+
+ return AL_NO_ERROR;
+}
+
+void RemoveUIntMapKey(UIntMap *map, ALuint key)
+{
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key == key)
+ {
+ if(low < map->size-1)
+ memmove(&map->array[low], &map->array[low+1],
+ (map->size-1-low)*sizeof(map->array[0]));
+ map->size--;
+ }
+ }
+}
+
+ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
+{
+ if(map->size > 0)
+ {
+ ALsizei low = 0;
+ ALsizei high = map->size - 1;
+ while(low < high)
+ {
+ ALsizei mid = low + (high-low)/2;
+ if(map->array[mid].key < key)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if(map->array[low].key == key)
+ return map->array[low].value;
+ }
+ return NULL;
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d343a62..3783a176 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -384,6 +384,7 @@ SET(ALC_OBJS Alc/ALc.c
Alc/alcRing.c
Alc/alcThread.c
Alc/bs2b.c
+ Alc/helpers.c
Alc/hrtf.c
Alc/mixer.c
Alc/panning.c
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 9a6c0c2b..8265380e 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -178,6 +178,10 @@ void *LoadLib(const char *name);
void CloseLib(void *handle);
void *GetSymbol(void *handle, const char *name);
+typedef LONG pthread_once_t;
+#define PTHREAD_ONCE_INIT 0
+void pthread_once(pthread_once_t *once, void (*callback)(void));
+
#else
#include <unistd.h>
@@ -259,6 +263,12 @@ static __inline ALuint NextPowerOf2(ALuint value)
}
+enum DevProbe {
+ DEVICE_PROBE,
+ ALL_DEVICE_PROBE,
+ CAPTURE_DEVICE_PROBE
+};
+
typedef struct {
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
void (*ClosePlayback)(ALCdevice*);
@@ -273,10 +283,12 @@ typedef struct {
ALCuint (*AvailableSamples)(ALCdevice*);
} BackendFuncs;
-enum DevProbe {
- DEVICE_PROBE,
- ALL_DEVICE_PROBE,
- CAPTURE_DEVICE_PROBE
+struct BackendInfo {
+ const char *name;
+ ALCboolean (*Init)(BackendFuncs*);
+ void (*Deinit)(void);
+ void (*Probe)(enum DevProbe);
+ BackendFuncs Funcs;
};
ALCboolean alc_alsa_init(BackendFuncs *func_list);
@@ -544,6 +556,7 @@ void al_print(const char *fname, unsigned int line, const char *fmt, ...)
PRINTF_STYLE(3,4);
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
+extern FILE *LogFile;
enum LogLevel {
NoLog,
LogError,
@@ -571,6 +584,8 @@ extern enum LogLevel LogLevel;
extern ALdouble ConeScale;
extern ALdouble ZScale;
+extern ALint RTPrioLevel;
+
#ifdef __cplusplus
}
#endif