From 16a53dfec7494c3bebcd00ae913e49d53280a8ab Mon Sep 17 00:00:00 2001 From: Antonino Di Guardo <64427768+digant73@users.noreply.github.com> Date: Sat, 13 Jun 2026 03:13:16 +0200 Subject: [PATCH] UI: Fix drag & drop of files on main window --- rpcs3/Emu/Cell/Modules/cellAudio.cpp | 7 +++++++ rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp | 14 ++++++++++++++ rpcs3/rpcs3qt/qt_music_handler.cpp | 23 ++++++++++++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index a52482e155..557c7ef13b 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -1019,6 +1019,13 @@ void cell_audio_thread::operator()() // Destroy ringbuffer ringbuffer.reset(); + + // Destroy the audio backend on this thread (the one that created it in cfg.reset()). + // The backend's ctor calls CoInitializeEx here on Windows; releasing it on a different + // thread (g_fxo->clear() runs on the GUI thread during Kill()) would land the matching + // CoUninitialize on the GUI thread, draining its OLE reference and silently breaking the + // main window's file drag&drop. Keep COM init/teardown balanced on this thread. + cfg.backend.reset(); } audio_port* cell_audio_thread::open_port() diff --git a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp index c5204b295c..cb597d3645 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp @@ -1413,6 +1413,20 @@ void rsxaudio_backend_thread::operator()() { lock.unlock(); backend_stop(); + + // Destroy the backend on this thread, the one that created it in backend_init(). + // The backend's ctor calls CoInitializeEx here on Windows; if it is instead released + // by ~rsxaudio_backend_thread() (which runs on the GUI thread via g_fxo->clear() + // during Kill()), the matching CoUninitialize lands on the GUI thread, draining its + // OLE reference and silently breaking the main window's file drag&drop. Keep COM + // init/teardown balanced on this thread. + if (backend) + { + backend->Close(); + backend->SetWriteCallback(nullptr); + backend->SetStateCallback(nullptr); + backend = nullptr; + } return; } diff --git a/rpcs3/rpcs3qt/qt_music_handler.cpp b/rpcs3/rpcs3qt/qt_music_handler.cpp index f17e0e6d92..a7ce6b6417 100644 --- a/rpcs3/rpcs3qt/qt_music_handler.cpp +++ b/rpcs3/rpcs3qt/qt_music_handler.cpp @@ -66,15 +66,24 @@ void fmt_class_string::format(std::string& out, u64 qt_music_handler::qt_music_handler() { - music_log.notice("Constructing Qt music handler..."); + // Construct the QMediaPlayer on the GUI thread, the same thread on which it is destroyed + // (see ~qt_music_handler). cellMusic creates this handler from an emulated thread, but Qt's + // Windows multimedia backend balances its COM init/teardown per calling thread: constructing + // off the GUI thread and destroying on it left an unmatched CoUninitialize on the GUI thread, + // draining the OLE reference that Qt's startup OleInitialize set up until file drag&drop on + // the main window silently broke. Keeping both on the GUI thread keeps them balanced. + Emu.BlockingCallFromMainThread([this]() + { + music_log.notice("Constructing Qt music handler..."); - m_media_player = std::make_unique(); - m_media_player->setAudioOutput(new QAudioOutput(m_media_player.get())); + m_media_player = std::make_unique(); + m_media_player->setAudioOutput(new QAudioOutput(m_media_player.get())); - connect(m_media_player.get(), &QMediaPlayer::mediaStatusChanged, this, &qt_music_handler::handle_media_status); - connect(m_media_player.get(), &QMediaPlayer::playbackStateChanged, this, &qt_music_handler::handle_music_state); - connect(m_media_player.get(), &QMediaPlayer::errorOccurred, this, &qt_music_handler::handle_music_error); - connect(m_media_player->audioOutput(), &QAudioOutput::volumeChanged, this, &qt_music_handler::handle_volume_change); + connect(m_media_player.get(), &QMediaPlayer::mediaStatusChanged, this, &qt_music_handler::handle_media_status); + connect(m_media_player.get(), &QMediaPlayer::playbackStateChanged, this, &qt_music_handler::handle_music_state); + connect(m_media_player.get(), &QMediaPlayer::errorOccurred, this, &qt_music_handler::handle_music_error); + connect(m_media_player->audioOutput(), &QAudioOutput::volumeChanged, this, &qt_music_handler::handle_volume_change); + }); } qt_music_handler::~qt_music_handler()