From 5c65edbbcaec306af23ace0c1cf30e3a2ce8e608 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 18 Nov 2023 22:19:58 +0100 Subject: [PATCH] win32: map waveOut devices to mmdevices via endpoint id --- win32/CWaveOut.cpp | 81 +++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/win32/CWaveOut.cpp b/win32/CWaveOut.cpp index 7711f20d..aba540cd 100644 --- a/win32/CWaveOut.cpp +++ b/win32/CWaveOut.cpp @@ -11,8 +11,10 @@ #include "../snes9x.h" #include "../apu/apu.h" #include "wsnes9x.h" +#include - +#define DRV_QUERYFUNCTIONINSTANCEID (DRV_RESERVED + 17) +#define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18) CWaveOut::CWaveOut(void) { @@ -244,13 +246,16 @@ std::vector CWaveOut::GetDeviceList() device_list.push_back(_T("Default")); - // try to enumerate devices via multimedia device enumerator, waveout has a 31 character limit on device names + std::map endpointId_deviceName_map; + + // try to get device names via multimedia device enumerator, waveOut has a 31 character limit on device names + // save them in a map with their endpoint id to later match to waveOut devices IMMDeviceEnumerator* deviceEnumerator; HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID*)&deviceEnumerator); if (SUCCEEDED(hr)) { IMMDeviceCollection* renderDevices; - hr = deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &renderDevices); + hr = deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL, &renderDevices); if (SUCCEEDED(hr)) { UINT count; @@ -262,19 +267,27 @@ std::vector CWaveOut::GetDeviceList() { continue; } - IPropertyStore* propStore; - PROPVARIANT propVar; - PropVariantInit(&propVar); - hr = renderDevice->OpenPropertyStore(STGM_READ, &propStore); + WCHAR* pstrEndpointId = NULL; + hr = renderDevice->GetId(&pstrEndpointId); if (SUCCEEDED(hr)) { - hr = propStore->GetValue(PKEY_Device_FriendlyName, &propVar); + std::wstring strEndpoint = pstrEndpointId; + CoTaskMemFree(pstrEndpointId); + IPropertyStore* propStore; + PROPVARIANT propVar; + PropVariantInit(&propVar); + hr = renderDevice->OpenPropertyStore(STGM_READ, &propStore); + if (SUCCEEDED(hr)) + { + hr = propStore->GetValue(PKEY_Device_FriendlyName, &propVar); + } + if (SUCCEEDED(hr) && propVar.vt == VT_LPWSTR) + { + endpointId_deviceName_map[strEndpoint] = propVar.pwszVal; + } + PropVariantClear(&propVar); } - if (SUCCEEDED(hr) && propVar.vt == VT_LPWSTR) - { - device_list.push_back(propVar.pwszVal); - } - PropVariantClear(&propVar); + renderDevice->Release(); } renderDevices->Release(); @@ -282,19 +295,41 @@ std::vector CWaveOut::GetDeviceList() deviceEnumerator->Release(); } - // if we still only have "default" in the list, use old waveout enumeration - if (device_list.size() == 1) + // enum waveOut devices, using mapped names if available + UINT num_devices = waveOutGetNumDevs(); + for (unsigned int i = 0; i < num_devices; i++) { - UINT num_devices = waveOutGetNumDevs(); - - for (unsigned int i = 0; i < num_devices; i++) + WAVEOUTCAPS caps; + MMRESULT mmr; + mmr = waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)); + if (mmr != MMSYSERR_NOERROR) { - WAVEOUTCAPS caps; - if (waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) - { - device_list.push_back(caps.szPname); - } + continue; } + + // get endpoint id, called function instance id in waveOutMessage + size_t endpointIdSize = 0; + mmr = waveOutMessage((HWAVEOUT)IntToPtr(i), DRV_QUERYFUNCTIONINSTANCEIDSIZE, (DWORD_PTR)&endpointIdSize, NULL); + if (mmr != MMSYSERR_NOERROR) + { + continue; + } + std::vector endpointIdBuffer(endpointIdSize); + mmr = waveOutMessage((HWAVEOUT)IntToPtr(i), DRV_QUERYFUNCTIONINSTANCEID, (DWORD_PTR)endpointIdBuffer.data(), endpointIdSize); + if (mmr != MMSYSERR_NOERROR) + { + continue; + } + std::wstring strEndpoint(endpointIdBuffer.data()); + + // use name retrieved from mmdevice above if available + std::wstring devName = caps.szPname; + if (endpointId_deviceName_map.count(strEndpoint)) + { + devName = endpointId_deviceName_map[strEndpoint]; + } + + device_list.push_back(devName); } return device_list;