From d30060cdc1e15f861ef987b58e68005b1e41f058 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 3 Nov 2023 19:05:22 +0100 Subject: [PATCH] win32: try MMDeviceEnumerator for waveOut device enumeration before falling back to device caps (#883) --- win32/CWaveOut.cpp | 93 ++++++++++++++++++++++++++++++++++------------ win32/CWaveOut.h | 1 - 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/win32/CWaveOut.cpp b/win32/CWaveOut.cpp index df1071e0..7711f20d 100644 --- a/win32/CWaveOut.cpp +++ b/win32/CWaveOut.cpp @@ -4,11 +4,16 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ + #include "CWaveOut.h" +#include // needs to be before snes9x.h, otherwise conflicts with SetFlags macro +#include #include "../snes9x.h" #include "../apu/apu.h" #include "wsnes9x.h" + + CWaveOut::CWaveOut(void) { hWaveOut = NULL; @@ -235,38 +240,80 @@ void CWaveOut::ProcessSound() std::vector CWaveOut::GetDeviceList() { - std::vector device_list; + std::vector device_list; - UINT num_devices = waveOutGetNumDevs(); + device_list.push_back(_T("Default")); - device_list.push_back(_T("Default")); + // try to enumerate devices via multimedia device enumerator, waveout has a 31 character limit on device names + 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); + if (SUCCEEDED(hr)) + { + UINT count; + renderDevices->GetCount(&count); + for (int i = 0; i < count; i++) + { + IMMDevice* renderDevice = NULL; + if (renderDevices->Item(i, &renderDevice) != S_OK) + { + continue; + } + 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) + { + device_list.push_back(propVar.pwszVal); + } + PropVariantClear(&propVar); + renderDevice->Release(); + } + renderDevices->Release(); + } + deviceEnumerator->Release(); + } - for (unsigned int i = 0; i < num_devices; i++) - { - WAVEOUTCAPS caps; - if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) - { - device_list.push_back(caps.szPname); - } - } + // if we still only have "default" in the list, use old waveout enumeration + if (device_list.size() == 1) + { + UINT num_devices = waveOutGetNumDevs(); - return device_list; + for (unsigned int i = 0; i < num_devices; i++) + { + WAVEOUTCAPS caps; + if (waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) + { + device_list.push_back(caps.szPname); + } + } + } + + return device_list; } int CWaveOut::FindDeviceIndex(TCHAR *audio_device) { - std::vector device_list = GetDeviceList(); + std::vector device_list = GetDeviceList(); - int index = 0; + int index = 0; - for (int i = 0; i < device_list.size(); i++) - { - if (_tcsstr(device_list[i].c_str(), audio_device) != NULL) - { - index = i; - break; - } - } + for (int i = 0; i < device_list.size(); i++) + { + if (_tcsstr(device_list[i].c_str(), audio_device) != NULL) + { + index = i; + break; + } + } - return index; + return index; } diff --git a/win32/CWaveOut.h b/win32/CWaveOut.h index 01fb7e3e..ddeb2698 100644 --- a/win32/CWaveOut.h +++ b/win32/CWaveOut.h @@ -6,7 +6,6 @@ #pragma once -#include "../snes9x.h" #include #include "IS9xSoundOutput.h" #include