From 62c137157ed04d08e6bcc7a741bcdb046943776f Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Wed, 17 Aug 2016 21:40:22 +0200
Subject: compat/win32-com: default to right COM type without caller specifying
 it

The main window always needs the apartment threaded context for OLE used by
Qt. Default to apartment threaded before a QApplication is created, or if the
thread is the QApplication thread. Use multithreaded COM otherwise.
---
 compat/camera-names.cpp |  2 +-
 compat/win32-com.cpp    | 15 ++++++++++++++-
 compat/win32-com.hpp    |  3 ++-
 cv/camera-dialog.cpp    |  2 +-
 dinput/dinput.cpp       |  2 +-
 gui/main.cpp            |  5 ++---
 6 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/compat/camera-names.cpp b/compat/camera-names.cpp
index 21ff3b52..2f4c2f91 100644
--- a/compat/camera-names.cpp
+++ b/compat/camera-names.cpp
@@ -33,7 +33,7 @@ OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names()
 #if defined(_WIN32)
     // Create the System Device Enumerator.
     HRESULT hr;
-    init_com_threading(com_apartment);
+    init_com_threading();
     ICreateDevEnum *pSysDevEnum = NULL;
     hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
     if (FAILED(hr))
diff --git a/compat/win32-com.cpp b/compat/win32-com.cpp
index 689e1411..7bebc500 100644
--- a/compat/win32-com.cpp
+++ b/compat/win32-com.cpp
@@ -5,11 +5,24 @@
 #include "compat/util.hpp"
 
 #include <QString>
+#include <QCoreApplication>
+#include <QApplication>
 #include <QThread>
 #include <QDebug>
 
-bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t)
+bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t_)
 {
+    const com_type t = progn(
+                           if (t_ != com_invalid)
+                               return t_;
+                           if (QCoreApplication::instance() == nullptr)
+                               return com_apartment;
+                           if (qApp->thread() == QThread::currentThread())
+                               return com_apartment;
+                           else
+                               return com_multithreaded;
+                       );
+
     HRESULT ret = CoInitializeEx(0, t);
 
     if (ret != S_OK && ret != S_FALSE)
diff --git a/compat/win32-com.hpp b/compat/win32-com.hpp
index 4e535815..fe2b478f 100644
--- a/compat/win32-com.hpp
+++ b/compat/win32-com.hpp
@@ -11,8 +11,9 @@ enum com_type : int
 {
     com_multithreaded = COINIT_MULTITHREADED,
     com_apartment = COINIT_APARTMENTTHREADED,
+    com_invalid = 0,
 };
 
-bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t);
+bool OPENTRACK_COMPAT_EXPORT init_com_threading(com_type t = com_invalid);
 
 #endif
diff --git a/cv/camera-dialog.cpp b/cv/camera-dialog.cpp
index c3e8f6fe..b422e63c 100644
--- a/cv/camera-dialog.cpp
+++ b/cv/camera-dialog.cpp
@@ -25,7 +25,7 @@ camera_dialog::~camera_dialog() {}
 void camera_dialog::open_camera_settings(cv::VideoCapture* cap, const QString& camera_name, QMutex* camera_mtx)
 {
 #ifdef _WIN32
-    init_com_threading(com_apartment);
+    init_com_threading();
 
     if (cap)
     {
diff --git a/dinput/dinput.cpp b/dinput/dinput.cpp
index 1b0cf09d..93aca79a 100644
--- a/dinput/dinput.cpp
+++ b/dinput/dinput.cpp
@@ -9,7 +9,7 @@ std::atomic_flag dinput_handle::init_lock = ATOMIC_FLAG_INIT;
 
 LPDIRECTINPUT8& dinput_handle::init_di()
 {
-    init_com_threading(com_multithreaded);
+    init_com_threading();
 
     static LPDIRECTINPUT8 di_ = nullptr;
     if (di_ == nullptr)
diff --git a/gui/main.cpp b/gui/main.cpp
index fd41cbd3..e7c9c239 100644
--- a/gui/main.cpp
+++ b/gui/main.cpp
@@ -112,7 +112,7 @@ static void add_program_library_path()
 int main(int argc, char** argv)
 {
 #ifdef _WIN32
-    init_com_threading(com_apartment);
+    init_com_threading();
     add_program_library_path();
 #elif !defined(__linux)
     // workaround QTBUG-38598
@@ -126,13 +126,12 @@ int main(int argc, char** argv)
     QApplication app(argc, argv);
 
     set_qt_style();
+    MainWindow::set_working_directory();
 
 #ifdef _WIN32
     add_win32_path();
 #endif
 
-    MainWindow::set_working_directory();
-
     {
         mem<MainWindow> w = std::make_shared<MainWindow>();
 
-- 
cgit v1.2.3