AudioCommon/WASAPI: Use WRL/WIL whenever possible

This fixes numerous resource leaks, as not every return path cleaned every created resource
Now they are all managed automatically and "commited" to WASAPIStream class fields only
after it's certain they initialized properly
This commit is contained in:
Silent
2019-08-16 23:53:47 +02:00
parent 374629ef30
commit c5a372ab2a
2 changed files with 105 additions and 157 deletions

View File

@ -5,16 +5,19 @@
#pragma once
#ifdef _WIN32
// clang-format off
#include <Windows.h>
#include <mmreg.h>
#include <objbase.h>
#include <wil/resource.h>
// clang-format on
#endif
#include <atomic>
#include <string>
#include <thread>
#include <vector>
#include <wrl/client.h>
#include "AudioCommon/SoundStream.h"
@ -23,6 +26,8 @@ struct IAudioRenderClient;
struct IMMDevice;
struct IMMDeviceEnumerator;
#endif
class WASAPIStream final : public SoundStream
{
#ifdef _WIN32
@ -35,7 +40,7 @@ public:
static bool isValid();
static std::vector<std::string> GetAvailableDevices();
static IMMDevice* GetDeviceByName(std::string name);
static Microsoft::WRL::ComPtr<IMMDevice> GetDeviceByName(std::string name);
private:
u32 m_frames_in_buffer = 0;
@ -43,10 +48,14 @@ private:
std::atomic<bool> m_stopped = false;
std::thread m_thread;
IAudioClient* m_audio_client = nullptr;
IAudioRenderClient* m_audio_renderer = nullptr;
IMMDeviceEnumerator* m_enumerator = nullptr;
HANDLE m_need_data_event = nullptr;
// CoUninitialize must be called after all WASAPI COM objects have been destroyed,
// therefore this member must be located before them, as first class fields are destructed last
wil::unique_couninitialize_call m_coinitialize{false};
Microsoft::WRL::ComPtr<IMMDeviceEnumerator> m_enumerator;
Microsoft::WRL::ComPtr<IAudioClient> m_audio_client;
Microsoft::WRL::ComPtr<IAudioRenderClient> m_audio_renderer;
wil::unique_event_nothrow m_need_data_event;
WAVEFORMATEXTENSIBLE m_format;
#endif // _WIN32
};