feat: native host bridge integration — C++ bridge, Rust SHM, JS routing, build scripts, docs

- native_bridge/: InstrumentEngineManager multi-channel, sample-accurate, CC/program/pitchbend, transport, Vst3Instrument stub (HAVE_VST3SDK)
- src-tauri: shm.rs, bridge spawn + audio pump + health monitor, open_vst_gui, externalBin, commands
- app: UnifiedMidiRouter, NativeBridgeService, bridgeAudioNode, audioRoutingEngine, Plugin Manager UI, Bridge/WASM indicator, set_position sync
- build: 3 ps1 (force-added, build/ ignored), verify_bundle --check-bridge, CI workflow
- docs: TASKS.md, TEST_NOTES.md (Windows verify checklist), install/report updates
This commit is contained in:
locpham
2026-08-11 23:37:29 +07:00
parent aae0b05473
commit c3368d0a91
37 changed files with 2970 additions and 80 deletions
+81
View File
@@ -0,0 +1,81 @@
# test_standalone.ps1 - Post-install verification for Native Host Bridge
# Run on the Windows machine AFTER installing the NSIS setup (or from dev tree).
# ASCII only (PowerShell 5.1 ANSI limitation).
$ErrorActionPreference = "Continue"
$APPDATA = Join-Path $env:APPDATA "SonicForgeDAW"
$LOG_DIR = Join-Path $APPDATA "logs"
$BRIDGE_LOG = Join-Path $LOG_DIR "bridge.log"
Write-Host "== [1/8] daw_vst_bridge.exe process =="
$proc = Get-Process -Name "daw_vst_bridge" -ErrorAction SilentlyContinue
if ($proc) { Write-Host " OK: running (PID $($proc.Id))" } else { Write-Host " FAIL: not running" }
Write-Host "== [2/8] daw_engine.exe process =="
$eng = Get-Process -Name "daw_engine" -ErrorAction SilentlyContinue
if ($eng) { Write-Host " OK: running (PID $($eng.Id))" } else { Write-Host " FAIL: not running" }
Write-Host "== [3/8] spawn.log (engine + bridge lines) =="
$spawn = Join-Path $LOG_DIR "spawn.log"
if (Test-Path $spawn) {
$content = Get-Content $spawn -Raw
if ($content -match "daw_vst_bridge.*exists=True") { Write-Host " OK: bridge found in spawn.log" }
else { Write-Host " WARN: no daw_vst_bridge line in spawn.log (old build?)" }
if ($content -match "daw_engine.*exists=True") { Write-Host " OK: engine found in spawn.log" }
else { Write-Host " FAIL: engine not found in spawn.log" }
} else { Write-Host " FAIL: spawn.log missing" }
Write-Host "== [4/8] Shared Memory mapping SonicForge_DAW_IPC =="
# Requires admin? Usually not for read. Use a tiny C# helper to OpenFileMapping.
$shmCheck = @'
using System;
using System.Runtime.InteropServices;
public static class ShmCheck {
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern IntPtr OpenFileMapping(uint dwDesiredAccess, bool bInheritHandle, string lpName);
public static int Check() {
IntPtr h = OpenFileMapping(0x6, false, "SonicForge_DAW_IPC"); // FILE_MAP_READ|FILE_MAP_WRITE
if (h == IntPtr.Zero) return Marshal.GetLastWin32Error();
return 0;
}
}
'@
try {
Add-Type -TypeDefinition $shmCheck -Language CSharp -ErrorAction Stop
$r = [ShmCheck]::Check()
if ($r -eq 0) { Write-Host " OK: SonicForge_DAW_IPC exists" } else { Write-Host " FAIL: shared memory not found (win32 err $r)" }
} catch { Write-Host " SKIP: cannot check SHM (compile error: $($_.Exception.Message))" }
Write-Host "== [5/8] Engine HTTP health =="
$health = $null
for ($p = 8000; $p -le 8010 -and -not $health; $p++) {
try { $health = Invoke-RestMethod -Uri "http://127.0.0.1:$p/health" -TimeoutSec 2 } catch {}
}
if ($health) { Write-Host " OK: engine health on port $p -> $($health | ConvertTo-Json -Compress)" }
else { Write-Host " FAIL: no engine on 8000-8010" }
Write-Host "== [6/8] Bridge status via engine API =="
try {
$st = Invoke-RestMethod -Uri "http://127.0.0.1:$p/api/v1/bridge/status" -TimeoutSec 3
Write-Host " bridge_status: $($st | ConvertTo-Json -Compress)"
} catch { Write-Host " WARN: /api/v1/bridge/status not available yet (endpoint added in Giai doan 6)" }
Write-Host "== [7/8] Audio smoke test: load SF2 + note -> PCM in SHM =="
# Requires a test soundfont; adjust path to a real .sf2 on this machine.
$sf = "C:\SonicForgeDAW\soundfonts\SGM-V2.01.sf2"
if (Test-Path $sf) {
try {
$body = @{ path = $sf; type = "SF2" } | ConvertTo-Json
Invoke-RestMethod -Uri "http://127.0.0.1:$p/api/v1/bridge/load" -Method Post -Body $body -ContentType "application/json" -TimeoutSec 30 | Out-Null
Write-Host " OK: bridge load SF2 requested. Press keys on MIDI keyboard and watch VU meters."
} catch { Write-Host " WARN: bridge/load failed ($($_.Exception.Message))" }
} else { Write-Host " SKIP: $sf not found - set a real .sf2 path" }
Write-Host "== [8/8] Manual checklist (spec VII) =="
Write-Host " [ ] Load VST3 (Vital.vst3) -> open floating GUI -> tweak knobs"
Write-Host " [ ] Load SF2 (SGM-V2.01.sf2) bank 0 prog 0 -> piano"
Write-Host " [ ] Load SFZ (SalamanderPiano.sfz) -> samples play"
Write-Host " [ ] MIDI keyboard live + Timeline play together -> no choke/dropout"
Write-Host " [ ] Track EQ cutoff + Master maximizer affect bridge audio instantly"
Write-Host " [ ] Kill daw_vst_bridge.exe -> app falls back to SonicSF WASM (no crash)"
Write-Host "== DONE =="