Fix device add/remove handlers

This commit is contained in:
2022-07-26 15:22:23 +02:00
parent cea13986f0
commit 3b4853acda
4 changed files with 71 additions and 45 deletions

View File

@@ -1,7 +1,35 @@
#include "ApplicationData.h" #include "ApplicationData.h"
#include "Util.h"
#include "AudioApi.h"
#include <functiondiscoverykeys.h>
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 AudioDevice::AudioDevice(AudioDevice&& other) noexcept

View File

@@ -18,7 +18,7 @@ public:
bool isDefaultMedia = {}; bool isDefaultMedia = {};
bool isDefaultCommunication = {}; bool isDefaultCommunication = {};
AudioDevice(); AudioDevice(IMMDevice* device, LPCWSTR deviceId);
AudioDevice(AudioDevice&& other) noexcept; AudioDevice(AudioDevice&& other) noexcept;
AudioDevice& operator=(AudioDevice&& other) noexcept; AudioDevice& operator=(AudioDevice&& other) noexcept;
~AudioDevice(); ~AudioDevice();

View File

@@ -66,57 +66,35 @@ void loadAudioDevices(AudioData& audioData, std::vector<AudioDevice>& deviceList
for (UINT i = 0; i < deviceCount; i += 1) for (UINT i = 0; i < deviceCount; i += 1)
{ {
AudioDevice deviceData{}; IMMDevice* device;
err = deviceCollection->Item(i, &device);
err = deviceCollection->Item(i, &deviceData.device);
if (isError(err, std::stringstream("Failed to get device ") << i << ": ")) if (isError(err, std::stringstream("Failed to get device ") << i << ": "))
{ {
continue; continue;
} }
LPWSTR deviceId; LPWSTR deviceId;
err = deviceData.device->GetId(&deviceId); err = device->GetId(&deviceId);
isError(err, std::stringstream("Failed to get device id ") << i << ": "); if (!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)
{ {
deviceData.isDefaultConsole = wcscmp(defaultConsoleId, deviceId) == 0; AudioDevice audioDevice(device, deviceId);
}
if (defaultMediaId) if (defaultConsoleId)
{ {
deviceData.isDefaultMedia = wcscmp(defaultMediaId, deviceId) == 0; audioDevice.isDefaultConsole = wcscmp(defaultConsoleId, deviceId) == 0;
} }
if (defaultCommunicationId) if (defaultMediaId)
{ {
deviceData.isDefaultCommunication = wcscmp(defaultCommunicationId, deviceId) == 0; 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); CoTaskMemFree(deviceId);
} }

View File

@@ -34,7 +34,25 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceAdded(LPCWSTR pwstrDeviceId
HRESULT result = audioData->deviceEnumerator->GetDevice(pwstrDeviceId, &newDevice); HRESULT result = audioData->deviceEnumerator->GetDevice(pwstrDeviceId, &newDevice);
if (SUCCEEDED(result) && newDevice != nullptr) 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; return result;
@@ -50,7 +68,9 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceRemoved(LPCWSTR pwstrDevice
if (wcscmp(deviceListIterator->id.c_str(), pwstrDeviceId) == 0) if (wcscmp(deviceListIterator->id.c_str(), pwstrDeviceId) == 0)
{ {
deviceListIterator = deviceList.erase(deviceListIterator); deviceListIterator = deviceList.erase(deviceListIterator);
continue;
} }
deviceListIterator++;
} }
}; };