diff --git a/Cargo.lock b/Cargo.lock index d7298eae..cdd719e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,6 +327,18 @@ dependencies = [ "ipc-channel", "serde_json", "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", ] [[package]] @@ -344,6 +356,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -502,6 +520,15 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -557,6 +584,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tokio" version = "1.42.0" @@ -586,6 +623,63 @@ dependencies = [ "syn", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.14" @@ -607,12 +701,40 @@ dependencies = [ "getrandom", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.58.0" diff --git a/Cargo.toml b/Cargo.toml index c4d19ede..4bf18f7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,5 @@ clap_derive = "4.5.18" ipc-channel = "0.19.0" serde_json = "1.0.133" tokio = { version = "1.42.0", features = ["full"] } +tracing = "0.1.41" +tracing-subscriber = "0.3.19" diff --git a/src/main.rs b/src/main.rs index 20297506..f4643a75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ use std::io::{self}; use std::path::PathBuf; use tokio::net::UnixStream; use tokio::io::{AsyncWriteExt, AsyncReadExt}; +use tracing::{debug, info, error}; +use tracing_subscriber; #[derive(Parser)] #[command(author, version, about)] @@ -33,22 +35,26 @@ enum CommandOptions { } const SOCKET_PATH: &str = "/tmp/mpvsocket"; - async fn send_ipc_command(command: &str, args: &[serde_json::Value]) -> io::Result> { + debug!("Sending IPC command: {} with arguments: {:?}", command, args); let mut socket = UnixStream::connect(SOCKET_PATH).await?; let message = json!({ "command": [command, args] }); let message_str = serde_json::to_string(&message)?; + socket.write_all(message_str.as_bytes()).await?; socket.flush().await?; + let mut response = vec![0; 1024]; let n = socket.read(&mut response).await?; let response_str = String::from_utf8_lossy(&response[..n]); - let json_response: Result = serde_json::from_str(&response_str); - match json_response { - Ok(response) => Ok(response.get("data").cloned()), + match serde_json::from_str::(&response_str) { + Ok(json_response) => { + debug!("Received response: {}", response_str); + Ok(json_response.get("data").cloned()) + } Err(e) => { - eprintln!("Failed to parse response: {}", e); + error!("Failed to parse response: {}", e); Ok(None) } } @@ -56,57 +62,76 @@ async fn send_ipc_command(command: &str, args: &[serde_json::Value]) -> io::Resu #[tokio::main] async fn main() -> io::Result<()> { + tracing_subscriber::fmt::init(); + let cli = Cli::parse(); + if !PathBuf::from(SOCKET_PATH).exists() { - eprintln!("Error: MPV socket not found. Is MPV running?"); + debug!(SOCKET_PATH); + error!("Error: MPV socket not found. Is MPV running?"); return Ok(()); } + match cli.command { CommandOptions::Play { index } => { if let Some(idx) = index { + info!("Playing media at index: {}", idx); send_ipc_command("set_property", &[json!("playlist-pos"), json!(idx)]).await?; } + info!("Unpausing playback"); send_ipc_command("set_property", &[json!("pause"), json!(false)]).await?; } CommandOptions::Pause => { + info!("Pausing playback"); send_ipc_command("set_property", &[json!("pause"), json!(true)]).await?; } CommandOptions::Stop => { + info!("Stopping playback and quitting MPV"); send_ipc_command("quit", &[]).await?; } CommandOptions::Next => { + info!("Skipping to next item in the playlist"); send_ipc_command("playlist-next", &[]).await?; } CommandOptions::Prev => { + info!("Skipping to previous item in the playlist"); send_ipc_command("playlist-prev", &[]).await?; } CommandOptions::Seek { seconds } => { + info!("Seeking to {} seconds", seconds); send_ipc_command("seek", &[json!(seconds)]).await?; } CommandOptions::Move { index1, index2 } => { + info!("Moving item from index {} to {}", index1, index2); send_ipc_command("playlist-move", &[json!(index1), json!(index2)]).await?; } CommandOptions::Remove { index } => { if let Some(idx) = index { + info!("Removing item at index {}", idx); send_ipc_command("playlist-remove", &[json!(idx)]).await?; } else { + info!("Removing current item from playlist"); send_ipc_command("playlist-remove", &[json!("current")]).await?; } } CommandOptions::Clear => { + info!("Clearing the playlist"); send_ipc_command("playlist-clear", &[]).await?; } CommandOptions::List => { + info!("Listing playlist items"); if let Some(data) = send_ipc_command("get_property", &[json!("playlist")]).await? { println!("{}", serde_json::to_string_pretty(&data)?); } } CommandOptions::Add { filenames } => { + info!("Adding {} files to the playlist", filenames.len()); for filename in filenames { send_ipc_command("loadfile", &[json!(filename), json!("append-play")]).await?; } } CommandOptions::Replace { filenames } => { + info!("Replacing current playlist with {} files", filenames.len()); if let Some(first_file) = filenames.first() { send_ipc_command("loadfile", &[json!(first_file), json!("replace")]).await?; for filename in &filenames[1..] { @@ -115,6 +140,7 @@ async fn main() -> io::Result<()> { } } CommandOptions::Prop { properties } => { + info!("Fetching properties: {:?}", properties); for property in properties { if let Some(data) = send_ipc_command("get_property", &[json!(property)]).await? { println!("{}: {}", property, data);