From 1068c1b06f1bea8791295765b72ca4d65fe18ba4 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 27 Feb 2019 16:07:06 -0500
Subject: [PATCH] audio_core/cubeb_sink: Ensure COM is initialized on Windows
 prior to calling cubeb_init

cubeb now requires that COM explicitly be initialized on the thread
prior to calling cubeb_init.
---
 src/audio_core/cubeb_sink.cpp | 15 +++++++++++++++
 src/audio_core/cubeb_sink.h   |  4 ++++
 2 files changed, 19 insertions(+)

diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index dc45dedd3..1da0b9f2a 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -12,6 +12,10 @@
 #include "common/ring_buffer.h"
 #include "core/settings.h"
 
+#ifdef _MSC_VER
+#include <objbase.h>
+#endif
+
 namespace AudioCore {
 
 class CubebSinkStream final : public SinkStream {
@@ -108,6 +112,11 @@ private:
 };
 
 CubebSink::CubebSink(std::string_view target_device_name) {
+    // Cubeb requires COM to be initialized on the thread calling cubeb_init on Windows
+#ifdef _MSC_VER
+    com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+#endif
+
     if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) {
         LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
         return;
@@ -142,6 +151,12 @@ CubebSink::~CubebSink() {
     }
 
     cubeb_destroy(ctx);
+
+#ifdef _MSC_VER
+    if (SUCCEEDED(com_init_result)) {
+        CoUninitialize();
+    }
+#endif
 }
 
 SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels,
diff --git a/src/audio_core/cubeb_sink.h b/src/audio_core/cubeb_sink.h
index efb9d1634..511df7bb1 100644
--- a/src/audio_core/cubeb_sink.h
+++ b/src/audio_core/cubeb_sink.h
@@ -25,6 +25,10 @@ private:
     cubeb* ctx{};
     cubeb_devid output_device{};
     std::vector<SinkStreamPtr> sink_streams;
+
+#ifdef _MSC_VER
+    u32 com_init_result = 0;
+#endif
 };
 
 std::vector<std::string> ListCubebSinkDevices();