Fix device add/remove handlers
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user