2014-03-04 06:07:13 -08:00
|
|
|
#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);
|
|
|
|
|
2017-05-28 15:30:06 -07:00
|
|
|
if (SUCCEEDED(res) && nameVar.pwszVal && *nameVar.pwszVal) {
|
2014-05-22 03:42:43 -07:00
|
|
|
size_t len = wcslen(nameVar.pwszVal);
|
2014-03-04 06:07:13 -08:00
|
|
|
size_t size;
|
|
|
|
|
2014-05-22 03:42:43 -07:00
|
|
|
size = os_wcs_to_utf8(nameVar.pwszVal, len,
|
|
|
|
nullptr, 0) + 1;
|
|
|
|
device_name.resize(size);
|
|
|
|
os_wcs_to_utf8(nameVar.pwszVal, len,
|
|
|
|
&device_name[0], size);
|
2014-03-04 06:07:13 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
2014-03-04 06:18:24 -08:00
|
|
|
if (FAILED(res))
|
2014-03-04 06:07:13 -08:00
|
|
|
throw HRError("Failed to create enumerator", res);
|
|
|
|
|
|
|
|
res = enumerator->EnumAudioEndpoints(input ? eCapture : eRender,
|
|
|
|
DEVICE_STATE_ACTIVE, collection.Assign());
|
2014-03-04 06:18:24 -08:00
|
|
|
if (FAILED(res))
|
2014-03-04 06:07:13 -08:00
|
|
|
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;
|
2014-05-22 03:42:43 -07:00
|
|
|
size_t len, size;
|
2014-03-04 06:07:13 -08:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2014-05-22 03:42:43 -07:00
|
|
|
len = wcslen(w_id);
|
|
|
|
size = os_wcs_to_utf8(w_id, len, nullptr, 0) + 1;
|
2014-03-04 06:07:13 -08:00
|
|
|
info.id.resize(size);
|
2014-05-22 03:42:43 -07:00
|
|
|
os_wcs_to_utf8(w_id, len, &info.id[0], size);
|
2014-03-06 06:02:25 -08:00
|
|
|
|
|
|
|
devices.push_back(info);
|
2014-03-04 06:07:13 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetWASAPIAudioDevices(vector<AudioDeviceInfo> &devices, bool input)
|
|
|
|
{
|
|
|
|
devices.clear();
|
|
|
|
|
|
|
|
try {
|
|
|
|
GetWASAPIAudioDevices_(devices, input);
|
|
|
|
|
|
|
|
} catch (HRError error) {
|
2014-03-07 12:04:38 -08:00
|
|
|
blog(LOG_WARNING, "[GetWASAPIAudioDevices] %s: %lX",
|
2014-03-04 06:07:13 -08:00
|
|
|
error.str, error.hr);
|
|
|
|
}
|
|
|
|
}
|