From 0c0aadb8ee48d2ee12ced1ef09bb17ef92c81ed7 Mon Sep 17 00:00:00 2001 From: locpham Date: Sun, 9 Aug 2026 10:48:09 +0000 Subject: [PATCH] fix: daw_engine khong chay tren Windows - bundle resources sai layout Spawn.log cho thay: resource_dir()/daw_engine/daw_engine.exe exists=false tren ca ban cai lan target/release - engine KHONG duoc bundle dung cho. Goc re (doc source tauri-utils/src/resources.rs + tauri-cli/src/interface/rust.rs): - bundle.resources dang ARRAY ['resources/daw_engine']: ResourcePaths::new (Slice) -> target = resource_relpath(path) GIU TIEN TO 'resources/' -> engine nam o /resources/daw_engine/... - lib.rs cu tim o /daw_engine/... -> exists=false. Fix: - tauri.conf.json: resources dang MAP {'resources/daw_engine': 'daw_engine/'} -> resources_map -> Walk mode, dest.join(strip_prefix) -> giu nguyen cay _internal, dich chuan /daw_engine/ (xac nhan tauri-cli BundleResources::Map -> settings.resources_map, dong 1467-1469). - lib.rs: do them 3 vi tri fallback (legacy resources/ prefix, portable exe_dir, dev exe_dir/../resources) + log diagnostic day du vao spawn.log (liet ke noi dung resource_dir/exe_dir khi khong tim thay). - build_windows.ps1: them huong dan xac minh spawn.log sau khi cai dat. --- DESKTOP_INSTALL_PLAN.md | 10 +++ build_windows.ps1 | 6 ++ src-tauri/src/lib.rs | 151 ++++++++++++++++++++++++++++++-------- src-tauri/tauri.conf.json | 6 +- 4 files changed, 139 insertions(+), 34 deletions(-) diff --git a/DESKTOP_INSTALL_PLAN.md b/DESKTOP_INSTALL_PLAN.md index ec222ac..2eb6eda 100644 --- a/DESKTOP_INSTALL_PLAN.md +++ b/DESKTOP_INSTALL_PLAN.md @@ -91,6 +91,16 @@ Nguyên nhân nặng cũ: `librosa` kéo theo `numba`+`llvmlite` (~171MB) + `sci NSIS không còn lỗi mmapping; `hooks.nsh` cài VC++ Redistributable (MSI không chạy hooks → máy thiếu VC++ → daw_engine.exe không chạy — đây là nguyên nhân "build xong không chạy daw_engine" trên Windows). +- **Fix layout resources (bản 1.1.1 — `exists=false` trong spawn.log)**: + `bundle.resources` dạng ARRAY `["resources/daw_engine"]` copy engine tới + `$RESOURCE_DIR/resources/daw_engine/...` (giữ tiền tố `resources/` — đọc + source `tauri-utils/src/resources.rs`) trong khi lib.rs tìm ở + `$RESOURCE_DIR/daw_engine/...` → `exists=false`. Đổi sang dạng MAP + `{"resources/daw_engine": "daw_engine/"}` (Walk mode, giữ nguyên cây + `_internal`, đích chuẩn `daw_engine/`). `src-tauri/src/lib.rs` đồng thời dò + thêm 3 vị trí fallback (legacy/portable/dev) + ghi diagnostic đầy đủ vào + `%APPDATA%/SonicForgeDAW/logs/spawn.log` (liệt kê nội dung resource_dir khi + không tìm thấy). Lệnh build 1 lệnh mỗi OS: ```bash diff --git a/build_windows.ps1 b/build_windows.ps1 index 7c2d0b1..a989c9e 100644 --- a/build_windows.ps1 +++ b/build_windows.ps1 @@ -87,3 +87,9 @@ Write-Host "" Write-Host "== DONE ==" Write-Host " NSIS: src-tauri\target\release\bundle\nsis\SonicForgeDAW_1.0.0_x64-setup.exe" Write-Host " MSI : src-tauri\target\release\bundle\msi\SonicForgeDAW_1.0.0_x64_en-US.msi" +Write-Host "" +Write-Host "== XAC MINH SAU KHI CAI DAT (quan trong) ==" +Write-Host " Mo %APPDATA%\SonicForgeDAW\logs\spawn.log - phai thay:" +Write-Host " [resource_dir/daw_engine (map layout)] ...exists=True" +Write-Host " Neu exists=False: bundle resources KHONG vao installer (chay lai buoc [4/6])." +Write-Host " Engine phai nam o: \daw_engine\daw_engine.exe" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 36cbffa..d265c6a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,34 +1,90 @@ -// SonicForge DAW — desktop shell: spawn/terminate daw_engine.exe sidecar. +// SonicForge DAW — desktop shell: spawn/terminate daw_engine sidecar. +// +// QUAN TRONG (fix bản 1.1.1 — engine không chạy trên Windows): +// tauri.conf.json bundle.resources giờ dùng dạng MAP: +// { "resources/daw_engine": "daw_engine/" } +// vì dạng ARRAY ("resources/daw_engine") copy file tới +// $RESOURCE_DIR/resources/daw_engine/... (giữ tiền tố "resources/"), +// trong khi code cũ tìm ở $RESOURCE_DIR/daw_engine/... -> exists=false. +// Dạng map (Walk mode) giữ nguyên cây thư mục (_internal) dưới đích +// "daw_engine/" — đúng layout lib.rs chờ. +// 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_shell::process::CommandChild; use tauri_plugin_shell::ShellExt; +use std::path::{Path, PathBuf}; use std::sync::Mutex; struct EngineProcess(Mutex>); +/// Các vị trí có thể chứa daw_engine, theo thứ tự ưu tiên. +fn engine_candidates(res_dir: &Path, exe_dir: &Path) -> Vec<(PathBuf, String)> { + let exe_name = if cfg!(windows) { "daw_engine.exe" } else { "daw_engine" }; + vec![ + // 1. Layout chuẩn (resources map): $RESOURCE/daw_engine/daw_engine.exe + ( + res_dir.join("daw_engine").join(exe_name), + "resource_dir/daw_engine (map layout)".into(), + ), + // 2. Legacy (resources array cũ giữ tiền tố resources/) + ( + res_dir.join("resources").join("daw_engine").join(exe_name), + "resource_dir/resources/daw_engine (legacy array)".into(), + ), + // 3. Portable: engine đặt cạnh exe + ( + exe_dir.join("daw_engine").join(exe_name), + "exe_dir/daw_engine (portable)".into(), + ), + // 4. Dev mode: target/{debug,release} -> src-tauri/resources + ( + exe_dir.join("..").join("resources").join("daw_engine").join(exe_name), + "exe_dir/../resources/daw_engine (dev)".into(), + ), + ] +} + +fn list_dir_snippet(dir: &Path) -> String { + let mut s = String::new(); + match std::fs::read_dir(dir) { + Ok(rd) => { + let mut n = 0; + for e in rd.flatten() { + if n > 0 { + s.push_str(", "); + } + s.push_str(&e.file_name().to_string_lossy()); + n += 1; + if n >= 15 { + s.push_str(", ..."); + break; + } + } + } + Err(_) => s.push_str(""), + } + s +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_dialog::init()) .setup(|app| { - // 1. Spawn daw_engine (PyInstaller ONEDIR bundle — khong giai nen - // moi lan chay nhu onefile, khoi dong nhanh). Bundle qua Tauri - // resources: resource_dir()/daw_engine/daw_engine(.exe) let res_dir = app .path() .resource_dir() .expect("resource dir not found"); - let engine_dir = res_dir.join("daw_engine"); - let engine_exe = if cfg!(windows) { - engine_dir.join("daw_engine.exe") - } else { - engine_dir.join("daw_engine") - }; - // Ghi log spawn de chan doan (UI khong duoc panic/thoat — chi log). - // Ghi vao %APPDATA%/SonicForgeDAW/logs/spawn.log (thu muc luon ton - // tai) — KHONG ghi vao engine_dir vi thu muc do co the khong duoc - // bundle vao installer (resources loi) -> ghi am tham that bai. + let exe_dir = std::env::current_exe() + .ok() + .and_then(|p| p.parent().map(|d| d.to_path_buf())) + .unwrap_or_default(); + let candidates = engine_candidates(&res_dir, &exe_dir); + + // Ghi log spawn de chan doan — vao %APPDATA%/SonicForgeDAW/logs/ + // spawn.log (thu muc luon ton tai), KHONG ghi vao engine_dir. let log_dir = std::env::var("APPDATA").unwrap_or_else(|_| ".".into()); let spawn_log_path = std::path::Path::new(&log_dir) .join("SonicForgeDAW") @@ -37,12 +93,31 @@ pub fn run() { if let Some(parent) = spawn_log_path.parent() { let _ = std::fs::create_dir_all(parent); } - let log_line = format!( - "spawn daw_engine: {} exists={}\nresource_dir={}\n", - engine_exe.display(), - engine_exe.exists(), - res_dir.display() + + let mut log_line = format!( + "resource_dir={}\nexe_dir={}\n", + res_dir.display(), + exe_dir.display() ); + let mut found: Option<(PathBuf, String)> = None; + for (path, label) in &candidates { + let exists = path.exists(); + log_line.push_str(&format!( + " [{label}] {} exists={}\n", + path.display(), + exists + )); + if found.is_none() && exists { + found = Some((path.clone(), label.clone())); + } + } + if found.is_none() { + log_line.push_str(&format!( + " NOT FOUND — resource_dir contents: {}\n exe_dir contents: {}\n", + list_dir_snippet(&res_dir), + list_dir_snippet(&exe_dir) + )); + } if let Ok(mut f) = std::fs::OpenOptions::new() .create(true) .append(true) @@ -51,26 +126,40 @@ pub fn run() { use std::io::Write; let _ = f.write_all(log_line.as_bytes()); } - match app.shell().command(&engine_exe) - .env("SF_PARENT_PID", std::process::id().to_string()) - .spawn() { - Ok((_rx, child)) => { - app.manage(EngineProcess(Mutex::new(Some(child)))); - println!("Python Background Engine started (localhost:8000, auto-fallback 8000-8010)"); + + match found { + Some((engine_exe, label)) => { + match app + .shell() + .command(&engine_exe) + .env("SF_PARENT_PID", std::process::id().to_string()) + .spawn() + { + Ok((_rx, child)) => { + app.manage(EngineProcess(Mutex::new(Some(child)))); + println!( + "Python Background Engine started ({label}): {}", + engine_exe.display() + ); + } + Err(e) => { + println!("Failed to spawn daw_engine {engine_exe:?}: {e}"); + app.manage(EngineProcess(Mutex::new(None))); + } + } } - Err(e) => { - // Khong panic: UI van mo, engine loi se hien trong UI loader - // ("Khong tim thay SonicForge Engine"). Log ro de chan doan. - println!("Failed to spawn daw_engine: {e}"); + None => { + println!( + "daw_engine binary not found in any candidate path — xem spawn.log de biet chi tiet" + ); app.manage(EngineProcess(Mutex::new(None))); } } Ok(()) }) .on_window_event(|window, event| { - // 2. Terminate sidecar khi DAW window dong — tranh orphan process + // Terminate sidecar khi DAW window dong — tranh orphan process if let tauri::WindowEvent::Destroyed = event { - // Lay child ra khoi lock, guard drop ngay tai day (trach E0597) let child = window .state::() .0 diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c6a0c19..c2a21b8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -32,9 +32,9 @@ "icons/128x128@2x.png", "icons/favicon.ico" ], - "resources": [ - "resources/daw_engine" - ], + "resources": { + "resources/daw_engine": "daw_engine/" + }, "externalBin": [], "windows": { "nsis": {