summaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c799
1 files changed, 407 insertions, 392 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d8211d03..ca692818 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -40,6 +40,9 @@
#include "alu.h"
+/************************************************
+ * Backends
+ ************************************************/
#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
static struct BackendInfo BackendList[] = {
#ifdef HAVE_PULSEAUDIO
@@ -91,9 +94,9 @@ static struct BackendInfo BackendLoopback = {
static struct BackendInfo PlaybackBackend;
static struct BackendInfo CaptureBackend;
-///////////////////////////////////////////////////////
-// STRING and EXTENSIONS
-
+/************************************************
+ * Functions, enums, and errors
+ ************************************************/
typedef struct ALCfunction {
const ALCchar *funcName;
ALCvoid *address;
@@ -104,7 +107,6 @@ typedef struct ALCenums {
ALCenum value;
} ALCenums;
-
static const ALCfunction alcFunctions[] = {
{ "alcCreateContext", (ALCvoid *) alcCreateContext },
{ "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent },
@@ -256,12 +258,10 @@ static const ALCfunction alcFunctions[] = {
};
static const ALCenums enumeration[] = {
- // 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 },
@@ -281,16 +281,13 @@ static const ALCenums enumeration[] = {
{ "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
{ "ALC_CONNECTED", ALC_CONNECTED },
- // EFX Properties
{ "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
{ "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
{ "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
- // Loopback device Properties
{ "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT },
{ "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT },
- // Buffer Channel Configurations
{ "ALC_MONO_SOFT", ALC_MONO_SOFT },
{ "ALC_STEREO_SOFT", ALC_STEREO_SOFT },
{ "ALC_QUAD_SOFT", ALC_QUAD_SOFT },
@@ -298,7 +295,6 @@ static const ALCenums enumeration[] = {
{ "ALC_6POINT1_SOFT", ALC_6POINT1_SOFT },
{ "ALC_7POINT1_SOFT", ALC_7POINT1_SOFT },
- // Buffer Sample Types
{ "ALC_BYTE_SOFT", ALC_BYTE_SOFT },
{ "ALC_UNSIGNED_BYTE_SOFT", ALC_UNSIGNED_BYTE_SOFT },
{ "ALC_SHORT_SOFT", ALC_SHORT_SOFT },
@@ -307,7 +303,6 @@ static const ALCenums enumeration[] = {
{ "ALC_UNSIGNED_INT_SOFT", ALC_UNSIGNED_INT_SOFT },
{ "ALC_FLOAT_SOFT", ALC_FLOAT_SOFT },
- // ALC Error Message
{ "ALC_NO_ERROR", ALC_NO_ERROR },
{ "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
{ "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
@@ -317,7 +312,7 @@ static const ALCenums enumeration[] = {
{ NULL, (ALCenum)0 }
};
-// Error strings
+
static const ALCchar alcNoError[] = "No Error";
static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
static const ALCchar alcErrInvalidContext[] = "Invalid Context";
@@ -325,51 +320,24 @@ static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
static const ALCchar alcErrInvalidValue[] = "Invalid Value";
static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
-/* Device lists. Sizes only include the first ending null character, not the
- * second */
+
+/************************************************
+ * Global variables
+ ************************************************/
+
+/* Enumerated device names */
static const ALCchar alcDefaultName[] = "OpenAL Soft\0";
static ALCchar *alcAllDeviceList;
-static size_t alcAllDeviceListSize;
static ALCchar *alcCaptureDeviceList;
+/* Sizes only include the first ending null character, not the second */
+static size_t alcAllDeviceListSize;
static size_t alcCaptureDeviceListSize;
+
/* Default is always the first in the list */
static ALCchar *alcDefaultAllDeviceSpecifier;
static ALCchar *alcCaptureDefaultDeviceSpecifier;
-
-static const ALCchar alcNoDeviceExtList[] =
- "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
- "ALC_EXT_thread_local_context ALC_SOFT_loopback";
-static const ALCchar alcExtensionList[] =
- "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
- "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
- "ALC_EXT_thread_local_context ALC_SOFT_loopback";
-static const ALCint alcMajorVersion = 1;
-static const ALCint alcMinorVersion = 1;
-
-static const ALCint alcEFXMajorVersion = 1;
-static const ALCint alcEFXMinorVersion = 0;
-
-///////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////
-// Global Variables
-
-static CRITICAL_SECTION ListLock;
-
-/* Device List */
-static ALCdevice *volatile DeviceList = NULL;
-
-// Thread-local current context
-static pthread_key_t LocalContext;
-// Process-wide current context
-static ALCcontext *volatile GlobalContext = NULL;
-
-/* Device Error */
-static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
-
-// Default context extensions
+/* Default context extensions */
static const ALchar alExtList[] =
"AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
"AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
@@ -377,13 +345,17 @@ static const ALchar alExtList[] =
"AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data "
"AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points";
-// Mixing Priority Level
+static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
+
+/* Thread-local current context */
+static pthread_key_t LocalContext;
+/* Process-wide current context */
+static ALCcontext *volatile GlobalContext = NULL;
+
+/* Mixing thread piority level */
ALint RTPrioLevel;
-// Output Log File
FILE *LogFile;
-
-// Output Log Level
#ifdef _DEBUG
enum LogLevel LogLevel = LogWarning;
#else
@@ -396,20 +368,46 @@ static ALCboolean TrapALCError = ALC_FALSE;
/* One-time configuration init control */
static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
-/* Forced effect that applies to sources that don't have an effect on send 0 */
+/* Default effect that applies to sources that don't have an effect on send 0 */
static ALeffect DefaultEffect;
-///////////////////////////////////////////////////////
+/************************************************
+ * ALC information
+ ************************************************/
+static const ALCchar alcNoDeviceExtList[] =
+ "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
+ "ALC_EXT_thread_local_context ALC_SOFT_loopback";
+static const ALCchar alcExtensionList[] =
+ "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
+ "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
+ "ALC_EXT_thread_local_context ALC_SOFT_loopback";
+static const ALCint alcMajorVersion = 1;
+static const ALCint alcMinorVersion = 1;
-///////////////////////////////////////////////////////
-// ALC Related helper functions
-static void ReleaseALC(void);
-static void ReleaseThreadCtx(void *ptr);
+static const ALCint alcEFXMajorVersion = 1;
+static const ALCint alcEFXMinorVersion = 0;
-static void alc_initconfig(void);
-#define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
+/************************************************
+ * Device lists
+ ************************************************/
+static ALCdevice *volatile DeviceList = NULL;
+
+static CRITICAL_SECTION ListLock;
+
+static void LockLists(void)
+{
+ EnterCriticalSection(&ListLock);
+}
+static void UnlockLists(void)
+{
+ LeaveCriticalSection(&ListLock);
+}
+
+/************************************************
+ * Library initialization
+ ************************************************/
#if defined(_WIN32)
static void alc_init(void);
static void alc_deinit(void);
@@ -477,13 +475,17 @@ static void alc_deinit(void) __attribute__((destructor));
#else
#error "No static initialization available on this platform!"
#endif
+
#elif defined(HAVE_GCC_DESTRUCTOR)
+
static void alc_init(void) __attribute__((constructor));
static void alc_deinit(void) __attribute__((destructor));
+
#else
#error "No global initialization available on this platform!"
#endif
+static void ReleaseThreadCtx(void *ptr);
static void alc_init(void)
{
const char *str;
@@ -503,38 +505,6 @@ static void alc_init(void)
ThunkInit();
}
-static void alc_deinit_safe(void)
-{
- ReleaseALC();
-
- FreeHrtf();
- FreeALConfig();
-
- ThunkExit();
- DeleteCriticalSection(&ListLock);
- pthread_key_delete(LocalContext);
-
- if(LogFile != stderr)
- fclose(LogFile);
- LogFile = NULL;
-}
-
-static void alc_deinit(void)
-{
- int i;
-
- ReleaseALC();
-
- memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
- memset(&CaptureBackend, 0, sizeof(CaptureBackend));
-
- for(i = 0;BackendList[i].Deinit;i++)
- BackendList[i].Deinit();
- BackendLoopback.Deinit();
-
- alc_deinit_safe();
-}
-
static void alc_initconfig(void)
{
const char *devs, *str;
@@ -723,19 +693,72 @@ static void alc_initconfig(void)
if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
LoadReverbPreset(str, &DefaultEffect);
}
+#define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
-static void LockLists(void)
+/************************************************
+ * Library deinitialization
+ ************************************************/
+static void alc_cleanup(void)
{
- EnterCriticalSection(&ListLock);
+ ALCdevice *dev;
+
+ free(alcAllDeviceList); alcAllDeviceList = NULL;
+ alcAllDeviceListSize = 0;
+ free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
+ alcCaptureDeviceListSize = 0;
+
+ free(alcDefaultAllDeviceSpecifier);
+ alcDefaultAllDeviceSpecifier = NULL;
+ free(alcCaptureDefaultDeviceSpecifier);
+ alcCaptureDefaultDeviceSpecifier = NULL;
+
+ if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
+ {
+ ALCuint num = 0;
+ do {
+ num++;
+ } while((dev=dev->next) != NULL);
+ ERR("%u device%s not closed\n", num, (num>1)?"s":"");
+ }
}
-static void UnlockLists(void)
+static void alc_deinit_safe(void)
{
- LeaveCriticalSection(&ListLock);
+ alc_cleanup();
+
+ FreeHrtf();
+ FreeALConfig();
+
+ ThunkExit();
+ DeleteCriticalSection(&ListLock);
+ pthread_key_delete(LocalContext);
+
+ if(LogFile != stderr)
+ fclose(LogFile);
+ LogFile = NULL;
}
+static void alc_deinit(void)
+{
+ int i;
+
+ alc_cleanup();
+ memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
+ memset(&CaptureBackend, 0, sizeof(CaptureBackend));
+
+ for(i = 0;BackendList[i].Deinit;i++)
+ BackendList[i].Deinit();
+ BackendLoopback.Deinit();
+
+ alc_deinit_safe();
+}
+
+
+/************************************************
+ * Device enumeration
+ ************************************************/
static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
{
DO_INITCONFIG();
@@ -789,88 +812,9 @@ DECL_APPEND_LIST_FUNC(CaptureDevice)
#undef DECL_APPEND_LIST_FUNC
-/* Sets the default channel order used by most non-WaveFormatEx-based APIs */
-void SetDefaultChannelOrder(ALCdevice *device)
-{
- switch(device->FmtChans)
- {
- case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT;
- device->DevChannels[4] = FRONT_CENTER;
- device->DevChannels[5] = LFE;
- return;
-
- case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT;
- device->DevChannels[4] = FRONT_CENTER;
- device->DevChannels[5] = LFE;
- device->DevChannels[6] = SIDE_LEFT;
- device->DevChannels[7] = SIDE_RIGHT;
- return;
-
- /* Same as WFX order */
- case DevFmtMono:
- case DevFmtStereo:
- case DevFmtQuad:
- case DevFmtX51Side:
- case DevFmtX61:
- break;
- }
- SetDefaultWFXChannelOrder(device);
-}
-/* Sets the default order used by WaveFormatEx */
-void SetDefaultWFXChannelOrder(ALCdevice *device)
-{
- switch(device->FmtChans)
- {
- case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
-
- case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT; break;
-
- case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = BACK_LEFT;
- device->DevChannels[3] = BACK_RIGHT; break;
-
- case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_LEFT;
- device->DevChannels[5] = BACK_RIGHT; break;
-
- case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = SIDE_LEFT;
- device->DevChannels[5] = SIDE_RIGHT; break;
-
- case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_CENTER;
- device->DevChannels[5] = SIDE_LEFT;
- device->DevChannels[6] = SIDE_RIGHT; break;
-
- case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
- device->DevChannels[1] = FRONT_RIGHT;
- device->DevChannels[2] = FRONT_CENTER;
- device->DevChannels[3] = LFE;
- device->DevChannels[4] = BACK_LEFT;
- device->DevChannels[5] = BACK_RIGHT;
- device->DevChannels[6] = SIDE_LEFT;
- device->DevChannels[7] = SIDE_RIGHT; break;
- }
-}
-
-
+/************************************************
+ * Device format information
+ ************************************************/
const ALCchar *DevFmtTypeString(enum DevFmtType type)
{
switch(type)
@@ -928,6 +872,7 @@ ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
}
return 0;
}
+
static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
enum DevFmtType *type)
{
@@ -1007,9 +952,102 @@ static ALCboolean IsValidALCChannels(ALCenum channels)
}
+/************************************************
+ * Miscellaneous ALC helpers
+ ************************************************/
+
+/* SetDefaultWFXChannelOrder
+ *
+ * Sets the default channel order used by WaveFormatEx.
+ */
+void SetDefaultWFXChannelOrder(ALCdevice *device)
+{
+ switch(device->FmtChans)
+ {
+ case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
+
+ case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT; break;
+
+ case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT; break;
+
+ case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_LEFT;
+ device->DevChannels[5] = BACK_RIGHT; break;
+
+ case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = SIDE_LEFT;
+ device->DevChannels[5] = SIDE_RIGHT; break;
+
+ case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_CENTER;
+ device->DevChannels[5] = SIDE_LEFT;
+ device->DevChannels[6] = SIDE_RIGHT; break;
+
+ case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = FRONT_CENTER;
+ device->DevChannels[3] = LFE;
+ device->DevChannels[4] = BACK_LEFT;
+ device->DevChannels[5] = BACK_RIGHT;
+ device->DevChannels[6] = SIDE_LEFT;
+ device->DevChannels[7] = SIDE_RIGHT; break;
+ }
+}
+
+/* SetDefaultChannelOrder
+ *
+ * Sets the default channel order used by most non-WaveFormatEx-based APIs.
+ */
+void SetDefaultChannelOrder(ALCdevice *device)
+{
+ switch(device->FmtChans)
+ {
+ case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT;
+ device->DevChannels[4] = FRONT_CENTER;
+ device->DevChannels[5] = LFE;
+ return;
+
+ case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
+ device->DevChannels[1] = FRONT_RIGHT;
+ device->DevChannels[2] = BACK_LEFT;
+ device->DevChannels[3] = BACK_RIGHT;
+ device->DevChannels[4] = FRONT_CENTER;
+ device->DevChannels[5] = LFE;
+ device->DevChannels[6] = SIDE_LEFT;
+ device->DevChannels[7] = SIDE_RIGHT;
+ return;
+
+ /* Same as WFX order */
+ case DevFmtMono:
+ case DevFmtStereo:
+ case DevFmtQuad:
+ case DevFmtX51Side:
+ case DevFmtX61:
+ break;
+ }
+ SetDefaultWFXChannelOrder(device);
+}
+
+
/* alcSetError
*
- * Stores the latest ALC Error
+ * Stores the latest ALC device error
*/
static void alcSetError(ALCdevice *device, ALCenum errorCode)
{
@@ -1437,7 +1475,7 @@ static ALCdevice *VerifyDevice(ALCdevice *device)
/* InitContext
*
- * Initializes context variables
+ * Initializes context fields
*/
static ALvoid InitContext(ALCcontext *Context)
{
@@ -1610,8 +1648,8 @@ static ALCcontext *VerifyContext(ALCcontext *context)
/* GetContextRef
*
- * Returns the currently active context, and adds a reference without locking
- * it.
+ * Returns the currently active context for this thread, and adds a reference
+ * without locking it.
*/
ALCcontext *GetContextRef(void)
{
@@ -1632,175 +1670,14 @@ ALCcontext *GetContextRef(void)
return context;
}
-///////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////
-// ALC Functions calls
-
-
-// This should probably move to another c file but for now ...
-ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
-{
- ALCdevice *device = NULL;
- ALCenum err;
-
- DO_INITCONFIG();
-
- if(!CaptureBackend.name)
- {
- alcSetError(NULL, ALC_INVALID_VALUE);
- return NULL;
- }
-
- if(samples <= 0)
- {
- alcSetError(NULL, ALC_INVALID_VALUE);
- return NULL;
- }
-
- if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
- deviceName = NULL;
-
- device = calloc(1, sizeof(ALCdevice));
- if(!device)
- {
- alcSetError(NULL, ALC_OUT_OF_MEMORY);
- return NULL;
- }
-
- //Validate device
- device->Funcs = &CaptureBackend.Funcs;
- device->ref = 1;
- device->Connected = ALC_TRUE;
- device->Type = Capture;
- InitializeCriticalSection(&device->Mutex);
-
- InitUIntMap(&device->BufferMap, ~0);
- InitUIntMap(&device->EffectMap, ~0);
- InitUIntMap(&device->FilterMap, ~0);
-
- device->DeviceName = NULL;
-
- device->Flags |= DEVICE_FREQUENCY_REQUEST;
- device->Frequency = frequency;
-
- device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
- if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
- {
- DeleteCriticalSection(&device->Mutex);
- free(device);
- alcSetError(NULL, ALC_INVALID_ENUM);
- return NULL;
- }
-
- device->UpdateSize = samples;
- device->NumUpdates = 1;
-
- LockLists();
- if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
- {
- UnlockLists();
- DeleteCriticalSection(&device->Mutex);
- free(device);
- alcSetError(NULL, err);
- return NULL;
- }
- UnlockLists();
-
- do {
- device->next = DeviceList;
- } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
-
- TRACE("Created device %p\n", device);
- return device;
-}
-
-ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
-{
- ALCdevice *volatile*list;
-
- LockLists();
- list = &DeviceList;
- while(*list && *list != Device)
- list = &(*list)->next;
-
- if(!*list || (*list)->Type != Capture)
- {
- alcSetError(*list, ALC_INVALID_DEVICE);
- UnlockLists();
- return ALC_FALSE;
- }
-
- *list = (*list)->next;
- UnlockLists();
-
- ALCdevice_CloseCapture(Device);
-
- ALCdevice_DecRef(Device);
-
- return ALC_TRUE;
-}
-
-ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
-{
- LockLists();
- if(!(device=VerifyDevice(device)) || device->Type != Capture)
- {
- UnlockLists();
- alcSetError(device, ALC_INVALID_DEVICE);
- if(device) ALCdevice_DecRef(device);
- return;
- }
- if(device->Connected)
- {
- if(!(device->Flags&DEVICE_RUNNING))
- ALCdevice_StartCapture(device);
- device->Flags |= DEVICE_RUNNING;
- }
- UnlockLists();
- ALCdevice_DecRef(device);
-}
+/************************************************
+ * Standard ALC functions
+ ************************************************/
-ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
-{
- LockLists();
- if(!(device=VerifyDevice(device)) || device->Type != Capture)
- {
- UnlockLists();
- alcSetError(device, ALC_INVALID_DEVICE);
- if(device) ALCdevice_DecRef(device);
- return;
- }
- if((device->Flags&DEVICE_RUNNING))
- ALCdevice_StopCapture(device);
- device->Flags &= ~DEVICE_RUNNING;
- UnlockLists();
-
- ALCdevice_DecRef(device);
-}
-
-ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
-{
- ALCenum err = ALC_INVALID_DEVICE;
- LockLists();
- if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
- {
- err = ALC_INVALID_VALUE;
- if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
- err = ALCdevice_CaptureSamples(device, buffer, samples);
- }
- UnlockLists();
- if(err != ALC_NO_ERROR)
- alcSetError(device, err);
- if(device) ALCdevice_DecRef(device);
-}
-
-/*
- alcGetError
-
- Return last ALC generated error code
+/* alcGetError
+ *
+ * Return last ALC generated error code for the given device
*/
ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
{
@@ -1961,7 +1838,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
/* alcGetIntegerv
*
- * Returns information about the Device and the version of Open AL
+ * Returns information about the device and the version of OpenAL
*/
ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
{
@@ -2214,7 +2091,7 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
/* alcGetEnumValue
*
- * Get the value for a particular ALC Enumerated Value
+ * Get the value for a particular ALC enumeration name
*/
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
{
@@ -2239,7 +2116,7 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e
/* alcCreateContext
*
- * Create and attach a Context to a particular Device.
+ * Create and attach a context to the given device.
*/
ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
{
@@ -2255,7 +2132,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
return NULL;
}
- /* Reset Context Last Error code */
device->LastError = ALC_NO_ERROR;
if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
@@ -2311,7 +2187,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
/* alcDestroyContext
*
- * Remove a Context
+ * Remove a context from its device
*/
ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
{
@@ -2335,9 +2211,9 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
/* alcGetCurrentContext
*
- * Returns the currently active Context
+ * Returns the currently active context on the calling thread
*/
-ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
+ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
{
ALCcontext *Context;
@@ -2349,7 +2225,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
/* alcGetThreadContext
*
- * Returns the currently active thread-local Context
+ * Returns the currently active thread-local context
*/
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
{
@@ -2361,11 +2237,12 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
/* alcMakeContextCurrent
*
- * Makes the given Context the active Context
+ * Makes the given context the active process-wide context, and removes the
+ * thread-local context for the calling thread.
*/
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
{
- /* context must be a valid Context or NULL */
+ /* context must be valid or NULL */
if(context && !(context=VerifyContext(context)))
{
alcSetError(NULL, ALC_INVALID_CONTEXT);
@@ -2386,13 +2263,13 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
/* alcSetThreadContext
*
- * Makes the given Context the active Context for the current thread
+ * Makes the given context the active context for the current thread
*/
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
{
ALCcontext *old;
- /* context must be a valid Context or NULL */
+ /* context must be valid or NULL */
if(context && !(context=VerifyContext(context)))
{
alcSetError(NULL, ALC_INVALID_CONTEXT);
@@ -2409,7 +2286,7 @@ ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
/* alcGetContextsDevice
*
- * Returns the Device that a particular Context is attached to
+ * Returns the device that a particular context is attached to
*/
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
{
@@ -2429,7 +2306,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
/* alcOpenDevice
*
- * Open the Device specified.
+ * Opens the named device.
*/
ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
{
@@ -2656,7 +2533,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
/* alcCloseDevice
*
- * Close the specified Device
+ * Closes the given device.
*/
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
{
@@ -2695,6 +2572,171 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
}
+/************************************************
+ * ALC capture functions
+ ************************************************/
+ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
+{
+ ALCdevice *device = NULL;
+ ALCenum err;
+
+ DO_INITCONFIG();
+
+ if(!CaptureBackend.name)
+ {
+ alcSetError(NULL, ALC_INVALID_VALUE);
+ return NULL;
+ }
+
+ if(samples <= 0)
+ {
+ alcSetError(NULL, ALC_INVALID_VALUE);
+ return NULL;
+ }
+
+ if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
+ deviceName = NULL;
+
+ device = calloc(1, sizeof(ALCdevice));
+ if(!device)
+ {
+ alcSetError(NULL, ALC_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ //Validate device
+ device->Funcs = &CaptureBackend.Funcs;
+ device->ref = 1;
+ device->Connected = ALC_TRUE;
+ device->Type = Capture;
+ InitializeCriticalSection(&device->Mutex);
+
+ InitUIntMap(&device->BufferMap, ~0);
+ InitUIntMap(&device->EffectMap, ~0);
+ InitUIntMap(&device->FilterMap, ~0);
+
+ device->DeviceName = NULL;
+
+ device->Flags |= DEVICE_FREQUENCY_REQUEST;
+ device->Frequency = frequency;
+
+ device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
+ if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
+ {
+ DeleteCriticalSection(&device->Mutex);
+ free(device);
+ alcSetError(NULL, ALC_INVALID_ENUM);
+ return NULL;
+ }
+
+ device->UpdateSize = samples;
+ device->NumUpdates = 1;
+
+ LockLists();
+ if((err=ALCdevice_OpenCapture(device, deviceName)) != ALC_NO_ERROR)
+ {
+ UnlockLists();
+ DeleteCriticalSection(&device->Mutex);
+ free(device);
+ alcSetError(NULL, err);
+ return NULL;
+ }
+ UnlockLists();
+
+ do {
+ device->next = DeviceList;
+ } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device));
+
+ TRACE("Created device %p\n", device);
+ return device;
+}
+
+ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device)
+{
+ ALCdevice *volatile*list;
+
+ LockLists();
+ list = &DeviceList;
+ while(*list && *list != Device)
+ list = &(*list)->next;
+
+ if(!*list || (*list)->Type != Capture)
+ {
+ alcSetError(*list, ALC_INVALID_DEVICE);
+ UnlockLists();
+ return ALC_FALSE;
+ }
+
+ *list = (*list)->next;
+ UnlockLists();
+
+ ALCdevice_CloseCapture(Device);
+
+ ALCdevice_DecRef(Device);
+
+ return ALC_TRUE;
+}
+
+ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
+{
+ LockLists();
+ if(!(device=VerifyDevice(device)) || device->Type != Capture)
+ {
+ UnlockLists();
+ alcSetError(device, ALC_INVALID_DEVICE);
+ if(device) ALCdevice_DecRef(device);
+ return;
+ }
+ if(device->Connected)
+ {
+ if(!(device->Flags&DEVICE_RUNNING))
+ ALCdevice_StartCapture(device);
+ device->Flags |= DEVICE_RUNNING;
+ }
+ UnlockLists();
+
+ ALCdevice_DecRef(device);
+}
+
+ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
+{
+ LockLists();
+ if(!(device=VerifyDevice(device)) || device->Type != Capture)
+ {
+ UnlockLists();
+ alcSetError(device, ALC_INVALID_DEVICE);
+ if(device) ALCdevice_DecRef(device);
+ return;
+ }
+ if((device->Flags&DEVICE_RUNNING))
+ ALCdevice_StopCapture(device);
+ device->Flags &= ~DEVICE_RUNNING;
+ UnlockLists();
+
+ ALCdevice_DecRef(device);
+}
+
+ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
+{
+ ALCenum err = ALC_INVALID_DEVICE;
+ LockLists();
+ if((device=VerifyDevice(device)) != NULL && device->Type == Capture)
+ {
+ err = ALC_INVALID_VALUE;
+ if(samples >= 0 && ALCdevice_AvailableSamples(device) >= (ALCuint)samples)
+ err = ALCdevice_CaptureSamples(device, buffer, samples);
+ }
+ UnlockLists();
+ if(err != ALC_NO_ERROR)
+ alcSetError(device, err);
+ if(device) ALCdevice_DecRef(device);
+}
+
+
+/************************************************
+ * ALC loopback functions
+ ************************************************/
+
/* alcLoopbackOpenDeviceSOFT
*
* Open a loopback device, for manual rendering.
@@ -2811,30 +2853,3 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe
aluMixData(device, buffer, samples);
if(device) ALCdevice_DecRef(device);
}
-
-
-static void ReleaseALC(void)
-{
- ALCdevice *dev;
-
- free(alcAllDeviceList); alcAllDeviceList = NULL;
- alcAllDeviceListSize = 0;
- free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
- alcCaptureDeviceListSize = 0;
-
- free(alcDefaultAllDeviceSpecifier);
- alcDefaultAllDeviceSpecifier = NULL;
- free(alcCaptureDefaultDeviceSpecifier);
- alcCaptureDefaultDeviceSpecifier = NULL;
-
- if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL)
- {
- ALCuint num = 0;
- do {
- num++;
- } while((dev=dev->next) != NULL);
- ERR("%u device%s not closed\n", num, (num>1)?"s":"");
- }
-}
-
-///////////////////////////////////////////////////////