cleanup
This commit is contained in:
@@ -37,13 +37,54 @@ AudioDevice::~AudioDevice()
|
|||||||
if (volumeInterface)
|
if (volumeInterface)
|
||||||
{
|
{
|
||||||
volumeInterface->Release();
|
volumeInterface->Release();
|
||||||
|
volumeInterface = nullptr;
|
||||||
}
|
}
|
||||||
if (meterInterface)
|
if (meterInterface)
|
||||||
{
|
{
|
||||||
meterInterface->Release();
|
meterInterface->Release();
|
||||||
|
meterInterface = nullptr;
|
||||||
}
|
}
|
||||||
if (device)
|
if (device)
|
||||||
{
|
{
|
||||||
device->Release();
|
device->Release();
|
||||||
|
device = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData::AudioData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData::AudioData(AudioData&& other) noexcept
|
||||||
|
: playbackDevices(std::move(other.playbackDevices)), recordingDevices(std::move(other.recordingDevices)),
|
||||||
|
deviceEnumerator(other.deviceEnumerator), audioNotificationListener(other.audioNotificationListener)
|
||||||
|
{
|
||||||
|
other.deviceEnumerator = nullptr;
|
||||||
|
other.audioNotificationListener = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData& AudioData::operator=(AudioData&& other) noexcept
|
||||||
|
{
|
||||||
|
playbackDevices = std::move(other.playbackDevices);
|
||||||
|
recordingDevices = std::move(other.recordingDevices);
|
||||||
|
deviceEnumerator = other.deviceEnumerator;
|
||||||
|
audioNotificationListener = other.audioNotificationListener;
|
||||||
|
|
||||||
|
other.deviceEnumerator = nullptr;
|
||||||
|
other.audioNotificationListener = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData::~AudioData()
|
||||||
|
{
|
||||||
|
if (deviceEnumerator)
|
||||||
|
{
|
||||||
|
deviceEnumerator->Release();
|
||||||
|
deviceEnumerator = nullptr;
|
||||||
|
}
|
||||||
|
if (audioNotificationListener)
|
||||||
|
{
|
||||||
|
audioNotificationListener->Release();
|
||||||
|
audioNotificationListener = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,19 @@ public:
|
|||||||
~AudioDevice();
|
~AudioDevice();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AudioData {
|
||||||
|
public:
|
||||||
|
std::vector<AudioDevice> playbackDevices = {};
|
||||||
|
std::vector<AudioDevice> recordingDevices = {};
|
||||||
|
IMMDeviceEnumerator* deviceEnumerator = nullptr;
|
||||||
|
AudioNotificationListener* audioNotificationListener = nullptr;
|
||||||
|
|
||||||
|
AudioData();
|
||||||
|
AudioData(AudioData&& other) noexcept;
|
||||||
|
AudioData& operator=(AudioData&& other) noexcept;
|
||||||
|
~AudioData();
|
||||||
|
};
|
||||||
|
|
||||||
class ApplicationSettings {
|
class ApplicationSettings {
|
||||||
public:
|
public:
|
||||||
bool showDisabledDevices = false;
|
bool showDisabledDevices = false;
|
||||||
@@ -33,8 +46,5 @@ public:
|
|||||||
class ApplicationData {
|
class ApplicationData {
|
||||||
public:
|
public:
|
||||||
ApplicationSettings settings = {};
|
ApplicationSettings settings = {};
|
||||||
std::vector<AudioDevice> playbackDevices = {};
|
std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>();
|
||||||
std::vector<AudioDevice> recordingDevices = {};
|
|
||||||
IMMDeviceEnumerator* deviceEnumerator = nullptr;
|
|
||||||
AudioNotificationListener* audioNotificationListener = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,14 +40,14 @@ void init(DrawData& drawData, void* customData)
|
|||||||
audioResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
audioResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||||
isError(audioResult, "Failed to initialize COM: ");
|
isError(audioResult, "Failed to initialize COM: ");
|
||||||
|
|
||||||
audioResult = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&appData->deviceEnumerator));
|
audioResult = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&appData->audioData->deviceEnumerator));
|
||||||
isError(audioResult, "Failed to set up audio device enumerator: ");
|
isError(audioResult, "Failed to set up audio device enumerator: ");
|
||||||
|
|
||||||
appData->audioNotificationListener = new AudioNotificationListener(appData);
|
appData->audioData->audioNotificationListener = new AudioNotificationListener(appData->audioData);
|
||||||
audioResult = appData->deviceEnumerator->RegisterEndpointNotificationCallback(appData->audioNotificationListener);
|
audioResult = appData->audioData->deviceEnumerator->RegisterEndpointNotificationCallback(appData->audioData->audioNotificationListener);
|
||||||
isError(audioResult, "Failed to register audio notification listener: ");
|
isError(audioResult, "Failed to register audio notification listener: ");
|
||||||
|
|
||||||
reloadDeviceLists(appData);
|
reloadDeviceLists(*appData->audioData);
|
||||||
|
|
||||||
// Set window icon
|
// Set window icon
|
||||||
LPWSTR iconId = MAKEINTRESOURCE(IDI_ICON1);
|
LPWSTR iconId = MAKEINTRESOURCE(IDI_ICON1);
|
||||||
@@ -70,14 +70,14 @@ void draw(DrawData& drawData, void* customData)
|
|||||||
// Playback Devices
|
// Playback Devices
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||||
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
||||||
customYCursor += audioDeviceWindow(appData, appData->playbackDevices, " \xEE\xB8\x84 Playback").y;
|
customYCursor += audioDeviceWindow(appData, appData->audioData->playbackDevices, " \xEE\xB8\x84 Playback").y;
|
||||||
|
|
||||||
customYCursor += 5.;
|
customYCursor += 5.;
|
||||||
|
|
||||||
// Recording devices
|
// Recording devices
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||||
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
||||||
customYCursor += audioDeviceWindow(appData, appData->recordingDevices, " \xEE\xBD\x8F Recording").y;
|
customYCursor += audioDeviceWindow(appData, appData->audioData->recordingDevices, " \xEE\xBD\x8F Recording").y;
|
||||||
|
|
||||||
// Resize viewport
|
// Resize viewport
|
||||||
if (appData->settings.fitWindowHeight)
|
if (appData->settings.fitWindowHeight)
|
||||||
@@ -103,7 +103,7 @@ ImVec2 menuBar(ApplicationData* appData)
|
|||||||
{
|
{
|
||||||
if (ImGui::Button("Manual Refresh"))
|
if (ImGui::Button("Manual Refresh"))
|
||||||
{
|
{
|
||||||
reloadDeviceLists(appData);
|
reloadDeviceLists(*appData->audioData);
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ ImVec2 audioDeviceWindow(ApplicationData* appData, std::vector<AudioDevice>& dev
|
|||||||
}
|
}
|
||||||
if (customButton("bn_d_", deviceIdUtf8.c_str(), "\xEE\xBE\x82", !dev.isDefaultConsole))
|
if (customButton("bn_d_", deviceIdUtf8.c_str(), "\xEE\xBE\x82", !dev.isDefaultConsole))
|
||||||
{
|
{
|
||||||
setDefaultAudioDevice(appData, dev.id.c_str(), ERole::eConsole);
|
setDefaultAudioDevice(*appData->audioData, dev.id.c_str(), ERole::eConsole);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -206,7 +206,7 @@ ImVec2 audioDeviceWindow(ApplicationData* appData, std::vector<AudioDevice>& dev
|
|||||||
}
|
}
|
||||||
if (customButton("bn_c_", deviceIdUtf8.c_str(), "\xEE\xBF\xA9", !dev.isDefaultCommunication))
|
if (customButton("bn_c_", deviceIdUtf8.c_str(), "\xEE\xBF\xA9", !dev.isDefaultCommunication))
|
||||||
{
|
{
|
||||||
setDefaultAudioDevice(appData, dev.id.c_str(), ERole::eCommunications);
|
setDefaultAudioDevice(*appData->audioData, dev.id.c_str(), ERole::eCommunications);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "ImguiBase.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "AudioApi.h"
|
#include "AudioApi.h"
|
||||||
#include "PolicyConfig.h"
|
#include "PolicyConfig.h"
|
||||||
@@ -25,7 +24,7 @@ HRESULT getDevicePropertyString(IPropertyStore* propertyStore, const PROPERTYKEY
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ERole role)
|
void setDefaultAudioDevice(AudioData& audioData, const wchar_t* deviceId, ERole role)
|
||||||
{
|
{
|
||||||
IPolicyConfigVista* pPolicyConfig;
|
IPolicyConfigVista* pPolicyConfig;
|
||||||
|
|
||||||
@@ -34,18 +33,18 @@ void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ER
|
|||||||
{
|
{
|
||||||
hr = pPolicyConfig->SetDefaultEndpoint(deviceId, role);
|
hr = pPolicyConfig->SetDefaultEndpoint(deviceId, role);
|
||||||
pPolicyConfig->Release();
|
pPolicyConfig->Release();
|
||||||
reloadDeviceLists(appData);
|
reloadDeviceLists(audioData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& deviceList, EDataFlow deviceType)
|
void loadAudioDevices(AudioData& audioData, std::vector<AudioDevice>& deviceList, EDataFlow deviceType)
|
||||||
{
|
{
|
||||||
deviceList.clear();
|
deviceList.clear();
|
||||||
|
|
||||||
HRESULT err;
|
HRESULT err;
|
||||||
IMMDeviceCollection* deviceCollection = NULL;
|
IMMDeviceCollection* deviceCollection = NULL;
|
||||||
|
|
||||||
err = appData->deviceEnumerator->EnumAudioEndpoints(deviceType, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &deviceCollection);
|
err = audioData.deviceEnumerator->EnumAudioEndpoints(deviceType, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &deviceCollection);
|
||||||
if (isError(err, "Failed to enumerate audio devices: ")) return;
|
if (isError(err, "Failed to enumerate audio devices: ")) return;
|
||||||
|
|
||||||
UINT deviceCount;
|
UINT deviceCount;
|
||||||
@@ -54,7 +53,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& device
|
|||||||
|
|
||||||
IMMDevice* defaultConsoleDevice = NULL;
|
IMMDevice* defaultConsoleDevice = NULL;
|
||||||
LPWSTR defaultConsoleId = nullptr;
|
LPWSTR defaultConsoleId = nullptr;
|
||||||
err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eConsole, &defaultConsoleDevice);
|
err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eConsole, &defaultConsoleDevice);
|
||||||
if (!FAILED(err))
|
if (!FAILED(err))
|
||||||
{
|
{
|
||||||
defaultConsoleDevice->GetId(&defaultConsoleId);
|
defaultConsoleDevice->GetId(&defaultConsoleId);
|
||||||
@@ -62,7 +61,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& device
|
|||||||
|
|
||||||
IMMDevice* defaultMediaOutput = NULL;
|
IMMDevice* defaultMediaOutput = NULL;
|
||||||
LPWSTR defaultMediaId = nullptr;
|
LPWSTR defaultMediaId = nullptr;
|
||||||
err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eMultimedia, &defaultMediaOutput);
|
err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eMultimedia, &defaultMediaOutput);
|
||||||
if (!FAILED(err))
|
if (!FAILED(err))
|
||||||
{
|
{
|
||||||
defaultMediaOutput->GetId(&defaultMediaId);
|
defaultMediaOutput->GetId(&defaultMediaId);
|
||||||
@@ -70,7 +69,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& device
|
|||||||
|
|
||||||
IMMDevice* defaultCommunicationOutput = NULL;
|
IMMDevice* defaultCommunicationOutput = NULL;
|
||||||
LPWSTR defaultCommunicationId = nullptr;
|
LPWSTR defaultCommunicationId = nullptr;
|
||||||
err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eCommunications, &defaultCommunicationOutput);
|
err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eCommunications, &defaultCommunicationOutput);
|
||||||
if (!FAILED(err))
|
if (!FAILED(err))
|
||||||
{
|
{
|
||||||
defaultCommunicationOutput->GetId(&defaultCommunicationId);
|
defaultCommunicationOutput->GetId(&defaultCommunicationId);
|
||||||
@@ -141,10 +140,10 @@ void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& device
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reloadDeviceLists(ApplicationData* appData)
|
void reloadDeviceLists(AudioData& audioData)
|
||||||
{
|
{
|
||||||
loadAudioDevices(appData, appData->playbackDevices, EDataFlow::eRender);
|
loadAudioDevices(audioData, audioData.playbackDevices, EDataFlow::eRender);
|
||||||
loadAudioDevices(appData, appData->recordingDevices, EDataFlow::eCapture);
|
loadAudioDevices(audioData, audioData.recordingDevices, EDataFlow::eCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getVolume(IAudioEndpointVolume* volumeInterface)
|
float getVolume(IAudioEndpointVolume* volumeInterface)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
HRESULT getDeviceProperty(IPropertyStore* propertyStore, const PROPERTYKEY propertyKey, PROPVARIANT* outData);
|
HRESULT getDeviceProperty(IPropertyStore* propertyStore, const PROPERTYKEY propertyKey, PROPVARIANT* outData);
|
||||||
HRESULT getDevicePropertyString(IPropertyStore* propertyStore, const PROPERTYKEY propertyKey, PROPVARIANT* outData, const wchar_t*& outString, const wchar_t* defaultStr = L"Unknown");
|
HRESULT getDevicePropertyString(IPropertyStore* propertyStore, const PROPERTYKEY propertyKey, PROPVARIANT* outData, const wchar_t*& outString, const wchar_t* defaultStr = L"Unknown");
|
||||||
void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ERole role);
|
void setDefaultAudioDevice(AudioData& audioData, const wchar_t* deviceId, ERole role);
|
||||||
void loadAudioDevices(ApplicationData* appData, std::vector<AudioDevice>& deviceList, EDataFlow deviceType);
|
void loadAudioDevices(AudioData& audioData, std::vector<AudioDevice>& deviceList, EDataFlow deviceType);
|
||||||
void reloadDeviceLists(ApplicationData* appData);
|
void reloadDeviceLists(AudioData& audioData);
|
||||||
float getVolume(IAudioEndpointVolume* volumeInterface);
|
float getVolume(IAudioEndpointVolume* volumeInterface);
|
||||||
float getMeterValue(IAudioMeterInformation* meterInterface);
|
float getMeterValue(IAudioMeterInformation* meterInterface);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "AudioNotificationListener.h"
|
#include "AudioNotificationListener.h"
|
||||||
|
|
||||||
|
|
||||||
AudioNotificationListener::AudioNotificationListener(ApplicationData* appData) : appData(appData)
|
AudioNotificationListener::AudioNotificationListener(std::shared_ptr<AudioData> audioData) : audioData(audioData)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,8 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceStateChanged(LPCWSTR pwstrD
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDevice(appData->playbackDevices);
|
updateDevice(audioData->playbackDevices);
|
||||||
updateDevice(appData->recordingDevices);
|
updateDevice(audioData->recordingDevices);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceStateChanged(LPCWSTR pwstrD
|
|||||||
HRESULT __stdcall AudioNotificationListener::OnDeviceAdded(LPCWSTR pwstrDeviceId)
|
HRESULT __stdcall AudioNotificationListener::OnDeviceAdded(LPCWSTR pwstrDeviceId)
|
||||||
{
|
{
|
||||||
IMMDevice* newDevice;
|
IMMDevice* newDevice;
|
||||||
HRESULT result = appData->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
|
// TODO: add to device list
|
||||||
@@ -54,8 +54,8 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceRemoved(LPCWSTR pwstrDevice
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteDevice(appData->playbackDevices);
|
deleteDevice(audioData->playbackDevices);
|
||||||
deleteDevice(appData->recordingDevices);
|
deleteDevice(audioData->recordingDevices);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -65,11 +65,11 @@ HRESULT __stdcall AudioNotificationListener::OnDefaultDeviceChanged(EDataFlow fl
|
|||||||
std::vector<AudioDevice>* deviceList;
|
std::vector<AudioDevice>* deviceList;
|
||||||
if (flow == EDataFlow::eRender)
|
if (flow == EDataFlow::eRender)
|
||||||
{
|
{
|
||||||
deviceList = &appData->playbackDevices;
|
deviceList = &audioData->playbackDevices;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
deviceList = &appData->recordingDevices;
|
deviceList = &audioData->recordingDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AudioDevice& audioDevice : *deviceList)
|
for (AudioDevice& audioDevice : *deviceList)
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <mmdeviceapi.h>
|
#include <mmdeviceapi.h>
|
||||||
|
|
||||||
|
class AudioData;
|
||||||
class ApplicationData;
|
class ApplicationData;
|
||||||
class AudioNotificationListener : public IMMNotificationClient {
|
class AudioNotificationListener : public IMMNotificationClient {
|
||||||
public:
|
public:
|
||||||
ApplicationData* appData;
|
std::shared_ptr<AudioData> audioData;
|
||||||
long refCount = 1;
|
long refCount = 1;
|
||||||
|
|
||||||
AudioNotificationListener(ApplicationData* appData);
|
AudioNotificationListener(std::shared_ptr<AudioData> audioData);
|
||||||
|
|
||||||
virtual HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override;
|
virtual HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override;
|
||||||
virtual HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override;
|
virtual HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user