fix(v8): 5 bugs — orphan bridge watchdog+state overwrite, stuck-note stop race, white VST GUI retry, VSTi auto-load via saved plugin_path, track-header button overflow
- native bridge: dedicated watchdog thread (parent death / PID-reuse via GetProcessTimes) -> TerminateProcess self; transportStopped flag drops note-on after STOP + CC64 sustain release + allNotesOff on stop - tauri: set_bridge_child overwrites managed BridgeProcess state (app.manage is no-op when state exists) so Destroyed handler kills restarted bridge - ui: stopAllPlayback syncs isPlayingRef/subTabsRef + second transport stop at 150ms; onStatusChange resets __bridgeLoadedChannels at callback start (auto-restart never emits bridge-down); openVstGuiRetry waits for async C++ load before OPEN_GUI; loadVstToBridge uses synth_engine.plugin_path / listPlugins fallback and persists plugin_path on load; shrink track-header Synth/GUI buttons
This commit is contained in:
@@ -209,6 +209,37 @@ int main(int argc, char* argv[]) {
|
||||
uint32_t parentPid = 0;
|
||||
if (const char* e = std::getenv("SF_PARENT_PID")) parentPid = (uint32_t)std::atoi(e);
|
||||
|
||||
// V8 bug 2: watchdog THREAD rieng - main loop chi check parent_alive giua
|
||||
// cac block; neu VST process() chan loop thi khong bao gio thoat -> orphan.
|
||||
// Thread nay chay doc lap, parent chet -> TerminateProcess ngay. Kem
|
||||
// start-time check chong PID reuse (OpenProcess tra handle cua process
|
||||
// khac chiem lai PID -> tuong parent con song mai).
|
||||
if (parentPid != 0) {
|
||||
std::thread([parentPid]() {
|
||||
auto proc_birth = [](HANDLE h) -> uint64_t {
|
||||
FILETIME c, e, k, u;
|
||||
if (GetProcessTimes(h, &c, &e, &k, &u))
|
||||
return (uint64_t(c.dwHighDateTime) << 32) | c.dwLowDateTime;
|
||||
return 0;
|
||||
};
|
||||
uint64_t birth = 0;
|
||||
{
|
||||
HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, parentPid);
|
||||
if (h) { birth = proc_birth(h); CloseHandle(h); }
|
||||
}
|
||||
for (;;) {
|
||||
Sleep(2000);
|
||||
HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, parentPid);
|
||||
if (!h) { TerminateProcess(GetCurrentProcess(), 0); return; }
|
||||
uint64_t nowBirth = proc_birth(h);
|
||||
CloseHandle(h);
|
||||
if (birth != 0 && nowBirth != 0 && nowBirth != birth) {
|
||||
TerminateProcess(GetCurrentProcess(), 0); return;
|
||||
}
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Real-time-ish timing: 1ms scheduler resolution
|
||||
timeBeginPeriod(1);
|
||||
@@ -252,6 +283,10 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
const uint32_t block = AUDIO_BLOCK_SIZE;
|
||||
uint64_t playheadSamples = 0;
|
||||
// V8 bug 3: khi STOP da xu ly, bo qua NOTE_ON (velocity>0) den sau - JS
|
||||
// note-on timer co the bay toi sau STOP (guardPlay tre do React re-render)
|
||||
// -> retrigger note -> VST loop am. Chi PLAY moi nhan note-on lai.
|
||||
bool transportStopped = false;
|
||||
|
||||
auto dispatch = [&](const SharedAudioBufferIPC::MidiEventIPC& evt) {
|
||||
auto* inst = instruments.get(evt.channel);
|
||||
@@ -261,9 +296,10 @@ int main(int argc, char* argv[]) {
|
||||
// sampleOffset LUON LUON = 0 khi den day: events duoc dispatch ngay
|
||||
// truoc segment chua no (A11 splitting), nen offset tuong doi la 0.
|
||||
// Truyen offset tuyet doi truoc day lam sfizz/VST3 trigger tre.
|
||||
if (evt.velocity > 0)
|
||||
if (evt.velocity > 0) {
|
||||
if (transportStopped) return; // V8 bug 3: drop note-on sau STOP
|
||||
inst->noteOn(evt.channel, evt.pitch, evt.velocity / 127.0f, 0);
|
||||
else
|
||||
} else
|
||||
inst->noteOff(evt.channel, evt.pitch, 0);
|
||||
break;
|
||||
case 0x8:
|
||||
@@ -363,9 +399,17 @@ int main(int argc, char* argv[]) {
|
||||
std::cout << "[NativeBridge] PANIC — all notes off" << std::endl;
|
||||
} else if (c.type == 3) { // TRANSPORT (A13)
|
||||
if (c.arg0 == 0) { // STOP → flush every note immediately
|
||||
transportStopped = true;
|
||||
// Release sustain pedal TRUOC (CC64=0) — nhieu VSTi giu note
|
||||
// khi pedal con down -> note-off cua allNotesOff bi bo qua
|
||||
// -> am treo loop (V8 bug 3).
|
||||
for (uint32_t ch = 0; ch < 16; ++ch) {
|
||||
if (auto* inst = instruments.get(ch)) inst->controlChange(ch, 64, 0);
|
||||
}
|
||||
instruments.allNotesOff();
|
||||
std::cout << "[NativeBridge] transport STOP — all notes off" << std::endl;
|
||||
} else if (c.arg0 == 1) { // PLAY
|
||||
transportStopped = false;
|
||||
playheadSamples = c.arg1;
|
||||
std::cout << "[NativeBridge] transport PLAY playhead=" << playheadSamples << std::endl;
|
||||
} else if (c.arg0 == 2) { // SET_POSITION (seek while stopped)
|
||||
|
||||
Reference in New Issue
Block a user