feat: native folder picker (Explorer) + Synth liet ke VSTi da scan + fix VU leak (ban 1.1.4)
1) Folder picker dung WINDOW EXPLORER (khong prompt nhap tay):
- src-tauri/src/lib.rs: IPC bridge — thread watcher ipc/pick_dir.request
-> run_on_main_thread -> dialog().file().blocking_pick_folder()
(tauri-plugin-dialog = IFileDialog/Explorer) -> ghi pick_dir.response;
ghi marker tauri_bridge_ready luc setup.
- app/api/v1/plugins.py: POST /pick-dir (def sync -> threadpool, khong
auth) — uu tien Tauri bridge, fallback PowerShell FolderBrowserDialog
(Win) / osascript (macOS) / zenity-kdialog (Linux).
- app.jsx pickPluginFolder: 1) pickPluginDir (native) -> 2) __TAURI__
invoke -> 3) in-app browser -> 4) prompt (cuoi cung).
2) Nut Synth liet ke VSTi da scan (truoc day rong):
- Root: list_available() chi quet settings.VST_DIR (mac dinh
/opt/daw_engine/vst3) trong khi Plugin Manager scan plugin_dirs user.
- plugins.py list_plugins: gop _scan_vst_in_dirs(plugin_dirs) (file
.vst3/.dll/.so + folder X.vst3 Windows).
- vst_engine.py: PluginManager.extra_vst_dirs + _scan_plugins quet them
(ca folder .vst3) + get_plugin_manager doc plugin_dirs.json -> load_vst
tim thay plugin user scan khi render.
3) VU meter leak: section-tab play -> sang MAIN SESSION -> track MAIN van
animate theo am section.
- Root: VU tick fallback _sub_ (sub-node section co analyser) chay cho
ca canvas MAIN; startSubTabPlayback ghi node o key track MAIN.
- Fix: fallback _sub_ chi ap dung cho canvas SECTION (isSessVu); 2 trigger
piano-roll them prefix _sess_ theo st.parent_tab_id.
Verify: 86 tests pass; engine frozen STARTUP 1.35s, 1 engine, 0 spawn '-c';
pick-dir IPC mock tra dung path; scan VST user dirs OK.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
// Ngoài ra lib.rs còn dò THÊM các vị trí fallback (legacy/portable/dev)
|
||||
// và ghi đầy đủ diagnostic vào %APPDATA%/SonicForgeDAW/logs/spawn.log.
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
use tauri_plugin_shell::process::CommandChild;
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -155,6 +156,53 @@ pub fn run() {
|
||||
app.manage(EngineProcess(Mutex::new(None)));
|
||||
}
|
||||
}
|
||||
|
||||
// ── Native folder picker bridge (folder picker cho Plugin Manager) ──
|
||||
// UI chay tren http://127.0.0.1:8000 (engine) — KHONG co __TAURI__
|
||||
// (WebView2 cung khong ho tro window.prompt) → engine goi qua file
|
||||
// IPC: engine ghi ipc/pick_dir.request → thread nay mo NATIVE dialog
|
||||
// (IFileDialog/Explorer — tauri-plugin-dialog) → ghi ket qua vao
|
||||
// ipc/pick_dir.response → engine tra ve cho frontend.
|
||||
let data_root = std::env::var("APPDATA").unwrap_or_else(|_| ".".into());
|
||||
let ipc_dir = std::path::Path::new(&data_root)
|
||||
.join("SonicForgeDAW")
|
||||
.join("ipc");
|
||||
if let Ok(()) = std::fs::create_dir_all(&ipc_dir) {
|
||||
// Marker: engine biet bridge ton tai (khong phai chay standalone)
|
||||
let _ = std::fs::write(ipc_dir.join("tauri_bridge_ready"), "1");
|
||||
}
|
||||
let ipc_dir_for_thread = ipc_dir.clone();
|
||||
let app_handle = app.handle().clone();
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
let req = ipc_dir_for_thread.join("pick_dir.request");
|
||||
if req.exists() {
|
||||
let _ = std::fs::remove_file(&req);
|
||||
let resp = ipc_dir_for_thread.join("pick_dir.response");
|
||||
let _ = std::fs::remove_file(&resp);
|
||||
// Dialog phai chay tren main thread (GTK/Windows message loop)
|
||||
let handle = app_handle.clone();
|
||||
let resp_for_main = resp.clone();
|
||||
let _ = handle.run_on_main_thread(move || {
|
||||
let picked: Option<PathBuf> = handle
|
||||
.dialog()
|
||||
.file()
|
||||
.blocking_pick_folder();
|
||||
let val = picked
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_default();
|
||||
let _ = std::fs::write(&resp_for_main, val);
|
||||
});
|
||||
// Cho den khi co response (user co the de dialog mo lau)
|
||||
let mut waited_ms = 0u32;
|
||||
while !resp.exists() && waited_ms < 300_000 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
waited_ms += 100;
|
||||
}
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
.on_window_event(|window, event| {
|
||||
|
||||
Reference in New Issue
Block a user