Fix GUI Qin không hiện lại sau hide + âm thanh lỗi sau khi đóng cửa sổ
- plugin_host_main.cpp: chặn WM_CLOSE (đóng GUI nhưng giữ window sống, hide thay vì destroy), WM_DESTROY reset hwnd; dùng g_hostHwnd toàn cục thay hwnd local để control OPEN_GUI/CLOSE_GUI tái sử dụng đúng window. - main.cpp: bỏ qua dedupe hasAttachedView cho instrument child-own (SandboxVst2Host) — bridge guiOpen_ stale sau khi child tự đóng nên OPEN_GUI lặp lại phải forward control 4; child tự chặn double-open. - Verify: WM_CLOSE -> window ẩn còn sống; OPEN_GUI lần 2 -> window hiện lại, âm ch1 vẫn kêu (peak 0.15), không câm.
This commit is contained in:
@@ -1096,7 +1096,7 @@ int main(int argc, char* argv[]) {
|
|||||||
// attached -> GUI da mo, khong post attach job lan nua. Re-attach
|
// attached -> GUI da mo, khong post attach job lan nua. Re-attach
|
||||||
// tren view dang attached lam plugin loi (Nexus createView null).
|
// tren view dang attached lam plugin loi (Nexus createView null).
|
||||||
if (instruments.withInstrument(guiCh, [](INativeInstrument* i0) {
|
if (instruments.withInstrument(guiCh, [](INativeInstrument* i0) {
|
||||||
return i0 && i0->hasAttachedView();
|
return i0 && i0->hasAttachedView() && !i0->ownsGuiWindow();
|
||||||
})) {
|
})) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1120,7 +1120,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (auto* inst0 = instruments.get(guiCh)) {
|
if (auto* inst0 = instruments.get(guiCh)) {
|
||||||
if (inst0->hasAttachedView()) {
|
if (inst0->hasAttachedView() && !inst0->ownsGuiWindow()) {
|
||||||
// Dedupe race: main da silence (setReloading) truoc khi post —
|
// Dedupe race: main da silence (setReloading) truoc khi post —
|
||||||
// restore de channel khong cam vinh vien.
|
// restore de channel khong cam vinh vien.
|
||||||
std::vector<uint32_t> sp = same_plugin_channels(guiCh);
|
std::vector<uint32_t> sp = same_plugin_channels(guiCh);
|
||||||
|
|||||||
@@ -38,10 +38,41 @@ static bool parent_alive(uint32_t pid) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// G4.7: the child owns the host window, so the user's X click lands HERE, not
|
||||||
|
// on the bridge. DefWindowProc destroys the window on WM_CLOSE while the VST2
|
||||||
|
// instrument still thinks its editor is attached (guiAttached_ stale true) -
|
||||||
|
// a second OPEN_GUI then can never re-show the GUI (bridge dedupes on
|
||||||
|
// hasAttachedView, and the child's openGUI guard skips too). Intercept:
|
||||||
|
// WM_CLOSE -> effEditClose + hide (keep the window alive, reopen works);
|
||||||
|
// WM_DESTROY (external destroy) -> forget the hwnd so the next OPEN_GUI
|
||||||
|
// creates a fresh window instead of attaching to a dead one.
|
||||||
|
static INativeInstrument* g_wndInst = nullptr;
|
||||||
|
static HWND g_hostHwnd = nullptr;
|
||||||
|
|
||||||
|
static LRESULT CALLBACK PluginHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
switch (msg) {
|
||||||
|
case WM_CLOSE:
|
||||||
|
if (g_wndInst) {
|
||||||
|
try { g_wndInst->closeGUI(); } catch (...) {}
|
||||||
|
}
|
||||||
|
if (g_hostHwnd) ShowWindow(g_hostHwnd, SW_HIDE);
|
||||||
|
return 0; // swallow: do NOT let DefWindowProc destroy the window
|
||||||
|
case WM_DESTROY:
|
||||||
|
if (g_wndInst) {
|
||||||
|
try { g_wndInst->closeGUI(); } catch (...) {}
|
||||||
|
}
|
||||||
|
g_hostHwnd = nullptr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
static HWND make_host_window() {
|
static HWND make_host_window() {
|
||||||
WNDCLASSEX wc = {};
|
WNDCLASSEX wc = {};
|
||||||
wc.cbSize = sizeof(wc);
|
wc.cbSize = sizeof(wc);
|
||||||
wc.lpfnWndProc = DefWindowProc;
|
wc.lpfnWndProc = PluginHostWndProc;
|
||||||
wc.hInstance = GetModuleHandle(nullptr);
|
wc.hInstance = GetModuleHandle(nullptr);
|
||||||
wc.lpszClassName = "PluginHostClass";
|
wc.lpszClassName = "PluginHostClass";
|
||||||
RegisterClassEx(&wc);
|
RegisterClassEx(&wc);
|
||||||
@@ -106,6 +137,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
INativeInstrument& inst = vst2 ? (INativeInstrument&)instV2 : (INativeInstrument&)instV3;
|
INativeInstrument& inst = vst2 ? (INativeInstrument&)instV2 : (INativeInstrument&)instV3;
|
||||||
|
g_wndInst = &inst; // WM_CLOSE (user X) needs the live instrument
|
||||||
|
|
||||||
// G4.6 auto-play fix: a loaded chunk can embed a stuck/sustained note
|
// G4.6 auto-play fix: a loaded chunk can embed a stuck/sustained note
|
||||||
// (factory state, seed, or a patch captured mid-note). Release everything
|
// (factory state, seed, or a patch captured mid-note). Release everything
|
||||||
@@ -145,12 +177,12 @@ int main(int argc, char* argv[]) {
|
|||||||
// VST3: GUI on the main thread at startup (editorhost pattern: attach then
|
// VST3: GUI on the main thread at startup (editorhost pattern: attach then
|
||||||
// pump below). VST2: deferred until control 4 (OPEN_GUI) so loading a Qin
|
// pump below). VST2: deferred until control 4 (OPEN_GUI) so loading a Qin
|
||||||
// does not pop a window for every track.
|
// does not pop a window for every track.
|
||||||
HWND hwnd = nullptr;
|
g_hostHwnd = nullptr;
|
||||||
if (!vst2) {
|
if (!vst2) {
|
||||||
hwnd = make_host_window();
|
g_hostHwnd = make_host_window();
|
||||||
printf("[plugin_host] ownHwnd=%p openGUI...\n", (void*)hwnd);
|
printf("[plugin_host] ownHwnd=%p openGUI...\n", (void*)g_hostHwnd);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
bool gui = inst.openGUI(hwnd);
|
bool gui = inst.openGUI(g_hostHwnd);
|
||||||
printf("[plugin_host] openGUI=%d\n", gui ? 1 : 0);
|
printf("[plugin_host] openGUI=%d\n", gui ? 1 : 0);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@@ -208,16 +240,16 @@ int main(int argc, char* argv[]) {
|
|||||||
for (uint32_t i = 0; i < nctl; ++i) {
|
for (uint32_t i = 0; i < nctl; ++i) {
|
||||||
const auto& c = ipc->base.controlQueue[i];
|
const auto& c = ipc->base.controlQueue[i];
|
||||||
if (c.type == 4) {
|
if (c.type == 4) {
|
||||||
if (!hwnd) hwnd = make_host_window();
|
if (!g_hostHwnd) g_hostHwnd = make_host_window();
|
||||||
if (hwnd && !inst.hasAttachedView()) {
|
if (g_hostHwnd && !inst.hasAttachedView()) {
|
||||||
printf("[plugin_host] OPEN_GUI ch=%u\n", channel);
|
printf("[plugin_host] OPEN_GUI ch=%u\n", channel);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
inst.openGUI(hwnd);
|
inst.openGUI(g_hostHwnd);
|
||||||
ShowWindow(hwnd, SW_SHOW);
|
ShowWindow(g_hostHwnd, SW_SHOW);
|
||||||
}
|
}
|
||||||
} else if (c.type == 5) {
|
} else if (c.type == 5) {
|
||||||
inst.closeGUI();
|
inst.closeGUI();
|
||||||
if (hwnd) ShowWindow(hwnd, SW_HIDE);
|
if (g_hostHwnd) ShowWindow(g_hostHwnd, SW_HIDE);
|
||||||
} else if (c.type == 6) {
|
} else if (c.type == 6) {
|
||||||
quit = true;
|
quit = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user