enum-wasapi.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "enum-wasapi.hpp"
  2. #include <util/base.h>
  3. #include <util/platform.h>
  4. #include <util/windows/HRError.hpp>
  5. #include <util/windows/ComPtr.hpp>
  6. #include <util/windows/CoTaskMemPtr.hpp>
  7. using namespace std;
  8. string GetDeviceName(IMMDevice *device)
  9. {
  10. string device_name;
  11. ComPtr<IPropertyStore> store;
  12. HRESULT res;
  13. if (SUCCEEDED(device->OpenPropertyStore(STGM_READ, store.Assign()))) {
  14. PROPVARIANT nameVar;
  15. PropVariantInit(&nameVar);
  16. res = store->GetValue(PKEY_Device_FriendlyName, &nameVar);
  17. if (SUCCEEDED(res) && nameVar.pwszVal && *nameVar.pwszVal) {
  18. size_t len = wcslen(nameVar.pwszVal);
  19. size_t size;
  20. size = os_wcs_to_utf8(nameVar.pwszVal, len, nullptr,
  21. 0) +
  22. 1;
  23. device_name.resize(size);
  24. os_wcs_to_utf8(nameVar.pwszVal, len, &device_name[0],
  25. size);
  26. }
  27. }
  28. return device_name;
  29. }
  30. static void GetWASAPIAudioDevices_(vector<AudioDeviceInfo> &devices, bool input)
  31. {
  32. ComPtr<IMMDeviceEnumerator> enumerator;
  33. ComPtr<IMMDeviceCollection> collection;
  34. UINT count;
  35. HRESULT res;
  36. res = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
  37. __uuidof(IMMDeviceEnumerator),
  38. (void **)enumerator.Assign());
  39. if (FAILED(res))
  40. throw HRError("Failed to create enumerator", res);
  41. res = enumerator->EnumAudioEndpoints(input ? eCapture : eRender,
  42. DEVICE_STATE_ACTIVE,
  43. collection.Assign());
  44. if (FAILED(res))
  45. throw HRError("Failed to enumerate devices", res);
  46. res = collection->GetCount(&count);
  47. if (FAILED(res))
  48. throw HRError("Failed to get device count", res);
  49. for (UINT i = 0; i < count; i++) {
  50. ComPtr<IMMDevice> device;
  51. CoTaskMemPtr<WCHAR> w_id;
  52. AudioDeviceInfo info;
  53. size_t len, size;
  54. res = collection->Item(i, device.Assign());
  55. if (FAILED(res))
  56. continue;
  57. res = device->GetId(&w_id);
  58. if (FAILED(res) || !w_id || !*w_id)
  59. continue;
  60. info.name = GetDeviceName(device);
  61. len = wcslen(w_id);
  62. size = os_wcs_to_utf8(w_id, len, nullptr, 0) + 1;
  63. info.id.resize(size);
  64. os_wcs_to_utf8(w_id, len, &info.id[0], size);
  65. devices.push_back(info);
  66. }
  67. }
  68. void GetWASAPIAudioDevices(vector<AudioDeviceInfo> &devices, bool input)
  69. {
  70. devices.clear();
  71. try {
  72. GetWASAPIAudioDevices_(devices, input);
  73. } catch (HRError &error) {
  74. blog(LOG_WARNING, "[GetWASAPIAudioDevices] %s: %lX", error.str,
  75. error.hr);
  76. }
  77. }