From 3b4853acda081104b4cf8c0ecd77850e5bb5af11 Mon Sep 17 00:00:00 2001 From: Asuro Date: Tue, 26 Jul 2022 15:22:23 +0200 Subject: [PATCH] Fix device add/remove handlers --- AsuroTool/ApplicationData.cpp | 30 +++++++++++- AsuroTool/ApplicationData.h | 2 +- AsuroTool/AudioApi.cpp | 62 ++++++++----------------- AsuroTool/AudioNotificationListener.cpp | 22 ++++++++- 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/AsuroTool/ApplicationData.cpp b/AsuroTool/ApplicationData.cpp index b0e5bd8..23fd263 100644 --- a/AsuroTool/ApplicationData.cpp +++ b/AsuroTool/ApplicationData.cpp @@ -1,7 +1,35 @@ #include "ApplicationData.h" +#include "Util.h" +#include "AudioApi.h" +#include -AudioDevice::AudioDevice() +AudioDevice::AudioDevice(IMMDevice* device, LPCWSTR deviceId) { + id = std::wstring(deviceId); + + IPropertyStore* propertyStore; + HRESULT err = device->OpenPropertyStore(STGM_READ, &propertyStore); + isError(err, "Failed to open prop store: "); + + PROPVARIANT deviceNameProp; + const wchar_t* deviceName; + err = getDevicePropertyString(propertyStore, PKEY_Device_FriendlyName, &deviceNameProp, deviceName); + isError(err, "Failed to read name of device :"); + name = utf8Encode(deviceName); + + err = device->GetState(&state); + isError(err, "Failed to reat state of device: "); + + err = device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID*)&volumeInterface); + isError(err, "Failed to get audio endpoint volume interface: "); + + err = device->Activate(__uuidof(IAudioMeterInformation), CLSCTX_INPROC_SERVER, NULL, (LPVOID*)&meterInterface); + isError(err, "Failed to get audio meter interface: "); + + if (propertyStore) + { + propertyStore->Release(); + } } AudioDevice::AudioDevice(AudioDevice&& other) noexcept diff --git a/AsuroTool/ApplicationData.h b/AsuroTool/ApplicationData.h index a34a985..cc8e829 100644 --- a/AsuroTool/ApplicationData.h +++ b/AsuroTool/ApplicationData.h @@ -18,7 +18,7 @@ public: bool isDefaultMedia = {}; bool isDefaultCommunication = {}; - AudioDevice(); + AudioDevice(IMMDevice* device, LPCWSTR deviceId); AudioDevice(AudioDevice&& other) noexcept; AudioDevice& operator=(AudioDevice&& other) noexcept; ~AudioDevice(); diff --git a/AsuroTool/AudioApi.cpp b/AsuroTool/AudioApi.cpp index 458ada1..45c92dd 100644 --- a/AsuroTool/AudioApi.cpp +++ b/AsuroTool/AudioApi.cpp @@ -66,57 +66,35 @@ void loadAudioDevices(AudioData& audioData, std::vector& deviceList for (UINT i = 0; i < deviceCount; i += 1) { - AudioDevice deviceData{}; - - err = deviceCollection->Item(i, &deviceData.device); + IMMDevice* device; + err = deviceCollection->Item(i, &device); if (isError(err, std::stringstream("Failed to get device ") << i << ": ")) { continue; } LPWSTR deviceId; - err = deviceData.device->GetId(&deviceId); - isError(err, std::stringstream("Failed to get device id ") << i << ": "); - deviceData.id = std::wstring(deviceId); - - IPropertyStore* propertyStore; - err = deviceData.device->OpenPropertyStore(STGM_READ, &propertyStore); - isError(err, std::stringstream("Failed to open device ") << i << "prop store: "); - - PROPVARIANT deviceNameProp; - const wchar_t* deviceName; - err = getDevicePropertyString(propertyStore, PKEY_Device_FriendlyName, &deviceNameProp, deviceName); - isError(err, std::stringstream("Failed to read name of device ") << i << ": "); - deviceData.name = utf8Encode(deviceName); - - err = deviceData.device->GetState(&deviceData.state); - isError(err, std::stringstream("Failed to reat state of device ") << i << ": "); - - err = deviceData.device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID*)&deviceData.volumeInterface); - isError(err, "Failed to get audio endpoint volume interface: "); - - err = deviceData.device->Activate(__uuidof(IAudioMeterInformation), CLSCTX_INPROC_SERVER, NULL, (LPVOID*)&deviceData.meterInterface); - isError(err, "Failed to get audio meter interface: "); - - if (defaultConsoleId) + err = device->GetId(&deviceId); + if (!isError(err, std::stringstream("Failed to get device id ") << i << ": ")) { - deviceData.isDefaultConsole = wcscmp(defaultConsoleId, deviceId) == 0; - } - if (defaultMediaId) - { - deviceData.isDefaultMedia = wcscmp(defaultMediaId, deviceId) == 0; - } - if (defaultCommunicationId) - { - deviceData.isDefaultCommunication = wcscmp(defaultCommunicationId, deviceId) == 0; + AudioDevice audioDevice(device, deviceId); + + if (defaultConsoleId) + { + audioDevice.isDefaultConsole = wcscmp(defaultConsoleId, deviceId) == 0; + } + if (defaultMediaId) + { + audioDevice.isDefaultMedia = wcscmp(defaultMediaId, deviceId) == 0; + } + if (defaultCommunicationId) + { + audioDevice.isDefaultCommunication = wcscmp(defaultCommunicationId, deviceId) == 0; + } + + deviceList.push_back(std::move(audioDevice)); } - deviceList.push_back(std::move(deviceData)); - - if (propertyStore) - { - propertyStore->Release(); - } CoTaskMemFree(deviceId); } diff --git a/AsuroTool/AudioNotificationListener.cpp b/AsuroTool/AudioNotificationListener.cpp index 142b0b9..3847f2e 100644 --- a/AsuroTool/AudioNotificationListener.cpp +++ b/AsuroTool/AudioNotificationListener.cpp @@ -34,7 +34,25 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceAdded(LPCWSTR pwstrDeviceId HRESULT result = audioData->deviceEnumerator->GetDevice(pwstrDeviceId, &newDevice); if (SUCCEEDED(result) && newDevice != nullptr) { - // TODO: add to device list + IMMEndpoint* endpoint; + result = newDevice->QueryInterface(&endpoint); + if (SUCCEEDED(result) && endpoint != nullptr) + { + EDataFlow dataFlow; + result = endpoint->GetDataFlow(&dataFlow); + if (SUCCEEDED(result)) + { + AudioDevice audioDevice(newDevice, pwstrDeviceId); + if (dataFlow == EDataFlow::eCapture) + { + audioData->recordingDevices.push_back(std::move(audioDevice)); + } + else + { + audioData->playbackDevices.push_back(std::move(audioDevice)); + } + } + } } return result; @@ -50,7 +68,9 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceRemoved(LPCWSTR pwstrDevice if (wcscmp(deviceListIterator->id.c_str(), pwstrDeviceId) == 0) { deviceListIterator = deviceList.erase(deviceListIterator); + continue; } + deviceListIterator++; } };