aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/backends')
-rw-r--r--Alc/backends/mmdevapi.c169
1 files changed, 68 insertions, 101 deletions
diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c
index 082d18a4..52b54eb4 100644
--- a/Alc/backends/mmdevapi.c
+++ b/Alc/backends/mmdevapi.c
@@ -55,7 +55,8 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0
typedef struct {
- GUID guid;
+ WCHAR *devid;
+
IMMDevice *mmdev;
IAudioClient *client;
IAudioRenderClient *render;
@@ -70,7 +71,7 @@ typedef struct {
typedef struct {
ALCchar *name;
- GUID guid;
+ LPWSTR devid;
} DevMap;
static DevMap *PlaybackDeviceList;
@@ -102,72 +103,10 @@ static HRESULT WaitForResponse(ThreadRequest *req)
}
-static HRESULT get_mmdevice_by_guid(IMMDeviceEnumerator *devenum, EDataFlow flowdir, const GUID *guid, IMMDevice **out)
-{
- IMMDeviceCollection *coll;
- UINT count, i;
- HRESULT hr;
-
- hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll);
- if(FAILED(hr))
- {
- ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr);
- return hr;
- }
-
- count = 0;
- IMMDeviceCollection_GetCount(coll, &count);
- for(i = 0;i < count;++i)
- {
- IMMDevice *device;
- IPropertyStore *ps;
- PROPVARIANT pv;
- GUID devid;
-
- if(FAILED(IMMDeviceCollection_Item(coll, i, &device)))
- continue;
-
- hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
- if(FAILED(hr))
- {
- WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
- continue;
- }
-
- PropVariantInit(&pv);
-
- hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pv);
- if(FAILED(hr))
- {
- PropVariantClear(&pv);
- IPropertyStore_Release(ps);
- WARN("GetValue failed: 0x%08lx\n", hr);
- continue;
- }
- CLSIDFromString(pv.pwszVal, &devid);
-
- PropVariantClear(&pv);
- IPropertyStore_Release(ps);
-
- if(IsEqualGUID(&devid, guid))
- {
- *out = device;
- break;
- }
-
- IMMDevice_Release(device);
- }
- hr = ((i==count) ? E_FAIL : S_OK);
-
- IMMDeviceCollection_Release(coll);
- return hr;
-}
-
-
-static void add_device(IMMDevice *device, DevMap *devmap)
+static ALCchar *get_device_name(IMMDevice *device)
{
+ ALCchar *name = NULL;
IPropertyStore *ps;
- PROPVARIANT pvguid;
PROPVARIANT pvname;
HRESULT hr;
int len;
@@ -176,38 +115,41 @@ static void add_device(IMMDevice *device, DevMap *devmap)
if(FAILED(hr))
{
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
- return;
+ return calloc(1, 1);
}
- PropVariantInit(&pvguid);
PropVariantInit(&pvname);
- hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pvguid);
+ hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
if(FAILED(hr))
- WARN("GetValue failed: 0x%08lx\n", hr);
- else
{
- hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
- if(FAILED(hr))
- WARN("GetValue failed: 0x%08lx\n", hr);
- }
- if(SUCCEEDED(hr))
- {
- TRACE("Got device \"%ls\", GUID \"%ls\"\n", pvname.pwszVal, pvguid.pwszVal);
- hr = CLSIDFromString(pvguid.pwszVal, &devmap->guid);
+ WARN("GetValue failed: 0x%08lx\n", hr);
+ name = calloc(1, 1);
}
- if(SUCCEEDED(hr))
+ else
{
if((len=WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, NULL, 0, NULL, NULL)) > 0)
{
- devmap->name = calloc(1, len);
- WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, devmap->name, len, NULL, NULL);
+ name = calloc(1, len);
+ WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, name, len, NULL, NULL);
}
}
PropVariantClear(&pvname);
- PropVariantClear(&pvguid);
IPropertyStore_Release(ps);
+
+ return name;
+}
+
+static void add_device(IMMDevice *device, DevMap *devmap)
+{
+ HRESULT hr;
+ hr = IMMDevice_GetId(device, &devmap->devid);
+ if(SUCCEEDED(hr))
+ {
+ devmap->name = get_device_name(device);
+ TRACE("Got device \"%s\", \"%ls\"\n", devmap->name, devmap->devid);
+ }
}
static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs)
@@ -678,14 +620,20 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
if(SUCCEEDED(hr))
{
Enumerator = ptr;
- hr = get_mmdevice_by_guid(Enumerator, eRender, &data->guid, &data->mmdev);
+ 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;
+ device->szDeviceName = get_device_name(data->mmdev);
+ }
if(FAILED(hr))
{
@@ -778,7 +726,10 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
}
for(i = 0;i < *numdevs;i++)
+ {
free((*devlist)[i].name);
+ CoTaskMemFree((*devlist)[i].devid);
+ }
free(*devlist);
*devlist = NULL;
*numdevs = 0;
@@ -849,29 +800,23 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
if(SUCCEEDED(hr))
{
- if(!PlaybackDeviceList)
- {
- ThreadRequest req = { data->MsgEvent, 0 };
- if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
- (void)WaitForResponse(&req);
- }
-
- if(!deviceName && NumPlaybackDevices > 0)
- {
- deviceName = PlaybackDeviceList[0].name;
- data->guid = PlaybackDeviceList[0].guid;
- }
- else
+ if(deviceName)
{
ALuint i;
+ if(!PlaybackDeviceList)
+ {
+ ThreadRequest req = { data->MsgEvent, 0 };
+ if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
+ (void)WaitForResponse(&req);
+ }
+
hr = E_FAIL;
for(i = 0;i < NumPlaybackDevices;i++)
{
- if(PlaybackDeviceList[i].name &&
- strcmp(deviceName, PlaybackDeviceList[i].name) == 0)
+ if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0)
{
- data->guid = PlaybackDeviceList[i].guid;
+ data->devid = strdupW(PlaybackDeviceList[i].devid);
hr = S_OK;
break;
}
@@ -904,7 +849,6 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
return ALC_INVALID_VALUE;
}
- device->szDeviceName = strdup(deviceName);
return ALC_NO_ERROR;
}
@@ -922,6 +866,9 @@ static void MMDevApiClosePlayback(ALCdevice *device)
CloseHandle(data->hNotifyEvent);
data->hNotifyEvent = NULL;
+ free(data->devid);
+ data->devid = NULL;
+
free(data);
device->ExtraData = NULL;
}
@@ -972,6 +919,26 @@ ALCboolean alcMMDevApiInit(BackendFuncs *FuncList)
void alcMMDevApiDeinit(void)
{
+ ALuint i;
+
+ for(i = 0;i < NumPlaybackDevices;i++)
+ {
+ free(PlaybackDeviceList[i].name);
+ CoTaskMemFree(PlaybackDeviceList[i].devid);
+ }
+ free(PlaybackDeviceList);
+ PlaybackDeviceList = NULL;
+ NumPlaybackDevices = 0;
+
+ for(i = 0;i < NumCaptureDevices;i++)
+ {
+ free(CaptureDeviceList[i].name);
+ CoTaskMemFree(CaptureDeviceList[i].devid);
+ }
+ free(CaptureDeviceList);
+ CaptureDeviceList = NULL;
+ NumCaptureDevices = 0;
+
if(ThreadHdl)
{
TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);