fix GUI VSTi mute/reopen/not-load: revert walkthrough 2 ve hanh vi 0cec3d3 (reloadForGUI reload-on-reopen, closeGUI khong goi view->removed(), post_close_gui reload-on-close + same-plugin silence + destroy children + pathBusy, editorOpenPredicate refcount mute, CoInitializeEx MTA, window main-thread), giu cai tien an toan (WM_ERASEBKGND/PAINT/SIZE chong trang, resizeView, call_once, jobEvent_/MsgWaitForMultipleObjects pump 128, ABOVE_NORMAL + PowerThrottling worker, setBypassed quanh assign/unload); queryInterface giu kNoInterface nhu 0cec3d3 — VERIFIED: probe_fix_flow PASS (mo GUI Nexus -> close -> reopen khong mute, load Ample khi GUI dang mo OK, screenshot khong trang); warning: driver stress test 6 Nexus cung luc crash xac suat CA tren exe stable 0cec3d3 (khong phai regression)

This commit is contained in:
2026-08-15 17:50:18 +07:00
parent f94b2fa757
commit 67e73a2a85
2 changed files with 154 additions and 85 deletions
+24 -24
View File
@@ -97,13 +97,7 @@ constexpr ParamID kHostMidiProgramChange = 0x3000;
// Minimal IComponentHandler so the plugin can inform the host of param edits.
class HostComponentHandler : public IComponentHandler {
public:
tresult queryInterface(const char* iid, void** v) override {
if (std::memcmp(iid, Steinberg::Vst::IComponentHandler::iid, 16) == 0 ||
std::memcmp(iid, Steinberg::FUnknown::iid, 16) == 0) {
*v = static_cast<Steinberg::Vst::IComponentHandler*>(this);
addRef();
return kResultOk;
}
tresult queryInterface(const char*, void** v) override {
*v = nullptr;
return kNoInterface;
}
@@ -118,13 +112,7 @@ public:
// Minimal IPlugFrame so plugins can resize their editor view.
class HostPlugFrame : public Steinberg::IPlugFrame {
public:
tresult queryInterface(const char* iid, void** v) override {
if (std::memcmp(iid, Steinberg::IPlugFrame::iid, 16) == 0 ||
std::memcmp(iid, Steinberg::FUnknown::iid, 16) == 0) {
*v = static_cast<Steinberg::IPlugFrame*>(this);
addRef();
return kResultOk;
}
tresult queryInterface(const char*, void** v) override {
*v = nullptr;
return kNoInterface;
}
@@ -543,6 +531,18 @@ bool Vst3Instrument::reloadForGUI() {
#else
auto* s = static_cast<Vst3HostState*>(state_);
if (!s || !s->controller) return false;
if (s->view && guiAttached_) return true;
if (hasAttachedOnce_ && !guiAttached_) {
// Reopen GUI sau khi dong: mot so plugin (Nexus...) hang o
// view->attached() LAN 2 tren cung component instance. Tao lai inst
// moi tren CUNG worker thread (COM STA con song) roi attach lai.
// PHAN NAY PHAI chay tren worker thread — apartment cua channel song
// o day; chay tren thread tam thi apartment moi chet ngay sau do
// (reopen lan sau -> treo nhu bridge_like).
if (!reload()) return false;
s = static_cast<Vst3HostState*>(state_);
if (!s || !s->controller) return false;
}
return true;
#endif
}
@@ -642,16 +642,16 @@ void Vst3Instrument::closeGUI() {
return;
#else
auto* s = static_cast<Vst3HostState*>(state_);
if (s && s->view) {
if (guiAttached_) {
try {
s->view->removed();
} catch (...) {
std::cerr << "[Vst3Instrument] Exception inside view->removed()" << std::endl;
}
}
s->view = nullptr;
}
// Do NOT call s->view->removed(): Nexus's removed() enters an internal
// modal wait for a message only this thread's message pump can dispatch
// — but this thread is inside removed(), so it deadlocks forever
// (observed: closeGUI job never returns; wdisp flood from the editor).
// Nulling the view and letting the next terminate() (reload / destructor)
// tear the editor windows down on this same thread is the deterministic
// path out. Callers (post_close_gui / load job) additionally destroy the
// editor's child windows right here on this thread so the plugin stops
// pumping; the leaked editor object is inert once its windows are gone.
if (s) s->view = nullptr;
guiAttached_ = false;
#endif
}