# CARLA BRIDGE — NATIVE GUI VSTi (Windows) + DUAL-MODE RUNTIME (Desktop / Docker Headless) > Tài liệu kỹ thuật & vận hành: tích hợp Carla làm host native GUI cho VSTi trên > Windows, tự phát hiện môi trường (desktop / headless), thư viện preset > (.vstpreset) làm cầu nối Carla → pedalboard, và Plugin Manager quản lý > soundfont + instrument. > > Phạm vi code: `app/core/runtime.py`, `app/api/v1/system.py`, > `app/api/v1/presets.py`, `app/api/v1/plugins.py`, `app/core/vst_engine.py`, > `app/core/render_engine.py`, `app/static/js/services/runtime.js`, `app.jsx`. --- ## 1. Bối cảnh & quyết định kiến trúc | Vấn đề | Quyết định | |---|---| | `pedalboard` **cố tình headless** — không mở được native GUI VSTi | Không thay thế pedalboard; dùng **Carla làm host GUI ngoài** (preview + chỉnh preset), pedalboard giữ nguyên làm **render engine** (offline, cùng code path cho preview & export) | | Browser không chạy được binary `.vst3` (Windows/Linux) | Preview realtime thật chỉ có trong **cửa sổ Carla**; trong web UI dùng **quick-render preview** (pedalboard render clip ngắn → wav — **âm thật = âm export**) | | App chạy 2 môi trường: **Windows desktop** (server+client 1 máy) và **Docker headless** (server + browser UI) | **Runtime profile tự phát hiện** → bật/tắt tính năng theo môi trường (nút Carla Bridge chỉ hiện trên desktop có Carla) | | Carla Windows là **bộ zip portable** — không installer, không PATH | **User tự định vị** thư mục chứa `carla.exe` (Plugin Manager → Định vị Carla...) + tìm kiếm dự phòng (registry, Program Files, quét nông Downloads/Desktop) | ``` ┌────────────────────────── Windows Desktop (1 máy) ──────────────────────────┐ │ Browser/Tauri UI ──► FastAPI (localhost:8000) ──► pedalboard (render VST3) │ │ │ │ ▲ │ │ ▼ ▼ │ load_preset │ │ Nút "Carla Bridge" ──► spawn carla.exe (native GUI) │ │ │ │ chọn VSTi, chỉnh âm, Save .vstpreset │ │ └──────────────► Upload preset ──► storage/presets ─┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌────────────────────────── Docker Headless (server) ─────────────────────────┐ │ Browser UI ──► FastAPI (container :8000) ──► pedalboard (VSTi Linux) │ │ Soundfont + VSTi mở được: mount volumes (docker-compose.prod.yml) │ │ Preset .vstpreset: user chỉnh ở máy desktop → upload qua web UI │ └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 2. Runtime tự phát hiện môi trường (`app/core/runtime.py`) ### 2.1 Nguyên tắc - **Heuristic + override**: `SF_RUNTIME=auto|desktop|headless` **thắng tuyệt đối** (WSL / docker-in-docker / remote desktop có thể làm heuristic sai). - `SF_DOCKER=1` hoặc tồn tại `/.dockerenv` → nhận diện container. - Linux: không có `DISPLAY` hoặc trong docker → `headless`; ngược lại `desktop`. - Windows/macOS → luôn `desktop`. ### 2.2 Capabilities API (frontend gọi 1 lần lúc boot) ``` GET /api/v1/system/capabilities (public — cần trước khi đăng nhập) ``` ```json { "success": true, "runtime": "desktop", // "desktop" | "headless" "platform": "windows", // "windows" | "linux" | "darwin" "docker": false, "features": { "carla_local": true, // có Carla trên máy → hiện nút "Carla Bridge" "carla_path": "D:/Tools/Carla/carla.exe", "preset_upload": true, // luôn true (upload .vstpreset qua web UI) "vst_render": true, // pedalboard khả dụng "tauri_bridge": false, "preview_mode": "quick_render" // "quick_render" | "wasm" }, "default_dirs": { "vst": [...], "soundfont": [...], "preset": "..." } } ``` ### 2.3 Bảng hành vi theo môi trường | Tính năng | Windows desktop | Docker headless | |---|---|---| | Render VSTi | pedalboard `VST3Plugin` + `load_preset` | giống hệt (VSTi **bản Linux**) | | Scan VST/SF | thư mục chuẩn Windows + `plugin_dirs.json` | mount volumes + `plugin_dirs.json` | | Preview VSTi | quick-render (âm thật); realtime trong Carla | quick-render | | Nút "Carla Bridge" (nút Synth) | **Hiện** → spawn `carla.exe` | **Ẩn** (không có GUI local) | | Preset | picker local / upload → thư viện | upload → thư viện | | SoundFont preview | FluidSynth WASM (browser) | giống hệt | --- ## 3. Cài đặt Carla trên Windows (bản portable zip) Carla phát hành dạng **zip** (`Carla-2.5.x-win64.zip`) — **không có installer, không ghi PATH**. Không bundle Carla vào installer của app (license GPL-2.0+, xem §8). 1. Tải: (bản `win64`). 2. Giải nén ra bất kỳ đâu (VD `D:\Tools\Carla\`, chứa `carla.exe`). 3. Mở app → **Plugin Manager** → section **"Carla Bridge (VSTi native GUI)"** → nút **"Định vị Carla..."** → chọn thư mục chứa `carla.exe` (hoặc chính file `carla.exe`). 4. App lưu vào `storage/carla_path.json` → cache detect bị xóa → nút **"Carla Bridge"** hiện trong dropdown nút Synth. ### 3.1 Thứ tự phát hiện `carla_local` | Ưu tiên | Nguồn | |---|---| | 1 | **Config user** (`storage/carla_path.json`) — kênh chính cho bản portable | | 2 | PATH (`shutil.which`) | | 3 | Registry (`HKLM/HKCU\SOFTWARE\Carla\InstallPath`) — nếu cài qua installer | | 4 | Thư mục chuẩn (`Program Files\Carla`, `%LOCALAPPDATA%\Programs\Carla`) | | 5 | **Quét nông** Downloads/Desktop/Documents (độ sâu ≤ 3, bỏ qua `node_modules`, `AppData`, `Windows`...) — không bao giờ quét toàn ổ đĩa | ``` POST /api/v1/system/carla-path (auth) — lưu vị trí Carla body: { "carla_path": "D:/Tools/Carla" } (thư mục HOẶC file exe) → trả { success, carla_path, ...capabilities } ``` --- ## 4. Luồng sử dụng end-to-end (Windows) 1. **Nút Synth** (track strip / btnSynth) → chọn **"🎛 Carla Bridge (mở Carla.exe)"** → app spawn `carla.exe` (ưu tiên `carla-single ` nếu chọn kèm plugin). 2. Trong Carla: **Add Plugin** → chọn VSTi (Kontakt, Nexus, Vital...) → native GUI hiện ra → chỉnh âm, chọn bank/preset của plugin. 3. **Save preset** bằng nút của CHÍNH plugin (không dùng project save của Carla) → file `.vstpreset`. 4. Trong app: dropdown Synth → **"⬆ Upload preset (từ Carla...)"** → chọn file `.vstpreset` → nằm trong **thư viện preset** → chọn preset trong danh sách **"VST Presets"** → gán vào track (`synth_engine.preset_id`). 5. **Render**: `render_engine.py` nạp plugin qua `load_vst()` rồi `apply_preset_to_plugin()` → **âm render = âm đã chỉnh trong Carla** (điều kiện: cùng sample rate — xem §7). Lưu ý: danh sách VSTi trong dropdown vẫn cần thiết — dùng để **map tên → đường dẫn khi pedalboard nạp plugin lúc render** (không phải để mở GUI). --- ## 5. Thư viện preset — cầu nối Carla ↔ pedalboard - Thư mục: `{STORAGE_DIR}/presets` (Windows: `%APPDATA%\SonicForgeDAW\storage\presets`; Docker: nằm trong volume `sf_db` → `/app/app/storage/presets`). - Định dạng hỗ trợ: `.vstpreset` (VST3 — chuẩn), `.fxp`/`.fxb` (VST2, chỉ preview trong Carla), `.dspreset` (DecentSampler/Pianobook). - `synth_engine` của track có thể chứa 1 trong 3 dạng (ưu tiên giảm dần): ```json { "type": "vst3", "plugin_id": "Kontakt 7", "preset_data": "", "preset_id": "a1b2c3....vstpreset", // thư viện storage/presets "preset_path": "D:/presets/Piano.vstpreset" } ``` ### API ``` GET /api/v1/presets (public) — danh sách POST /api/v1/presets/upload (auth) — multipart file + plugin_hint GET /api/v1/presets/{id}/download DELETE /api/v1/presets/{id} (auth) ``` ### Quick-render preview (âm thật = âm export) ``` POST /api/v1/plugins/preview body: { instrument_id, notes:[{pitch,start_beat,duration_beats,velocity}], bpm, sample_rate, preset_id?, preset_path?, preset_data? } → { success, url: "/static/audio/processed/preview_xxx.wav", duration_sec } ``` Cùng code path với export (pedalboard + `load_preset`) → **preview nghe đúng plugin/preset** (khác "Preview Synth WASM" cũ — âm giả). --- ## 6. Plugin Manager — SoundFont: Add Directory → Scan → Instrument → Synth 1. **Add Directory** (folder picker native / in-app browser) → thư mục vào danh sách (lưu `plugin_dirs.json`). 2. **Scan** → quét soundfont trong các thư mục (catalog qua `SoundFontAutoScanner`) + liệt kê VST. 3. Bấm vào **một soundfont** (▸) → expand danh sách **instrument bên trong** (Bank/Program/Tên) qua `GET /api/v1/plugins/soundfont-instruments/{sf_id}`. 4. Nút **"Chèn vào Synth"** → gán instrument (bank/program) vào **track đang chọn** (`setTrackInstrumentWithProgram`) và đóng Plugin Manager. > SF3: instrument đọc sau khi chuyển đổi SF3→SF2 (endpoint download tự chuyển > đổi khi cần). Nếu thiếu libfluidsynth, danh sách trả `[]` (graceful). --- ## 7. Lưu ý kỹ thuật & hạn chế (đã xác minh) 1. **Sample rate**: Carla chạy theo audio device (thường 48 kHz), pedalboard render mặc định 44.1 kHz → plugin phụ thuộc SR (delay/chorus/oversampling) nghe khác. **Render đúng SR của thiết bị Carla** để preview = export. 2. **VST2**: pedalboard 0.10+ **đã gỡ hỗ trợ VST2** (chỉ còn VST3) → chỉ preset VST3 (`.vstpreset`) round-trip được. Plugin VST2 cũ: preview được trong Carla nhưng **không render** được qua pedalboard. 3. **VSTi trên Docker**: chỉ chạy được plugin có bản **Linux** (`.vst3`/`.so`); plugin Windows-only (`.dll`) không chạy trên server Linux (không khuyến nghị Wine bridge trong container). 4. **License Carla GPL-2.0+**: app **không bundle/nhúng** Carla — chỉ spawn tiến trình ngoài + trao đổi file preset (không link code) → không dính copyleft. User tự tải zip. 5. **Preview WASM ≠ âm thật**: Preview Synth trong browser không phải plugin thật — dùng quick-render (`/plugins/preview`) nếu cần nghe đúng âm. --- ## 8. Checklist QA - [ ] Windows: cài Carla zip → Định vị Carla → nút "Carla Bridge" hiện ở nút Synth - [ ] Bấm Carla Bridge → `carla.exe` chạy, mở được VSTi + native GUI - [ ] Save `.vstpreset` từ GUI plugin → Upload trong app → gán vào track → render ra âm đúng preset - [ ] Render cùng SR với Carla → preview (Carla) nghe = âm export - [ ] Plugin Manager: Add Directory → Scan → expand soundfont → "Chèn vào Synth" gán đúng bank/program vào track đang chọn - [ ] Docker (`SF_DOCKER=1`): capabilities `runtime=headless`, không hiện Carla Bridge, preset upload hoạt động, render VSTi Linux + soundfont từ mount OK - [ ] `SF_RUNTIME=desktop` trên Linux có DISPLAY → chạy như desktop - [ ] pytest: `86 passed, 7 skipped`