94 lines
2.1 KiB
C++
94 lines
2.1 KiB
C++
|
#include "enum-wasapi.hpp"
|
||
|
|
||
|
#include <util/base.h>
|
||
|
#include <util/platform.h>
|
||
|
#include <util/windows/HRError.hpp>
|
||
|
#include <util/windows/ComPtr.hpp>
|
||
|
#include <util/windows/CoTaskMemPtr.hpp>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
string GetDeviceName(IMMDevice *device)
|
||
|
{
|
||
|
string device_name;
|
||
|
ComPtr<IPropertyStore> store;
|
||
|
HRESULT res;
|
||
|
|
||
|
if (SUCCEEDED(device->OpenPropertyStore(STGM_READ, store.Assign()))) {
|
||
|
PROPVARIANT nameVar;
|
||
|
|
||
|
PropVariantInit(&nameVar);
|
||
|
res = store->GetValue(PKEY_Device_FriendlyName, &nameVar);
|
||
|
|
||
|
if (SUCCEEDED(res)) {
|
||
|
size_t size;
|
||
|
|
||
|
size = os_wcs_to_utf8(nameVar.pwszVal, 0, nullptr);
|
||
|
if (size) {
|
||
|
device_name.resize(size);
|
||
|
os_wcs_to_utf8(nameVar.pwszVal, size,
|
||
|
&device_name[0]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return device_name;
|
||
|
}
|
||
|
|
||
|
void GetWASAPIAudioDevices_(vector<AudioDeviceInfo> &devices, bool input)
|
||
|
{
|
||
|
ComPtr<IMMDeviceEnumerator> enumerator;
|
||
|
ComPtr<IMMDeviceCollection> collection;
|
||
|
UINT count;
|
||
|
HRESULT res;
|
||
|
|
||
|
res = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
|
||
|
__uuidof(IMMDeviceEnumerator),
|
||
|
(void**)enumerator.Assign());
|
||
|
if (!res)
|
||
|
throw HRError("Failed to create enumerator", res);
|
||
|
|
||
|
res = enumerator->EnumAudioEndpoints(input ? eCapture : eRender,
|
||
|
DEVICE_STATE_ACTIVE, collection.Assign());
|
||
|
if (!res)
|
||
|
throw HRError("Failed to enumerate devices", res);
|
||
|
|
||
|
res = collection->GetCount(&count);
|
||
|
if (FAILED(res))
|
||
|
throw HRError("Failed to get device count", res);
|
||
|
|
||
|
for (UINT i = 0; i < count; i++) {
|
||
|
ComPtr<IMMDevice> device;
|
||
|
CoTaskMemPtr<WCHAR> w_id;
|
||
|
AudioDeviceInfo info;
|
||
|
size_t size;
|
||
|
|
||
|
res = collection->Item(i, device.Assign());
|
||
|
if (FAILED(res))
|
||
|
continue;
|
||
|
|
||
|
res = device->GetId(&w_id);
|
||
|
if (FAILED(res) || !w_id || !*w_id)
|
||
|
continue;
|
||
|
|
||
|
info.name = GetDeviceName(device);
|
||
|
|
||
|
size = os_wcs_to_utf8(w_id, 0, nullptr);
|
||
|
info.id.resize(size);
|
||
|
os_wcs_to_utf8(w_id, size, &info.id[0]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GetWASAPIAudioDevices(vector<AudioDeviceInfo> &devices, bool input)
|
||
|
{
|
||
|
devices.clear();
|
||
|
|
||
|
try {
|
||
|
GetWASAPIAudioDevices_(devices, input);
|
||
|
|
||
|
} catch (HRError error) {
|
||
|
blog(LOG_ERROR, "[GetWASAPIAudioDevices] %s: %lX",
|
||
|
error.str, error.hr);
|
||
|
}
|
||
|
}
|