wip walkthrough 2 bridge: jobEvent_/MsgWaitForMultipleObjects pump, SetThreadPriority + PowerThrottling, isBypassed silence quanh assign/unload, closeGUI view->removed(), reloadForGUI reuse instance, bo mute khi GUI mo, CoInitializeEx MTA — CHƯA verified: driver test 1/3 PASS (AV c0000005 Nexus!GetPluginFactory luc attachView ch5, nghi MTA/bo mute), exe deploy giu ban 0cec3d3 (28104a47)

This commit is contained in:
2026-08-15 17:11:47 +07:00
parent 0cec3d3cce
commit f94b2fa757
6 changed files with 220 additions and 152 deletions
+34 -24
View File
@@ -97,7 +97,13 @@ 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*, void** v) override {
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;
}
*v = nullptr;
return kNoInterface;
}
@@ -112,7 +118,13 @@ public:
// Minimal IPlugFrame so plugins can resize their editor view.
class HostPlugFrame : public Steinberg::IPlugFrame {
public:
tresult queryInterface(const char*, void** v) override {
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;
}
*v = nullptr;
return kNoInterface;
}
@@ -531,18 +543,6 @@ 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
}
@@ -598,6 +598,16 @@ bool Vst3Instrument::attachView(void* parentWindowHandle) {
#endif
}
void Vst3Instrument::resizeView(int w, int h) {
#ifdef HAVE_VST3SDK
auto* s = static_cast<Vst3HostState*>(state_);
if (s && s->view) {
Steinberg::ViewRect rect(0, 0, w, h);
s->view->onSize(&rect);
}
#endif
}
bool Vst3Instrument::hasAttachedView() const {
return state_ != nullptr && guiAttached_;
}
@@ -632,16 +642,16 @@ void Vst3Instrument::closeGUI() {
return;
#else
auto* s = static_cast<Vst3HostState*>(state_);
// 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;
if (s && s->view) {
if (guiAttached_) {
try {
s->view->removed();
} catch (...) {
std::cerr << "[Vst3Instrument] Exception inside view->removed()" << std::endl;
}
}
s->view = nullptr;
}
guiAttached_ = false;
#endif
}