aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c1117
-rw-r--r--Alc/alcConfig.c283
-rw-r--r--Alc/alcThread.c125
-rw-r--r--Alc/alsa.c828
-rw-r--r--Alc/dsound.c294
-rw-r--r--Alc/oss.c328
-rw-r--r--Alc/winmm.c421
-rw-r--r--Alu/ALu.c677
-rw-r--r--CMakeConf/.empty0
-rw-r--r--CMakeLists.txt256
-rw-r--r--COPYING484
-rw-r--r--OpenAL32/Include/alBuffer.h32
-rw-r--r--OpenAL32/Include/alError.h16
-rw-r--r--OpenAL32/Include/alExtension.h33
-rw-r--r--OpenAL32/Include/alListener.h23
-rw-r--r--OpenAL32/Include/alMain.h170
-rw-r--r--OpenAL32/Include/alSource.h71
-rw-r--r--OpenAL32/Include/alState.h14
-rw-r--r--OpenAL32/Include/alThunk.h42
-rw-r--r--OpenAL32/Include/alu.h26
-rw-r--r--OpenAL32/OpenAL32.c75
-rw-r--r--OpenAL32/alBuffer.c989
-rw-r--r--OpenAL32/alError.c61
-rw-r--r--OpenAL32/alExtension.c274
-rw-r--r--OpenAL32/alListener.c513
-rw-r--r--OpenAL32/alSource.c2108
-rw-r--r--OpenAL32/alState.c677
-rw-r--r--OpenAL32/alThunk.c108
-rw-r--r--Router/OpenAL32.cpp135
-rw-r--r--Router/OpenAL32.h341
-rw-r--r--Router/OpenAL32.rc101
-rw-r--r--Router/al.cpp981
-rw-r--r--Router/alList.cpp1029
-rw-r--r--Router/alList.h433
-rw-r--r--Router/alc.cpp2332
-rw-r--r--Router/resource.h15
-rw-r--r--RouterTest/main.cpp647
-rw-r--r--config.h.in43
-rw-r--r--include/AL/al.h724
-rw-r--r--include/AL/alc.h281
-rw-r--r--include/COPYING483
-rw-r--r--openalrc.sample51
42 files changed, 17641 insertions, 0 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
new file mode 100644
index 00000000..2adcbb8e
--- /dev/null
+++ b/Alc/ALc.c
@@ -0,0 +1,1117 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+///////////////////////////////////////////////////////
+// DEBUG INFORMATION
+
+#ifdef _DEBUG
+ char szDebug[256];
+#endif
+
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// FUNCTION PROTOTYPES
+
+void fill_device_list();
+
+void alc_alsa_init(BackendFuncs *func_list);
+void alc_oss_init(BackendFuncs *func_list);
+void alcDSoundInit(BackendFuncs *func_list);
+void alcWinMMInit(BackendFuncs *FuncList);
+
+#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+struct {
+ const char *name;
+ void (*Init)(BackendFuncs*);
+ BackendFuncs Funcs;
+} BackendList[] = {
+#ifdef HAVE_ALSA
+ { "alsa", alc_alsa_init, EmptyFuncs },
+#endif
+#ifdef HAVE_OSS
+ { "oss", alc_oss_init, EmptyFuncs },
+#endif
+#ifdef HAVE_DSOUND
+ { "dsound", alcDSoundInit, EmptyFuncs },
+#endif
+#ifdef HAVE_WINMM
+ { "winmm", alcWinMMInit, EmptyFuncs },
+#endif
+
+ { NULL, NULL, EmptyFuncs }
+};
+#undef EmptyFuncs
+
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// STRING and EXTENSIONS
+
+typedef struct ALCextension_struct
+{
+ ALCchar *extName;
+ ALvoid *address;
+} ALCextension;
+
+typedef struct ALCfunction_struct
+{
+ ALCchar *funcName;
+ ALvoid *address;
+} ALCfunction;
+
+static ALCextension alcExtensions[] = {
+ { "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
+ { "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
+ { "ALC_EXT_CAPTURE", (ALvoid *) NULL },
+ { NULL, (ALvoid *) NULL }
+};
+
+static ALCfunction alcFunctions[] = {
+ { "alcCreateContext", (ALvoid *) alcCreateContext },
+ { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
+ { "alcProcessContext", (ALvoid *) alcProcessContext },
+ { "alcSuspendContext", (ALvoid *) alcSuspendContext },
+ { "alcDestroyContext", (ALvoid *) alcDestroyContext },
+ { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
+ { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
+ { "alcOpenDevice", (ALvoid *) alcOpenDevice },
+ { "alcCloseDevice", (ALvoid *) alcCloseDevice },
+ { "alcGetError", (ALvoid *) alcGetError },
+ { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
+ { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
+ { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
+ { "alcGetString", (ALvoid *) alcGetString },
+ { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
+ { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
+ { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
+ { "alcCaptureStart", (ALvoid *) alcCaptureStart },
+ { "alcCaptureStop", (ALvoid *) alcCaptureStop },
+ { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
+ { NULL, (ALvoid *) NULL }
+};
+
+static ALenums enumeration[]={
+ // Types
+ { (ALchar *)"ALC_INVALID", ALC_INVALID },
+ { (ALchar *)"ALC_FALSE", ALC_FALSE },
+ { (ALchar *)"ALC_TRUE", ALC_TRUE },
+
+ // ALC Properties
+ { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
+ { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
+ { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
+ { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
+ { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
+ { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
+ { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
+ { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
+ { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
+ { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
+ { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
+ { (ALchar *)"ALC_SYNC", ALC_SYNC },
+ { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
+ { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
+ { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
+ { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER },
+ { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
+
+ // ALC Error Message
+ { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
+ { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
+ { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
+ { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
+ { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
+ { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
+ { (ALchar *)NULL, (ALenum)0 }
+};
+// Error strings
+static const ALCchar alcNoError[] = "No Error";
+static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
+static const ALCchar alcErrInvalidContext[] = "Invalid Context";
+static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
+static const ALCchar alcErrInvalidValue[] = "Invalid Value";
+static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
+
+// Context strings
+static ALCchar alcDeviceList[2048];
+static ALCchar alcAllDeviceList[2048];
+static ALCchar alcCaptureDeviceList[2048];
+// Default is always the first in the list
+static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
+static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
+static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
+
+
+static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
+static ALCint alcMajorVersion = 1;
+static ALCint alcMinorVersion = 1;
+
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// Global Variables
+
+// Critical Section data
+extern CRITICAL_SECTION g_mutex;
+
+// Context List
+static ALCcontext *g_pContextList = NULL;
+static ALCuint g_ulContextCount = 0;
+
+// Context Error
+static ALCenum g_eLastContextError = ALC_NO_ERROR;
+
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// ALC Related helper functions
+
+ALCchar *AppendDeviceList(char *name)
+{
+ static int pos;
+ ALCchar *ret = alcDeviceList+pos;
+ pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos, "%s", name) + 1;
+ return ret;
+}
+
+ALCchar *AppendAllDeviceList(char *name)
+{
+ static int pos;
+ ALCchar *ret = alcAllDeviceList+pos;
+ pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos, "%s", name) + 1;
+ return ret;
+}
+
+ALCchar *AppendCaptureDeviceList(char *name)
+{
+ static int pos;
+ ALCchar *ret = alcCaptureDeviceList+pos;
+ pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos, "%s", name) + 1;
+ return ret;
+}
+
+/*
+ IsContext
+
+ Check pContext is a valid Context pointer
+*/
+ALCboolean IsContext(ALCcontext *pContext)
+{
+ ALCcontext *pTempContext;
+
+ pTempContext = g_pContextList;
+ while (pTempContext && pTempContext != pContext)
+ pTempContext = pTempContext->next;
+
+ return (pTempContext ? ALC_TRUE : ALC_FALSE);
+}
+
+
+/*
+ SetALCError
+
+ Store latest ALC Error
+*/
+ALCvoid SetALCError(ALenum errorCode)
+{
+ g_eLastContextError = errorCode;
+}
+
+
+/*
+ SuspendContext
+
+ Thread-safe entry
+*/
+ALCvoid SuspendContext(ALCcontext *pContext)
+{
+ (void)pContext;
+ EnterCriticalSection(&g_mutex);
+}
+
+
+/*
+ ProcessContext
+
+ Thread-safe exit
+*/
+ALCvoid ProcessContext(ALCcontext *pContext)
+{
+ (void)pContext;
+ LeaveCriticalSection(&g_mutex);
+}
+
+
+/*
+ InitContext
+
+ Initialize Context variables
+*/
+static ALvoid InitContext(ALCcontext *pContext)
+{
+ //Initialise listener
+ pContext->Listener.Gain = 1.0f;
+ pContext->Listener.Position[0] = 0.0f;
+ pContext->Listener.Position[1] = 0.0f;
+ pContext->Listener.Position[2] = 0.0f;
+ pContext->Listener.Velocity[0] = 0.0f;
+ pContext->Listener.Velocity[1] = 0.0f;
+ pContext->Listener.Velocity[2] = 0.0f;
+ pContext->Listener.Forward[0] = 0.0f;
+ pContext->Listener.Forward[1] = 0.0f;
+ pContext->Listener.Forward[2] = -1.0f;
+ pContext->Listener.Up[0] = 0.0f;
+ pContext->Listener.Up[1] = 1.0f;
+ pContext->Listener.Up[2] = 0.0f;
+
+ //Validate pContext
+ pContext->LastError = AL_NO_ERROR;
+ pContext->InUse = AL_FALSE;
+
+ //Set output format
+ pContext->Frequency = pContext->Device->Frequency;
+
+ //Set globals
+ pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
+ pContext->DopplerFactor = 1.0f;
+ pContext->DopplerVelocity = 1.0f;
+ pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
+
+ pContext->lNumStereoSources = 1;
+ pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
+
+ strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
+}
+
+
+/*
+ ExitContext
+
+ Clean up Context, destroy any remaining Sources
+*/
+static ALCvoid ExitContext(ALCcontext *pContext)
+{
+ unsigned int i;
+ ALsource *ALSource;
+ ALsource *ALTempSource;
+
+#ifdef _DEBUG
+ if (pContext->SourceCount>0)
+ {
+ sprintf(szDebug,"OpenAL32 : alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
+ OutputDebugString(szDebug);
+ }
+#endif
+
+ // Free all the Sources still remaining
+ ALSource = pContext->Source;
+ for (i = 0; i < pContext->SourceCount; i++)
+ {
+ ALTempSource = ALSource->next;
+ ALTHUNK_REMOVEENTRY(ALSource->source);
+ memset(ALSource, 0, sizeof(ALsource));
+ free(ALSource);
+ ALSource = ALTempSource;
+ }
+
+ //Invalidate context
+ pContext->LastError = AL_NO_ERROR;
+ pContext->InUse = AL_FALSE;
+}
+
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// ALC Functions calls
+
+
+// This should probably move to another c file but for now ...
+ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
+{
+ ALCboolean DeviceFound = ALC_FALSE;
+ ALCdevice *pDevice = NULL;
+ ALCint i;
+
+ fill_device_list();
+
+ pDevice = malloc(sizeof(ALCdevice));
+ if (pDevice)
+ {
+ if (SampleSize > 0)
+ {
+ //Initialise device structure
+ memset(pDevice, 0, sizeof(ALCdevice));
+
+ //Validate device
+ pDevice->InUse = AL_TRUE;
+ pDevice->IsCaptureDevice = AL_TRUE;
+
+ pDevice->Frequency = frequency;
+ pDevice->Format = format;
+ pDevice->Channels = aluChannelsFromFormat(format);
+ pDevice->FrameSize = aluBytesFromFormat(format) *
+ pDevice->Channels;
+
+ for(i = 0;BackendList[i].Init;i++)
+ {
+ pDevice->Funcs = &BackendList[i].Funcs;
+ if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
+ {
+ DeviceFound = ALC_TRUE;
+ break;
+ }
+ }
+ }
+ else
+ SetALCError(ALC_INVALID_VALUE);
+
+ if(!DeviceFound)
+ {
+ free(pDevice);
+ pDevice = NULL;
+ }
+ }
+ else
+ SetALCError(ALC_OUT_OF_MEMORY);
+
+ return pDevice;
+}
+
+ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
+{
+ ALCboolean bReturn = ALC_FALSE;
+
+ if ((pDevice)&&(pDevice->IsCaptureDevice))
+ {
+ ALCdevice_CloseCapture(pDevice);
+ free(pDevice);
+
+ bReturn = ALC_TRUE;
+ }
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+
+ return bReturn;
+}
+
+ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
+{
+ if ((pDevice)&&(pDevice->IsCaptureDevice))
+ ALCdevice_StartCapture(pDevice);
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+}
+
+ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
+{
+ if ((pDevice)&&(pDevice->IsCaptureDevice))
+ ALCdevice_StopCapture(pDevice);
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+}
+
+ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
+{
+ if ((pDevice) && (pDevice->IsCaptureDevice))
+ ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+}
+
+/*
+ alcGetError
+
+ Return last ALC generated error code
+*/
+ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
+{
+ ALCenum errorCode;
+
+ (void)device;
+
+ errorCode = g_eLastContextError;
+ g_eLastContextError = ALC_NO_ERROR;
+ return errorCode;
+}
+
+
+/*
+ alcSuspendContext
+
+ Not functional
+*/
+ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
+{
+ // Not a lot happens here !
+ (void)pContext;
+}
+
+
+/*
+ alcProcessContext
+
+ Not functional
+*/
+ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
+{
+ // Not a lot happens here !
+ (void)pContext;
+}
+
+
+/*
+ alcGetString
+
+ Returns information about the Device, and error strings
+*/
+ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
+{
+ const ALCchar *value = NULL;
+
+ fill_device_list();
+
+ switch (param)
+ {
+ case ALC_NO_ERROR:
+ value = alcNoError;
+ break;
+
+ case ALC_INVALID_ENUM:
+ value = alcErrInvalidEnum;
+ break;
+
+ case ALC_INVALID_VALUE:
+ value = alcErrInvalidValue;
+ break;
+
+ case ALC_INVALID_DEVICE:
+ value = alcErrInvalidDevice;
+ break;
+
+ case ALC_INVALID_CONTEXT:
+ value = alcErrInvalidContext;
+ break;
+
+ case ALC_OUT_OF_MEMORY:
+ value = alcErrOutOfMemory;
+ break;
+
+ case ALC_DEFAULT_DEVICE_SPECIFIER:
+ value = alcDefaultDeviceSpecifier;
+ break;
+
+ case ALC_DEVICE_SPECIFIER:
+ if (pDevice)
+ value = pDevice->szDeviceName;
+ else
+ value = alcDeviceList;
+ break;
+
+ case ALC_ALL_DEVICES_SPECIFIER:
+ value = alcAllDeviceList;
+ break;
+
+ case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
+ value = alcDefaultAllDeviceSpecifier;
+ break;
+
+ case ALC_CAPTURE_DEVICE_SPECIFIER:
+ if (pDevice)
+ value = pDevice->szDeviceName;
+ else
+ value = alcCaptureDeviceList;
+ break;
+
+ case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
+ value = alcCaptureDefaultDeviceSpecifier;
+ break;
+
+ case ALC_EXTENSIONS:
+ value = alcExtensionList;
+ break;
+
+ default:
+ SetALCError(ALC_INVALID_ENUM);
+ break;
+ }
+
+ return value;
+}
+
+
+/*
+ alcGetIntegerv
+
+ Returns information about the Device and the version of Open AL
+*/
+ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
+{
+ fill_device_list();
+
+ if ((device)&&(device->IsCaptureDevice))
+ {
+ SuspendContext(NULL);
+
+ // Capture device
+ switch (param)
+ {
+ case ALC_CAPTURE_SAMPLES:
+ if ((size) && (data))
+ *data = ALCdevice_AvailableSamples(device);
+ else
+ SetALCError(ALC_INVALID_VALUE);
+ break;
+
+ default:
+ SetALCError(ALC_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(NULL);
+ }
+ else
+ {
+ if(data)
+ {
+ // Playback Device
+ switch (param)
+ {
+ case ALC_MAJOR_VERSION:
+ if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = alcMajorVersion;
+ break;
+
+ case ALC_MINOR_VERSION:
+ if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = alcMinorVersion;
+ break;
+
+ case ALC_ATTRIBUTES_SIZE:
+ if(!device)
+ SetALCError(ALC_INVALID_DEVICE);
+ else if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = 11;
+ break;
+
+ case ALC_ALL_ATTRIBUTES:
+ if(!device)
+ SetALCError(ALC_INVALID_DEVICE);
+ else if (size < 7)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ {
+ int i = 0;
+
+ data[i++] = ALC_FREQUENCY;
+ data[i++] = device->Frequency;
+
+ data[i++] = ALC_REFRESH;
+ data[i++] = device->UpdateFreq;
+
+ data[i++] = ALC_SYNC;
+ data[i++] = ALC_FALSE;
+
+ SuspendContext(NULL);
+ if(device->Context && size >= 11)
+ {
+ data[i++] = ALC_MONO_SOURCES;
+ data[i++] = device->Context->lNumMonoSources;
+
+ data[i++] = ALC_STEREO_SOURCES;
+ data[i++] = device->Context->lNumStereoSources;
+ }
+ ProcessContext(NULL);
+
+ data[i++] = 0;
+ }
+ break;
+
+ case ALC_FREQUENCY:
+ if(!device)
+ SetALCError(ALC_INVALID_DEVICE);
+ else if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = device->Frequency;
+ break;
+
+ case ALC_REFRESH:
+ if(!device)
+ SetALCError(ALC_INVALID_DEVICE);
+ else if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = device->UpdateFreq;
+ break;
+
+ case ALC_SYNC:
+ if(!device)
+ SetALCError(ALC_INVALID_DEVICE);
+ else if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = ALC_FALSE;
+ break;
+
+ default:
+ SetALCError(ALC_INVALID_ENUM);
+ break;
+ }
+ }
+ else if(size)
+ SetALCError(ALC_INVALID_VALUE);
+ }
+
+ return;
+}
+
+
+/*
+ alcIsExtensionPresent
+
+ Determines if there is support for a particular extension
+*/
+ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
+{
+ ALCboolean bResult = ALC_FALSE;
+ ALsizei i = 0;
+
+ (void)device;
+
+ if (extName)
+ {
+ while(alcExtensions[i].extName &&
+ strcasecmp(alcExtensions[i].extName,extName) != 0)
+ i++;
+
+ if (alcExtensions[i].extName)
+ bResult = ALC_TRUE;
+ }
+ else
+ SetALCError(ALC_INVALID_VALUE);
+
+ return bResult;
+}
+
+
+/*
+ alcGetProcAddress
+
+ Retrieves the function address for a particular extension function
+*/
+ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
+{
+ ALCvoid *pFunction = NULL;
+ ALsizei i = 0;
+
+ (void)device;
+
+ if (funcName)
+ {
+ while(alcFunctions[i].funcName &&
+ strcmp(alcFunctions[i].funcName,funcName) != 0)
+ i++;
+ pFunction = alcFunctions[i].address;
+ }
+ else
+ SetALCError(ALC_INVALID_VALUE);
+
+ return pFunction;
+}
+
+
+/*
+ alcGetEnumValue
+
+ Get the value for a particular ALC Enumerated Value
+*/
+ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
+{
+ ALsizei i = 0;
+ ALCenum val;
+
+ (void)device;
+
+ while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
+ i++;
+ val = enumeration[i].value;
+
+ if(!enumeration[i].enumName)
+ SetALCError(ALC_INVALID_VALUE);
+
+ return val;
+}
+
+
+/*
+ alcCreateContext
+
+ Create and attach a Context to a particular Device.
+*/
+ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
+{
+ ALCcontext *ALContext = NULL;
+ ALuint ulAttributeIndex, ulRequestedStereoSources;
+
+ if ((device)&&(!device->IsCaptureDevice))
+ {
+ // Reset Context Last Error code
+ g_eLastContextError = ALC_NO_ERROR;
+
+ // Current implementation only allows one Context per Device
+ if(!device->Context)
+ {
+ ALContext = calloc(1, sizeof(ALCcontext));
+ if(!ALContext)
+ {
+ SetALCError(ALC_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ ALContext->Device = device;
+ InitContext(ALContext);
+
+ device->Context = ALContext;
+
+ SuspendContext(NULL);
+
+ ALContext->next = g_pContextList;
+ g_pContextList = ALContext;
+ g_ulContextCount++;
+
+ ProcessContext(NULL);
+
+ // Check for Voice Count attributes
+ if (attrList)
+ {
+ ulAttributeIndex = 0;
+ while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
+ {
+ if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
+ {
+ ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
+
+ if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
+ ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
+
+ ALContext->lNumStereoSources = ulRequestedStereoSources;
+ ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
+ break;
+ }
+
+ ulAttributeIndex += 2;
+ }
+ }
+ }
+ else
+ {
+ SetALCError(ALC_INVALID_VALUE);
+ ALContext = NULL;
+ }
+ }
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+
+ return ALContext;
+}
+
+
+/*
+ alcDestroyContext
+
+ Remove a Context
+*/
+ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
+{
+ ALCcontext **list;
+
+ // Lock context list
+ SuspendContext(NULL);
+
+ if (IsContext(context))
+ {
+ // Lock context
+ SuspendContext(context);
+
+ context->Device->Context = NULL;
+
+ list = &g_pContextList;
+ while(*list != context)
+ list = &(*list)->next;
+
+ *list = (*list)->next;
+ g_ulContextCount--;
+
+ // Unlock context
+ ProcessContext(context);
+
+ ExitContext(context);
+
+ // Free memory (MUST do this after ProcessContext)
+ memset(context, 0, sizeof(ALCcontext));
+ free(context);
+ }
+ else
+ SetALCError(ALC_INVALID_CONTEXT);
+
+ ProcessContext(NULL);
+}
+
+
+/*
+ alcGetCurrentContext
+
+ Returns the currently active Context
+*/
+ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
+{
+ ALCcontext *pContext = NULL;
+
+ SuspendContext(NULL);
+
+ pContext = g_pContextList;
+ while ((pContext) && (!pContext->InUse))
+ pContext = pContext->next;
+
+ ProcessContext(NULL);
+
+ return pContext;
+}
+
+
+/*
+ alcGetContextsDevice
+
+ Returns the Device that a particular Context is attached to
+*/
+ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
+{
+ ALCdevice *pDevice = NULL;
+
+ SuspendContext(NULL);
+ if (IsContext(pContext))
+ pDevice = pContext->Device;
+ else
+ SetALCError(ALC_INVALID_CONTEXT);
+ ProcessContext(NULL);
+
+ return pDevice;
+}
+
+
+/*
+ alcMakeContextCurrent
+
+ Makes the given Context the active Context
+*/
+ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
+{
+ ALCcontext *ALContext;
+ ALboolean bReturn = AL_TRUE;
+
+ SuspendContext(NULL);
+
+ // context must be a valid Context or NULL
+ if ((IsContext(context)) || (context == NULL))
+ {
+ if ((ALContext=alcGetCurrentContext()))
+ {
+ SuspendContext(ALContext);
+ ALContext->InUse=AL_FALSE;
+ ProcessContext(ALContext);
+ }
+
+ if ((ALContext=context) && (ALContext->Device))
+ {
+ SuspendContext(ALContext);
+ ALContext->InUse=AL_TRUE;
+ ProcessContext(ALContext);
+ }
+ }
+ else
+ {
+ SetALCError(ALC_INVALID_CONTEXT);
+ bReturn = AL_FALSE;
+ }
+
+ ProcessContext(NULL);
+
+ return bReturn;
+}
+
+
+/*
+ alcOpenDevice
+
+ Open the Device specified.
+*/
+ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
+{
+ ALboolean bDeviceFound = AL_FALSE;
+ ALCdevice *device;
+ ALint i;
+
+ fill_device_list();
+
+ device = malloc(sizeof(ALCdevice));
+ if (device)
+ {
+ const char *fmt;
+
+ //Initialise device structure
+ memset(device, 0, sizeof(ALCdevice));
+
+ //Validate device
+ device->InUse = AL_TRUE;
+ device->IsCaptureDevice = AL_FALSE;
+
+ //Set output format
+ device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
+ if((ALint)device->Frequency <= 0)
+ device->Frequency = SWMIXER_OUTPUT_RATE;
+
+ fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
+ if(fmt[0])
+ device->Format = alGetEnumValue(fmt);
+ switch(device->Format)
+ {
+ case AL_FORMAT_MONO8:
+ device->Channels = 1;
+ device->FrameSize = 1;
+ break;
+ case AL_FORMAT_STEREO8:
+ device->Channels = 2;
+ device->FrameSize = 2;
+ break;
+ case AL_FORMAT_QUAD8:
+ device->Channels = 4;
+ device->FrameSize = 4;
+ break;
+ case AL_FORMAT_MONO16:
+ device->Channels = 1;
+ device->FrameSize = 2;
+ break;
+ case AL_FORMAT_STEREO16:
+ device->Channels = 2;
+ device->FrameSize = 4;
+ break;
+ case AL_FORMAT_QUAD16:
+ device->Channels = 4;
+ device->FrameSize = 8;
+ break;
+ default:
+ device->Format = AL_FORMAT_STEREO16;
+ device->Channels = 2;
+ device->FrameSize = 4;
+ break;
+ }
+
+ device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
+ if((ALint)device->UpdateFreq <= 0)
+ device->UpdateFreq = 8192 * device->Frequency / 22050;
+
+ // Find a playback device to open
+ for(i = 0;BackendList[i].Init;i++)
+ {
+ device->Funcs = &BackendList[i].Funcs;
+ if(ALCdevice_OpenPlayback(device, deviceName))
+ {
+ bDeviceFound = AL_TRUE;
+ break;
+ }
+ }
+
+ if (!bDeviceFound)
+ {
+ // No suitable output device found
+ free(device);
+ device = NULL;
+ }
+ }
+
+ return device;
+}
+
+
+/*
+ alcCloseDevice
+
+ Close the specified Device
+*/
+ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
+{
+ ALCboolean bReturn = ALC_FALSE;
+
+ if ((pDevice)&&(!pDevice->IsCaptureDevice))
+ {
+ ALCdevice_ClosePlayback(pDevice);
+
+ //Release device structure
+ memset(pDevice, 0, sizeof(ALCdevice));
+ free(pDevice);
+
+ bReturn = ALC_TRUE;
+ }
+ else
+ SetALCError(ALC_INVALID_DEVICE);
+
+ return bReturn;
+}
+///////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// ALC Device Specific Functions
+
+void fill_device_list()
+{
+ static int done = 0;
+ if(!done)
+ {
+ int i;
+ for(i = 0;BackendList[i].Init;i++)
+ BackendList[i].Init(&BackendList[i].Funcs);
+ done = 1;
+ }
+}
diff --git a/Alc/alcConfig.c b/Alc/alcConfig.c
new file mode 100644
index 00000000..f20b5e4f
--- /dev/null
+++ b/Alc/alcConfig.c
@@ -0,0 +1,283 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+typedef struct ConfigEntry {
+ char *key;
+ char *value;
+} ConfigEntry;
+
+typedef struct ConfigBlock {
+ char *name;
+ ConfigEntry *entries;
+ size_t entryCount;
+} ConfigBlock;
+
+static ConfigBlock *cfgBlocks;
+static size_t cfgCount;
+
+static char buffer[1024];
+
+static void LoadConfigFromFile(FILE *f)
+{
+ ConfigBlock *curBlock = cfgBlocks;
+ ConfigEntry *ent;
+
+ while(fgets(buffer, sizeof(buffer), f))
+ {
+ size_t i = 0;
+
+ while(isspace(buffer[i]))
+ i++;
+ if(!buffer[i] || buffer[i] == '#')
+ continue;
+
+ memmove(buffer, buffer+i, strlen(buffer+i)+1);
+
+ if(buffer[0] == '[')
+ {
+ ConfigBlock *nextBlock;
+
+ i = 1;
+ while(buffer[i] && buffer[i] != ']')
+ i++;
+
+ if(!buffer[i])
+ {
+ fprintf(stderr, "openal: config parse error: bad line \"%s\"\n", buffer);
+ continue;
+ }
+ buffer[i] = 0;
+
+ do {
+ i++;
+ if(buffer[i] && !isspace(buffer[i]))
+ {
+ if(buffer[i] != '#')
+ fprintf(stderr, "openal: config warning: extra data after block: \"%s\"\n", buffer+i);
+ break;
+ }
+ } while(buffer[i]);
+
+ nextBlock = NULL;
+ for(i = 0;i < cfgCount;i++)
+ {
+ if(strcasecmp(cfgBlocks[i].name, buffer+1) == 0)
+ {
+ nextBlock = cfgBlocks+i;
+// printf("found block '%s'\n", nextBlock->name);
+ break;
+ }
+ }
+
+ if(!nextBlock)
+ {
+ nextBlock = realloc(cfgBlocks, (cfgCount+1)*sizeof(ConfigBlock));
+ if(!nextBlock)
+ {
+ fprintf(stderr, "openal: config parse error: error reallocating config blocks\n");
+ continue;
+ }
+ cfgBlocks = nextBlock;
+ nextBlock = cfgBlocks+cfgCount;
+ cfgCount++;
+
+ nextBlock->name = strdup(buffer+1);
+ nextBlock->entries = NULL;
+ nextBlock->entryCount = 0;
+
+// printf("found new block '%s'\n", nextBlock->name);
+ }
+ curBlock = nextBlock;
+ continue;
+ }
+
+ /* Look for the option name */
+ i = 0;
+ while(buffer[i] && buffer[i] != '#' && buffer[i] != '=' &&
+ !isspace(buffer[i]))
+ i++;
+
+ if(!buffer[i] || buffer[i] == '#' || i == 0)
+ {
+ fprintf(stderr, "openal: config parse error: malformed option line: \"%s\"\n", buffer);
+ continue;
+ }
+
+ /* Seperate the option */
+ if(buffer[i] != '=')
+ {
+ buffer[i++] = 0;
+
+ while(isspace(buffer[i]))
+ i++;
+ if(buffer[i] != '=')
+ {
+ fprintf(stderr, "openal: config parse error: option without a value: \"%s\"\n", buffer);
+ continue;
+ }
+ }
+ /* Find the start of the value */
+ buffer[i++] = 0;
+ while(isspace(buffer[i]))
+ i++;
+
+ /* Check if we already have this option set */
+ ent = curBlock->entries;
+ while((size_t)(ent-curBlock->entries) < curBlock->entryCount)
+ {
+ if(strcasecmp(ent->key, buffer) == 0)
+ break;
+ ent++;
+ }
+
+ if((size_t)(ent-curBlock->entries) >= curBlock->entryCount)
+ {
+ /* Allocate a new option entry */
+ ent = realloc(curBlock->entries, (curBlock->entryCount+1)*sizeof(ConfigEntry));
+ if(!ent)
+ {
+ fprintf(stderr, "openal: config parse error: error reallocating config entries\n");
+ continue;
+ }
+ curBlock->entries = ent;
+ ent = curBlock->entries + curBlock->entryCount;
+ curBlock->entryCount++;
+
+ ent->key = strdup(buffer);
+ ent->value = NULL;
+ }
+
+ /* Look for the end of the line (Null term, new-line, or #-symbol) and
+ eat up the trailing whitespace */
+ memmove(buffer, buffer+i, strlen(buffer+i)+1);
+
+ i = 0;
+ while(buffer[i] && buffer[i] != '#' && buffer[i] != '\n')
+ i++;
+ do {
+ i--;
+ } while(isspace(buffer[i]));
+ buffer[++i] = 0;
+
+ free(ent->value);
+ ent->value = strdup(buffer);
+
+// printf("found '%s' = '%s'\n", ent->key, ent->value);
+ }
+}
+
+void ReadALConfig(void)
+{
+ FILE *f;
+
+ cfgBlocks = calloc(1, sizeof(ConfigBlock));
+ cfgBlocks->name = strdup("general");
+ cfgCount = 1;
+
+#ifdef _WIN32
+#else
+ f = fopen("/etc/openal/config", "r");
+ if(f)
+ {
+ LoadConfigFromFile(f);
+ fclose(f);
+ }
+ if(getenv("HOME") && *(getenv("HOME")))
+ {
+ snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME"));
+ f = fopen(buffer, "r");
+ if(f)
+ {
+ LoadConfigFromFile(f);
+ fclose(f);
+ }
+ }
+#endif
+}
+
+void FreeALConfig(void)
+{
+ size_t i;
+
+ for(i = 0;i < cfgCount;i++)
+ {
+ size_t j;
+ for(j = 0;j < cfgBlocks[i].entryCount;j++)
+ {
+ free(cfgBlocks[i].entries[j].key);
+ free(cfgBlocks[i].entries[j].value);
+ }
+ free(cfgBlocks[i].entries);
+ free(cfgBlocks[i].name);
+ }
+ free(cfgBlocks);
+ cfgBlocks = NULL;
+ cfgCount = 0;
+}
+
+const char *GetConfigValue(const char *blockName, const char *keyName, const char *def)
+{
+ size_t i, j;
+
+ if(keyName)
+ {
+ if(!blockName)
+ blockName = "general";
+
+ for(i = 0;i < cfgCount;i++)
+ {
+ if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
+ continue;
+
+ for(j = 0;j < cfgBlocks[i].entryCount;j++)
+ {
+ if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
+ return cfgBlocks[i].entries[j].value;
+ }
+ }
+ }
+
+ return def;
+}
+
+int GetConfigValueInt(const char *blockName, const char *keyName, int def)
+{
+ const char *val = GetConfigValue(blockName, keyName, "");
+
+ if(!val[0]) return def;
+ return strtol(val, NULL, 0);
+}
+
+float GetConfigValueFloat(const char *blockName, const char *keyName, float def)
+{
+ const char *val = GetConfigValue(blockName, keyName, "");
+
+ if(!val[0]) return def;
+#ifdef HAVE_STRTOF
+ return strtof(val, NULL);
+#else
+ return (float)strtod(val, NULL);
+#endif
+}
diff --git a/Alc/alcThread.c b/Alc/alcThread.c
new file mode 100644
index 00000000..6752f702
--- /dev/null
+++ b/Alc/alcThread.c
@@ -0,0 +1,125 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+
+#include "alMain.h"
+#include "alThunk.h"
+
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+typedef struct {
+ ALuint (*func)(ALvoid*);
+ ALvoid *ptr;
+ HANDLE thread;
+} ThreadInfo;
+
+static DWORD CALLBACK StarterFunc(void *ptr)
+{
+ ThreadInfo *inf = (ThreadInfo*)ptr;
+ ALint ret;
+
+ ret = inf->func(inf->ptr);
+ ExitThread((DWORD)ret);
+
+ return (DWORD)ret;
+}
+
+ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
+{
+ ThreadInfo *inf = malloc(sizeof(ThreadInfo));
+ if(!inf) return 0;
+
+ inf->func = func;
+ inf->ptr = ptr;
+
+ inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, NULL);
+ if(!inf->thread)
+ {
+ free(inf);
+ return NULL;
+ }
+
+ return inf;
+}
+
+ALuint StopThread(ALvoid *thread)
+{
+ ThreadInfo *inf = thread;
+ DWORD ret = 0;
+
+ WaitForSingleObject(inf->thread, INFINITE);
+ GetExitCodeThread(inf->thread, &ret);
+
+ free(inf);
+
+ return (ALuint)ret;
+}
+
+#else
+
+#include <pthread.h>
+
+typedef struct {
+ ALuint (*func)(ALvoid*);
+ ALvoid *ptr;
+ pthread_t thread;
+} ThreadInfo;
+
+static void *StarterFunc(void *ptr)
+{
+ ThreadInfo *inf = (ThreadInfo*)ptr;
+ ALint ret;
+
+ ret = inf->func(inf->ptr);
+ return (void*)ret;
+}
+
+ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
+{
+ ThreadInfo *inf = malloc(sizeof(ThreadInfo));
+ if(!inf) return 0;
+
+ inf->func = func;
+ inf->ptr = ptr;
+ if(pthread_create(&inf->thread, NULL, StarterFunc, inf) != 0)
+ {
+ free(inf);
+ return NULL;
+ }
+
+ return inf;
+}
+
+ALuint StopThread(ALvoid *thread)
+{
+ ThreadInfo *inf = thread;
+ void *ret;
+
+ pthread_join(inf->thread, &ret);
+ free(inf);
+
+ return (ALuint)ret;
+}
+
+#endif
diff --git a/Alc/alsa.c b/Alc/alsa.c
new file mode 100644
index 00000000..df866a66
--- /dev/null
+++ b/Alc/alsa.c
@@ -0,0 +1,828 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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>
+#include <stdio.h>
+#include <memory.h>
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#include <alsa/asoundlib.h>
+
+
+typedef struct {
+ snd_pcm_t *pcmHandle;
+ snd_pcm_format_t format;
+ int killNow;
+ ALvoid *thread;
+} alsa_data;
+
+typedef struct {
+ ALCchar *name;
+ int card, dev;
+} DevMap;
+
+static void *alsa_handle;
+#define MAKE_FUNC(f) static typeof(f) * p##f
+MAKE_FUNC(snd_strerror);
+MAKE_FUNC(snd_pcm_open);
+MAKE_FUNC(snd_pcm_close);
+MAKE_FUNC(snd_pcm_nonblock);
+MAKE_FUNC(snd_pcm_frames_to_bytes);
+MAKE_FUNC(snd_pcm_hw_params_malloc);
+MAKE_FUNC(snd_pcm_hw_params_free);
+MAKE_FUNC(snd_pcm_hw_params_any);
+MAKE_FUNC(snd_pcm_hw_params_set_access);
+MAKE_FUNC(snd_pcm_hw_params_set_format);
+MAKE_FUNC(snd_pcm_hw_params_set_channels);
+MAKE_FUNC(snd_pcm_hw_params_set_periods_near);
+MAKE_FUNC(snd_pcm_hw_params_set_rate_near);
+MAKE_FUNC(snd_pcm_hw_params_set_rate);
+MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
+MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
+MAKE_FUNC(snd_pcm_hw_params);
+MAKE_FUNC(snd_pcm_prepare);
+MAKE_FUNC(snd_pcm_start);
+MAKE_FUNC(snd_pcm_resume);
+MAKE_FUNC(snd_pcm_state);
+MAKE_FUNC(snd_pcm_avail_update);
+MAKE_FUNC(snd_pcm_areas_silence);
+MAKE_FUNC(snd_pcm_mmap_begin);
+MAKE_FUNC(snd_pcm_mmap_commit);
+MAKE_FUNC(snd_pcm_drain);
+MAKE_FUNC(snd_pcm_info_malloc);
+MAKE_FUNC(snd_pcm_info_free);
+MAKE_FUNC(snd_pcm_info_set_device);
+MAKE_FUNC(snd_pcm_info_set_subdevice);
+MAKE_FUNC(snd_pcm_info_set_stream);
+MAKE_FUNC(snd_pcm_info_get_name);
+MAKE_FUNC(snd_ctl_pcm_next_device);
+MAKE_FUNC(snd_ctl_pcm_info);
+MAKE_FUNC(snd_ctl_open);
+MAKE_FUNC(snd_ctl_close);
+MAKE_FUNC(snd_ctl_card_info_malloc);
+MAKE_FUNC(snd_ctl_card_info_free);
+MAKE_FUNC(snd_ctl_card_info);
+MAKE_FUNC(snd_ctl_card_info_get_name);
+MAKE_FUNC(snd_card_next);
+#undef MAKE_FUNC
+
+#define MAX_DEVICES 16
+#define MAX_ALL_DEVICES 32
+
+static DevMap allDevNameMap[MAX_ALL_DEVICES];
+static ALCchar *alsaDeviceList[MAX_DEVICES];
+static ALCchar *alsaCaptureDeviceList[MAX_DEVICES];
+
+static int xrun_recovery(snd_pcm_t *handle, int err)
+{
+ if (err == -EPIPE)
+ { /* under-run */
+ err = psnd_pcm_prepare(handle);
+ if(err >= 0)
+ err = psnd_pcm_start(handle);
+ if (err < 0)
+ printf("Can't recover from underrun, prepare failed: %s\n", psnd_strerror(err));
+ }
+ else if (err == -ESTRPIPE)
+ {
+ while ((err = psnd_pcm_resume(handle)) == -EAGAIN)
+ usleep(1); /* wait until the suspend flag is released */
+ if (err < 0)
+ {
+ err = psnd_pcm_prepare(handle);
+ if(err >= 0)
+ err = psnd_pcm_start(handle);
+ if (err < 0)
+ printf("Can't recover from suspend, prepare failed: %s\n", psnd_strerror(err));
+ }
+ }
+ return err;
+}
+
+
+static ALuint ALSAProc(ALvoid *ptr)
+{
+ ALCdevice *pDevice = (ALCdevice*)ptr;
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ const snd_pcm_channel_area_t *areas = NULL;
+ snd_pcm_sframes_t avail, commitres;
+ snd_pcm_uframes_t offset, frames;
+ char *WritePtr;
+ int WriteCnt;
+ int err;
+
+ while(!data->killNow)
+ {
+ snd_pcm_state_t state = psnd_pcm_state(data->pcmHandle);
+ if(state == SND_PCM_STATE_XRUN)
+ {
+ err = xrun_recovery(data->pcmHandle, -EPIPE);
+ if (err < 0)
+ {
+ fprintf(stderr, "XRUN recovery failed: %s\n", psnd_strerror(err));
+ break;
+ }
+ }
+ else if (state == SND_PCM_STATE_SUSPENDED)
+ {
+ err = xrun_recovery(data->pcmHandle, -ESTRPIPE);
+ if (err < 0)
+ {
+ fprintf(stderr, "SUSPEND recovery failed: %s\n", psnd_strerror(err));
+ break;
+ }
+ }
+
+ avail = psnd_pcm_avail_update(data->pcmHandle);
+ if(avail < 0)
+ {
+ err = xrun_recovery(data->pcmHandle, avail);
+ if (err < 0)
+ {
+ fprintf(stderr, "available update failed: %s\n", psnd_strerror(err));
+ break;
+ }
+ }
+
+ // make sure there's frames to process
+ if(avail == 0)
+ {
+ usleep(1000);
+ continue;
+ }
+
+ // it is possible that contiguous areas are smaller, thus we use a loop
+ while (avail > 0)
+ {
+ frames = avail;
+
+ err = psnd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames);
+ if (err < 0)
+ {
+ err = xrun_recovery(data->pcmHandle, err);
+ if (err < 0)
+ fprintf(stderr, "mmap begin error: %s\n", psnd_strerror(err));
+ break;
+ }
+
+ SuspendContext(NULL);
+ if(pDevice->Context)
+ {
+ // If we have an active context, mix data directly into output
+ // buffer
+ WritePtr = (char*)areas->addr + (offset * areas->step / 8);
+ WriteCnt = psnd_pcm_frames_to_bytes(data->pcmHandle, frames);
+
+ aluMixData(pDevice->Context, WritePtr, WriteCnt, pDevice->Format);
+ }
+ else
+ psnd_pcm_areas_silence(areas, offset, pDevice->Channels, frames, data->format);
+ ProcessContext(NULL);
+
+ commitres = psnd_pcm_mmap_commit(data->pcmHandle, offset, frames);
+ if (commitres < 0 || (commitres-frames) != 0)
+ {
+ fprintf(stderr, "mmap commit error: %s\n",
+ psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
+ break;
+ }
+
+ avail -= frames;
+ }
+ }
+
+ return 0;
+}
+
+static void fill_silence(snd_pcm_t *pcmHandle, snd_pcm_format_t alsaFormat, int channels)
+{
+ const snd_pcm_channel_area_t *areas = NULL;
+ snd_pcm_sframes_t avail, commitres;
+ snd_pcm_uframes_t offset, frames;
+ int err;
+
+ avail = psnd_pcm_avail_update(pcmHandle);
+ if(avail < 0)
+ {
+ err = xrun_recovery(pcmHandle, avail);
+ if (err < 0)
+ {
+ fprintf(stderr, "available update failed: %s\n", psnd_strerror(err));
+ return;
+ }
+ }
+
+ // it is possible that contiguous areas are smaller, thus we use a loop
+ while (avail > 0)
+ {
+ frames = avail;
+
+ err = psnd_pcm_mmap_begin(pcmHandle, &areas, &offset, &frames);
+ if (err < 0)
+ {
+ err = xrun_recovery(pcmHandle, err);
+ if (err < 0)
+ {
+ fprintf(stderr, "mmap begin error: %s\n", psnd_strerror(err));
+ break;
+ }
+ continue;
+ }
+
+ psnd_pcm_areas_silence(areas, offset, channels, frames, alsaFormat);
+
+ commitres = psnd_pcm_mmap_commit(pcmHandle, offset, frames);
+ if (commitres < 0 || (commitres-frames) != 0)
+ {
+ fprintf(stderr, "mmap commit error: %s\n",
+ psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
+ break;
+ }
+
+ avail -= frames;
+ }
+}
+
+static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
+{
+ snd_pcm_uframes_t bufferSizeInFrames;
+ snd_pcm_hw_params_t *p = NULL;
+ unsigned int periods;
+ alsa_data *data;
+ char driver[64];
+ int i;
+
+ strncpy(driver, GetConfigValue("alsa", "default", "default"), sizeof(driver)-1);
+ driver[sizeof(driver)-1] = 0;
+ if(deviceName)
+ {
+ size_t idx;
+
+ for(idx = 0;idx < MAX_ALL_DEVICES;idx++)
+ {
+ if(allDevNameMap[idx].name &&
+ strcmp(deviceName, allDevNameMap[idx].name) == 0)
+ {
+ if(idx > 0)
+ sprintf(driver, "hw:%d,%d", allDevNameMap[idx].card, allDevNameMap[idx].dev);
+ goto open_alsa;
+ }
+ }
+ for(idx = 0;idx < MAX_DEVICES;idx++)
+ {
+ if(alsaDeviceList[idx] &&
+ strcmp(deviceName, alsaDeviceList[idx]) == 0)
+ {
+ if(idx > 0)
+ sprintf(driver, "hw:%d,0", idx-1);
+ goto open_alsa;
+ }
+ }
+ return ALC_FALSE;
+ }
+
+ if(deviceName)
+ strcpy(device->szDeviceName, deviceName);
+ else
+ strcpy(device->szDeviceName, alsaDeviceList[0]);
+
+open_alsa:
+ data = (alsa_data*)calloc(1, sizeof(alsa_data));
+
+ i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ if(i < 0)
+ {
+ usleep(200000);
+ i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ }
+ if(i >= 0)
+ {
+ i = psnd_pcm_nonblock(data->pcmHandle, 0);
+ if(i < 0)
+ psnd_pcm_close(data->pcmHandle);
+ }
+ if(i < 0)
+ {
+ free(data);
+ return ALC_FALSE;
+ }
+
+ switch(device->Format)
+ {
+ case AL_FORMAT_MONO8:
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_QUAD8:
+ data->format = SND_PCM_FORMAT_U8;
+ break;
+ case AL_FORMAT_MONO16:
+ case AL_FORMAT_STEREO16:
+ case AL_FORMAT_QUAD16:
+ data->format = SND_PCM_FORMAT_S16;
+ break;
+ default:
+ data->format = SND_PCM_FORMAT_UNKNOWN;
+ fprintf(stderr, "Unknown format?! %x\n", device->Format);
+ }
+
+ periods = GetConfigValueInt("alsa", "periods", 4);
+ if((int)periods <= 0)
+ periods = 4;
+ bufferSizeInFrames = device->UpdateFreq;
+
+ psnd_pcm_hw_params_malloc(&p);
+#define ok(func, str) (i=(func),((i<0)?fprintf(stderr,"%s failed: %s\n", str, psnd_strerror(i)),0:1))
+ /* start with the largest configuration space possible */
+ if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
+ /* set interleaved access */
+ ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") &&
+ /* set format (implicitly sets sample bits) */
+ ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->format), "set format") &&
+ /* set channels (implicitly sets frame bits) */
+ ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, device->Channels), "set channels") &&
+ /* set periods (implicitly constrains period/buffer parameters) */
+ ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near") &&
+ /* set rate (implicitly constrains period/buffer parameters) */
+ ok(psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &device->Frequency, NULL), "set rate near") &&
+ /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
+ ok(psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames), "set buffer size near") &&
+ /* install and prepare hardware configuration */
+ ok(psnd_pcm_hw_params(data->pcmHandle, p), "set params")))
+ {
+ psnd_pcm_hw_params_free(p);
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+#undef ok
+ psnd_pcm_hw_params_free(p);
+
+ device->MaxNoOfSources = 256;
+ device->UpdateFreq = bufferSizeInFrames;
+
+ i = psnd_pcm_prepare(data->pcmHandle);
+ if(i < 0)
+ {
+ fprintf(stderr, "prepare error: %s\n", psnd_strerror(i));
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+
+ fill_silence(data->pcmHandle, data->format, device->Channels);
+ i = psnd_pcm_start(data->pcmHandle);
+ if(i < 0)
+ {
+ fprintf(stderr, "start error: %s\n", psnd_strerror(i));
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+
+ device->ExtraData = data;
+ data->thread = StartThread(ALSAProc, device);
+ if(data->thread == NULL)
+ {
+ psnd_pcm_close(data->pcmHandle);
+ device->ExtraData = NULL;
+ free(data);
+ return ALC_FALSE;
+ }
+
+ return ALC_TRUE;
+}
+
+static void alsa_close_playback(ALCdevice *device)
+{
+ alsa_data *data = (alsa_data*)device->ExtraData;
+ data->killNow = 1;
+ StopThread(data->thread);
+ psnd_pcm_close(data->pcmHandle);
+
+ free(data);
+ device->ExtraData = NULL;
+}
+
+
+static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
+{
+ snd_pcm_format_t alsaFormat;
+ snd_pcm_hw_params_t *p;
+ unsigned int periods = 4;
+ snd_pcm_uframes_t bufferSizeInFrames = SampleSize;
+ alsa_data *data;
+ char driver[64];
+ int i;
+
+ strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1);
+ driver[sizeof(driver)-1] = 0;
+ if(deviceName)
+ {
+ size_t idx;
+
+ for(idx = 0;idx < MAX_DEVICES;idx++)
+ {
+ if(alsaCaptureDeviceList[idx] &&
+ strcmp(deviceName, alsaCaptureDeviceList[idx]) == 0)
+ {
+ if(idx > 0)
+ sprintf(driver, "hw:%d,0", idx-1);
+ goto open_alsa;
+ }
+ }
+ return ALC_FALSE;
+ }
+
+ if(deviceName)
+ strcpy(pDevice->szDeviceName, deviceName);
+ else
+ strcpy(pDevice->szDeviceName, alsaCaptureDeviceList[0]);
+
+open_alsa:
+ data = (alsa_data*)calloc(1, sizeof(alsa_data));
+
+ i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
+ if(i < 0)
+ {
+ usleep(200000);
+ i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
+ }
+ if(i >= 0)
+ {
+ i = psnd_pcm_nonblock(data->pcmHandle, 0);
+ if(i < 0)
+ psnd_pcm_close(data->pcmHandle);
+ }
+ if(i < 0)
+ {
+ free(data);
+ return ALC_FALSE;
+ }
+
+ switch(aluBytesFromFormat(format))
+ {
+ case 1:
+ alsaFormat = SND_PCM_FORMAT_U8;
+ break;
+ case 2:
+ alsaFormat = SND_PCM_FORMAT_S16;
+ break;
+ default:
+ alsaFormat = SND_PCM_FORMAT_UNKNOWN;
+ fprintf(stderr, "Unknown format?! %x\n", format);
+ }
+
+ psnd_pcm_hw_params_malloc(&p);
+#define ok(func, str) (i=(func),((i<0)?fprintf(stderr,"%s failed\n", str),0:1))
+ /* start with the largest configuration space possible */
+ if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
+ /* set interleaved access */
+ ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") &&
+ /* set format (implicitly sets sample bits) */
+ ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, alsaFormat), "set format") &&
+ /* set channels (implicitly sets frame bits) */
+ ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, pDevice->Channels), "set channels") &&
+ /* set periods (implicitly constrains period/buffer parameters) */
+ ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near") &&
+ /* set rate (implicitly constrains period/buffer parameters) */
+ ok(psnd_pcm_hw_params_set_rate(data->pcmHandle, p, frequency, 0), "set rate") &&
+ /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
+ ok(psnd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, p, &bufferSizeInFrames), "set buffer size min") &&
+ /* install and prepare hardware configuration */
+ ok(psnd_pcm_hw_params(data->pcmHandle, p), "set params")))
+ {
+ psnd_pcm_hw_params_free(p);
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+#undef ok
+ psnd_pcm_hw_params_free(p);
+
+ i = psnd_pcm_prepare(data->pcmHandle);
+ if(i < 0)
+ {
+ fprintf(stderr, "prepare error: %s\n", psnd_strerror(i));
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+
+ pDevice->ExtraData = data;
+ return ALC_TRUE;
+}
+
+static void alsa_close_capture(ALCdevice *pDevice)
+{
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ psnd_pcm_close(data->pcmHandle);
+
+ free(data);
+ pDevice->ExtraData = NULL;
+}
+
+static void alsa_start_capture(ALCdevice *pDevice)
+{
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ psnd_pcm_start(data->pcmHandle);
+}
+
+static void alsa_stop_capture(ALCdevice *pDevice)
+{
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ psnd_pcm_drain(data->pcmHandle);
+}
+
+static void alsa_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
+{
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ const snd_pcm_channel_area_t *areas = NULL;
+ snd_pcm_sframes_t frames, commitres;
+ snd_pcm_uframes_t size, offset;
+ int err;
+
+ frames = psnd_pcm_avail_update(data->pcmHandle);
+ if(frames < 0)
+ {
+ err = xrun_recovery(data->pcmHandle, frames);
+ if (err < 0)
+ fprintf(stderr, "available update failed: %s\n", psnd_strerror(err));
+ else
+ frames = psnd_pcm_avail_update(data->pcmHandle);
+ }
+ if (frames < (snd_pcm_sframes_t)lSamples)
+ {
+ SetALCError(ALC_INVALID_VALUE);
+ return;
+ }
+
+ // it is possible that contiguous areas are smaller, thus we use a loop
+ while (lSamples > 0)
+ {
+ char *Pointer;
+ int Count;
+
+ size = lSamples;
+ err = psnd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &size);
+ if (err < 0)
+ {
+ err = xrun_recovery(data->pcmHandle, err);
+ if (err < 0)
+ {
+ fprintf(stderr, "mmap begin error: %s\n", psnd_strerror(err));
+ break;
+ }
+ continue;
+ }
+
+ Pointer = (char*)areas->addr + (offset * areas->step / 8);
+ Count = size * pDevice->FrameSize;
+
+ memcpy(pBuffer, Pointer, Count);
+ pBuffer = (char*)pBuffer + Count;
+
+ commitres = psnd_pcm_mmap_commit(data->pcmHandle, offset, size);
+ if (commitres < 0 || (commitres-size) != 0)
+ {
+ fprintf(stderr, "mmap commit error: %s\n",
+ psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
+ break;
+ }
+
+ lSamples -= size;
+ }
+}
+
+static ALCuint alsa_available_samples(ALCdevice *pDevice)
+{
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ snd_pcm_sframes_t frames = psnd_pcm_avail_update(data->pcmHandle);
+ if(frames < 0)
+ {
+ int err = xrun_recovery(data->pcmHandle, frames);
+ if (err < 0)
+ fprintf(stderr, "available update failed: %s\n", psnd_strerror(err));
+ else
+ frames = psnd_pcm_avail_update(data->pcmHandle);
+ if(frames < 0) /* ew.. */
+ SetALCError(ALC_INVALID_DEVICE);
+ }
+ return max(frames, 0);
+}
+
+
+BackendFuncs alsa_funcs = {
+ alsa_open_playback,
+ alsa_close_playback,
+ alsa_open_capture,
+ alsa_close_capture,
+ alsa_start_capture,
+ alsa_stop_capture,
+ alsa_capture_samples,
+ alsa_available_samples
+};
+
+void alc_alsa_init(BackendFuncs *func_list)
+{
+#define error(...) do { \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+}while(0)
+ snd_ctl_t *handle;
+ int card, err, dev, idx = 1;
+ snd_ctl_card_info_t *info;
+ snd_pcm_info_t *pcminfo;
+ snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
+ char name[128];
+ char *str;
+
+ *func_list = alsa_funcs;
+
+#ifdef HAVE_DLFCN_H
+ alsa_handle = dlopen("libasound.so.2", RTLD_NOW);
+ if(!alsa_handle)
+ return;
+ dlerror();
+
+#define LOAD_FUNC(f) do { \
+ p##f = (typeof(f)*)dlsym(alsa_handle, #f); \
+ if((str=dlerror()) != NULL) \
+ { \
+ dlclose(alsa_handle); \
+ alsa_handle = NULL; \
+ error("Could not load %s from libasound.so.2: %s", #f, str); \
+ return; \
+ } \
+} while(0)
+#else
+ str = NULL;
+ alsa_handle = NULL;
+#define LOAD_FUNC(f) p##f = f
+#endif
+
+LOAD_FUNC(snd_strerror);
+LOAD_FUNC(snd_pcm_open);
+LOAD_FUNC(snd_pcm_close);
+LOAD_FUNC(snd_pcm_nonblock);
+LOAD_FUNC(snd_pcm_frames_to_bytes);
+LOAD_FUNC(snd_pcm_hw_params_malloc);
+LOAD_FUNC(snd_pcm_hw_params_free);
+LOAD_FUNC(snd_pcm_hw_params_any);
+LOAD_FUNC(snd_pcm_hw_params_set_access);
+LOAD_FUNC(snd_pcm_hw_params_set_format);
+LOAD_FUNC(snd_pcm_hw_params_set_channels);
+LOAD_FUNC(snd_pcm_hw_params_set_periods_near);
+LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
+LOAD_FUNC(snd_pcm_hw_params_set_rate);
+LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
+LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
+LOAD_FUNC(snd_pcm_hw_params);
+LOAD_FUNC(snd_pcm_prepare);
+LOAD_FUNC(snd_pcm_start);
+LOAD_FUNC(snd_pcm_resume);
+LOAD_FUNC(snd_pcm_state);
+LOAD_FUNC(snd_pcm_avail_update);
+LOAD_FUNC(snd_pcm_areas_silence);
+LOAD_FUNC(snd_pcm_mmap_begin);
+LOAD_FUNC(snd_pcm_mmap_commit);
+LOAD_FUNC(snd_pcm_drain);
+
+LOAD_FUNC(snd_pcm_info_malloc);
+LOAD_FUNC(snd_pcm_info_free);
+LOAD_FUNC(snd_pcm_info_set_device);
+LOAD_FUNC(snd_pcm_info_set_subdevice);
+LOAD_FUNC(snd_pcm_info_set_stream);
+LOAD_FUNC(snd_pcm_info_get_name);
+LOAD_FUNC(snd_ctl_pcm_next_device);
+LOAD_FUNC(snd_ctl_pcm_info);
+LOAD_FUNC(snd_ctl_open);
+LOAD_FUNC(snd_ctl_close);
+LOAD_FUNC(snd_ctl_card_info_malloc);
+LOAD_FUNC(snd_ctl_card_info_free);
+LOAD_FUNC(snd_ctl_card_info);
+LOAD_FUNC(snd_ctl_card_info_get_name);
+LOAD_FUNC(snd_card_next);
+
+#undef LOAD_FUNC
+
+ psnd_ctl_card_info_malloc(&info);
+ psnd_pcm_info_malloc(&pcminfo);
+
+ card = -1;
+ if(psnd_card_next(&card) < 0 || card < 0)
+ error("no playback cards found...");
+ else
+ {
+ alsaDeviceList[0] = AppendDeviceList("ALSA Software on default");
+ allDevNameMap[0].name = AppendAllDeviceList("ALSA Software on default");
+ }
+
+ while (card >= 0) {
+ sprintf(name, "hw:%d", card);
+ if ((err = psnd_ctl_open(&handle, name, 0)) < 0) {
+ error("control open (%i): %s", card, psnd_strerror(err));
+ goto next_card;
+ }
+ if ((err = psnd_ctl_card_info(handle, info)) < 0) {
+ error("control hardware info (%i): %s", card, psnd_strerror(err));
+ psnd_ctl_close(handle);
+ goto next_card;
+ }
+ if(card < MAX_DEVICES-1) {
+ snprintf(name, sizeof(name), "ALSA Software on %s",
+ psnd_ctl_card_info_get_name(info));
+ alsaDeviceList[card+1] = AppendDeviceList(name);
+ }
+
+ dev = -1;
+ while (idx < MAX_ALL_DEVICES) {
+ if (psnd_ctl_pcm_next_device(handle, &dev)<0)
+ error("snd_ctl_pcm_next_device");
+ if (dev < 0)
+ break;
+ psnd_pcm_info_set_device(pcminfo, dev);
+ psnd_pcm_info_set_subdevice(pcminfo, 0);
+ psnd_pcm_info_set_stream(pcminfo, stream);
+ if ((err = psnd_ctl_pcm_info(handle, pcminfo)) < 0) {
+ if (err != -ENOENT)
+ error("control digital audio info (%i): %s", card, psnd_strerror(err));
+ continue;
+ }
+ snprintf(name, sizeof(name), "ALSA Software on %s [%s]",
+ psnd_ctl_card_info_get_name(info),
+ psnd_pcm_info_get_name(pcminfo));
+ allDevNameMap[idx].name = AppendAllDeviceList(name);
+ allDevNameMap[idx].card = card;
+ allDevNameMap[idx].dev = dev;
+ idx++;
+ }
+ psnd_ctl_close(handle);
+next_card:
+ if(psnd_card_next(&card) < 0) {
+ error("snd_card_next");
+ break;
+ }
+ }
+
+
+ stream = SND_PCM_STREAM_CAPTURE;
+
+ card = -1;
+ if(psnd_card_next(&card) < 0 || card < 0) {
+ error("no capture cards found...");
+ psnd_pcm_info_free(pcminfo);
+ psnd_ctl_card_info_free(info);
+ return;
+ }
+
+ alsaCaptureDeviceList[0] = AppendCaptureDeviceList("ALSA Capture on default");
+
+ while (card >= 0) {
+ sprintf(name, "hw:%d", card);
+ handle = NULL;
+ if ((err = psnd_ctl_open(&handle, name, 0)) < 0) {
+ error("control open (%i): %s", card, psnd_strerror(err));
+ }
+ if (err >= 0 && (err = psnd_ctl_card_info(handle, info)) < 0) {
+ error("control hardware info (%i): %s", card, psnd_strerror(err));
+ psnd_ctl_close(handle);
+ }
+ else if (err >= 0 && card < MAX_DEVICES-1)
+ {
+ snprintf(name, sizeof(name), "ALSA Capture on %s",
+ psnd_ctl_card_info_get_name(info));
+ alsaCaptureDeviceList[card+1] = AppendCaptureDeviceList(name);
+ }
+ if(handle) psnd_ctl_close(handle);
+ if(psnd_card_next(&card) < 0) {
+ error("snd_card_next");
+ break;
+ }
+ }
+ psnd_pcm_info_free(pcminfo);
+ psnd_ctl_card_info_free(info);
+#undef error
+}
diff --git a/Alc/dsound.c b/Alc/dsound.c
new file mode 100644
index 00000000..5d688567
--- /dev/null
+++ b/Alc/dsound.c
@@ -0,0 +1,294 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+
+#include <windows.h>
+#include <mmsystem.h>
+#include <dsound.h>
+
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+
+typedef struct {
+ // DirectSound Playback Device
+ LPDIRECTSOUND lpDS;
+ LPDIRECTSOUNDBUFFER DSpbuffer;
+ LPDIRECTSOUNDBUFFER DSsbuffer;
+ MMRESULT ulDSTimerID;
+} DSoundData;
+
+
+static ALCchar *DeviceList[16];
+
+static void CALLBACK DirectSoundProc(UINT uID,UINT uReserved,DWORD_PTR dwUser,DWORD_PTR dwReserved1,DWORD_PTR dwReserved2)
+{
+ static DWORD OldWriteCursor=0;
+
+ ALCdevice *pDevice = (ALCdevice *)dwUser;
+ DSoundData *pData = pDevice->ExtraData;
+ DWORD PlayCursor,WriteCursor;
+ BYTE *WritePtr1,*WritePtr2;
+ DWORD WriteCnt1,WriteCnt2;
+ WAVEFORMATEX OutputType;
+ DWORD BytesPlayed;
+ DWORD BufSize;
+ HRESULT DSRes;
+
+ (void)uID;
+ (void)uReserved;
+ (void)dwReserved1;
+ (void)dwReserved2;
+
+ BufSize = pDevice->UpdateFreq * pDevice->FrameSize;
+
+ // Get current play and write cursors
+ IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer,&PlayCursor,&WriteCursor);
+ if (!OldWriteCursor) OldWriteCursor=WriteCursor-PlayCursor;
+
+ // Get the output format and figure the number of bytes played (block aligned)
+ IDirectSoundBuffer_GetFormat(pData->DSsbuffer,&OutputType,sizeof(WAVEFORMATEX),NULL);
+ BytesPlayed=((((WriteCursor<OldWriteCursor)?(BufSize+WriteCursor-OldWriteCursor):(WriteCursor-OldWriteCursor))/OutputType.nBlockAlign)*OutputType.nBlockAlign);
+
+ // Lock output buffer started at 40msec in front of the old write cursor (15msec in front of the actual write cursor)
+ DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
+
+ // If the buffer is lost, restore it, play and lock
+ if (DSRes==DSERR_BUFFERLOST)
+ {
+ IDirectSoundBuffer_Restore(pData->DSsbuffer);
+ IDirectSoundBuffer_Play(pData->DSsbuffer,0,0,DSBPLAY_LOOPING);
+ DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
+ }
+
+ // Successfully locked the output buffer
+ if (DSRes==DS_OK)
+ {
+ // If we have an active context, mix data directly into output buffer otherwise fill with silence
+ SuspendContext(NULL);
+ if(pDevice->Context)
+ {
+ if (WritePtr1)
+ aluMixData(pDevice->Context, WritePtr1, WriteCnt1, pDevice->Format);
+ if (WritePtr2)
+ aluMixData(pDevice->Context, WritePtr2, WriteCnt2, pDevice->Format);
+ }
+ else
+ {
+ if (WritePtr1) memset(WritePtr1, 0, WriteCnt1);
+ if (WritePtr2) memset(WritePtr2, 0, WriteCnt2);
+ }
+ ProcessContext(NULL);
+
+ // Unlock output buffer only when successfully locked
+ IDirectSoundBuffer_Unlock(pData->DSsbuffer,WritePtr1,WriteCnt1,WritePtr2,WriteCnt2);
+ }
+
+ // Update old write cursor location
+ OldWriteCursor=((OldWriteCursor+BytesPlayed)%BufSize);
+}
+
+
+static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
+{
+ DSBUFFERDESC DSBDescription;
+ DSoundData *pData = NULL;
+ WAVEFORMATEX OutputType;
+ HRESULT hr;
+
+ if(deviceName)
+ {
+ int i;
+ for(i = 0;DeviceList[i];i++)
+ {
+ if(strcmp(deviceName, DeviceList[i]) == 0)
+ break;
+ }
+ if(!DeviceList[i])
+ return ALC_FALSE;
+ }
+
+ //Platform specific
+ memset(&OutputType, 0, sizeof(WAVEFORMATEX));
+ OutputType.wFormatTag = WAVE_FORMAT_PCM;
+ OutputType.nChannels = device->Channels;
+ OutputType.wBitsPerSample = (((device->Format==AL_FORMAT_MONO16)||(device->Format==AL_FORMAT_STEREO16)||(device->Format==AL_FORMAT_QUAD16))?16:8);
+ OutputType.nBlockAlign = OutputType.nChannels*OutputType.wBitsPerSample/8;
+ OutputType.nSamplesPerSec = device->Frequency;
+ OutputType.nAvgBytesPerSec = OutputType.nSamplesPerSec*OutputType.nBlockAlign;
+ OutputType.cbSize = 0;
+
+ //Initialise requested device
+
+ pData = calloc(1, sizeof(DSoundData));
+ if(!pData)
+ {
+ SetALCError(ALC_OUT_OF_MEMORY);
+ return ALC_FALSE;
+ }
+
+ //Init COM
+ CoInitialize(NULL);
+
+ //DirectSound Init code
+ hr = CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (LPVOID*)&pData->lpDS);
+ if(SUCCEEDED(hr))
+ hr = IDirectSound_Initialize(pData->lpDS, NULL);
+ if(SUCCEEDED(hr))
+ hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
+
+ if(SUCCEEDED(hr))
+ {
+ memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
+ DSBDescription.dwSize=sizeof(DSBUFFERDESC);
+ DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
+ hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL);
+ }
+ if(SUCCEEDED(hr))
+ hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType);
+
+ if(SUCCEEDED(hr))
+ {
+ memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
+ DSBDescription.dwSize=sizeof(DSBUFFERDESC);
+ DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
+ DSBDescription.dwBufferBytes=device->UpdateFreq * device->FrameSize;
+ DSBDescription.lpwfxFormat=&OutputType;
+ hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
+ }
+
+ if(SUCCEEDED(hr))
+ hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
+
+ if(FAILED(hr))
+ {
+ if (pData->DSsbuffer)
+ IDirectSoundBuffer_Release(pData->DSsbuffer);
+ if (pData->DSpbuffer)
+ IDirectSoundBuffer_Release(pData->DSpbuffer);
+ if (pData->lpDS)
+ IDirectSound_Release(pData->lpDS);
+
+ free(pData);
+ return ALC_FALSE;
+ }
+
+ pData->ulDSTimerID = timeSetEvent(25, 0, (LPTIMECALLBACK)DirectSoundProc, (DWORD)device, (UINT)TIME_CALLBACK_FUNCTION|TIME_PERIODIC);
+ device->MaxNoOfSources = 256;
+
+ if(deviceName)
+ strcpy(device->szDeviceName, deviceName);
+ else
+ strcpy(device->szDeviceName, DeviceList[0]);
+
+ device->ExtraData = pData;
+ return ALC_TRUE;
+}
+
+static void DSoundClosePlayback(ALCdevice *device)
+{
+ DSoundData *pData = device->ExtraData;
+
+ // Stop and release the DS timer
+ if (pData->ulDSTimerID)
+ timeKillEvent(pData->ulDSTimerID);
+
+ // Wait ... just in case any timer events happen
+ Sleep(100);
+
+ SuspendContext(NULL);
+
+ if (pData->DSsbuffer)
+ IDirectSoundBuffer_Release(pData->DSsbuffer);
+ if (pData->DSpbuffer)
+ IDirectSoundBuffer_Release(pData->DSpbuffer);
+ IDirectSound_Release(pData->lpDS);
+
+ //Deinit COM
+ CoUninitialize();
+
+ ProcessContext(NULL);
+
+ free(pData);
+ device->ExtraData = NULL;
+}
+
+
+static ALCboolean DSoundOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
+{
+ (void)pDevice;
+ (void)deviceName;
+ (void)frequency;
+ (void)format;
+ (void)SampleSize;
+ return ALC_FALSE;
+}
+
+static void DSoundCloseCapture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void DSoundStartCapture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void DSoundStopCapture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void DSoundCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
+{
+ (void)pDevice;
+ (void)pBuffer;
+ (void)lSamples;
+}
+
+static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
+{
+ (void)pDevice;
+ return 0;
+}
+
+
+BackendFuncs DSoundFuncs = {
+ DSoundOpenPlayback,
+ DSoundClosePlayback,
+ DSoundOpenCapture,
+ DSoundCloseCapture,
+ DSoundStartCapture,
+ DSoundStopCapture,
+ DSoundCaptureSamples,
+ DSoundAvailableSamples
+};
+
+void alcDSoundInit(BackendFuncs *FuncList)
+{
+ *FuncList = DSoundFuncs;
+
+ DeviceList[0] = AppendDeviceList("DirectSound Software");
+ AppendAllDeviceList(DeviceList[0]);
+}
diff --git a/Alc/oss.c b/Alc/oss.c
new file mode 100644
index 00000000..5874a88c
--- /dev/null
+++ b/Alc/oss.c
@@ -0,0 +1,328 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <unistd.h>
+#include <errno.h>
+#include <math.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#include <sys/soundcard.h>
+
+/*
+ * The OSS documentation talks about SOUND_MIXER_READ, but the header
+ * only contains MIXER_READ. Play safe. Same for WRITE.
+ */
+#ifndef SOUND_MIXER_READ
+#define SOUND_MIXER_READ MIXER_READ
+#endif
+#ifndef SOUND_MIXER_WRITE
+#define SOUND_MIXER_WRITE MIXER_WRITE
+#endif
+
+static char *oss_device;
+
+typedef struct {
+ int fd;
+ int killNow;
+ ALvoid *thread;
+
+ void *mix_data;
+ int data_size;
+ int silence;
+} oss_data;
+
+
+static int log2i(ALCuint x)
+{
+ int y = 0;
+ while (x > 1)
+ {
+ x >>= 1;
+ y++;
+ }
+ return y;
+}
+
+
+static ALuint OSSProc(ALvoid *ptr)
+{
+ ALCdevice *pDevice = (ALCdevice*)ptr;
+ oss_data *data = (oss_data*)pDevice->ExtraData;
+ int remaining;
+ int wrote;
+
+ while(!data->killNow)
+ {
+ SuspendContext(NULL);
+ if(pDevice->Context)
+ aluMixData(pDevice->Context,data->mix_data,data->data_size,pDevice->Format);
+ else
+ memset(data->mix_data,data->silence,data->data_size);
+ ProcessContext(NULL);
+
+ remaining = data->data_size;
+ while(remaining > 0)
+ {
+ wrote = write(data->fd, data->mix_data+data->data_size-remaining, remaining);
+ if(wrote < 0)
+ {
+ fprintf(stderr, "write failed: %s\n", strerror(errno));
+ break;
+ }
+ if(wrote == 0)
+ {
+ usleep(1000);
+ continue;
+ }
+ remaining -= wrote;
+ }
+ }
+
+ return 0;
+}
+
+static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
+{
+ int numFragmentsLogSize;
+ int log2FragmentSize;
+ unsigned int periods;
+ audio_buf_info info;
+ char driver[64];
+ int numChannels;
+ oss_data *data;
+ int ossFormat;
+ int ossSpeed;
+ int i;
+
+ strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1);
+ driver[sizeof(driver)-1] = 0;
+ if(deviceName)
+ {
+ if(strcmp(deviceName, oss_device))
+ return ALC_FALSE;
+ }
+
+ if(deviceName)
+ strcpy(device->szDeviceName, deviceName);
+ else
+ strcpy(device->szDeviceName, oss_device);
+
+ data = (oss_data*)calloc(1, sizeof(oss_data));
+ data->killNow = 0;
+
+ data->fd = open(driver, O_WRONLY);
+ if(data->fd == -1)
+ {
+ free(data);
+ return ALC_FALSE;
+ }
+
+ switch(device->Format)
+ {
+ case AL_FORMAT_MONO8:
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_QUAD8:
+ data->silence = 0x80;
+ ossFormat = AFMT_U8;
+ break;
+ case AL_FORMAT_MONO16:
+ case AL_FORMAT_STEREO16:
+ case AL_FORMAT_QUAD16:
+ data->silence = 0;
+ ossFormat = AFMT_S16_NE;
+ break;
+ default:
+ ossFormat = -1;
+ fprintf(stderr, "Unknown format?! %x\n", device->Format);
+ }
+
+ periods = GetConfigValueInt("oss", "periods", 4);
+ if((int)periods < 0)
+ periods = 4;
+ numChannels = device->Channels;
+ ossSpeed = device->Frequency;
+ log2FragmentSize = log2i(device->UpdateFreq * device->FrameSize / periods);
+
+ /* according to the OSS spec, 16 bytes are the minimum */
+ if (log2FragmentSize < 4)
+ log2FragmentSize = 4;
+ numFragmentsLogSize = (periods << 16) | log2FragmentSize;
+
+#define ok(func, str) (i=(func),((i<0)?fprintf(stderr,"%s failed\n", str),0:1))
+ if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize), "set fragment") &&
+ ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
+ ok(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels), "set channels") &&
+ ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
+ ok(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info), "get space")))
+ {
+ close(data->fd);
+ free(data);
+ return ALC_FALSE;
+ }
+#undef ok
+
+ device->Channels = numChannels;
+ device->Frequency = ossSpeed;
+ device->Format = 0;
+ if(ossFormat == AFMT_U8)
+ {
+ if(device->Channels == 1)
+ {
+ device->Format = AL_FORMAT_MONO8;
+ device->FrameSize = 1;
+ }
+ else if(device->Channels == 2)
+ {
+ device->Format = AL_FORMAT_STEREO8;
+ device->FrameSize = 2;
+ }
+ else if(device->Channels == 4)
+ {
+ device->Format = AL_FORMAT_QUAD8;
+ device->FrameSize = 4;
+ }
+ }
+ else if(ossFormat == AFMT_S16_NE)
+ {
+ if(device->Channels == 1)
+ {
+ device->Format = AL_FORMAT_MONO16;
+ device->FrameSize = 2;
+ }
+ else if(device->Channels == 2)
+ {
+ device->Format = AL_FORMAT_STEREO16;
+ device->FrameSize = 4;
+ }
+ else if(device->Channels == 4)
+ {
+ device->Format = AL_FORMAT_QUAD16;
+ device->FrameSize = 8;
+ }
+ }
+
+ if(!device->Format)
+ {
+ fprintf(stderr, "Unknown returned format/channel %#x/%d!\n", ossFormat, numChannels);
+ close(data->fd);
+ free(data);
+ return ALC_FALSE;
+ }
+
+ device->UpdateFreq = info.fragsize / device->FrameSize;
+
+ data->data_size = device->UpdateFreq * device->FrameSize;
+ data->mix_data = calloc(1, data->data_size);
+
+ device->MaxNoOfSources = 256;
+
+ device->ExtraData = data;
+ data->thread = StartThread(OSSProc, device);
+ if(data->thread == NULL)
+ {
+ device->ExtraData = NULL;
+ free(data->mix_data);
+ free(data);
+ return ALC_FALSE;
+ }
+
+ return ALC_TRUE;
+}
+
+static void oss_close_playback(ALCdevice *device)
+{
+ oss_data *data = (oss_data*)device->ExtraData;
+ data->killNow = 1;
+ StopThread(data->thread);
+
+ close(data->fd);
+
+ free(data->mix_data);
+ free(data);
+ device->ExtraData = NULL;
+}
+
+
+static ALCboolean oss_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
+{
+ (void)pDevice;
+ (void)deviceName;
+ (void)frequency;
+ (void)format;
+ (void)SampleSize;
+ return ALC_FALSE;
+}
+
+static void oss_close_capture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void oss_start_capture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void oss_stop_capture(ALCdevice *pDevice)
+{
+ (void)pDevice;
+}
+
+static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
+{
+ (void)pDevice;
+ (void)pBuffer;
+ (void)lSamples;
+}
+
+static ALCuint oss_available_samples(ALCdevice *pDevice)
+{
+ (void)pDevice;
+ return 0;
+}
+
+
+BackendFuncs oss_funcs = {
+ oss_open_playback,
+ oss_close_playback,
+ oss_open_capture,
+ oss_close_capture,
+ oss_start_capture,
+ oss_stop_capture,
+ oss_capture_samples,
+ oss_available_samples
+};
+
+void alc_oss_init(BackendFuncs *func_list)
+{
+ *func_list = oss_funcs;
+
+ oss_device = AppendDeviceList("OSS Software");
+ AppendAllDeviceList(oss_device);
+}
diff --git a/Alc/winmm.c b/Alc/winmm.c
new file mode 100644
index 00000000..26f40db2
--- /dev/null
+++ b/Alc/winmm.c
@@ -0,0 +1,421 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+
+typedef struct {
+ // MMSYSTEM Capture Device
+ ALboolean bWaveInShutdown;
+ HANDLE hWaveInHdrEvent;
+ HANDLE hWaveInThreadEvent;
+ HANDLE hWaveInThread;
+ DWORD ulWaveInThreadID;
+ ALint lWaveInBuffersCommitted;
+ HWAVEIN hWaveInHandle;
+ WAVEHDR WaveInBuffer[4];
+ ALCchar *pCapturedSampleData;
+ ALuint ulCapturedDataSize;
+ ALuint ulReadCapturedDataPos;
+ ALuint ulWriteCapturedDataPos;
+} WinMMData;
+
+
+static ALCchar *CaptureDeviceList[16];
+
+/*
+ WaveInProc
+
+ Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
+ returns to the application (with more data)
+*/
+static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
+{
+ ALCdevice *pDevice = (ALCdevice *)dwInstance;
+ WinMMData *pData = pDevice->ExtraData;
+
+ (void)hDevice;
+ (void)dwParam2;
+
+ if ((uMsg==WIM_DATA) && (pDevice))
+ {
+ // Decrement number of buffers in use
+ pData->lWaveInBuffersCommitted--;
+
+ if (pData->bWaveInShutdown == AL_FALSE)
+ {
+ // Notify Wave Processor Thread that a Wave Header has returned
+ PostThreadMessage(pData->ulWaveInThreadID,uMsg,0,dwParam1);
+ }
+ else
+ {
+ if (pData->lWaveInBuffersCommitted == 0)
+ {
+ // Signal Wave Buffers Returned event
+ if (pData->hWaveInHdrEvent)
+ SetEvent(pData->hWaveInHdrEvent);
+
+ // Post 'Quit' Message to WaveIn Processor Thread
+ PostThreadMessage(pData->ulWaveInThreadID,WM_QUIT,0,0);
+ }
+ }
+ }
+}
+
+/*
+ CaptureThreadProc
+
+ Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
+ audio data.
+*/
+DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
+{
+ ALCdevice *pDevice = (ALCdevice*)lpParameter;
+ WinMMData *pData = pDevice->ExtraData;
+ ALuint ulOffset, ulMaxSize, ulSection;
+ LPWAVEHDR pWaveHdr;
+ MSG msg;
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if ((msg.message==WIM_DATA)&&(!pData->bWaveInShutdown))
+ {
+ SuspendContext(NULL);
+
+ pWaveHdr = ((LPWAVEHDR)msg.lParam);
+
+ // Calculate offset in local buffer to write data to
+ ulOffset = pData->ulWriteCapturedDataPos % pData->ulCapturedDataSize;
+
+ if ((ulOffset + pWaveHdr->dwBytesRecorded) > pData->ulCapturedDataSize)
+ {
+ ulSection = pData->ulCapturedDataSize - ulOffset;
+ memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, ulSection);
+ memcpy(pData->pCapturedSampleData, pWaveHdr->lpData + ulSection, pWaveHdr->dwBytesRecorded - ulSection);
+ }
+ else
+ {
+ memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);
+ }
+
+ pData->ulWriteCapturedDataPos += pWaveHdr->dwBytesRecorded;
+
+ if (pData->ulWriteCapturedDataPos > (pData->ulReadCapturedDataPos + pData->ulCapturedDataSize))
+ {
+ // Application has not read enough audio data from the capture buffer so data has been
+ // overwritten. Reset ReadPosition.
+ pData->ulReadCapturedDataPos = pData->ulWriteCapturedDataPos - pData->ulCapturedDataSize;
+ }
+
+ // To prevent an over-flow prevent the offset values from getting too large
+ ulMaxSize = pData->ulCapturedDataSize << 4;
+ if ((pData->ulReadCapturedDataPos > ulMaxSize) && (pData->ulWriteCapturedDataPos > ulMaxSize))
+ {
+ pData->ulReadCapturedDataPos -= ulMaxSize;
+ pData->ulWriteCapturedDataPos -= ulMaxSize;
+ }
+
+ // Send buffer back to capture more data
+ waveInAddBuffer(pData->hWaveInHandle,pWaveHdr,sizeof(WAVEHDR));
+ pData->lWaveInBuffersCommitted++;
+
+ ProcessContext(NULL);
+ }
+ }
+
+ // Signal Wave Thread completed event
+ if (pData->hWaveInThreadEvent)
+ SetEvent(pData->hWaveInThreadEvent);
+
+ ExitThread(0);
+
+ return 0;
+}
+
+
+static ALCboolean WinMMOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
+{
+ (void)device;
+ (void)deviceName;
+ return ALC_FALSE;
+}
+
+static void WinMMClosePlayback(ALCdevice *device)
+{
+ (void)device;
+}
+
+
+static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
+{
+ WAVEFORMATEX wfexCaptureFormat;
+ WinMMData *pData = NULL;
+ ALint lDeviceID = 0;
+ ALint lBufferSize;
+ ALint i;
+
+ (void)format;
+
+ // Find the Device ID matching the deviceName if valid
+ if (deviceName)
+ {
+ for(i = 0;CaptureDeviceList[i];i++)
+ {
+ if (!strcmp(deviceName, CaptureDeviceList[i]))
+ {
+ lDeviceID = i;
+ break;
+ }
+ }
+ if(!CaptureDeviceList[i])
+ return ALC_FALSE;
+ }
+
+ pData = calloc(1, sizeof(*pData));
+ if(!pData)
+ {
+ SetALCError(ALC_OUT_OF_MEMORY);
+ return ALC_FALSE;
+ }
+
+ memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
+ wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
+ wfexCaptureFormat.nChannels = pDevice->Channels;
+ wfexCaptureFormat.wBitsPerSample = pDevice->FrameSize / pDevice->Channels * 8;
+ wfexCaptureFormat.nBlockAlign = pDevice->FrameSize;
+ wfexCaptureFormat.nSamplesPerSec = frequency;
+ wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
+ pDevice->FrameSize;
+ wfexCaptureFormat.cbSize = 0;
+
+ if (waveInOpen(&pData->hWaveInHandle, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
+ goto failure;
+
+ pData->hWaveInHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInAllHeadersReturned");
+ if (pData->hWaveInHdrEvent == NULL)
+ goto failure;
+
+ pData->hWaveInThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInThreadDestroyed");
+ if (pData->hWaveInThreadEvent == NULL)
+ goto failure;
+
+ pData->hWaveInThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveInThreadID);
+ if (pData->hWaveInThread == NULL)
+ goto failure;
+
+ // Allocate circular memory buffer for the captured audio
+ pData->ulCapturedDataSize = SampleSize * wfexCaptureFormat.nBlockAlign;
+
+ // Make sure circular buffer is at least 100ms in size (and an exact multiple of
+ // the block alignment
+ if (pData->ulCapturedDataSize < (wfexCaptureFormat.nAvgBytesPerSec / 10))
+ {
+ pData->ulCapturedDataSize = wfexCaptureFormat.nAvgBytesPerSec / 10;
+ pData->ulCapturedDataSize -= (pData->ulCapturedDataSize % wfexCaptureFormat.nBlockAlign);
+ }
+
+ pData->pCapturedSampleData = (ALCchar*)malloc(pData->ulCapturedDataSize);
+ pData->lWaveInBuffersCommitted=0;
+
+ // Create 4 Buffers of 50ms each
+ lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
+ lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
+
+ for (i=0;i<4;i++)
+ {
+ memset(&pData->WaveInBuffer[i], 0, sizeof(WAVEHDR));
+ pData->WaveInBuffer[i].dwBufferLength = lBufferSize;
+ pData->WaveInBuffer[i].lpData = calloc(1,pData->WaveInBuffer[i].dwBufferLength);
+ pData->WaveInBuffer[i].dwFlags = 0;
+ pData->WaveInBuffer[i].dwLoops = 0;
+ waveInPrepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
+ waveInAddBuffer(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
+ pData->lWaveInBuffersCommitted++;
+ }
+
+ pData->ulReadCapturedDataPos = 0;
+ pData->ulWriteCapturedDataPos = 0;
+
+ strcpy(pDevice->szDeviceName, CaptureDeviceList[lDeviceID]);
+
+ pDevice->ExtraData = pData;
+ return ALC_TRUE;
+
+failure:
+ if (pData->hWaveInThreadEvent)
+ CloseHandle(pData->hWaveInThreadEvent);
+ if (pData->hWaveInHdrEvent)
+ CloseHandle(pData->hWaveInHdrEvent);
+ if (pData->hWaveInHandle)
+ waveInClose(pData->hWaveInHandle);
+
+ free(pData);
+ return ALC_FALSE;
+}
+
+static void WinMMCloseCapture(ALCdevice *pDevice)
+{
+ WinMMData *pData = (WinMMData*)pDevice->ExtraData;
+ int i;
+
+ // Call waveOutReset to shutdown wave device
+ pData->bWaveInShutdown = AL_TRUE;
+ waveInReset(pData->hWaveInHandle);
+
+ // Wait for signal that all Wave Buffers have returned
+ WaitForSingleObjectEx(pData->hWaveInHdrEvent, 5000, FALSE);
+
+ // Wait for signal that Wave Thread has been destroyed
+ WaitForSingleObjectEx(pData->hWaveInThreadEvent, 5000, FALSE);
+
+ // Release the wave buffers
+ for (i=0;i<4;i++)
+ {
+ waveInUnprepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
+ free(pData->WaveInBuffer[i].lpData);
+ }
+
+ // Free Audio Buffer data
+ free(pData->pCapturedSampleData);
+ pData->pCapturedSampleData = NULL;
+
+ // Close the Wave device
+ waveInClose(pData->hWaveInHandle);
+ pData->hWaveInHandle = 0;
+
+ CloseHandle(pData->hWaveInThread);
+ pData->hWaveInThread = 0;
+
+ if (pData->hWaveInHdrEvent)
+ {
+ CloseHandle(pData->hWaveInHdrEvent);
+ pData->hWaveInHdrEvent = 0;
+ }
+
+ if (pData->hWaveInThreadEvent)
+ {
+ CloseHandle(pData->hWaveInThreadEvent);
+ pData->hWaveInThreadEvent = 0;
+ }
+
+ free(pData);
+ pDevice->ExtraData = NULL;
+}
+
+static void WinMMStartCapture(ALCdevice *pDevice)
+{
+ WinMMData *pData = (WinMMData*)pDevice->ExtraData;
+ waveInStart(pData->hWaveInHandle);
+}
+
+static void WinMMStopCapture(ALCdevice *pDevice)
+{
+ WinMMData *pData = (WinMMData*)pDevice->ExtraData;
+ waveInStop(pData->hWaveInHandle);
+}
+
+static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
+{
+ WinMMData *pData = (WinMMData*)pDevice->ExtraData;
+ ALuint ulSamples = (unsigned long)lSamples;
+ ALuint ulBytes, ulBytesToCopy;
+ ALuint ulCapturedSamples;
+ ALuint ulReadOffset;
+
+ // Check that we have the requested numbers of Samples
+ ulCapturedSamples = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos) / pDevice->FrameSize;
+ if(ulSamples > ulCapturedSamples)
+ {
+ SetALCError(ALC_INVALID_VALUE);
+ return;
+ }
+
+ ulBytes = ulSamples * pDevice->FrameSize;
+
+ // Get Read Offset
+ ulReadOffset = (pData->ulReadCapturedDataPos % pData->ulCapturedDataSize);
+
+ // Check for wrap-around condition
+ if ((ulReadOffset + ulBytes) > pData->ulCapturedDataSize)
+ {
+ // Copy data from last Read position to end of data
+ ulBytesToCopy = pData->ulCapturedDataSize - ulReadOffset;
+ memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytesToCopy);
+
+ // Copy rest of the data from the start of the captured data
+ memcpy(((char *)pBuffer) + ulBytesToCopy, pData->pCapturedSampleData, ulBytes - ulBytesToCopy);
+ }
+ else
+ {
+ // Copy data from the read position in the captured data
+ memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytes);
+ }
+
+ // Update Read Position
+ pData->ulReadCapturedDataPos += ulBytes;
+}
+
+static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
+{
+ WinMMData *pData = (WinMMData*)pDevice->ExtraData;
+ ALCuint lCapturedBytes = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos);
+ return lCapturedBytes / pDevice->FrameSize;
+}
+
+
+BackendFuncs WinMMFuncs = {
+ WinMMOpenPlayback,
+ WinMMClosePlayback,
+ WinMMOpenCapture,
+ WinMMCloseCapture,
+ WinMMStartCapture,
+ WinMMStopCapture,
+ WinMMCaptureSamples,
+ WinMMAvailableSamples
+};
+
+void alcWinMMInit(BackendFuncs *FuncList)
+{
+ ALint lNumDevs;
+ ALint lLoop;
+
+ *FuncList = WinMMFuncs;
+
+ lNumDevs = waveInGetNumDevs();
+ for (lLoop = 0; lLoop < lNumDevs; lLoop++)
+ {
+ WAVEINCAPS WaveInCaps;
+ if(waveInGetDevCaps(lLoop, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
+ {
+ char name[128];
+ snprintf(name, sizeof(name), "WaveIn on %s", WaveInCaps.szPname);
+ CaptureDeviceList[lLoop] = AppendCaptureDeviceList(name);
+ }
+ }
+}
diff --git a/Alu/ALu.c b/Alu/ALu.c
new file mode 100644
index 00000000..1b9fbce9
--- /dev/null
+++ b/Alu/ALu.c
@@ -0,0 +1,677 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
+
+#include "config.h"
+
+#include <math.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#if defined(HAVE_STDINT_H)
+#include <stdint.h>
+typedef int64_t ALint64;
+#elif defined(HAVE___INT64)
+typedef __int64 ALint64;
+#elif (SIZEOF_LONG == 8)
+typedef long ALint64;
+#elif (SIZEOF_LONG_LONG == 8)
+typedef long long ALint64;
+#endif
+
+#ifdef HAVE_SQRTF
+#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
+#else
+#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
+#endif
+
+// fixes for mingw32.
+#if defined(max) && !defined(__max)
+#define __max max
+#endif
+#if defined(min) && !defined(__min)
+#define __min min
+#endif
+
+__inline ALuint aluBytesFromFormat(ALenum format)
+{
+ switch(format)
+ {
+ case AL_FORMAT_MONO8:
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_QUAD8:
+ return 1;
+
+ case AL_FORMAT_MONO16:
+ case AL_FORMAT_STEREO16:
+ case AL_FORMAT_QUAD16:
+ return 2;
+
+ default:
+ return 0;
+ }
+}
+
+__inline ALuint aluChannelsFromFormat(ALenum format)
+{
+ switch(format)
+ {
+ case AL_FORMAT_MONO8:
+ case AL_FORMAT_MONO16:
+ return 1;
+
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_STEREO16:
+ return 2;
+
+ case AL_FORMAT_QUAD8:
+ case AL_FORMAT_QUAD16:
+ return 4;
+
+ default:
+ return 0;
+ }
+}
+
+static __inline ALint aluF2L(ALfloat Value)
+{
+ if(sizeof(ALint) == 4 && sizeof(double) == 8)
+ {
+ double temp;
+ temp = Value + (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
+ return *((ALint*)&temp);
+ }
+ return (ALint)Value;
+}
+
+static __inline ALshort aluF2S(ALfloat Value)
+{
+ ALint i;
+
+ i = aluF2L(Value);
+ i = __min( 32767, i);
+ i = __max(-32768, i);
+ return ((ALshort)i);
+}
+
+static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
+{
+ outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
+ outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
+ outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
+}
+
+static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
+{
+ return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
+ inVector1[2]*inVector2[2];
+}
+
+static __inline ALvoid aluNormalize(ALfloat *inVector)
+{
+ ALfloat length, inverse_length;
+
+ length = (ALfloat)aluSqrt(aluDotproduct(inVector, inVector));
+ if(length != 0)
+ {
+ inverse_length = 1.0f/length;
+ inVector[0] *= inverse_length;
+ inVector[1] *= inverse_length;
+ inVector[2] *= inverse_length;
+ }
+}
+
+static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
+{
+ ALfloat result[3];
+
+ result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
+ result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
+ result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
+ memcpy(vector, result, sizeof(result));
+}
+
+static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
+ ALenum isMono, ALenum OutputFormat,
+ ALfloat *drysend, ALfloat *wetsend,
+ ALfloat *pitch)
+{
+ ALfloat ListenerOrientation[6],ListenerPosition[3],ListenerVelocity[3];
+ ALfloat InnerAngle,OuterAngle,OuterGain,Angle,Distance,DryMix,WetMix;
+ ALfloat Direction[3],Position[3],Velocity[3],SourceToListener[3];
+ ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
+ ALfloat Pitch,ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
+ ALfloat U[3],V[3],N[3];
+ ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
+ ALfloat flVSS, flVLS;
+ ALint DistanceModel;
+ ALfloat Matrix[3][3];
+ ALint HeadRelative;
+ ALfloat flAttenuation;
+
+ //Get context properties
+ DopplerFactor = ALContext->DopplerFactor;
+ DistanceModel = ALContext->DistanceModel;
+ DopplerVelocity = ALContext->DopplerVelocity;
+ flSpeedOfSound = ALContext->flSpeedOfSound;
+
+ //Get listener properties
+ ListenerGain = ALContext->Listener.Gain;
+ memcpy(ListenerPosition, ALContext->Listener.Position, sizeof(ALContext->Listener.Position));
+ memcpy(ListenerVelocity, ALContext->Listener.Velocity, sizeof(ALContext->Listener.Velocity));
+ memcpy(&ListenerOrientation[0], ALContext->Listener.Forward, sizeof(ALContext->Listener.Forward));
+ memcpy(&ListenerOrientation[3], ALContext->Listener.Up, sizeof(ALContext->Listener.Up));
+
+ //Get source properties
+ Pitch = ALSource->flPitch;
+ SourceVolume = ALSource->flGain;
+ memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
+ memcpy(Velocity, ALSource->vVelocity, sizeof(ALSource->vVelocity));
+ memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
+ MinVolume = ALSource->flMinGain;
+ MaxVolume = ALSource->flMaxGain;
+ MinDist = ALSource->flRefDistance;
+ MaxDist = ALSource->flMaxDistance;
+ Rolloff = ALSource->flRollOffFactor;
+ OuterGain = ALSource->flOuterGain;
+ InnerAngle = ALSource->flInnerAngle;
+ OuterAngle = ALSource->flOuterAngle;
+ HeadRelative = ALSource->bHeadRelative;
+
+ //Set working variables
+ DryMix = (ALfloat)(1.0f);
+ WetMix = (ALfloat)(0.0f);
+
+ //Only apply 3D calculations for mono buffers
+ if(isMono != AL_FALSE)
+ {
+ //1. Translate Listener to origin (convert to head relative)
+ if(HeadRelative==AL_FALSE)
+ {
+ Position[0] -= ListenerPosition[0];
+ Position[1] -= ListenerPosition[1];
+ Position[2] -= ListenerPosition[2];
+ }
+
+ //2. Calculate distance attenuation
+ Distance = aluSqrt(aluDotproduct(Position, Position));
+
+ flAttenuation = 1.0f;
+ switch (DistanceModel)
+ {
+ case AL_INVERSE_DISTANCE_CLAMPED:
+ Distance=__max(Distance,MinDist);
+ Distance=__min(Distance,MaxDist);
+ if (MaxDist < MinDist)
+ break;
+ //fall-through
+ case AL_INVERSE_DISTANCE:
+ if (MinDist > 0.0f)
+ {
+ if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
+ flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
+ }
+ break;
+
+ case AL_LINEAR_DISTANCE_CLAMPED:
+ Distance=__max(Distance,MinDist);
+ Distance=__min(Distance,MaxDist);
+ if (MaxDist < MinDist)
+ break;
+ //fall-through
+ case AL_LINEAR_DISTANCE:
+ Distance=__min(Distance,MaxDist);
+ if (MaxDist != MinDist)
+ flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
+ break;
+
+ case AL_EXPONENT_DISTANCE_CLAMPED:
+ Distance=__max(Distance,MinDist);
+ Distance=__min(Distance,MaxDist);
+ if (MaxDist < MinDist)
+ break;
+ //fall-through
+ case AL_EXPONENT_DISTANCE:
+ if ((Distance > 0.0f) && (MinDist > 0.0f))
+ flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
+ break;
+
+ case AL_NONE:
+ default:
+ flAttenuation = 1.0f;
+ break;
+ }
+
+ // Source Gain + Attenuation
+ DryMix = SourceVolume * flAttenuation;
+
+ // Clamp to Min/Max Gain
+ DryMix = __min(DryMix,MaxVolume);
+ DryMix = __max(DryMix,MinVolume);
+ WetMix = __min(WetMix,MaxVolume);
+ WetMix = __max(WetMix,MinVolume);
+ //3. Apply directional soundcones
+ SourceToListener[0] = -Position[0];
+ SourceToListener[1] = -Position[1];
+ SourceToListener[2] = -Position[2];
+ aluNormalize(Direction);
+ aluNormalize(SourceToListener);
+ Angle = (ALfloat)(180.0*acos(aluDotproduct(Direction,SourceToListener))/3.141592654f);
+ if(Angle >= InnerAngle && Angle <= OuterAngle)
+ ConeVolume = (1.0f+(OuterGain-1.0f)*(Angle-InnerAngle)/(OuterAngle-InnerAngle));
+ else if(Angle > OuterAngle)
+ ConeVolume = (1.0f+(OuterGain-1.0f) );
+ else
+ ConeVolume = 1.0f;
+
+ //4. Calculate Velocity
+ if(DopplerFactor != 0.0f)
+ {
+ flVLS = aluDotproduct(ListenerVelocity, SourceToListener);
+ flVSS = aluDotproduct(Velocity, SourceToListener);
+
+ flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
+
+ if (flVSS >= flMaxVelocity)
+ flVSS = (flMaxVelocity - 1.0f);
+ else if (flVSS <= -flMaxVelocity)
+ flVSS = -flMaxVelocity + 1.0f;
+
+ if (flVLS >= flMaxVelocity)
+ flVLS = (flMaxVelocity - 1.0f);
+ else if (flVLS <= -flMaxVelocity)
+ flVLS = -flMaxVelocity + 1.0f;
+
+ pitch[0] = Pitch * ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
+ ((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
+ }
+ else
+ pitch[0] = Pitch;
+
+ //5. Align coordinate system axes
+ aluCrossproduct(&ListenerOrientation[0], &ListenerOrientation[3], U); // Right-vector
+ aluNormalize(U); // Normalized Right-vector
+ memcpy(V, &ListenerOrientation[3], sizeof(V)); // Up-vector
+ aluNormalize(V); // Normalized Up-vector
+ memcpy(N, &ListenerOrientation[0], sizeof(N)); // At-vector
+ aluNormalize(N); // Normalized At-vector
+ Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
+ Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
+ Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
+ aluMatrixVector(Position, Matrix);
+
+ //6. Convert normalized position into left/right front/back pannings
+ if(Distance != 0.0f)
+ {
+ aluNormalize(Position);
+ PanningLR = 0.5f + 0.5f*Position[0];
+ PanningFB = 0.5f + 0.5f*Position[2];
+ }
+ else
+ {
+ PanningLR = 0.5f;
+ PanningFB = 0.5f;
+ }
+
+ //7. Convert pannings into channel volumes
+ switch(OutputFormat)
+ {
+ case AL_FORMAT_MONO8:
+ case AL_FORMAT_MONO16:
+ drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
+ drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
+ wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
+ wetsend[1] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
+ break;
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_STEREO16:
+ drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct
+ drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct
+ wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room
+ wetsend[1] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room
+ break;
+ case AL_FORMAT_QUAD8:
+ case AL_FORMAT_QUAD16:
+ drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Direct
+ drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Direct
+ drysend[2] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Direct
+ drysend[3] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Direct
+ wetsend[0] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Room
+ wetsend[1] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Room
+ wetsend[2] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Room
+ wetsend[3] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Room
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ //1. Multi-channel buffers always play "normal"
+ drysend[0] = SourceVolume * 1.0f * ListenerGain;
+ drysend[1] = SourceVolume * 1.0f * ListenerGain;
+ drysend[2] = SourceVolume * 1.0f * ListenerGain;
+ drysend[3] = SourceVolume * 1.0f * ListenerGain;
+ wetsend[0] = SourceVolume * 0.0f * ListenerGain;
+ wetsend[1] = SourceVolume * 0.0f * ListenerGain;
+ wetsend[2] = SourceVolume * 0.0f * ListenerGain;
+ wetsend[3] = SourceVolume * 0.0f * ListenerGain;
+
+ pitch[0] = Pitch;
+ }
+}
+
+ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
+{
+ static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
+ static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
+ ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ ALuint BlockAlign,BufferSize;
+ ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
+ ALuint Channels,Bits,Frequency,ulExtraSamples;
+ ALfloat Pitch;
+ ALint Looping,increment,State;
+ ALuint Buffer,fraction;
+ ALuint SamplesToDo;
+ ALsource *ALSource;
+ ALbuffer *ALBuffer;
+ ALfloat value;
+ ALshort *Data;
+ ALuint i,j,k;
+ ALbufferlistitem *BufferListItem;
+ ALuint loop;
+ ALint64 DataSize64,DataPos64;
+
+ SuspendContext(ALContext);
+
+ if(buffer)
+ {
+ //Figure output format variables
+ BlockAlign = aluChannelsFromFormat(format) *
+ aluBytesFromFormat(format);
+
+ size /= BlockAlign;
+ while(size > 0)
+ {
+ //Setup variables
+ ALSource = ALContext->Source;
+ SamplesToDo = min(size, BUFFERSIZE);
+
+ //Clear mixing buffer
+ memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
+ memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
+
+ //Actual mixing loop
+ while(ALSource)
+ {
+ j = 0;
+ State = ALSource->state;
+ while(State == AL_PLAYING && j < SamplesToDo)
+ {
+ DataSize = 0;
+ DataPosInt = 0;
+ DataPosFrac = 0;
+
+ //Get buffer info
+ if((Buffer = ALSource->ulBufferID))
+ {
+ ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
+
+ Data = ALBuffer->data;
+ Bits = aluBytesFromFormat(ALBuffer->format) * 8;
+ Channels = aluChannelsFromFormat(ALBuffer->format);
+ DataSize = ALBuffer->size;
+ Frequency = ALBuffer->frequency;
+
+ CalcSourceParams(ALContext, ALSource,
+ (Channels==1) ? AL_TRUE : AL_FALSE,
+ format, DrySend, WetSend, &Pitch);
+
+
+ Pitch = (Pitch*Frequency) / ALContext->Frequency;
+ DataSize = DataSize / (Bits*Channels/8);
+
+ //Get source info
+ DataPosInt = ALSource->position;
+ DataPosFrac = ALSource->position_fraction;
+
+ //Compute 18.14 fixed point step
+ increment = aluF2L(Pitch*(1L<<FRACTIONBITS));
+ if(increment > (MAX_PITCH<<FRACTIONBITS))
+ increment = (MAX_PITCH<<FRACTIONBITS);
+
+ //Figure out how many samples we can mix.
+ //Pitch must be <= 4 (the number below !)
+ DataSize64 = DataSize+MAX_PITCH;
+ DataSize64 <<= FRACTIONBITS;
+ DataPos64 = DataPosInt;
+ DataPos64 <<= FRACTIONBITS;
+ DataPos64 += DataPosFrac;
+ BufferSize = (ALuint)((DataSize64-DataPos64) / increment);
+ BufferListItem = ALSource->queue;
+ for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
+ {
+ if(BufferListItem)
+ BufferListItem = BufferListItem->next;
+ }
+ if (BufferListItem)
+ {
+ if (BufferListItem->next)
+ {
+ if(BufferListItem->next->buffer &&
+ ((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->data)
+ {
+ ulExtraSamples = min(((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->size, (ALint)(16*Channels));
+ memcpy(&Data[DataSize*Channels], ((ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer))->data, ulExtraSamples);
+ }
+ }
+ else if (ALSource->bLooping)
+ {
+ if (ALSource->queue->buffer)
+ {
+ if(((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->data)
+ {
+ ulExtraSamples = min(((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->size, (ALint)(16*Channels));
+ memcpy(&Data[DataSize*Channels], ((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer))->data, ulExtraSamples);
+ }
+ }
+ }
+ }
+ BufferSize = min(BufferSize, (SamplesToDo-j));
+
+ //Actual sample mixing loop
+ Data += DataPosInt*Channels;
+ while(BufferSize--)
+ {
+ k = DataPosFrac>>FRACTIONBITS;
+ fraction = DataPosFrac&FRACTIONMASK;
+ if(Channels==1)
+ {
+ //First order interpolator
+ value = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>FRACTIONBITS));
+ //Direct path final mix buffer and panning
+ DryBuffer[j][0] += value*DrySend[0];
+ DryBuffer[j][1] += value*DrySend[1];
+ DryBuffer[j][2] += value*DrySend[2];
+ DryBuffer[j][3] += value*DrySend[3];
+ //Room path final mix buffer and panning
+ WetBuffer[j][0] += value*WetSend[0];
+ WetBuffer[j][1] += value*WetSend[1];
+ WetBuffer[j][2] += value*WetSend[2];
+ WetBuffer[j][3] += value*WetSend[3];
+ }
+ else
+ {
+ //First order interpolator (left)
+ value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+2]*(fraction)))>>FRACTIONBITS));
+ //Direct path final mix buffer and panning (left)
+ DryBuffer[j][0] += value*DrySend[0];
+ //Room path final mix buffer and panning (left)
+ WetBuffer[j][0] += value*WetSend[0];
+ //First order interpolator (right)
+ value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+3]*(fraction)))>>FRACTIONBITS));
+ //Direct path final mix buffer and panning (right)
+ DryBuffer[j][1] += value*DrySend[1];
+ //Room path final mix buffer and panning (right)
+ WetBuffer[j][1] += value*WetSend[1];
+ }
+ DataPosFrac += increment;
+ j++;
+ }
+ DataPosInt += (DataPosFrac>>FRACTIONBITS);
+ DataPosFrac = (DataPosFrac&FRACTIONMASK);
+
+ //Update source info
+ ALSource->position = DataPosInt;
+ ALSource->position_fraction = DataPosFrac;
+ }
+
+ //Handle looping sources
+ if(!Buffer || DataPosInt >= DataSize)
+ {
+ //queueing
+ if(ALSource->queue)
+ {
+ Looping = ALSource->bLooping;
+ if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
+ {
+ BufferListItem = ALSource->queue;
+ for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
+ {
+ if(BufferListItem)
+ {
+ if(!Looping)
+ BufferListItem->bufferstate = PROCESSED;
+ BufferListItem = BufferListItem->next;
+ }
+ }
+ if(!Looping)
+ ALSource->BuffersProcessed++;
+ if(BufferListItem)
+ ALSource->ulBufferID = BufferListItem->buffer;
+ ALSource->position = DataPosInt-DataSize;
+ ALSource->position_fraction = DataPosFrac;
+ ALSource->BuffersPlayed++;
+ }
+ else
+ {
+ if(!Looping)
+ {
+ /* alSourceStop */
+ ALSource->state = AL_STOPPED;
+ ALSource->inuse = AL_FALSE;
+ ALSource->BuffersPlayed = ALSource->BuffersProcessed = ALSource->BuffersInQueue;
+ BufferListItem = ALSource->queue;
+ while(BufferListItem != NULL)
+ {
+ BufferListItem->bufferstate = PROCESSED;
+ BufferListItem = BufferListItem->next;
+ }
+ }
+ else
+ {
+ /* alSourceRewind */
+ /* alSourcePlay */
+ ALSource->state = AL_PLAYING;
+ ALSource->inuse = AL_TRUE;
+ ALSource->play = AL_TRUE;
+ ALSource->BuffersPlayed = 0;
+ ALSource->BufferPosition = 0;
+ ALSource->lBytesPlayed = 0;
+ ALSource->BuffersProcessed = 0;
+ BufferListItem = ALSource->queue;
+ while(BufferListItem != NULL)
+ {
+ BufferListItem->bufferstate = PENDING;
+ BufferListItem = BufferListItem->next;
+ }
+ ALSource->ulBufferID = ALSource->queue->buffer;
+
+ ALSource->position = DataPosInt-DataSize;
+ ALSource->position_fraction = DataPosFrac;
+ }
+ }
+ }
+ }
+
+ //Get source state
+ State = ALSource->state;
+ }
+
+ ALSource = ALSource->next;
+ }
+
+ //Post processing loop
+ switch(format)
+ {
+ case AL_FORMAT_MONO8:
+ for(i = 0;i < SamplesToDo;i++)
+ {
+ *((ALubyte*)buffer) = (aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128;
+ buffer = ((ALubyte*)buffer) + 1;
+ }
+ break;
+ case AL_FORMAT_STEREO8:
+ for(i = 0;i < SamplesToDo*2;i++)
+ {
+ *((ALubyte*)buffer) = (aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1])>>8)+128;
+ buffer = ((ALubyte*)buffer) + 1;
+ }
+ break;
+ case AL_FORMAT_QUAD8:
+ for(i = 0;i < SamplesToDo*4;i++)
+ {
+ *((ALubyte*)buffer) = (aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3])>>8)+128;
+ buffer = ((ALubyte*)buffer) + 1;
+ }
+ break;
+ case AL_FORMAT_MONO16:
+ for(i = 0;i < SamplesToDo;i++)
+ {
+ *((ALshort*)buffer) = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]);
+ buffer = ((ALshort*)buffer) + 1;
+ }
+ break;
+ case AL_FORMAT_STEREO16:
+ default:
+ for(i = 0;i < SamplesToDo*2;i++)
+ {
+ *((ALshort*)buffer) = aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1]);
+ buffer = ((ALshort*)buffer) + 1;
+ }
+ break;
+ case AL_FORMAT_QUAD16:
+ for(i = 0;i < SamplesToDo*4;i++)
+ {
+ *((ALshort*)buffer) = aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3]);
+ buffer = ((ALshort*)buffer) + 1;
+ }
+ break;
+ }
+
+ size -= SamplesToDo;
+ }
+ }
+
+ ProcessContext(ALContext);
+}
diff --git a/CMakeConf/.empty b/CMakeConf/.empty
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/CMakeConf/.empty
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..a414c493
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,256 @@
+# CMake build file list for OpenAL
+
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckIncludeFile)
+INCLUDE(CheckCCompilerFlag)
+INCLUDE(CheckCSourceCompiles)
+INCLUDE(CheckTypeSize)
+
+
+PROJECT(OpenAL)
+
+
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
+
+
+OPTION(ALSA "ALSA backend" ON)
+OPTION(OSS "OSS backend" ON)
+OPTION(DSOUND "DirectSound backend" ON)
+
+OPTION(DLOPEN "Use the dlopen API for loading optional libs" ON)
+
+OPTION(DEBUG "Build lib in debug mode" OFF)
+OPTION(NODEBUG "Disable all debug info for optimizations" OFF)
+OPTION(WERROR "Treat compile warnings as errors" OFF)
+
+
+SET(LIB_MAJOR_VERSION "1")
+SET(LIB_MINOR_VERSION "0")
+SET(LIB_BUILD_VERSION "0")
+SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
+
+
+IF("${WIN32}")
+ SET(LIBNAME openal32)
+ELSE()
+ SET(LIBNAME openal)
+ENDIF()
+
+
+CHECK_TYPE_SIZE("long" SIZEOF_LONG)
+CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
+CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
+CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP)
+
+
+# Add definitions, compiler switches, etc.
+INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}")
+SET(EXTRA_LIBS m ${EXTRA_LIBS})
+
+IF("${MSVC}")
+ # ???
+ELSE()
+ ADD_DEFINITIONS(-W -Wall)
+ IF(WERROR)
+ ADD_DEFINITIONS(-Werror)
+ ENDIF()
+ IF(DEBUG)
+ ADD_DEFINITIONS(-g3)
+ ELSEIF(NODEBUG)
+ ADD_DEFINITIONS(-O2 -funroll-loops -fomit-frame-pointer)
+ ELSE()
+ ADD_DEFINITIONS(-g -O2 -funroll-loops)
+ ENDIF()
+
+ # The mixer doesn't like GCC's strict aliasing optimizations. Make sure
+ # it's turned off
+ CHECK_C_COMPILER_FLAG(-fstrict-aliasing HAVE_STRICT_ALIASING)
+ IF("${HAVE_STRICT_ALIASING}")
+ ADD_DEFINITIONS(-fno-strict-aliasing)
+ ENDIF()
+
+ # Set visibility options if available
+ IF(NOT "${WIN32}")
+ CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
+ int main() {return 0;}" HAVE_GCC_VISIBILITY)
+ IF("${HAVE_GCC_VISIBILITY}")
+ ADD_DEFINITIONS(-fvisibility=hidden -DHAVE_GCC_VISIBILITY)
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
+CHECK_LIBRARY_EXISTS("" strtof "" HAVE_STRTOF)
+
+CHECK_LIBRARY_EXISTS("" strcasecmp "" HAVE_STRCASECMP)
+IF(NOT "${HAVE_STRCASECMP}")
+ CHECK_LIBRARY_EXISTS("" _stricmp "" HAVE__STRICMP)
+ IF(NOT "${HAVE__STRICMP}")
+ MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!")
+ ENDIF()
+
+ ADD_DEFINITIONS(-Dstrcasecmp=_stricmp)
+ENDIF()
+
+# Check for the dlopen API (for dynamicly loading backend libs)
+IF(DLOPEN)
+ CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
+ IF("${HAVE_DLFCN_H}")
+ CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL)
+ IF("${HAVE_LIBDL}")
+ SET(EXTRA_LIBS dl ${EXTRA_LIBS})
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+# Check if we have Windows headers
+CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H)
+IF(NOT "${HAVE_WINDOWS_H}")
+ # We need pthreads outside of Windows
+ CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
+ IF(NOT "${HAVE_PTHREAD_H}")
+ MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
+ ENDIF()
+
+ # _GNU_SOURCE is needed on some systems for extra attributes, and
+ # _REENTRANT is needed for libc thread-safety
+ ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_REENTRANT)
+ CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD)
+ IF("${HAVE_LIBPTHREAD}")
+ SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
+ ENDIF()
+ENDIF()
+
+# Check for a 64-bit type
+CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
+IF(NOT "${HAVE_STDINT_H}")
+ IF("${HAVE_WINDOWS_H}")
+ CHECK_C_SOURCE_COMPILES("\#include <windows.h>
+ __int64 foo;
+ int main() {return 0;}" HAVE___INT64)
+ ENDIF()
+ IF(NOT "${HAVE___INT64}")
+ IF(NOT "${SIZEOF_LONG}" MATCHES "8")
+ IF(NOT "${SIZEOF_LONG_LONG}" MATCHES "8")
+ MESSAGE(FATAL_ERROR "No 64-bit types found, please report!")
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+
+SET(OPENAL_OBJS OpenAL32/alBuffer.c
+ OpenAL32/alError.c
+ OpenAL32/alExtension.c
+ OpenAL32/alListener.c
+ OpenAL32/alSource.c
+ OpenAL32/alState.c
+ OpenAL32/alThunk.c
+ OpenAL32/OpenAL32.c
+)
+SET(ALU_OBJS Alu/ALu.c)
+SET(ALC_OBJS Alc/ALc.c
+ Alc/alcConfig.c
+ Alc/alcThread.c
+)
+
+SET(BACKENDS "")
+
+# Check ALSA backend
+IF(ALSA)
+ CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H)
+ IF("${HAVE_ALSA_ASOUNDLIB_H}")
+ CHECK_LIBRARY_EXISTS(asound snd_pcm_open "" HAVE_LIBASOUND)
+ IF("${HAVE_DLFCN_H}" OR "${HAVE_LIBASOUND}")
+ SET(HAVE_ALSA 1)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/alsa.c)
+ IF("${HAVE_DLFCN_H}")
+ SET(BACKENDS ${BACKENDS} ALSA)
+ ELSE()
+ SET(BACKENDS ${BACKENDS} ALSA\(linked\))
+ SET(EXTRA_LIBS asound ${EXTRA_LIBS})
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+# Check OSS backend
+IF(OSS)
+ CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
+ IF("${HAVE_SYS_SOUNDCARD_H}")
+ SET(HAVE_OSS 1)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/oss.c)
+ SET(BACKENDS ${BACKENDS} OSS)
+ ENDIF()
+ENDIF()
+
+# Check DSound/MMSystem backend
+IF(DSOUND)
+ IF("${HAVE_WINDOWS_H}")
+ SET(CMAKE_REQUIRED_LIBRARIES ole32)
+ CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBOLE32)
+ SET(CMAKE_REQUIRED_LIBRARIES "")
+# CHECK_LIBRARY_EXISTS(ole32 CoInitialize "" HAVE_LIBOLE32)
+ IF("${HAVE_LIBOLE32}")
+ SET(EXTRA_LIBS ole32 ${EXTRA_LIBS})
+ ENDIF()
+
+ CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
+ IF("${HAVE_DSOUND_H}")
+ SET(HAVE_DSOUND 1)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
+ SET(BACKENDS ${BACKENDS} DirectSound)
+
+ CHECK_LIBRARY_EXISTS(dxguid IID_IDirectSound "" HAVE_LIBDXGUID)
+ IF("${HAVE_LIBDXGUID}")
+ SET(EXTRA_LIBS dxguid ${EXTRA_LIBS})
+ ENDIF()
+ ENDIF()
+
+ CHECK_C_SOURCE_COMPILES("\#include <windows.h>
+ \#include <mmsystem.h>
+ int main() {return 0;}" HAVE_MMSYSTEM_H)
+ IF("${HAVE_MMSYSTEM_H}")
+ SET(HAVE_WINMM 1)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
+ SET(BACKENDS ${BACKENDS} WinMM)
+
+ SET(CMAKE_REQUIRED_LIBRARIES winmm)
+ CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBWINMM)
+ SET(CMAKE_REQUIRED_LIBRARIES "")
+# CHECK_LIBRARY_EXISTS(winmm waveInOpen "" HAVE_LIBWINMM)
+ IF("${HAVE_LIBWINMM}")
+ SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+# End configuration
+CONFIGURE_FILE(
+ "${OpenAL_SOURCE_DIR}/config.h.in"
+ "${OpenAL_BINARY_DIR}/config.h")
+
+ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
+
+# Build a shared library
+ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALU_OBJS} ${ALC_OBJS})
+SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION} SOVERSION ${LIB_MAJOR_VERSION})
+
+TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
+
+# Add an install target here
+INSTALL(TARGETS ${LIBNAME}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
+INSTALL(FILES include/AL/al.h
+ include/AL/alc.h
+ DESTINATION include/AL
+)
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Building OpenAL with support for the following backends:")
+MESSAGE(STATUS " ${BACKENDS}")
+MESSAGE(STATUS "")
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..d0c89786
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,484 @@
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h
new file mode 100644
index 00000000..06ffdea0
--- /dev/null
+++ b/OpenAL32/Include/alBuffer.h
@@ -0,0 +1,32 @@
+#ifndef _AL_BUFFER_H_
+#define _AL_BUFFER_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNUSED 0
+#define PENDING 1
+#define PROCESSED 2
+
+typedef struct ALbuffer_struct
+{
+ ALenum format;
+ ALenum eOriginalFormat;
+ ALshort *data;
+ ALsizei size;
+ ALsizei frequency;
+ ALenum state;
+ ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0)
+ struct ALbuffer_struct *next;
+} ALbuffer;
+
+ALvoid ReleaseALBuffers(ALvoid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alError.h b/OpenAL32/Include/alError.h
new file mode 100644
index 00000000..5cee8db8
--- /dev/null
+++ b/OpenAL32/Include/alError.h
@@ -0,0 +1,16 @@
+#ifndef _AL_ERROR_H_
+#define _AL_ERROR_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ALvoid alSetError(ALenum errorCode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alExtension.h b/OpenAL32/Include/alExtension.h
new file mode 100644
index 00000000..1f33f9af
--- /dev/null
+++ b/OpenAL32/Include/alExtension.h
@@ -0,0 +1,33 @@
+#ifndef _AL_EXTENSION_H_
+#define _AL_EXTENSION_H_
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALextension_struct
+{
+ ALchar *extName;
+ ALvoid *address;
+} ALextension;
+
+typedef struct ALfunction_struct
+{
+ ALchar *funcName;
+ ALvoid *address;
+} ALfunction;
+
+typedef struct ALenum_struct
+{
+ ALchar *enumName;
+ ALenum value;
+} ALenums;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alListener.h b/OpenAL32/Include/alListener.h
new file mode 100644
index 00000000..2075e612
--- /dev/null
+++ b/OpenAL32/Include/alListener.h
@@ -0,0 +1,23 @@
+#ifndef _AL_LISTENER_H_
+#define _AL_LISTENER_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALlistener_struct
+{
+ ALfloat Position[3];
+ ALfloat Velocity[3];
+ ALfloat Forward[3];
+ ALfloat Up[3];
+ ALfloat Gain;
+} ALlistener;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
new file mode 100644
index 00000000..3d34cf38
--- /dev/null
+++ b/OpenAL32/Include/alMain.h
@@ -0,0 +1,170 @@
+#ifndef AL_MAIN_H
+#define AL_MAIN_H
+
+#define AL_MAX_CHANNELS 4
+#define AL_MAX_SOURCES 32
+
+#include <string.h>
+
+#include "alu.h"
+
+#ifdef _WIN32
+#include <windows.h>
+//#define strcasecmp _stricmp
+
+#else
+
+#include <assert.h>
+#include <pthread.h>
+
+#define IsBadWritePtr(a,b) (0)
+
+typedef pthread_mutex_t CRITICAL_SECTION;
+static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_lock(cs) == 0);
+}
+static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_unlock(cs) == 0);
+}
+static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
+{
+ pthread_mutexattr_t attrib;
+
+ assert(pthread_mutexattr_init(&attrib) == 0);
+
+ assert(pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE) == 0);
+ assert(pthread_mutex_init(cs, &attrib) == 0);
+
+ pthread_mutexattr_destroy(&attrib);
+}
+
+static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_destroy(cs) == 0);
+}
+
+#define min(x,y) (((x)<(y))?(x):(y))
+#define max(x,y) (((x)>(y))?(x):(y))
+#endif
+
+#include "alBuffer.h"
+#include "alError.h"
+#include "alExtension.h"
+#include "alListener.h"
+#include "alSource.h"
+#include "alState.h"
+#include "alThunk.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define AL_FORMAT_MONO_IMA4 0x1300
+#define AL_FORMAT_STEREO_IMA4 0x1301
+// These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer
+// can use 4-channel formats
+#define AL_FORMAT_QUAD8 0x1204
+#define AL_FORMAT_QUAD16 0x1205
+
+#define SWMIXER_OUTPUT_RATE 44100
+//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050)
+
+#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
+
+typedef struct {
+ ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
+ void (*ClosePlayback)(ALCdevice*);
+
+ ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*, ALCuint, ALCenum, ALCsizei);
+ void (*CloseCapture)(ALCdevice*);
+ void (*StartCapture)(ALCdevice*);
+ void (*StopCapture)(ALCdevice*);
+ void (*CaptureSamples)(ALCdevice*, void*, ALCuint);
+ ALCuint (*AvailableSamples)(ALCdevice*);
+} BackendFuncs;
+
+struct ALCdevice_struct
+{
+ ALboolean InUse;
+ ALboolean IsCaptureDevice;
+
+ ALuint Frequency;
+ ALuint UpdateFreq;
+ ALuint FrameSize;
+ ALuint Channels;
+ ALenum Format;
+
+ ALCchar szDeviceName[256];
+
+ // Maximum number of sources that can be created
+ ALuint MaxNoOfSources;
+
+ // Context created on this device
+ ALCcontext *Context;
+
+ BackendFuncs *Funcs;
+ void *ExtraData; // For the backend's use
+};
+
+#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
+#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
+#define ALCdevice_OpenCapture(a,b,c,d,e) ((a)->Funcs->OpenCapture((a), (b), (c), (d), (e)))
+#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
+#define ALCdevice_StartCapture(a) ((a)->Funcs->StartCapture((a)))
+#define ALCdevice_StopCapture(a) ((a)->Funcs->StopCapture((a)))
+#define ALCdevice_CaptureSamples(a,b,c) ((a)->Funcs->CaptureSamples((a), (b), (c)))
+#define ALCdevice_AvailableSamples(a) ((a)->Funcs->AvailableSamples((a)))
+
+struct ALCcontext_struct
+{
+ ALlistener Listener;
+
+ ALsource *Source;
+ ALuint SourceCount;
+
+ ALenum LastError;
+ ALboolean InUse;
+
+ ALuint Frequency;
+
+ ALenum DistanceModel;
+
+ ALfloat DopplerFactor;
+ ALfloat DopplerVelocity;
+ ALfloat flSpeedOfSound;
+
+ ALint lNumMonoSources;
+ ALint lNumStereoSources;
+
+ ALCdevice *Device;
+ ALCchar ExtensionList[1024];
+
+ ALCcontext *next;
+};
+
+ALCchar *AppendDeviceList(char *name);
+ALCchar *AppendAllDeviceList(char *name);
+ALCchar *AppendCaptureDeviceList(char *name);
+
+ALCvoid SetALCError(ALenum errorCode);
+
+ALCvoid SuspendContext(ALCcontext *context);
+ALCvoid ProcessContext(ALCcontext *context);
+
+ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
+ALuint StopThread(ALvoid *thread);
+
+void ReadALConfig(void);
+void FreeALConfig(void);
+const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
+int GetConfigValueInt(const char *blockName, const char *keyName, int def);
+float GetConfigValueFloat(const char *blockName, const char *keyName, float def);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
new file mode 100644
index 00000000..499ddcf4
--- /dev/null
+++ b/OpenAL32/Include/alSource.h
@@ -0,0 +1,71 @@
+#ifndef _AL_SOURCE_H_
+#define _AL_SOURCE_H_
+
+#define AL_NUM_SOURCE_PARAMS 128
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALbufferlistitem
+{
+ ALuint buffer;
+ ALuint bufferstate;
+ ALuint flag;
+ struct ALbufferlistitem *next;
+} ALbufferlistitem;
+
+typedef struct ALsource_struct
+{
+ ALfloat flPitch;
+ ALfloat flGain;
+ ALfloat flOuterGain;
+ ALfloat flMinGain;
+ ALfloat flMaxGain;
+ ALfloat flInnerAngle;
+ ALfloat flOuterAngle;
+ ALfloat flRefDistance;
+ ALfloat flMaxDistance;
+ ALfloat flRollOffFactor;
+ ALfloat vPosition[3];
+ ALfloat vVelocity[3];
+ ALfloat vOrientation[3];
+ ALboolean bHeadRelative;
+ ALboolean bLooping;
+
+ ALuint ulBufferID;
+
+ ALboolean inuse;
+ ALboolean play;
+ ALenum state;
+ ALuint position;
+ ALuint position_fraction;
+ struct ALbufferlistitem *queue; // Linked list of buffers in queue
+ ALuint BuffersInQueue; // Number of buffers in queue
+ ALuint BuffersProcessed; // Number of buffers already processed (played)
+
+ ALuint TotalBufferDataSize; // Total amount of data contained in the buffers queued for this source
+ ALuint BuffersPlayed; // Number of buffers played on this loop
+ ALuint BufferPosition; // Read position in audio data of current buffer
+
+ // Index to itself
+ ALuint source;
+
+ ALint lBytesPlayed;
+
+ ALint lOffset;
+ ALint lOffsetType;
+
+ // Source Type (Static, Streaming, or Undetermined)
+ ALint lSourceType;
+
+ struct ALsource_struct *next;
+} ALsource;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alState.h b/OpenAL32/Include/alState.h
new file mode 100644
index 00000000..332176b0
--- /dev/null
+++ b/OpenAL32/Include/alState.h
@@ -0,0 +1,14 @@
+#ifndef _AL_STATE_H_
+#define _AL_STATE_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alThunk.h b/OpenAL32/Include/alThunk.h
new file mode 100644
index 00000000..2ed32871
--- /dev/null
+++ b/OpenAL32/Include/alThunk.h
@@ -0,0 +1,42 @@
+#ifndef _AL_THUNK_H_
+#define _AL_THUNK_H_
+
+#include "config.h"
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (SIZEOF_VOIDP > SIZEOF_UINT)
+
+void alThunkInit(void);
+void alThunkExit(void);
+ALuint alThunkAddEntry(ALvoid * ptr);
+void alThunkRemoveEntry(ALuint index);
+ALvoid *alThunkLookupEntry(ALuint index);
+
+#define ALTHUNK_INIT() alThunkInit()
+#define ALTHUNK_EXIT() alThunkExit()
+#define ALTHUNK_ADDENTRY(p) alThunkAddEntry(p)
+#define ALTHUNK_REMOVEENTRY(i) alThunkRemoveEntry(i)
+#define ALTHUNK_LOOKUPENTRY(i) alThunkLookupEntry(i)
+
+#else
+
+#define ALTHUNK_INIT()
+#define ALTHUNK_EXIT()
+#define ALTHUNK_ADDENTRY(p) ((ALuint)p)
+#define ALTHUNK_REMOVEENTRY(i)
+#define ALTHUNK_LOOKUPENTRY(i) ((ALvoid*)(i))
+
+#endif // (SIZEOF_VOIDP > SIZEOF_INT)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_AL_THUNK_H_
+
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
new file mode 100644
index 00000000..e4fe0dc3
--- /dev/null
+++ b/OpenAL32/Include/alu.h
@@ -0,0 +1,26 @@
+#ifndef _ALU_H_
+#define _ALU_H_
+
+#define BUFFERSIZE 48000
+#define FRACTIONBITS 14
+#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
+#define MAX_PITCH 4
+#define OUTPUTCHANNELS 4
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__inline ALuint aluBytesFromFormat(ALenum format);
+__inline ALuint aluChannelsFromFormat(ALenum format);
+ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/OpenAL32/OpenAL32.c b/OpenAL32/OpenAL32.c
new file mode 100644
index 00000000..20ca14f9
--- /dev/null
+++ b/OpenAL32/OpenAL32.c
@@ -0,0 +1,75 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 "alMain.h"
+#include "alBuffer.h"
+#include "alThunk.h"
+
+CRITICAL_SECTION g_mutex;
+
+#ifdef _WIN32
+BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
+{
+ (void)lpReserved;
+
+ // Perform actions based on the reason for calling.
+ switch(ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hModule);
+ InitializeCriticalSection(&g_mutex);
+ ALTHUNK_INIT();
+ ReadALConfig();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ ReleaseALBuffers();
+ FreeALConfig();
+ ALTHUNK_EXIT();
+ DeleteCriticalSection(&g_mutex);
+ break;
+ }
+ return TRUE;
+}
+#else
+static void my_init() __attribute__((constructor));
+static void my_init()
+{
+ static ALenum once = AL_FALSE;
+ if(once) return;
+ once = AL_TRUE;
+
+ InitializeCriticalSection(&g_mutex);
+ ALTHUNK_INIT();
+ ReadALConfig();
+}
+static void my_deinit() __attribute__((destructor));
+static void my_deinit()
+{
+ static ALenum once = AL_FALSE;
+ if(once) return;
+ once = AL_TRUE;
+
+ ReleaseALBuffers();
+ FreeALConfig();
+ ALTHUNK_EXIT();
+ DeleteCriticalSection(&g_mutex);
+}
+#endif
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
new file mode 100644
index 00000000..53ee128a
--- /dev/null
+++ b/OpenAL32/alBuffer.c
@@ -0,0 +1,989 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alBuffer.h"
+
+#ifdef _DEBUG
+ char szDebug[256];
+#endif
+
+/*
+ * AL Buffer Functions
+ *
+ * AL Buffers are shared amoung Contexts, so we store the list of generated Buffers
+ * as a global variable in this module. (A valid context is not required to make
+ * AL Buffer function calls
+ *
+ */
+
+/*
+* Global Variables
+*/
+
+static ALbuffer *g_pBuffers = NULL; // Linked List of Buffers
+static ALuint g_uiBufferCount = 0; // Buffer Count
+
+static const long g_IMAStep_size[89]={ // IMA ADPCM Stepsize table
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442,11487,12635,13899,
+ 15289,16818,18500,20350,22358,24633,27086,29794,32767
+};
+
+static const long g_IMACodeword_4[16]={ // IMA4 ADPCM Codeword decode table
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ -1,-3,-5,-7,-9,-11,-13,-15,
+};
+
+static const long g_IMAIndex_adjust_4[16]={ // IMA4 ADPCM Step index adjust decode table
+ -1,-1,-1,-1, 2, 4, 6, 8,
+ -1,-1,-1,-1, 2, 4, 6, 8
+};
+
+/*
+* alGenBuffers(ALsizei n, ALuint *puiBuffers)
+*
+* Generates n AL Buffers, and stores the Buffers Names in the array pointed to by puiBuffers
+*/
+ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
+{
+ ALCcontext *Context;
+ ALsizei i=0;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ // Check that we are actually generation some Buffers
+ if (n > 0)
+ {
+ // Check the pointer is valid (and points to enough memory to store Buffer Names)
+ if (!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
+ {
+ ALbuffer **list = &g_pBuffers;
+ while(*list)
+ list = &(*list)->next;
+
+ // Create all the new Buffers
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALbuffer));
+ if(*list)
+ {
+ puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->state = UNUSED;
+ g_uiBufferCount++;
+ i++;
+
+ list = &(*list)->next;
+ }
+ }
+
+ // If we didn't create all the Buffers, we must have run out of memory
+ if (i != n)
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ // Pointer does not point to enough memory to write Buffer names
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+
+ ProcessContext(Context);
+
+ return;
+}
+
+/*
+* alDeleteBuffers(ALsizei n, ALuint *puiBuffers)
+*
+* Deletes the n AL Buffers pointed to by puiBuffers
+*/
+ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
+{
+ ALCcontext *Context;
+ ALbuffer *ALBuf;
+ ALsizei i;
+ ALboolean bFailed = AL_FALSE;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ // Check we are actually Deleting some Buffers
+ if (n >= 0)
+ {
+ if ((ALuint)n <= g_uiBufferCount)
+ {
+ // Check that all the buffers are valid and can actually be deleted
+ for (i = 0; i < n; i++)
+ {
+ // Check for valid Buffer ID (can be NULL buffer)
+ if (alIsBuffer(puiBuffers[i]))
+ {
+ // If not the NULL buffer, check that the reference count is 0
+ ALBuf = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
+ if (ALBuf)
+ {
+ if (ALBuf->refcount != 0)
+ {
+ // Buffer still in use, cannot be deleted
+ alSetError(AL_INVALID_OPERATION);
+ bFailed = AL_TRUE;
+ }
+ }
+ }
+ else
+ {
+ // Invalid Buffer
+ alSetError(AL_INVALID_NAME);
+ bFailed = AL_TRUE;
+ }
+ }
+
+ // If all the Buffers were valid (and have Reference Counts of 0), then we can delete them
+ if (!bFailed)
+ {
+ for (i = 0; i < n; i++)
+ {
+ ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
+ if (ALBuf)
+ {
+ ALbuffer **list = &g_pBuffers;
+ while(*list && *list != ALBuf)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+
+ // Release the memory used to store audio data
+ free(ALBuf->data);
+
+ // Release buffer structure
+ ALTHUNK_REMOVEENTRY(puiBuffers[i]);
+ memset(ALBuf, 0, sizeof(ALbuffer));
+ g_uiBufferCount--;
+ free(ALBuf);
+ }
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+
+ return;
+
+}
+
+/*
+* alIsBuffer(ALuint uiBuffer)
+*
+* Checks if ulBuffer is a valid Buffer Name
+*/
+ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint uiBuffer)
+{
+ ALCcontext *Context;
+ ALboolean result=AL_FALSE;
+ ALbuffer *ALBuf;
+ ALbuffer *TgtALBuf;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (uiBuffer)
+ {
+ TgtALBuf = (ALbuffer *)ALTHUNK_LOOKUPENTRY(uiBuffer);
+
+ // Check through list of generated buffers for uiBuffer
+ ALBuf = g_pBuffers;
+ while (ALBuf)
+ {
+ if (ALBuf == TgtALBuf)
+ {
+ result = AL_TRUE;
+ break;
+ }
+
+ ALBuf = ALBuf->next;
+ }
+ }
+ else
+ {
+ result = AL_TRUE;
+ }
+
+
+ ProcessContext(Context);
+
+ return result;
+}
+
+/*
+* alBufferData(ALuint buffer,ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
+*
+* Fill buffer with audio data
+*/
+ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq)
+{
+ ALuint *IMAData,IMACode;
+ ALCcontext *Context;
+ ALint Sample,Index;
+ ALint LeftSample,LeftIndex;
+ ALint RightSample,RightIndex;
+ ALuint LeftIMACode,RightIMACode;
+ ALbuffer *ALBuf;
+ ALsizei i,j,k;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+ if ((ALBuf->refcount==0)&&(data))
+ {
+ switch(format)
+ {
+ case AL_FORMAT_MONO8:
+ if ((size%1) == 0)
+ {
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO8;
+ for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
+ ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
+ memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 16);
+ ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_MONO16:
+ if ((size%2) == 0)
+ {
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO16;
+ memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 16);
+ ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO8:
+ if ((size%2) == 0)
+ {
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO8;
+ for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
+ ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
+ memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 32);
+ ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO16:
+ if ((size%4) == 0)
+ {
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO16;
+ memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 32);
+ ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_MONO_IMA4:
+ // Here is where things vary:
+ // nVidia and Apple use 64+1 samples per block => block_size=36 bytes
+ // Most PC sound software uses 2040+1 samples per block -> block_size=1024 bytes
+ if ((size%36) == 0)
+ {
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/36)*(65*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO_IMA4;
+ IMAData=(ALuint *)data;
+ for (i=0;i<size/36;i++)
+ {
+ Sample=((ALshort *)IMAData)[0];
+ Index=((ALshort *)IMAData)[1];
+
+ Index=Index<0?0:Index;
+ Index=Index>88?88:Index;
+
+ ALBuf->data[i*65]=(short)Sample;
+
+ IMAData++;
+
+ for (j=1;j<65;j+=8)
+ {
+ IMACode=*IMAData;
+ for (k=0;k<8;k+=2)
+ {
+ Sample+=((g_IMAStep_size[Index]*g_IMACodeword_4[IMACode&15])/8);
+ Index+=g_IMAIndex_adjust_4[IMACode&15];
+ if (Sample<-32768) Sample=-32768;
+ else if (Sample>32767) Sample=32767;
+ if (Index<0) Index=0;
+ else if (Index>88) Index=88;
+ ALBuf->data[i*65+j+k]=(short)Sample;
+ IMACode>>=4;
+
+ Sample+=((g_IMAStep_size[Index]*g_IMACodeword_4[IMACode&15])/8);
+ Index+=g_IMAIndex_adjust_4[IMACode&15];
+ if (Sample<-32768) Sample=-32768;
+ else if (Sample>32767) Sample=32767;
+ if (Index<0) Index=0;
+ else if (Index>88) Index=88;
+ ALBuf->data[i*65+j+k+1]=(short)Sample;
+ IMACode>>=4;
+ }
+ IMAData++;
+ }
+ }
+ memset(&(ALBuf->data[(size/36*65)]), 0, 16);
+ ALBuf->size=size/36*65*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO_IMA4:
+ // Here is where things vary:
+ // nVidia and Apple use 64+1 samples per channel per block => block_size=72 bytes
+ // Most PC sound software uses 2040+1 samples per channel per block -> block_size=2048 bytes
+ if ((size%72) == 0)
+ {
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/72)*(2*65*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO_IMA4;
+ IMAData=(ALuint *)data;
+ for (i=0;i<size/72;i++)
+ {
+ LeftSample=((ALshort *)IMAData)[0];
+ LeftIndex=((ALshort *)IMAData)[1];
+
+ LeftIndex=LeftIndex<0?0:LeftIndex;
+ LeftIndex=LeftIndex>88?88:LeftIndex;
+
+ ALBuf->data[i*2*65]=(short)LeftSample;
+
+ IMAData++;
+
+ RightSample=((ALshort *)IMAData)[0];
+ RightIndex=((ALshort *)IMAData)[1];
+
+ RightIndex=RightIndex<0?0:RightIndex;
+ RightIndex=RightIndex>88?88:RightIndex;
+
+ ALBuf->data[i*2*65+1]=(short)RightSample;
+
+ IMAData++;
+
+ for (j=2;j<130;j+=16)
+ {
+ LeftIMACode=IMAData[0];
+ RightIMACode=IMAData[1];
+ for (k=0;k<16;k+=4)
+ {
+ LeftSample+=((g_IMAStep_size[LeftIndex]*g_IMACodeword_4[LeftIMACode&15])/8);
+ LeftIndex+=g_IMAIndex_adjust_4[LeftIMACode&15];
+ if (LeftSample<-32768) LeftSample=-32768;
+ else if (LeftSample>32767) LeftSample=32767;
+ if (LeftIndex<0) LeftIndex=0;
+ else if (LeftIndex>88) LeftIndex=88;
+ ALBuf->data[i*2*65+j+k]=(short)LeftSample;
+ LeftIMACode>>=4;
+
+ RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
+ RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
+ if (RightSample<-32768) RightSample=-32768;
+ else if (RightSample>32767) RightSample=32767;
+ if (RightIndex<0) RightIndex=0;
+ else if (RightIndex>88) RightIndex=88;
+ ALBuf->data[i*2*65+j+k+1]=(short)RightSample;
+ RightIMACode>>=4;
+
+ LeftSample+=((g_IMAStep_size[LeftIndex]*g_IMACodeword_4[LeftIMACode&15])/8);
+ LeftIndex+=g_IMAIndex_adjust_4[LeftIMACode&15];
+ if (LeftSample<-32768) LeftSample=-32768;
+ else if (LeftSample>32767) LeftSample=32767;
+ if (LeftIndex<0) LeftIndex=0;
+ else if (LeftIndex>88) LeftIndex=88;
+ ALBuf->data[i*2*65+j+k+2]=(short)LeftSample;
+ LeftIMACode>>=4;
+
+ RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
+ RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
+ if (RightSample<-32768) RightSample=-32768;
+ else if (RightSample>32767) RightSample=32767;
+ if (RightIndex<0) RightIndex=0;
+ else if (RightIndex>88) RightIndex=88;
+ ALBuf->data[i*2*65+j+k+3]=(short)RightSample;
+ RightIMACode>>=4;
+ }
+ IMAData+=2;
+ }
+ }
+ memset(&(ALBuf->data[(size/72*2*65)]), 0, 32);
+ ALBuf->size=size/72*2*65*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // Buffer is in use, or data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Invalid Buffer Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+}
+
+
+ALAPI void ALAPIENTRY alBufferf(ALuint buffer, ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValue;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBuffer3f(ALuint buffer, ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValue1;
+ (void)flValue2;
+ (void)flValue3;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferfv(ALuint buffer, ALenum eParam, const ALfloat* flValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValues;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferi(ALuint buffer, ALenum eParam, ALint lValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)lValue;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBuffer3i( ALuint buffer, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)lValue1;
+ (void)lValue2;
+ (void)lValue3;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)plValues;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBuffer3f(ALuint buffer, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pflValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch (eParam)
+ {
+ case AL_FREQUENCY:
+ *plValue = pBuffer->frequency;
+ break;
+
+ case AL_BITS:
+ *plValue= (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_STEREO8))?8:16);
+ break;
+
+ case AL_CHANNELS:
+ *plValue = (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_MONO16))?1:2);
+ break;
+
+ case AL_SIZE:
+ *plValue = pBuffer->size;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBuffer3i(ALuint buffer, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch (eParam)
+ {
+ case AL_FREQUENCY:
+ case AL_BITS:
+ case AL_CHANNELS:
+ case AL_SIZE:
+ alGetBufferi(buffer, eParam, plValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+/*
+* ReleaseALBuffers()
+*
+* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
+*/
+ALvoid ReleaseALBuffers(ALvoid)
+{
+ ALbuffer *ALBuffer;
+ ALbuffer *ALBufferTemp;
+
+#ifdef _DEBUG
+ if(g_uiBufferCount > 0)
+ {
+ sprintf(szDebug, "OpenAL32 : DllMain() %d Buffer(s) NOT deleted\n", g_uiBufferCount);
+ OutputDebugString(szDebug);
+ }
+#endif
+
+ ALBuffer = g_pBuffers;
+ while(ALBuffer)
+ {
+ // Release sample data
+ free(ALBuffer->data);
+
+ // Release Buffer structure
+ ALBufferTemp = ALBuffer;
+ ALBuffer = ALBuffer->next;
+ memset(ALBufferTemp, 0, sizeof(ALbuffer));
+ free(ALBufferTemp);
+ }
+ g_pBuffers = NULL;
+ g_uiBufferCount = 0;
+}
diff --git a/OpenAL32/alError.c b/OpenAL32/alError.c
new file mode 100644
index 00000000..df5c16e4
--- /dev/null
+++ b/OpenAL32/alError.c
@@ -0,0 +1,61 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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 "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+
+ALAPI ALenum ALAPIENTRY alGetError(ALvoid)
+{
+ ALCcontext *Context;
+ ALenum errorCode;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (Context)
+ {
+ errorCode = Context->LastError;
+ Context->LastError = AL_NO_ERROR;
+ }
+ else
+ {
+ errorCode = AL_INVALID_OPERATION;
+ }
+
+ ProcessContext(Context);
+
+ return errorCode;
+}
+
+ALvoid alSetError(ALenum errorCode)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (Context)
+ {
+ Context->LastError=errorCode;
+ }
+
+ ProcessContext(Context);
+}
diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c
new file mode 100644
index 00000000..1d0928d2
--- /dev/null
+++ b/OpenAL32/alExtension.c
@@ -0,0 +1,274 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "alExtension.h"
+#include "alError.h"
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+static ALfunction function[]= {
+ { "alEnable", (ALvoid *) alEnable },
+ { "alDisable", (ALvoid *) alDisable },
+ { "alIsEnabled", (ALvoid *) alIsEnabled },
+ { "alGetString", (ALvoid *) alGetString },
+ { "alGetBooleanv", (ALvoid *) alGetBooleanv },
+ { "alGetIntegerv", (ALvoid *) alGetIntegerv },
+ { "alGetFloatv", (ALvoid *) alGetFloatv },
+ { "alGetDoublev", (ALvoid *) alGetDoublev },
+ { "alGetBoolean", (ALvoid *) alGetBoolean },
+ { "alGetInteger", (ALvoid *) alGetInteger },
+ { "alGetFloat", (ALvoid *) alGetFloat },
+ { "alGetDouble", (ALvoid *) alGetDouble },
+ { "alGetError", (ALvoid *) alGetError },
+ { "alIsExtensionPresent", (ALvoid *) alIsExtensionPresent },
+ { "alGetProcAddress", (ALvoid *) alGetProcAddress },
+ { "alGetEnumValue", (ALvoid *) alGetEnumValue },
+ { "alListenerf", (ALvoid *) alListenerf },
+ { "alListener3f", (ALvoid *) alListener3f },
+ { "alListenerfv", (ALvoid *) alListenerfv },
+ { "alListeneri", (ALvoid *) alListeneri },
+ { "alListener3i", (ALvoid *) alListener3i },
+ { "alListeneriv", (ALvoid *) alListeneriv },
+ { "alGetListenerf", (ALvoid *) alGetListenerf },
+ { "alGetListener3f", (ALvoid *) alGetListener3f },
+ { "alGetListenerfv", (ALvoid *) alGetListenerfv },
+ { "alGetListeneri", (ALvoid *) alGetListeneri },
+ { "alGetListener3i", (ALvoid *) alGetListener3i },
+ { "alGetListeneriv", (ALvoid *) alGetListeneriv },
+ { "alGenSources", (ALvoid *) alGenSources },
+ { "alDeleteSources", (ALvoid *) alDeleteSources },
+ { "alIsSource", (ALvoid *) alIsSource },
+ { "alSourcef", (ALvoid *) alSourcef },
+ { "alSource3f", (ALvoid *) alSource3f },
+ { "alSourcefv", (ALvoid *) alSourcefv },
+ { "alSourcei", (ALvoid *) alSourcei },
+ { "alSource3i", (ALvoid *) alSource3i },
+ { "alSourceiv", (ALvoid *) alSourceiv },
+ { "alGetSourcef", (ALvoid *) alGetSourcef },
+ { "alGetSource3f", (ALvoid *) alGetSource3f },
+ { "alGetSourcefv", (ALvoid *) alGetSourcefv },
+ { "alGetSourcei", (ALvoid *) alGetSourcei },
+ { "alGetSource3i", (ALvoid *) alGetSource3i },
+ { "alGetSourceiv", (ALvoid *) alGetSourceiv },
+ { "alSourcePlayv", (ALvoid *) alSourcePlayv },
+ { "alSourceStopv", (ALvoid *) alSourceStopv },
+ { "alSourceRewindv", (ALvoid *) alSourceRewindv },
+ { "alSourcePausev", (ALvoid *) alSourcePausev },
+ { "alSourcePlay", (ALvoid *) alSourcePlay },
+ { "alSourceStop", (ALvoid *) alSourceStop },
+ { "alSourceRewind", (ALvoid *) alSourceRewind },
+ { "alSourcePause", (ALvoid *) alSourcePause },
+ { "alSourceQueueBuffers", (ALvoid *) alSourceQueueBuffers },
+ { "alSourceUnqueueBuffers", (ALvoid *) alSourceUnqueueBuffers },
+ { "alGenBuffers", (ALvoid *) alGenBuffers },
+ { "alDeleteBuffers", (ALvoid *) alDeleteBuffers },
+ { "alIsBuffer", (ALvoid *) alIsBuffer },
+ { "alBufferData", (ALvoid *) alBufferData },
+ { "alBufferf", (ALvoid *) alBufferf },
+ { "alBuffer3f", (ALvoid *) alBuffer3f },
+ { "alBufferfv", (ALvoid *) alBufferfv },
+ { "alBufferi", (ALvoid *) alBufferi },
+ { "alBuffer3i", (ALvoid *) alBuffer3i },
+ { "alBufferiv", (ALvoid *) alBufferiv },
+ { "alGetBufferf", (ALvoid *) alGetBufferf },
+ { "alGetBuffer3f", (ALvoid *) alGetBuffer3f },
+ { "alGetBufferfv", (ALvoid *) alGetBufferfv },
+ { "alGetBufferi", (ALvoid *) alGetBufferi },
+ { "alGetBuffer3i", (ALvoid *) alGetBuffer3i },
+ { "alGetBufferiv", (ALvoid *) alGetBufferiv },
+ { "alDopplerFactor", (ALvoid *) alDopplerFactor },
+ { "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
+ { "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
+ { "alDistanceModel", (ALvoid *) alDistanceModel },
+ { NULL, (ALvoid *) NULL } };
+
+static ALenums enumeration[]={
+ // Types
+ { (ALchar *)"AL_INVALID", AL_INVALID },
+ { (ALchar *)"AL_NONE", AL_NONE },
+ { (ALchar *)"AL_FALSE", AL_FALSE },
+ { (ALchar *)"AL_TRUE", AL_TRUE },
+
+ // Source and Listener Properties
+ { (ALchar *)"AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE },
+ { (ALchar *)"AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE },
+ { (ALchar *)"AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE },
+ { (ALchar *)"AL_PITCH", AL_PITCH },
+ { (ALchar *)"AL_POSITION", AL_POSITION },
+ { (ALchar *)"AL_DIRECTION", AL_DIRECTION },
+ { (ALchar *)"AL_VELOCITY", AL_VELOCITY },
+ { (ALchar *)"AL_LOOPING", AL_LOOPING },
+ { (ALchar *)"AL_BUFFER", AL_BUFFER },
+ { (ALchar *)"AL_GAIN", AL_GAIN },
+ { (ALchar *)"AL_MIN_GAIN", AL_MIN_GAIN },
+ { (ALchar *)"AL_MAX_GAIN", AL_MAX_GAIN },
+ { (ALchar *)"AL_ORIENTATION", AL_ORIENTATION },
+ { (ALchar *)"AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE },
+ { (ALchar *)"AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR },
+ { (ALchar *)"AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN },
+ { (ALchar *)"AL_MAX_DISTANCE", AL_MAX_DISTANCE },
+ { (ALchar *)"AL_SEC_OFFSET", AL_SEC_OFFSET },
+ { (ALchar *)"AL_SAMPLE_OFFSET", AL_SAMPLE_OFFSET },
+ { (ALchar *)"AL_BYTE_OFFSET", AL_BYTE_OFFSET },
+ { (ALchar *)"AL_SOURCE_TYPE", AL_SOURCE_TYPE },
+ { (ALchar *)"AL_STATIC", AL_STATIC },
+ { (ALchar *)"AL_STREAMING", AL_STREAMING },
+ { (ALchar *)"AL_UNDETERMINED", AL_UNDETERMINED },
+
+ // Source State information
+ { (ALchar *)"AL_SOURCE_STATE", AL_SOURCE_STATE },
+ { (ALchar *)"AL_INITIAL", AL_INITIAL },
+ { (ALchar *)"AL_PLAYING", AL_PLAYING },
+ { (ALchar *)"AL_PAUSED", AL_PAUSED },
+ { (ALchar *)"AL_STOPPED", AL_STOPPED },
+
+ // Queue information
+ { (ALchar *)"AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
+ { (ALchar *)"AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
+
+ // Buffer Formats
+ { (ALchar *)"AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
+ { (ALchar *)"AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
+ { (ALchar *)"AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
+ { (ALchar *)"AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
+ { (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
+ { (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
+ { (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
+ { (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
+
+ // Buffer attributes
+ { (ALchar *)"AL_FREQUENCY", AL_FREQUENCY },
+ { (ALchar *)"AL_BITS", AL_BITS },
+ { (ALchar *)"AL_CHANNELS", AL_CHANNELS },
+ { (ALchar *)"AL_SIZE", AL_SIZE },
+
+ // Buffer States (not supported yet)
+ { (ALchar *)"AL_UNUSED", AL_UNUSED },
+ { (ALchar *)"AL_PENDING", AL_PENDING },
+ { (ALchar *)"AL_PROCESSED", AL_PROCESSED },
+
+ // AL Error Messages
+ { (ALchar *)"AL_NO_ERROR", AL_NO_ERROR },
+ { (ALchar *)"AL_INVALID_NAME", AL_INVALID_NAME },
+ { (ALchar *)"AL_INVALID_ENUM", AL_INVALID_ENUM },
+ { (ALchar *)"AL_INVALID_VALUE", AL_INVALID_VALUE },
+ { (ALchar *)"AL_INVALID_OPERATION", AL_INVALID_OPERATION },
+ { (ALchar *)"AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY },
+
+ // Context strings
+ { (ALchar *)"AL_VENDOR", AL_VENDOR },
+ { (ALchar *)"AL_VERSION", AL_VERSION },
+ { (ALchar *)"AL_RENDERER", AL_RENDERER },
+ { (ALchar *)"AL_EXTENSIONS", AL_EXTENSIONS },
+
+ // Global states
+ { (ALchar *)"AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR },
+ { (ALchar *)"AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY },
+ { (ALchar *)"AL_DISTANCE_MODEL", AL_DISTANCE_MODEL },
+ { (ALchar *)"AL_SPEED_OF_SOUND", AL_SPEED_OF_SOUND },
+
+ // Distance Models
+ { (ALchar *)"AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE },
+ { (ALchar *)"AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED },
+ { (ALchar *)"AL_LINEAR_DISTANCE", AL_LINEAR_DISTANCE },
+ { (ALchar *)"AL_LINEAR_DISTANCE_CLAMPED", AL_LINEAR_DISTANCE_CLAMPED },
+ { (ALchar *)"AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
+ { (ALchar *)"AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
+
+ // Default
+ { (ALchar *)NULL, (ALenum ) 0 } };
+
+
+
+ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
+{
+ ALboolean bIsSupported = AL_FALSE;
+ ALCcontext *pContext;
+ char *ptr, *ext;
+
+ if (!extName)
+ {
+ alSetError(AL_INVALID_VALUE);
+ return AL_FALSE;
+ }
+
+ pContext = alcGetCurrentContext();
+ if(!pContext)
+ {
+ alSetError(AL_INVALID_OPERATION);
+ return AL_FALSE;
+ }
+
+ ext = strdup(extName);
+ ptr = ext;
+ do {
+ *ptr = toupper(*ptr);
+ } while(*(ptr++));
+
+ SuspendContext(pContext);
+
+ ptr = pContext->ExtensionList;
+ while((ptr=strstr(ptr, ext)) != NULL)
+ {
+ if(ptr == pContext->ExtensionList || ptr[-1] == ' ')
+ {
+ char e = ptr[strlen(ext)];
+ if(e == ' ' || e == 0)
+ {
+ bIsSupported = AL_TRUE;
+ break;
+ }
+ }
+ ptr++;
+ }
+
+ ProcessContext(pContext);
+
+ free(ext);
+ return bIsSupported;
+}
+
+
+ALAPI ALvoid * ALAPIENTRY alGetProcAddress(const ALchar *funcName)
+{
+ ALsizei i = 0;
+
+ while(function[i].funcName &&
+ strcmp((char*)function[i].funcName, (char*)funcName) != 0)
+ i++;
+
+ return function[i].address;
+}
+
+/* NOTE: This function must be able to run without a context! */
+ALAPI ALenum ALAPIENTRY alGetEnumValue(const ALchar *enumName)
+{
+ ALsizei i = 0;
+
+ while(enumeration[i].enumName &&
+ strcmp(enumeration[i].enumName, enumName) != 0)
+ i++;
+
+ return enumeration[i].value;
+}
diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c
new file mode 100644
index 00000000..97fc593c
--- /dev/null
+++ b/OpenAL32/alListener.c
@@ -0,0 +1,513 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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 "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alListener.h"
+
+ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch (eParam)
+ {
+ case AL_GAIN:
+ if (flValue >= 0.0f)
+ pContext->Listener.Gain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ pContext->Listener.Position[0] = flValue1;
+ pContext->Listener.Position[1] = flValue2;
+ pContext->Listener.Position[2] = flValue3;
+ break;
+
+ case AL_VELOCITY:
+ pContext->Listener.Velocity[0] = flValue1;
+ pContext->Listener.Velocity[1] = flValue2;
+ pContext->Listener.Velocity[2] = flValue3;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ if (pflValues[0] >= 0.0f)
+ pContext->Listener.Gain = pflValues[0];
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_POSITION:
+ pContext->Listener.Position[0] = pflValues[0];
+ pContext->Listener.Position[1] = pflValues[1];
+ pContext->Listener.Position[2] = pflValues[2];
+ break;
+
+ case AL_VELOCITY:
+ pContext->Listener.Velocity[0] = pflValues[0];
+ pContext->Listener.Velocity[1] = pflValues[1];
+ pContext->Listener.Velocity[2] = pflValues[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ pContext->Listener.Forward[0] = pflValues[0];
+ pContext->Listener.Forward[1] = pflValues[1];
+ pContext->Listener.Forward[2] = pflValues[2];
+ pContext->Listener.Up[0] = pflValues[3];
+ pContext->Listener.Up[1] = pflValues[4];
+ pContext->Listener.Up[2] = pflValues[5];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListeneri(ALenum eParam, ALint lValue)
+{
+ ALCcontext *pContext;
+
+ (void)lValue;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch (eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
+{
+ ALCcontext *pContext;
+ ALfloat flValues[6];
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ flValues[0] = (ALfloat)plValues[0];
+ flValues[1] = (ALfloat)plValues[1];
+ flValues[2] = (ALfloat)plValues[2];
+ alListenerfv(eParam, flValues);
+ break;
+
+ case AL_ORIENTATION:
+ flValues[0] = (ALfloat)plValues[0];
+ flValues[1] = (ALfloat)plValues[1];
+ flValues[2] = (ALfloat)plValues[2];
+ flValues[3] = (ALfloat)plValues[3];
+ flValues[4] = (ALfloat)plValues[4];
+ flValues[5] = (ALfloat)plValues[5];
+ alListenerfv(eParam, flValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ *pflValue = pContext->Listener.Gain;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ *pflValue1 = pContext->Listener.Position[0];
+ *pflValue2 = pContext->Listener.Position[1];
+ *pflValue3 = pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ *pflValue1 = pContext->Listener.Velocity[0];
+ *pflValue2 = pContext->Listener.Velocity[1];
+ *pflValue3 = pContext->Listener.Velocity[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ pflValues[0] = pContext->Listener.Gain;
+ break;
+
+ case AL_POSITION:
+ pflValues[0] = pContext->Listener.Position[0];
+ pflValues[1] = pContext->Listener.Position[1];
+ pflValues[2] = pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ pflValues[0] = pContext->Listener.Velocity[0];
+ pflValues[1] = pContext->Listener.Velocity[1];
+ pflValues[2] = pContext->Listener.Velocity[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ pflValues[0] = pContext->Listener.Forward[0];
+ pflValues[1] = pContext->Listener.Forward[1];
+ pflValues[2] = pContext->Listener.Forward[2];
+ pflValues[3] = pContext->Listener.Up[0];
+ pflValues[4] = pContext->Listener.Up[1];
+ pflValues[5] = pContext->Listener.Up[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ switch (eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ *plValue1 = (ALint)pContext->Listener.Position[0];
+ *plValue2 = (ALint)pContext->Listener.Position[1];
+ *plValue3 = (ALint)pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ *plValue1 = (ALint)pContext->Listener.Velocity[0];
+ *plValue2 = (ALint)pContext->Listener.Velocity[1];
+ *plValue3 = (ALint)pContext->Listener.Velocity[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ plValues[0] = (ALint)pContext->Listener.Position[0];
+ plValues[1] = (ALint)pContext->Listener.Position[1];
+ plValues[2] = (ALint)pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ plValues[0] = (ALint)pContext->Listener.Velocity[0];
+ plValues[1] = (ALint)pContext->Listener.Velocity[1];
+ plValues[2] = (ALint)pContext->Listener.Velocity[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ plValues[0] = (ALint)pContext->Listener.Forward[0];
+ plValues[1] = (ALint)pContext->Listener.Forward[1];
+ plValues[2] = (ALint)pContext->Listener.Forward[2];
+ plValues[3] = (ALint)pContext->Listener.Up[0];
+ plValues[4] = (ALint)pContext->Listener.Up[1];
+ plValues[5] = (ALint)pContext->Listener.Up[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
new file mode 100644
index 00000000..90d70939
--- /dev/null
+++ b/OpenAL32/alSource.c
@@ -0,0 +1,2108 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alSource.h"
+
+ALvoid InitSourceParams(ALsource *pSource);
+ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset);
+ALvoid ApplyOffset(ALsource *pSource, ALboolean bUpdateContext);
+ALint GetByteOffset(ALsource *pSource);
+
+ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
+{
+ ALCcontext *Context;
+ ALCdevice *Device;
+ ALsizei i=0;
+
+ Context = alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (n > 0)
+ {
+ Device = alcGetContextsDevice(Context);
+
+ if (Device)
+ {
+ // Check that enough memory has been allocted in the 'sources' array for n Sources
+ if (!IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
+ {
+ // Check that the requested number of sources can be generated
+ if ((Context->SourceCount + n) <= Device->MaxNoOfSources)
+ {
+ ALsource **list = &Context->Source;
+ while(*list)
+ list = &(*list)->next;
+
+ // Add additional sources to the list (Source->next points to the location for the next Source structure)
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALsource));
+ if(*list)
+ {
+ sources[i]=(ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->source = sources[i];
+
+ InitSourceParams(*list);
+ Context->SourceCount++;
+ i++;
+
+ list = &(*list)->next;
+ }
+ }
+
+ // If we didn't create all the Sources, we must have run out or memory
+ if(i != n)
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ // Not enough resources to create the Sources
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Bad pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // No Device created, or attached to Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALCdevice *Device;
+ ALsource *ALSource;
+ ALsource **list;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context = alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (n >= 0)
+ {
+ Device = alcGetContextsDevice(Context);
+
+ if (Device)
+ {
+ if ((ALuint)n <= Context->SourceCount)
+ {
+ // Check that all Sources are valid (and can therefore be deleted)
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ // All Sources are valid, and can be deleted
+ for (i = 0; i < n; i++)
+ {
+ // Recheck that the Source is valid, because there could be duplicated Source names
+ if (alIsSource(sources[i]))
+ {
+ ALSource=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ alSourceStop((ALuint)ALSource->source);
+
+ // For each buffer in the source's queue, decrement its reference counter and remove it
+ while (ALSource->queue != NULL)
+ {
+ ALBufferList = ALSource->queue;
+ // Decrement buffer's reference counter
+ if (ALBufferList->buffer != 0)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
+ // Update queue to point to next element in list
+ ALSource->queue = ALBufferList->next;
+ // Release memory allocated for buffer list item
+ free(ALBufferList);
+ }
+
+ // Decrement Source count
+ Context->SourceCount--;
+
+ // Remove Source from list of Sources
+ list = &Context->Source;
+ while(*list && *list != ALSource)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+ ALTHUNK_REMOVEENTRY(ALSource->source);
+
+ memset(ALSource,0,sizeof(ALsource));
+ free(ALSource);
+ }
+ }
+
+ }
+ }
+ else
+ {
+ // Trying to delete more Sources than have been generated
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ // No Device created, or attached to Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALboolean ALAPIENTRY alIsSource(ALuint source)
+{
+ ALboolean result=AL_FALSE;
+ ALCcontext *Context;
+ ALsource *Source;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ // To determine if this is a valid Source name, look through the list of generated Sources
+ Source = Context->Source;
+ while(Source)
+ {
+ if (Source == (ALsource*)ALTHUNK_LOOKUPENTRY(source))
+ {
+ result = AL_TRUE;
+ break;
+ }
+
+ Source = Source->next;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return result;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_PITCH:
+ if (flValue >= 0.0f)
+ {
+ pSource->flPitch = flValue;
+ if(pSource->flPitch < 0.001f)
+ pSource->flPitch = 0.001f;
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ if ((flValue >= 0.0f) && (flValue <= 360.0f))
+ pSource->flInnerAngle = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ if ((flValue >= 0.0f) && (flValue <= 360.0f))
+ pSource->flOuterAngle = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_GAIN:
+ if (flValue >= 0.0f)
+ pSource->flGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MAX_DISTANCE:
+ if (flValue >= 0.0f)
+ pSource->flMaxDistance = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ if (flValue >= 0.0f)
+ pSource->flRollOffFactor = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ if (flValue >= 0.0f)
+ pSource->flRefDistance = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MIN_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flMinGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MAX_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flMaxGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flOuterGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (flValue >= 0.0f)
+ {
+ pSource->lOffsetType = eParam;
+
+ // Store Offset (convert Seconds into Milliseconds)
+ if (eParam == AL_SEC_OFFSET)
+ pSource->lOffset = (ALint)(flValue * 1000.0f);
+ else
+ pSource->lOffset = (ALint)flValue;
+
+ if ((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED))
+ ApplyOffset(pSource, AL_TRUE);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ // Invalid context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+ switch(eParam)
+ {
+ case AL_POSITION:
+ pSource->vPosition[0] = flValue1;
+ pSource->vPosition[1] = flValue2;
+ pSource->vPosition[2] = flValue3;
+ break;
+
+ case AL_VELOCITY:
+ pSource->vVelocity[0] = flValue1;
+ pSource->vVelocity[1] = flValue2;
+ pSource->vVelocity[2] = flValue3;
+ break;
+
+ case AL_DIRECTION:
+ pSource->vOrientation[0] = flValue1;
+ pSource->vOrientation[1] = flValue2;
+ pSource->vOrientation[2] = flValue3;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_PITCH:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_GAIN:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ case AL_MIN_GAIN:
+ case AL_MAX_GAIN:
+ case AL_CONE_OUTER_GAIN:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ alSourcef(source, eParam, pflValues[0]);
+ break;
+
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALbufferlistitem *pALBufferListItem;
+ ALint Counter = 0;
+ ALint DataSize = 0;
+ ALint BufferSize;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ alSourcef(source, eParam, (ALfloat)lValue);
+ break;
+
+ case AL_SOURCE_RELATIVE:
+ if ((lValue == AL_FALSE) || (lValue == AL_TRUE))
+ pSource->bHeadRelative = (ALboolean)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ if ((lValue >= 0) && (lValue <= 360))
+ pSource->flInnerAngle = (float)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ if ((lValue >= 0) && (lValue <= 360))
+ pSource->flOuterAngle = (float)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_LOOPING:
+ if ((lValue == AL_FALSE) || (lValue == AL_TRUE))
+ pSource->bLooping = (ALboolean)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_BUFFER:
+ if ((pSource->state == AL_STOPPED) || (pSource->state == AL_INITIAL))
+ {
+ if (alIsBuffer(lValue))
+ {
+ // Remove all elements in the queue
+ while (pSource->queue != NULL)
+ {
+ pALBufferListItem = pSource->queue;
+ pSource->queue = pALBufferListItem->next;
+ // Decrement reference counter for buffer
+ if (pALBufferListItem->buffer)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem->buffer)))->refcount--;
+ // Record size of buffer
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pALBufferListItem->buffer))->size;
+ DataSize += BufferSize;
+ // Increment the number of buffers removed from queue
+ Counter++;
+ // Release memory for buffer list item
+ free(pALBufferListItem);
+ // Decrement the number of buffers in the queue
+ pSource->BuffersInQueue--;
+ }
+
+ // Add the buffer to the queue (as long as it is NOT the NULL buffer)
+ if (lValue != 0)
+ {
+ // Source is now in STATIC mode
+ pSource->lSourceType = AL_STATIC;
+
+ // Add the selected buffer to the queue
+ pALBufferListItem = malloc(sizeof(ALbufferlistitem));
+ pALBufferListItem->buffer = lValue;
+ pALBufferListItem->bufferstate = PENDING;
+ pALBufferListItem->flag = 0;
+ pALBufferListItem->next = NULL;
+
+ pSource->queue = pALBufferListItem;
+ pSource->BuffersInQueue = 1;
+
+ DataSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(lValue))->size;
+
+ // Increment reference counter for buffer
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(lValue)))->refcount++;
+ }
+ else
+ {
+ // Source is now in UNDETERMINED mode
+ pSource->lSourceType = AL_UNDETERMINED;
+ }
+
+ // Set Buffers Processed
+ pSource->BuffersProcessed = 0;
+
+ // Update AL_BUFFER parameter
+ pSource->ulBufferID = lValue;
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_SOURCE_STATE:
+ // Query only
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (lValue >= 0)
+ {
+ pSource->lOffsetType = eParam;
+
+ // Store Offset (convert Seconds into Milliseconds)
+ if (eParam == AL_SEC_OFFSET)
+ pSource->lOffset = lValue * 1000;
+ else
+ pSource->lOffset = lValue;
+
+ if ((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED))
+ ApplyOffset(pSource, AL_TRUE);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_SOURCE_RELATIVE:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_LOOPING:
+ case AL_BUFFER:
+ case AL_SOURCE_STATE:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ alSourcei(source, eParam, plValues[0]);
+ break;
+
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALfloat flOffset;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_PITCH:
+ *pflValue = pSource->flPitch;
+ break;
+
+ case AL_GAIN:
+ *pflValue = pSource->flGain;
+ break;
+
+ case AL_MIN_GAIN:
+ *pflValue = pSource->flMinGain;
+ break;
+
+ case AL_MAX_GAIN:
+ *pflValue = pSource->flMaxGain;
+ break;
+
+ case AL_MAX_DISTANCE:
+ *pflValue = pSource->flMaxDistance;
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ *pflValue = pSource->flRollOffFactor;
+ break;
+
+ case AL_CONE_OUTER_GAIN:
+ *pflValue = pSource->flOuterGain;
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (GetSourceOffset(pSource, eParam, &flOffset))
+ *pflValue = flOffset;
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ *pflValue = pSource->flInnerAngle;
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ *pflValue = pSource->flOuterAngle;
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ *pflValue = pSource->flRefDistance;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ *pflValue1 = pSource->vPosition[0];
+ *pflValue2 = pSource->vPosition[1];
+ *pflValue3 = pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ *pflValue1 = pSource->vVelocity[0];
+ *pflValue2 = pSource->vVelocity[1];
+ *pflValue3 = pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ *pflValue1 = pSource->vOrientation[0];
+ *pflValue2 = pSource->vOrientation[1];
+ *pflValue3 = pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_PITCH:
+ case AL_GAIN:
+ case AL_MIN_GAIN:
+ case AL_MAX_GAIN:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_CONE_OUTER_GAIN:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_REFERENCE_DISTANCE:
+ alGetSourcef(source, eParam, pflValues);
+ break;
+
+ case AL_POSITION:
+ pflValues[0] = pSource->vPosition[0];
+ pflValues[1] = pSource->vPosition[1];
+ pflValues[2] = pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ pflValues[0] = pSource->vVelocity[0];
+ pflValues[1] = pSource->vVelocity[1];
+ pflValues[2] = pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ pflValues[0] = pSource->vOrientation[0];
+ pflValues[1] = pSource->vOrientation[1];
+ pflValues[2] = pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALfloat flOffset;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_MAX_DISTANCE:
+ *plValue = (ALint)pSource->flMaxDistance;
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ *plValue = (ALint)pSource->flRollOffFactor;
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ *plValue = (ALint)pSource->flRefDistance;
+ break;
+
+ case AL_SOURCE_RELATIVE:
+ *plValue = pSource->bHeadRelative;
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ *plValue = (ALint)pSource->flInnerAngle;
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ *plValue = (ALint)pSource->flOuterAngle;
+ break;
+
+ case AL_LOOPING:
+ *plValue = pSource->bLooping;
+ break;
+
+ case AL_BUFFER:
+ *plValue = pSource->ulBufferID;
+ break;
+
+ case AL_SOURCE_STATE:
+ *plValue = pSource->state;
+ break;
+
+ case AL_BUFFERS_QUEUED:
+ *plValue = pSource->BuffersInQueue;
+ break;
+
+ case AL_BUFFERS_PROCESSED:
+ if(pSource->bLooping)
+ {
+ /* Buffers on a looping source are in a perpetual state
+ * of PENDING, so don't report any as PROCESSED */
+ *plValue = 0;
+ }
+ else
+ *plValue = pSource->BuffersProcessed;
+ break;
+
+ case AL_SOURCE_TYPE:
+ *plValue = pSource->lSourceType;
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (GetSourceOffset(pSource, eParam, &flOffset))
+ *plValue = (ALint)flOffset;
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetSource3i(ALuint source, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ *plValue1 = (ALint)pSource->vPosition[0];
+ *plValue2 = (ALint)pSource->vPosition[1];
+ *plValue3 = (ALint)pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ *plValue1 = (ALint)pSource->vVelocity[0];
+ *plValue2 = (ALint)pSource->vVelocity[1];
+ *plValue3 = (ALint)pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ *plValue1 = (ALint)pSource->vOrientation[0];
+ *plValue2 = (ALint)pSource->vOrientation[1];
+ *plValue3 = (ALint)pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_SOURCE_RELATIVE:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_LOOPING:
+ case AL_BUFFER:
+ case AL_SOURCE_STATE:
+ case AL_BUFFERS_QUEUED:
+ case AL_BUFFERS_PROCESSED:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ case AL_SOURCE_TYPE:
+ alGetSourcei(source, eParam, plValues);
+ break;
+
+ case AL_POSITION:
+ plValues[0] = (ALint)pSource->vPosition[0];
+ plValues[1] = (ALint)pSource->vPosition[1];
+ plValues[2] = (ALint)pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ plValues[0] = (ALint)pSource->vVelocity[0];
+ plValues[1] = (ALint)pSource->vVelocity[1];
+ plValues[2] = (ALint)pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ plValues[0] = (ALint)pSource->vOrientation[0];
+ plValues[1] = (ALint)pSource->vOrientation[1];
+ plValues[2] = (ALint)pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcePlay(ALuint source)
+{
+ alSourcePlayv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALbufferlistitem *ALBufferList;
+ ALboolean bSourcesValid = AL_TRUE;
+ ALboolean bPlay;
+ ALsizei i;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pSourceList)
+ {
+ // Check that all the Sources are valid
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsSource(pSourceList[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i = 0; i < n; i++)
+ {
+ // Assume Source won't need to play
+ bPlay = AL_FALSE;
+
+ pSource = ((ALsource*)ALTHUNK_LOOKUPENTRY(pSourceList[i]));
+
+ // Check that there is a queue containing at least one non-null, non zero length AL Buffer
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ if ((ALBufferList->buffer != 0) && (((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALBufferList->buffer))->size))
+ {
+ bPlay = AL_TRUE;
+ break;
+ }
+ ALBufferList = ALBufferList->next;
+ }
+
+ if (bPlay)
+ {
+ if (pSource->state != AL_PAUSED)
+ {
+ pSource->state = AL_PLAYING;
+ pSource->inuse = AL_TRUE;
+ pSource->play = AL_TRUE;
+ pSource->position = 0;
+ pSource->position_fraction = 0;
+ pSource->BuffersProcessed = 0;
+ pSource->BuffersPlayed = 0;
+ pSource->BufferPosition = 0;
+ pSource->lBytesPlayed = 0;
+
+ pSource->ulBufferID = pSource->queue->buffer;
+
+ // Make sure all the Buffers in the queue are marked as PENDING
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ ALBufferList->bufferstate = PENDING;
+ ALBufferList = ALBufferList->next;
+ }
+ }
+ else
+ {
+ pSource->state = AL_PLAYING;
+ pSource->inuse = AL_TRUE;
+ pSource->play = AL_TRUE;
+ }
+
+ // Check if an Offset has been set
+ if (pSource->lOffset)
+ ApplyOffset(pSource, AL_FALSE);
+ }
+ else
+ {
+ // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ ALBufferList->bufferstate = PROCESSED;
+ ALBufferList = ALBufferList->next;
+ }
+
+ pSource->BuffersPlayed = pSource->BuffersProcessed = pSource->BuffersInQueue;
+ }
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePause(ALuint source)
+{
+ alSourcePausev(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state==AL_PLAYING)
+ {
+ Source->state=AL_PAUSED;
+ Source->inuse=AL_FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceStop(ALuint source)
+{
+ alSourceStopv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALbufferlistitem *ALBufferListItem;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state!=AL_INITIAL)
+ {
+ Source->state=AL_STOPPED;
+ Source->inuse=AL_FALSE;
+ Source->BuffersPlayed = Source->BuffersProcessed = Source->BuffersInQueue;
+ ALBufferListItem= Source->queue;
+ while (ALBufferListItem != NULL)
+ {
+ ALBufferListItem->bufferstate = PROCESSED;
+ ALBufferListItem = ALBufferListItem->next;
+ }
+ }
+ Source->lOffset = 0;
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceRewind(ALuint source)
+{
+ alSourceRewindv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALbufferlistitem *ALBufferListItem;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state!=AL_INITIAL)
+ {
+ Source->state=AL_INITIAL;
+ Source->inuse=AL_FALSE;
+ Source->position=0;
+ Source->position_fraction=0;
+ Source->BuffersProcessed = 0;
+ ALBufferListItem= Source->queue;
+ while (ALBufferListItem != NULL)
+ {
+ ALBufferListItem->bufferstate = PENDING;
+ ALBufferListItem = ALBufferListItem->next;
+ }
+ if (Source->queue)
+ Source->ulBufferID = Source->queue->buffer;
+ }
+ Source->lOffset = 0;
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, const ALuint* buffers )
+{
+ ALCcontext *Context;
+ ALsource *ALSource;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALbufferlistitem *ALBufferListStart;
+ ALuint DataSize;
+ ALuint BufferSize;
+ ALint iFrequency;
+ ALint iFormat;
+ ALboolean bBuffersValid = AL_TRUE;
+
+ if (n == 0)
+ return;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ DataSize = 0;
+ BufferSize = 0;
+
+ // Check that all buffers are valid or zero and that the source is valid
+
+ // Check that this is a valid source
+ if (alIsSource(source))
+ {
+ ALSource = (ALsource*)ALTHUNK_LOOKUPENTRY(source);
+
+ // Check that this is not a STATIC Source
+ if (ALSource->lSourceType != AL_STATIC)
+ {
+ iFrequency = -1;
+ iFormat = -1;
+
+ // Check existing Queue (if any) for a valid Buffers and get its frequency and format
+ ALBufferList = ALSource->queue;
+ while (ALBufferList)
+ {
+ if (ALBufferList->buffer)
+ {
+ iFrequency = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->frequency;
+ iFormat = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->format;
+ break;
+ }
+ ALBufferList = ALBufferList->next;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ if (alIsBuffer(buffers[i]))
+ {
+ if (buffers[i])
+ {
+ if ((iFrequency == -1) && (iFormat == -1))
+ {
+ iFrequency = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->frequency;
+ iFormat = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->format;
+ }
+ else
+ {
+ if ((iFrequency != ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->frequency) ||
+ (iFormat != ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->format))
+ {
+ alSetError(AL_INVALID_OPERATION);
+ bBuffersValid = AL_FALSE;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ bBuffersValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bBuffersValid)
+ {
+ // Change Source Type
+ ALSource->lSourceType = AL_STREAMING;
+
+ // All buffers are valid - so add them to the list
+ ALBufferListStart = malloc(sizeof(ALbufferlistitem));
+ ALBufferListStart->buffer = buffers[0];
+ ALBufferListStart->bufferstate = PENDING;
+ ALBufferListStart->flag = 0;
+ ALBufferListStart->next = NULL;
+
+ if (buffers[0])
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[0]))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+
+ // Increment reference counter for buffer
+ if (buffers[0])
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[0])))->refcount++;
+
+ ALBufferList = ALBufferListStart;
+
+ for (i = 1; i < n; i++)
+ {
+ ALBufferList->next = malloc(sizeof(ALbufferlistitem));
+ ALBufferList->next->buffer = buffers[i];
+ ALBufferList->next->bufferstate = PENDING;
+ ALBufferList->next->flag = 0;
+ ALBufferList->next->next = NULL;
+
+ if (buffers[i])
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[i]))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+
+ // Increment reference counter for buffer
+ if (buffers[i])
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->refcount++;
+
+ ALBufferList = ALBufferList->next;
+ }
+
+ if (ALSource->queue == NULL)
+ {
+ ALSource->queue = ALBufferListStart;
+ // Update Current Buffer
+ ALSource->ulBufferID = ALBufferListStart->buffer;
+ }
+ else
+ {
+ // Find end of queue
+ ALBufferList = ALSource->queue;
+ while (ALBufferList->next != NULL)
+ {
+ ALBufferList = ALBufferList->next;
+ }
+
+ ALBufferList->next = ALBufferListStart;
+ }
+
+ // Update number of buffers in queue
+ ALSource->BuffersInQueue += n;
+ }
+ }
+ else
+ {
+ // Invalid Source Type (can't queue on a Static Source)
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+// Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
+// an array of buffer IDs that are to be filled with the names of the buffers removed
+ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers )
+{
+ ALCcontext *Context;
+ ALsource *ALSource;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALuint DataSize;
+ ALuint BufferSize;
+ ALuint BufferID;
+ ALboolean bBuffersProcessed;
+
+ if (n == 0)
+ return;
+
+ DataSize = 0;
+ BufferSize = 0;
+ bBuffersProcessed = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (alIsSource(source))
+ {
+ ALSource = (ALsource*)ALTHUNK_LOOKUPENTRY(source);
+
+ // Check that all 'n' buffers have been processed
+ ALBufferList = ALSource->queue;
+ for (i = 0; i < n; i++)
+ {
+ if ((ALBufferList != NULL) && (ALBufferList->bufferstate == PROCESSED))
+ {
+ ALBufferList = ALBufferList->next;
+ }
+ else
+ {
+ bBuffersProcessed = AL_FALSE;
+ break;
+ }
+ }
+
+ // If all 'n' buffers have been processed, remove them from the queue
+ if (bBuffersProcessed)
+ {
+ for (i = 0; i < n; i++)
+ {
+ ALBufferList = ALSource->queue;
+
+ ALSource->queue = ALBufferList->next;
+ // Record name of buffer
+ buffers[i] = ALBufferList->buffer;
+ // Decrement buffer reference counter
+ if (ALBufferList->buffer)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
+ // Record size of buffer
+ if (ALBufferList->buffer)
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALBufferList->buffer))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+ // Release memory for buffer list item
+ free(ALBufferList);
+ ALSource->BuffersInQueue--;
+ ALSource->BuffersProcessed--;
+ }
+
+ if (ALSource->state != AL_PLAYING)
+ {
+ if (ALSource->queue)
+ BufferID = ALSource->queue->buffer;
+ else
+ BufferID = 0;
+
+ ALSource->ulBufferID = BufferID;
+ }
+
+ if((ALuint)n > ALSource->BuffersPlayed)
+ {
+ ALSource->BuffersPlayed = 0;
+ ALSource->BufferPosition = 0;
+ }
+ else
+ ALSource->BuffersPlayed -= n;
+ }
+ else
+ {
+ // Some buffers can't be unqueue because they have not been processed
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALvoid InitSourceParams(ALsource *pSource)
+{
+ pSource->flInnerAngle = 360.0f;
+ pSource->flOuterAngle = 360.0f;
+ pSource->flPitch = 1.0f;
+ pSource->vPosition[0] = 0.0f;
+ pSource->vPosition[1] = 0.0f;
+ pSource->vPosition[2] = 0.0f;
+ pSource->vOrientation[0] = 0.0f;
+ pSource->vOrientation[1] = 0.0f;
+ pSource->vOrientation[2] = 0.0f;
+ pSource->vVelocity[0] = 0.0f;
+ pSource->vVelocity[1] = 0.0f;
+ pSource->vVelocity[2] = 0.0f;
+ pSource->flRefDistance = 1.0f;
+ pSource->flMaxDistance = FLT_MAX;
+ pSource->flRollOffFactor = 1.0f;
+ pSource->bLooping = AL_FALSE;
+ pSource->flGain = 1.0f;
+ pSource->flMinGain = 0.0f;
+ pSource->flMaxGain = 1.0f;
+ pSource->flOuterGain = 0.0f;
+
+ pSource->state = AL_INITIAL;
+ pSource->lSourceType = AL_UNDETERMINED;
+
+ pSource->ulBufferID= 0;
+}
+
+
+/*
+ GetSourceOffset
+
+ Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
+ The offset is relative to the start of the queue (not the start of the current buffer)
+*/
+ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset)
+{
+ ALbufferlistitem *pBufferList;
+ ALfloat flBufferFreq;
+ ALint lBufferSize, lBytesPlayed, lChannels;
+ ALenum eOriginalFormat;
+ ALboolean bReturn = AL_TRUE;
+ ALint lTotalBufferDataSize;
+
+ if (((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED)) && (pSource->ulBufferID))
+ {
+ // Get Current Buffer Size and frequency (in milliseconds)
+ lBufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->size;
+ flBufferFreq = (ALfloat)(((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->frequency);
+ eOriginalFormat = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->eOriginalFormat;
+ lChannels = ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->format == AL_FORMAT_MONO16)?1:2);
+
+ // Get Current BytesPlayed
+ lBytesPlayed = pSource->position * lChannels * 2; // NOTE : This is the byte offset into the *current* buffer
+ // Add byte length of any processed buffers in the queue
+ pBufferList = pSource->queue;
+ while ((pBufferList) && (pBufferList->bufferstate == PROCESSED))
+ {
+ lBytesPlayed += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ lTotalBufferDataSize = 0;
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ lTotalBufferDataSize += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ if (pSource->bLooping)
+ {
+ if (lBytesPlayed < 0)
+ lBytesPlayed = 0;
+ else
+ lBytesPlayed = lBytesPlayed % lTotalBufferDataSize;
+ }
+ else
+ {
+ // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
+ if(lBytesPlayed < 0)
+ lBytesPlayed = 0;
+ if(lBytesPlayed > lTotalBufferDataSize)
+ lBytesPlayed = lTotalBufferDataSize;
+ }
+
+ switch (eName)
+ {
+ case AL_SEC_OFFSET:
+ *pflOffset = ((ALfloat)lBytesPlayed / (lChannels * 2.0f * flBufferFreq));
+ break;
+ case AL_SAMPLE_OFFSET:
+ *pflOffset = (ALfloat)(lBytesPlayed / (lChannels * 2));
+ break;
+ case AL_BYTE_OFFSET:
+ // Take into account the original format of the Buffer
+ if ((eOriginalFormat == AL_FORMAT_MONO8) || (eOriginalFormat == AL_FORMAT_STEREO8))
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed >> 1);
+ }
+ else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ {
+ // Compression rate of the ADPCM supported is 3.6111 to 1
+ lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f);
+ // Round down to nearest ADPCM block
+ *pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels);
+ }
+ else
+ {
+ *pflOffset = (ALfloat)lBytesPlayed;
+ }
+ break;
+ }
+ }
+ else
+ {
+ *pflOffset = 0.0f;
+ }
+
+ return bReturn;
+}
+
+
+/*
+ ApplyOffset
+
+ Apply a playback offset to the Source. This function will update the queue (to correctly
+ mark buffers as 'pending' or 'processed' depending upon the new offset.
+*/
+void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
+{
+ ALbufferlistitem *pBufferList;
+ ALint lBufferSize, lTotalBufferSize;
+ ALint lByteOffset;
+
+ // Get true byte offset
+ lByteOffset = GetByteOffset(pSource);
+
+ // If this is a valid offset apply it
+ if (lByteOffset != -1)
+ {
+ // Sort out the queue (pending and processed states)
+ pBufferList = pSource->queue;
+ lTotalBufferSize = 0;
+ pSource->BuffersPlayed = 0;
+ pSource->BuffersProcessed = 0;
+ while (pBufferList)
+ {
+ lBufferSize = pBufferList->buffer ? ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size : 0;
+
+ if ((lTotalBufferSize + lBufferSize) <= lByteOffset)
+ {
+ // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
+ // update the state to PROCESSED
+ pSource->BuffersPlayed++;
+
+ if (!pSource->bLooping)
+ {
+ pBufferList->bufferstate = PROCESSED;
+ pSource->BuffersProcessed++;
+ }
+ }
+ else if (lTotalBufferSize <= lByteOffset)
+ {
+ // Offset is within this buffer
+ pBufferList->bufferstate = PENDING;
+
+ // Set Current Buffer ID
+ pSource->ulBufferID = pBufferList->buffer;
+
+ // Set current position in this buffer
+ pSource->BufferPosition = lByteOffset - lTotalBufferSize;
+
+ // Set Total Bytes Played to Offset
+ pSource->lBytesPlayed = lByteOffset;
+
+ // SW Mixer Positions are in Samples
+ pSource->position = pSource->BufferPosition / ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->format == AL_FORMAT_MONO16)?2:4);
+ }
+ else
+ {
+ // Offset is before this buffer, so mark as pending
+ pBufferList->bufferstate = PENDING;
+ }
+
+ // Increment the TotalBufferSize
+ lTotalBufferSize += lBufferSize;
+
+ // Move on to next buffer in the Queue
+ pBufferList = pBufferList->next;
+ }
+ }
+ else
+ {
+ if (bUpdateContext)
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ // Clear Offset
+ pSource->lOffset = 0;
+}
+
+
+/*
+ GetByteOffset
+
+ Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
+ offset supplied by the application). This takes into account the fact that the buffer format
+ may have been modifed by AL (e.g 8bit samples are converted to 16bit)
+*/
+ALint GetByteOffset(ALsource *pSource)
+{
+ ALbuffer *pBuffer = NULL;
+ ALbufferlistitem *pBufferList;
+ ALfloat flBufferFreq;
+ ALint lChannels;
+ ALint lByteOffset = -1;
+ ALint lTotalBufferDataSize;
+
+ // Find the first non-NULL Buffer in the Queue
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ {
+ pBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer);
+ break;
+ }
+ pBufferList = pBufferList->next;
+ }
+
+ if (pBuffer)
+ {
+ flBufferFreq = ((ALfloat)pBuffer->frequency);
+ lChannels = (pBuffer->format == AL_FORMAT_MONO16)?1:2;
+
+ // Determine the ByteOffset (and ensure it is block aligned)
+ switch (pSource->lOffsetType)
+ {
+ case AL_BYTE_OFFSET:
+ // Take into consideration the original format
+ if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO8) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO8))
+ {
+ lByteOffset = pSource->lOffset * 2;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ {
+ // Round down to nearest ADPCM block
+ lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels;
+ // Multiply by compression rate
+ lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset);
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else
+ {
+ lByteOffset = pSource->lOffset;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ break;
+
+ case AL_SAMPLE_OFFSET:
+ lByteOffset = pSource->lOffset * lChannels * 2;
+ break;
+
+ case AL_SEC_OFFSET:
+ // Note - lOffset is internally stored as Milliseconds
+ lByteOffset = (ALint)(pSource->lOffset * lChannels * 2.0f * flBufferFreq / 1000.0f);
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ break;
+ }
+
+ lTotalBufferDataSize = 0;
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ lTotalBufferDataSize += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
+ if (lByteOffset >= lTotalBufferDataSize)
+ lByteOffset = -1;
+ }
+
+ return lByteOffset;
+}
diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c
new file mode 100644
index 00000000..06da8a88
--- /dev/null
+++ b/OpenAL32/alState.c
@@ -0,0 +1,677 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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 <stdlib.h>
+#include "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alState.h"
+
+static const ALchar alVendor[] = "OpenAL Community";
+static const ALchar alVersion[] = "1.1";
+static const ALchar alRenderer[] = "OpenAL Sample Implementation";
+
+// Error Messages
+static const ALchar alNoError[] = "No Error";
+static const ALchar alErrInvalidName[] = "Invalid Name";
+static const ALchar alErrInvalidEnum[] = "Invalid Enum";
+static const ALchar alErrInvalidValue[] = "Invalid Value";
+static const ALchar alErrInvalidOp[] = "Invalid Operation";
+static const ALchar alErrOutOfMemory[] = "Out of Memory";
+
+ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+}
+
+ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+}
+
+ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
+{
+ ALCcontext *Context;
+ ALboolean value=AL_FALSE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALboolean ALAPIENTRY alGetBoolean(ALenum pname)
+{
+ ALCcontext *Context;
+ ALboolean value=AL_FALSE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ if (Context->DopplerFactor != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ if (Context->DopplerVelocity != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ if (Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
+ value = AL_TRUE;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ if (Context->flSpeedOfSound != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALdouble ALAPIENTRY alGetDouble(ALenum pname)
+{
+ ALCcontext *Context;
+ ALdouble value = 0.0;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = (double)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = (double)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (double)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = (double)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALfloat ALAPIENTRY alGetFloat(ALenum pname)
+{
+ ALCcontext *Context;
+ ALfloat value = 0.0f;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (float)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALint ALAPIENTRY alGetInteger(ALenum pname)
+{
+ ALCcontext *Context;
+ ALint value = 0;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = (ALint)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = (ALint)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (ALint)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = (ALint)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (Context->DopplerFactor != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (Context->DopplerVelocity != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (Context->flSpeedOfSound != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetDoublev(ALenum pname,ALdouble *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (double)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (double)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (double)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (double)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetFloatv(ALenum pname,ALfloat *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (float)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetIntegerv(ALenum pname,ALint *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (ALint)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (ALint)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (ALint)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (ALint)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
+{
+ const ALchar *value;
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if(!pContext)
+ {
+ alSetError(AL_INVALID_OPERATION);
+ return NULL;
+ }
+
+ SuspendContext(pContext);
+
+ switch(pname)
+ {
+ case AL_VENDOR:
+ value=alVendor;
+ break;
+
+ case AL_VERSION:
+ value=alVersion;
+ break;
+
+ case AL_RENDERER:
+ value=alRenderer;
+ break;
+
+ case AL_EXTENSIONS:
+ value=pContext->ExtensionList;//alExtensions;
+ break;
+
+ case AL_NO_ERROR:
+ value=alNoError;
+ break;
+
+ case AL_INVALID_NAME:
+ value=alErrInvalidName;
+ break;
+
+ case AL_INVALID_ENUM:
+ value=alErrInvalidEnum;
+ break;
+
+ case AL_INVALID_VALUE:
+ value=alErrInvalidValue;
+ break;
+
+ case AL_INVALID_OPERATION:
+ value=alErrInvalidOp;
+ break;
+
+ case AL_OUT_OF_MEMORY:
+ value=alErrOutOfMemory;
+ break;
+
+ default:
+ value=NULL;
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+
+ return value;
+}
+
+ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (value>=0.0f)
+ Context->DopplerFactor = value;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (value>0.0f)
+ Context->DopplerVelocity=value;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (flSpeedOfSound > 0.0f)
+ pContext->flSpeedOfSound = flSpeedOfSound;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (value)
+ {
+ case AL_NONE:
+ case AL_INVERSE_DISTANCE:
+ case AL_INVERSE_DISTANCE_CLAMPED:
+ case AL_LINEAR_DISTANCE:
+ case AL_LINEAR_DISTANCE_CLAMPED:
+ case AL_EXPONENT_DISTANCE:
+ case AL_EXPONENT_DISTANCE_CLAMPED:
+ Context->DistanceModel = value;
+ break;
+
+ default:
+ alSetError(AL_INVALID_VALUE);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
diff --git a/OpenAL32/alThunk.c b/OpenAL32/alThunk.c
new file mode 100644
index 00000000..d050d6b4
--- /dev/null
+++ b/OpenAL32/alThunk.c
@@ -0,0 +1,108 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 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 <stdlib.h>
+
+#include "alMain.h"
+#include "alThunk.h"
+
+typedef struct {
+ ALvoid *ptr;
+ ALboolean InUse;
+} ThunkEntry;
+
+static ThunkEntry *g_ThunkArray;
+static ALuint g_ThunkArraySize;
+
+static CRITICAL_SECTION g_ThunkLock;
+
+void alThunkInit(void)
+{
+ InitializeCriticalSection(&g_ThunkLock);
+ g_ThunkArraySize = 1;
+ g_ThunkArray = calloc(1, g_ThunkArraySize * sizeof(ThunkEntry));
+}
+
+void alThunkExit(void)
+{
+ free(g_ThunkArray);
+ g_ThunkArray = NULL;
+ g_ThunkArraySize = 0;
+ DeleteCriticalSection(&g_ThunkLock);
+}
+
+ALuint alThunkAddEntry(ALvoid *ptr)
+{
+ ALuint index;
+
+ EnterCriticalSection(&g_ThunkLock);
+
+ for(index = 0;index < g_ThunkArraySize;index++)
+ {
+ if(g_ThunkArray[index].InUse == AL_FALSE)
+ break;
+ }
+
+ if(index == g_ThunkArraySize)
+ {
+ ThunkEntry *NewList;
+
+ NewList = realloc(g_ThunkArray, g_ThunkArraySize*2 * sizeof(ThunkEntry));
+ if(!NewList)
+ {
+ LeaveCriticalSection(&g_ThunkLock);
+ return 0;
+ }
+ memset(&NewList[g_ThunkArraySize], 0, g_ThunkArraySize*sizeof(ThunkEntry));
+ g_ThunkArraySize *= 2;
+ g_ThunkArray = NewList;
+ }
+
+ g_ThunkArray[index].ptr = ptr;
+ g_ThunkArray[index].InUse = AL_TRUE;
+
+ LeaveCriticalSection(&g_ThunkLock);
+
+ return index+1;
+}
+
+void alThunkRemoveEntry(ALuint index)
+{
+ EnterCriticalSection(&g_ThunkLock);
+
+ if(index > 0 && index <= g_ThunkArraySize)
+ g_ThunkArray[index-1].InUse = AL_FALSE;
+
+ LeaveCriticalSection(&g_ThunkLock);
+}
+
+ALvoid *alThunkLookupEntry(ALuint index)
+{
+ ALvoid *ptr = NULL;
+
+ EnterCriticalSection(&g_ThunkLock);
+
+ if(index > 0 && index <= g_ThunkArraySize)
+ ptr = g_ThunkArray[index-1].ptr;
+
+ LeaveCriticalSection(&g_ThunkLock);
+
+ return ptr;
+}
diff --git a/Router/OpenAL32.cpp b/Router/OpenAL32.cpp
new file mode 100644
index 00000000..8c84148b
--- /dev/null
+++ b/Router/OpenAL32.cpp
@@ -0,0 +1,135 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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 <windows.h>
+#include "OpenAL32.h"
+
+
+void CleanDeviceEnumeration();
+void CleanDeviceList(ALDEVICE *pDeviceList);
+
+//*****************************************************************************
+// DllMain
+//*****************************************************************************
+//
+BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID reserved)
+{
+ BOOL result = TRUE;
+
+ // Perform actions based on the reason for calling.
+ switch(reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Create the context list lock so I can safely add/remove contexts.
+ result = alListCreate(&alContextList);
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // Do thread-specific initialization.
+ break;
+
+ case DLL_THREAD_DETACH:
+ // Do thread-specific cleanup.
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ CleanDeviceEnumeration();
+ alListFree(alContextList);
+ alContextList = 0;
+ break;
+ }
+
+ return TRUE;
+}
+
+
+void CleanDeviceEnumeration()
+{
+ if (pszDefaultDeviceSpecifier)
+ {
+ free(pszDefaultDeviceSpecifier);
+ pszDefaultDeviceSpecifier = NULL;
+ }
+
+ if (pszDeviceSpecifierList)
+ {
+ free(pszDeviceSpecifierList);
+ pszDeviceSpecifierList = NULL;
+ }
+
+ if (pszDefaultCaptureDeviceSpecifier)
+ {
+ free(pszDefaultCaptureDeviceSpecifier);
+ pszDefaultCaptureDeviceSpecifier = NULL;
+ }
+
+ if (pszCaptureDeviceSpecifierList)
+ {
+ free(pszCaptureDeviceSpecifierList);
+ pszCaptureDeviceSpecifierList = NULL;
+ }
+
+ if (pszDefaultAllDevicesSpecifier)
+ {
+ free(pszDefaultAllDevicesSpecifier);
+ pszDefaultAllDevicesSpecifier = NULL;
+ }
+
+ if (pszAllDevicesSpecifierList)
+ {
+ free(pszAllDevicesSpecifierList);
+ pszAllDevicesSpecifierList = NULL;
+ }
+
+ CleanDeviceList(g_pDeviceList);
+ g_pDeviceList = NULL;
+
+ CleanDeviceList(g_pCaptureDeviceList);
+ g_pCaptureDeviceList = NULL;
+
+ CleanDeviceList(g_pAllDevicesList);
+ g_pAllDevicesList = NULL;
+}
+
+void CleanDeviceList(ALDEVICE *pDeviceList)
+{
+ ALDEVICE *pDevice, *pNextDevice;
+
+ pDevice = pDeviceList;
+
+ while (pDevice)
+ {
+ pNextDevice = pDevice->pNextDevice;
+
+ if (pDevice->pszHostDLLFilename)
+ free(pDevice->pszHostDLLFilename);
+
+ if (pDevice->pszDeviceName)
+ free(pDevice->pszDeviceName);
+
+ free(pDevice);
+
+ pDevice = pNextDevice;
+ }
+} \ No newline at end of file
diff --git a/Router/OpenAL32.h b/Router/OpenAL32.h
new file mode 100644
index 00000000..a291a5a8
--- /dev/null
+++ b/Router/OpenAL32.h
@@ -0,0 +1,341 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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
+ */
+
+
+
+
+#ifndef _OPENAL32_H_
+#define _OPENAL32_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AL_BUILD_LIBRARY
+
+#include "al\al.h"
+
+// ALAPI
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_ENABLE)(ALenum capability);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DISABLE)(ALenum capability);
+typedef ALAPI ALboolean (ALAPIENTRY *ALAPI_IS_ENABLED)(ALenum capability);
+
+typedef ALAPI const ALchar* (ALAPIENTRY *ALAPI_GET_STRING)(ALenum param);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BOOLEANV)(ALenum param, ALboolean* data);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_INTEGERV)(ALenum param, ALint* data);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_FLOATV)(ALenum param, ALfloat* data);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_DOUBLEV)(ALenum param, ALdouble* data);
+typedef ALAPI ALboolean (ALAPIENTRY *ALAPI_GET_BOOLEAN)(ALenum param);
+typedef ALAPI ALint (ALAPIENTRY *ALAPI_GET_INTEGER)(ALenum param);
+typedef ALAPI ALfloat (ALAPIENTRY *ALAPI_GET_FLOAT)(ALenum param);
+typedef ALAPI ALdouble (ALAPIENTRY *ALAPI_GET_DOUBLE)(ALenum param);
+
+typedef ALAPI ALenum (ALAPIENTRY *ALAPI_GET_ERROR)(ALvoid);
+
+typedef ALAPI ALboolean (ALAPIENTRY *ALAPI_IS_EXTENSION_PRESENT)(const ALchar* ename);
+typedef ALAPI ALvoid* (ALAPIENTRY *ALAPI_GET_PROC_ADDRESS)(const ALchar* fname);
+typedef ALAPI ALenum (ALAPIENTRY *ALAPI_GET_ENUM_VALUE)(const ALchar* ename);
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENERF)(ALenum param, ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENER3F)(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENERFV)(ALenum param, const ALfloat* values);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENERI)(ALenum param, ALint value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENER3I)( ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_LISTENERIV)( ALenum param, const ALint* values );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENERF)(ALenum param, ALfloat* value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENER3F)(ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENERFV)(ALenum param, ALfloat* values);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENERI)(ALenum param, ALint* value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENER3I)( ALenum param, ALint *value1, ALint *value2, ALint *value3 );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_LISTENERIV)( ALenum param, ALint* values );
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GEN_SOURCES)(ALsizei n, ALuint* sourceNames);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DELETE_SOURCES)(ALsizei n, const ALuint* sourceNames);
+typedef ALAPI ALboolean (ALAPIENTRY *ALAPI_IS_SOURCE)(ALuint id);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCEF)(ALuint sourceName, ALenum param, ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE3F)(ALuint sourceName, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCEFV)(ALuint sourceName, ALenum param, const ALfloat* values);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCEI)(ALuint sourceName, ALenum param, ALint value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE3I)( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCEIV)( ALuint sid, ALenum param, const ALint* values );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCEF)(ALuint sourceName, ALenum param, ALfloat* value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCE3F)(ALuint sourceName, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCEFV)(ALuint sourceName, ALenum param, const ALfloat* values);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCEI)(ALuint sourceName, ALenum param, ALint* value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCE3I)( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_SOURCEIV)( ALuint sid, ALenum param, ALint* values );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_PLAYV)(ALsizei n, const ALuint* sources);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_STOPV)(ALsizei n, const ALuint* sources);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_REWINDV)(ALsizei n, const ALuint* sources);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_PAUSEV)(ALsizei n, const ALuint* sources);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_PLAY)(ALuint sourceName);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_STOP)(ALuint sourceName);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_REWIND)(ALuint sourceName);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_PAUSE)(ALuint sourceName);
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_QUEUE_BUFFERS)(ALuint sourceName, ALsizei n, const ALuint* bufferNames);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SOURCE_UNQUEUE_BUFFERS)(ALuint sourceName, ALsizei n, ALuint* bufferNames);
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GEN_BUFFERS)(ALsizei n, ALuint* bufferNames);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DELETE_BUFFERS)(ALsizei n, const ALuint* bufferNames);
+typedef ALAPI ALboolean (ALAPIENTRY *ALAPI_IS_BUFFER)(ALuint bufferName);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFER_DATA)(ALuint bufferName, ALenum format, const ALvoid* data, ALsizei size, ALuint freq);
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFERF)( ALuint bid, ALenum param, ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFER3F)( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFERFV)( ALuint bid, ALenum param, const ALfloat* values );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFERI)( ALuint bid, ALenum param, ALint value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFER3I)( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_BUFFERIV)( ALuint bid, ALenum param, const ALint* values );
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFERF)( ALuint bid, ALenum param, ALfloat* value );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFER3F)( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFERFV)( ALuint bid, ALenum param, ALfloat* values );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFERI)( ALuint bid, ALenum param, ALint* value );
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFER3I)( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_GET_BUFFERIV)( ALuint bid, ALenum param, ALint* values );
+
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DOPPLER_FACTOR)(ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DOPPLER_VELOCITY)(ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_SPEED_OF_SOUND)(ALfloat value);
+typedef ALAPI ALvoid (ALAPIENTRY *ALAPI_DISTANCE_MODEL)(ALenum value);
+
+typedef struct ALAPI_FXN_TABLE_STRUCT
+{
+ ALAPI_ENABLE alEnable;
+ ALAPI_DISABLE alDisable;
+ ALAPI_IS_ENABLED alIsEnabled;
+
+ ALAPI_GET_STRING alGetString;
+ ALAPI_GET_BOOLEANV alGetBooleanv;
+ ALAPI_GET_INTEGERV alGetIntegerv;
+ ALAPI_GET_FLOATV alGetFloatv;
+ ALAPI_GET_DOUBLEV alGetDoublev;
+ ALAPI_GET_BOOLEAN alGetBoolean;
+ ALAPI_GET_INTEGER alGetInteger;
+ ALAPI_GET_FLOAT alGetFloat;
+ ALAPI_GET_DOUBLE alGetDouble;
+
+ ALAPI_GET_ERROR alGetError;
+
+ ALAPI_IS_EXTENSION_PRESENT alIsExtensionPresent;
+ ALAPI_GET_PROC_ADDRESS alGetProcAddress;
+ ALAPI_GET_ENUM_VALUE alGetEnumValue;
+
+ ALAPI_LISTENERF alListenerf;
+ ALAPI_LISTENER3F alListener3f;
+ ALAPI_LISTENERFV alListenerfv;
+ ALAPI_LISTENERI alListeneri;
+ ALAPI_LISTENER3I alListener3i;
+ ALAPI_LISTENERIV alListeneriv;
+
+ ALAPI_GET_LISTENERF alGetListenerf;
+ ALAPI_GET_LISTENER3F alGetListener3f;
+ ALAPI_GET_LISTENERFV alGetListenerfv;
+ ALAPI_GET_LISTENERI alGetListeneri;
+ ALAPI_GET_LISTENER3I alGetListener3i;
+ ALAPI_GET_LISTENERIV alGetListeneriv;
+
+ ALAPI_GEN_SOURCES alGenSources;
+ ALAPI_DELETE_SOURCES alDeleteSources;
+ ALAPI_IS_SOURCE alIsSource;
+ ALAPI_SOURCEF alSourcef;
+ ALAPI_SOURCE3F alSource3f;
+ ALAPI_SOURCEFV alSourcefv;
+ ALAPI_SOURCEI alSourcei;
+ ALAPI_SOURCE3I alSource3i;
+ ALAPI_SOURCEIV alSourceiv;
+ ALAPI_GET_SOURCEF alGetSourcef;
+ ALAPI_GET_SOURCE3F alGetSource3f;
+ ALAPI_GET_SOURCEFV alGetSourcefv;
+ ALAPI_GET_SOURCEI alGetSourcei;
+ ALAPI_GET_SOURCE3I alGetSource3i;
+ ALAPI_GET_SOURCEIV alGetSourceiv;
+ ALAPI_SOURCE_PLAYV alSourcePlayv;
+ ALAPI_SOURCE_STOPV alSourceStopv;
+ ALAPI_SOURCE_REWINDV alSourceRewindv;
+ ALAPI_SOURCE_PAUSEV alSourcePausev;
+ ALAPI_SOURCE_PLAY alSourcePlay;
+ ALAPI_SOURCE_STOP alSourceStop;
+ ALAPI_SOURCE_REWIND alSourceRewind;
+ ALAPI_SOURCE_PAUSE alSourcePause;
+
+ ALAPI_SOURCE_QUEUE_BUFFERS alSourceQueueBuffers;
+ ALAPI_SOURCE_UNQUEUE_BUFFERS alSourceUnqueueBuffers;
+
+ ALAPI_GEN_BUFFERS alGenBuffers;
+ ALAPI_DELETE_BUFFERS alDeleteBuffers;
+ ALAPI_IS_BUFFER alIsBuffer;
+ ALAPI_BUFFER_DATA alBufferData;
+ ALAPI_BUFFERF alBufferf;
+ ALAPI_BUFFER3F alBuffer3f;
+ ALAPI_BUFFERFV alBufferfv;
+ ALAPI_BUFFERI alBufferi;
+ ALAPI_BUFFER3I alBuffer3i;
+ ALAPI_BUFFERIV alBufferiv;
+ ALAPI_GET_BUFFERF alGetBufferf;
+ ALAPI_GET_BUFFER3F alGetBuffer3f;
+ ALAPI_GET_BUFFERFV alGetBufferfv;
+ ALAPI_GET_BUFFERI alGetBufferi;
+ ALAPI_GET_BUFFER3I alGetBuffer3i;
+ ALAPI_GET_BUFFERIV alGetBufferiv;
+
+ ALAPI_DOPPLER_FACTOR alDopplerFactor;
+ ALAPI_DOPPLER_VELOCITY alDopplerVelocity;
+ ALAPI_SPEED_OF_SOUND alSpeedOfSound;
+ ALAPI_DISTANCE_MODEL alDistanceModel;
+
+} ALAPI_FXN_TABLE;
+
+#include "al\alc.h"
+
+// ALCAPI
+typedef struct ALCdevice_struct ALCdevice;
+typedef struct ALCcontext_struct ALCcontext;
+
+typedef ALCAPI ALCcontext* (ALCAPIENTRY *ALCAPI_CREATE_CONTEXT)(ALCdevice* device, const ALint* attrList);
+typedef ALCAPI ALboolean (ALCAPIENTRY *ALCAPI_MAKE_CONTEXT_CURRENT)(ALCcontext* context);
+typedef ALCAPI ALvoid (ALCAPIENTRY *ALCAPI_PROCESS_CONTEXT)(ALCcontext* context);
+typedef ALCAPI ALCvoid (ALCAPIENTRY *ALCAPI_SUSPEND_CONTEXT)(ALCcontext* context);
+typedef ALCAPI ALvoid (ALCAPIENTRY *ALCAPI_DESTROY_CONTEXT)(ALCcontext* context);
+typedef ALCAPI ALCcontext* (ALCAPIENTRY *ALCAPI_GET_CURRENT_CONTEXT)(ALvoid);
+typedef ALCAPI ALCdevice* (ALCAPIENTRY *ALCAPI_GET_CONTEXTS_DEVICE)(ALCcontext* context);
+
+typedef ALCAPI ALCdevice* (ALCAPIENTRY *ALCAPI_OPEN_DEVICE)(const ALCchar* deviceName);
+typedef ALCAPI ALCboolean (ALCAPIENTRY *ALCAPI_CLOSE_DEVICE)(ALCdevice* device);
+
+typedef ALCAPI ALenum (ALCAPIENTRY *ALCAPI_GET_ERROR)(ALCdevice* device);
+
+typedef ALCAPI ALboolean (ALCAPIENTRY *ALCAPI_IS_EXTENSION_PRESENT)(ALCdevice* device, const ALCchar* eName);
+typedef ALCAPI ALvoid* (ALCAPIENTRY *ALCAPI_GET_PROC_ADDRESS)(ALCdevice* device, const ALCchar* fName);
+typedef ALCAPI ALenum (ALCAPIENTRY *ALCAPI_GET_ENUM_VALUE)(ALCdevice* device, const ALCchar* eName);
+
+typedef ALCAPI const ALCchar* (ALCAPIENTRY *ALCAPI_GET_STRING)(ALCdevice* device, ALenum param);
+typedef ALCAPI ALvoid (ALCAPIENTRY *ALCAPI_GET_INTEGERV)(ALCdevice* device, ALenum param, ALsizei size, ALint* data);
+
+typedef ALCAPI ALCdevice * (ALCAPIENTRY *ALCAPI_CAPTURE_OPEN_DEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
+typedef ALCAPI ALCboolean (ALCAPIENTRY *ALCAPI_CAPTURE_CLOSE_DEVICE)( ALCdevice *device );
+typedef ALCAPI void (ALCAPIENTRY *ALCAPI_CAPTURE_START)( ALCdevice *device );
+typedef ALCAPI void (ALCAPIENTRY *ALCAPI_CAPTURE_STOP)( ALCdevice *device );
+typedef ALCAPI void (ALCAPIENTRY *ALCAPI_CAPTURE_SAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
+
+typedef struct ALCAPI_FXN_TABLE_STRUCT
+{
+ ALCAPI_CREATE_CONTEXT alcCreateContext;
+ ALCAPI_MAKE_CONTEXT_CURRENT alcMakeContextCurrent;
+ ALCAPI_PROCESS_CONTEXT alcProcessContext;
+ ALCAPI_SUSPEND_CONTEXT alcSuspendContext;
+ ALCAPI_DESTROY_CONTEXT alcDestroyContext;
+ ALCAPI_GET_CURRENT_CONTEXT alcGetCurrentContext;
+ ALCAPI_GET_CONTEXTS_DEVICE alcGetContextsDevice;
+
+ ALCAPI_OPEN_DEVICE alcOpenDevice;
+ ALCAPI_CLOSE_DEVICE alcCloseDevice;
+
+ ALCAPI_GET_ERROR alcGetError;
+
+ ALCAPI_IS_EXTENSION_PRESENT alcIsExtensionPresent;
+ ALCAPI_GET_PROC_ADDRESS alcGetProcAddress;
+ ALCAPI_GET_ENUM_VALUE alcGetEnumValue;
+
+ ALCAPI_GET_STRING alcGetString;
+ ALCAPI_GET_INTEGERV alcGetIntegerv;
+
+ ALCAPI_CAPTURE_OPEN_DEVICE alcCaptureOpenDevice;
+ ALCAPI_CAPTURE_CLOSE_DEVICE alcCaptureCloseDevice;
+ ALCAPI_CAPTURE_START alcCaptureStart;
+ ALCAPI_CAPTURE_STOP alcCaptureStop;
+ ALCAPI_CAPTURE_SAMPLES alcCaptureSamples;
+
+} ALCAPI_FXN_TABLE;
+
+#include "windows.h"
+#include "alList.h"
+
+
+//*****************************************************************************
+// Additional Defines
+//*****************************************************************************
+
+typedef struct ALCdevice_struct
+{
+ //
+ // These variables must always be initialized.
+ //
+ ALenum LastError;
+ ALint InUse;
+
+ //
+ // Support for 3rd party OpenAL implementations.
+ //
+ HINSTANCE Dll;
+ ALCAPI_FXN_TABLE AlcApi;
+
+ // Capture Device
+ ALCdevice* CaptureDevice;
+
+ struct ALCdevice_struct* DllDevice;
+
+} ALCdevice;
+
+typedef struct ALCcontext_struct
+{
+ //
+ // These variables are always initialized.
+ //
+ ALlistEntry ListEntry;
+ ALboolean Suspended;
+ ALenum LastError;
+ ALCdevice* Device;
+ ALAPI_FXN_TABLE AlApi;
+ CRITICAL_SECTION Lock;
+ struct ALCcontext_struct* DllContext;
+
+} ALCcontext;
+
+
+extern ALlist* alContextList;
+extern ALCcontext* alCurrentContext;
+
+// Device Enumeration structures, strings and variables
+typedef struct _ALDEVICE
+{
+ ALchar *pszDeviceName;
+ TCHAR *pszHostDLLFilename;
+ struct _ALDEVICE *pNextDevice;
+} ALDEVICE;
+
+extern ALchar *pszDefaultDeviceSpecifier;
+extern ALchar *pszDeviceSpecifierList;
+extern ALchar *pszDefaultCaptureDeviceSpecifier;
+extern ALchar *pszCaptureDeviceSpecifierList;
+extern ALchar *pszDefaultAllDevicesSpecifier;
+extern ALchar *pszAllDevicesSpecifierList;
+
+extern ALDEVICE *g_pDeviceList;
+extern ALDEVICE *g_pCaptureDeviceList;
+extern ALDEVICE *g_pAllDevicesList;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/Router/OpenAL32.rc b/Router/OpenAL32.rc
new file mode 100644
index 00000000..5ddbb5b9
--- /dev/null
+++ b/Router/OpenAL32.rc
@@ -0,0 +1,101 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 6,14,357,23
+ PRODUCTVERSION 6,14,357,23
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Portions (C) Creative Labs Inc. and NVIDIA Corp."
+ VALUE "FileDescription", "Standard OpenAL(TM) Implementation"
+ VALUE "FileVersion", "6.14.0357.23"
+ VALUE "LegalCopyright", "Copyright (C) 2000-2006"
+ VALUE "OriginalFilename", "OpenAL32.dll"
+ VALUE "ProductName", "Standard OpenAL(TM) Library"
+ VALUE "ProductVersion", "6.14.0357.23"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Router/al.cpp b/Router/al.cpp
new file mode 100644
index 00000000..81e11461
--- /dev/null
+++ b/Router/al.cpp
@@ -0,0 +1,981 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2003 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 <al\alc.h>
+#include "OpenAL32.h"
+
+typedef struct ALfunction_struct
+{
+ ALchar *funcName;
+ ALvoid *address;
+} ALfunction;
+
+static ALfunction function[]= {
+ { "alEnable", (ALvoid *) alEnable },
+ { "alDisable", (ALvoid *) alDisable },
+ { "alIsEnabled", (ALvoid *) alIsEnabled },
+ { "alGetString", (ALvoid *) alGetString },
+ { "alGetBooleanv", (ALvoid *) alGetBooleanv },
+ { "alGetIntegerv", (ALvoid *) alGetIntegerv },
+ { "alGetFloatv", (ALvoid *) alGetFloatv },
+ { "alGetDoublev", (ALvoid *) alGetDoublev },
+ { "alGetBoolean", (ALvoid *) alGetBoolean },
+ { "alGetInteger", (ALvoid *) alGetInteger },
+ { "alGetFloat", (ALvoid *) alGetFloat },
+ { "alGetDouble", (ALvoid *) alGetDouble },
+ { "alGetError", (ALvoid *) alGetError },
+ { "alIsExtensionPresent", (ALvoid *) alIsExtensionPresent },
+ { "alGetProcAddress", (ALvoid *) alGetProcAddress },
+ { "alGetEnumValue", (ALvoid *) alGetEnumValue },
+ { "alListenerf", (ALvoid *) alListenerf },
+ { "alListener3f", (ALvoid *) alListener3f },
+ { "alListenerfv", (ALvoid *) alListenerfv },
+ { "alListeneri", (ALvoid *) alListeneri },
+ { "alListener3i", (ALvoid *) alListener3i },
+ { "alListeneriv", (ALvoid *) alListeneriv },
+ { "alGetListenerf", (ALvoid *) alGetListenerf },
+ { "alGetListener3f", (ALvoid *) alGetListener3f },
+ { "alGetListenerfv", (ALvoid *) alGetListenerfv },
+ { "alGetListeneri", (ALvoid *) alGetListeneri },
+ { "alGetListener3i", (ALvoid *) alGetListener3i },
+ { "alGetListeneriv", (ALvoid *) alGetListeneriv },
+ { "alGenSources", (ALvoid *) alGenSources },
+ { "alDeleteSources", (ALvoid *) alDeleteSources },
+ { "alIsSource", (ALvoid *) alIsSource },
+ { "alSourcef", (ALvoid *) alSourcef },
+ { "alSource3f", (ALvoid *) alSource3f },
+ { "alSourcefv", (ALvoid *) alSourcefv },
+ { "alSourcei", (ALvoid *) alSourcei },
+ { "alSource3i", (ALvoid *) alSource3i },
+ { "alSourceiv", (ALvoid *) alSourceiv },
+ { "alGetSourcef", (ALvoid *) alGetSourcef },
+ { "alGetSource3f", (ALvoid *) alGetSource3f },
+ { "alGetSourcefv", (ALvoid *) alGetSourcefv },
+ { "alGetSourcei", (ALvoid *) alGetSourcei },
+ { "alGetSource3i", (ALvoid *) alGetSource3i },
+ { "alGetSourceiv", (ALvoid *) alGetSourceiv },
+ { "alSourcePlayv", (ALvoid *) alSourcePlayv },
+ { "alSourceStopv", (ALvoid *) alSourceStopv },
+ { "alSourceRewindv", (ALvoid *) alSourceRewindv },
+ { "alSourcePausev", (ALvoid *) alSourcePausev },
+ { "alSourcePlay", (ALvoid *) alSourcePlay },
+ { "alSourceStop", (ALvoid *) alSourceStop },
+ { "alSourceRewind", (ALvoid *) alSourceRewind },
+ { "alSourcePause", (ALvoid *) alSourcePause },
+ { "alSourceQueueBuffers", (ALvoid *) alSourceQueueBuffers },
+ { "alSourceUnqueueBuffers", (ALvoid *) alSourceUnqueueBuffers },
+ { "alGenBuffers", (ALvoid *) alGenBuffers },
+ { "alDeleteBuffers", (ALvoid *) alDeleteBuffers },
+ { "alIsBuffer", (ALvoid *) alIsBuffer },
+ { "alBufferData", (ALvoid *) alBufferData },
+ { "alBufferf", (ALvoid *) alBufferf },
+ { "alBuffer3f", (ALvoid *) alBuffer3f },
+ { "alBufferfv", (ALvoid *) alBufferfv },
+ { "alBufferi", (ALvoid *) alBufferi },
+ { "alBuffer3i", (ALvoid *) alBuffer3i },
+ { "alBufferiv", (ALvoid *) alBufferiv },
+ { "alGetBufferf", (ALvoid *) alGetBufferf },
+ { "alGetBuffer3f", (ALvoid *) alGetBuffer3f },
+ { "alGetBufferfv", (ALvoid *) alGetBufferfv },
+ { "alGetBufferi", (ALvoid *) alGetBufferi },
+ { "alGetBuffer3i", (ALvoid *) alGetBuffer3i },
+ { "alGetBufferiv", (ALvoid *) alGetBufferiv },
+ { "alDopplerFactor", (ALvoid *) alDopplerFactor },
+ { "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
+ { "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
+ { "alDistanceModel", (ALvoid *) alDistanceModel },
+ { NULL, (ALvoid *) NULL } };
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Defines
+//
+//*****************************************************************************
+//*****************************************************************************
+
+
+#ifdef __MINGW32__
+// fix for Mingw32.
+#define AL_VOID_FXN(fxn) \
+ ALCcontext* context; \
+ \
+ alListAcquireLock(alContextList); \
+ if(!alCurrentContext) \
+ { \
+ alListReleaseLock(alContextList); \
+ return; \
+ } \
+ \
+ context = alCurrentContext; \
+ EnterCriticalSection(&context->Lock); \
+ alListReleaseLock(alContextList); \
+ \
+ context->AlApi.fxn; \
+ LeaveCriticalSection(&context->Lock); \
+ return
+#define AL_RESULT_FXN(fxn, resultType, resultDefVal) \
+ resultType result = resultDefVal; \
+ ALCcontext* context; \
+ \
+ alListAcquireLock(alContextList); \
+ if(!alCurrentContext) \
+ { \
+ alListReleaseLock(alContextList); \
+ return result; \
+ } \
+ \
+ context = alCurrentContext; \
+ EnterCriticalSection(&context->Lock); \
+ alListReleaseLock(alContextList); \
+ \
+ result = context->AlApi.fxn; \
+ LeaveCriticalSection(&context->Lock); \
+ return result
+
+#else
+#define AL_RESULT_FXN(fxn, resultType, resultDefVal) \
+ resultType result = resultDefVal; \
+ ALCcontext* context; \
+ \
+ alListAcquireLock(alContextList); \
+ if(!alCurrentContext) \
+ { \
+ alListReleaseLock(alContextList); \
+ return result; \
+ } \
+ \
+ context = alCurrentContext; \
+ EnterCriticalSection(&context->Lock); \
+ alListReleaseLock(alContextList); \
+ \
+ result = context->AlApi.##fxn; \
+ LeaveCriticalSection(&context->Lock); \
+ return result
+
+#define AL_VOID_FXN(fxn) \
+ ALCcontext* context; \
+ \
+ alListAcquireLock(alContextList); \
+ if(!alCurrentContext) \
+ { \
+ alListReleaseLock(alContextList); \
+ return; \
+ } \
+ \
+ context = alCurrentContext; \
+ EnterCriticalSection(&context->Lock); \
+ alListReleaseLock(alContextList); \
+ \
+ context->AlApi.##fxn; \
+ LeaveCriticalSection(&context->Lock); \
+ return
+#endif
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// AL API Buffer Entry Points
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//*****************************************************************************
+// alGenBuffers
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n, ALuint* bufferNames)
+{
+ AL_VOID_FXN(alGenBuffers(n, bufferNames));
+}
+
+
+//*****************************************************************************
+// alDeleteBuffers
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint* bufferNames)
+{
+ AL_VOID_FXN(alDeleteBuffers(n, bufferNames));
+}
+
+
+//*****************************************************************************
+// alIsBuffer
+//*****************************************************************************
+//
+ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint bufferName)
+{
+ AL_RESULT_FXN(alIsBuffer(bufferName), ALboolean, AL_FALSE);
+}
+
+//*****************************************************************************
+// alBuffer3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBuffer3f(ALuint bufferName, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3)
+{
+ AL_VOID_FXN(alBuffer3f(bufferName, param, v1, v2, v3));
+}
+
+//*****************************************************************************
+// alBuffer3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBuffer3i(ALuint bufferName, ALenum param, ALint v1, ALint v2, ALint v3)
+{
+ AL_VOID_FXN(alBuffer3i(bufferName, param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alBufferData
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBufferData(ALuint bufferName, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq)
+{
+ AL_VOID_FXN(alBufferData(bufferName, format, data, size, freq));
+}
+
+
+//*****************************************************************************
+// alBufferf
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBufferf(ALuint bufferName, ALenum param, ALfloat value)
+{
+ AL_VOID_FXN(alBufferf(bufferName, param, value));
+}
+
+
+//*****************************************************************************
+// alBufferfv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBufferfv(ALuint bufferName, ALenum param, const ALfloat* values)
+{
+ AL_VOID_FXN(alBufferfv(bufferName, param, values));
+}
+
+
+//*****************************************************************************
+// alBufferi
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBufferi(ALuint bufferName, ALenum param, ALint value)
+{
+ AL_VOID_FXN(alBufferi(bufferName, param, value));
+}
+
+
+//*****************************************************************************
+// alBufferiv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alBufferiv(ALuint bufferName, ALenum param, const ALint* values)
+{
+ AL_VOID_FXN(alBufferiv(bufferName, param, values));
+}
+
+//*****************************************************************************
+// alGetBuffer3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBuffer3f(ALuint bufferName, ALenum param, ALfloat *v1, ALfloat *v2, ALfloat *v3)
+{
+ AL_VOID_FXN(alGetBuffer3f(bufferName, param, v1, v2, v3));
+}
+
+//*****************************************************************************
+// alGetBuffer3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBuffer3i(ALuint bufferName, ALenum param, ALint *v1, ALint *v2, ALint *v3)
+{
+ AL_VOID_FXN(alGetBuffer3i(bufferName, param, v1, v2, v3));
+}
+
+//*****************************************************************************
+// alGetBufferf
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBufferf(ALuint bufferName, ALenum param, ALfloat* value)
+{
+ AL_VOID_FXN(alGetBufferf(bufferName, param, value));
+}
+
+//*****************************************************************************
+// alGetBufferfv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBufferfv(ALuint bufferName, ALenum param, ALfloat* values)
+{
+ AL_VOID_FXN(alGetBufferfv(bufferName, param, values));
+}
+
+
+//*****************************************************************************
+// alGetBufferi
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint bufferName, ALenum param, ALint* value)
+{
+ AL_VOID_FXN(alGetBufferi(bufferName, param, value));
+}
+
+//*****************************************************************************
+// alGetBufferiv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBufferiv(ALuint bufferName, ALenum param, ALint* values)
+{
+ AL_VOID_FXN(alGetBufferiv(bufferName, param, values));
+}
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// AL API Generic Entry Points
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//*****************************************************************************
+// alEnable
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
+{
+ AL_VOID_FXN(alEnable(capability));
+}
+
+
+//*****************************************************************************
+// alDisable
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
+{
+ AL_VOID_FXN(alDisable(capability));
+}
+
+
+//*****************************************************************************
+// alDopplerFactor
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
+{
+ AL_VOID_FXN(alDopplerFactor(value));
+}
+
+
+//*****************************************************************************
+// alDopplerVelocity
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
+{
+ AL_VOID_FXN(alDopplerVelocity(value));
+}
+
+
+//*****************************************************************************
+// alSpeedOfSound
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat value)
+{
+ ALCcontext* context;
+
+ alListAcquireLock(alContextList);
+ if(!alCurrentContext)
+ {
+ alListReleaseLock(alContextList);
+ return;
+ }
+
+ context = alCurrentContext;
+ EnterCriticalSection(&context->Lock);
+ alListReleaseLock(alContextList);
+
+ if (context->AlApi.alSpeedOfSound) { // protect against talking to a 1.0 lib
+ context->AlApi.alSpeedOfSound(value);
+ }
+ LeaveCriticalSection(&context->Lock);
+ return;
+}
+
+
+//*****************************************************************************
+// alDistanceModel
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
+{
+ AL_VOID_FXN(alDistanceModel(value));
+}
+
+
+//*****************************************************************************
+// alGetBoolean
+//*****************************************************************************
+//
+ALAPI ALboolean ALAPIENTRY alGetBoolean(ALenum param)
+{
+ AL_RESULT_FXN(alGetBoolean(param), ALboolean, AL_FALSE);
+}
+
+
+//*****************************************************************************
+// alGetBooleanv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetBooleanv(ALenum param, ALboolean* data)
+{
+ AL_VOID_FXN(alGetBooleanv(param, data));
+}
+
+
+//*****************************************************************************
+// alGetDouble
+//*****************************************************************************
+//
+ALAPI ALdouble ALAPIENTRY alGetDouble(ALenum param)
+{
+ AL_RESULT_FXN(alGetDouble(param), ALdouble, 0.0);
+}
+
+
+//*****************************************************************************
+// alGetDoublev
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetDoublev(ALenum param, ALdouble* data)
+{
+ AL_VOID_FXN(alGetDoublev(param, data));
+}
+
+//*****************************************************************************
+// alGetFloat
+//*****************************************************************************
+//
+ALAPI ALfloat ALAPIENTRY alGetFloat(ALenum param)
+{
+ AL_RESULT_FXN(alGetFloat(param), ALfloat, 0.0f);
+}
+
+
+//*****************************************************************************
+// alGetFloatv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetFloatv(ALenum param, ALfloat* data)
+{
+ AL_VOID_FXN(alGetFloatv(param, data));
+}
+
+
+//*****************************************************************************
+// alGetInteger
+//*****************************************************************************
+//
+ALAPI ALint ALAPIENTRY alGetInteger(ALenum param)
+{
+ AL_RESULT_FXN(alGetInteger(param), ALint, 0);
+}
+
+
+//*****************************************************************************
+// alGetIntegerv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetIntegerv(ALenum param, ALint* data)
+{
+ AL_VOID_FXN(alGetIntegerv(param, data));
+}
+
+
+//*****************************************************************************
+// alGetEnumValue
+//*****************************************************************************
+//
+ALAPI ALenum ALAPIENTRY alGetEnumValue(const ALCchar* ename)
+{
+ AL_RESULT_FXN(alGetEnumValue(ename), ALenum, AL_INVALID_ENUM);
+}
+
+
+//*****************************************************************************
+// alGetError
+//*****************************************************************************
+//
+ALAPI ALenum ALAPIENTRY alGetError(ALvoid)
+{
+ AL_RESULT_FXN(alGetError(), ALenum, AL_NO_ERROR);
+}
+
+
+//*****************************************************************************
+// alGetProcAddress
+//*****************************************************************************
+//
+ALAPI ALvoid* ALAPIENTRY alGetProcAddress(const ALCchar* fname)
+{
+ // return router's address if available
+ ALsizei i=0;
+ ALvoid *pAddress;
+
+ while ((function[i].funcName)&&(strcmp((char *)function[i].funcName,(char *)fname)))
+ i++;
+ pAddress = function[i].address;
+
+ if (pAddress != NULL) {
+ return pAddress;
+ }
+
+ // router doesn't have this entry point, so go to the device...
+ AL_RESULT_FXN(alGetProcAddress(fname), ALvoid*, 0);
+
+ return pAddress;
+}
+
+
+//*****************************************************************************
+// alGetString
+//*****************************************************************************
+//
+ALAPI const ALCchar* ALAPIENTRY alGetString(ALenum param)
+{
+ AL_RESULT_FXN(alGetString(param), const ALCchar*, 0);
+}
+
+
+//*****************************************************************************
+// alIsExtensionPresent
+//*****************************************************************************
+//
+ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALCchar* ename)
+{
+ AL_RESULT_FXN(alIsExtensionPresent(ename), ALboolean, AL_FALSE);
+}
+
+
+//*****************************************************************************
+// alIsEnabled
+//*****************************************************************************
+//
+ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
+{
+ AL_RESULT_FXN(alIsEnabled(capability), ALboolean, AL_FALSE);
+}
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// AL API Listener Entry Points
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//*****************************************************************************
+// alListenerf
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListenerf(ALenum param, ALfloat value)
+{
+ AL_VOID_FXN(alListenerf(param, value));
+}
+
+
+//*****************************************************************************
+// alListener3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3)
+{
+ AL_VOID_FXN(alListener3f(param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alListener3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListener3i(ALenum param, ALint v1, ALint v2, ALint v3)
+{
+ AL_VOID_FXN(alListener3i(param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alListenerfv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum param, const ALfloat* values)
+{
+ AL_VOID_FXN(alListenerfv(param, values));
+}
+
+
+//*****************************************************************************
+// alListeneri
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListeneri(ALenum param, ALint value)
+{
+ AL_VOID_FXN(alListeneri(param, value));
+}
+
+
+//*****************************************************************************
+// alListeneriv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alListeneriv(ALenum param, const ALint *values)
+{
+ AL_VOID_FXN(alListeneriv(param, values));
+}
+
+
+//*****************************************************************************
+// alGetListenerf
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum param, ALfloat* value)
+{
+ AL_VOID_FXN(alGetListenerf(param, value));
+}
+
+
+//*****************************************************************************
+// alGetListener3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3)
+{
+ AL_VOID_FXN(alGetListener3f(param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alGetListener3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListener3i(ALenum param, ALint* v1, ALint* v2, ALint* v3)
+{
+ AL_VOID_FXN(alGetListener3i(param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alGetListenerfv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum param, ALfloat* values)
+{
+ AL_VOID_FXN(alGetListenerfv(param, values));
+}
+
+
+//*****************************************************************************
+// alGetListeneri
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListeneri(ALenum param, ALint* value)
+{
+ AL_VOID_FXN(alGetListeneri(param, value));
+}
+
+
+//*****************************************************************************
+// alGetListeneriv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetListeneriv(ALenum param, ALint* values)
+{
+ AL_VOID_FXN(alGetListeneriv(param, values));
+}
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// AL API Source Entry Points
+//
+//*****************************************************************************
+//*****************************************************************************
+
+
+//*****************************************************************************
+// alGenSources
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n, ALuint* sourceNames)
+{
+ AL_VOID_FXN(alGenSources(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alDeleteSources
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint* sourceNames)
+{
+ AL_VOID_FXN(alDeleteSources(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alIsSource
+//*****************************************************************************
+//
+ALAPI ALboolean ALAPIENTRY alIsSource(ALuint sourceName)
+{
+ AL_RESULT_FXN(alIsSource(sourceName), ALboolean, AL_FALSE);
+}
+
+
+//*****************************************************************************
+// alSourcef
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcef(ALuint sourceName, ALenum param, ALfloat value)
+{
+ AL_VOID_FXN(alSourcef(sourceName, param, value));
+}
+
+
+//*****************************************************************************
+// alSourcefv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcefv(ALuint sourceName, ALenum param, const ALfloat* values)
+{
+ AL_VOID_FXN(alSourcefv(sourceName, param, values));
+}
+
+
+//*****************************************************************************
+// alSource3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSource3f(ALuint sourceName, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3)
+{
+ AL_VOID_FXN(alSource3f(sourceName, param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alSource3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSource3i(ALuint sourceName, ALenum param, ALint v1, ALint v2, ALint v3)
+{
+ AL_VOID_FXN(alSource3i(sourceName, param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alSourcei
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcei(ALuint sourceName, ALenum param, ALint value)
+{
+ AL_VOID_FXN(alSourcei(sourceName, param, value));
+}
+
+//*****************************************************************************
+// alSourceiv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceiv(ALuint sourceName, ALenum param, const ALint* values)
+{
+ AL_VOID_FXN(alSourceiv(sourceName, param, values));
+}
+
+
+//*****************************************************************************
+// alGetSourcef
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint sourceName, ALenum param, ALfloat* value)
+{
+ AL_VOID_FXN(alGetSourcef(sourceName, param, value));
+}
+
+//*****************************************************************************
+// alGetSource3f
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSource3f(ALuint sourceName, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3)
+{
+ AL_VOID_FXN(alGetSource3f(sourceName, param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alGetSource3i
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSource3i(ALuint sourceName, ALenum param, ALint* v1, ALint* v2, ALint* v3)
+{
+ AL_VOID_FXN(alGetSource3i(sourceName, param, v1, v2, v3));
+}
+
+
+//*****************************************************************************
+// alGetSourcefv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint sourceName, ALenum param, ALfloat* values)
+{
+ AL_VOID_FXN(alGetSourcefv(sourceName, param, values));
+}
+
+
+//*****************************************************************************
+// alGetSourcei
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint sourceName, ALenum param, ALint* value)
+{
+ AL_VOID_FXN(alGetSourcei(sourceName, param, value));
+}
+
+
+//*****************************************************************************
+// alGetSourceiv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alGetSourceiv(ALuint sourceName, ALenum param, ALint* values)
+{
+ AL_VOID_FXN(alGetSourceiv(sourceName, param, values));
+}
+
+
+//*****************************************************************************
+// alSourcePlay
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcePlay(ALuint sourceName)
+{
+ AL_VOID_FXN(alSourcePlay(sourceName));
+}
+
+
+//*****************************************************************************
+// alSourcePlayv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint* sourceNames)
+{
+ AL_VOID_FXN(alSourcePlayv(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alSourcePause
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcePause(ALuint sourceName)
+{
+ AL_VOID_FXN(alSourcePause(sourceName));
+}
+
+
+//*****************************************************************************
+// alSourcePausev
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourcePausev(ALsizei n, const ALuint* sourceNames)
+{
+ AL_VOID_FXN(alSourcePausev(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alSourceStop
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceStop(ALuint sourceName)
+{
+ AL_VOID_FXN(alSourceStop(sourceName));
+}
+
+
+//*****************************************************************************
+// alSourceStopv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceStopv(ALsizei n, const ALuint* sourceNames)
+{
+ AL_VOID_FXN(alSourceStopv(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alSourceRewind
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceRewind(ALuint sourceName)
+{
+ AL_VOID_FXN(alSourceRewind(sourceName));
+}
+
+
+//*****************************************************************************
+// alSourceRewindv
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n, const ALuint* sourceNames)
+{
+ AL_VOID_FXN(alSourceRewindv(n, sourceNames));
+}
+
+
+//*****************************************************************************
+// alSourceQueueBuffers
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers(ALuint sourceName, ALsizei n, const ALuint* buffers)
+{
+ AL_VOID_FXN(alSourceQueueBuffers(sourceName, n, buffers));
+}
+
+
+//*****************************************************************************
+// alSourceUnqueueBuffers
+//*****************************************************************************
+//
+ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers(ALuint sourceName, ALsizei n, ALuint* buffers)
+{
+ AL_VOID_FXN(alSourceUnqueueBuffers(sourceName, n, buffers));
+}
+
diff --git a/Router/alList.cpp b/Router/alList.cpp
new file mode 100644
index 00000000..2c884c56
--- /dev/null
+++ b/Router/alList.cpp
@@ -0,0 +1,1029 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2003 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 "alList.h"
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+//****************************************************************************
+//****************************************************************************
+//
+// Defines
+//
+//****************************************************************************
+//****************************************************************************
+
+//
+// Some occasionally useful debugging stuff.
+//
+#if(DBG)
+ #ifndef ASSERT
+ static ALint alListDebugAssertsEnabled = 1;
+ #define ASSERT(exp) \
+ { \
+ if(!(exp) && alListDebugAssertsEnabled) \
+ { \
+ char tempStr[256]; \
+ OutputDebugString("\n"); \
+ sprintf(tempStr, "Assert failed in file %s, line %d!\n", \
+ __FILE__, __LINE__); \
+ OutputDebugString(tempStr); \
+ OutputDebugString("\n"); \
+ if(alListDebugAssertsEnabled) \
+ { \
+ DebugBreak(); \
+ } \
+ } \
+ }
+
+ #endif
+#else
+ #ifndef ASSERT
+ #define ASSERT(exp)
+ #endif
+#endif
+
+
+
+//****************************************************************************
+//****************************************************************************
+//
+// List Functions
+//
+//****************************************************************************
+//****************************************************************************
+
+//*****************************************************************************
+// alListAddEntry
+//*****************************************************************************
+// Adds an entry to the tail of the list. Each entry must be unique.
+//
+ALvoid alListAddEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+)
+{
+#if(DBG)
+ ALlistEntry* pCurrent = 0;
+#endif
+
+ ASSERT(pList);
+ ASSERT(pEntry);
+ ASSERT(pList->Locked);
+ ASSERT(!pEntry->Next);
+ ASSERT(!pEntry->Previous);
+
+ //
+ // Verify the entry doesn't already exist.
+ //
+#if(DBG)
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent == pEntry)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ if(pCurrent)
+ {
+ // Duplicate entries are not supported.
+ ASSERT(0);
+ return;
+ }
+#endif
+
+
+ //
+ // Add the item to the tail of the list.
+ //
+ if(pList->Tail)
+ {
+ pList->Tail->Next = pEntry;
+ }
+
+ pEntry->Previous = pList->Tail;
+ pList->Tail = pEntry;
+
+ //
+ // Check if this is the first entry.
+ //
+ if(!pList->Head)
+ {
+ pList->Head = pEntry;
+ pList->Current = pEntry;
+ }
+
+ pList->NumberOfEntries++;
+}
+
+
+//*****************************************************************************
+// alListAddEntryToHead
+//*****************************************************************************
+// Adds an entry to the head of the list. Each entry must be unique.
+//
+ALvoid alListAddEntryToHead
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+)
+{
+#if(DBG)
+ ALlistEntry* pCurrent = 0;
+#endif
+ ASSERT(pList);
+ ASSERT(pEntry);
+ ASSERT(pList->Locked);
+ ASSERT(!pEntry->Next);
+ ASSERT(!pEntry->Previous);
+
+ //
+ // Verify the entry doesn't already exist.
+ //
+#if(DBG)
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent == pEntry)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ if(pCurrent)
+ {
+ // Duplicate entries are not supported.
+ ASSERT(0);
+ return;
+ }
+#endif
+
+
+ //
+ // Add the item to the head of the list.
+ //
+ if(pList->Head)
+ {
+ pList->Head->Previous = pEntry;
+ }
+
+ pEntry->Next = pList->Head;
+ pList->Head = pEntry;
+
+ //
+ // Check if this is the first entry.
+ //
+ if(!pList->Tail)
+ {
+ pList->Tail = pEntry;
+ pList->Current = pEntry;
+ }
+
+ pList->NumberOfEntries++;
+}
+
+
+//*****************************************************************************
+// alListAcquireLock
+//*****************************************************************************
+// This is called to aquire the list lock for operations that span multiple
+// list calls like iterating over the list.
+//
+ALvoid alListAcquireLock
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+
+ EnterCriticalSection(&pList->Lock);
+#if(DBG)
+ pList->Locked++;
+#endif
+
+ //
+ // Check that only one person has the lock.
+ //
+ ASSERT(pList->Locked == 1);
+}
+
+
+//*****************************************************************************
+// alListCreate
+//*****************************************************************************
+// Creates and initializes a list.
+//
+ALboolean alListCreate
+(
+ OUT ALlist** ppList
+)
+{
+ ALlist* pList = 0;
+
+ ASSERT(ppList);
+
+ //
+ // Allocate and initialize the list context.
+ //
+ *ppList = 0;
+ pList = (ALlist*)malloc(sizeof(ALlist));
+ if(!pList)
+ {
+ // Failed to allocate the list!
+ ASSERT(0);
+ return FALSE;
+ }
+
+ memset(pList, 0, sizeof(ALlist));
+ InitializeCriticalSection(&pList->Lock);
+ pList->NumberOfEntries = 0;
+ *ppList = pList;
+ return TRUE;
+}
+
+
+//*****************************************************************************
+// alListFree
+//*****************************************************************************
+// Destroys the list.
+//
+ALvoid alListFree
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(!pList->Head);
+
+ //
+ // Free the resources allocated during the creation.
+ //
+ if(pList)
+ {
+ DeleteCriticalSection(&pList->Lock);
+ free(pList);
+ }
+
+ return;
+}
+
+
+//*****************************************************************************
+// alListGetData
+//*****************************************************************************
+// Returns the data from the list entry.
+//
+ALvoid* alListGetData
+(
+ IN ALlistEntry* pEntry
+)
+{
+ ASSERT(pEntry);
+
+ return pEntry->Data;
+}
+
+
+//*****************************************************************************
+// alListGetEntryAt
+//*****************************************************************************
+// Returns the entry in the list at the specified index of the list.
+//
+ALlistEntry* alListGetEntryAt
+(
+ IN ALlist* pList,
+ IN ALint Index
+)
+{
+ ALlistEntry* pEntry = 0;
+ ALint i;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+ ASSERT(Index < pList->NumberOfEntries);
+
+ pEntry = pList->Head;
+ for(i = 0; i < Index && pEntry; i++)
+ {
+ pEntry = pEntry->Next;
+ }
+
+ return pEntry;
+}
+
+
+//*****************************************************************************
+// alListGetEntryCount
+//*****************************************************************************
+// Returns the number of items stored in the list.
+//
+ALint alListGetEntryCount
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList->Locked);
+ return pList->NumberOfEntries;
+}
+
+
+//*****************************************************************************
+// alListGetHead
+//*****************************************************************************
+// Returns the first entry in the list.
+//
+ALlistEntry* alListGetHead
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ return pList->Head;
+}
+
+
+//*****************************************************************************
+// alListGetNext
+//*****************************************************************************
+// Returns the entry after to the entry pointed to by the iterator. If
+// the iterator is at the last entry (or has finished iterating over the
+// list), the returned entry will be 0.
+//
+ALlistEntry* alListGetNext
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ if(!pList->Current)
+ {
+ return 0;
+ }
+
+ return pList->Current->Next;
+}
+
+
+//*****************************************************************************
+// alListGetPrevious
+//*****************************************************************************
+// Returns the entry previous to the entry pointed to by the iterator. If
+// the iterator is at the first entry, the returned entry will be 0.
+//
+ALlistEntry* alListGetPrevious
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ if(!pList->Current)
+ {
+ return 0;
+ }
+
+ return pList->Current->Previous;
+}
+
+
+//*****************************************************************************
+// alListGetTail
+//*****************************************************************************
+// Returns the last entry in the list.
+//
+ALlistEntry* alListGetTail
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ return pList->Tail;
+}
+
+
+//*****************************************************************************
+// alListInitializeEntry
+//*****************************************************************************
+// Initializes a preallocated list entry.
+//
+ALvoid alListInitializeEntry
+(
+ ALlistEntry* pEntry,
+ ALvoid* pData
+)
+{
+ ASSERT(pEntry);
+
+ pEntry->Data = pData;
+ pEntry->Next = 0;
+ pEntry->Previous = 0;
+}
+
+
+//*****************************************************************************
+// alListIsEmpty
+//*****************************************************************************
+// Returns the TRUE if the list is empty.
+//
+ALboolean alListIsEmpty
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ return (pList->Head == 0);
+}
+
+
+//*****************************************************************************
+// alListIteratorGet
+//*****************************************************************************
+// Returns the entry pointed to by the iterator.
+//
+ALlistEntry* alListIteratorGet
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ return pList->Current;
+}
+
+
+//*****************************************************************************
+// alListIteratorFindData
+//*****************************************************************************
+// Searches the list for the matching item and return the pointer to the
+// entry. If the match is not found, the return will be 0.
+//
+ALlistEntry* alListIteratorFindData
+(
+ IN ALlist* pList,
+ IN ALvoid* pData
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Find the item.
+ //
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent->Data == pData)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ pList->Current = pCurrent;
+ return pCurrent;
+}
+
+
+//*****************************************************************************
+// alListIteratorNext
+//*****************************************************************************
+// This is called to advance the list iterator to the next entry in the list
+// and return that entry.
+//
+ALlistEntry* alListIteratorNext
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ if(!pList->Current)
+ {
+ return 0;
+ }
+
+ pList->Current = pList->Current->Next;
+ return pList->Current;
+}
+
+
+//*****************************************************************************
+// alListIteratorPrevious
+//*****************************************************************************
+// This is called to advance the list iterator to the previous entry in the
+// list and return that entry.
+//
+ALlistEntry* alListIteratorPrevious
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ if(!pList->Current)
+ {
+ return 0;
+ }
+
+ pList->Current = pList->Current->Previous;
+ return pList->Current;
+}
+
+
+//*****************************************************************************
+// alListIteratorRemove
+//*****************************************************************************
+// Removes the current item from the list and returns it. The iterator will
+// equal the next item in the list.
+//
+ALlistEntry* alListIteratorRemove
+(
+ IN ALlist* pList
+)
+{
+ ALlistEntry* pEntry = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Make sure we aren't at the end of the list.
+ //
+ if(!pList->Current)
+ {
+ return 0;
+ }
+
+ //
+ // Remove the item from the list.
+ //
+ pEntry = pList->Current;
+
+ //
+ // Fix up the next item in the list.
+ //
+ if(pEntry->Next)
+ {
+ pEntry->Next->Previous = pEntry->Previous;
+ }
+
+ //
+ // Fix up the previous item in the list.
+ //
+ if(pEntry->Previous)
+ {
+ pEntry->Previous->Next = pEntry->Next;
+ }
+
+ //
+ // Fix up the current pointer.
+ //
+ pList->Current = pEntry->Next;
+
+ //
+ // Check the head pointer.
+ //
+ if(pList->Head == pEntry)
+ {
+ pList->Head = pEntry->Next;
+ }
+
+ //
+ // Check the tail pointer.
+ //
+ if(pList->Tail == pEntry)
+ {
+ pList->Tail = pEntry->Previous;
+ }
+
+ //
+ // Set the entry pointers.
+ //
+ pEntry->Next = 0;
+ pEntry->Previous = 0;
+ pList->NumberOfEntries--;
+ ASSERT(0 <= pList->NumberOfEntries);
+ return pEntry;
+}
+
+
+//*****************************************************************************
+// alListIteratorReset
+//*****************************************************************************
+// Returns the list iterator to the head of the list.
+//
+ALlistEntry* alListIteratorReset
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ pList->Current = pList->Head;
+ return pList->Current;
+}
+
+
+//*****************************************************************************
+// alListIteratorSet
+//*****************************************************************************
+// Sets the current entry pointer to the entry passed in. If the entry is not
+// found, the current entry will be 0.
+//
+ALlistEntry* alListIteratorSet
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent == pEntry)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ pList->Current = pCurrent;
+ return pList->Current;
+}
+
+
+//*****************************************************************************
+// alListMatchEntry
+//*****************************************************************************
+// Matches the entry to an item in the list and returns the data in that
+// entry. If the match is not found, the return will be 0.
+//
+ALvoid* alListMatchEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Find the item.
+ //
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent == pEntry)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ if(!pCurrent)
+ {
+ return 0;
+ }
+
+ return pCurrent->Data;
+}
+
+
+//*****************************************************************************
+// alListMatchData
+//*****************************************************************************
+// Searches the list for the first matching item and returns the pointer to
+// the entry. If the match is not found, the return will be 0.
+//
+ALlistEntry* alListMatchData
+(
+ IN ALlist* pList,
+ IN ALvoid* pData
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Find the item.
+ //
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent->Data == pData)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ return pCurrent;
+}
+
+
+//*****************************************************************************
+// alListReleaseLock
+//*****************************************************************************
+// This is called to release the list lock.
+//
+ALvoid alListReleaseLock
+(
+ IN ALlist* pList
+)
+{
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+#if(DBG)
+ pList->Locked--;
+ ASSERT(pList->Locked == 0);
+#endif
+
+ LeaveCriticalSection(&pList->Lock);
+}
+
+
+//*****************************************************************************
+// alListRemoveEntry
+//*****************************************************************************
+// Removes the item from the list and returns the data from the item. If
+// this is the current item, the current item will equal the next item in the
+// list.
+//
+ALvoid* alListRemoveEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+ ASSERT(pEntry);
+
+ //
+ // Release the item from the list.
+ //
+ pCurrent = pList->Head;
+ while(pCurrent)
+ {
+ if(pCurrent == pEntry)
+ {
+ break;
+ }
+
+ pCurrent = pCurrent->Next;
+ }
+
+ if(!pCurrent)
+ {
+ return 0;
+ }
+
+ //
+ // Fix up the next item in the list.
+ //
+ if(pEntry->Next)
+ {
+ pEntry->Next->Previous = pEntry->Previous;
+ }
+
+ //
+ // Fix up the previous item in the list.
+ //
+ if(pEntry->Previous)
+ {
+ pEntry->Previous->Next = pEntry->Next;
+ }
+
+ //
+ // Fix up the current pointer.
+ //
+ if(pCurrent == pList->Current)
+ {
+ pList->Current = pEntry->Next;
+ }
+
+ //
+ // Check the head pointer.
+ //
+ if(pList->Head == pEntry)
+ {
+ pList->Head = pEntry->Next;
+ }
+
+ //
+ // Check the tail pointer.
+ //
+ if(pList->Tail == pEntry)
+ {
+ pList->Tail = pEntry->Previous;
+ }
+
+ //
+ // Set the entry pointers.
+ //
+ pEntry->Next = 0;
+ pEntry->Previous = 0;
+ pList->NumberOfEntries--;
+ ASSERT(0 <= pList->NumberOfEntries);
+ return pEntry->Data;
+}
+
+
+//*****************************************************************************
+// alListRemoveHead
+//*****************************************************************************
+// Removes the list entry at the head of the list. If this is the current
+// item, the current item will equal the next item in the list.
+//
+ALlistEntry* alListRemoveHead
+(
+ IN ALlist* pList
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Release the item from the list.
+ //
+ pCurrent = pList->Head;
+ if(!pCurrent)
+ {
+ return 0;
+ }
+
+ //
+ // Fix up the next item in the list.
+ //
+ if(pCurrent->Next)
+ {
+ pCurrent->Next->Previous = 0;
+ }
+
+ //
+ // Fix up the previous item in the list.
+ //
+ ASSERT(!pCurrent->Previous)
+
+ //
+ // Fix up the current pointer.
+ //
+ if(pCurrent == pList->Current)
+ {
+ pList->Current = pCurrent->Next;
+ }
+
+ //
+ // Check the head pointer.
+ //
+ pList->Head = pCurrent->Next;
+
+ //
+ // Check the tail pointer.
+ //
+ if(pList->Tail == pCurrent)
+ {
+ pList->Tail = 0;
+ }
+
+ //
+ // Set the entry pointers.
+ //
+ pCurrent->Next = 0;
+ pCurrent->Previous = 0;
+ pList->NumberOfEntries--;
+ ASSERT(0 <= pList->NumberOfEntries);
+ return pCurrent;
+}
+
+
+//*****************************************************************************
+// alListRemoveTail
+//*****************************************************************************
+// Removes the list entry at the tail of the list. If this is the current
+// item, the current item will be null.
+//
+ALlistEntry* alListRemoveTail
+(
+ IN ALlist* pList
+)
+{
+ ALlistEntry* pCurrent = 0;
+
+ ASSERT(pList);
+ ASSERT(pList->Locked);
+
+ //
+ // Release the item from the list.
+ //
+ pCurrent = pList->Tail;
+ if(!pCurrent)
+ {
+ return 0;
+ }
+
+ //
+ // Fix up the next item in the list.
+ //
+ ASSERT(!pCurrent->Next)
+
+ //
+ // Fix up the previous item in the list.
+ //
+ if(pCurrent->Previous)
+ {
+ pCurrent->Previous->Next = 0;
+ }
+
+ //
+ // Fix up the current pointer.
+ //
+ if(pCurrent == pList->Current)
+ {
+ pList->Current = 0;
+ }
+
+ //
+ // Check the head pointer.
+ //
+ if(pList->Head == pCurrent)
+ {
+ pList->Head = 0;
+ }
+
+ //
+ // Check the tail pointer.
+ //
+ pList->Tail = pCurrent->Previous;
+
+ //
+ // Set the entry pointers.
+ //
+ pCurrent->Next = 0;
+ pCurrent->Previous = 0;
+ pList->NumberOfEntries--;
+ ASSERT(0 <= pList->NumberOfEntries);
+ return pCurrent;
+}
+
diff --git a/Router/alList.h b/Router/alList.h
new file mode 100644
index 00000000..71dc43c5
--- /dev/null
+++ b/Router/alList.h
@@ -0,0 +1,433 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2003 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
+ */
+
+
+
+
+#ifndef _AL_LIST_H_
+#define _AL_LIST_H_
+
+#include <al/al.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Defines
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//
+// Some useful things to track parameters.
+//
+#ifndef IN
+#define IN
+#endif
+
+#ifndef OPTIONAL
+#define OPTIONAL
+#endif
+
+#ifndef OUT
+#define OUT
+#endif
+
+//
+// The list entry. This should not be modified outside the list routines.
+//
+typedef struct ALlistEntry_Struct
+{
+ //
+ // The previous list entry.
+ //
+ struct ALlistEntry_Struct* Previous;
+
+ //
+ // The next list entry.
+ //
+ struct ALlistEntry_Struct* Next;
+
+ //
+ // The data for the current entry.
+ //
+ ALvoid* Data;
+
+} ALlistEntry;
+
+
+//
+// This is the context to pass to all the list calls. It must be initialized
+// before any list calls are made.
+//
+typedef struct //ALlist_Struct
+{
+ //
+ // This is the pointer to the first item in the list.
+ //
+ ALlistEntry* Head;
+
+ //
+ // This is the pointer to the last item in the list.
+ //
+ ALlistEntry* Tail;
+
+ //
+ // This is the list iterator.
+ //
+ ALlistEntry* Current;
+
+ //
+ // This is the list lock to prevent simultaneous addition and removal
+ // of entries.
+ //
+ CRITICAL_SECTION Lock;
+
+ //
+ // This maintains a count of the number of entries in the list.
+ //
+ ALint NumberOfEntries;
+
+ //
+ // This is set if the list is locked. For debug use only.
+ //
+#if(DBG)
+ ALint Locked;
+#endif
+
+} ALlist;
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// List Functions
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//*****************************************************************************
+// alListAddEntry
+//*****************************************************************************
+// Adds an entry to the tail of the list. Each entry must be unique.
+//
+ALvoid alListAddEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListAddEntryToHead
+//*****************************************************************************
+// Adds an entry to the head of the list. Each entry must be unique.
+//
+ALvoid alListAddEntryToHead
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListAcquireLock
+//*****************************************************************************
+// This is called to acquire the list lock for operations that span multiple
+// list calls like iterating over the list.
+//
+ALvoid alListAcquireLock
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListCreate
+//*****************************************************************************
+// Creates and initializes a list.
+//
+ALboolean alListCreate
+(
+ OUT ALlist** ppList
+);
+
+//*****************************************************************************
+// alListFree
+//*****************************************************************************
+// Destroys the list. Dynamically allocated entries are not freed.
+//
+ALvoid alListFree
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListGetData
+//*****************************************************************************
+// Returns the data from the list entry.
+//
+ALvoid* alListGetData
+(
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListGetEntryAt
+//*****************************************************************************
+// Returns the entry in the list at the specified index of the list.
+//
+ALlistEntry* alListGetEntryAt
+(
+ IN ALlist* pList,
+ IN ALint Index
+);
+
+//*****************************************************************************
+// alListGetEntryCount
+//*****************************************************************************
+// Returns the number of items stored in the list.
+//
+ALint alListGetEntryCount
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListGetHead
+//*****************************************************************************
+// Returns the first entry in the list.
+//
+ALlistEntry* alListGetHead
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListGetNext
+//*****************************************************************************
+// Returns the entry after to the entry pointed to by the iterator. If
+// the iterator is at the last entry (or has finished iterating over the
+// list), the returned entry will be 0.
+//
+ALlistEntry* alListGetNext
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListGetPrevious
+//*****************************************************************************
+// Returns the entry previous to the entry pointed to by the iterator. If
+// the iterator is at the first entry, the returned entry will be 0.
+//
+ALlistEntry* alListGetPrevious
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListGetTail
+//*****************************************************************************
+// Returns the last entry in the list.
+//
+ALlistEntry* alListGetTail
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListInitializeEntry
+//*****************************************************************************
+// Initializes a preallocated list entry.
+//
+ALvoid alListInitializeEntry
+(
+ IN ALlistEntry* pListEntry,
+ IN ALvoid* pData
+);
+
+//*****************************************************************************
+// alListIsEmpty
+//*****************************************************************************
+// Returns the TRUE if the list is empty.
+//
+ALboolean alListIsEmpty
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorGet
+//*****************************************************************************
+// Returns the entry pointed to by the iterator.
+//
+ALlistEntry* alListIteratorGet
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorFindData
+//*****************************************************************************
+// Searches the list for the matching item and return the pointer to the
+// entry. If the match is not found, the return will be 0.
+//
+ALlistEntry* alListIteratorFindData
+(
+ IN ALlist* pList,
+ IN ALvoid* pData
+);
+
+//*****************************************************************************
+// alListIteratorNext
+//*****************************************************************************
+// This is called to advance the list iterator to the next entry in the list
+// and return that entry.
+//
+ALlistEntry* alListIteratorNext
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorPrevious
+//*****************************************************************************
+// This is called to advance the list iterator to the previous entry in the
+// list and return that entry.
+//
+ALlistEntry* alListIteratorPrevious
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorReset
+//*****************************************************************************
+// Returns the list iterator to the head of the list and returns the head
+// entry.
+//
+ALlistEntry* alListIteratorReset
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorRemove
+//*****************************************************************************
+// Removes the current item from the list and returns it. The iterator will
+// equal the next item in the list.
+//
+ALlistEntry* alListIteratorRemove
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListIteratorSet
+//*****************************************************************************
+// Sets the current entry pointer to the entry passed in. If the entry is not
+// found, the current entry will be 0.
+//
+ALlistEntry* alListIteratorSet
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListMatchEntry
+//*****************************************************************************
+// Matches the entry to an item in the list and returns the data in that
+// entry. If the match is not found, the return will be 0.
+//
+ALvoid* alListMatchEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListMatchData
+//*****************************************************************************
+// Searches the list for the matching item and return the pointer to the
+// entry. If the match is not found, the return will be 0.
+//
+ALlistEntry* alListMatchData
+(
+ IN ALlist* pList,
+ IN ALvoid* pData
+);
+
+//*****************************************************************************
+// alListReleaseLock
+//*****************************************************************************
+// This is called to release the list lock.
+//
+ALvoid alListReleaseLock
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListRemoveEntry
+//*****************************************************************************
+// Removes the item from the list and returns the data from the item. If
+// this is the current item, the current item will equal the next item in the
+// list.
+//
+ALvoid* alListRemoveEntry
+(
+ IN ALlist* pList,
+ IN ALlistEntry* pEntry
+);
+
+//*****************************************************************************
+// alListRemoveHead
+//*****************************************************************************
+// Removes the list entry at the head of the list. If this is the current
+// item, the current item will equal the next item in the list.
+//
+ALlistEntry* alListRemoveHead
+(
+ IN ALlist* pList
+);
+
+//*****************************************************************************
+// alListRemoveTail
+//*****************************************************************************
+// Removes the list entry at the tail of the list. If this is the current
+// item, the current item will be null.
+//
+ALlistEntry* alListRemoveTail
+(
+ IN ALlist* pList
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Router/alc.cpp b/Router/alc.cpp
new file mode 100644
index 00000000..c4abff8c
--- /dev/null
+++ b/Router/alc.cpp
@@ -0,0 +1,2332 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 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
+ */
+
+#ifndef __MINGW32__
+#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
+#endif
+
+#include <stdlib.h>
+#include <memory.h>
+#define AL_BUILD_LIBRARY
+#include <al/alc.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <assert.h>
+
+#include <stddef.h>
+#include <windows.h>
+#if defined(_MSC_VER)
+#include <crtdbg.h>
+#else
+#define _malloc_dbg(s,x,f,l) malloc(s)
+#define _realloc_dbg(p,s,x,f,l) realloc(p,s)
+#endif
+#include <objbase.h>
+#ifndef __MINGW32__
+#include <atlconv.h>
+#else
+#define T2A(x) x
+#endif
+#include <mmsystem.h>
+
+#include "OpenAL32.h"
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Defines
+//
+//*****************************************************************************
+//*****************************************************************************
+
+typedef struct ALCextension_struct
+{
+
+ const char* ename;
+
+} ALCextension;
+
+typedef struct
+{
+ const char* ename;
+ ALenum value;
+
+} ALCRouterEnum;
+
+typedef struct ALCfunction_struct
+{
+
+ const char* fname;
+ ALvoid* address;
+
+} ALCfunction;
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Global Vars
+//
+//*****************************************************************************
+//*****************************************************************************
+
+ALlist* alContextList = 0;
+ALCcontext* alCurrentContext = 0;
+
+ALCdevice* g_CaptureDevice = NULL;
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Local Vars
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//
+// The values of the enums supported by OpenAL.
+//
+static ALCRouterEnum alcEnums[] =
+{
+ // Types
+ {"ALC_INVALID", ALC_INVALID},
+ {"ALC_FALSE", ALC_FALSE},
+ {"ALC_TRUE", ALC_TRUE},
+
+ // ALC Properties
+ {"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION},
+ {"ALC_MINOR_VERSION", ALC_MINOR_VERSION},
+ {"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE},
+ {"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES},
+ {"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER},
+ {"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER},
+ {"ALC_EXTENSIONS", ALC_EXTENSIONS},
+ {"ALC_FREQUENCY", ALC_FREQUENCY},
+ {"ALC_REFRESH", ALC_REFRESH},
+ {"ALC_SYNC", ALC_SYNC},
+ {"ALC_MONO_SOURCES", ALC_MONO_SOURCES},
+ {"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES},
+ {"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER},
+ {"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
+ {"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES},
+
+ // New Enumeration extension
+ {"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER},
+ {"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER},
+
+ // ALC Error Message
+ {"ALC_NO_ERROR", ALC_NO_ERROR},
+ {"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE},
+ {"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT},
+ {"ALC_INVALID_ENUM", ALC_INVALID_ENUM},
+ {"ALC_INVALID_VALUE", ALC_INVALID_VALUE},
+ {"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY},
+
+ // Default
+ {0, (ALenum)0}
+};
+
+//
+// Our function pointers.
+//
+static ALCfunction alcFunctions[] =
+{
+ {"alcCreateContext", (ALvoid*)alcCreateContext},
+ {"alcMakeContextCurrent", (ALvoid*)alcMakeContextCurrent},
+ {"alcProcessContext", (ALvoid*)alcProcessContext},
+ {"alcSuspendContext", (ALvoid*)alcSuspendContext},
+ {"alcDestroyContext", (ALvoid*)alcDestroyContext},
+ {"alcGetCurrentContext", (ALvoid*)alcGetCurrentContext},
+ {"alcGetContextsDevice", (ALvoid*)alcGetContextsDevice},
+ {"alcOpenDevice", (ALvoid*)alcOpenDevice},
+ {"alcCloseDevice", (ALvoid*)alcCloseDevice},
+ {"alcGetError", (ALvoid*)alcGetError},
+ {"alcIsExtensionPresent", (ALvoid*)alcIsExtensionPresent},
+ {"alcGetProcAddress", (ALvoid*)alcGetProcAddress},
+ {"alcGetEnumValue", (ALvoid*)alcGetEnumValue},
+ {"alcGetString", (ALvoid*)alcGetString},
+ {"alcGetIntegerv", (ALvoid*)alcGetIntegerv},
+ {"alcCaptureOpenDevice", (ALvoid*)alcCaptureOpenDevice},
+ {"alcCaptureCloseDevice", (ALvoid*)alcCaptureCloseDevice},
+ {"alcCaptureStart", (ALvoid*)alcCaptureStart},
+ {"alcCaptureStop", (ALvoid*)alcCaptureStop},
+ {"alcCaptureSamples", (ALvoid*)alcCaptureSamples},
+ {0, (ALvoid*)0}
+};
+
+//
+// Our extensions.
+//
+static ALCextension alcExtensions[] =
+{
+ "ALC_ENUMERATION_EXT",
+ "ALC_ENUMERATE_ALL_EXT",
+ "ALC_EXT_CAPTURE",
+ 0
+};
+
+
+// Error strings
+static ALenum LastError = ALC_NO_ERROR;
+static const ALCchar alcNoError[] = "No Error";
+static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
+static const ALCchar alcErrInvalidContext[] = "Invalid Context";
+static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
+static const ALCchar alcErrInvalidValue[] = "Invalid Value";
+
+static ALint alcMajorVersion = 1;
+static ALint alcMinorVersion = 1;
+
+// Enumeration stuff
+ALDEVICE *g_pDeviceList = NULL; // ALC_ENUMERATION_EXT Device List
+ALDEVICE *g_pCaptureDeviceList = NULL; // ALC_ENUMERATION_EXT Capture Device List
+ALDEVICE *g_pAllDevicesList = NULL; // ALC_ENUMERATE_ALL_EXT Device List
+
+ALchar *pszDefaultDeviceSpecifier = NULL;
+ALchar *pszDeviceSpecifierList = NULL;
+ALchar *pszDefaultCaptureDeviceSpecifier = NULL;
+ALchar *pszCaptureDeviceSpecifierList = NULL;
+ALchar *pszDefaultAllDevicesSpecifier = NULL;
+ALchar *pszAllDevicesSpecifierList = NULL;
+ALchar szEmptyString[] = "";
+
+typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID);
+typedef HRESULT (WINAPI *LPDIRECTSOUNDENUMERATEA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
+typedef HRESULT (WINAPI *LPDIRECTSOUNDCAPTUREENUMERATEA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
+
+BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext);
+bool GetDefaultPlaybackDeviceName(char **pszName);
+bool GetDefaultCaptureDeviceName(char **pszName);
+bool FindDevice(ALDEVICE *pDeviceList, char *szDeviceName, bool bExactMatch, char **ppszDefaultName);
+bool HasDLLAlreadyBeenUsed(ALDEVICE *pDeviceList, TCHAR *szDLLName);
+//bool ValidCaptureDevice(const char *szCaptureDeviceName);
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Logging Options
+//
+//*****************************************************************************
+//*****************************************************************************
+
+// NOTE : LOG macro below requires a compiler newer than Visual Studio 6
+
+//#define _LOGCALLS
+
+#ifdef _LOGCALLS
+ void OutputMessage(const char *szTest,...);
+ #define LOG(x, ...) OutputMessage(x, ##__VA_ARGS__)
+ #define LOGFILENAME "OpenALCalls.txt"
+#endif
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// Local Functions
+//
+//*****************************************************************************
+//*****************************************************************************
+
+//*****************************************************************************
+// GetLoadedModuleDirectory
+//*****************************************************************************
+BOOL GetLoadedModuleDirectory(LPCTSTR moduleName,
+ LPTSTR directoryContainingModule,
+ DWORD directoryContainingModuleLength) {
+ // Attempts to find the given module in the address space of this
+ // process and return the directory containing the module. A NULL
+ // moduleName means to look up the directory containing the
+ // application rather than any given loaded module. There is no
+ // trailing backslash ('\') on the returned path. If the named
+ // module was found in the address space of this process, returns
+ // TRUE, otherwise returns FALSE. directoryContainingModule may be
+ // mutated regardless.
+ HMODULE module = NULL;
+ TCHAR fileDrive[MAX_PATH + 1];
+ TCHAR fileDir[MAX_PATH + 1];
+ TCHAR fileName[MAX_PATH + 1];
+ TCHAR fileExt[MAX_PATH + 1];
+ DWORD numChars;
+
+ if (moduleName != NULL) {
+ module = GetModuleHandle(moduleName);
+ if (module == NULL)
+ return FALSE;
+ }
+
+ numChars = GetModuleFileName(module,
+ directoryContainingModule,
+ directoryContainingModuleLength);
+ if (numChars == 0)
+ return FALSE;
+
+ _splitpath(directoryContainingModule, fileDrive, fileDir, fileName, fileExt);
+ _tcscpy(directoryContainingModule, fileDrive);
+ _tcscat(directoryContainingModule, fileDir);
+ return TRUE;
+}
+
+
+
+
+//*****************************************************************************
+// AddDevice
+//*****************************************************************************
+void AddDevice(const char *pszDeviceName, TCHAR *pszHostDLLFilename, ALDEVICE **ppDeviceList)
+{
+ // Adds pszDeviceName nad pszHostDLLFilename to the given Device List *IF* pszDeviceName has
+ // not already been added.
+ ALDEVICE *pNewDevice, *pTempDevice;
+
+ // Check if unique
+ for (pTempDevice = *ppDeviceList; pTempDevice; pTempDevice = pTempDevice->pNextDevice)
+ {
+ if (strcmp(pTempDevice->pszDeviceName, pszDeviceName) == 0)
+ break;
+ }
+
+ if (pTempDevice)
+ return;
+
+ pNewDevice = (ALDEVICE*)malloc(sizeof(ALDEVICE));
+ if (pNewDevice)
+ {
+ pNewDevice->pszDeviceName = (char*)malloc((strlen(pszDeviceName)+1)*sizeof(char));
+ if (pNewDevice->pszDeviceName)
+ strcpy(pNewDevice->pszDeviceName, pszDeviceName);
+
+ pNewDevice->pszHostDLLFilename = (TCHAR*)malloc((_tcslen(pszHostDLLFilename)+1)*sizeof(TCHAR));
+ if (pNewDevice->pszHostDLLFilename)
+ _tcscpy(pNewDevice->pszHostDLLFilename, pszHostDLLFilename);
+
+ pNewDevice->pNextDevice = NULL;
+
+ if (*ppDeviceList)
+ {
+ pTempDevice = *ppDeviceList;
+ while (pTempDevice->pNextDevice)
+ pTempDevice = pTempDevice->pNextDevice;
+ pTempDevice->pNextDevice = pNewDevice;
+ }
+ else
+ {
+ *ppDeviceList = pNewDevice;
+ }
+ }
+}
+
+
+
+
+//*****************************************************************************
+// BuildDeviceList
+//*****************************************************************************
+ALvoid BuildDeviceList()
+{
+ // This function will scan several directories (details below) looking for
+ // OpenAL DLLs. Each OpenAL DLL found will be opened and queried for it's
+ // list of playback and capture devices. All the information is stored
+ // in various lists: -
+ //
+ // g_pDevicesList : List of Playback Devices
+ // g_pCaptureDeviceList : List of Capture devices
+ // g_pAllDevicesList : List of *all* possible Playback devices (ALC_ENUMERATE_ALL_EXT support)
+ //
+ // In addition this function allocates memory for the strings that will
+ // be returned to the application in response to alcGetString queries.
+ //
+ // pszDefaultDeviceSpecifier : Default Playback Device
+ // pszDeviceSpecifierList : List of Playback Devices
+ // pszDefaultCaptureDeviceSpecifier : Default Capture Device
+ // pszCaptureDeviceSpecifierList : List of Capture Devices
+ // pszDefaultAllDevicesSpecifier : Default *all* Playback Device (ALC_ENUMERATE_ALL_EXT support)
+ // pszAllDevicesSpecifierList : List of *all* Playback Devices (ALC_ENUMERATE_ALL_EXT support)
+ WIN32_FIND_DATA findData;
+ HANDLE searchHandle = INVALID_HANDLE_VALUE;
+ TCHAR searchName[MAX_PATH + 1];
+ BOOL found = FALSE;
+ const ALCchar* specifier = 0;
+ ALuint specifierSize = 0;
+ ALCdevice *device;
+ void *context;
+ bool bUsedWrapper = false;
+ ALDEVICE *pDevice = NULL;
+
+ // Only build the list once ...
+ if (((g_pDeviceList == NULL) && (waveOutGetNumDevs())) ||
+ ((g_pCaptureDeviceList == NULL) && (waveInGetNumDevs())))
+ {
+ //
+ // Directory[0] is the directory containing OpenAL32.dll
+ // Directory[1] is the current directory.
+ // Directory[2] is the current app directory
+ // Directory[3] is the system directory
+ //
+ TCHAR dir[4][MAX_PATH + 1] = { 0 };
+ int numDirs = 0;
+ int i;
+ HINSTANCE dll = 0;
+ ALCAPI_GET_STRING alcGetStringFxn = 0;
+ ALCAPI_IS_EXTENSION_PRESENT alcIsExtensionPresentFxn = 0;
+ ALCAPI_OPEN_DEVICE alcOpenDeviceFxn = 0;
+ ALCAPI_CREATE_CONTEXT alcCreateContextFxn = 0;
+ ALCAPI_MAKE_CONTEXT_CURRENT alcMakeContextCurrentFxn = 0;
+ ALCAPI_DESTROY_CONTEXT alcDestroyContextFxn = 0;
+ ALCAPI_CLOSE_DEVICE alcCloseDeviceFxn = 0;
+
+ //
+ // Construct our search paths
+ //
+ if (GetLoadedModuleDirectory("OpenAL32.dll", dir[0], MAX_PATH)) {
+ ++numDirs;
+ }
+
+ GetCurrentDirectory(MAX_PATH, dir[1]);
+ _tcscat(dir[1], _T("\\"));
+ ++numDirs;
+
+ GetLoadedModuleDirectory(NULL, dir[2], MAX_PATH);
+ ++numDirs;
+
+ GetSystemDirectory(dir[3], MAX_PATH);
+ _tcscat(dir[3], _T("\\"));
+ ++numDirs;
+
+ //
+ // Begin searching for additional OpenAL implementations.
+ //
+ for(i = 0; i < numDirs; i++)
+ {
+ if ((i == 0) && (strcmp(dir[0], dir[3]) == 0)) // if searching router dir and router dir is sys dir, skip search
+ continue;
+
+ if ((i == 2) && (strcmp(dir[2], dir[1]) == 0)) // if searching app dir and app dir is current dir, skip search
+ continue;
+
+ if ((i == 3) && ((strcmp(dir[3], dir[2]) == 0) || (strcmp(dir[3], dir[1]) == 0))) // if searching sys dir and sys dir is either current or app directory, skip search
+ continue;
+
+ _tcscpy(searchName, dir[i]);
+ _tcscat(searchName, _T("*oal.dll"));
+ searchHandle = FindFirstFile(searchName, &findData);
+ if(searchHandle != INVALID_HANDLE_VALUE)
+ {
+ while(TRUE)
+ {
+ //
+ // if this is an OpenAL32.dll, skip it -- it's probably a router and shouldn't be enumerated regardless
+ //
+ _tcscpy(searchName, dir[i]);
+ _tcscat(searchName, findData.cFileName);
+ TCHAR cmpName[MAX_PATH];
+ _tcscpy(cmpName, searchName);
+ _tcsupr(cmpName);
+ if (_tcsstr(cmpName, _T("OPENAL32.DLL")) == 0)
+ {
+ boolean skipSearch = false;
+
+ // don't search the same DLL twice
+ TCHAR *szDLLName = _tcsrchr(searchName, _T('\\'));
+ if (szDLLName)
+ szDLLName++; // Skip over the '\'
+ else
+ szDLLName = searchName;
+
+ skipSearch = HasDLLAlreadyBeenUsed(g_pDeviceList, szDLLName);
+ if (!skipSearch)
+ skipSearch = HasDLLAlreadyBeenUsed(g_pCaptureDeviceList, szDLLName);
+ if (!skipSearch)
+ skipSearch = HasDLLAlreadyBeenUsed(g_pAllDevicesList, szDLLName);
+
+ if (skipSearch == false) {
+ dll = LoadLibrary(searchName);
+ if(dll)
+ {
+ alcOpenDeviceFxn = (ALCAPI_OPEN_DEVICE)GetProcAddress(dll, "alcOpenDevice");
+ alcCreateContextFxn = (ALCAPI_CREATE_CONTEXT)GetProcAddress(dll, "alcCreateContext");
+ alcMakeContextCurrentFxn = (ALCAPI_MAKE_CONTEXT_CURRENT)GetProcAddress(dll, "alcMakeContextCurrent");
+ alcGetStringFxn = (ALCAPI_GET_STRING)GetProcAddress(dll, "alcGetString");
+ alcDestroyContextFxn = (ALCAPI_DESTROY_CONTEXT)GetProcAddress(dll, "alcDestroyContext");
+ alcCloseDeviceFxn = (ALCAPI_CLOSE_DEVICE)GetProcAddress(dll, "alcCloseDevice");
+ alcIsExtensionPresentFxn = (ALCAPI_IS_EXTENSION_PRESENT)GetProcAddress(dll, "alcIsExtensionPresent");
+
+ if ((alcOpenDeviceFxn != 0) &&
+ (alcCreateContextFxn != 0) &&
+ (alcMakeContextCurrentFxn != 0) &&
+ (alcGetStringFxn != 0) &&
+ (alcDestroyContextFxn != 0) &&
+ (alcCloseDeviceFxn != 0) &&
+ (alcIsExtensionPresentFxn != 0)) {
+
+ bool bAddToAllDevicesList = false;
+
+ if (alcIsExtensionPresentFxn(NULL, "ALC_ENUMERATE_ALL_EXT")) {
+ // this DLL can enumerate *all* devices -- so add complete list of devices
+ specifier = alcGetStringFxn(0, ALC_ALL_DEVICES_SPECIFIER);
+ if ((specifier) && strlen(specifier))
+ {
+ do {
+ AddDevice(specifier, searchName, &g_pAllDevicesList);
+ specifier += strlen((char *)specifier) + 1;
+ } while (strlen((char *)specifier) > 0);
+ }
+ } else {
+ bAddToAllDevicesList = true;
+ }
+
+ if (alcIsExtensionPresentFxn(NULL, "ALC_ENUMERATION_EXT")) {
+ // this DLL can enumerate devices -- so add complete list of devices
+ specifier = alcGetStringFxn(0, ALC_DEVICE_SPECIFIER);
+ if ((specifier) && strlen(specifier))
+ {
+ do {
+ AddDevice(specifier, searchName, &g_pDeviceList);
+ if (bAddToAllDevicesList)
+ AddDevice(specifier, searchName, &g_pAllDevicesList);
+ specifier += strlen((char *)specifier) + 1;
+ } while (strlen((char *)specifier) > 0);
+ }
+ } else {
+ // no enumeration ability, -- so just add default device to the list
+ device = alcOpenDeviceFxn(NULL);
+ if (device != NULL) {
+ context = alcCreateContextFxn(device, NULL);
+ alcMakeContextCurrentFxn((ALCcontext *)context);
+ if (context != NULL) {
+ specifier = alcGetStringFxn(device, ALC_DEVICE_SPECIFIER);
+ if ((specifier) && strlen(specifier))
+ {
+ AddDevice(specifier, searchName, &g_pDeviceList);
+ if (bAddToAllDevicesList)
+ AddDevice(specifier, searchName, &g_pAllDevicesList);
+ }
+ alcMakeContextCurrentFxn((ALCcontext *)NULL);
+ alcDestroyContextFxn((ALCcontext *)context);
+ alcCloseDeviceFxn(device);
+ }
+ }
+ }
+
+ // add to capture device list
+ if (_tcsstr(cmpName, _T("CT_OAL.DLL")) == 0) {
+ // Skip native AL component (will contain same Capture List as the wrap_oal component)
+ if (alcIsExtensionPresentFxn(NULL, "ALC_EXT_CAPTURE")) {
+ // this DLL supports capture -- so add complete list of capture devices
+ specifier = alcGetStringFxn(0, ALC_CAPTURE_DEVICE_SPECIFIER);
+ if ((specifier) && strlen(specifier))
+ {
+ do {
+ AddDevice(specifier, searchName, &g_pCaptureDeviceList);
+ specifier += strlen((char *)specifier) + 1;
+ } while (strlen((char *)specifier) > 0);
+ }
+ }
+ }
+ }
+
+ FreeLibrary(dll);
+ dll = 0;
+ }
+ }
+ }
+
+ if(!FindNextFile(searchHandle, &findData))
+ {
+ if(GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ break;
+ }
+ }
+ }
+
+ FindClose(searchHandle);
+ searchHandle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ // We now have a list of all the Device Names and their associated DLLs.
+ // Put the names in the appropriate strings
+ ALuint uiLength;
+ ALchar *pszTemp;
+ char *pszDefaultName = NULL;
+ bool bFound = false;
+
+ if (g_pDeviceList)
+ {
+ uiLength = 0;
+ for (pDevice = g_pDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ uiLength += (strlen(pDevice->pszDeviceName) + 1);
+
+ pszDeviceSpecifierList = (ALchar*)malloc((uiLength + 1) * sizeof(ALchar));
+ if (pszTemp = pszDeviceSpecifierList)
+ {
+ memset(pszDeviceSpecifierList, 0, (uiLength + 1) * sizeof(ALchar));
+ for (pDevice = g_pDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ strcpy(pszTemp, pDevice->pszDeviceName);
+ pszTemp += (strlen(pDevice->pszDeviceName) + 1);
+ }
+ }
+
+ // Determine what the Default Device should be
+ if (GetDefaultPlaybackDeviceName(&pszDefaultName))
+ {
+ bFound = false;
+
+ // Search for an exact match first
+ bFound = FindDevice(g_pDeviceList, pszDefaultName, true, &pszDefaultDeviceSpecifier);
+
+ // If we haven't found a match ... search for a partial match if name contains 'X-Fi'
+ if ((!bFound) && (strstr(pszDefaultName, "X-Fi")))
+ bFound = FindDevice(g_pDeviceList, "X-Fi", false, &pszDefaultDeviceSpecifier);
+
+ // If we haven't found a match ... search for a partial match if name contains 'Audigy'
+ if ((!bFound) && (strstr(pszDefaultName, "Audigy")))
+ bFound = FindDevice(g_pDeviceList, "Audigy", false, &pszDefaultDeviceSpecifier);
+
+ // If we haven't found a match ... search for a partial match with 'Generic Hardware'
+ if (!bFound)
+ bFound = FindDevice(g_pDeviceList, "Generic Hardware", false, &pszDefaultDeviceSpecifier);
+
+ // If we haven't found a match ... search for a partial match with 'Generic Software'
+ if (!bFound)
+ bFound = FindDevice(g_pDeviceList, "Generic Software", false, &pszDefaultDeviceSpecifier);
+
+ // If we STILL haven't found a match ... pick the 1st device!
+ if (!bFound)
+ {
+ pszDefaultDeviceSpecifier = (char*)malloc((strlen(g_pDeviceList->pszDeviceName) + 1) * sizeof(char));
+ if (pszDefaultDeviceSpecifier)
+ strcpy(pszDefaultDeviceSpecifier, g_pDeviceList->pszDeviceName);
+ }
+
+ free(pszDefaultName);
+ pszDefaultName = NULL;
+ }
+ }
+
+ if (g_pCaptureDeviceList)
+ {
+ uiLength = 0;
+ for (pDevice = g_pCaptureDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ uiLength += (strlen(pDevice->pszDeviceName) + 1);
+
+ pszCaptureDeviceSpecifierList = (ALchar*)malloc((uiLength + 1) * sizeof(ALchar));
+ if (pszTemp = pszCaptureDeviceSpecifierList)
+ {
+ memset(pszCaptureDeviceSpecifierList, 0, (uiLength + 1) * sizeof(ALchar));
+ for (pDevice = g_pCaptureDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ strcpy(pszTemp, pDevice->pszDeviceName);
+ pszTemp += (strlen(pDevice->pszDeviceName) + 1);
+ }
+ }
+
+ if (GetDefaultCaptureDeviceName(&pszDefaultName))
+ {
+ bFound = false;
+
+ // Search for an exact match first
+ bFound = FindDevice(g_pCaptureDeviceList, pszDefaultName, true, &pszDefaultCaptureDeviceSpecifier);
+
+ // If we haven't found a match, truncate the default name to 32 characters (MMSYSTEM limitation)
+ if ((!bFound) && (strlen(pszDefaultName) > 31))
+ {
+ pszDefaultName[31] = '\0';
+ bFound = FindDevice(g_pCaptureDeviceList, pszDefaultName, true, &pszDefaultCaptureDeviceSpecifier);
+ }
+
+ // If we haven't found a match ... pick the 1st device!
+ if (!bFound)
+ {
+ pszDefaultCaptureDeviceSpecifier = (char*)malloc((strlen(g_pCaptureDeviceList->pszDeviceName) + 1) * sizeof(char));
+ if (pszDefaultCaptureDeviceSpecifier)
+ strcpy(pszDefaultCaptureDeviceSpecifier, g_pCaptureDeviceList->pszDeviceName);
+ }
+
+ free(pszDefaultName);
+ pszDefaultName = NULL;
+ }
+ }
+
+ if (g_pAllDevicesList)
+ {
+ uiLength = 0;
+ for (pDevice = g_pAllDevicesList; pDevice; pDevice = pDevice->pNextDevice)
+ uiLength += (strlen(pDevice->pszDeviceName) + 1);
+
+ pszAllDevicesSpecifierList = (ALchar*)malloc((uiLength + 1) * sizeof(ALchar));
+ if (pszTemp = pszAllDevicesSpecifierList)
+ {
+ memset(pszAllDevicesSpecifierList, 0, (uiLength + 1) * sizeof(ALchar));
+ for (pDevice = g_pAllDevicesList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ strcpy(pszTemp, pDevice->pszDeviceName);
+ pszTemp += (strlen(pDevice->pszDeviceName) + 1);
+ }
+ }
+
+ // Determine what the Default Device should be
+ if (GetDefaultPlaybackDeviceName(&pszDefaultName))
+ {
+ bFound = false;
+
+ // If the (regular) default Playback device exists in this list ... use that
+ bFound = FindDevice(g_pAllDevicesList, pszDefaultDeviceSpecifier, true, &pszDefaultAllDevicesSpecifier);
+
+ // If we haven't found a match ... pick a partial match with the Default Device Name
+ if (!bFound)
+ bFound = FindDevice(g_pAllDevicesList, pszDefaultName, false, &pszDefaultAllDevicesSpecifier);
+
+ // If we STILL haven't found a match ... pick the 1st device!
+ if (!bFound)
+ {
+ pszDefaultAllDevicesSpecifier = (char*)malloc((strlen(g_pAllDevicesList->pszDeviceName) + 1) * sizeof(char));
+ if (pszDefaultAllDevicesSpecifier)
+ strcpy(pszDefaultAllDevicesSpecifier, g_pAllDevicesList->pszDeviceName);
+ }
+
+ free(pszDefaultName);
+ pszDefaultName = NULL;
+ }
+ }
+ }
+
+ return;
+}
+
+
+
+
+//*****************************************************************************
+// HasDLLAlreadyBeenUsed
+//*****************************************************************************
+bool HasDLLAlreadyBeenUsed(ALDEVICE *pDeviceList, TCHAR *szDLLName)
+{
+ // Checks if an OpenAL DLL has already been enumerated
+ ALDEVICE *pDevice = NULL;
+ TCHAR *szHostDLLName;
+ bool bReturn = false;
+
+ for (pDevice = pDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ szHostDLLName = _tcsrchr(pDevice->pszHostDLLFilename, _T('\\'));
+ if (szHostDLLName)
+ szHostDLLName++; // Skip over the '\'
+ else
+ szHostDLLName = pDevice->pszHostDLLFilename;
+
+ if (_tcscmp(szHostDLLName, szDLLName) == 0)
+ {
+ bReturn = true;
+ break;
+ }
+ }
+
+ return bReturn;
+}
+
+
+
+
+//*****************************************************************************
+// ValidCaptureDevice
+//*****************************************************************************
+/*
+bool ValidCaptureDevice(const char *szCaptureDeviceName)
+{
+ // Microsoft changed the behaviour of Input devices on Windows Vista such that *each* input
+ // on each soundcard is reported as a separate device. Unfortunately, even though you can
+ // enumerate each input there are restrictions on what devices can be opened (e.g. you can only
+ // open the soundcard's default input). There is no API call to change the default input, so
+ // there is little point enumerating input devices that cannot be used, so we filter them out here.
+ WAVEFORMATEX wfex = { WAVE_FORMAT_PCM, 1, 22050, 44100, 2, 16, 0 }; // 16bit Mono 22050Hz
+ WAVEINCAPS WaveInCaps;
+ HWAVEIN hWaveIn;
+ bool bValid = false;
+
+ // Find the device ID from the device name
+ long lNumCaptureDevs = waveInGetNumDevs();
+ long lDeviceID = -1;
+ for (long lLoop = 0; lLoop < lNumCaptureDevs; lLoop++)
+ {
+ if (waveInGetDevCaps(lLoop, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
+ {
+ if (!strcmp(szCaptureDeviceName, WaveInCaps.szPname))
+ {
+ lDeviceID = lLoop;
+ break;
+ }
+ }
+ }
+
+ if (lDeviceID != -1)
+ {
+ if (waveInOpen(&hWaveIn, lDeviceID, &wfex, NULL, NULL, WAVE_MAPPED) == MMSYSERR_NOERROR)
+ {
+ waveInClose(hWaveIn);
+ bValid = true;
+ }
+ }
+
+ return bValid;
+}
+*/
+
+
+
+//*****************************************************************************
+// GetDefaultPlaybackDeviceName
+//*****************************************************************************
+bool GetDefaultPlaybackDeviceName(char **pszName)
+{
+ // Try to use DirectSound to get the name of the 'Preferred Audio Device / Endpoint"
+ // If that fails use MMSYSTEM (name will be limited to 32 characters in length)
+ TCHAR szPath[_MAX_PATH];
+ HINSTANCE hDSoundDLL;
+
+ if (!pszName)
+ return false;
+
+ *pszName = NULL;
+
+ // Load dsound.dll from the System Directory and use the DirectSoundEnumerateA function to
+ // get the list of playback devices
+ if (GetSystemDirectory(szPath, _MAX_PATH))
+ {
+ _tcscat(szPath, "\\dsound.dll");
+ hDSoundDLL = LoadLibrary(szPath);
+ if (hDSoundDLL)
+ {
+ LPDIRECTSOUNDENUMERATEA pfnDirectSoundEnumerateA = (LPDIRECTSOUNDENUMERATEA)GetProcAddress(hDSoundDLL, "DirectSoundEnumerateA");
+ if (pfnDirectSoundEnumerateA)
+ pfnDirectSoundEnumerateA(&DSEnumCallback, pszName);
+ FreeLibrary(hDSoundDLL);
+ }
+ }
+
+ // Falling back to MMSYSTEM
+ if (*pszName == NULL)
+ {
+ UINT uDeviceID=0;
+ DWORD dwFlags=1;
+ WAVEOUTCAPS outputInfo;
+
+ #if !defined(_WIN64)
+ #ifdef __GNUC__
+ __asm__ ("pusha;");
+ #else
+ __asm pusha; // workaround for register destruction caused by these wavOutMessage calls (weird but true)
+ #endif
+ #endif // !defined(_WIN64)
+ waveOutMessage((HWAVEOUT)(UINT_PTR)WAVE_MAPPER,0x2000+0x0015,(LPARAM)&uDeviceID,(WPARAM)&dwFlags);
+ waveOutGetDevCaps(uDeviceID,&outputInfo,sizeof(outputInfo));
+ #if !defined(_WIN64)
+ #ifdef __GNUC__
+ __asm__ ("popa;");
+ #else
+ __asm popa;
+ #endif
+ #endif // !defined(_WIN64)
+
+ *pszName = (char*)malloc((strlen(outputInfo.szPname) + 1) * sizeof(char));
+ if (*pszName)
+ strcpy(*pszName, outputInfo.szPname);
+ }
+
+ return (*pszName) ? true : false;
+}
+
+
+
+
+//*****************************************************************************
+// GetDefaultCaptureDeviceName
+//*****************************************************************************
+bool GetDefaultCaptureDeviceName(char **pszName)
+{
+ // Try to use DirectSound to get the name of the 'Preferred Audio Device / Endpoint" for recording.
+ // If that fails use MMSYSTEM (name will be limited to 32 characters in length)
+ TCHAR szPath[_MAX_PATH];
+ HINSTANCE hDSoundDLL;
+
+ if (!pszName)
+ return false;
+
+ *pszName = NULL;
+
+ // Load dsound.dll from the System Directory and use the DirectSoundCaptureEnumerateA function to
+ // get the list of capture devices
+ if (GetSystemDirectory(szPath, _MAX_PATH))
+ {
+ _tcscat(szPath, "\\dsound.dll");
+ hDSoundDLL = LoadLibrary(szPath);
+ if (hDSoundDLL)
+ {
+ LPDIRECTSOUNDCAPTUREENUMERATEA pfnDirectSoundCaptureEnumerateA = (LPDIRECTSOUNDCAPTUREENUMERATEA)GetProcAddress(hDSoundDLL, "DirectSoundCaptureEnumerateA");
+ if (pfnDirectSoundCaptureEnumerateA)
+ pfnDirectSoundCaptureEnumerateA(&DSEnumCallback, pszName);
+ FreeLibrary(hDSoundDLL);
+ }
+ }
+
+ // Falling back to MMSYSTEM
+ if (*pszName == NULL)
+ {
+ UINT uDeviceID=0;
+ DWORD dwFlags=1;
+ WAVEINCAPS inputInfo;
+
+ #if !defined(_WIN64)
+ #ifdef __GNUC__
+ __asm__ ("pusha;");
+ #else
+ __asm pusha; // workaround for register destruction caused by these wavOutMessage calls (weird but true)
+ #endif
+ #endif // !defined(_WIN64)
+ waveInMessage((HWAVEIN)(UINT_PTR)WAVE_MAPPER,0x2000+0x0015,(LPARAM)&uDeviceID,(WPARAM)&dwFlags);
+ waveInGetDevCaps(uDeviceID, &inputInfo, sizeof(inputInfo));
+ #if !defined(_WIN64)
+ #ifdef __GNUC__
+ __asm__ ("popa;");
+ #else
+ __asm popa;
+ #endif
+ #endif // !defined(_WIN64)
+
+ *pszName = (char*)malloc((strlen(inputInfo.szPname) + 1) * sizeof(char));
+ if (*pszName)
+ strcpy(*pszName, inputInfo.szPname);
+ }
+
+ return (*pszName) ? true : false;
+}
+
+
+
+
+//*****************************************************************************
+// DSEnumCallback
+//*****************************************************************************
+BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
+{
+ // DirectSound Enumeration callback will be called for each device found.
+ // The first device returned with a non-NULL GUID is the 'preferred device'
+
+ // Skip over the device without a GUID
+ if (lpGuid)
+ {
+ char **pszName = (char**)lpContext;
+ *pszName = (char*)malloc((strlen(lpcstrDescription)+1) * sizeof(char));
+ if (*pszName)
+ {
+ strcpy(*pszName, lpcstrDescription);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+//*****************************************************************************
+// FindDevice
+//*****************************************************************************
+bool FindDevice(ALDEVICE *pDeviceList, char *szDeviceName, bool bExactMatch, char **ppszDefaultName)
+{
+ // Search through pDeviceList for szDeviceName using an exact match if bExactMatch is true, or using
+ // a sub-string search otherwise.
+ // If found, allocate memory for *ppszDefaultName and copy the device name over
+ ALDEVICE *pDevice = NULL;
+ bool bFound = false;
+
+ if (!pDeviceList || !szDeviceName || !ppszDefaultName)
+ return false;
+
+ for (pDevice = pDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ if (bExactMatch)
+ bFound = (strcmp(pDevice->pszDeviceName, szDeviceName) == 0) ? true : false;
+ else
+ bFound = (strstr(pDevice->pszDeviceName, szDeviceName)) ? true : false;
+
+ if (bFound)
+ {
+ *ppszDefaultName = (char*)malloc((strlen(pDevice->pszDeviceName) + 1) * sizeof(char));
+ if (*ppszDefaultName)
+ {
+ strcpy(*ppszDefaultName, pDevice->pszDeviceName);
+ break;
+ }
+ }
+ }
+
+ return *ppszDefaultName ? true : false;
+}
+
+
+
+
+//*****************************************************************************
+// LoadDevicesDLL
+//*****************************************************************************
+HINSTANCE LoadDevicesDLL(ALDEVICE *pDeviceList, const ALchar *szDeviceName)
+{
+ // Search pDeviceList for szDeviceName, and when found load the OpenAL DLL
+ // that contains that Device name.
+ HINSTANCE hDLL = NULL;
+ ALDEVICE *pDevice;
+
+ for (pDevice = pDeviceList; pDevice; pDevice = pDevice->pNextDevice)
+ {
+ if (strcmp(pDevice->pszDeviceName, szDeviceName) == 0)
+ {
+ hDLL = LoadLibrary(pDevice->pszHostDLLFilename);
+ break;
+ }
+ }
+
+ return hDLL;
+}
+
+
+
+
+//*****************************************************************************
+// FillOutAlcFunctions
+//*****************************************************************************
+ALboolean FillOutAlcFunctions(ALCdevice* device)
+{
+ ALboolean alcFxns = FALSE;
+ ALCAPI_FXN_TABLE* alcApi = &device->AlcApi;
+
+ memset(alcApi, 0, sizeof(ALCAPI_FXN_TABLE));
+
+ //
+ // Get the OpenAL 1.0 Entry points.
+ //
+ alcApi->alcCreateContext = (ALCAPI_CREATE_CONTEXT)GetProcAddress(device->Dll, "alcCreateContext");
+ alcApi->alcMakeContextCurrent = (ALCAPI_MAKE_CONTEXT_CURRENT)GetProcAddress(device->Dll, "alcMakeContextCurrent");
+ alcApi->alcProcessContext = (ALCAPI_PROCESS_CONTEXT)GetProcAddress(device->Dll, "alcProcessContext");
+ alcApi->alcSuspendContext = (ALCAPI_SUSPEND_CONTEXT)GetProcAddress(device->Dll, "alcSuspendContext");
+ alcApi->alcDestroyContext = (ALCAPI_DESTROY_CONTEXT)GetProcAddress(device->Dll, "alcDestroyContext");
+ alcApi->alcGetCurrentContext = (ALCAPI_GET_CURRENT_CONTEXT)GetProcAddress(device->Dll, "alcGetCurrentContext");
+ alcApi->alcGetContextsDevice = (ALCAPI_GET_CONTEXTS_DEVICE)GetProcAddress(device->Dll, "alcGetContextsDevice");
+
+ alcApi->alcOpenDevice = (ALCAPI_OPEN_DEVICE)GetProcAddress(device->Dll, "alcOpenDevice");
+ alcApi->alcCloseDevice = (ALCAPI_CLOSE_DEVICE)GetProcAddress(device->Dll, "alcCloseDevice");
+
+ alcApi->alcGetError = (ALCAPI_GET_ERROR)GetProcAddress(device->Dll, "alcGetError");
+
+ alcApi->alcIsExtensionPresent = (ALCAPI_IS_EXTENSION_PRESENT)GetProcAddress(device->Dll, "alcIsExtensionPresent");
+ alcApi->alcGetProcAddress = (ALCAPI_GET_PROC_ADDRESS)GetProcAddress(device->Dll, "alcGetProcAddress");
+ alcApi->alcGetEnumValue = (ALCAPI_GET_ENUM_VALUE)GetProcAddress(device->Dll, "alcGetEnumValue");
+
+ alcApi->alcGetString = (ALCAPI_GET_STRING)GetProcAddress(device->Dll, "alcGetString");
+ alcApi->alcGetIntegerv = (ALCAPI_GET_INTEGERV)GetProcAddress(device->Dll, "alcGetIntegerv");
+
+ //
+ // Get the OpenAL 1.1 Entry points.
+ //
+ alcApi->alcCaptureOpenDevice = (ALCAPI_CAPTURE_OPEN_DEVICE)GetProcAddress(device->Dll, "alcCaptureOpenDevice");
+ alcApi->alcCaptureCloseDevice = (ALCAPI_CAPTURE_CLOSE_DEVICE)GetProcAddress(device->Dll, "alcCaptureCloseDevice");
+ alcApi->alcCaptureStart = (ALCAPI_CAPTURE_START)GetProcAddress(device->Dll, "alcCaptureStart");
+ alcApi->alcCaptureStop = (ALCAPI_CAPTURE_STOP)GetProcAddress(device->Dll, "alcCaptureStop");
+ alcApi->alcCaptureSamples = (ALCAPI_CAPTURE_SAMPLES)GetProcAddress(device->Dll, "alcCaptureSamples");
+
+ // handle legacy issue with old Creative DLLs which may not have alcGetProcAddress, alcIsExtensionPresent, alcGetEnumValue
+ if (alcApi->alcGetProcAddress == NULL) {
+ alcApi->alcGetProcAddress = (ALCAPI_GET_PROC_ADDRESS)alcGetProcAddress;
+ }
+ if (alcApi->alcIsExtensionPresent == NULL) {
+ alcApi->alcIsExtensionPresent = (ALCAPI_IS_EXTENSION_PRESENT)alcIsExtensionPresent;
+ }
+ if (alcApi->alcGetEnumValue == NULL) {
+ alcApi->alcGetEnumValue = (ALCAPI_GET_ENUM_VALUE)alcGetEnumValue;
+ }
+
+
+ alcFxns = (alcApi->alcCreateContext &&
+ alcApi->alcMakeContextCurrent &&
+ alcApi->alcProcessContext &&
+ alcApi->alcSuspendContext &&
+ alcApi->alcDestroyContext &&
+ alcApi->alcGetCurrentContext &&
+ alcApi->alcGetContextsDevice &&
+ alcApi->alcOpenDevice &&
+ alcApi->alcCloseDevice &&
+ alcApi->alcGetError &&
+ alcApi->alcIsExtensionPresent &&
+ alcApi->alcGetProcAddress &&
+ alcApi->alcGetEnumValue &&
+ alcApi->alcGetString &&
+ alcApi->alcGetIntegerv);
+
+ return alcFxns;
+}
+
+
+
+
+//*****************************************************************************
+// FillOutAlFunctions
+//*****************************************************************************
+ALboolean FillOutAlFunctions(ALCcontext* context)
+{
+ ALboolean alFxns = FALSE;
+ ALAPI_FXN_TABLE* alApi = &context->AlApi;
+
+ memset(alApi, 0, sizeof(ALAPI_FXN_TABLE));
+
+ //
+ // Get the OpenAL 1.0 & 1.1 Entry points.
+ //
+ alApi->alEnable = (ALAPI_ENABLE)GetProcAddress(context->Device->Dll, "alEnable");
+ alApi->alDisable = (ALAPI_DISABLE)GetProcAddress(context->Device->Dll, "alDisable");
+ alApi->alIsEnabled = (ALAPI_IS_ENABLED)GetProcAddress(context->Device->Dll, "alIsEnabled");
+
+ alApi->alGetString = (ALAPI_GET_STRING)GetProcAddress(context->Device->Dll, "alGetString");
+ alApi->alGetBooleanv = (ALAPI_GET_BOOLEANV)GetProcAddress(context->Device->Dll, "alGetBooleanv");
+ alApi->alGetIntegerv = (ALAPI_GET_INTEGERV)GetProcAddress(context->Device->Dll, "alGetIntegerv");
+ alApi->alGetFloatv = (ALAPI_GET_FLOATV)GetProcAddress(context->Device->Dll, "alGetFloatv");
+ alApi->alGetDoublev = (ALAPI_GET_DOUBLEV)GetProcAddress(context->Device->Dll, "alGetDoublev");
+ alApi->alGetBoolean = (ALAPI_GET_BOOLEAN)GetProcAddress(context->Device->Dll, "alGetBoolean");
+ alApi->alGetInteger = (ALAPI_GET_INTEGER)GetProcAddress(context->Device->Dll, "alGetInteger");
+ alApi->alGetFloat = (ALAPI_GET_FLOAT)GetProcAddress(context->Device->Dll, "alGetFloat");
+ alApi->alGetDouble = (ALAPI_GET_DOUBLE)GetProcAddress(context->Device->Dll, "alGetDouble");
+ alApi->alGetError = (ALAPI_GET_ERROR)GetProcAddress(context->Device->Dll, "alGetError");
+ alApi->alIsExtensionPresent = (ALAPI_IS_EXTENSION_PRESENT)GetProcAddress(context->Device->Dll, "alIsExtensionPresent");
+ alApi->alGetProcAddress = (ALAPI_GET_PROC_ADDRESS)GetProcAddress(context->Device->Dll, "alGetProcAddress");
+ alApi->alGetEnumValue = (ALAPI_GET_ENUM_VALUE)GetProcAddress(context->Device->Dll, "alGetEnumValue");
+
+ alApi->alListenerf = (ALAPI_LISTENERF)GetProcAddress(context->Device->Dll, "alListenerf");
+ alApi->alListener3f = (ALAPI_LISTENER3F)GetProcAddress(context->Device->Dll, "alListener3f");
+ alApi->alListenerfv = (ALAPI_LISTENERFV)GetProcAddress(context->Device->Dll, "alListenerfv");
+ alApi->alListeneri = (ALAPI_LISTENERI)GetProcAddress(context->Device->Dll, "alListeneri");
+ alApi->alListener3i = (ALAPI_LISTENER3I)GetProcAddress(context->Device->Dll, "alListener3i");
+ alApi->alListeneriv = (ALAPI_LISTENERIV)GetProcAddress(context->Device->Dll, "alListeneriv");
+ alApi->alGetListenerf = (ALAPI_GET_LISTENERF)GetProcAddress(context->Device->Dll, "alGetListenerf");
+ alApi->alGetListener3f = (ALAPI_GET_LISTENER3F)GetProcAddress(context->Device->Dll, "alGetListener3f");
+ alApi->alGetListenerfv = (ALAPI_GET_LISTENERFV)GetProcAddress(context->Device->Dll, "alGetListenerfv");
+ alApi->alGetListeneri = (ALAPI_GET_LISTENERI)GetProcAddress(context->Device->Dll, "alGetListeneri");
+ alApi->alGetListener3i = (ALAPI_GET_LISTENER3I)GetProcAddress(context->Device->Dll, "alGetListener3i");
+ alApi->alGetListeneriv = (ALAPI_GET_LISTENERIV)GetProcAddress(context->Device->Dll, "alGetListeneriv");
+
+ alApi->alGenSources = (ALAPI_GEN_SOURCES)GetProcAddress(context->Device->Dll, "alGenSources");
+ alApi->alDeleteSources = (ALAPI_DELETE_SOURCES)GetProcAddress(context->Device->Dll, "alDeleteSources");
+ alApi->alIsSource = (ALAPI_IS_SOURCE)GetProcAddress(context->Device->Dll, "alIsSource");
+ alApi->alSourcef = (ALAPI_SOURCEF)GetProcAddress(context->Device->Dll, "alSourcef");
+ alApi->alSource3f = (ALAPI_SOURCE3F)GetProcAddress(context->Device->Dll, "alSource3f");
+ alApi->alSourcefv = (ALAPI_SOURCEFV)GetProcAddress(context->Device->Dll, "alSourcefv");
+ alApi->alSourcei = (ALAPI_SOURCEI)GetProcAddress(context->Device->Dll, "alSourcei");
+ alApi->alSource3i = (ALAPI_SOURCE3I)GetProcAddress(context->Device->Dll, "alSource3i");
+ alApi->alSourceiv = (ALAPI_SOURCEIV)GetProcAddress(context->Device->Dll, "alSourceiv");
+ alApi->alGetSourcef = (ALAPI_GET_SOURCEF)GetProcAddress(context->Device->Dll, "alGetSourcef");
+ alApi->alGetSource3f = (ALAPI_GET_SOURCE3F)GetProcAddress(context->Device->Dll, "alGetSource3f");
+ alApi->alGetSourcefv = (ALAPI_GET_SOURCEFV)GetProcAddress(context->Device->Dll, "alGetSourcefv");
+ alApi->alGetSourcei = (ALAPI_GET_SOURCEI)GetProcAddress(context->Device->Dll, "alGetSourcei");
+ alApi->alGetSource3i = (ALAPI_GET_SOURCE3I)GetProcAddress(context->Device->Dll, "alGetSource3i");
+ alApi->alGetSourceiv = (ALAPI_GET_SOURCEIV)GetProcAddress(context->Device->Dll, "alGetSourceiv");
+ alApi->alSourcePlayv = (ALAPI_SOURCE_PLAYV)GetProcAddress(context->Device->Dll, "alSourcePlayv");
+ alApi->alSourceStopv = (ALAPI_SOURCE_STOPV)GetProcAddress(context->Device->Dll, "alSourceStopv");
+ alApi->alSourceRewindv = (ALAPI_SOURCE_REWINDV)GetProcAddress(context->Device->Dll, "alSourceRewindv");
+ alApi->alSourcePausev = (ALAPI_SOURCE_PAUSEV)GetProcAddress(context->Device->Dll, "alSourcePausev");
+ alApi->alSourcePlay = (ALAPI_SOURCE_PLAY)GetProcAddress(context->Device->Dll, "alSourcePlay");
+ alApi->alSourceStop = (ALAPI_SOURCE_STOP)GetProcAddress(context->Device->Dll, "alSourceStop");
+ alApi->alSourceRewind = (ALAPI_SOURCE_STOP)GetProcAddress(context->Device->Dll, "alSourceRewind");
+ alApi->alSourcePause = (ALAPI_SOURCE_PAUSE)GetProcAddress(context->Device->Dll, "alSourcePause");
+
+ alApi->alSourceQueueBuffers = (ALAPI_SOURCE_QUEUE_BUFFERS)GetProcAddress(context->Device->Dll, "alSourceQueueBuffers");
+ alApi->alSourceUnqueueBuffers = (ALAPI_SOURCE_UNQUEUE_BUFFERS)GetProcAddress(context->Device->Dll, "alSourceUnqueueBuffers");
+
+ alApi->alGenBuffers = (ALAPI_GEN_BUFFERS)GetProcAddress(context->Device->Dll, "alGenBuffers");
+ alApi->alDeleteBuffers = (ALAPI_DELETE_BUFFERS)GetProcAddress(context->Device->Dll, "alDeleteBuffers");
+ alApi->alIsBuffer = (ALAPI_IS_BUFFER)GetProcAddress(context->Device->Dll, "alIsBuffer");
+ alApi->alBufferData = (ALAPI_BUFFER_DATA)GetProcAddress(context->Device->Dll, "alBufferData");
+ alApi->alBufferf = (ALAPI_BUFFERF)GetProcAddress(context->Device->Dll, "alBufferf");
+ alApi->alBuffer3f = (ALAPI_BUFFER3F)GetProcAddress(context->Device->Dll, "alBuffer3f");
+ alApi->alBufferfv = (ALAPI_BUFFERFV)GetProcAddress(context->Device->Dll, "alBufferfv");
+ alApi->alBufferi = (ALAPI_BUFFERI)GetProcAddress(context->Device->Dll, "alBufferi");
+ alApi->alBuffer3i = (ALAPI_BUFFER3I)GetProcAddress(context->Device->Dll, "alBuffer3i");
+ alApi->alBufferiv = (ALAPI_BUFFERIV)GetProcAddress(context->Device->Dll, "alBufferiv");
+ alApi->alGetBufferf = (ALAPI_GET_BUFFERF)GetProcAddress(context->Device->Dll, "alGetBufferf");
+ alApi->alGetBuffer3f = (ALAPI_GET_BUFFER3F)GetProcAddress(context->Device->Dll, "alGetBuffer3f");
+ alApi->alGetBufferfv = (ALAPI_GET_BUFFERFV)GetProcAddress(context->Device->Dll, "alGetBufferfv");
+ alApi->alGetBufferi = (ALAPI_GET_BUFFERI)GetProcAddress(context->Device->Dll, "alGetBufferi");
+ alApi->alGetBuffer3i = (ALAPI_GET_BUFFER3I)GetProcAddress(context->Device->Dll, "alGetBuffer3i");
+ alApi->alGetBufferiv = (ALAPI_GET_BUFFERIV)GetProcAddress(context->Device->Dll, "alGetBufferiv");
+
+ alApi->alDopplerFactor = (ALAPI_DOPPLER_FACTOR)GetProcAddress(context->Device->Dll, "alDopplerFactor");
+ alApi->alDopplerVelocity = (ALAPI_DOPPLER_VELOCITY)GetProcAddress(context->Device->Dll, "alDopplerVelocity");
+ alApi->alSpeedOfSound = (ALAPI_SPEED_OF_SOUND)GetProcAddress(context->Device->Dll, "alSpeedOfSound");
+ alApi->alDistanceModel = (ALAPI_DISTANCE_MODEL)GetProcAddress(context->Device->Dll, "alDistanceModel");
+
+ alFxns = (alApi->alEnable &&
+ alApi->alDisable &&
+ alApi->alIsEnabled &&
+
+ alApi->alGetString &&
+ alApi->alGetBooleanv &&
+ alApi->alGetIntegerv &&
+ alApi->alGetFloatv &&
+ alApi->alGetDoublev &&
+ alApi->alGetBoolean &&
+ alApi->alGetInteger &&
+ alApi->alGetFloat &&
+ alApi->alGetDouble &&
+
+ alApi->alGetError &&
+
+ alApi->alIsExtensionPresent &&
+ alApi->alGetProcAddress &&
+ alApi->alGetEnumValue &&
+
+ alApi->alListenerf &&
+ alApi->alListener3f &&
+ alApi->alListenerfv &&
+ alApi->alListeneri &&
+ alApi->alGetListenerf &&
+ alApi->alGetListener3f &&
+ alApi->alGetListenerfv &&
+ alApi->alGetListeneri &&
+
+ alApi->alGenSources &&
+ alApi->alDeleteSources &&
+ alApi->alIsSource &&
+ alApi->alSourcef &&
+ alApi->alSource3f &&
+ alApi->alSourcefv &&
+ alApi->alSourcei &&
+ alApi->alGetSourcef &&
+ alApi->alGetSource3f &&
+ alApi->alGetSourcefv &&
+ alApi->alGetSourcei &&
+ alApi->alSourcePlayv &&
+ alApi->alSourceStopv &&
+ alApi->alSourceRewindv &&
+ alApi->alSourcePausev &&
+ alApi->alSourcePlay &&
+ alApi->alSourceStop &&
+ alApi->alSourceRewind &&
+ alApi->alSourcePause &&
+
+ alApi->alSourceQueueBuffers &&
+ alApi->alSourceUnqueueBuffers &&
+
+ alApi->alGenBuffers &&
+ alApi->alDeleteBuffers &&
+ alApi->alIsBuffer &&
+ alApi->alBufferData &&
+ alApi->alGetBufferf &&
+ alApi->alGetBufferi &&
+
+ alApi->alDopplerFactor &&
+ alApi->alDopplerVelocity &&
+ alApi->alDistanceModel);
+
+ return alFxns;
+}
+
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+//
+// ALC API Entry Points
+//
+//*****************************************************************************ALC_
+//*****************************************************************************
+
+//*****************************************************************************
+// alcCloseDevice
+//*****************************************************************************
+//
+ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice* device)
+{
+#ifdef _LOGCALLS
+ LOG("alcCloseDevice device %p\n", device);
+#endif
+ if(!device)
+ {
+ return ALC_FALSE;
+ }
+
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcCloseDevice(g_CaptureDevice->CaptureDevice);
+
+ //
+ // Check if its linked to a context.
+ //
+ if(device->InUse)
+ {
+ ALCcontext* context = 0;
+ ALlistEntry* entry = 0;
+
+ //
+ // Not all of the contexts using the device have been destroyed.
+ //
+ assert(0);
+
+ //
+ // Loop through the context list and free and contexts linked to the device.
+ // Go back to the beginning each time in case some one changed the context
+ // list iterator.
+ //
+ alListAcquireLock(alContextList);
+ entry = alListIteratorReset(alContextList);
+ while(entry)
+ {
+ context = (ALCcontext*)alListGetData(entry);
+ if(context->Device == device)
+ {
+ alListReleaseLock(alContextList);
+ alcDestroyContext((ALCcontext *)context);
+ alListAcquireLock(alContextList);
+ entry = alListIteratorReset(alContextList);
+ }
+
+ else
+ {
+ entry = alListIteratorNext(alContextList);
+ }
+ }
+
+ alListReleaseLock(alContextList);
+ assert(!device->InUse);
+ }
+
+ device->AlcApi.alcCloseDevice(device->DllDevice);
+ FreeLibrary(device->Dll);
+ free(device);
+
+ return ALC_TRUE;
+}
+
+
+
+
+//*****************************************************************************
+// alcCreateContext
+//*****************************************************************************
+ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice* device, const ALint* attrList)
+{
+#ifdef _LOGCALLS
+ LOG("alcCreateContext device %p ", device);
+ if (attrList)
+ {
+ unsigned long ulIndex = 0;
+ while ((ulIndex < 16) && (attrList[ulIndex]))
+ {
+ switch(attrList[ulIndex])
+ {
+ case ALC_FREQUENCY:
+ LOG("ALC_FREQUENCY %d ", attrList[ulIndex + 1]);
+ break;
+
+ case ALC_REFRESH:
+ LOG("ALC_REFRESH %d ", attrList[ulIndex + 1]);
+ break;
+
+ case ALC_SYNC:
+ LOG("ALC_SYNC %d ", attrList[ulIndex + 1]);
+ break;
+
+ case ALC_MONO_SOURCES:
+ LOG("ALC_MONO_SOURCES %d ", attrList[ulIndex + 1]);
+ break;
+
+ case ALC_STEREO_SOURCES:
+ LOG("ALC_STEREO_SOURCES %d ", attrList[ulIndex + 1]);
+ break;
+
+ case 0x20003/*ALC_MAX_AUXILIARY_SENDS*/:
+ LOG("ALC_MAX_AUXILIARY_SENDS %d", attrList[ulIndex + 1]);
+ break;
+ }
+ ulIndex += 2;
+ }
+ }
+ LOG("\n");
+#endif
+
+ ALCcontext* context = 0;
+
+ if(!device)
+ {
+ LastError = ALC_INVALID_DEVICE;
+ return 0;
+ }
+
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcCreateContext(g_CaptureDevice->CaptureDevice, attrList);
+
+ //
+ // Allocate the context.
+ //
+ context = (ALCcontext*)malloc(sizeof(ALCcontext));
+ if(!context)
+ {
+ return 0;
+ }
+
+ memset(context, 0, sizeof(ALCcontext));
+ context->Device = device;
+ context->Suspended = FALSE;
+ context->LastError = ALC_NO_ERROR;
+ InitializeCriticalSection(&context->Lock);
+
+ //
+ // We don't fill out the AL functions in case they are context specific.
+ //
+
+ context->DllContext = device->AlcApi.alcCreateContext(device->DllDevice, attrList);
+ if(!context->DllContext)
+ {
+ DeleteCriticalSection(&context->Lock);
+ free(context);
+ context = 0;
+ return 0;
+ }
+
+ device->InUse++;
+
+ //
+ // Add it to the context list.
+ //
+ alListInitializeEntry(&context->ListEntry, context);
+ alListAcquireLock(alContextList);
+ alListAddEntry(alContextList, &context->ListEntry);
+ alListReleaseLock(alContextList);
+ return context;
+}
+
+
+
+
+//*****************************************************************************
+// alcDestroyContext
+//*****************************************************************************
+ALCAPI ALvoid ALCAPIENTRY alcDestroyContext(ALCcontext* context)
+{
+#ifdef _LOGCALLS
+ LOG("alcDestroyContext context %p\n", context);
+#endif
+ ALCcontext* listData = 0;
+
+ if(!context)
+ {
+ return;
+ }
+
+ //
+ // Remove the entry from the context list.
+ //
+ alListAcquireLock(alContextList);
+ listData = (ALCcontext*)alListRemoveEntry(alContextList, &context->ListEntry);
+ if(!listData)
+ {
+ alListReleaseLock(alContextList);
+ return;
+ }
+
+ if(context == alCurrentContext)
+ {
+ alCurrentContext = 0;
+ }
+
+ EnterCriticalSection(&context->Lock);
+ alListReleaseLock(alContextList);
+
+ context->Device->InUse--;
+
+ // Clean up the context.
+ if(context->DllContext)
+ {
+ context->Device->AlcApi.alcDestroyContext(context->DllContext);
+ }
+
+ LeaveCriticalSection(&context->Lock);
+ DeleteCriticalSection(&context->Lock);
+ free(context);
+}
+
+
+
+
+//*****************************************************************************
+// alcGetContextsDevice
+//*****************************************************************************
+ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext* context)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetContextsDevice context %p\n", context);
+#endif
+ ALCdevice* ALCdevice = 0;
+
+ alListAcquireLock(alContextList);
+ if(alListMatchData(alContextList, context))
+ {
+ ALCdevice = context->Device;
+ }
+
+ alListReleaseLock(alContextList);
+
+ return ALCdevice;
+}
+
+
+
+
+//*****************************************************************************
+// alcGetCurrentContext
+//*****************************************************************************
+ALCAPI ALCcontext* ALCAPIENTRY alcGetCurrentContext(ALvoid)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetCurrentContext\n");
+#endif
+ return (ALCcontext *)alCurrentContext;
+}
+
+
+
+
+//*****************************************************************************
+// alcGetEnumValue
+//*****************************************************************************
+ALCAPI ALenum ALCAPIENTRY alcGetEnumValue(ALCdevice* device, const ALCchar* ename)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetEnumValue device %p enum name '%s'\n", device, ename ? ename : "<NULL>");
+#endif
+ //
+ // Always return the router version of the ALC enum if it exists.
+ //
+ ALsizei i = 0;
+ while(alcEnums[i].ename && strcmp((char*)alcEnums[i].ename, (char*)ename))
+ {
+ i++;
+ }
+
+ if(alcEnums[i].ename)
+ {
+ return alcEnums[i].value;
+ }
+
+ if(device)
+ {
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcGetEnumValue(g_CaptureDevice->CaptureDevice, ename);
+
+ return device->AlcApi.alcGetEnumValue(device->DllDevice, ename);
+ }
+
+ LastError = ALC_INVALID_ENUM;
+ return 0;
+}
+
+
+
+
+//*****************************************************************************
+// alcGetError
+//*****************************************************************************
+ALCAPI ALenum ALCAPIENTRY alcGetError(ALCdevice* device)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetError device %p\n", device);
+#endif
+ ALenum errorCode = ALC_NO_ERROR;
+
+ // Try to get a valid device.
+ if(!device)
+ {
+ if (g_CaptureDevice == device)
+ return
+ errorCode = LastError;
+ LastError = ALC_NO_ERROR;
+ return errorCode;
+ }
+
+ //
+ // Check if its a 3rd party device.
+ //
+ if (device == g_CaptureDevice)
+ errorCode = g_CaptureDevice->AlcApi.alcGetError(g_CaptureDevice->CaptureDevice);
+ else
+ errorCode = device->AlcApi.alcGetError(device->DllDevice);
+
+ return errorCode;
+}
+
+
+
+
+//*****************************************************************************
+// alcGetIntegerv
+//*****************************************************************************
+ALCAPI ALvoid ALCAPIENTRY alcGetIntegerv(ALCdevice* device, ALenum param, ALsizei size, ALint* data)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetIntegerv device %p enum ", device);
+ switch (param)
+ {
+ case ALC_ATTRIBUTES_SIZE:
+ LOG("ALC_ATTRIBUTES_SIZE\n");
+ break;
+ case ALC_ALL_ATTRIBUTES:
+ LOG("ALC_ALL_ATTRIBUTES\n");
+ break;
+ case ALC_MAJOR_VERSION:
+ LOG("ALC_MAJOR_VERSION\n");
+ break;
+ case ALC_MINOR_VERSION:
+ LOG("ALC_MINOR_VERSION\n");
+ break;
+ case ALC_CAPTURE_SAMPLES:
+ LOG("ALC_CAPTURE_SAMPLES\n");
+ break;
+ case ALC_FREQUENCY:
+ LOG("ALC_FREQUENCY\n");
+ break;
+ case ALC_REFRESH:
+ LOG("ALC_REFRESH\n");
+ break;
+ case ALC_SYNC:
+ LOG("ALC_SYNC\n");
+ break;
+ case ALC_MONO_SOURCES:
+ LOG("ALC_MONO_SOURCES\n");
+ break;
+ case ALC_STEREO_SOURCES:
+ LOG("ALC_STEREO_SOURCES\n");
+ break;
+ case 0x20003: // ALC_MAX_AUXILIARY_SENDS
+ LOG("ALC_MAX_AUXILIARY_SENDS\n");
+ break;
+ case 0x20001: // ALC_EFX_MAJOR_VERSION
+ LOG("ALC_EFX_MAJOR_VERSION\n");
+ break;
+ case 0x20002: // ALC_EFX_MINOR_VERSION
+ LOG("ALC_EFX_MINOR_VERSION\n");
+ break;
+ default:
+ LOG("<Unknown>\n");
+ break;
+ }
+#endif
+
+ if(device)
+ {
+ if (device == g_CaptureDevice)
+ {
+ g_CaptureDevice->AlcApi.alcGetIntegerv(g_CaptureDevice->CaptureDevice, param, size, data);
+ return;
+ }
+
+ device->AlcApi.alcGetIntegerv(device->DllDevice, param, size, data);
+ return;
+ }
+
+ switch(param)
+ {
+ case ALC_MAJOR_VERSION:
+ {
+ if((size < sizeof(ALint)) || (data == 0))
+ {
+ LastError = ALC_INVALID;
+ return;
+ }
+
+ *data = alcMajorVersion;
+ }
+ break;
+
+ case ALC_MINOR_VERSION:
+ {
+ if((size < sizeof(ALint)) || (data == 0))
+ {
+ LastError = ALC_INVALID;
+ return;
+ }
+
+ *data = alcMinorVersion;
+ }
+ break;
+
+ default:
+ {
+ device->LastError = ALC_INVALID_ENUM;
+ }
+ break;
+ }
+}
+
+
+
+
+//*****************************************************************************
+// alcGetProcAddress
+//*****************************************************************************
+ALCAPI ALvoid* ALCAPIENTRY alcGetProcAddress(ALCdevice* device, const ALCchar* fname)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetProcAddress device %p function name '%s'\n", device, fname ? fname : "<NULL>");
+#endif
+
+ //
+ // Always return the router version of the ALC function if it exists.
+ //
+ ALsizei i = 0;
+ while(alcFunctions[i].fname && strcmp((char*)alcFunctions[i].fname, (char*)fname))
+ {
+ i++;
+ }
+
+ if(alcFunctions[i].fname)
+ {
+ return alcFunctions[i].address;
+ }
+
+ if(device)
+ {
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcGetProcAddress(g_CaptureDevice->CaptureDevice, fname);
+
+ return device->AlcApi.alcGetProcAddress(device->DllDevice, fname);
+ }
+
+ LastError = ALC_INVALID_ENUM;
+ return 0;
+}
+
+
+
+
+//*****************************************************************************
+// alcIsExtensionPresent
+//*****************************************************************************
+ALCAPI ALboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice* device, const ALCchar* ename)
+{
+#ifdef _LOGCALLS
+ LOG("alcIsExtensionPresent device %p extension name '%s'\n", device, ename ? ename : "<NULL>");
+#endif
+ //
+ // Check if its a router supported extension first as its a good idea to have
+ // ALC calls go through the router if possible.
+ //
+ ALsizei i = 0;
+ while(alcExtensions[i].ename && _stricmp((char*)alcExtensions[i].ename, (char*)ename))
+ {
+ i++;
+ }
+
+ if(alcExtensions[i].ename)
+ {
+ return ALC_TRUE;
+ }
+
+ //
+ // Check the device passed in to see if the extension is supported.
+ //
+ if(device)
+ {
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcIsExtensionPresent(g_CaptureDevice->CaptureDevice, ename);
+
+ return device->AlcApi.alcIsExtensionPresent(device->DllDevice, ename);
+ }
+
+ LastError = ALC_INVALID_ENUM;
+ return ALC_FALSE;
+}
+
+
+
+
+//*****************************************************************************
+// alcMakeContextCurrent
+//*****************************************************************************
+ALCAPI ALboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext* context)
+{
+#ifdef _LOGCALLS
+ LOG("alcMakeContextCurrent context %p\n", context);
+#endif
+ ALboolean contextSwitched = AL_TRUE;
+
+ //
+ // Context must be a valid context or 0
+ //
+ alListAcquireLock(alContextList);
+ if(!alListMatchData(alContextList, context) && context != 0)
+ {
+ alListReleaseLock(alContextList);
+ return ALC_FALSE;
+ }
+
+ //
+ // Try the new context.
+ //
+ if(context)
+ {
+ contextSwitched = context->Device->AlcApi.alcMakeContextCurrent(context->DllContext);
+
+ //
+ // If this is the first time the context has been made the current context, fill in the context
+ // function pointers.
+ //
+ if(contextSwitched && !context->AlApi.alGetProcAddress)
+ {
+ //
+ // Don't fill out the functions here in case they are context specific pointers in the device.
+ //
+ if(!FillOutAlFunctions(context))
+ {
+ LastError = ALC_INVALID_CONTEXT;
+ contextSwitched = AL_FALSE;
+
+ //
+ // Something went wrong, restore the old context.
+ //
+ if(alCurrentContext)
+ {
+ alCurrentContext->Device->AlcApi.alcMakeContextCurrent(alCurrentContext->DllContext);
+ }
+
+ else
+ {
+ alCurrentContext->Device->AlcApi.alcMakeContextCurrent(0);
+ }
+ }
+ }
+ } else {
+ if ((alCurrentContext) && (alCurrentContext->Device) && (alCurrentContext->Device->AlcApi.alcMakeContextCurrent)) {
+ contextSwitched = alCurrentContext->Device->AlcApi.alcMakeContextCurrent(0);
+ }
+ }
+
+ //
+ // Set the context states if the switch was successful.
+ //
+ if(contextSwitched)
+ {
+ alCurrentContext = context;
+ }
+
+ alListReleaseLock(alContextList);
+ return contextSwitched;
+}
+
+
+
+
+//*****************************************************************************
+// alcOpenDevice
+//*****************************************************************************
+ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar* deviceName)
+{
+#ifdef _LOGCALLS
+ LOG("alcOpenDevice device name '%s'\n", deviceName ? deviceName : "<NULL>");
+#endif
+ HINSTANCE dll = 0;
+ ALCdevice* device = 0;
+ const ALchar *pszDeviceName = NULL;
+
+ BuildDeviceList();
+
+ if (g_pDeviceList)
+ {
+ if ((!deviceName) || (strlen(deviceName)==0) || (strcmp(deviceName, "DirectSound3D")==0))
+ pszDeviceName = pszDefaultDeviceSpecifier;
+ else
+ pszDeviceName = deviceName;
+
+ // Search for device in Playback Device List
+ dll = LoadDevicesDLL(g_pDeviceList, pszDeviceName);
+
+ if (!dll)
+ {
+ // If NOT found, and the requested name is one of these ...
+ // "Generic Hardware" (no longer available on Windows Vista)
+ // "DirectSound" (legacy name for OpenAL Software mixer device)
+ // "MMSYSTEM" (legacy name for OpenAL Software mixer using MMSYSTEM instead of DirectSound)
+ // try to open the "Generic Software" device instead
+ if ((strcmp(pszDeviceName, "Generic Hardware") == 0) ||
+ (strcmp(pszDeviceName, "DirectSound") == 0) ||
+ (strcmp(pszDeviceName, "MMSYSTEM") == 0))
+ {
+ dll = LoadDevicesDLL(g_pDeviceList, "Generic Software");
+ }
+ }
+
+ if (!dll)
+ dll = LoadDevicesDLL(g_pAllDevicesList, pszDeviceName);
+
+ if (dll)
+ {
+ device = (ALCdevice*)malloc(sizeof(ALCdevice));
+ if (device)
+ {
+ memset(device, 0, sizeof(ALCdevice));
+ device->LastError = ALC_NO_ERROR;
+ device->InUse = 0;
+ device->Dll = dll;
+ if (FillOutAlcFunctions(device))
+ device->DllDevice = device->AlcApi.alcOpenDevice(pszDeviceName);
+
+ if (!device->DllDevice)
+ {
+ FreeLibrary(dll);
+ free(device);
+ device = 0;
+ }
+ }
+ }
+ }
+
+ if (!device)
+ LastError = ALC_INVALID_DEVICE;
+
+ return device;
+}
+
+
+
+
+//*****************************************************************************
+// alcProcessContext
+//*****************************************************************************
+ALCAPI ALvoid ALCAPIENTRY alcProcessContext(ALCcontext* context)
+{
+#ifdef _LOGCALLS
+ LOG("alcProcessContext context %p\n", context);
+#endif
+ alListAcquireLock(alContextList);
+ if(!context && !alCurrentContext)
+ {
+ alListReleaseLock(alContextList);
+ return;
+ }
+
+ if(!context)
+ {
+ context = alCurrentContext;
+ }
+
+ EnterCriticalSection(&context->Lock);
+ alListReleaseLock(alContextList);
+
+ if(context->DllContext)
+ {
+ context->Device->AlcApi.alcProcessContext(context->DllContext);
+ }
+
+ context->Suspended = FALSE;
+
+ LeaveCriticalSection(&context->Lock);
+ return;
+}
+
+
+
+
+//*****************************************************************************
+// alcSuspendContext
+//*****************************************************************************
+ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext* context)
+{
+#ifdef _LOGCALLS
+ LOG("alcSuspendContext context %p\n", context);
+#endif
+ alListAcquireLock(alContextList);
+ if(!context && !alCurrentContext)
+ {
+ alListReleaseLock(alContextList);
+ return;
+ }
+
+ if(!context)
+ {
+ context = (ALCcontext *)alCurrentContext;
+ }
+
+ EnterCriticalSection(&context->Lock);
+ alListReleaseLock(alContextList);
+
+ context->Suspended = TRUE;
+
+ if(context->DllContext)
+ {
+ context->Device->AlcApi.alcSuspendContext(context->DllContext);
+ }
+
+ LeaveCriticalSection(&context->Lock);
+ return;
+}
+
+
+
+
+//*****************************************************************************
+// alcGetString
+//*****************************************************************************
+ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice* device, ALenum param)
+{
+#ifdef _LOGCALLS
+ LOG("alcGetString device %p enum ", device);
+ switch (param)
+ {
+ case ALC_NO_ERROR:
+ LOG("ALC_NO_ERROR\n");
+ break;
+ case ALC_INVALID_ENUM:
+ LOG("ALC_INVALID_ENUM\n");
+ break;
+ case ALC_INVALID_VALUE:
+ LOG("ALC_INVALID_VALUE\n");
+ break;
+ case ALC_INVALID_DEVICE:
+ LOG("ALC_INVALID_DEVICE\n");
+ break;
+ case ALC_INVALID_CONTEXT:
+ LOG("ALC_INVALID_CONTEXT\n");
+ break;
+ case ALC_DEFAULT_DEVICE_SPECIFIER:
+ LOG("ALC_DEFAULT_DEVICE_SPECIFIER\n");
+ break;
+ case ALC_DEVICE_SPECIFIER:
+ LOG("ALC_DEVICE_SPECIFIER\n");
+ break;
+ case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
+ LOG("ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER\n");
+ break;
+ case ALC_CAPTURE_DEVICE_SPECIFIER:
+ LOG("ALC_CAPTURE_DEVICE_SPECIFIER\n");
+ break;
+ case ALC_ALL_DEVICES_SPECIFIER:
+ LOG("ALC_ALL_DEVICES_SPECIFIER\n");
+ break;
+ case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
+ LOG("ALC_DEFAULT_ALL_DEVICES_SPECIFIER\n");
+ break;
+ case ALC_EXTENSIONS:
+ LOG("ALC_EXTENSIONS\n");
+ break;
+ default:
+ LOG("<Unknown>\n");
+ break;
+ }
+#endif
+
+ const ALCchar* value = 0;
+
+ if ((param != ALC_DEFAULT_DEVICE_SPECIFIER) && (param != ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) {
+ if(device)
+ {
+ if (device == g_CaptureDevice)
+ return g_CaptureDevice->AlcApi.alcGetString(g_CaptureDevice->CaptureDevice, param);
+
+ return device->AlcApi.alcGetString(device->DllDevice, param);
+ }
+ }
+
+ switch(param)
+ {
+ case ALC_NO_ERROR:
+ {
+ value = alcNoError;
+ }
+ break;
+
+ case ALC_INVALID_ENUM:
+ {
+ value = alcErrInvalidEnum;
+ }
+ break;
+
+ case ALC_INVALID_VALUE:
+ {
+ value = alcErrInvalidValue;
+ }
+ break;
+
+ case ALC_INVALID_DEVICE:
+ {
+ value = alcErrInvalidDevice;
+ }
+ break;
+
+ case ALC_INVALID_CONTEXT:
+ {
+ value = alcErrInvalidContext;
+ }
+ break;
+
+ case ALC_DEFAULT_DEVICE_SPECIFIER:
+ BuildDeviceList();
+ if (pszDefaultDeviceSpecifier)
+ value = pszDefaultDeviceSpecifier;
+ else
+ value = szEmptyString;
+ break;
+
+ case ALC_DEVICE_SPECIFIER:
+ BuildDeviceList();
+ if (pszDeviceSpecifierList)
+ value = pszDeviceSpecifierList;
+ else
+ value = szEmptyString;
+ break;
+
+ case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
+ BuildDeviceList();
+ if (pszDefaultCaptureDeviceSpecifier)
+ value = pszDefaultCaptureDeviceSpecifier;
+ else
+ value = szEmptyString;
+ break;
+
+ case ALC_CAPTURE_DEVICE_SPECIFIER:
+ BuildDeviceList();
+ if (pszCaptureDeviceSpecifierList)
+ value = pszCaptureDeviceSpecifierList;
+ else
+ value = szEmptyString;
+ break;
+
+ case ALC_ALL_DEVICES_SPECIFIER:
+ BuildDeviceList();
+ if (pszAllDevicesSpecifierList)
+ value = pszAllDevicesSpecifierList;
+ else
+ value = szEmptyString;
+ break;
+
+ case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
+ BuildDeviceList();
+ if (pszDefaultAllDevicesSpecifier)
+ value = pszDefaultAllDevicesSpecifier;
+ else
+ value = szEmptyString;
+ break;
+
+ default:
+ LastError = ALC_INVALID_ENUM;
+ break;
+ }
+
+ return value;
+}
+
+
+
+
+//*****************************************************************************
+// alcCaptureOpenDevice
+//*****************************************************************************
+ALCAPI ALCdevice * ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei buffersize)
+{
+#ifdef _LOGCALLS
+ LOG("alcCaptureOpenDevice device name '%s' frequency %d format %d buffersize %d\n", deviceName ? deviceName : "<NULL>", frequency, format, buffersize);
+#endif
+ const ALchar *pszDeviceName = NULL;
+
+ BuildDeviceList();
+
+ if (!g_pCaptureDeviceList)
+ return NULL;
+
+ if (!g_CaptureDevice) {
+ g_CaptureDevice = (ALCdevice*)malloc(sizeof(ALCdevice));
+
+ if (g_CaptureDevice)
+ {
+ // clear
+ memset(g_CaptureDevice, 0, sizeof(ALCdevice));
+
+ // make sure we have a device name
+ if ((!deviceName) || (strlen(deviceName) == 0))
+ pszDeviceName = pszDefaultCaptureDeviceSpecifier;
+ else
+ pszDeviceName = deviceName;
+
+ g_CaptureDevice->Dll = LoadDevicesDLL(g_pCaptureDeviceList, pszDeviceName);
+
+ if (g_CaptureDevice->Dll) {
+ if(FillOutAlcFunctions(g_CaptureDevice)) {
+ if (g_CaptureDevice->AlcApi.alcCaptureOpenDevice) {
+ g_CaptureDevice->CaptureDevice = g_CaptureDevice->AlcApi.alcCaptureOpenDevice(pszDeviceName, frequency, format, buffersize);
+ g_CaptureDevice->LastError = ALC_NO_ERROR;
+ g_CaptureDevice->InUse = 0;
+ } else {
+ g_CaptureDevice->LastError = ALC_INVALID_DEVICE;
+ }
+ }
+ }
+ }
+ } else {
+ // already open
+ g_CaptureDevice->LastError = ALC_INVALID_VALUE;
+ }
+
+ if (g_CaptureDevice != NULL) {
+ if (g_CaptureDevice->CaptureDevice) {
+ return g_CaptureDevice;
+ } else {
+ free(g_CaptureDevice);
+ g_CaptureDevice = NULL;
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+
+
+
+//*****************************************************************************
+// alcCaptureCloseDevice
+//*****************************************************************************
+ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *device)
+{
+#ifdef _LOGCALLS
+ LOG("alcCaptureCloseDevice device %p\n", device);
+#endif
+ ALCboolean bReturn = ALC_FALSE;
+
+ if (device == g_CaptureDevice)
+ {
+ if (g_CaptureDevice != NULL) {
+ if (g_CaptureDevice->AlcApi.alcCaptureCloseDevice) {
+ bReturn = g_CaptureDevice->AlcApi.alcCaptureCloseDevice(g_CaptureDevice->CaptureDevice);
+ delete g_CaptureDevice;
+ g_CaptureDevice = NULL;
+ } else {
+ g_CaptureDevice->LastError = ALC_INVALID_DEVICE;
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+
+
+
+//*****************************************************************************
+// alcCaptureStart
+//*****************************************************************************
+ALCAPI ALCvoid ALCAPIENTRY alcCaptureStart(ALCdevice *device)
+{
+#ifdef _LOGCALLS
+ LOG("alcCaptureStart device %p\n", device);
+#endif
+ if (device == g_CaptureDevice)
+ {
+ if (g_CaptureDevice != NULL) {
+ if (g_CaptureDevice->AlcApi.alcCaptureStart) {
+ g_CaptureDevice->AlcApi.alcCaptureStart(g_CaptureDevice->CaptureDevice);
+ } else {
+ g_CaptureDevice->LastError = ALC_INVALID_DEVICE;
+ }
+ }
+ }
+
+ return;
+}
+
+
+
+
+//*****************************************************************************
+// alcCaptureStop
+//*****************************************************************************
+ALCAPI ALCvoid ALCAPIENTRY alcCaptureStop(ALCdevice *device)
+{
+#ifdef _LOGCALLS
+ LOG("alcCaptureStop device %p\n", device);
+#endif
+ if (device == g_CaptureDevice)
+ {
+ if (g_CaptureDevice != NULL) {
+ if (g_CaptureDevice->AlcApi.alcCaptureStop) {
+ g_CaptureDevice->AlcApi.alcCaptureStop(g_CaptureDevice->CaptureDevice);
+ } else {
+ g_CaptureDevice->LastError = ALC_INVALID_DEVICE;
+ }
+ }
+ }
+
+ return;
+}
+
+
+
+
+//*****************************************************************************
+// alcCaptureSamples
+//*****************************************************************************
+ALCAPI ALCvoid ALCAPIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
+{
+#ifdef _LOGCALLS
+ LOG("alcCaptureSamples device %p buffer %p samples %d\n", device, buffer, samples);
+#endif
+ if (device == g_CaptureDevice)
+ {
+ if (g_CaptureDevice != NULL) {
+ if (g_CaptureDevice->AlcApi.alcCaptureSamples) {
+ g_CaptureDevice->AlcApi.alcCaptureSamples(g_CaptureDevice->CaptureDevice, buffer, samples);
+ } else {
+ g_CaptureDevice->LastError = ALC_INVALID_DEVICE;
+ }
+ }
+ }
+
+ return;
+}
+
+#ifdef _LOGCALLS
+void OutputMessage(const char *szDebug,...)
+{
+ static FILE *pFile = NULL;
+ SYSTEMTIME sysTime;
+ va_list args;
+
+ va_start(args, szDebug);
+
+ if (!pFile)
+ {
+ pFile = fopen(LOGFILENAME, "w");
+ GetLocalTime(&sysTime);
+ fprintf(pFile, "OpenAL Router\n\nLog Time : %d/%d/%d at %d:%s%d:%s%d\n\n", sysTime.wDay, sysTime.wMonth, sysTime.wYear,
+ sysTime.wHour, (sysTime.wMinute < 10) ? "0" : "", sysTime.wMinute, (sysTime.wSecond < 10) ? "0" : "", sysTime.wSecond);
+ }
+
+ vfprintf(pFile, szDebug, args);
+ fflush(pFile);
+
+ va_end(args);
+}
+#endif \ No newline at end of file
diff --git a/Router/resource.h b/Router/resource.h
new file mode 100644
index 00000000..bdff6160
--- /dev/null
+++ b/Router/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by openal32.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/RouterTest/main.cpp b/RouterTest/main.cpp
new file mode 100644
index 00000000..961c3ecb
--- /dev/null
+++ b/RouterTest/main.cpp
@@ -0,0 +1,647 @@
+#include <al.h>
+#include <alc.h>
+#include <stdio.h>
+#include <conio.h>
+#include <string.h>
+#include <windows.h>
+#include <mmsystem.h>
+
+int main(int argc, char* argv[])
+{
+ const ALchar *szNames = NULL;
+ long lErrorCount = 0;
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Enumerate the playback devices
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING ALC_ENUMERATION_EXT EXTENSION\n\n");
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
+ {
+ printf("ALC_ENUMERATION_EXT Device List:-\n\n");
+
+ szNames = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+ if (strlen(szNames) == 0)
+ printf("NO DEVICES FOUND\n");
+ else
+ {
+ while (szNames && *szNames)
+ {
+ printf("%s ", szNames);
+ // Try opening each device
+ ALCdevice *pDevice = alcOpenDevice(szNames);
+ if (pDevice)
+ {
+ printf("- Opened Successfully\n");
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ printf("- FAILED to open\n");
+ lErrorCount++;
+ }
+ szNames += (strlen(szNames) + 1);
+ }
+ }
+ }
+ else
+ {
+ printf("!!!ERROR!!! : ALC_ENUMERATION_EXT NOT FOUND!\n");
+ lErrorCount++;
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Get Default Playback Device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING GET DEFAULT PLAYBACK DEVICE\n\n");
+ szNames = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+ if (szNames && strlen(szNames))
+ {
+ printf("\nDEFAULT DEVICE is %s\n", szNames);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("\n!!!ERROR!!! DEFAULT DEVICE NOT FOUND!\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("\nDEFAULT DEVICE NOT FOUND!\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Enumerate all the capture devices
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING CAPTURE ENUMERATION EXTENSION\n\n");
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
+ {
+ printf("ALC_ENUMERATION_EXT Capture Device List:-\n\n");
+
+ szNames = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
+ if (strlen(szNames) == 0)
+ printf("NO DEVICES FOUND\n");
+ else
+ {
+ while (szNames && *szNames)
+ {
+ printf("%s ", szNames);
+ // Try opening each device
+ ALCdevice *pDevice = alcCaptureOpenDevice(szNames, 11025, AL_FORMAT_STEREO16, 8192);
+ if (pDevice)
+ {
+ printf("- Opened Successfully\n");
+ alcCaptureCloseDevice(pDevice);
+ }
+ else
+ {
+ printf("- FAILED to open\n");
+ lErrorCount++;
+ }
+ szNames += (strlen(szNames) + 1);
+ }
+ }
+ }
+ else
+ {
+ printf("!!!ERROR!!! : ALC_ENUMERATION_EXT NOT FOUND!\n");
+ lErrorCount++;
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Get Default Capture Device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING DEFAULT CAPTURE DEVICE\n\n");
+ szNames = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
+ if (szNames && strlen(szNames))
+ {
+ printf("\nDEFAULT CAPTURE DEVICE IS %s\n", szNames);
+ }
+ else
+ {
+ if (waveInGetNumDevs())
+ {
+ printf("\n!!!ERROR!!! DEFAULT CAPTURE DEVICE NOT FOUND!\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("\nDEFAULT CAPTURE DEVICE NOT FOUND!\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Enumerate *all* the playback devices
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING PLAYBACK ENUMERATE ALL EXTENSION\n\n");
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
+ {
+ printf("ALC_ENUMERATE_ALL_EXT DEVICE LIST:-\n\n");
+
+ szNames = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
+ if (strlen(szNames) == 0)
+ printf("NO DEVICES FOUND\n");
+ else
+ {
+ while (szNames && *szNames)
+ {
+ printf("%s ", szNames);
+
+ // Try opening each device
+ ALCdevice *pDevice = alcOpenDevice(szNames);
+ if (pDevice)
+ {
+ printf("- Opened Successfully\n");
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ printf("- FAILED to open\n");
+ lErrorCount++;
+ }
+
+ szNames += (strlen(szNames) + 1);
+ }
+ }
+ }
+ else
+ {
+ printf("!!!ERROR!!! : ALC_ENUMERATE_ALL_EXT NOT FOUND!\n");
+ lErrorCount++;
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Get Default *All* Playback Device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING DEFAULT ALL PLAYBACK DEVICE\n\n");
+ szNames = alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
+ if (szNames && strlen(szNames))
+ {
+ printf("\nDEFAULT ALL DEVICES IS %s\n", szNames);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("\n!!!ERROR!!! DEFAULT ALL DEVICE NOT FOUND!\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("\nDEFAULT ALL DEVICES NOT FOUND!\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open 'Generic Hardware' device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING 'Generic Hardware' DEVICE\n\n");
+ ALCdevice *pDevice = alcOpenDevice("Generic Hardware");
+ if (pDevice)
+ {
+ printf("OPENED 'Generic Hardware' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN 'Generic Hardware' DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'Generic Hardware' DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open 'Generic Software' device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING 'Generic Software' DEVICE\n\n");
+ pDevice = alcOpenDevice("Generic Software");
+ if (pDevice)
+ {
+ printf("OPENED 'Generic Software' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN 'Generic Software' DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'Generic Software' DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open legacy 'DirectSound3D' device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING LEGACY 'DirectSound3D' DEVICE\n\n");
+ pDevice = alcOpenDevice("DirectSound3D");
+ if (pDevice)
+ {
+ printf("OPENED 'DirectSound3D' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN 'DirectSound3D' DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'DirectSound3D' DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open legacy 'DirectSound' device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING LEGACY 'DirectSound' DEVICE\n\n");
+ pDevice = alcOpenDevice("DirectSound");
+ if (pDevice)
+ {
+ printf("OPENED 'DirectSound' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN 'DirectSound' DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'DirectSound' DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open legacy 'MMSYSTEM' device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING LEGACY 'MMSYSTEM' DEVICE\n\n");
+ pDevice = alcOpenDevice("MMSYSTEM");
+ if (pDevice)
+ {
+ printf("OPENED 'MMSYSTEM' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN 'MMSYSTEM' DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'MMSYSTEM' DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open NULL device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING NULL DEVICE\n\n");
+ pDevice = alcOpenDevice(NULL);
+ if (pDevice)
+ {
+ printf("OPENED NULL DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN NULL DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN NULL DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open "" device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING EMPTY DEVICE\n\n");
+ pDevice = alcOpenDevice("");
+ if (pDevice)
+ {
+ printf("OPENED \"\" DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveOutGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN EMPTY DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN EMPTY DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open "A Random Name" device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING 'A Random Name' DEVICE\n\n");
+ pDevice = alcOpenDevice("A Random Name");
+ if (pDevice)
+ {
+ printf("!!!ERROR!!! : OPENED 'A Random Name' DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
+ lErrorCount++;
+ alcCloseDevice(pDevice);
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'A Random Name' DEVICE\n");
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open NULL Capture device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING NULL CAPTURE DEVICE\n\n");
+ pDevice = alcCaptureOpenDevice(NULL, 22500, AL_FORMAT_MONO16, 4096);
+ if (pDevice)
+ {
+ printf("OPENED NULL CAPTURE DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_CAPTURE_DEVICE_SPECIFIER));
+ alcCaptureCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveInGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN NULL CAPTURE DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN NULL CAPTURE DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open "" capture device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING EMPTY CAPTURE DEVICE\n\n");
+ pDevice = alcCaptureOpenDevice("", 22500, AL_FORMAT_MONO16, 4096);
+ if (pDevice)
+ {
+ printf("OPENED \"\" CAPTURE DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_CAPTURE_DEVICE_SPECIFIER));
+ alcCaptureCloseDevice(pDevice);
+ }
+ else
+ {
+ if (waveInGetNumDevs())
+ {
+ printf("!!!ERROR!!! : FAILED TO OPEN EMPTY CAPTURE DEVICE\n");
+ lErrorCount++;
+ }
+ else
+ {
+ printf("FAILED TO OPEN EMPTY CAPTURE DEVICE\n");
+ }
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ // TEST : Open "A Random Name" capture device
+ //
+ printf("--------------------------------------\n");
+ printf("TESTING 'A Random Name' CAPTURE DEVICE\n\n");
+ pDevice = alcCaptureOpenDevice("A Random Name", 22500, AL_FORMAT_MONO16, 4096);
+ if (pDevice)
+ {
+ printf("!!!ERROR!!! : OPENED 'A Random Name' CAPTURE DEVICE ... GOT %s\n", alcGetString(pDevice, ALC_CAPTURE_DEVICE_SPECIFIER));
+ lErrorCount++;
+ alcCaptureCloseDevice(pDevice);
+ }
+ else
+ {
+ printf("FAILED TO OPEN 'A Random Name' CAPTURE DEVICE\n");
+ }
+ printf("--------------------------------------\n\n");
+ ///////////////////////////////////////////////////////////////////
+
+ printf("\nFOUND %d ERRORS\n", lErrorCount);
+
+ printf("\nPress a key to quit\n");
+ char ch = _getch();
+
+ return 0;
+}
+
+
+/*
+ALboolean InitOpenAL(ALCdevice **ppDevice, ALCcontext **ppContext)
+{
+ ALchar szDeviceNames[10][1024];
+ ALchar *szNames;
+ ALint lNumDevices;
+ ALint lLoop;
+ ALint lLength;
+ ALbyte ch;
+ ALboolean bInit;
+
+ bInit = AL_FALSE;
+ memset(szDeviceNames, 0, sizeof(ALchar) * 10 * 1024);
+ lNumDevices = 0;
+
+
+
+ if (!szNames)
+ {
+ szNames = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+ if (szNames && *szNames && (strlen(szNames) < 1024))
+ strcpy(szDeviceNames[lNumDevices++], szNames);
+ }
+
+ for (lLoop = 0; lLoop < lNumDevices; lLoop++)
+ printf("Press %d for '%s' Device\n", lLoop+1, szDeviceNames[lLoop]);
+ printf("Press Q to quit\n");
+
+ do
+ {
+ ch = _getch();
+ if (ch == 'q' || ch == 'Q')
+ exit(0);
+ else if ((ch >= '1') && (ch < ('1' + lNumDevices)))
+ break;
+ } while (1);
+
+ *ppDevice = alcOpenDevice(szDeviceNames[ch - '1']);
+ if (*ppDevice)
+ {
+ *ppContext = alcCreateContext(*ppDevice,NULL);
+ if (*ppContext)
+ {
+ alcGetError(*ppDevice);
+ alcMakeContextCurrent(*ppContext);
+ if (alcGetError(*ppDevice) == ALC_NO_ERROR)
+ bInit = AL_TRUE;
+ }
+ else
+ {
+ alcCloseDevice(*ppDevice);
+ }
+ }
+
+ return bInit;
+}
+
+
+ALboolean InitOpenALEx(ALCdevice **ppDevice, ALCcontext **ppContext)
+{
+ ALchar szDeviceNames[32][1024];
+ const ALchar *szNames;
+ const ALchar *szDefaultName = NULL;
+ const ALchar *szDefaultAllName = NULL;
+ ALint lNumDevices = 0;
+ ALint lLoop;
+ ALint lLength;
+ ALbyte ch;
+ ALboolean bInit;
+
+ bInit = AL_FALSE;
+ memset(szDeviceNames, 0, sizeof(ALchar) * 32 * 1024);
+
+ // Get legacy enumeration list and Default Device
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
+ {
+ szNames = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+
+ while (szNames && *szNames)
+ {
+ if ((lLength = strlen(szNames)) < 1024)
+ strcpy(szDeviceNames[lNumDevices++], szNames);
+ szNames += lLength + 1;
+ }
+
+ szDefaultName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+ }
+
+ // Get new uber enumeration list and Default Device
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
+ {
+ szNames = alcGetString(NULL, alcGetEnumValue(NULL, "ALC_ALL_DEVICES_SPECIFIER"));
+
+ while (szNames && *szNames)
+ {
+ if ((lLength = strlen(szNames)) < 1024)
+ strcpy(szDeviceNames[lNumDevices++], szNames);
+ szNames += lLength + 1;
+ }
+
+ szDefaultAllName = alcGetString(NULL, alcGetEnumValue(NULL, "ALC_DEFAULT_ALL_DEVICES_SPECIFIER"));
+ }
+
+
+ for (lLoop = 0; lLoop < lNumDevices; lLoop++)
+ printf("Press %d for '%s' Device %s\n", lLoop+1, szDeviceNames[lLoop],
+ (strcmp(szDeviceNames[lLoop], szDefaultName?szDefaultName:"") == 0) ? "*" : (strcmp(szDeviceNames[lLoop], szDefaultAllName?szDefaultAllName:"") == 0) ? "**" : "");
+ printf("Press Q to quit\n");
+
+ do
+ {
+ ch = _getch();
+ if (ch == 'q' || ch == 'Q')
+ exit(0);
+ else if ((ch >= '1') && (ch < ('1' + lNumDevices)))
+ break;
+ } while (1);
+
+ *ppDevice = alcOpenDevice(szDeviceNames[ch - '1']);
+ if (*ppDevice)
+ {
+ *ppContext = alcCreateContext(*ppDevice,NULL);
+ if (*ppContext)
+ {
+ alcGetError(*ppDevice);
+ alcMakeContextCurrent(*ppContext);
+ if (alcGetError(*ppDevice) == ALC_NO_ERROR)
+ bInit = AL_TRUE;
+ }
+ else
+ {
+ alcCloseDevice(*ppDevice);
+ }
+ }
+
+ return bInit;
+}
+*/ \ No newline at end of file
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 00000000..d8c26def
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,43 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* Define if we have the ALSA backend */
+#cmakedefine HAVE_ALSA
+
+/* Define if we have the OSS backend */
+#cmakedefine HAVE_OSS
+
+/* Define if we have the DSound backend */
+#cmakedefine HAVE_DSOUND
+
+/* Define if we have the Windows Multimedia backend */
+#cmakedefine HAVE_WINMM
+
+/* Define if we have dlfcn.h */
+#cmakedefine HAVE_DLFCN_H
+
+/* Define if we have the sqrtf function */
+#cmakedefine HAVE_SQRTF
+
+/* Define if we have the strtof function */
+#cmakedefine HAVE_STRTOF
+
+/* Define if we have stdint.h */
+#cmakedefine HAVE_STDINT_H
+
+/* Define if we have the __int64 type */
+#cmakedefine HAVE___INT64
+
+/* Define to the size of a long int type */
+#cmakedefine SIZEOF_LONG ${SIZEOF_LONG}
+
+/* Define to the size of a long long int type */
+#cmakedefine SIZEOF_LONG_LONG ${SIZEOF_LONG_LONG}
+
+/* Define to the size of an unsigned int type */
+#cmakedefine SIZEOF_UINT ${SIZEOF_UINT}
+
+/* Define to the size of a void pointer type */
+#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP}
+
+#endif
diff --git a/include/AL/al.h b/include/AL/al.h
new file mode 100644
index 00000000..630b6ad5
--- /dev/null
+++ b/include/AL/al.h
@@ -0,0 +1,724 @@
+#ifndef AL_AL_H
+#define AL_AL_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(_WIN32) && !defined(_XBOX)
+ /* _OPENAL32LIB is deprecated */
+ #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB)
+ #define AL_API __declspec(dllexport)
+ #else
+ #define AL_API __declspec(dllimport)
+ #endif
+#else
+ #if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
+ #define AL_API __attribute__((visibility("default")))
+ #else
+ #define AL_API extern
+ #endif
+#endif
+
+#if defined(_WIN32)
+ #define AL_APIENTRY __cdecl
+#else
+ #define AL_APIENTRY
+#endif
+
+#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
+ #pragma export on
+#endif
+
+/*
+ * The OPENAL, ALAPI, ALAPIENTRY, AL_INVALID, AL_ILLEGAL_ENUM, and
+ * AL_ILLEGAL_COMMAND macros are deprecated, but are included for
+ * applications porting code from AL 1.0
+ */
+#define OPENAL
+#define ALAPI AL_API
+#define ALAPIENTRY AL_APIENTRY
+#define AL_INVALID (-1)
+#define AL_ILLEGAL_ENUM AL_INVALID_ENUM
+#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
+
+#define AL_VERSION_1_0
+#define AL_VERSION_1_1
+
+
+/** 8-bit boolean */
+typedef char ALboolean;
+
+/** character */
+typedef char ALchar;
+
+/** signed 8-bit 2's complement integer */
+typedef char ALbyte;
+
+/** unsigned 8-bit integer */
+typedef unsigned char ALubyte;
+
+/** signed 16-bit 2's complement integer */
+typedef short ALshort;
+
+/** unsigned 16-bit integer */
+typedef unsigned short ALushort;
+
+/** signed 32-bit 2's complement integer */
+typedef int ALint;
+
+/** unsigned 32-bit integer */
+typedef unsigned int ALuint;
+
+/** non-negative 32-bit binary integer size */
+typedef int ALsizei;
+
+/** enumerated 32-bit value */
+typedef int ALenum;
+
+/** 32-bit IEEE754 floating-point */
+typedef float ALfloat;
+
+/** 64-bit IEEE754 floating-point */
+typedef double ALdouble;
+
+/** void type (for opaque pointers only) */
+typedef void ALvoid;
+
+
+/* Enumerant values begin at column 50. No tabs. */
+
+/* "no distance model" or "no buffer" */
+#define AL_NONE 0
+
+/* Boolean False. */
+#define AL_FALSE 0
+
+/** Boolean True. */
+#define AL_TRUE 1
+
+/** Indicate Source has relative coordinates. */
+#define AL_SOURCE_RELATIVE 0x202
+
+
+
+/**
+ * Directional source, inner cone angle, in degrees.
+ * Range: [0-360]
+ * Default: 360
+ */
+#define AL_CONE_INNER_ANGLE 0x1001
+
+/**
+ * Directional source, outer cone angle, in degrees.
+ * Range: [0-360]
+ * Default: 360
+ */
+#define AL_CONE_OUTER_ANGLE 0x1002
+
+/**
+ * Specify the pitch to be applied, either at source,
+ * or on mixer results, at listener.
+ * Range: [0.5-2.0]
+ * Default: 1.0
+ */
+#define AL_PITCH 0x1003
+
+/**
+ * Specify the current location in three dimensional space.
+ * OpenAL, like OpenGL, uses a right handed coordinate system,
+ * where in a frontal default view X (thumb) points right,
+ * Y points up (index finger), and Z points towards the
+ * viewer/camera (middle finger).
+ * To switch from a left handed coordinate system, flip the
+ * sign on the Z coordinate.
+ * Listener position is always in the world coordinate system.
+ */
+#define AL_POSITION 0x1004
+
+/** Specify the current direction. */
+#define AL_DIRECTION 0x1005
+
+/** Specify the current velocity in three dimensional space. */
+#define AL_VELOCITY 0x1006
+
+/**
+ * Indicate whether source is looping.
+ * Type: ALboolean?
+ * Range: [AL_TRUE, AL_FALSE]
+ * Default: FALSE.
+ */
+#define AL_LOOPING 0x1007
+
+/**
+ * Indicate the buffer to provide sound samples.
+ * Type: ALuint.
+ * Range: any valid Buffer id.
+ */
+#define AL_BUFFER 0x1009
+
+/**
+ * Indicate the gain (volume amplification) applied.
+ * Type: ALfloat.
+ * Range: ]0.0- ]
+ * A value of 1.0 means un-attenuated/unchanged.
+ * Each division by 2 equals an attenuation of -6dB.
+ * Each multiplicaton with 2 equals an amplification of +6dB.
+ * A value of 0.0 is meaningless with respect to a logarithmic
+ * scale; it is interpreted as zero volume - the channel
+ * is effectively disabled.
+ */
+#define AL_GAIN 0x100A
+
+/*
+ * Indicate minimum source attenuation
+ * Type: ALfloat
+ * Range: [0.0 - 1.0]
+ *
+ * Logarthmic
+ */
+#define AL_MIN_GAIN 0x100D
+
+/**
+ * Indicate maximum source attenuation
+ * Type: ALfloat
+ * Range: [0.0 - 1.0]
+ *
+ * Logarthmic
+ */
+#define AL_MAX_GAIN 0x100E
+
+/**
+ * Indicate listener orientation.
+ *
+ * at/up
+ */
+#define AL_ORIENTATION 0x100F
+
+/**
+ * Source state information.
+ */
+#define AL_SOURCE_STATE 0x1010
+#define AL_INITIAL 0x1011
+#define AL_PLAYING 0x1012
+#define AL_PAUSED 0x1013
+#define AL_STOPPED 0x1014
+
+/**
+ * Buffer Queue params
+ */
+#define AL_BUFFERS_QUEUED 0x1015
+#define AL_BUFFERS_PROCESSED 0x1016
+
+/**
+ * Source buffer position information
+ */
+#define AL_SEC_OFFSET 0x1024
+#define AL_SAMPLE_OFFSET 0x1025
+#define AL_BYTE_OFFSET 0x1026
+
+/*
+ * Source type (Static, Streaming or undetermined)
+ * Source is Static if a Buffer has been attached using AL_BUFFER
+ * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
+ * Source is undetermined when it has the NULL buffer attached
+ */
+#define AL_SOURCE_TYPE 0x1027
+#define AL_STATIC 0x1028
+#define AL_STREAMING 0x1029
+#define AL_UNDETERMINED 0x1030
+
+/** Sound samples: format specifier. */
+#define AL_FORMAT_MONO8 0x1100
+#define AL_FORMAT_MONO16 0x1101
+#define AL_FORMAT_STEREO8 0x1102
+#define AL_FORMAT_STEREO16 0x1103
+
+/**
+ * source specific reference distance
+ * Type: ALfloat
+ * Range: 0.0 - +inf
+ *
+ * At 0.0, no distance attenuation occurs. Default is
+ * 1.0.
+ */
+#define AL_REFERENCE_DISTANCE 0x1020
+
+/**
+ * source specific rolloff factor
+ * Type: ALfloat
+ * Range: 0.0 - +inf
+ *
+ */
+#define AL_ROLLOFF_FACTOR 0x1021
+
+/**
+ * Directional source, outer cone gain.
+ *
+ * Default: 0.0
+ * Range: [0.0 - 1.0]
+ * Logarithmic
+ */
+#define AL_CONE_OUTER_GAIN 0x1022
+
+/**
+ * Indicate distance above which sources are not
+ * attenuated using the inverse clamped distance model.
+ *
+ * Default: +inf
+ * Type: ALfloat
+ * Range: 0.0 - +inf
+ */
+#define AL_MAX_DISTANCE 0x1023
+
+/**
+ * Sound samples: frequency, in units of Hertz [Hz].
+ * This is the number of samples per second. Half of the
+ * sample frequency marks the maximum significant
+ * frequency component.
+ */
+#define AL_FREQUENCY 0x2001
+#define AL_BITS 0x2002
+#define AL_CHANNELS 0x2003
+#define AL_SIZE 0x2004
+
+/**
+ * Buffer state.
+ *
+ * Not supported for public use (yet).
+ */
+#define AL_UNUSED 0x2010
+#define AL_PENDING 0x2011
+#define AL_PROCESSED 0x2012
+
+
+/** Errors: No Error. */
+#define AL_NO_ERROR AL_FALSE
+
+/**
+ * Invalid Name paramater passed to AL call.
+ */
+#define AL_INVALID_NAME 0xA001
+
+/**
+ * Invalid parameter passed to AL call.
+ */
+#define AL_INVALID_ENUM 0xA002
+
+/**
+ * Invalid enum parameter value.
+ */
+#define AL_INVALID_VALUE 0xA003
+
+/**
+ * Illegal call.
+ */
+#define AL_INVALID_OPERATION 0xA004
+
+
+/**
+ * No mojo.
+ */
+#define AL_OUT_OF_MEMORY 0xA005
+
+
+/** Context strings: Vendor Name. */
+#define AL_VENDOR 0xB001
+#define AL_VERSION 0xB002
+#define AL_RENDERER 0xB003
+#define AL_EXTENSIONS 0xB004
+
+/** Global tweakage. */
+
+/**
+ * Doppler scale. Default 1.0
+ */
+#define AL_DOPPLER_FACTOR 0xC000
+
+/**
+ * Tweaks speed of propagation.
+ */
+#define AL_DOPPLER_VELOCITY 0xC001
+
+/**
+ * Speed of Sound in units per second
+ */
+#define AL_SPEED_OF_SOUND 0xC003
+
+/**
+ * Distance models
+ *
+ * used in conjunction with DistanceModel
+ *
+ * implicit: NONE, which disances distance attenuation.
+ */
+#define AL_DISTANCE_MODEL 0xD000
+#define AL_INVERSE_DISTANCE 0xD001
+#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
+#define AL_LINEAR_DISTANCE 0xD003
+#define AL_LINEAR_DISTANCE_CLAMPED 0xD004
+#define AL_EXPONENT_DISTANCE 0xD005
+#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006
+
+/*
+ * Renderer State management
+ */
+AL_API void AL_APIENTRY alEnable( ALenum capability );
+
+AL_API void AL_APIENTRY alDisable( ALenum capability );
+
+AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability );
+
+
+/*
+ * State retrieval
+ */
+AL_API const ALchar* AL_APIENTRY alGetString( ALenum param );
+
+AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data );
+
+AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data );
+
+AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data );
+
+AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data );
+
+AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param );
+
+AL_API ALint AL_APIENTRY alGetInteger( ALenum param );
+
+AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param );
+
+AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param );
+
+
+/*
+ * Error support.
+ * Obtain the most recent error generated in the AL state machine.
+ */
+AL_API ALenum AL_APIENTRY alGetError( void );
+
+
+/*
+ * Extension support.
+ * Query for the presence of an extension, and obtain any appropriate
+ * function pointers and enum values.
+ */
+AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname );
+
+AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname );
+
+AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename );
+
+
+/*
+ * LISTENER
+ * Listener represents the location and orientation of the
+ * 'user' in 3D-space.
+ *
+ * Properties include: -
+ *
+ * Gain AL_GAIN ALfloat
+ * Position AL_POSITION ALfloat[3]
+ * Velocity AL_VELOCITY ALfloat[3]
+ * Orientation AL_ORIENTATION ALfloat[6] (Forward then Up vectors)
+*/
+
+/*
+ * Set Listener parameters
+ */
+AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value );
+
+AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+
+AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values );
+
+AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value );
+
+AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 );
+
+AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values );
+
+/*
+ * Get Listener parameters
+ */
+AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value );
+
+AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 );
+
+AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values );
+
+AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value );
+
+AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 );
+
+AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values );
+
+
+/**
+ * SOURCE
+ * Sources represent individual sound objects in 3D-space.
+ * Sources take the PCM data provided in the specified Buffer,
+ * apply Source-specific modifications, and then
+ * submit them to be mixed according to spatial arrangement etc.
+ *
+ * Properties include: -
+ *
+ * Gain AL_GAIN ALfloat
+ * Min Gain AL_MIN_GAIN ALfloat
+ * Max Gain AL_MAX_GAIN ALfloat
+ * Position AL_POSITION ALfloat[3]
+ * Velocity AL_VELOCITY ALfloat[3]
+ * Direction AL_DIRECTION ALfloat[3]
+ * Head Relative Mode AL_SOURCE_RELATIVE ALint (AL_TRUE or AL_FALSE)
+ * Reference Distance AL_REFERENCE_DISTANCE ALfloat
+ * Max Distance AL_MAX_DISTANCE ALfloat
+ * RollOff Factor AL_ROLLOFF_FACTOR ALfloat
+ * Inner Angle AL_CONE_INNER_ANGLE ALint or ALfloat
+ * Outer Angle AL_CONE_OUTER_ANGLE ALint or ALfloat
+ * Cone Outer Gain AL_CONE_OUTER_GAIN ALint or ALfloat
+ * Pitch AL_PITCH ALfloat
+ * Looping AL_LOOPING ALint (AL_TRUE or AL_FALSE)
+ * MS Offset AL_MSEC_OFFSET ALint or ALfloat
+ * Byte Offset AL_BYTE_OFFSET ALint or ALfloat
+ * Sample Offset AL_SAMPLE_OFFSET ALint or ALfloat
+ * Attached Buffer AL_BUFFER ALint
+ * State (Query only) AL_SOURCE_STATE ALint
+ * Buffers Queued (Query only) AL_BUFFERS_QUEUED ALint
+ * Buffers Processed (Query only) AL_BUFFERS_PROCESSED ALint
+ */
+
+/* Create Source objects */
+AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources );
+
+/* Delete Source objects */
+AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources );
+
+/* Verify a handle is a valid Source */
+AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid );
+
+/*
+ * Set Source parameters
+ */
+AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value );
+
+AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+
+AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values );
+
+AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value );
+
+AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 );
+
+AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values );
+
+/*
+ * Get Source parameters
+ */
+AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value );
+
+AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
+
+AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values );
+
+AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value );
+
+AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+
+AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values );
+
+
+/*
+ * Source vector based playback calls
+ */
+
+/* Play, replay, or resume (if paused) a list of Sources */
+AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids );
+
+/* Stop a list of Sources */
+AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids );
+
+/* Rewind a list of Sources */
+AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids );
+
+/* Pause a list of Sources */
+AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids );
+
+/*
+ * Source based playback calls
+ */
+
+/* Play, replay, or resume a Source */
+AL_API void AL_APIENTRY alSourcePlay( ALuint sid );
+
+/* Stop a Source */
+AL_API void AL_APIENTRY alSourceStop( ALuint sid );
+
+/* Rewind a Source (set playback postiton to beginning) */
+AL_API void AL_APIENTRY alSourceRewind( ALuint sid );
+
+/* Pause a Source */
+AL_API void AL_APIENTRY alSourcePause( ALuint sid );
+
+/*
+ * Source Queuing
+ */
+AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids );
+
+AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids );
+
+
+/**
+ * BUFFER
+ * Buffer objects are storage space for sample data.
+ * Buffers are referred to by Sources. One Buffer can be used
+ * by multiple Sources.
+ *
+ * Properties include: -
+ *
+ * Frequency (Query only) AL_FREQUENCY ALint
+ * Size (Query only) AL_SIZE ALint
+ * Bits (Query only) AL_BITS ALint
+ * Channels (Query only) AL_CHANNELS ALint
+ */
+
+/* Create Buffer objects */
+AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers );
+
+/* Delete Buffer objects */
+AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers );
+
+/* Verify a handle is a valid Buffer */
+AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid );
+
+/* Specify the data to be copied into a buffer */
+AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq );
+
+/*
+ * Set Buffer parameters
+ */
+AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value );
+
+AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+
+AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values );
+
+AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value );
+
+AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 );
+
+AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values );
+
+/*
+ * Get Buffer parameters
+ */
+AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value );
+
+AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
+
+AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values );
+
+AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value );
+
+AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+
+AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values );
+
+
+/*
+ * Global Parameters
+ */
+AL_API void AL_APIENTRY alDopplerFactor( ALfloat value );
+
+AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value );
+
+AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value );
+
+AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel );
+
+/*
+ * Pointer-to-function types, useful for dynamically getting AL entry points.
+ */
+typedef void (AL_APIENTRY *LPALENABLE)( ALenum capability );
+typedef void (AL_APIENTRY *LPALDISABLE)( ALenum capability );
+typedef ALboolean (AL_APIENTRY *LPALISENABLED)( ALenum capability );
+typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)( ALenum param );
+typedef void (AL_APIENTRY *LPALGETBOOLEANV)( ALenum param, ALboolean* data );
+typedef void (AL_APIENTRY *LPALGETINTEGERV)( ALenum param, ALint* data );
+typedef void (AL_APIENTRY *LPALGETFLOATV)( ALenum param, ALfloat* data );
+typedef void (AL_APIENTRY *LPALGETDOUBLEV)( ALenum param, ALdouble* data );
+typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)( ALenum param );
+typedef ALint (AL_APIENTRY *LPALGETINTEGER)( ALenum param );
+typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)( ALenum param );
+typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)( ALenum param );
+typedef ALenum (AL_APIENTRY *LPALGETERROR)( void );
+typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar* extname );
+typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)( const ALchar* fname );
+typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)( const ALchar* ename );
+typedef void (AL_APIENTRY *LPALLISTENERF)( ALenum param, ALfloat value );
+typedef void (AL_APIENTRY *LPALLISTENER3F)( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+typedef void (AL_APIENTRY *LPALLISTENERFV)( ALenum param, const ALfloat* values );
+typedef void (AL_APIENTRY *LPALLISTENERI)( ALenum param, ALint value );
+typedef void (AL_APIENTRY *LPALLISTENER3I)( ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef void (AL_APIENTRY *LPALLISTENERIV)( ALenum param, const ALint* values );
+typedef void (AL_APIENTRY *LPALGETLISTENERF)( ALenum param, ALfloat* value );
+typedef void (AL_APIENTRY *LPALGETLISTENER3F)( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 );
+typedef void (AL_APIENTRY *LPALGETLISTENERFV)( ALenum param, ALfloat* values );
+typedef void (AL_APIENTRY *LPALGETLISTENERI)( ALenum param, ALint* value );
+typedef void (AL_APIENTRY *LPALGETLISTENER3I)( ALenum param, ALint *value1, ALint *value2, ALint *value3 );
+typedef void (AL_APIENTRY *LPALGETLISTENERIV)( ALenum param, ALint* values );
+typedef void (AL_APIENTRY *LPALGENSOURCES)( ALsizei n, ALuint* sources );
+typedef void (AL_APIENTRY *LPALDELETESOURCES)( ALsizei n, const ALuint* sources );
+typedef ALboolean (AL_APIENTRY *LPALISSOURCE)( ALuint sid );
+typedef void (AL_APIENTRY *LPALSOURCEF)( ALuint sid, ALenum param, ALfloat value);
+typedef void (AL_APIENTRY *LPALSOURCE3F)( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+typedef void (AL_APIENTRY *LPALSOURCEFV)( ALuint sid, ALenum param, const ALfloat* values );
+typedef void (AL_APIENTRY *LPALSOURCEI)( ALuint sid, ALenum param, ALint value);
+typedef void (AL_APIENTRY *LPALSOURCE3I)( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef void (AL_APIENTRY *LPALSOURCEIV)( ALuint sid, ALenum param, const ALint* values );
+typedef void (AL_APIENTRY *LPALGETSOURCEF)( ALuint sid, ALenum param, ALfloat* value );
+typedef void (AL_APIENTRY *LPALGETSOURCE3F)( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
+typedef void (AL_APIENTRY *LPALGETSOURCEFV)( ALuint sid, ALenum param, ALfloat* values );
+typedef void (AL_APIENTRY *LPALGETSOURCEI)( ALuint sid, ALenum param, ALint* value );
+typedef void (AL_APIENTRY *LPALGETSOURCE3I)( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+typedef void (AL_APIENTRY *LPALGETSOURCEIV)( ALuint sid, ALenum param, ALint* values );
+typedef void (AL_APIENTRY *LPALSOURCEPLAYV)( ALsizei ns, const ALuint *sids );
+typedef void (AL_APIENTRY *LPALSOURCESTOPV)( ALsizei ns, const ALuint *sids );
+typedef void (AL_APIENTRY *LPALSOURCEREWINDV)( ALsizei ns, const ALuint *sids );
+typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)( ALsizei ns, const ALuint *sids );
+typedef void (AL_APIENTRY *LPALSOURCEPLAY)( ALuint sid );
+typedef void (AL_APIENTRY *LPALSOURCESTOP)( ALuint sid );
+typedef void (AL_APIENTRY *LPALSOURCEREWIND)( ALuint sid );
+typedef void (AL_APIENTRY *LPALSOURCEPAUSE)( ALuint sid );
+typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, const ALuint *bids );
+typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, ALuint *bids );
+typedef void (AL_APIENTRY *LPALGENBUFFERS)( ALsizei n, ALuint* buffers );
+typedef void (AL_APIENTRY *LPALDELETEBUFFERS)( ALsizei n, const ALuint* buffers );
+typedef ALboolean (AL_APIENTRY *LPALISBUFFER)( ALuint bid );
+typedef void (AL_APIENTRY *LPALBUFFERDATA)( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq );
+typedef void (AL_APIENTRY *LPALBUFFERF)( ALuint bid, ALenum param, ALfloat value);
+typedef void (AL_APIENTRY *LPALBUFFER3F)( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
+typedef void (AL_APIENTRY *LPALBUFFERFV)( ALuint bid, ALenum param, const ALfloat* values );
+typedef void (AL_APIENTRY *LPALBUFFERI)( ALuint bid, ALenum param, ALint value);
+typedef void (AL_APIENTRY *LPALBUFFER3I)( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 );
+typedef void (AL_APIENTRY *LPALBUFFERIV)( ALuint bid, ALenum param, const ALint* values );
+typedef void (AL_APIENTRY *LPALGETBUFFERF)( ALuint bid, ALenum param, ALfloat* value );
+typedef void (AL_APIENTRY *LPALGETBUFFER3F)( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
+typedef void (AL_APIENTRY *LPALGETBUFFERFV)( ALuint bid, ALenum param, ALfloat* values );
+typedef void (AL_APIENTRY *LPALGETBUFFERI)( ALuint bid, ALenum param, ALint* value );
+typedef void (AL_APIENTRY *LPALGETBUFFER3I)( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
+typedef void (AL_APIENTRY *LPALGETBUFFERIV)( ALuint bid, ALenum param, ALint* values );
+typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)( ALfloat value );
+typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)( ALfloat value );
+typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)( ALfloat value );
+typedef void (AL_APIENTRY *LPALDISTANCEMODEL)( ALenum distanceModel );
+
+#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
+ #pragma export off
+#endif
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif /* AL_AL_H */
diff --git a/include/AL/alc.h b/include/AL/alc.h
new file mode 100644
index 00000000..b0bbfbe7
--- /dev/null
+++ b/include/AL/alc.h
@@ -0,0 +1,281 @@
+#ifndef AL_ALC_H
+#define AL_ALC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(_WIN32) && !defined(_XBOX)
+ /* _OPENAL32LIB is deprecated */
+ #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB)
+ #define ALC_API __declspec(dllexport)
+ #else
+ #define ALC_API __declspec(dllimport)
+ #endif
+#else
+ #if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
+ #define ALC_API __attribute__((visibility("default")))
+ #else
+ #define ALC_API extern
+ #endif
+#endif
+
+#if defined(_WIN32)
+ #define ALC_APIENTRY __cdecl
+#else
+ #define ALC_APIENTRY
+#endif
+
+#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
+ #pragma export on
+#endif
+
+/*
+ * The ALCAPI, ALCAPIENTRY, and ALC_INVALID macros are deprecated, but are
+ * included for applications porting code from AL 1.0
+ */
+#define ALCAPI ALC_API
+#define ALCAPIENTRY ALC_APIENTRY
+#define ALC_INVALID 0
+
+
+#define ALC_VERSION_0_1 1
+
+typedef struct ALCdevice_struct ALCdevice;
+typedef struct ALCcontext_struct ALCcontext;
+
+
+/** 8-bit boolean */
+typedef char ALCboolean;
+
+/** character */
+typedef char ALCchar;
+
+/** signed 8-bit 2's complement integer */
+typedef char ALCbyte;
+
+/** unsigned 8-bit integer */
+typedef unsigned char ALCubyte;
+
+/** signed 16-bit 2's complement integer */
+typedef short ALCshort;
+
+/** unsigned 16-bit integer */
+typedef unsigned short ALCushort;
+
+/** signed 32-bit 2's complement integer */
+typedef int ALCint;
+
+/** unsigned 32-bit integer */
+typedef unsigned int ALCuint;
+
+/** non-negative 32-bit binary integer size */
+typedef int ALCsizei;
+
+/** enumerated 32-bit value */
+typedef int ALCenum;
+
+/** 32-bit IEEE754 floating-point */
+typedef float ALCfloat;
+
+/** 64-bit IEEE754 floating-point */
+typedef double ALCdouble;
+
+/** void type (for opaque pointers only) */
+typedef void ALCvoid;
+
+
+/* Enumerant values begin at column 50. No tabs. */
+
+/* Boolean False. */
+#define ALC_FALSE 0
+
+/* Boolean True. */
+#define ALC_TRUE 1
+
+/**
+ * followed by <int> Hz
+ */
+#define ALC_FREQUENCY 0x1007
+
+/**
+ * followed by <int> Hz
+ */
+#define ALC_REFRESH 0x1008
+
+/**
+ * followed by AL_TRUE, AL_FALSE
+ */
+#define ALC_SYNC 0x1009
+
+/**
+ * followed by <int> Num of requested Mono (3D) Sources
+ */
+#define ALC_MONO_SOURCES 0x1010
+
+/**
+ * followed by <int> Num of requested Stereo Sources
+ */
+#define ALC_STEREO_SOURCES 0x1011
+
+/**
+ * errors
+ */
+
+/**
+ * No error
+ */
+#define ALC_NO_ERROR ALC_FALSE
+
+/**
+ * No device
+ */
+#define ALC_INVALID_DEVICE 0xA001
+
+/**
+ * invalid context ID
+ */
+#define ALC_INVALID_CONTEXT 0xA002
+
+/**
+ * bad enum
+ */
+#define ALC_INVALID_ENUM 0xA003
+
+/**
+ * bad value
+ */
+#define ALC_INVALID_VALUE 0xA004
+
+/**
+ * Out of memory.
+ */
+#define ALC_OUT_OF_MEMORY 0xA005
+
+
+/**
+ * The Specifier string for default device
+ */
+#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
+#define ALC_DEVICE_SPECIFIER 0x1005
+#define ALC_EXTENSIONS 0x1006
+
+#define ALC_MAJOR_VERSION 0x1000
+#define ALC_MINOR_VERSION 0x1001
+
+#define ALC_ATTRIBUTES_SIZE 0x1002
+#define ALC_ALL_ATTRIBUTES 0x1003
+
+/**
+ * ALC_ENUMERATE_ALL_EXT enums
+ */
+#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
+#define ALC_ALL_DEVICES_SPECIFIER 0x1013
+
+/**
+ * Capture extension
+ */
+#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
+#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
+#define ALC_CAPTURE_SAMPLES 0x312
+
+
+/*
+ * Context Management
+ */
+ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist );
+
+ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context );
+
+ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context );
+
+ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context );
+
+ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context );
+
+ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( void );
+
+ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context );
+
+
+/*
+ * Device Management
+ */
+ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename );
+
+ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device );
+
+
+/*
+ * Error support.
+ * Obtain the most recent Context error
+ */
+ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device );
+
+
+/*
+ * Extension support.
+ * Query for the presence of an extension, and obtain any appropriate
+ * function pointers and enum values.
+ */
+ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname );
+
+ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname );
+
+ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname );
+
+
+/*
+ * Query functions
+ */
+ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param );
+
+ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data );
+
+
+/*
+ * Capture functions
+ */
+ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
+
+ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device );
+
+ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device );
+
+ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device );
+
+ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
+
+/*
+ * Pointer-to-function types, useful for dynamically getting ALC entry points.
+ */
+typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist);
+typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context );
+typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)( ALCcontext *context );
+typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)( ALCcontext *context );
+typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context );
+typedef ALCcontext * (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)( void );
+typedef ALCdevice * (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)( ALCcontext *context );
+typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename );
+typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device );
+typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)( ALCdevice *device );
+typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname );
+typedef void * (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname );
+typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname );
+typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param );
+typedef void (ALC_APIENTRY *LPALCGETINTEGERV)( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest );
+typedef ALCdevice * (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
+typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)( ALCdevice *device );
+typedef void (ALC_APIENTRY *LPALCCAPTURESTART)( ALCdevice *device );
+typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)( ALCdevice *device );
+typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
+
+#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
+ #pragma export off
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* AL_ALC_H */
diff --git a/include/COPYING b/include/COPYING
new file mode 100644
index 00000000..e463f462
--- /dev/null
+++ b/include/COPYING
@@ -0,0 +1,483 @@
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/openalrc.sample b/openalrc.sample
new file mode 100644
index 00000000..74bcba22
--- /dev/null
+++ b/openalrc.sample
@@ -0,0 +1,51 @@
+# OpenAL config file. Options that are not under a block or are under the
+# [general] block are for general, non-backend-specific options. Blocks may
+# appear multiple times, and duplicated options will take the last value
+# specified. The system-wide settings can be put in /etc/openal/config and
+# user-specific override settings in ~/.openalrc
+
+# Option and block names are case-insenstive. The supplied values are only
+# hints and may not be honored (though generally it'll try to get as close as
+# possible). These are the current available settings:
+
+format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of:
+ # AL_FORMAT_MONO8 (8-bit mono)
+ # AL_FORMAT_STEREO8 (8-bit stereo)
+ # AL_FORMAT_QUAD8 (8-bit 4-channel)
+ # AL_FORMAT_MONO16 (16-bit mono)
+ # AL_FORMAT_STEREO16 (16-bit stereo)
+ # AL_FORMAT_QUAD16 (16-bit 4-channel)
+ # Default is AL_FORMAT_STEREO16
+
+frequency = 44100 # Sets the output frequency. Default is 44100
+
+refresh = 0 # Sets the number of frames-per-update. Default is calculated as
+ # 8192*frequency/22050. Note that the actual granularity may or
+ # may not be less than this.
+
+# TODO: Implement this option
+drivers = # Sets the backend driver list order, comma-seperated. Unknown
+ # backends and duplicated names are ignored, and unlisted backends
+ # won't be considered for use. An empty list means the default.
+ # Default is:
+ # alsa,oss,dsound,winmm
+
+[alsa] # ALSA backend stuff
+device = default # Sets the device name for the default playback device.
+ # Default is default
+
+periods = 4 # Sets the number of update buffers. Default is 4
+
+capture = default # Sets the device name for the default capture device.
+ # Default is default
+
+[oss] # OSS backend stuff
+device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
+
+periods = 4 # Sets the number of update buffers. Default is 4
+
+[dsound] # DirectSound backend stuff
+ # Nothing yet...
+
+[winmm] # Windows Multimedia backend stuff
+ # Nothing yet...