diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 09c7bcb..581704e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -43,6 +43,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -73,6 +84,23 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -106,6 +134,12 @@ dependencies = [ "rustversion", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "assert_cfg" version = "0.1.0" @@ -533,6 +567,30 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "brotli" version = "8.0.2" @@ -580,6 +638,40 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-unit" +version = "5.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bcaa4a0975bed4a760af3efe4368825098ce5f9d37a30c5a021d635dc63d8f" +dependencies = [ + "rust_decimal", + "schemars 1.2.1", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.25.0" @@ -1373,6 +1465,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1436,6 +1538,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1500,6 +1611,7 @@ dependencies = [ "tauri-plugin-fs", "tauri-plugin-http", "tauri-plugin-libmpv", + "tauri-plugin-log", "tauri-plugin-notification", "tauri-plugin-process", "tauri-plugin-shell", @@ -2077,6 +2189,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -3011,6 +3126,9 @@ name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +dependencies = [ + "value-bag", +] [[package]] name = "lru-slab" @@ -3307,6 +3425,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc2" version = "0.6.4" @@ -3916,6 +4043,26 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "publicsuffix" version = "2.3.0" @@ -4197,6 +4344,15 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.28" @@ -4321,6 +4477,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rlimit" version = "0.10.2" @@ -4340,6 +4525,23 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust_decimal" +version = "1.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2a24f50780bc85f09cc6ac299bdf1424302742d77221106859c9d8b102126a" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] + [[package]] name = "rustc-hash" version = "2.1.2" @@ -4529,6 +4731,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "3.7.0" @@ -4998,6 +5206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] @@ -5375,6 +5584,28 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "tauri-plugin-log" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2", + "objc2-foundation", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "time", +] + [[package]] name = "tauri-plugin-notification" version = "2.3.3" @@ -5654,7 +5885,9 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -6170,6 +6403,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -6188,6 +6427,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "version-compare" version = "0.2.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7799eda..991277e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -37,6 +37,7 @@ tauri-plugin-single-instance = "2" tauri-plugin-updater = "2" tauri-plugin-process = "2" tauri-plugin-dialog = "2" +tauri-plugin-log = "2" [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.18" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 870d5d7..47c1e9e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -301,6 +301,15 @@ pub fn run() { } } })) + .plugin( + tauri_plugin_log::Builder::new() + .level(log::LevelFilter::Debug) + .targets([ + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::LogDir { file_name: None }), + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout), + ]) + .build(), + ) .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_dialog::init()) diff --git a/src-tauri/src/mpv_render.rs b/src-tauri/src/mpv_render.rs index 08936d3..260d40e 100644 --- a/src-tauri/src/mpv_render.rs +++ b/src-tauri/src/mpv_render.rs @@ -673,6 +673,7 @@ impl MpvRenderer { let text = unsafe { CStr::from_ptr(msg.text) }.to_string_lossy(); let text = text.trim_end(); if !text.is_empty() { + log::debug!("mpv: {text}"); if self.log_ring.len() >= 20 { self.log_ring.pop_front(); } diff --git a/src-tauri/src/player.rs b/src-tauri/src/player.rs index 5f3cf69..0b0951d 100644 --- a/src-tauri/src/player.rs +++ b/src-tauri/src/player.rs @@ -256,6 +256,7 @@ pub fn player_load( start_at: Option, total_duration: Option, ) -> Result<(), String> { + log::info!("player_load: url={url} start_at={start_at:?} total_duration={total_duration:?}"); *state.thumb_url.lock().unwrap() = Some(url.clone()); #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))] @@ -263,6 +264,7 @@ pub fn player_load( if let Some(surface) = ensure_native_player_surface(&app, &state) { return surface.load(url, start_at, total_duration); } + log::warn!("player_load: no native player surface available, falling back to headless renderer"); } let _ = app; diff --git a/src-tauri/src/windows_player_surface.rs b/src-tauri/src/windows_player_surface.rs index 7146f69..638791a 100644 --- a/src-tauri/src/windows_player_surface.rs +++ b/src-tauri/src/windows_player_surface.rs @@ -129,6 +129,7 @@ pub fn install(app_handle: AppHandle) -> Result { let app = app_handle.clone(); std::thread::spawn(move || { + log::info!("player surface: install thread starting"); // Register the OpenGL-capable window class once per process. static CLASS_REGISTERED: OnceLock<()> = OnceLock::new(); CLASS_REGISTERED.get_or_init(|| { @@ -168,6 +169,7 @@ pub fn install(app_handle: AppHandle) -> Result { ) }; if child_hwnd == 0 { + log::error!("player surface: CreateWindowExW failed for mpv surface"); let _ = setup_tx.send(Err("CreateWindowExW failed for mpv surface".to_string())); return; } @@ -180,6 +182,7 @@ pub fn install(app_handle: AppHandle) -> Result { // WGL context setup let hdc = unsafe { GetDC(child_hwnd) }; if hdc == 0 { + log::error!("player surface: GetDC failed"); let _ = setup_tx.send(Err("GetDC failed".to_string())); return; } @@ -195,20 +198,24 @@ pub fn install(app_handle: AppHandle) -> Result { let pf_idx = unsafe { ChoosePixelFormat(hdc, &pfd) }; if pf_idx == 0 { + log::error!("player surface: ChoosePixelFormat failed"); let _ = setup_tx.send(Err("ChoosePixelFormat failed".to_string())); return; } if unsafe { SetPixelFormat(hdc, pf_idx, &pfd) } == FALSE { + log::error!("player surface: SetPixelFormat failed"); let _ = setup_tx.send(Err("SetPixelFormat failed".to_string())); return; } let hglrc = unsafe { wglCreateContext(hdc) }; if hglrc == 0 { + log::error!("player surface: wglCreateContext failed"); let _ = setup_tx.send(Err("wglCreateContext failed".to_string())); return; } if unsafe { wglMakeCurrent(hdc, hglrc) } == FALSE { + log::error!("player surface: wglMakeCurrent failed"); unsafe { wglDeleteContext(hglrc) }; let _ = setup_tx.send(Err("wglMakeCurrent failed".to_string())); return; @@ -224,8 +231,12 @@ pub fn install(app_handle: AppHandle) -> Result { let mut renderer = state.player_renderer.lock().unwrap(); if renderer.is_none() { match crate::mpv_render::MpvRenderer::new() { - Ok(r) => *renderer = Some(r), + Ok(r) => { + log::info!("player surface: MpvRenderer::new() succeeded"); + *renderer = Some(r); + } Err(e) => { + log::error!("player surface: MpvRenderer::new() failed: {e}"); unsafe { wglMakeCurrent(0 as _, 0 as _); wglDeleteContext(hglrc); @@ -237,6 +248,7 @@ pub fn install(app_handle: AppHandle) -> Result { } if let Some(r) = renderer.as_mut() { if let Err(e) = r.prepare_opengl_context() { + log::error!("player surface: prepare_opengl_context() failed: {e}"); unsafe { wglMakeCurrent(0 as _, 0 as _); wglDeleteContext(hglrc); @@ -252,6 +264,7 @@ pub fn install(app_handle: AppHandle) -> Result { } } + log::info!("player surface: setup complete, entering render loop"); let _ = setup_tx.send(Ok(())); // Render + command loop @@ -263,6 +276,7 @@ pub fn install(app_handle: AppHandle) -> Result { while let Ok(cmd) = receiver.try_recv() { match cmd { SurfaceCommand::Load { url, start_at, .. } => { + log::info!("player surface: loading url={url} start_at={start_at:?}"); unsafe { ShowWindow(child_hwnd, SW_SHOW) }; unsafe { SetWindowPos( @@ -282,11 +296,16 @@ pub fn install(app_handle: AppHandle) -> Result { let mut renderer = state.player_renderer.lock().unwrap(); if let Some(r) = renderer.as_mut() { if let Err(e) = r.load(&url, start_at) { + log::error!("player surface: load() failed: {e}"); drop(renderer); let _ = app.emit("native-player-error", e); visible = false; unsafe { ShowWindow(child_hwnd, SW_HIDE) }; + } else { + log::info!("player surface: load() command accepted by mpv"); } + } else { + log::error!("player surface: Load command received but renderer is None"); } } SurfaceCommand::Hide => { @@ -378,7 +397,9 @@ fn check_player_events(app: &AppHandle) { }; for event in events { let crate::mpv_render::PlayerEvent::EndFile { eof, error } = event; + log::info!("player surface: mpv END_FILE event eof={eof} error={error:?}"); if let Some(message) = error { + log::error!("player surface: stream failed to play: {message}"); let _ = app.emit("native-player-error", message); continue; } @@ -388,8 +409,10 @@ fn check_player_events(app: &AppHandle) { let next_sub = state.next_ep_subtitle.lock().unwrap().clone(); let auto_play = *state.auto_play_next_episode.lock().unwrap(); if !next_sub.is_empty() && auto_play { + log::info!("player surface: eof reached, auto-playing next episode"); let _ = app.emit("native-player-next-episode", ()); } else { + log::info!("player surface: eof reached, closing player"); let _ = app.emit("native-player-close-requested", ()); } }