fix(bridge): noteId match noteOn (0) for noteOff; create VST GUI window on main thread, attach on worker
This commit is contained in:
@@ -80,7 +80,7 @@ public:
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("usage: gui_probe <plugin.vst3> [variant] [secs] [hwnd]\n"
|
||||
"variants: main_own | worker_own_nopump | worker_own_pump | worker_foreign_nopump | worker_foreign_pump | bridge_like | same_thread | two_instances | two_instances_close | close_reopen | bridge_two | shared_worker\n");
|
||||
"variants: main_own | worker_own_nopump | worker_own_pump | worker_foreign_nopump | worker_foreign_pump | bridge_like | same_thread | two_instances | two_instances_close | close_reopen | bridge_two | shared_worker | two_workers_close\n");
|
||||
return 2;
|
||||
}
|
||||
std::string path = argv[1];
|
||||
@@ -315,6 +315,99 @@ int main(int argc, char* argv[]) {
|
||||
aDone.load() ? 1 : 0, aOk.load() ? 1 : 0,
|
||||
bDone.load() ? 1 : 0, bOk.load() ? 1 : 0);
|
||||
return (aDone.load() && aOk.load() && bDone.load() && bOk.load()) ? 0 : 3;
|
||||
} else if (variant == "two_workers_close") {
|
||||
// Round-4 exact bridge pattern: per-channel workers (own STA
|
||||
// apartments); attach via temp thread + WORKER nested pump (the bridge
|
||||
// main.cpp job pumps the worker queue while attachView runs on a
|
||||
// temporary thread); close editor inst1 before attaching inst2 on its
|
||||
// own worker.
|
||||
ProbeWorker wa, wb;
|
||||
wa.start();
|
||||
wb.start();
|
||||
std::atomic<bool> aDone{false}, aOk{false}, bDone{false}, bOk{false};
|
||||
wa.post([&]() {
|
||||
printf("[two_workers_close] workerA load inst1\n");
|
||||
fflush(stdout);
|
||||
bool r = inst.loadPlugin(path, 44100.0);
|
||||
printf("[two_workers_close] workerA load inst1=%d\n", r ? 1 : 0);
|
||||
fflush(stdout);
|
||||
if (r) {
|
||||
HWND h = CreateWindowEx(0, "GuiProbeClass", "ProbeA", WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 800, 600, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
printf("[two_workers_close] workerA hwnd=%p\n", (void*)h);
|
||||
fflush(stdout);
|
||||
bool r2 = false;
|
||||
std::atomic<bool> d{false};
|
||||
std::thread t([&]() {
|
||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
r2 = inst.attachView(h);
|
||||
CoUninitialize();
|
||||
d = true;
|
||||
});
|
||||
while (!d.load()) {
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
t.join();
|
||||
printf("[two_workers_close] workerA attach inst1=%d\n", r2 ? 1 : 0);
|
||||
fflush(stdout);
|
||||
aOk = r2;
|
||||
inst.closeGUI(); // view->removed() on worker A
|
||||
printf("[two_workers_close] workerA closeGUI inst1\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
aDone = true;
|
||||
});
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto elapsed = [&]() {
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::steady_clock::now() - t0).count();
|
||||
};
|
||||
while (!aDone.load() && elapsed() < secs) Sleep(50);
|
||||
if (!aDone.load()) { printf("RESULT: TIMEOUT inst1 (aDone=0)\n"); return 3; }
|
||||
wb.post([&]() {
|
||||
printf("[two_workers_close] workerB load inst2\n");
|
||||
fflush(stdout);
|
||||
bool r = inst2.loadPlugin(path, 44100.0);
|
||||
printf("[two_workers_close] workerB load inst2=%d\n", r ? 1 : 0);
|
||||
fflush(stdout);
|
||||
if (r) {
|
||||
HWND h = CreateWindowEx(0, "GuiProbeClass", "ProbeB", WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 800, 600, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
printf("[two_workers_close] workerB hwnd=%p\n", (void*)h);
|
||||
fflush(stdout);
|
||||
bool r2 = false;
|
||||
std::atomic<bool> d{false};
|
||||
std::thread t([&]() {
|
||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
r2 = inst2.attachView(h);
|
||||
CoUninitialize();
|
||||
d = true;
|
||||
});
|
||||
while (!d.load()) {
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
t.join();
|
||||
printf("[two_workers_close] workerB attach inst2=%d\n", r2 ? 1 : 0);
|
||||
fflush(stdout);
|
||||
bOk = r2;
|
||||
}
|
||||
bDone = true;
|
||||
});
|
||||
while ((!aDone.load() || !bDone.load()) && elapsed() < secs) Sleep(50);
|
||||
printf("RESULT: aDone=%d aOk=%d bDone=%d bOk=%d\n",
|
||||
aDone.load() ? 1 : 0, aOk.load() ? 1 : 0,
|
||||
bDone.load() ? 1 : 0, bOk.load() ? 1 : 0);
|
||||
return (aDone.load() && aOk.load() && bDone.load() && bOk.load()) ? 0 : 3;
|
||||
} else if (variant == "two_instances" || variant == "two_instances_close" || variant == "close_reopen") {
|
||||
// Bridge round-3 probes: does a SECOND instance of the same plugin hang
|
||||
// in view->attached() while the first instance's view is attached?
|
||||
|
||||
Reference in New Issue
Block a user