diff options
-rw-r--r-- | router/alc.c | 123 |
1 files changed, 122 insertions, 1 deletions
diff --git a/router/alc.c b/router/alc.c index cd9d0dc6..438326bd 100644 --- a/router/alc.c +++ b/router/alc.c @@ -2,6 +2,8 @@ #include "config.h" #include <stddef.h> +#include <stdlib.h> +#include <string.h> #include "AL/alc.h" #include "router.h" @@ -230,6 +232,8 @@ 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"; +static const ALCchar alcExtensionList[] = + "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE"; static const ALCint alcMajorVersion = 1; static const ALCint alcMinorVersion = 1; @@ -240,6 +244,65 @@ PtrIntMap DeviceIfaceMap = PTRINTMAP_STATIC_INITIALIZE; PtrIntMap ContextIfaceMap = PTRINTMAP_STATIC_INITIALIZE; +typedef struct EnumeratedList { + ALCchar *Names; + ALCchar *NamesEnd; + ALCint *Indicies; + ALCsizei IndexSize; +} EnumeratedList; +static EnumeratedList DevicesList = { NULL, NULL, NULL, 0 }; +static EnumeratedList AllDevicesList = { NULL, NULL, NULL, 0 }; +static EnumeratedList CaptureDevicesList = { NULL, NULL, NULL, 0 }; + +static void ClearDeviceList(EnumeratedList *list) +{ + free(list->Names); + list->Names = NULL; + list->NamesEnd = NULL; + + free(list->Indicies); + list->Indicies = NULL; + list->IndexSize = 0; +} + +static void AppendDeviceList(EnumeratedList *list, const ALCchar *names, ALint idx) +{ + const ALCchar *name_end = names; + ALCsizei count = 0; + ALCchar *new_list; + ALCint *new_indicies; + size_t len; + ALCsizei i; + + if(!name_end) + return; + while(*name_end) + { + count++; + name_end += strlen(name_end)+1; + } + if(names == name_end) + return; + + len = (list->NamesEnd - list->Names) + (name_end - names); + new_list = calloc(1, len + 1); + memcpy(new_list, list->Names, list->NamesEnd - list->Names); + memcpy(new_list + (list->NamesEnd - list->Names), names, name_end - names); + free(list->Names); + list->Names = new_list; + list->NamesEnd = list->Names + len; + + new_indicies = calloc(sizeof(ALCint), list->IndexSize + count); + for(i = 0;i < list->IndexSize;i++) + new_indicies[i] = list->Indicies[i]; + for(i = 0;i < count;i++) + new_indicies[list->IndexSize+i] = idx; + free(list->Indicies); + list->Indicies = new_indicies; + list->IndexSize += count; +} + + ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename) { return NULL; @@ -318,6 +381,9 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) { + const char *ptr; + size_t len; + if(device) { ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device); @@ -328,6 +394,20 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A } return DriverList[idx].alcIsExtensionPresent(device, extname); } + + len = strlen(extname); + ptr = alcExtensionList; + while(ptr && *ptr) + { + if(strncasecmp(ptr, extname, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len]))) + return ALC_TRUE; + if((ptr=strchr(ptr, ' ')) != NULL) + { + do { + ++ptr; + } while(isspace(*ptr)); + } + } return ALC_FALSE; } @@ -379,6 +459,8 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param) { + ALsizei i = 0; + if(device) { ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device); @@ -408,9 +490,48 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum para return ""; case ALC_DEVICE_SPECIFIER: + ClearDeviceList(&DevicesList); + for(i = 0;i < DriverListSize;i++) + { + /* Only enumerate names from drivers that support it. + * FIXME: Check for ALC 1.1 too, since that guarantees enumeration + * support. + */ + if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) + AppendDeviceList(&DevicesList, + DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i + ); + } + return DevicesList.Names; + case ALC_ALL_DEVICES_SPECIFIER: + ClearDeviceList(&AllDevicesList); + for(i = 0;i < DriverListSize;i++) + { + /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute + * standard enumeration. + */ + if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) + AppendDeviceList(&AllDevicesList, + DriverList[i].alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER), i + ); + else if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) + AppendDeviceList(&AllDevicesList, + DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i + ); + } + return AllDevicesList.Names; + case ALC_CAPTURE_DEVICE_SPECIFIER: - return ""; + ClearDeviceList(&CaptureDevicesList); + for(i = 0;i < DriverListSize;i++) + { + if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE")) + AppendDeviceList(&CaptureDevicesList, + DriverList[i].alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER), i + ); + } + return CaptureDevicesList.Names; case ALC_DEFAULT_DEVICE_SPECIFIER: case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: |