From cf066fd306a915963d6bf1379f6c81c4c924ff1e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 17 Mar 2014 09:40:56 -0700 Subject: Don't assume the default mmdevapi device is in the collection --- Alc/backends/mmdevapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index b93ff667..24769213 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -186,7 +186,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu hr = IMMDeviceCollection_GetCount(coll, &count); if(SUCCEEDED(hr) && count > 0) { - devlist = calloc(count, sizeof(*devlist)); + devlist = calloc(count+1, sizeof(*devlist)); if(!devlist) { IMMDeviceCollection_Release(coll); @@ -199,7 +199,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu if(SUCCEEDED(hr) && defdev != NULL) add_device(defdev, &devlist[idx++]); - for(i = 0;i < count && idx < count;++i) + for(i = 0;i < count;++i) { IMMDevice *device; -- cgit v1.2.3 From 4f3e71e5b7ce4768a33c1b3dfa0a3b3df698789b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 27 Mar 2014 17:17:35 -0700 Subject: Reactivate the mmdevapi audio client and set the event handle on reset --- Alc/backends/mmdevapi.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 24769213..bfa283a1 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -339,8 +339,21 @@ static HRESULT DoReset(ALCdevice *device) WAVEFORMATEX *wfx = NULL; REFERENCE_TIME min_per, buf_time; UINT32 buffer_len, min_len; + void *ptr = NULL; HRESULT hr; + if(data->client) + IAudioClient_Release(data->client); + data->client = NULL; + + hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + data->client = ptr; + hr = IAudioClient_GetMixFormat(data->client, &wfx); if(FAILED(hr)) { @@ -560,6 +573,13 @@ static HRESULT DoReset(ALCdevice *device) device->UpdateSize = buffer_len / device->NumUpdates; } + hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent); + if(FAILED(hr)) + { + ERR("Failed to set event handle: 0x%08lx\n", hr); + return hr; + } + return hr; } @@ -671,15 +691,9 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) data = device->ExtraData; ResetEvent(data->NotifyEvent); - hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent); + hr = IAudioClient_Start(data->client); if(FAILED(hr)) - ERR("Failed to set event handle: 0x%08lx\n", hr); - else - { - hr = IAudioClient_Start(data->client); - if(FAILED(hr)) - ERR("Failed to start audio client: 0x%08lx\n", hr); - } + ERR("Failed to start audio client: 0x%08lx\n", hr); if(SUCCEEDED(hr)) hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr); @@ -728,10 +742,12 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) device = (ALCdevice*)msg.lParam; data = device->ExtraData; - IAudioClient_Release(data->client); + if(data->client) + IAudioClient_Release(data->client); data->client = NULL; - IMMDevice_Release(data->mmdev); + if(data->mmdev) + IMMDevice_Release(data->mmdev); data->mmdev = NULL; if(--deviceCount == 0) -- cgit v1.2.3 From d997be67fd8771f21791be73ef6e7bfd08105416 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Mar 2014 07:59:47 -0700 Subject: Use al_string to handle mmdevapi and dsound device names --- Alc/alstring.h | 16 +++++++ Alc/backends/dsound.c | 119 ++++++++++++++++++++++++++++-------------------- Alc/backends/mmdevapi.c | 52 ++++++++++----------- Alc/helpers.c | 27 +++++++++++ 4 files changed, 135 insertions(+), 79 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/alstring.h b/Alc/alstring.h index b393a8f4..8f7d1655 100644 --- a/Alc/alstring.h +++ b/Alc/alstring.h @@ -1,8 +1,11 @@ #ifndef ALSTRING_H #define ALSTRING_H +#include + #include "vector.h" + typedef char al_string_char_type; DECL_VECTOR(al_string_char_type) @@ -23,10 +26,23 @@ inline const al_string_char_type *al_string_get_cstr(const_al_string str) void al_string_clear(al_string *str); +inline int al_string_cmp(const_al_string str1, const_al_string str2) +{ return strcmp(al_string_get_cstr(str1), al_string_get_cstr(str2)); } + +inline int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2) +{ return strcmp(al_string_get_cstr(str1), str2); } + void al_string_copy(al_string *str, const_al_string from); void al_string_copy_cstr(al_string *str, const al_string_char_type *from); void al_string_append_char(al_string *str, const al_string_char_type c); +void al_string_append_cstr(al_string *str, const al_string_char_type *from); void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); +#ifdef _WIN32 +#include +/* Windows-only methods to deal with WideChar strings. */ +void al_string_copy_wcstr(al_string *str, const wchar_t *from); +#endif + #endif /* ALSTRING_H */ diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 6b108fba..b8fc02d6 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -36,6 +36,7 @@ #include "alu.h" #include "threads.h" #include "compat.h" +#include "alstring.h" #ifndef DSSPEAKER_5POINT1 # define DSSPEAKER_5POINT1 0x00000006 @@ -57,14 +58,14 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0 static void *ds_handle; static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); -static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); +static HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter); -static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); +static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); #define DirectSoundCreate pDirectSoundCreate -#define DirectSoundEnumerateA pDirectSoundEnumerateA +#define DirectSoundEnumerateW pDirectSoundEnumerateW #define DirectSoundCaptureCreate pDirectSoundCaptureCreate -#define DirectSoundCaptureEnumerateA pDirectSoundCaptureEnumerateA +#define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW typedef struct { @@ -90,7 +91,7 @@ typedef struct { typedef struct { - ALCchar *name; + al_string name; GUID guid; } DevMap; @@ -121,19 +122,19 @@ static ALCboolean DSoundLoad(void) } \ } while(0) LOAD_FUNC(DirectSoundCreate); - LOAD_FUNC(DirectSoundEnumerateA); + LOAD_FUNC(DirectSoundEnumerateW); LOAD_FUNC(DirectSoundCaptureCreate); - LOAD_FUNC(DirectSoundCaptureEnumerateA); + LOAD_FUNC(DirectSoundCaptureEnumerateW); #undef LOAD_FUNC } return ALC_TRUE; } -static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data)) +static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCWSTR desc, LPCWSTR UNUSED(drvname), LPVOID UNUSED(data)) { LPOLESTR guidstr = NULL; - char str[1024]; + al_string dname; HRESULT hr; void *temp; int count; @@ -142,17 +143,22 @@ static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR if(!guid) return TRUE; + AL_STRING_INIT(dname); + count = 0; do { - if(count == 0) - snprintf(str, sizeof(str), "%s", desc); - else - snprintf(str, sizeof(str), "%s #%d", desc, count+1); + al_string_copy_wcstr(&dname, desc); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; for(i = 0;i < NumPlaybackDevices;i++) { - if(strcmp(str, PlaybackDeviceList[i].name) == 0) + if(al_string_cmp(dname, PlaybackDeviceList[i].name) == 0) break; } } while(i != NumPlaybackDevices); @@ -160,15 +166,17 @@ static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR hr = StringFromCLSID(guid, &guidstr); if(SUCCEEDED(hr)) { - TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr); + TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(dname), guidstr); CoTaskMemFree(guidstr); } temp = realloc(PlaybackDeviceList, sizeof(DevMap) * (NumPlaybackDevices+1)); - if(temp) + if(!temp) + AL_STRING_DEINIT(dname); + else { PlaybackDeviceList = temp; - PlaybackDeviceList[NumPlaybackDevices].name = strdup(str); + PlaybackDeviceList[NumPlaybackDevices].name = dname; PlaybackDeviceList[NumPlaybackDevices].guid = *guid; NumPlaybackDevices++; } @@ -177,10 +185,10 @@ static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR } -static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data)) +static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCWSTR desc, LPCWSTR UNUSED(drvname), LPVOID UNUSED(data)) { LPOLESTR guidstr = NULL; - char str[1024]; + al_string dname; HRESULT hr; void *temp; int count; @@ -189,17 +197,22 @@ static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR U if(!guid) return TRUE; + AL_STRING_INIT(dname); + count = 0; do { - if(count == 0) - snprintf(str, sizeof(str), "%s", desc); - else - snprintf(str, sizeof(str), "%s #%d", desc, count+1); + al_string_copy_wcstr(&dname, desc); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; for(i = 0;i < NumCaptureDevices;i++) { - if(strcmp(str, CaptureDeviceList[i].name) == 0) + if(al_string_cmp(dname, CaptureDeviceList[i].name) == 0) break; } } while(i != NumCaptureDevices); @@ -207,15 +220,17 @@ static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR U hr = StringFromCLSID(guid, &guidstr); if(SUCCEEDED(hr)) { - TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr); + TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(dname), guidstr); CoTaskMemFree(guidstr); } temp = realloc(CaptureDeviceList, sizeof(DevMap) * (NumCaptureDevices+1)); - if(temp) + if(!temp) + AL_STRING_DEINIT(dname); + else { CaptureDeviceList = temp; - CaptureDeviceList[NumCaptureDevices].name = strdup(str); + CaptureDeviceList[NumCaptureDevices].name = dname; CaptureDeviceList[NumCaptureDevices].guid = *guid; NumCaptureDevices++; } @@ -336,18 +351,22 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) { DSoundPlaybackData *data = NULL; LPGUID guid = NULL; - HRESULT hr; + HRESULT hr, hrcom; if(!PlaybackDeviceList) { - hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL); + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); + hr = DirectSoundEnumerateW(DSoundEnumPlaybackDevices, NULL); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); + if(SUCCEEDED(hrcom)) + CoUninitialize(); } if(!deviceName && NumPlaybackDevices > 0) { - deviceName = PlaybackDeviceList[0].name; + deviceName = al_string_get_cstr(PlaybackDeviceList[0].name); guid = &PlaybackDeviceList[0].guid; } else @@ -356,7 +375,7 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) for(i = 0;i < NumPlaybackDevices;i++) { - if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0) + if(al_string_cmp_cstr(PlaybackDeviceList[i].name, deviceName) == 0) { guid = &PlaybackDeviceList[i].guid; break; @@ -669,16 +688,16 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) { /* Initialize COM to prevent name truncation */ hrcom = CoInitialize(NULL); - hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL); + hr = DirectSoundCaptureEnumerateW(DSoundEnumCaptureDevices, NULL); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); if(SUCCEEDED(hrcom)) CoUninitialize(); } if(!deviceName && NumCaptureDevices > 0) { - deviceName = CaptureDeviceList[0].name; + deviceName = al_string_get_cstr(CaptureDeviceList[0].name); guid = &CaptureDeviceList[0].guid; } else @@ -687,7 +706,7 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) for(i = 0;i < NumCaptureDevices;i++) { - if(strcmp(deviceName, CaptureDeviceList[i].name) == 0) + if(al_string_cmp_cstr(CaptureDeviceList[i].name, deviceName) == 0) { guid = &CaptureDeviceList[i].guid; break; @@ -972,13 +991,13 @@ void alcDSoundDeinit(void) ALuint i; for(i = 0;i < NumPlaybackDevices;++i) - free(PlaybackDeviceList[i].name); + AL_STRING_DEINIT(PlaybackDeviceList[i].name); free(PlaybackDeviceList); PlaybackDeviceList = NULL; NumPlaybackDevices = 0; for(i = 0;i < NumCaptureDevices;++i) - free(CaptureDeviceList[i].name); + AL_STRING_DEINIT(CaptureDeviceList[i].name); free(CaptureDeviceList); CaptureDeviceList = NULL; NumCaptureDevices = 0; @@ -993,44 +1012,44 @@ void alcDSoundProbe(enum DevProbe type) HRESULT hr, hrcom; ALuint i; + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); switch(type) { case ALL_DEVICE_PROBE: for(i = 0;i < NumPlaybackDevices;++i) - free(PlaybackDeviceList[i].name); + AL_STRING_DEINIT(PlaybackDeviceList[i].name); free(PlaybackDeviceList); PlaybackDeviceList = NULL; NumPlaybackDevices = 0; - hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL); + hr = DirectSoundEnumerateW(DSoundEnumPlaybackDevices, NULL); if(FAILED(hr)) - ERR("Error enumerating DirectSound playback devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); else { for(i = 0;i < NumPlaybackDevices;i++) - AppendAllDevicesList(PlaybackDeviceList[i].name); + AppendAllDevicesList(al_string_get_cstr(PlaybackDeviceList[i].name)); } break; case CAPTURE_DEVICE_PROBE: for(i = 0;i < NumCaptureDevices;++i) - free(CaptureDeviceList[i].name); + AL_STRING_DEINIT(CaptureDeviceList[i].name); free(CaptureDeviceList); CaptureDeviceList = NULL; NumCaptureDevices = 0; - /* Initialize COM to prevent name truncation */ - hrcom = CoInitialize(NULL); - hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL); + hr = DirectSoundCaptureEnumerateW(DSoundEnumCaptureDevices, NULL); if(FAILED(hr)) - ERR("Error enumerating DirectSound capture devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); else { for(i = 0;i < NumCaptureDevices;i++) - AppendCaptureDeviceList(CaptureDeviceList[i].name); + AppendCaptureDeviceList(al_string_get_cstr(CaptureDeviceList[i].name)); } - if(SUCCEEDED(hrcom)) - CoUninitialize(); break; } + if(SUCCEEDED(hrcom)) + CoUninitialize(); } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index bfa283a1..9933c873 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -42,6 +42,7 @@ #include "alu.h" #include "threads.h" #include "compat.h" +#include "alstring.h" DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); @@ -76,7 +77,7 @@ typedef struct { typedef struct { - ALCchar *name; + al_string name; WCHAR *devid; } DevMap; @@ -112,42 +113,29 @@ static HRESULT WaitForResponse(ThreadRequest *req) } -static ALCchar *get_device_name(IMMDevice *device) +static void get_device_name(IMMDevice *device, al_string *name) { - ALCchar *name = NULL; IPropertyStore *ps; PROPVARIANT pvname; HRESULT hr; - int len; hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return calloc(1, 1); + return; } PropVariantInit(&pvname); hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); if(FAILED(hr)) - { WARN("GetValue failed: 0x%08lx\n", hr); - name = calloc(1, 1); - } else - { - if((len=WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, NULL, 0, NULL, NULL)) > 0) - { - name = calloc(1, len); - WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, name, len, NULL, NULL); - } - } + al_string_copy_wcstr(name, pvname.pwszVal); PropVariantClear(&pvname); IPropertyStore_Release(ps); - - return name; } static void add_device(IMMDevice *device, DevMap *devmap) @@ -155,12 +143,16 @@ static void add_device(IMMDevice *device, DevMap *devmap) LPWSTR devid; HRESULT hr; + AL_STRING_INIT(devmap->name); + hr = IMMDevice_GetId(device, &devid); - if(SUCCEEDED(hr)) + if(FAILED(hr)) + devmap->devid = calloc(sizeof(WCHAR), 1); + else { devmap->devid = strdupW(devid); - devmap->name = get_device_name(device); - TRACE("Got device \"%s\", \"%ls\"\n", devmap->name, devmap->devid); + get_device_name(device, &devmap->name); + TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(devmap->name), devmap->devid); CoTaskMemFree(devid); } } @@ -660,8 +652,13 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); if(SUCCEEDED(hr)) { + al_string str; + data->client = ptr; - device->DeviceName = get_device_name(data->mmdev); + AL_STRING_INIT(str); + get_device_name(data->mmdev, &str); + device->DeviceName = strdup(al_string_get_cstr(str)); + AL_STRING_DEINIT(str); } if(FAILED(hr)) @@ -788,7 +785,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) for(i = 0;i < *numdevs;i++) { - free((*devlist)[i].name); + AL_STRING_DEINIT((*devlist)[i].name); free((*devlist)[i].devid); } free(*devlist); @@ -878,7 +875,7 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName hr = E_FAIL; for(i = 0;i < NumPlaybackDevices;i++) { - if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0) + if(strcmp(deviceName, al_string_get_cstr(PlaybackDeviceList[i].name)) == 0) { data->devid = strdupW(PlaybackDeviceList[i].devid); hr = S_OK; @@ -1016,7 +1013,7 @@ void alcMMDevApiDeinit(void) for(i = 0;i < NumPlaybackDevices;i++) { - free(PlaybackDeviceList[i].name); + AL_STRING_DEINIT(PlaybackDeviceList[i].name); free(PlaybackDeviceList[i].devid); } free(PlaybackDeviceList); @@ -1025,7 +1022,7 @@ void alcMMDevApiDeinit(void) for(i = 0;i < NumCaptureDevices;i++) { - free(CaptureDeviceList[i].name); + AL_STRING_DEINIT(CaptureDeviceList[i].name); free(CaptureDeviceList[i].devid); } free(CaptureDeviceList); @@ -1058,10 +1055,7 @@ void alcMMDevApiProbe(enum DevProbe type) { ALuint i; for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i].name) - AppendAllDevicesList(PlaybackDeviceList[i].name); - } + AppendAllDevicesList(al_string_get_cstr(PlaybackDeviceList[i].name)); } break; diff --git a/Alc/helpers.c b/Alc/helpers.c index 77bfb353..3365f828 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -794,6 +794,8 @@ ALboolean vector_resize(void *ptr, size_t base_size, size_t obj_count, size_t ob extern inline ALsizei al_string_length(const_al_string str); extern inline ALsizei al_string_empty(const_al_string str); extern inline const al_string_char_type *al_string_get_cstr(const_al_string str); +extern inline int al_string_cmp(const_al_string str1, const_al_string str2); +extern inline int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2); void al_string_clear(al_string *str) { @@ -831,6 +833,18 @@ void al_string_append_char(al_string *str, const al_string_char_type c) *VECTOR_ITER_END(*str) = 0; } +void al_string_append_cstr(al_string *str, const al_string_char_type *from) +{ + size_t len = strlen(from); + if(len != 0) + { + VECTOR_RESERVE(*str, al_string_length(*str)+len+1); + VECTOR_RESIZE(*str, al_string_length(*str)+len); + memcpy(VECTOR_ITER_END(*str)-len, from, len); + *VECTOR_ITER_END(*str) = 0; + } +} + void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) { ptrdiff_t len = to - from; @@ -843,6 +857,19 @@ void al_string_append_range(al_string *str, const al_string_char_type *from, con } } +#ifdef _WIN32 +void al_string_copy_wcstr(al_string *str, const wchar_t *from) +{ + int len; + if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) + { + VECTOR_RESERVE(*str, len); + VECTOR_RESIZE(*str, len-1); + WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL); + *VECTOR_ITER_END(*str) = 0; + } +} +#endif void InitUIntMap(UIntMap *map, ALsizei limit) -- cgit v1.2.3 From 7b93e10f7a24b7e18c916b0f791d9998f9b4b800 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Mar 2014 22:11:34 -0700 Subject: Use an al_string for the device name --- Alc/ALc.c | 19 +++++++++---------- Alc/backends/alsa.c | 4 ++-- Alc/backends/coreaudio.c | 4 +++- Alc/backends/dsound.c | 4 ++-- Alc/backends/loopback.c | 2 +- Alc/backends/mmdevapi.c | 9 ++------- Alc/backends/null.c | 2 +- Alc/backends/opensl.c | 2 +- Alc/backends/oss.c | 4 ++-- Alc/backends/portaudio.c | 4 ++-- Alc/backends/pulseaudio.c | 6 ++---- Alc/backends/qsa.c | 8 ++++---- Alc/backends/sndio.c | 2 +- Alc/backends/solaris.c | 2 +- Alc/backends/wave.c | 2 +- Alc/backends/winmm.c | 4 ++-- OpenAL32/Include/alMain.h | 3 ++- 17 files changed, 38 insertions(+), 43 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/ALc.c b/Alc/ALc.c index 93e773c3..b6cc3114 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -2024,8 +2024,7 @@ static ALCvoid FreeDevice(ALCdevice *device) free(device->Bs2b); device->Bs2b = NULL; - free(device->DeviceName); - device->DeviceName = NULL; + AL_STRING_DEINIT(device->DeviceName); al_free(device); } @@ -2355,7 +2354,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para case ALC_ALL_DEVICES_SPECIFIER: if(VerifyDevice(Device)) { - value = Device->DeviceName; + value = al_string_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else @@ -2368,7 +2367,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para case ALC_CAPTURE_DEVICE_SPECIFIER: if(VerifyDevice(Device)) { - value = Device->DeviceName; + value = al_string_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else @@ -3069,7 +3068,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->Flags = 0; device->Bs2b = NULL; device->Bs2bLevel = 0; - device->DeviceName = NULL; + AL_STRING_INIT(device->DeviceName); device->ContextList = NULL; @@ -3285,7 +3284,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->next = DeviceList; } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next); - TRACE("Created device %p, \"%s\"\n", device, device->DeviceName); + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); return device; } @@ -3365,6 +3364,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, device->Connected = ALC_TRUE; device->Type = Capture; + AL_STRING_INIT(device->DeviceName); + InitUIntMap(&device->BufferMap, ~0); InitUIntMap(&device->EffectMap, ~0); InitUIntMap(&device->FilterMap, ~0); @@ -3372,8 +3373,6 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, InitUIntMap(&device->PresetMap, ~0); InitUIntMap(&device->FontsoundMap, ~0); - device->DeviceName = NULL; - if(!CaptureBackend.getFactory) device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs, ALCbackend_Capture); @@ -3414,7 +3413,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, device->next = DeviceList; } while(CompExchangePtr((XchgPtr*)&DeviceList, device->next, device) != device->next); - TRACE("Created device %p, \"%s\"\n", device, device->DeviceName); + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); return device; } @@ -3535,7 +3534,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN device->Flags = 0; device->Bs2b = NULL; device->Bs2bLevel = 0; - device->DeviceName = NULL; + AL_STRING_INIT(device->DeviceName); device->ContextList = NULL; diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 51965cec..106e788e 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -647,7 +647,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -1052,7 +1052,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) } } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 5c9b69c8..8098f84a 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -180,7 +180,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -577,6 +577,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) if(data->ring == NULL) goto error; + al_string_copy_cstr(&device->DeviceName, deviceName); + return ALC_NO_ERROR; error: diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index b8fc02d6..079ed02d 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -411,7 +411,7 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -854,7 +854,7 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) data->BufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(device); - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index 053cfce4..d509313a 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -59,7 +59,7 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 9933c873..b713e831 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -652,13 +652,8 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); if(SUCCEEDED(hr)) { - al_string str; - data->client = ptr; - AL_STRING_INIT(str); - get_device_name(data->mmdev, &str); - device->DeviceName = strdup(al_string_get_cstr(str)); - AL_STRING_DEINIT(str); + get_device_name(data->mmdev, &device->DeviceName); } if(FAILED(hr)) @@ -875,7 +870,7 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName hr = E_FAIL; for(i = 0;i < NumPlaybackDevices;i++) { - if(strcmp(deviceName, al_string_get_cstr(PlaybackDeviceList[i].name)) == 0) + if(al_string_cmp_cstr(PlaybackDeviceList[i].name, deviceName) == 0) { data->devid = strdupW(PlaybackDeviceList[i].devid); hr = S_OK; diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 59299dff..6b59ef7a 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -120,7 +120,7 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) return ALC_INVALID_VALUE; device = STATIC_CAST(ALCbackend, self)->mDevice; - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 619c9847..220e6e5c 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -193,7 +193,7 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName return ALC_INVALID_VALUE; } - Device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&Device->DeviceName, deviceName); Device->ExtraData = data; return ALC_NO_ERROR; diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 54c487a4..f0532cdf 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -168,7 +168,7 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -491,7 +491,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 162788fc..0bb6372c 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -212,7 +212,7 @@ retry_open: } device->ExtraData = data; - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; } @@ -354,7 +354,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName) goto error; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index d2d5c9aa..bb371453 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -695,8 +695,7 @@ static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const return; } - free(device->DeviceName); - device->DeviceName = strdup(info->description); + al_string_copy_cstr(&device->DeviceName, info->description); } @@ -1281,8 +1280,7 @@ static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), cons return; } - free(device->DeviceName); - device->DeviceName = strdup(info->description); + al_string_copy_cstr(&device->DeviceName, info->description); } diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index c9762f85..d9d7c87b 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -343,8 +343,8 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - device->DeviceName=strdup(deviceName); - device->ExtraData=data; + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; return ALC_NO_ERROR; } @@ -711,8 +711,8 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - device->DeviceName=strdup(deviceName); - device->ExtraData=data; + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; switch (device->FmtType) { diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 80aebfd1..9e43f08a 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -111,7 +111,7 @@ static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 700131c8..edd0e060 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -119,7 +119,7 @@ static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceNam return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 2209c798..f6bedc08 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -191,7 +191,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 7082a874..19cad879 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -336,7 +336,7 @@ retry_open: goto failure; } - Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]); + al_string_copy_cstr(&Device->DeviceName, PlaybackDeviceList[DeviceID]); return ALC_NO_ERROR; failure: @@ -606,7 +606,7 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) if (data->WaveThread == NULL) goto failure; - Device->DeviceName = strdup(CaptureDeviceList[DeviceID]); + al_string_copy_cstr(&Device->DeviceName, CaptureDeviceList[DeviceID]); return ALC_NO_ERROR; failure: diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 3d1f062a..501d2a81 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -23,6 +23,7 @@ #include "atomic.h" #include "uintmap.h" #include "vector.h" +#include "alstring.h" #ifndef ALC_SOFT_HRTF #define ALC_SOFT_HRTF 1 @@ -612,7 +613,7 @@ struct ALCdevice_struct enum DevFmtChannels FmtChans; enum DevFmtType FmtType; - ALCchar *DeviceName; + al_string DeviceName; volatile ALCenum LastError; -- cgit v1.2.3 From 18ab9cbbdd4b8db8e5cd9ea6155efafdb79fcad0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 16 Apr 2014 05:19:34 -0700 Subject: Implement a C11-like thread wrapper and use it in mmdevapi and pulseaudio --- Alc/backends/mmdevapi.c | 16 ++--- Alc/backends/pulseaudio.c | 17 ++--- Alc/helpers.c | 169 ++++++++++++++++++++++++++++++++++++++++++--- OpenAL32/Include/threads.h | 82 ++++++++++++++++++++-- 4 files changed, 250 insertions(+), 34 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index b713e831..75d80749 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -72,7 +72,7 @@ typedef struct { volatile UINT32 Padding; volatile int killNow; - althread_t thread; + althrd_t thread; } MMDevApiData; @@ -212,7 +212,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu } -FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr) +FORCE_ALIGN static int MMDevApiProc(void *ptr) { ALCdevice *device = ptr; MMDevApiData *data = device->ExtraData; @@ -692,7 +692,8 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) if(SUCCEEDED(hr)) { data->render = ptr; - if(!StartThread(&data->thread, MMDevApiProc, device)) + data->killNow = 0; + if(althrd_create(&data->thread, MMDevApiProc, device) != althrd_success) { if(data->render) IAudioRenderClient_Release(data->render); @@ -712,13 +713,12 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) device = (ALCdevice*)msg.lParam; data = device->ExtraData; - if(data->thread) + if(data->render) { - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; + int res; - data->killNow = 0; + data->killNow = 1; + althrd_join(data->thread, &res); IAudioRenderClient_Release(data->render); data->render = NULL; diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index bb371453..6b7b00a3 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -479,7 +479,7 @@ typedef struct ALCpulsePlayback { pa_context *context; volatile ALboolean killNow; - althread_t thread; + althrd_t thread; } ALCpulsePlayback; DECLARE_ALCBACKEND_VTABLE(ALCpulsePlayback); @@ -496,7 +496,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_thr pa_context *context, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap); -static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr); +static int ALCpulsePlayback_mixerProc(void *ptr); static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device); static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, void, Destruct) @@ -751,7 +751,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, } -static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr) +static int ALCpulsePlayback_mixerProc(void *ptr) { ALCpulsePlayback *self = ptr; ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -1051,7 +1051,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) { - if(!StartThread(&self->thread, ALCpulsePlayback_mixerProc, self)) + self->killNow = AL_FALSE; + if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } @@ -1059,17 +1060,13 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) static void ALCpulsePlayback_stop(ALCpulsePlayback *self) { pa_operation *o; + int res; if(!self->stream) return; self->killNow = AL_TRUE; - if(self->thread) - { - StopThread(self->thread); - self->thread = NULL; - } - self->killNow = AL_FALSE; + althrd_join(self->thread, &res); pa_threaded_mainloop_lock(self->loop); diff --git a/Alc/helpers.c b/Alc/helpers.c index dc8eefaf..7e6b59a5 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -309,11 +309,88 @@ void RestoreFPUMode(const FPUCtl *ctl) } +extern inline int althrd_equal(althrd_t thr0, althrd_t thr1); +extern inline void althrd_exit(int res); +extern inline void althrd_yield(void); + extern inline int almtx_lock(almtx_t *mtx); extern inline int almtx_unlock(almtx_t *mtx); extern inline int almtx_trylock(almtx_t *mtx); #ifdef _WIN32 + +#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */ + +typedef struct thread_cntr { + althrd_start_t func; + void *arg; +} thread_cntr; + +static DWORD WINAPI thread_starter(void *arg) +{ + thread_cntr cntr; + memcpy(&cntr, arg, sizeof(cntr)); + free(arg); + + return (DWORD)((*cntr.func)(cntr.arg)); +} + + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg) +{ + thread_cntr *cntr; + DWORD dummy; + HANDLE hdl; + + cntr = malloc(sizeof(*cntr)); + if(!cntr) return althrd_nomem; + + cntr->func = func; + cntr->arg = arg; + + hdl = CreateThread(NULL, THREAD_STACK_SIZE, thread_starter, cntr, 0, &dummy); + if(!hdl) + { + free(cntr); + return althrd_error; + } + + *thr = hdl; + return althrd_success; +} + +int althrd_detach(althrd_t thr) +{ + if(!thr) return althrd_error; + CloseHandle(thr); + + return althrd_success; +} + +int althrd_join(althrd_t thr, int *res) +{ + DWORD code; + + if(!thr) return althrd_error; + + WaitForSingleObject(thr, INFINITE); + GetExitCodeThread(thr, &code); + CloseHandle(thr); + + *res = (int)code; + return althrd_success; +} + +int althrd_sleep(const struct timespec *ts, struct timespec* UNUSED(rem)) +{ + DWORD msec; + msec = ts->tv_sec * 1000; + msec += (ts->tv_nsec+999999) / 1000000; + Sleep(msec); + return 0; +} + + int almtx_init(almtx_t *mtx, int type) { if(!mtx) return althrd_error; @@ -329,16 +406,16 @@ void almtx_destroy(almtx_t *mtx) DeleteCriticalSection(mtx); } -int almtx_timedlock(almtx_t *mtx, const alxtime *xt) +int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { DWORD expire; int ret; - if(!mtx || !xt) + if(!mtx || !ts) return althrd_error; - expire = xt->sec * 1000; - expire += (xt->nsec+999999) / 1000000; + expire = ts->tv_sec * 1000; + expire += (ts->tv_nsec+999999) / 1000000; expire += timeGetTime(); while((ret=almtx_trylock(mtx)) == althrd_busy) @@ -465,6 +542,80 @@ FILE *al_fopen(const char *fname, const char *mode) #include +extern inline althrd_t althrd_current(void); +extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem); + + +#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */ + +typedef struct thread_cntr { + althrd_start_t func; + void *arg; +} thread_cntr; + +static void *thread_starter(void *arg) +{ + thread_cntr cntr; + memcpy(&cntr, arg, sizeof(cntr)); + free(arg); + + return (void*)(intptr_t)((*cntr.func)(cntr.arg)); +} + + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg) +{ + thread_cntr *cntr; + pthread_attr_t attr; + + cntr = malloc(sizeof(*cntr)); + if(!cntr) return althrd_nomem; + + if(pthread_attr_init(&attr) != 0) + { + free(cntr); + return althrd_error; + } + if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0) + { + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; + } + + cntr->func = func; + cntr->arg = arg; + if(pthread_create(thr, &attr, thread_starter, cntr) != 0) + { + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; + } + pthread_attr_destroy(&attr); + + return althrd_success; +} + +int althrd_detach(althrd_t thr) +{ + if(pthread_detach(thr) != 0) + return althrd_error; + return althrd_success; +} + +int althrd_join(althrd_t thr, int *res) +{ + void *code; + + if(!res) return althrd_error; + + if(pthread_join(thr, &code) != 0) + return althrd_error; + *res = (int)(intptr_t)code; + return althrd_success; +} + + int almtx_init(almtx_t *mtx, int type) { int ret; @@ -513,16 +664,12 @@ void almtx_destroy(almtx_t *mtx) pthread_mutex_destroy(mtx); } -int almtx_timedlock(almtx_t *mtx, const alxtime *xt) +int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { - struct timespec ts; - - if(!mtx || !xt) + if(!mtx || !ts) return althrd_error; - ts.tv_sec = xt->sec; - ts.tv_nsec = xt->nsec; - if(pthread_mutex_timedlock(mtx, &ts) != 0) + if(pthread_mutex_timedlock(mtx, ts) != 0) return althrd_busy; return althrd_success; } diff --git a/OpenAL32/Include/threads.h b/OpenAL32/Include/threads.h index 03589d15..8f564cd1 100644 --- a/OpenAL32/Include/threads.h +++ b/OpenAL32/Include/threads.h @@ -1,6 +1,8 @@ #ifndef AL_THREADS_H #define AL_THREADS_H +#include + #include "alMain.h" struct althread_info; @@ -28,18 +30,55 @@ enum { almtx_errorcheck = 8 }; -typedef struct alxtime { - time_t sec; - long nsec; -} alxtime; + +typedef int (*althrd_start_t)(void*); #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +typedef HANDLE althrd_t; typedef CRITICAL_SECTION almtx_t; +#ifndef __MINGW32__ +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif + + +int althrd_sleep(const struct timespec *ts, struct timespec *rem); + + +#if 0 +inline althrd_t althrd_current(void) +{ + /* This is wrong. GetCurrentThread() returns a psuedo-handle of -1 which + * various functions will interpret as the calling thread. There is no + * apparent way to retrieve the same handle that was returned by + * CreateThread. */ + return GetCurrentThread(); +} +#endif + +inline int althrd_equal(althrd_t thr0, althrd_t thr1) +{ + return GetThreadId(thr0) == GetThreadId(thr1); +} + +inline void althrd_exit(int res) +{ + ExitThread(res); +} + +inline void althrd_yield(void) +{ + SwitchToThread(); +} + + inline int almtx_lock(almtx_t *mtx) { if(!mtx) return althrd_error; @@ -67,8 +106,36 @@ inline int almtx_trylock(almtx_t *mtx) #include +typedef pthread_t althrd_t; typedef pthread_mutex_t almtx_t; + +inline althrd_t althrd_current(void) +{ + return pthread_self(); +} + +inline int althrd_equal(althrd_t thr0, althrd_t thr1) +{ + return pthread_equal(thr0, thr1); +} + +inline void althrd_exit(int res) +{ + pthread_exit((void*)(intptr_t)res); +} + +inline void althrd_yield(void) +{ + sched_yield(); +} + +inline int althrd_sleep(const struct timespec *ts, struct timespec *rem) +{ + return nanosleep(ts, rem); +} + + inline int almtx_lock(almtx_t *mtx) { if(!mtx) return althrd_error; @@ -93,8 +160,13 @@ inline int almtx_trylock(almtx_t *mtx) #endif + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg); +int althrd_detach(althrd_t thr); +int althrd_join(althrd_t thr, int *res); + int almtx_init(almtx_t *mtx, int type); void almtx_destroy(almtx_t *mtx); -int almtx_timedlock(almtx_t *mtx, const alxtime *xt); +int almtx_timedlock(almtx_t *mtx, const struct timespec *ts); #endif /* AL_THREADS_H */ -- cgit v1.2.3 From 36df67f546c3162e06964ca6a2466023647c7485 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 17 Apr 2014 20:41:32 -0700 Subject: Rename SetThreadName to althrd_setname --- Alc/backends/alsa.c | 4 ++-- Alc/backends/dsound.c | 2 +- Alc/backends/mmdevapi.c | 2 +- Alc/backends/null.c | 2 +- Alc/backends/oss.c | 4 ++-- Alc/backends/pulseaudio.c | 2 +- Alc/backends/qsa.c | 2 +- Alc/backends/sndio.c | 2 +- Alc/backends/solaris.c | 2 +- Alc/backends/wave.c | 2 +- Alc/backends/winmm.c | 4 ++-- Alc/threads.c | 18 ++++++++++-------- OpenAL32/Include/threads.h | 6 +----- 13 files changed, 25 insertions(+), 27 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 56cbb9ca..70801aa8 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -430,7 +430,7 @@ static int ALCplaybackAlsa_mixerProc(void *ptr) int err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; num_updates = device->NumUpdates; @@ -520,7 +520,7 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) int err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; num_updates = device->NumUpdates; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index ac97e54d..b09208ae 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -196,7 +196,7 @@ FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) HRESULT err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); memset(&DSBCaps, 0, sizeof(DSBCaps)); DSBCaps.dwSize = sizeof(DSBCaps); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 75d80749..54ac6dd6 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -232,7 +232,7 @@ FORCE_ALIGN static int MMDevApiProc(void *ptr) } SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; buffer_len = update_size * device->NumUpdates; diff --git a/Alc/backends/null.c b/Alc/backends/null.c index a96ab701..2c13a80f 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -78,7 +78,7 @@ static int ALCnullBackend_mixerProc(void *ptr) device->Frequency / 2); SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); done = 0; if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 2a4e4dd3..93e026e9 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -107,7 +107,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr) ssize_t wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); @@ -345,7 +345,7 @@ static int ALCcaptureOSS_recordProc(void *ptr) int amt; SetRTPriority(); - SetThreadName("alsoft-record"); + althrd_setname(althrd_current(), "alsoft-record"); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 8bc147a8..97068885 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -761,7 +761,7 @@ static int ALCpulsePlayback_mixerProc(void *ptr) ssize_t len; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); pa_threaded_mainloop_lock(self->loop); frame_size = pa_frame_size(&self->spec); diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index b77a66ad..9258e4e5 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -183,7 +183,7 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) struct timeval timeout; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); /* Increase default 10 priority to 11 to avoid jerky sound */ SchedGet(0, 0, ¶m); diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index cdc052c8..7152b2d6 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -59,7 +59,7 @@ static int sndio_proc(void *ptr) size_t wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 7a8c23d2..20d861d2 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -62,7 +62,7 @@ static int SolarisProc(void *ptr) int wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 343a3cb5..421ca5d7 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -96,7 +96,7 @@ static int WaveProc(void *ptr) const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / device->Frequency / 2); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index acffd2f3..e5b18372 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -192,7 +192,7 @@ FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param) FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); while(GetMessage(&msg, NULL, 0, 0)) { @@ -255,7 +255,7 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param) MSG msg; FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - SetThreadName("alsoft-record"); + althrd_setname(althrd_current(), "alsoft-record"); while(GetMessage(&msg, NULL, 0, 0)) { diff --git a/Alc/threads.c b/Alc/threads.c index e1d071ac..29e177ea 100644 --- a/Alc/threads.c +++ b/Alc/threads.c @@ -29,6 +29,7 @@ #include "alThunk.h" +extern inline althrd_t althrd_current(void); extern inline int althrd_equal(althrd_t thr0, althrd_t thr1); extern inline void althrd_exit(int res); extern inline void althrd_yield(void); @@ -50,7 +51,7 @@ extern inline int altss_set(altss_t tss_id, void *val); #include -void SetThreadName(const char *name) +void althrd_setname(althrd_t thr, const char *name) { #if defined(_MSC_VER) #define MS_VC_EXCEPTION 0x406D1388 @@ -64,7 +65,7 @@ void SetThreadName(const char *name) #pragma pack(pop) info.dwType = 0x1000; info.szName = name; - info.dwThreadID = -1; + info.dwThreadID = ((thr == GetCurrentThread()) ? -1 : GetThreadId(thr)); info.dwFlags = 0; __try { @@ -74,7 +75,7 @@ void SetThreadName(const char *name) } #undef MS_VC_EXCEPTION #else - TRACE("Can't set thread %04lx name to \"%s\"\n", GetCurrentThreadId(), name); + TRACE("Can't set thread %04lx name to \"%s\"\n", GetThreadId(thr), name); #endif } @@ -282,21 +283,22 @@ int altimespec_get(struct timespec *ts, int base) #endif -extern inline althrd_t althrd_current(void); extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem); -void SetThreadName(const char *name) +void althrd_setname(althrd_t thr, const char *name) { #if defined(HAVE_PTHREAD_SETNAME_NP) #if defined(__GNUC__) - if(pthread_setname_np(pthread_self(), name) != 0) + if(pthread_setname_np(thr, name) != 0) #elif defined(__APPLE__) - if(pthread_setname_np(name) != 0) + if(!althrd_equal(thr, althrd_current()) + WARN("Can't set thread name \"%s\" on non-current thread"); + else if(pthread_setname_np(name) != 0) #endif WARN("Failed to set thread name to \"%s\": %s\n", name, strerror(errno)); #elif defined(HAVE_PTHREAD_SET_NAME_NP) - pthread_set_name_np(pthread_self(), name); + pthread_set_name_np(thr, name); #else TRACE("Can't set thread name to \"%s\"\n", name); #endif diff --git a/OpenAL32/Include/threads.h b/OpenAL32/Include/threads.h index 762e5b15..1d9f7640 100644 --- a/OpenAL32/Include/threads.h +++ b/OpenAL32/Include/threads.h @@ -44,7 +44,6 @@ struct timespec { int althrd_sleep(const struct timespec *ts, struct timespec *rem); -#if 0 inline althrd_t althrd_current(void) { /* This is wrong. GetCurrentThread() returns a psuedo-handle of -1 which @@ -53,7 +52,6 @@ inline althrd_t althrd_current(void) * CreateThread. */ return GetCurrentThread(); } -#endif inline int althrd_equal(althrd_t thr0, althrd_t thr1) { @@ -202,6 +200,7 @@ inline int altss_set(altss_t tss_id, void *val) int althrd_create(althrd_t *thr, althrd_start_t func, void *arg); int althrd_detach(althrd_t thr); int althrd_join(althrd_t thr, int *res); +void althrd_setname(althrd_t thr, const char *name); int almtx_init(almtx_t *mtx, int type); void almtx_destroy(almtx_t *mtx); @@ -214,7 +213,4 @@ int altimespec_get(struct timespec *ts, int base); void al_nssleep(time_t sec, long nsec); - -void SetThreadName(const char *name); - #endif /* AL_THREADS_H */ -- cgit v1.2.3 From f6ad3ef221411c8a66931001ef20694dedc81c94 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 22 Apr 2014 06:13:49 -0700 Subject: Use a helper to return mmdevapi message thread responses --- Alc/backends/mmdevapi.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 54ac6dd6..5af500d1 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -104,6 +104,12 @@ typedef struct { #define WM_USER_Enumerate (WM_USER+5) #define WM_USER_Last (WM_USER+5) +static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res) +{ + req->result = res; + SetEvent(req->FinishedEvt); +} + static HRESULT WaitForResponse(ThreadRequest *req) { if(WaitForSingleObject(req->FinishedEvt, INFINITE) == WAIT_OBJECT_0) @@ -592,8 +598,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) if(FAILED(cohr)) { WARN("Failed to initialize COM: 0x%08lx\n", cohr); - req->result = cohr; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, cohr); return 0; } @@ -602,8 +607,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) { WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); CoUninitialize(); - req->result = hr; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, hr); return 0; } Enumerator = ptr; @@ -665,16 +669,15 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) CoUninitialize(); } - req->result = hr; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, hr); continue; case WM_USER_ResetDevice: req = (ThreadRequest*)msg.wParam; device = (ALCdevice*)msg.lParam; - req->result = DoReset(device); - SetEvent(req->FinishedEvt); + hr = DoReset(device); + ReturnMsgResponse(req, hr); continue; case WM_USER_StartDevice: @@ -704,8 +707,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) } } - req->result = hr; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, hr); continue; case WM_USER_StopDevice: @@ -725,8 +727,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) IAudioClient_Stop(data->client); } - req->result = S_OK; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, S_OK); continue; case WM_USER_CloseDevice: @@ -745,8 +746,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) if(--deviceCount == 0) CoUninitialize(); - req->result = S_OK; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, S_OK); continue; case WM_USER_Enumerate: @@ -796,8 +796,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) if(--deviceCount == 0 && SUCCEEDED(cohr)) CoUninitialize(); - req->result = S_OK; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, S_OK); continue; default: -- cgit v1.2.3 From 28e9f0db8c3133e820faa2e3c377abfb8a4ee624 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 24 Apr 2014 04:02:05 -0700 Subject: Use a vector for mmdevapi device lists --- Alc/backends/mmdevapi.c | 170 ++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 93 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 5af500d1..18feab02 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -80,11 +80,24 @@ typedef struct { al_string name; WCHAR *devid; } DevMap; +DECL_VECTOR(DevMap) -static DevMap *PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static DevMap *CaptureDeviceList; -static ALuint NumCaptureDevices; +static void clear_devlist(vector_DevMap *list) +{ + DevMap *iter, *end; + + iter = VECTOR_ITER_BEGIN(*list); + end = VECTOR_ITER_END(*list); + for(;iter != end;iter++) + { + AL_STRING_DEINIT(iter->name); + free(iter->devid); + } + VECTOR_RESIZE(*list, 0); +} + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; static HANDLE ThreadHdl; @@ -144,58 +157,58 @@ static void get_device_name(IMMDevice *device, al_string *name) IPropertyStore_Release(ps); } -static void add_device(IMMDevice *device, DevMap *devmap) +static void add_device(IMMDevice *device, vector_DevMap *list) { LPWSTR devid; HRESULT hr; - AL_STRING_INIT(devmap->name); - hr = IMMDevice_GetId(device, &devid); - if(FAILED(hr)) - devmap->devid = calloc(sizeof(WCHAR), 1); - else + if(SUCCEEDED(hr)) { - devmap->devid = strdupW(devid); - get_device_name(device, &devmap->name); - TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(devmap->name), devmap->devid); + DevMap entry; + AL_STRING_INIT(entry.name); + + entry.devid = strdupW(devid); + get_device_name(device, &entry.name); + CoTaskMemFree(devid); + + TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid); + VECTOR_PUSH_BACK(*list, entry); } } -static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs) +static HRESULT ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; - DevMap *devlist = NULL; HRESULT hr; UINT count; - UINT idx; UINT i; hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); - return NULL; + return hr; } - idx = count = 0; + count = 0; hr = IMMDeviceCollection_GetCount(coll, &count); if(SUCCEEDED(hr) && count > 0) { - devlist = calloc(count+1, sizeof(*devlist)); - if(!devlist) + clear_devlist(list); + if(!VECTOR_RESERVE(*list, count+1)) { IMMDeviceCollection_Release(coll); - return NULL; + return E_OUTOFMEMORY; } hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, eMultimedia, &defdev); } if(SUCCEEDED(hr) && defdev != NULL) - add_device(defdev, &devlist[idx++]); + add_device(defdev, list); for(i = 0;i < count;++i) { @@ -205,7 +218,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu continue; if(device != defdev) - add_device(device, &devlist[idx++]); + add_device(device, list); IMMDevice_Release(device); } @@ -213,8 +226,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu if(defdev) IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); - *numdevs = idx; - return devlist; + return S_OK; } @@ -623,8 +635,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); TRACE("Message thread initialization complete\n"); - req->result = S_OK; - SetEvent(req->FinishedEvt); + ReturnMsgResponse(req, S_OK); TRACE("Starting message loop\n"); while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) @@ -759,35 +770,12 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); if(SUCCEEDED(hr)) { - EDataFlow flowdir; - DevMap **devlist; - ALuint *numdevs; - ALuint i; - Enumerator = ptr; - if(msg.lParam == CAPTURE_DEVICE_PROBE) - { - flowdir = eCapture; - devlist = &CaptureDeviceList; - numdevs = &NumCaptureDevices; - } - else - { - flowdir = eRender; - devlist = &PlaybackDeviceList; - numdevs = &NumPlaybackDevices; - } - for(i = 0;i < *numdevs;i++) - { - AL_STRING_DEINIT((*devlist)[i].name); - free((*devlist)[i].devid); - } - free(*devlist); - *devlist = NULL; - *numdevs = 0; - - *devlist = ProbeDevices(Enumerator, flowdir, numdevs); + if(msg.lParam == ALL_DEVICE_PROBE) + hr = ProbeDevices(Enumerator, eRender, &PlaybackDevices); + else if(msg.lParam == CAPTURE_DEVICE_PROBE) + hr = ProbeDevices(Enumerator, eCapture, &CaptureDevices); IMMDeviceEnumerator_Release(Enumerator); Enumerator = NULL; @@ -796,7 +784,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr) if(--deviceCount == 0 && SUCCEEDED(cohr)) CoUninitialize(); - ReturnMsgResponse(req, S_OK); + ReturnMsgResponse(req, hr); continue; default: @@ -857,9 +845,9 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName { if(deviceName) { - ALuint i; + const DevMap *iter, *end; - if(!PlaybackDeviceList) + if(VECTOR_SIZE(PlaybackDevices) == 0) { ThreadRequest req = { data->MsgEvent, 0 }; if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) @@ -867,11 +855,13 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName } hr = E_FAIL; - for(i = 0;i < NumPlaybackDevices;i++) + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) { - if(al_string_cmp_cstr(PlaybackDeviceList[i].name, deviceName) == 0) + if(al_string_cmp_cstr(iter->name, deviceName) == 0) { - data->devid = strdupW(PlaybackDeviceList[i].devid); + data->devid = strdupW(iter->devid); hr = S_OK; break; } @@ -995,6 +985,9 @@ static const BackendFuncs MMDevApiFuncs = { ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) { + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + if(!MMDevApiLoad()) return ALC_FALSE; *FuncList = MMDevApiFuncs; @@ -1003,25 +996,11 @@ ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) void alcMMDevApiDeinit(void) { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) - { - AL_STRING_DEINIT(PlaybackDeviceList[i].name); - free(PlaybackDeviceList[i].devid); - } - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - NumPlaybackDevices = 0; - - for(i = 0;i < NumCaptureDevices;i++) - { - AL_STRING_DEINIT(CaptureDeviceList[i].name); - free(CaptureDeviceList[i].devid); - } - free(CaptureDeviceList); - CaptureDeviceList = NULL; - NumCaptureDevices = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); if(ThreadHdl) { @@ -1035,28 +1014,33 @@ void alcMMDevApiDeinit(void) void alcMMDevApiProbe(enum DevProbe type) { ThreadRequest req = { NULL, 0 }; + const DevMap *iter, *end; HRESULT hr = E_FAIL; - switch(type) + req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); + if(req.FinishedEvt == NULL) + ERR("Failed to create event: %lu\n", GetLastError()); + else { + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) + hr = WaitForResponse(&req); + if(SUCCEEDED(hr)) switch(type) + { case ALL_DEVICE_PROBE: - req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); - if(req.FinishedEvt == NULL) - ERR("Failed to create event: %lu\n", GetLastError()); - else if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) - hr = WaitForResponse(&req); - if(SUCCEEDED(hr)) - { - ALuint i; - for(i = 0;i < NumPlaybackDevices;i++) - AppendAllDevicesList(al_string_get_cstr(PlaybackDeviceList[i].name)); - } + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) + AppendAllDevicesList(al_string_get_cstr(iter->name)); break; case CAPTURE_DEVICE_PROBE: + iter = VECTOR_ITER_BEGIN(CaptureDevices); + end = VECTOR_ITER_END(CaptureDevices); + for(;iter != end;iter++) + AppendCaptureDeviceList(al_string_get_cstr(iter->name)); break; - } - if(req.FinishedEvt != NULL) + } CloseHandle(req.FinishedEvt); - req.FinishedEvt = NULL; + req.FinishedEvt = NULL; + } } -- cgit v1.2.3 From 149df6d4db8c5c4a4dc926c395fbb7c77d79ab74 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 25 Apr 2014 09:26:53 -0700 Subject: Convert the mmdevapi backend to the new backend API --- Alc/ALc.c | 2 +- Alc/backends/base.h | 1 + Alc/backends/mmdevapi.c | 974 ++++++++++++++++++++++++++-------------------- OpenAL32/Include/alMain.h | 3 - 4 files changed, 547 insertions(+), 433 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/ALc.c b/Alc/ALc.c index f0f5ced7..5114942c 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -83,7 +83,7 @@ static struct BackendInfo BackendList[] = { { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, #endif #ifdef HAVE_MMDEVAPI - { "mmdevapi", NULL, alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, + { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_DSOUND { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 9db6e19d..5573c178 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -123,6 +123,7 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ ALCbackendFactory *ALCpulseBackendFactory_getFactory(void); ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 18feab02..968b73ff 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -44,6 +44,8 @@ #include "compat.h" #include "alstring.h" +#include "backends/base.h" + DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); @@ -59,23 +61,6 @@ DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) -typedef struct { - WCHAR *devid; - - IMMDevice *mmdev; - IAudioClient *client; - IAudioRenderClient *render; - HANDLE NotifyEvent; - - HANDLE MsgEvent; - - volatile UINT32 Padding; - - volatile int killNow; - althrd_t thread; -} MMDevApiData; - - typedef struct { al_string name; WCHAR *devid; @@ -178,7 +163,7 @@ static void add_device(IMMDevice *device, vector_DevMap *list) } } -static HRESULT ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) +static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; @@ -230,10 +215,242 @@ static HRESULT ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vec } -FORCE_ALIGN static int MMDevApiProc(void *ptr) +/* Proxy interface used by the message handler. */ +struct ALCmmdevProxyVtable; + +typedef struct ALCmmdevProxy { + const struct ALCmmdevProxyVtable *vtbl; +} ALCmmdevProxy; + +struct ALCmmdevProxyVtable { + HRESULT (*const openProxy)(ALCmmdevProxy*); + void (*const closeProxy)(ALCmmdevProxy*); + + HRESULT (*const resetProxy)(ALCmmdevProxy*); + HRESULT (*const startProxy)(ALCmmdevProxy*); + void (*const stopProxy)(ALCmmdevProxy*); +}; + +#define DEFINE_ALCMMDEVPROXY_VTABLE(T) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, openProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, void, closeProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, resetProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, startProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, void, stopProxy) \ + \ +static const struct ALCmmdevProxyVtable T##_ALCmmdevProxy_vtable = { \ + T##_ALCmmdevProxy_openProxy, \ + T##_ALCmmdevProxy_closeProxy, \ + T##_ALCmmdevProxy_resetProxy, \ + T##_ALCmmdevProxy_startProxy, \ + T##_ALCmmdevProxy_stopProxy, \ +} + +static void ALCmmdevProxy_Construct(ALCmmdevProxy* UNUSED(self)) { } +static void ALCmmdevProxy_Destruct(ALCmmdevProxy* UNUSED(self)) { } + +static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr) +{ + ThreadRequest *req = ptr; + IMMDeviceEnumerator *Enumerator; + ALuint deviceCount = 0; + ALCmmdevProxy *proxy; + HRESULT hr, cohr; + MSG msg; + + TRACE("Starting message thread\n"); + + cohr = CoInitialize(NULL); + if(FAILED(cohr)) + { + WARN("Failed to initialize COM: 0x%08lx\n", cohr); + ReturnMsgResponse(req, cohr); + return 0; + } + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(FAILED(hr)) + { + WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); + CoUninitialize(); + ReturnMsgResponse(req, hr); + return 0; + } + Enumerator = ptr; + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + + CoUninitialize(); + + /* HACK: Force Windows to create a message queue for this thread before + * returning success, otherwise PostThreadMessage may fail if it gets + * called before GetMessage. + */ + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + TRACE("Message thread initialization complete\n"); + ReturnMsgResponse(req, S_OK); + + TRACE("Starting message loop\n"); + while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) + { + TRACE("Got message %u\n", msg.message); + switch(msg.message) + { + case WM_USER_OpenDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = V0(proxy,openProxy)(); + if(FAILED(hr)) + { + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + } + + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_ResetDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = V0(proxy,resetProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StartDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = V0(proxy,startProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StopDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + V0(proxy,stopProxy)(); + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_CloseDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + V0(proxy,closeProxy)(); + if(--deviceCount == 0) + CoUninitialize(); + + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_Enumerate: + req = (ThreadRequest*)msg.wParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + Enumerator = ptr; + + if(msg.lParam == ALL_DEVICE_PROBE) + hr = probe_devices(Enumerator, eRender, &PlaybackDevices); + else if(msg.lParam == CAPTURE_DEVICE_PROBE) + hr = probe_devices(Enumerator, eCapture, &CaptureDevices); + + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + + ReturnMsgResponse(req, hr); + continue; + + default: + ERR("Unexpected message: %u\n", msg.message); + continue; + } + } + TRACE("Message loop finished\n"); + + return 0; +} + + +typedef struct ALCmmdevPlayback { + DERIVE_FROM_TYPE(ALCbackend); + DERIVE_FROM_TYPE(ALCmmdevProxy); + + WCHAR *devid; + + IMMDevice *mmdev; + IAudioClient *client; + IAudioRenderClient *render; + HANDLE NotifyEvent; + + HANDLE MsgEvent; + + volatile UINT32 Padding; + + volatile int killNow; + althrd_t thread; +} ALCmmdevPlayback; + +static int ALCmmdevPlayback_mixerProc(void *arg); + +static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device); +static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self); +static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *name); +static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_close(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self); +static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self); +static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self); +static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self); +static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self); +static DECLARE_FORWARD2(ALCmmdevPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) +static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, ALCuint, availableSamples) +static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self); +static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCmmdevPlayback) + +DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevPlayback); +DEFINE_ALCBACKEND_VTABLE(ALCmmdevPlayback); + + +static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device) +{ + SET_VTABLE2(ALCmmdevPlayback, ALCbackend, self); + SET_VTABLE2(ALCmmdevPlayback, ALCmmdevProxy, self); + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); +} + +static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) +{ + ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) { - ALCdevice *device = ptr; - MMDevApiData *data = device->ExtraData; + ALCmmdevPlayback *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; UINT32 buffer_len, written; ALuint update_size, len; BYTE *buffer; @@ -246,7 +463,7 @@ FORCE_ALIGN static int MMDevApiProc(void *ptr) ALCdevice_Lock(device); aluHandleDisconnect(device); ALCdevice_Unlock(device); - return 0; + return 1; } SetRTPriority(); @@ -254,9 +471,9 @@ FORCE_ALIGN static int MMDevApiProc(void *ptr) update_size = device->UpdateSize; buffer_len = update_size * device->NumUpdates; - while(!data->killNow) + while(!self->killNow) { - hr = IAudioClient_GetCurrentPadding(data->client, &written); + hr = IAudioClient_GetCurrentPadding(self->client, &written); if(FAILED(hr)) { ERR("Failed to get padding: 0x%08lx\n", hr); @@ -265,27 +482,27 @@ FORCE_ALIGN static int MMDevApiProc(void *ptr) ALCdevice_Unlock(device); break; } - data->Padding = written; + self->Padding = written; len = buffer_len - written; if(len < update_size) { DWORD res; - res = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE); + res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); if(res != WAIT_OBJECT_0) ERR("WaitForSingleObjectEx error: 0x%lx\n", res); continue; } len -= len%update_size; - hr = IAudioRenderClient_GetBuffer(data->render, len, &buffer); + hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); if(SUCCEEDED(hr)) { ALCdevice_Lock(device); aluMixData(device, buffer, len); - data->Padding = written + len; + self->Padding = written + len; ALCdevice_Unlock(device); - hr = IAudioRenderClient_ReleaseBuffer(data->render, len, 0); + hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); } if(FAILED(hr)) { @@ -296,7 +513,7 @@ FORCE_ALIGN static int MMDevApiProc(void *ptr) break; } } - data->Padding = 0; + self->Padding = 0; CoUninitialize(); return 0; @@ -342,64 +559,213 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX * return ALC_TRUE; } -static HRESULT DoReset(ALCdevice *device) + +static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) { - MMDevApiData *data = device->ExtraData; - WAVEFORMATEXTENSIBLE OutputType; - WAVEFORMATEX *wfx = NULL; - REFERENCE_TIME min_per, buf_time; - UINT32 buffer_len, min_len; - void *ptr = NULL; - HRESULT hr; + HRESULT hr = S_OK; - if(data->client) - IAudioClient_Release(data->client); - data->client = NULL; + self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL || self->MsgEvent == NULL) + { + ERR("Failed to create message events: %lu\n", GetLastError()); + hr = E_FAIL; + } - hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(FAILED(hr)) + if(SUCCEEDED(hr)) { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); - return hr; + if(deviceName) + { + const DevMap *iter, *end; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) + (void)WaitForResponse(&req); + } + + hr = E_FAIL; + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) + { + if(al_string_cmp_cstr(iter->name, deviceName) == 0) + { + self->devid = strdupW(iter->devid); + hr = S_OK; + break; + } + } + if(FAILED(hr)) + WARN("Failed to find device name matching \"%s\"\n", deviceName); + } } - data->client = ptr; - hr = IAudioClient_GetMixFormat(data->client, &wfx); - if(FAILED(hr)) + if(SUCCEEDED(hr)) { - ERR("Failed to get mix format: 0x%08lx\n", hr); - return hr; + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); } - if(!MakeExtensible(&OutputType, wfx)) + if(FAILED(hr)) { - CoTaskMemFree(wfx); - return E_FAIL; + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ERR("Device init failed: 0x%08lx\n", hr); + return ALC_INVALID_VALUE; } - CoTaskMemFree(wfx); - wfx = NULL; - buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + - device->Frequency-1) / device->Frequency; + return ALC_NO_ERROR; +} - if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) - device->Frequency = OutputType.Format.nSamplesPerSec; - if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) +static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + void *ptr; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) { - if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) - device->FmtChans = DevFmtMono; - else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) - device->FmtChans = DevFmtStereo; - else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) - device->FmtChans = DevFmtQuad; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) - device->FmtChans = DevFmtX51; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) - device->FmtChans = DevFmtX51Side; - else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) - device->FmtChans = DevFmtX61; - else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) - device->FmtChans = DevFmtX71; + IMMDeviceEnumerator *Enumerator = ptr; + if(!self->devid) + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &self->mmdev); + else + hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + if(SUCCEEDED(hr)) + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(SUCCEEDED(hr)) + { + self->client = ptr; + get_device_name(self->mmdev, &device->DeviceName); + } + + if(FAILED(hr)) + { + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; + } + + return hr; +} + + +static void ALCmmdevPlayback_close(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + free(self->devid); + self->devid = NULL; +} + +static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self) +{ + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; +} + + +static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + WAVEFORMATEXTENSIBLE OutputType; + WAVEFORMATEX *wfx = NULL; + REFERENCE_TIME min_per, buf_time; + UINT32 buffer_len, min_len; + void *ptr = NULL; + HRESULT hr; + + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + self->client = ptr; + + hr = IAudioClient_GetMixFormat(self->client, &wfx); + if(FAILED(hr)) + { + ERR("Failed to get mix format: 0x%08lx\n", hr); + return hr; + } + + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } + CoTaskMemFree(wfx); + wfx = NULL; + + buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + + device->Frequency-1) / device->Frequency; + + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) + device->Frequency = OutputType.Format.nSamplesPerSec; + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) + { + if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) + device->FmtChans = DevFmtMono; + else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) + device->FmtChans = DevFmtStereo; + else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) + device->FmtChans = DevFmtQuad; + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) + device->FmtChans = DevFmtX51; + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) + device->FmtChans = DevFmtX51Side; + else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) + device->FmtChans = DevFmtX61; + else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) + device->FmtChans = DevFmtX71; else ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); } @@ -474,11 +840,11 @@ static HRESULT DoReset(ALCdevice *device) OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * OutputType.Format.nBlockAlign; - hr = IAudioClient_IsFormatSupported(data->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + hr = IAudioClient_IsFormatSupported(self->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); if(FAILED(hr)) { ERR("Failed to check format support: 0x%08lx\n", hr); - hr = IAudioClient_GetMixFormat(data->client, &wfx); + hr = IAudioClient_GetMixFormat(self->client, &wfx); } if(FAILED(hr)) { @@ -550,7 +916,7 @@ static HRESULT DoReset(ALCdevice *device) SetDefaultWFXChannelOrder(device); - hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED, + hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time, 0, &OutputType.Format, NULL); if(FAILED(hr)) @@ -559,14 +925,14 @@ static HRESULT DoReset(ALCdevice *device) return hr; } - hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL); + hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL); if(SUCCEEDED(hr)) { min_len = (UINT32)((min_per*device->Frequency + 10000000-1) / 10000000); /* Find the nearest multiple of the period size to the update size */ if(min_len < device->UpdateSize) min_len *= (device->UpdateSize + min_len/2)/min_len; - hr = IAudioClient_GetBufferSize(data->client, &buffer_len); + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); } if(FAILED(hr)) { @@ -583,7 +949,7 @@ static HRESULT DoReset(ALCdevice *device) device->UpdateSize = buffer_len / device->NumUpdates; } - hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent); + hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); if(FAILED(hr)) { ERR("Failed to set event handle: 0x%08lx\n", hr); @@ -594,208 +960,90 @@ static HRESULT DoReset(ALCdevice *device) } -static DWORD CALLBACK MMDevApiMsgProc(void *ptr) +static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self) { - ThreadRequest *req = ptr; - IMMDeviceEnumerator *Enumerator; - ALuint deviceCount = 0; - MMDevApiData *data; - ALCdevice *device; - HRESULT hr, cohr; - MSG msg; - - TRACE("Starting message thread\n"); - - cohr = CoInitialize(NULL); - if(FAILED(cohr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", cohr); - ReturnMsgResponse(req, cohr); - return 0; - } + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(FAILED(hr)) - { - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - CoUninitialize(); - ReturnMsgResponse(req, hr); - return 0; - } - Enumerator = ptr; - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; + if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); - CoUninitialize(); + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} - /* HACK: Force Windows to create a message queue for this thread before - * returning success, otherwise PostThreadMessage may fail if it gets - * called before GetMessage. - */ - PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); +static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self) +{ + HRESULT hr; + void *ptr; - TRACE("Message thread initialization complete\n"); - ReturnMsgResponse(req, S_OK); + ResetEvent(self->NotifyEvent); + hr = IAudioClient_Start(self->client); + if(FAILED(hr)) + ERR("Failed to start audio client: 0x%08lx\n", hr); - TRACE("Starting message loop\n"); - while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) + if(SUCCEEDED(hr)) + hr = IAudioClient_GetService(self->client, &IID_IAudioRenderClient, &ptr); + if(SUCCEEDED(hr)) { - TRACE("Got message %u\n", msg.message); - switch(msg.message) + self->render = ptr; + self->killNow = 0; + if(althrd_create(&self->thread, ALCmmdevPlayback_mixerProc, self) != althrd_success) { - case WM_USER_OpenDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - hr = cohr = S_OK; - if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); - if(SUCCEEDED(hr)) - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - Enumerator = ptr; - if(!data->devid) - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev); - else - hr = IMMDeviceEnumerator_GetDevice(Enumerator, data->devid, &data->mmdev); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - if(SUCCEEDED(hr)) - hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(SUCCEEDED(hr)) - { - data->client = ptr; - get_device_name(data->mmdev, &device->DeviceName); - } - - if(FAILED(hr)) - { - if(data->mmdev) - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - } - - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_ResetDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - - hr = DoReset(device); - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_StartDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - ResetEvent(data->NotifyEvent); - hr = IAudioClient_Start(data->client); - if(FAILED(hr)) - ERR("Failed to start audio client: 0x%08lx\n", hr); - - if(SUCCEEDED(hr)) - hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr); - if(SUCCEEDED(hr)) - { - data->render = ptr; - data->killNow = 0; - if(althrd_create(&data->thread, MMDevApiProc, device) != althrd_success) - { - if(data->render) - IAudioRenderClient_Release(data->render); - data->render = NULL; - IAudioClient_Stop(data->client); - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - } - - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_StopDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - if(data->render) - { - int res; - - data->killNow = 1; - althrd_join(data->thread, &res); - - IAudioRenderClient_Release(data->render); - data->render = NULL; - IAudioClient_Stop(data->client); - } - - ReturnMsgResponse(req, S_OK); - continue; + if(self->render) + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); + ERR("Failed to start thread\n"); + hr = E_FAIL; + } + } - case WM_USER_CloseDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; + return hr; +} - if(data->client) - IAudioClient_Release(data->client); - data->client = NULL; - if(data->mmdev) - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; +static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); +} - if(--deviceCount == 0) - CoUninitialize(); +static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self) +{ + int res; - ReturnMsgResponse(req, S_OK); - continue; + if(!self->render) + return; - case WM_USER_Enumerate: - req = (ThreadRequest*)msg.wParam; + self->killNow = 1; + althrd_join(self->thread, &res); - hr = cohr = S_OK; - if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); - if(SUCCEEDED(hr)) - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - Enumerator = ptr; + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); +} - if(msg.lParam == ALL_DEVICE_PROBE) - hr = ProbeDevices(Enumerator, eRender, &PlaybackDevices); - else if(msg.lParam == CAPTURE_DEVICE_PROBE) - hr = ProbeDevices(Enumerator, eCapture, &CaptureDevices); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } +static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return (ALint64)self->Padding * 1000000000 / device->Frequency; +} - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - ReturnMsgResponse(req, hr); - continue; +typedef struct ALCmmdevBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCmmdevBackendFactory; +#define ALCMMDEVBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCmmdevBackendFactory, ALCbackendFactory) } } - default: - ERR("Unexpected message: %u\n", msg.message); - continue; - } - } - TRACE("Message loop finished\n"); +static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory *self); +static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory *self); +static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory *self, ALCbackend_Type type); +static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory *self, ALCdevice *device, ALCbackend_Type type); - return 0; -} +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCmmdevBackendFactory); static BOOL MMDevApiLoad(void) @@ -811,7 +1059,7 @@ static BOOL MMDevApiLoad(void) ERR("Failed to create event: %lu\n", GetLastError()); else { - ThreadHdl = CreateThread(NULL, 0, MMDevApiMsgProc, &req, 0, &ThreadID); + ThreadHdl = CreateThread(NULL, 0, ALCmmdevProxy_messageHandler, &req, 0, &ThreadID); if(ThreadHdl != NULL) InitResult = WaitForResponse(&req); CloseHandle(req.FinishedEvt); @@ -820,181 +1068,17 @@ static BOOL MMDevApiLoad(void) return SUCCEEDED(InitResult); } - -static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName) -{ - MMDevApiData *data = NULL; - HRESULT hr; - - //Initialise requested device - data = calloc(1, sizeof(MMDevApiData)); - if(!data) - return ALC_OUT_OF_MEMORY; - device->ExtraData = data; - - hr = S_OK; - data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->NotifyEvent == NULL || data->MsgEvent == NULL) - { - ERR("Failed to create message events: %lu\n", GetLastError()); - hr = E_FAIL; - } - - if(SUCCEEDED(hr)) - { - if(deviceName) - { - const DevMap *iter, *end; - - if(VECTOR_SIZE(PlaybackDevices) == 0) - { - ThreadRequest req = { data->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) - (void)WaitForResponse(&req); - } - - hr = E_FAIL; - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;iter++) - { - if(al_string_cmp_cstr(iter->name, deviceName) == 0) - { - data->devid = strdupW(iter->devid); - hr = S_OK; - break; - } - } - if(FAILED(hr)) - WARN("Failed to find device name matching \"%s\"\n", deviceName); - } - } - - if(SUCCEEDED(hr)) - { - ThreadRequest req = { data->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - else - ERR("Failed to post thread message: %lu\n", GetLastError()); - } - - if(FAILED(hr)) - { - if(data->NotifyEvent != NULL) - CloseHandle(data->NotifyEvent); - data->NotifyEvent = NULL; - if(data->MsgEvent != NULL) - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - free(data->devid); - data->devid = NULL; - - free(data); - device->ExtraData = NULL; - - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; - } - - return ALC_NO_ERROR; -} - -static void MMDevApiClosePlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); - - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - CloseHandle(data->NotifyEvent); - data->NotifyEvent = NULL; - - free(data->devid); - data->devid = NULL; - - free(data); - device->ExtraData = NULL; -} - -static ALCboolean MMDevApiResetPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static ALCboolean MMDevApiStartPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static void MMDevApiStopPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); -} - - -static ALint64 MMDevApiGetLatency(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - - return (ALint64)data->Padding * 1000000000 / device->Frequency; -} - - -static const BackendFuncs MMDevApiFuncs = { - MMDevApiOpenPlayback, - MMDevApiClosePlayback, - MMDevApiResetPlayback, - MMDevApiStartPlayback, - MMDevApiStopPlayback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MMDevApiGetLatency -}; - - -ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) +static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory* UNUSED(self)) { VECTOR_INIT(PlaybackDevices); VECTOR_INIT(CaptureDevices); if(!MMDevApiLoad()) return ALC_FALSE; - *FuncList = MMDevApiFuncs; return ALC_TRUE; } -void alcMMDevApiDeinit(void) +static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self)) { clear_devlist(&PlaybackDevices); VECTOR_DEINIT(PlaybackDevices); @@ -1011,7 +1095,14 @@ void alcMMDevApiDeinit(void) } } -void alcMMDevApiProbe(enum DevProbe type) +static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type) { ThreadRequest req = { NULL, 0 }; const DevMap *iter, *end; @@ -1044,3 +1135,28 @@ void alcMMDevApiProbe(enum DevProbe type) req.FinishedEvt = NULL; } } + +static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCmmdevPlayback *backend; + + backend = ALCmmdevPlayback_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCmmdevPlayback_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + + +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void) +{ + static ALCmmdevBackendFactory factory = ALCMMDEVBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 1838fb09..5af33a3a 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -503,9 +503,6 @@ void alc_solaris_probe(enum DevProbe type); ALCboolean alc_sndio_init(BackendFuncs *func_list); void alc_sndio_deinit(void); void alc_sndio_probe(enum DevProbe type); -ALCboolean alcMMDevApiInit(BackendFuncs *func_list); -void alcMMDevApiDeinit(void); -void alcMMDevApiProbe(enum DevProbe type); ALCboolean alcWinMMInit(BackendFuncs *FuncList); void alcWinMMDeinit(void); void alcWinMMProbe(enum DevProbe type); -- cgit v1.2.3 From f15067687326baa4ffe479e13411dbe588242e70 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 30 Apr 2014 12:30:02 -0700 Subject: Add a helper VECTOR_FOR_EACH macro --- Alc/backends/alsa.c | 17 +++++++---------- Alc/backends/dsound.c | 16 +++++++--------- Alc/backends/mmdevapi.c | 18 ++++++++---------- Alc/backends/pulseaudio.c | 17 +++++++---------- Alc/backends/winmm.c | 29 +++++++++++++---------------- Alc/vector.h | 7 +++++++ 6 files changed, 49 insertions(+), 55 deletions(-) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 4cade858..749db892 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1302,6 +1302,11 @@ static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self) } +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + typedef struct ALCalsaBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCalsaBackendFactory; @@ -1341,24 +1346,16 @@ static ALCboolean ALCalsaBackendFactory_querySupport(ALCalsaBackendFactory* UNUS static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type) { - DevMap *iter, *end; - switch(type) { case ALL_DEVICE_PROBE: probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;iter++) - AppendAllDevicesList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); - iter = VECTOR_ITER_BEGIN(CaptureDevices); - end = VECTOR_ITER_END(CaptureDevices); - for(;iter != end;iter++) - AppendCaptureDeviceList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 12ea8103..3ca398ed 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -950,6 +950,11 @@ done: } +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + typedef struct ALCdsoundBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCdsoundBackendFactory; @@ -1006,7 +1011,6 @@ static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory* static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type) { - DevMap *iter, *end; HRESULT hr, hrcom; /* Initialize COM to prevent name truncation */ @@ -1018,10 +1022,7 @@ static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;++iter) - AppendAllDevicesList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: @@ -1029,10 +1030,7 @@ static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); - iter = VECTOR_ITER_BEGIN(CaptureDevices); - end = VECTOR_ITER_END(CaptureDevices); - for(;iter != end;++iter) - AppendCaptureDeviceList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } if(SUCCEEDED(hrcom)) diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 968b73ff..4061105c 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1032,6 +1032,11 @@ static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self) } +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + typedef struct ALCmmdevBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCmmdevBackendFactory; @@ -1105,30 +1110,23 @@ static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UN static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type) { ThreadRequest req = { NULL, 0 }; - const DevMap *iter, *end; - HRESULT hr = E_FAIL; req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); if(req.FinishedEvt == NULL) ERR("Failed to create event: %lu\n", GetLastError()); else { + HRESULT hr = E_FAIL; if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) hr = WaitForResponse(&req); if(SUCCEEDED(hr)) switch(type) { case ALL_DEVICE_PROBE: - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;iter++) - AppendAllDevicesList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: - iter = VECTOR_ITER_BEGIN(CaptureDevices); - end = VECTOR_ITER_END(CaptureDevices); - for(;iter != end;iter++) - AppendCaptureDeviceList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } CloseHandle(req.FinishedEvt); diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index d1472c7d..f71f9ec9 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1617,6 +1617,11 @@ static void ALCpulseCapture_unlock(ALCpulseCapture *self) } +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + typedef struct ALCpulseBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCpulseBackendFactory; @@ -1702,24 +1707,16 @@ static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UN static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type) { - DevMap *iter, *end; - switch(type) { case ALL_DEVICE_PROBE: ALCpulsePlayback_probeDevices(); - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;iter++) - AppendAllDevicesList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: ALCpulseCapture_probeDevices(); - iter = VECTOR_ITER_BEGIN(CaptureDevices); - end = VECTOR_ITER_END(CaptureDevices); - for(;iter != end;iter++) - AppendCaptureDeviceList(al_string_get_cstr(iter->name)); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } } diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index d274a81c..2f01ffdf 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -659,6 +659,17 @@ static ALCuint WinMMAvailableSamples(ALCdevice *Device) } +static inline void AppendAllDevicesList2(const al_string *name) +{ + if(!al_string_empty(*name)) + AppendAllDevicesList(al_string_get_cstr(*name)); +} +static inline void AppendCaptureDeviceList2(const al_string *name) +{ + if(!al_string_empty(*name)) + AppendCaptureDeviceList(al_string_get_cstr(*name)); +} + static const BackendFuncs WinMMFuncs = { WinMMOpenPlayback, WinMMClosePlayback, @@ -694,30 +705,16 @@ void alcWinMMDeinit() void alcWinMMProbe(enum DevProbe type) { - const al_string *iter, *end; - switch(type) { case ALL_DEVICE_PROBE: ProbePlaybackDevices(); - iter = VECTOR_ITER_BEGIN(PlaybackDevices); - end = VECTOR_ITER_END(PlaybackDevices); - for(;iter != end;iter++) - { - if(!al_string_empty(*iter)) - AppendAllDevicesList(al_string_get_cstr(*iter)); - } + VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: ProbeCaptureDevices(); - iter = VECTOR_ITER_BEGIN(CaptureDevices); - end = VECTOR_ITER_END(CaptureDevices); - for(;iter != end;iter++) - { - if(!al_string_empty(*iter)) - AppendCaptureDeviceList(al_string_get_cstr(*iter)); - } + VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2); break; } } diff --git a/Alc/vector.h b/Alc/vector.h index 242c5fa5..b4a843d5 100644 --- a/Alc/vector.h +++ b/Alc/vector.h @@ -59,4 +59,11 @@ ALboolean vector_insert(void *ptr, size_t base_size, size_t obj_size, void *ins_ #define VECTOR_ELEM(_x, _o) ((_x)->Data[(_o)]) +#define VECTOR_FOR_EACH(_t, _x, _f) do { \ + _t *_iter = VECTOR_ITER_BEGIN((_x)); \ + _t *_end = VECTOR_ITER_END((_x)); \ + for(;_iter != _end;++_iter) \ + (_f)(_iter); \ +} while(0) + #endif /* AL_VECTOR_H */ -- cgit v1.2.3 From 3bdb3f9db7e37fc81a0b72a39c2c248000add53f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 May 2014 10:47:31 -0700 Subject: Iniitialize some mmdevapi backend fields in the constructor --- Alc/backends/mmdevapi.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'Alc/backends/mmdevapi.c') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 4061105c..d732c3e1 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -438,10 +438,33 @@ static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device SET_VTABLE2(ALCmmdevPlayback, ALCmmdevProxy, self); ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); + + self->devid = NULL; + + self->mmdev = NULL; + self->client = NULL; + self->render = NULL; + self->NotifyEvent = NULL; + + self->MsgEvent = NULL; + + self->Padding = 0; + + self->killNow = 0; } static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) { + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } -- cgit v1.2.3