fix(v9): 5 bugs — GUI deferred until VST loaded (no white window), fixed retry 8x500ms, VST3 folder resolve for auto-load, sustain-CC64 dropped after STOP, taskkill process tree on exit, Synth+GUI same row in TCP

This commit is contained in:
2026-08-13 21:57:23 +07:00
parent 96d31ee685
commit 7a8122f99d
6 changed files with 72 additions and 29 deletions
+16 -13
View File
@@ -5768,7 +5768,7 @@ const PluginManagerModal = ({ isOpen, onClose, pluginsData, onInsertInstrument }
// Requirement 2: VST3 load m native GUI ngay (C++ attach editor vào
// ca s bridge t to control type=4, hwnd=0).
if (ok && type === 'VST3' && window.NativeBridgeService.openNativeGUI) {
try { await window.NativeBridgeService.openNativeGUI(name); } catch (e) {}
try { await openVstGuiRetry(name, 0, 8); } catch (e) {}
}
return ok;
} catch (err) {
@@ -6210,17 +6210,20 @@ const ensureAndOpenVstGui = async (trackId, instrumentId) => {
const ok = await loadVstToBridge({ id: trackId, instrumentId });
if (!ok) return;
}
try { await openVstGuiRetry(instrumentId, bch, 5); } catch (e) { console.warn('[Bridge] openNativeGUI fail:', e); }
try { await openVstGuiRetry(instrumentId, bch, 8); } catch (e) { console.warn('[Bridge] openNativeGUI fail:', e); }
};
// V8 bug 4: C++ load instrument ASYNC (worker thread) OPEN_GUI gui toi truoc
// khi assign() xong instruments.get(guiCh) null "GUI attach FAILED"
// nen trang. Retry mo GUI nhieu lan, cach 400ms cho load xong.
// V8 bug 4 + V9 bug 3/6/7: C++ load instrument ASYNC (worker thread) OPEN_GUI
// som C++ defer (chi log stderr, invoke van tra Ok) retry PHAI chay DU so
// lan, khong `return true` som. Mo GUI co the can cho den khi assign() xong
// (Nexus ~1-2s) 8 lan x 500ms, window reuse khi load xong.
const openVstGuiRetry = async (instrumentId, bch, attempts) => {
for (let i = 0; i < (attempts || 5); i++) {
try { await window.NativeBridgeService.openNativeGUI(instrumentId, bch); return true; } catch (e) { console.warn('[Bridge] openNativeGUI retry', i + 1, e); }
await new Promise(r => setTimeout(r, 400));
const n = (attempts && attempts > 0) ? attempts : 8;
for (let i = 0; i < n; i++) {
try { await window.NativeBridgeService.openNativeGUI(instrumentId, bch); }
catch (e) { console.warn('[Bridge] openNativeGUI retry', i + 1, e); }
await new Promise(r => setTimeout(r, 500));
}
return false;
return true;
};
// Module-level so both ProfileModal (open project) and App (auto-restore) can
// warm the FluidSynth font cache for each track's instrument. This only loads
@@ -15510,7 +15513,7 @@ const App = () => {
// Requirement 2: chn VST3 qua nút Synth load xong m native GUI
// (C++ attach editor vào ca s bridge t to control type=4, hwnd=0).
if (ok && btype === 'VST3' && window.NativeBridgeService.openNativeGUI) {
try { await openVstGuiRetry(instrumentId, bch, 5); } catch (e) {}
try { await openVstGuiRetry(instrumentId, bch, 8); } catch (e) {}
}
}
})();
@@ -29840,20 +29843,20 @@ STRICT CONSTRAINTS:
className: "text-zinc-500 font-normal"
}, track.fxType || "None")), /*#__PURE__*/React.createElement("button", {
onClick: (e) => { e.stopPropagation(); openInstrumentSelector(track.id); },
className: "px-1.5 py-0.5 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-[10px] font-bold flex items-center gap-1 max-w-[70px] shrink-0"
className: "px-1.5 py-0.5 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-[10px] font-bold flex items-center gap-1 max-w-[90px] shrink-0"
}, /*#__PURE__*/React.createElement("span", {
className: "inline-flex items-center shrink-0"
}, /*#__PURE__*/React.createElement("i", {
"data-lucide": "music",
className: "w-2.5 h-2.5 shrink-0"
})), /*#__PURE__*/React.createElement("span", { className: "truncate text-[10px] min-w-0" }, track.instrumentName || track.instrumentId || "Synth"), /*#__PURE__*/React.createElement("i", { "data-lucide": "chevron-down", className: "w-3 h-3 shrink-0" }))), (track.instrumentId && typeof track.instrumentId === 'string' && !track.instrumentId.startsWith('sf_') ? /*#__PURE__*/React.createElement("button", {
})), /*#__PURE__*/React.createElement("span", { className: "truncate text-[10px] min-w-0" }, track.instrumentName || track.instrumentId || "Synth"), /*#__PURE__*/React.createElement("i", { "data-lucide": "chevron-down", className: "w-3 h-3 shrink-0" }))), /*#__PURE__*/React.createElement("div", { className: "flex items-center gap-0.5 shrink-0 min-w-0" }, (track.instrumentId && typeof track.instrumentId === 'string' && !track.instrumentId.startsWith('sf_') ? /*#__PURE__*/React.createElement("button", {
onClick: (e) => {
e.stopPropagation();
ensureAndOpenVstGui(track.id, track.instrumentId);
},
title: "Mở lại GUI VSTi",
className: "px-1 py-0.5 bg-zinc-800 hover:bg-zinc-700 text-violet-300 border border-violet-800 rounded text-[9px] font-bold flex items-center gap-0.5 shrink-0"
}, /*#__PURE__*/React.createElement("i", { "data-lucide": "sliders-horizontal", className: "w-2.5 h-2.5 shrink-0" }), /*#__PURE__*/React.createElement("span", { className: "truncate text-[8px] min-w-0" }, "GUI")) : null), /*#__PURE__*/React.createElement("div", {
}, /*#__PURE__*/React.createElement("i", { "data-lucide": "sliders-horizontal", className: "w-2.5 h-2.5 shrink-0" }), /*#__PURE__*/React.createElement("span", { className: "truncate text-[8px] min-w-0" }, "GUI")) : null)), /*#__PURE__*/React.createElement("div", {
onMouseDown: e => handleTrackResizeMouseDown(e, track.id),
className: "absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",
onClick: e => e.stopPropagation()