enum-wasapi.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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)) {
  18. size_t size;
  19. size = os_wcs_to_utf8(nameVar.pwszVal, 0, nullptr);
  20. if (size) {
  21. device_name.resize(size);
  22. os_wcs_to_utf8(nameVar.pwszVal, size,
  23. &device_name[0]);
  24. }
  25. }
  26. }
  27. return device_name;
  28. }
  29. void GetWASAPIAudioDevices_(vector<AudioDeviceInfo> &devices, bool input)
  30. {
  31. ComPtr<IMMDeviceEnumerator> enumerator;
  32. ComPtr<IMMDeviceCollection> collection;
  33. UINT count;
  34. HRESULT res;
  35. res = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
  36. __uuidof(IMMDeviceEnumerator),
  37. (void**)enumerator.Assign());
  38. if (!res)
  39. throw HRError("Failed to create enumerator", res);
  40. res = enumerator->EnumAudioEndpoints(input ? eCapture : eRender,
  41. DEVICE_STATE_ACTIVE, collection.Assign());
  42. if (!res)
  43. throw HRError("Failed to enumerate devices", res);
  44. res = collection->GetCount(&count);
  45. if (FAILED(res))
  46. throw HRError("Failed to get device count", res);
  47. for (UINT i = 0; i < count; i++) {
  48. ComPtr<IMMDevice> device;
  49. CoTaskMemPtr<WCHAR> w_id;
  50. AudioDeviceInfo info;
  51. size_t size;
  52. res = collection->Item(i, device.Assign());
  53. if (FAILED(res))
  54. continue;
  55. res = device->GetId(&w_id);
  56. if (FAILED(res) || !w_id || !*w_id)
  57. continue;
  58. info.name = GetDeviceName(device);
  59. size = os_wcs_to_utf8(w_id, 0, nullptr);
  60. info.id.resize(size);
  61. os_wcs_to_utf8(w_id, size, &info.id[0]);
  62. }
  63. }
  64. void GetWASAPIAudioDevices(vector<AudioDeviceInfo> &devices, bool input)
  65. {
  66. devices.clear();
  67. try {
  68. GetWASAPIAudioDevices_(devices, input);
  69. } catch (HRError error) {
  70. blog(LOG_ERROR, "[GetWASAPIAudioDevices] %s: %lX",
  71. error.str, error.hr);
  72. }
  73. }