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
+41 -1
View File
@@ -28,6 +28,46 @@ Ký hiệu: **[MỚI]** tạo mới, **[THAY]** thay thế/đổi luồng hiện
> `--check-bridge`; F5 hooks.nsh OK; F6 docs 2 sidecar; F7 CI yml; B6 externalBin; B7 capabilities OK;
> A7 tách Vst3Instrument.h/.cpp (guard HAVE_VST3SDK, stub no-op khi thiếu submodule — A6 host thật vẫn
> TODO chờ vst3sdk trên Windows). Bundle rebuild OK; selfcheck 11160 pass Linux.
> **BATCH 2026-08-12 (chạy thật Windows + GỠ CARLA):** E2 resolve path fix — `_resolve_bridge_asset`
> scan plugin_dirs + os.walk cho SF2/SF3/SFZ; `loadTrackInstrumentToBridge` luôn gửi `r.path` qua
> `bridgeLoad`. **GỠ CARLA khỏi luồng instrument**: xóa `ensureCarlaForPlayback` + 2 call site + nút 🎛
> PM scan VST + dropdown "Carla Bridge (mở Carla.exe)" + 2 auto-open instrumentSelector/dropdown + nút
> Carla Bridge riêng (app.jsx); `runtime.js shouldRoute/shouldRoutePlayback` → false vô điều kiện (bridge
> host mọi instrument; Carla KHÔNG còn được mở/route khi bridge connected). GIỮ: FX module "Load Carla
> Bridge" (VST FX ngoài, user tự cài). **E2E thật (Tauri UI + CDP):** chèn SF2 024_BigSymphny.sf2 từ
> Plugin Manager → bridge load FULL PATH (log `[NativeBridge] instrument loaded ch=0 type=2 ...`), NOTE_ON
> → peak 0.0213 (âm phát), NOTE_OFF → 0 (decay). **`tauri build` lại**: NSIS `SonicForgeDAW_1.0.0_x64-setup.exe`
> (363MB) + MSI `SonicForgeDAW_1.0.0_x64_en-US.msi` (598MB) — engine mới (hash MD5 khớp dist) verify trong
> **FIX VST GUI HANG (attached()):** nguyên nhân `view->attached()` treo = openGUI chạy thread mới trong khi
> plugin được load ở thread cũ đã EXIT → COM STA apartment của load thread chết → plugin marshal nội bộ
> (Nexus) hang. Xác minh bằng `gui_probe` (standalone, target CMake, không ship): `bridge_like` (load
> thread A exit → openGUI thread B) TREO; `same_thread` (load+openGUI cùng thread, pump song song) OK.
> **Fix**: `main.cpp` thêm `ChannelWorker` — 1 thread persistent mỗi channel, giữ COM STA sống, LOAD và
> OPEN_GUI đều post job vào thread đó, thread pump message queue khi idle. Kèm: message pump ở đầu
> vòng audio loop (PeekMessage/Translate/Dispatch) cho editor trong lúc attached(). **Kết quả E2E (CDP +
> SHM):** Nexus `attached=0` → `[NativeBridge] GUI attached`, child editor windows visible trong
> `vst-Nexus`; SF2 peak 0.0236; Scaler2 note peak 0.0062 (VST audio routing OK); Nexus note peak 0 =
> license/preset (không phải host bug, GUI là đường load preset). 1 bridge process, 0 restart.
> **BATCH 2026-08-12 (FIX UI E2E — GUI VST native + audio path bridge):**
> **Issue 2 — GUI plugin là HTML che, không phải cửa sổ thật:** `open_vst_gui` (src-tauri/src/lib.rs)
> bỏ WebviewWindowBuilder/thread → chỉ `shm.push_control(4,0,0,0,&plugin_id)` (hwnd=0 → bridge tự tạo).
> `main.cpp` thêm `create_native_vst_window(title)` (RegisterClassA `SonicForge_Native_VST3_Class`,
> CreateWindowExA WS_OVERLAPPEDWINDOW|WS_VISIBLE 800x600, DefWindowProcA, KHÔNG WS_EX_TOPMOST); case
> OPEN_GUI arg1==0 tạo window NGAY TRONG ChannelWorker job (giữ COM STA), giữ `std::map<uint32_t,void*>
> guiWindows`; fix dangling: lambda capture `arg2=std::string(c.arg2)`. Verify: win_enum hwnd 0x4BE0EC4,
> class `SonicForge_Native_VST3_Class`, title Nexus, pid=27272, child `JUCE_19ff6684f11` visible —
> KHÔNG HTML che. Nexus note peak vẫn 0 = license/preset (kỳ vọng, GUI là đường load preset; init 1-2 phút).
> **Issue 1 — SF2 preview/play câm:** root cause `HAS_PYFLUIDSYNTH=FALSE` trong bundled engine →
> `/api/v1/plugins/soundfont-render` 501; VST3 play path cũ dùng nativeSf/scheduleCarlaNote (Carla đã gỡ →
> shouldRouteCarla false). Fix `app/static/js/app.jsx`: thêm guard `&& !(window.SonicMidiRouter &&
> window.SonicMidiRouter.isBridgeActive())` vào 8 chỗ (kbNative, keybed mouseenter, pvCtx wheel preview,
> clCtx piano-roll click, dwTrk draw, pvCtxInst draw preview, nativeSf x2, subNativeSf) → bridge active thì
> MỌI đường note đi qua router → pushEvent → bridge. Build + copy app.precompiled.js vào 3 nơi
> (src-tauri/target/release/daw_engine/_internal/app/static/, src-tauri/resources, dist/daw_engine). Verify
> HTTP: guard count=2 trong bundle served. **E2E chính ĐẠT:** sf2_focus2 — loadInstrument SF2 orchestral
> ch0 → dispatchMidiEvent NOTE_ON 60 → SHM peak **0.029745** → NOTE_OFF → 0. GUI Nexus native window OK.
> installer. D7 + E2 coi là hoàn tất (E2E thật).
> **BATCH CUỐI (2026-08-11):** B5 ✅ (pump thread tồn tại trong lib.rs ~263 — review tay, cần cargo check
> Windows); F5 ✅ (hooks.nsh `customInstall` ExecWait vc_redist toàn máy — đủ cho cả 2 exe); F2 🟡
> (ps1 đã copy, chạy thật cần Windows); D9 bổ sung `transport('set_position', playhead)` ~mỗi giây trong
@@ -88,7 +128,7 @@ Code skeleton đã chuẩn bị sẵn trong workspace `native_bridge/`; copy và
| ✅ D4 | `SonicCarlaMidi` (runtime.js ~74) | **[THAY]** `shouldRouteCarla` trả false khi bridge connected (VSTi do bridge host); giữ Carla khi không có bridge | không kép âm VST (bridge + Carla) |
| ✅ D5 | `updateSfRouting` ~21255 + `setOutputDestination` | **[BỔ SUNG]** Nhánh mới: khi bridge active, `audioRoutingEngine.connectNativeBridgeToTrackFX(node, trackId)` thay vì `SonicSF.setOutputDestination` | âm bridge vào đúng track FX chain |
| D6 | `panic`/`stopAll` (soundfontPlayer.js) + Stop handler app.jsx | **[BỔ SUNG]** Stop/panic → `transport_control('panic')` tới bridge + vẫn gọi fallback cục bộ | không note kẹt sau Stop |
| D7 | UI Plugin Manager / Synth dropdown | **[BỔ SUNG]** Hiển thị trạng thái bridge (`bridge_status`); nút "Load vào Native Bridge" gọi `C2.loadInstrument` với path resolve từ API plugins (Bổ sung E1) | chọn VSTi/SF2 → bridge load, GUI VST mở được |
| D7 | UI Plugin Manager / Synth dropdown | **[BỔ SUNG]** Hiển thị trạng thái bridge (`bridge_status`); nút "Load vào Native Bridge" gọi `C2.loadInstrument` với path resolve từ API plugins (Bổ sung E1) | chọn VSTi/SF2 → bridge load, GUI VST mở được |
---