From 1911ab2e1c06d44b53bd814beaac174ff4e1fb04 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 11 Jan 2020 14:20:51 +1000 Subject: [PATCH] CubebAudioStream: Initialize COM on Windows if it isn't already initialized --- src/common/cubeb_audio_stream.cpp | 36 +++++++++++++++++++++++++------ src/common/cubeb_audio_stream.h | 6 ++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/common/cubeb_audio_stream.cpp b/src/common/cubeb_audio_stream.cpp index 1a725ca53..7888e0577 100644 --- a/src/common/cubeb_audio_stream.cpp +++ b/src/common/cubeb_audio_stream.cpp @@ -3,6 +3,12 @@ #include "common/log.h" Log_SetChannel(CubebAudioStream); +#ifdef WIN32 +#include "common/windows_headers.h" +#include +#pragma comment(lib, "Ole32.lib") +#endif + CubebAudioStream::CubebAudioStream() = default; CubebAudioStream::~CubebAudioStream() @@ -15,6 +21,16 @@ bool CubebAudioStream::OpenDevice() { Assert(!IsOpen()); +#ifdef WIN32 + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + m_com_initialized_by_us = SUCCEEDED(hr); + if (FAILED(hr) && hr != RPC_E_CHANGED_MODE && hr != S_FALSE) + { + Log_ErrorPrintf("Failed to initialize COM"); + return false; + } +#endif + int rv = cubeb_init(&m_cubeb_context, "DuckStation", nullptr); if (rv != CUBEB_OK) { @@ -34,8 +50,7 @@ bool CubebAudioStream::OpenDevice() if (rv != CUBEB_OK) { Log_ErrorPrintf("Could not get minimum latency: %d", rv); - cubeb_destroy(m_cubeb_context); - m_cubeb_context = nullptr; + DestroyContext(); return false; } @@ -53,8 +68,7 @@ bool CubebAudioStream::OpenDevice() if (rv != CUBEB_OK) { Log_ErrorPrintf("Could not create stream: %d", rv); - cubeb_destroy(m_cubeb_context); - m_cubeb_context = nullptr; + DestroyContext(); return false; } @@ -84,8 +98,7 @@ void CubebAudioStream::CloseDevice() cubeb_stream_destroy(m_cubeb_stream); m_cubeb_stream = nullptr; - cubeb_destroy(m_cubeb_context); - m_cubeb_context = nullptr; + DestroyContext(); } long CubebAudioStream::DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, @@ -114,6 +127,17 @@ void CubebAudioStream::StateCallback(cubeb_stream* stream, void* user_ptr, cubeb void CubebAudioStream::BufferAvailable() {} +void CubebAudioStream::DestroyContext() +{ + cubeb_destroy(m_cubeb_context); + m_cubeb_context = nullptr; + +#ifdef WIN32 + if (m_com_initialized_by_us) + CoUninitialize(); +#endif +} + std::unique_ptr AudioStream::CreateCubebAudioStream() { return std::make_unique(); diff --git a/src/common/cubeb_audio_stream.h b/src/common/cubeb_audio_stream.h index a63c77be3..34863fd01 100644 --- a/src/common/cubeb_audio_stream.h +++ b/src/common/cubeb_audio_stream.h @@ -17,6 +17,8 @@ protected: void CloseDevice() override; void BufferAvailable() override; + void DestroyContext(); + static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, long nframes); static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state); @@ -24,4 +26,8 @@ protected: cubeb* m_cubeb_context = nullptr; cubeb_stream* m_cubeb_stream = nullptr; bool m_paused = true; + +#ifdef WIN32 + bool m_com_initialized_by_us = false; +#endif };