summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon/WASAPIStream.cpp
diff options
context:
space:
mode:
authorSilent <zdanio95@gmail.com>2019-08-17 13:08:58 +0200
committerSilent <zdanio95@gmail.com>2021-01-12 19:25:38 +0100
commit11c5150c168f13dca001c9217f7c27cd250fb1b4 (patch)
treeb0aaca44b41a5e62a2fedb73a4f321d70a0a296b /Source/Core/AudioCommon/WASAPIStream.cpp
parentc373890505ee3cce3687078d4fe99b8f38ca9d2b (diff)
AudioCommon/WASAPI: Factorize device enumeration logic into a function to greatly reduce code duplication
Diffstat (limited to 'Source/Core/AudioCommon/WASAPIStream.cpp')
-rw-r--r--Source/Core/AudioCommon/WASAPIStream.cpp83
1 files changed, 26 insertions, 57 deletions
diff --git a/Source/Core/AudioCommon/WASAPIStream.cpp b/Source/Core/AudioCommon/WASAPIStream.cpp
index 552e60cd55..7664356132 100644
--- a/Source/Core/AudioCommon/WASAPIStream.cpp
+++ b/Source/Core/AudioCommon/WASAPIStream.cpp
@@ -77,14 +77,13 @@ static bool HandleWinAPI(std::string_view message, HRESULT result)
return SUCCEEDED(result);
}
-
-std::vector<std::string> WASAPIStream::GetAvailableDevices()
+static void ForEachNamedDevice(const std::function<bool(ComPtr<IMMDevice>, std::string)>& callback)
{
HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
// RPC_E_CHANGED_MODE means that thread has COM already initialized with a different threading
// model. We don't necessarily need multithreaded model here, so don't treat this as an error
if (result != RPC_E_CHANGED_MODE && !HandleWinAPI("Failed to call CoInitialize", result))
- return {};
+ return;
wil::unique_couninitialize_call cleanup;
if (FAILED(result))
@@ -97,20 +96,17 @@ std::vector<std::string> WASAPIStream::GetAvailableDevices()
IID_PPV_ARGS(enumerator.GetAddressOf()));
if (!HandleWinAPI("Failed to create MMDeviceEnumerator", result))
- return {};
+ return;
ComPtr<IMMDeviceCollection> devices;
result = enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, devices.GetAddressOf());
if (!HandleWinAPI("Failed to get available devices", result))
- return {};
+ return;
UINT count;
devices->GetCount(&count);
- std::vector<std::string> device_names;
- device_names.reserve(count);
-
for (u32 i = 0; i < count; i++)
{
ComPtr<IMMDevice> device;
@@ -128,64 +124,37 @@ std::vector<std::string> WASAPIStream::GetAvailableDevices()
wil::unique_prop_variant device_name;
device_properties->GetValue(PKEY_Device_FriendlyName, device_name.addressof());
- device_names.push_back(TStrToUTF8(device_name.pwszVal));
+ if (!callback(std::move(device), TStrToUTF8(device_name.pwszVal)))
+ break;
}
-
- return device_names;
}
-ComPtr<IMMDevice> WASAPIStream::GetDeviceByName(std::string_view name)
+std::vector<std::string> WASAPIStream::GetAvailableDevices()
{
- HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
- // RPC_E_CHANGED_MODE means that thread has COM already initialized with a different threading
- // model. We don't necessarily need multithreaded model here, so don't treat this as an error
- if (result != RPC_E_CHANGED_MODE && !HandleWinAPI("Failed to call CoInitialize", result))
- return nullptr;
-
- wil::unique_couninitialize_call cleanup;
- if (FAILED(result))
- cleanup.release(); // CoUninitialize must be matched with each successful CoInitialize call, so
- // don't call it if initialize fails
-
- ComPtr<IMMDeviceEnumerator> enumerator;
-
- result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(enumerator.GetAddressOf()));
-
- if (!HandleWinAPI("Failed to create MMDeviceEnumerator", result))
- return nullptr;
-
- ComPtr<IMMDeviceCollection> devices;
- result = enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, devices.GetAddressOf());
-
- if (!HandleWinAPI("Failed to get available devices", result))
- return nullptr;
-
- UINT count;
- devices->GetCount(&count);
-
- for (u32 i = 0; i < count; i++)
- {
- ComPtr<IMMDevice> device;
- devices->Item(i, device.GetAddressOf());
- if (!HandleWinAPI("Failed to get device " + std::to_string(i), result))
- continue;
-
- ComPtr<IPropertyStore> device_properties;
+ std::vector<std::string> device_names;
- result = device->OpenPropertyStore(STGM_READ, device_properties.GetAddressOf());
+ ForEachNamedDevice([&device_names](ComPtr<IMMDevice>, std::string n) {
+ device_names.push_back(std::move(n));
+ return true;
+ });
- if (!HandleWinAPI("Failed to initialize IPropertyStore", result))
- continue;
+ return device_names;
+}
- wil::unique_prop_variant device_name;
- device_properties->GetValue(PKEY_Device_FriendlyName, device_name.addressof());
+ComPtr<IMMDevice> WASAPIStream::GetDeviceByName(std::string_view name)
+{
+ ComPtr<IMMDevice> device;
- if (TStrToUTF8(device_name.pwszVal) == name)
- return device;
- }
+ ForEachNamedDevice([&device, &name](ComPtr<IMMDevice> d, std::string n) {
+ if (n == name)
+ {
+ device = std::move(d);
+ return false;
+ }
+ return true;
+ });
- return nullptr;
+ return device;
}
bool WASAPIStream::Init()