diff --git a/AsuroTool/ApplicationData.cpp b/AsuroTool/ApplicationData.cpp index 8f22789..b0e5bd8 100644 --- a/AsuroTool/ApplicationData.cpp +++ b/AsuroTool/ApplicationData.cpp @@ -37,13 +37,54 @@ AudioDevice::~AudioDevice() if (volumeInterface) { volumeInterface->Release(); + volumeInterface = nullptr; } if (meterInterface) { meterInterface->Release(); + meterInterface = nullptr; } if (device) { 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; } } diff --git a/AsuroTool/ApplicationData.h b/AsuroTool/ApplicationData.h index b899e4b..6b9c8bb 100644 --- a/AsuroTool/ApplicationData.h +++ b/AsuroTool/ApplicationData.h @@ -24,6 +24,19 @@ public: ~AudioDevice(); }; +class AudioData { +public: + std::vector playbackDevices = {}; + std::vector recordingDevices = {}; + IMMDeviceEnumerator* deviceEnumerator = nullptr; + AudioNotificationListener* audioNotificationListener = nullptr; + + AudioData(); + AudioData(AudioData&& other) noexcept; + AudioData& operator=(AudioData&& other) noexcept; + ~AudioData(); +}; + class ApplicationSettings { public: bool showDisabledDevices = false; @@ -33,8 +46,5 @@ public: class ApplicationData { public: ApplicationSettings settings = {}; - std::vector playbackDevices = {}; - std::vector recordingDevices = {}; - IMMDeviceEnumerator* deviceEnumerator = nullptr; - AudioNotificationListener* audioNotificationListener = nullptr; + std::shared_ptr audioData = std::make_shared(); }; diff --git a/AsuroTool/AsuroTool.cpp b/AsuroTool/AsuroTool.cpp index 1ee9386..0b8b825 100644 --- a/AsuroTool/AsuroTool.cpp +++ b/AsuroTool/AsuroTool.cpp @@ -40,14 +40,14 @@ void init(DrawData& drawData, void* customData) audioResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); 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: "); - appData->audioNotificationListener = new AudioNotificationListener(appData); - audioResult = appData->deviceEnumerator->RegisterEndpointNotificationCallback(appData->audioNotificationListener); + appData->audioData->audioNotificationListener = new AudioNotificationListener(appData->audioData); + audioResult = appData->audioData->deviceEnumerator->RegisterEndpointNotificationCallback(appData->audioData->audioNotificationListener); isError(audioResult, "Failed to register audio notification listener: "); - reloadDeviceLists(appData); + reloadDeviceLists(*appData->audioData); // Set window icon LPWSTR iconId = MAKEINTRESOURCE(IDI_ICON1); @@ -70,14 +70,14 @@ void draw(DrawData& drawData, void* customData) // Playback Devices ImGui::SetNextWindowPos(ImVec2(0, customYCursor)); 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.; // Recording devices ImGui::SetNextWindowPos(ImVec2(0, customYCursor)); 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 if (appData->settings.fitWindowHeight) @@ -103,7 +103,7 @@ ImVec2 menuBar(ApplicationData* appData) { if (ImGui::Button("Manual Refresh")) { - reloadDeviceLists(appData); + reloadDeviceLists(*appData->audioData); } ImGui::EndMenu(); } @@ -196,7 +196,7 @@ ImVec2 audioDeviceWindow(ApplicationData* appData, std::vector& dev } 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(); @@ -206,7 +206,7 @@ ImVec2 audioDeviceWindow(ApplicationData* appData, std::vector& dev } 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); } } diff --git a/AsuroTool/AudioApi.cpp b/AsuroTool/AudioApi.cpp index 425adc7..124378d 100644 --- a/AsuroTool/AudioApi.cpp +++ b/AsuroTool/AudioApi.cpp @@ -6,7 +6,6 @@ #include #include -#include "ImguiBase.h" #include "Util.h" #include "AudioApi.h" #include "PolicyConfig.h" @@ -25,7 +24,7 @@ HRESULT getDevicePropertyString(IPropertyStore* propertyStore, const PROPERTYKEY return result; } -void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ERole role) +void setDefaultAudioDevice(AudioData& audioData, const wchar_t* deviceId, ERole role) { IPolicyConfigVista* pPolicyConfig; @@ -34,18 +33,18 @@ void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ER { hr = pPolicyConfig->SetDefaultEndpoint(deviceId, role); pPolicyConfig->Release(); - reloadDeviceLists(appData); + reloadDeviceLists(audioData); } } -void loadAudioDevices(ApplicationData* appData, std::vector& deviceList, EDataFlow deviceType) +void loadAudioDevices(AudioData& audioData, std::vector& deviceList, EDataFlow deviceType) { deviceList.clear(); HRESULT err; 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; UINT deviceCount; @@ -54,7 +53,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector& device IMMDevice* defaultConsoleDevice = NULL; LPWSTR defaultConsoleId = nullptr; - err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eConsole, &defaultConsoleDevice); + err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eConsole, &defaultConsoleDevice); if (!FAILED(err)) { defaultConsoleDevice->GetId(&defaultConsoleId); @@ -62,7 +61,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector& device IMMDevice* defaultMediaOutput = NULL; LPWSTR defaultMediaId = nullptr; - err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eMultimedia, &defaultMediaOutput); + err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eMultimedia, &defaultMediaOutput); if (!FAILED(err)) { defaultMediaOutput->GetId(&defaultMediaId); @@ -70,7 +69,7 @@ void loadAudioDevices(ApplicationData* appData, std::vector& device IMMDevice* defaultCommunicationOutput = NULL; LPWSTR defaultCommunicationId = nullptr; - err = appData->deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eCommunications, &defaultCommunicationOutput); + err = audioData.deviceEnumerator->GetDefaultAudioEndpoint(deviceType, ERole::eCommunications, &defaultCommunicationOutput); if (!FAILED(err)) { defaultCommunicationOutput->GetId(&defaultCommunicationId); @@ -141,10 +140,10 @@ void loadAudioDevices(ApplicationData* appData, std::vector& device } } -void reloadDeviceLists(ApplicationData* appData) +void reloadDeviceLists(AudioData& audioData) { - loadAudioDevices(appData, appData->playbackDevices, EDataFlow::eRender); - loadAudioDevices(appData, appData->recordingDevices, EDataFlow::eCapture); + loadAudioDevices(audioData, audioData.playbackDevices, EDataFlow::eRender); + loadAudioDevices(audioData, audioData.recordingDevices, EDataFlow::eCapture); } float getVolume(IAudioEndpointVolume* volumeInterface) diff --git a/AsuroTool/AudioApi.h b/AsuroTool/AudioApi.h index 3a1bf1b..aff5d09 100644 --- a/AsuroTool/AudioApi.h +++ b/AsuroTool/AudioApi.h @@ -6,8 +6,8 @@ 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"); -void setDefaultAudioDevice(ApplicationData* appData, const wchar_t* deviceId, ERole role); -void loadAudioDevices(ApplicationData* appData, std::vector& deviceList, EDataFlow deviceType); -void reloadDeviceLists(ApplicationData* appData); +void setDefaultAudioDevice(AudioData& audioData, const wchar_t* deviceId, ERole role); +void loadAudioDevices(AudioData& audioData, std::vector& deviceList, EDataFlow deviceType); +void reloadDeviceLists(AudioData& audioData); float getVolume(IAudioEndpointVolume* volumeInterface); float getMeterValue(IAudioMeterInformation* meterInterface); diff --git a/AsuroTool/AudioNotificationListener.cpp b/AsuroTool/AudioNotificationListener.cpp index f62939e..c725578 100644 --- a/AsuroTool/AudioNotificationListener.cpp +++ b/AsuroTool/AudioNotificationListener.cpp @@ -4,7 +4,7 @@ #include "AudioNotificationListener.h" -AudioNotificationListener::AudioNotificationListener(ApplicationData* appData) : appData(appData) +AudioNotificationListener::AudioNotificationListener(std::shared_ptr audioData) : audioData(audioData) { } @@ -22,8 +22,8 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceStateChanged(LPCWSTR pwstrD } }; - updateDevice(appData->playbackDevices); - updateDevice(appData->recordingDevices); + updateDevice(audioData->playbackDevices); + updateDevice(audioData->recordingDevices); return S_OK; } @@ -31,7 +31,7 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceStateChanged(LPCWSTR pwstrD HRESULT __stdcall AudioNotificationListener::OnDeviceAdded(LPCWSTR pwstrDeviceId) { IMMDevice* newDevice; - HRESULT result = appData->deviceEnumerator->GetDevice(pwstrDeviceId, &newDevice); + HRESULT result = audioData->deviceEnumerator->GetDevice(pwstrDeviceId, &newDevice); if (SUCCEEDED(result) && newDevice != nullptr) { // TODO: add to device list @@ -54,8 +54,8 @@ HRESULT __stdcall AudioNotificationListener::OnDeviceRemoved(LPCWSTR pwstrDevice } }; - deleteDevice(appData->playbackDevices); - deleteDevice(appData->recordingDevices); + deleteDevice(audioData->playbackDevices); + deleteDevice(audioData->recordingDevices); return S_OK; } @@ -65,11 +65,11 @@ HRESULT __stdcall AudioNotificationListener::OnDefaultDeviceChanged(EDataFlow fl std::vector* deviceList; if (flow == EDataFlow::eRender) { - deviceList = &appData->playbackDevices; + deviceList = &audioData->playbackDevices; } else { - deviceList = &appData->recordingDevices; + deviceList = &audioData->recordingDevices; } for (AudioDevice& audioDevice : *deviceList) diff --git a/AsuroTool/AudioNotificationListener.h b/AsuroTool/AudioNotificationListener.h index 2242590..1f3c66e 100644 --- a/AsuroTool/AudioNotificationListener.h +++ b/AsuroTool/AudioNotificationListener.h @@ -1,14 +1,16 @@ #pragma once +#include #include +class AudioData; class ApplicationData; class AudioNotificationListener : public IMMNotificationClient { public: - ApplicationData* appData; + std::shared_ptr audioData; long refCount = 1; - AudioNotificationListener(ApplicationData* appData); + AudioNotificationListener(std::shared_ptr audioData); virtual HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override; virtual HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override;