fix(master-fx): loại double-processing khi load VST FX vào master fx chain

- Bỏ push setFxChain xuống native bridge (T2.4) — SHM fxRt loop (fx_vst_bridge
  --realtime-fx) là nơi xử lý live master mix duy nhất; trước đây MIDI/VSTi
  instrument bị xử lý 2 lần (native bridge + SHM loop) → over-process,
  âm bể/crackle. setFxChain vẫn dùng khi Export/Offline render.
- closeMasterGui/closeFxGui: POST /close (kill process) thay vì /hide —
  không còn cửa sổ floating always-on-top lơ lửng, tắt được dứt điểm.
- openFxGui already_running kèm embed_url → mở lại embed panel thay vì chỉ toast.
- open_fx_gui (plugins.py): spawn fx-gui với SF_PARENT_PID=<engine pid>.
- RenderFxJob.cpp: watchdog thread trong run_open_fx_gui/run_fx_gui_server —
  engine chết → WM_CLOSE, GUI process tự thoát, không để lại cửa sổ mồ côi.
This commit is contained in:
2026-08-22 16:53:20 +07:00
parent e22757d5be
commit 6ba38286ad
5 changed files with 47 additions and 18 deletions
+28
View File
@@ -1224,6 +1224,32 @@ const char* kFxGuiWndClass = "SonicForge_FX_GUI_Class";
struct FxGuiCtx {
bool closing = false;
};
// Parent watchdog: engine spawn fx-gui voi SF_PARENT_PID=<engine pid>. Neu
// engine chet (crash/quit) ma bridge fx-gui khong tu thoat -> cua so topmost
// van lo lung, khong tat duoc. Watchdog thread: parent mat -> WM_CLOSE.
static uint32_t fxGuiParentPid() {
const char* e = std::getenv("SF_PARENT_PID");
return e ? (uint32_t)std::atoi(e) : 0;
}
static bool fxGuiParentAlive(uint32_t pid) {
if (pid == 0) return true;
HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (!h) return false;
CloseHandle(h);
return true;
}
static void fxGuiStartWatchdog(HWND hwnd, uint32_t parentPid) {
if (parentPid == 0) return;
std::thread([hwnd, parentPid]() {
while (IsWindow(hwnd)) {
Sleep(2000);
if (!fxGuiParentAlive(parentPid)) {
PostMessageA(hwnd, WM_CLOSE, 0, 0); // pump exits -> process returns
return;
}
}
}).detach();
}
// Worker (HTTP) thread -> pump thread editor-resize request. The plugin's
// checkSizeConstraint/onSize must run on the thread that owns the editor.
@@ -1418,6 +1444,7 @@ int run_open_fx_gui(const std::string& jobPath) {
FxGuiCtx ctx;
const int rc = fxGuiSetup(jobPath, &fx, &hwnd, /*offscreen=*/false, (LONG_PTR)&ctx);
if (rc) return rc;
fxGuiStartWatchdog(hwnd, fxGuiParentPid());
// 5. Pump messages until the window is destroyed.
MSG msg;
@@ -1453,6 +1480,7 @@ int run_fx_gui_server(const std::string& jobPath) {
if (rc) return rc;
rc = fxGuiCreateWindow(name, /*offscreen=*/true, 0, &hwnd);
if (rc) return rc;
fxGuiStartWatchdog(hwnd, fxGuiParentPid());
SetPropA(hwnd, "FXGUI_FX", &fx); // for WM_FXGUI_RESIZE on the pump thread
int loadRc = 0;