CubebAudioStream: Initialize COM on Windows if it isn't already initialized

This commit is contained in:
Connor McLaughlin 2020-01-11 14:20:51 +10:00
parent d52d6252a9
commit 1911ab2e1c
2 changed files with 36 additions and 6 deletions

View file

@ -3,6 +3,12 @@
#include "common/log.h" #include "common/log.h"
Log_SetChannel(CubebAudioStream); Log_SetChannel(CubebAudioStream);
#ifdef WIN32
#include "common/windows_headers.h"
#include <objbase.h>
#pragma comment(lib, "Ole32.lib")
#endif
CubebAudioStream::CubebAudioStream() = default; CubebAudioStream::CubebAudioStream() = default;
CubebAudioStream::~CubebAudioStream() CubebAudioStream::~CubebAudioStream()
@ -15,6 +21,16 @@ bool CubebAudioStream::OpenDevice()
{ {
Assert(!IsOpen()); 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); int rv = cubeb_init(&m_cubeb_context, "DuckStation", nullptr);
if (rv != CUBEB_OK) if (rv != CUBEB_OK)
{ {
@ -34,8 +50,7 @@ bool CubebAudioStream::OpenDevice()
if (rv != CUBEB_OK) if (rv != CUBEB_OK)
{ {
Log_ErrorPrintf("Could not get minimum latency: %d", rv); Log_ErrorPrintf("Could not get minimum latency: %d", rv);
cubeb_destroy(m_cubeb_context); DestroyContext();
m_cubeb_context = nullptr;
return false; return false;
} }
@ -53,8 +68,7 @@ bool CubebAudioStream::OpenDevice()
if (rv != CUBEB_OK) if (rv != CUBEB_OK)
{ {
Log_ErrorPrintf("Could not create stream: %d", rv); Log_ErrorPrintf("Could not create stream: %d", rv);
cubeb_destroy(m_cubeb_context); DestroyContext();
m_cubeb_context = nullptr;
return false; return false;
} }
@ -84,8 +98,7 @@ void CubebAudioStream::CloseDevice()
cubeb_stream_destroy(m_cubeb_stream); cubeb_stream_destroy(m_cubeb_stream);
m_cubeb_stream = nullptr; m_cubeb_stream = nullptr;
cubeb_destroy(m_cubeb_context); DestroyContext();
m_cubeb_context = nullptr;
} }
long CubebAudioStream::DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, 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::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> AudioStream::CreateCubebAudioStream() std::unique_ptr<AudioStream> AudioStream::CreateCubebAudioStream()
{ {
return std::make_unique<CubebAudioStream>(); return std::make_unique<CubebAudioStream>();

View file

@ -17,6 +17,8 @@ protected:
void CloseDevice() override; void CloseDevice() override;
void BufferAvailable() override; void BufferAvailable() override;
void DestroyContext();
static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer,
long nframes); long nframes);
static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state); static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state);
@ -24,4 +26,8 @@ protected:
cubeb* m_cubeb_context = nullptr; cubeb* m_cubeb_context = nullptr;
cubeb_stream* m_cubeb_stream = nullptr; cubeb_stream* m_cubeb_stream = nullptr;
bool m_paused = true; bool m_paused = true;
#ifdef WIN32
bool m_com_initialized_by_us = false;
#endif
}; };