fix: GUI VST native window qua bridge + audio path bridge (SF2 preview/play câm)

- open_vst_gui: bo WebviewWindowBuilder/thread, chi push_control type=4 (hwnd=0 -> bridge tao window)
- main.cpp: create_native_vst_window (class SonicForge_Native_VST3_Class, 800x600, khong TOPMOST),
  tao trong ChannelWorker job, map guiWindows, capture arg2 by value (fix dangling)
- app.jsx: guard isBridgeActive() 8 cho -> bridge active thi moi note di router -> pushEvent -> bridge
  (truoc day SF2 cam vi HAS_PYFLUIDSYNTH=FALSE -> /soundfont-render 501; VST3 path cu dung nativeSf/Carla)
- E2E: SF2 NOTE_ON qua dispatchMidiEvent -> SHM peak 0.029745; Nexus GUI native hwnd OK (license/preset)
- docs: TASKS.md + TEST_NOTES.md ghi batch fix + ket qua; gitignore vendor/junk
This commit is contained in:
2026-08-12 22:12:43 +07:00
parent c3368d0a91
commit d8f8506077
37 changed files with 2170 additions and 419 deletions
+38 -16
View File
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="utf-8">
@@ -12,23 +12,45 @@
<body>
<div id="msg">Đang khởi động SonicForge Engine…</div>
<script>
// Engine (sidecar) có thể cần vài giây để boot (import librosa/pedalboard).
// Thử health-check trên dải port 8000-8010, redirect tới port đầu tiên OK.
// Frontend host (Tauri asset page). KHÔNG location.href redirect: chuyển
// sang http://127.0.0.1:8000 sẽ rời Tauri context -> mất window.__TAURI__
// -> NativeBridgeService vô hiệu (bridge-audio/load_instrument không dùng
// được; MIDI rơi về fallback WASM/Carla). Thay vào đó: quét port engine
// (8000-8010), nạp toàn bộ UI engine qua document.write trên CÙNG document
// (origin tauri:// giữ nguyên -> __TAURI__ sống), base href + API_BASE_URL
// trỏ engine HTTP (CORS * đã bật).
(async function () {
var tries = 0;
while (tries < 90) { // ~60s tối đa
for (var p = 8000; p <= 8010; p++) {
try {
var r = await fetch('http://127.0.0.1:' + p + '/health', { cache: 'no-store' });
if (r.ok) { location.href = 'http://127.0.0.1:' + p + '/'; return; }
} catch (e) { /* port chưa mở */ }
}
tries++;
await new Promise(function (res) { setTimeout(res, 700); });
var base = null;
for (var p = 8000; p <= 8010 && !base; p++) {
try {
var r = await fetch('http://127.0.0.1:' + p + '/health', { cache: 'no-store' });
if (r.ok) base = 'http://127.0.0.1:' + p + '/';
} catch (e) { /* port chưa mở */ }
}
document.getElementById('msg').textContent =
'Không tìm thấy SonicForge Engine (port 80008010). Hãy đóng và chạy lại ứng dụng. ' +
'Nếu lặp lại, xem log: %APPDATA%\\SonicForgeDAW\\logs\\engine.log';
if (!base) {
document.getElementById('msg').textContent =
'Không tìm thấy SonicForge Engine (port 80008010). Hãy đóng và chạy lại ứng dụng. ' +
'Nếu lặp lại, xem log: %APPDATA%\\SonicForgeDAW\\logs\\engine.log';
return;
}
var html;
try {
var res = await fetch(base, { cache: 'no-store' });
html = await res.text();
} catch (e) {
document.getElementById('msg').textContent = 'Engine không phản hồi: ' + e;
return;
}
// base href để /static, /api resolve về engine; API_BASE_URL override
// location.origin (origin thật là tauri://). KHÔNG trailing slash trong
// API_BASE_URL: api.js nối `${API_BASE_URL}/api/...` -> double slash
// `//api/...` -> FastAPI 404 "Not Found" (login báo not found).
html = html.replace('<head>',
'<head>\n<base href="' + base + '">\n' +
'<script>window.API_BASE_URL = "' + base.replace(/\/$/, '') + '";<\/script>');
document.open();
document.write(html);
document.close();
})();
</script>
</body>