From 455ec54613230f4004a24f8d2798fb0084e00cb4 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 11 May 2026 16:25:49 +0200 Subject: Add display_format config, fix restart command, clean up config code - Add display_format option with get/set/list/unset for customizing track display - Add Track::format() supporting $ARTIST, $ALBUM, $TRACK variables - Update queue, status, notifications to use display_format - Fix restart command using wrong subcommand 'start' -> 'start-daemon' - Remove socket_path from config (now computed at runtime from XDG_RUNTIME_DIR) - Consolidate duplicate save() and save_all() into single save() - Fix redundant .clone().clone() in config.rs - Add todo item for caching config in daemon hot paths --- src/daemon.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'src/daemon.rs') diff --git a/src/daemon.rs b/src/daemon.rs index b79e67a..acc7729 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -12,7 +12,7 @@ use std::time::Duration; pub fn start_daemon() -> Result<(), Box> { let config = Config::load()?; - let socket_path = config.get_socket_path(); + let socket_path = Config::get_socket_path(); let pid_path = get_pid_path(&config); // Check if daemon is already running @@ -55,7 +55,6 @@ pub fn start_daemon() -> Result<(), Box> { let queue = Arc::new(Mutex::new(Queue::new())); // Load and apply saved settings - let config = Config::load().unwrap_or_default(); if let Some(vol) = config.volume { audio_engine.set_volume(vol as f32 / 100.0); } @@ -69,6 +68,9 @@ pub fn start_daemon() -> Result<(), Box> { } } + // Save full config + config.save()?; + // Accept connections until shutdown listener.set_nonblocking(true)?; // Helper: poll until a specific track actually starts playing or timeout @@ -106,7 +108,8 @@ pub fn start_daemon() -> Result<(), Box> { audio_engine.play(next_track.clone()); if wait_for_start(&audio_engine, &next_track, 500) { started = true; - notification::notify_track(&Track::from_path(next_track)); + let fmt = Config::load().ok().and_then(|c| c.display_format.clone()); + notification::notify_track(&Track::from_path(next_track), fmt.as_deref()); break; } } else { @@ -182,7 +185,7 @@ pub fn stop_daemon() -> Result<(), Box> { } // Clean up files - let socket_path = config.get_socket_path(); + let socket_path = Config::get_socket_path(); std::fs::remove_file(&socket_path).ok(); std::fs::remove_file(&pid_path).ok(); @@ -203,7 +206,7 @@ pub fn restart_daemon() -> Result<(), Box> { // Start new daemon in background let current_exe = std::env::current_exe()?; std::process::Command::new(current_exe) - .arg("start") + .arg("start-daemon") .spawn()?; println!("Daemon restarted"); @@ -216,8 +219,7 @@ pub fn send_command(cmd: String) -> Result<(), Box> { } fn send_command_raw(cmd: String) -> Result<(), Box> { - let config = Config::load()?; - let socket_path = config.get_socket_path(); + let socket_path = Config::get_socket_path(); let mut stream = UnixStream::connect(socket_path)?; stream.write_all(cmd.as_bytes())?; @@ -254,7 +256,11 @@ fn process_command( if audio.is_playing() { if let Some(track_path) = audio.current_track() { let track = Track::from_path(track_path); - let track_str = track.display_string(0, 1); + let fmt = Config::load().ok().and_then(|c| c.display_format.clone()); + let track_str = match fmt.as_deref() { + Some(f) => track.format(f), + None => track.display_string(0, 1), + }; format!("Playing\nTrack: {}\n", track_str) } else { "Playing\n".to_string() @@ -296,7 +302,11 @@ fn process_command( if let Ok(mut q) = queue.lock() { if let Some(next_track) = q.next() { audio.play(next_track.clone()); - notification::notify_track(&Track::from_path(next_track)); + let fmt = Config::load().ok().and_then(|c| c.display_format.clone()); + notification::notify_track( + &Track::from_path(next_track.clone()), + fmt.as_deref(), + ); "Playing next track\n".to_string() } else { audio.stop(); @@ -311,7 +321,11 @@ fn process_command( if let Ok(mut q) = queue.lock() { if let Some(prev_track) = q.previous() { audio.play(prev_track.clone()); - notification::notify_track(&Track::from_path(prev_track)); + let fmt = Config::load().ok().and_then(|c| c.display_format.clone()); + notification::notify_track( + &Track::from_path(prev_track.clone()), + fmt.as_deref(), + ); "Playing previous track\n".to_string() } else { "No previous track\n".to_string() @@ -371,7 +385,13 @@ fn process_command( } else { ("last", rest) }; - let path_str = path_str.to_string(); + let path_str = if path_str.starts_with("~/") { + std::env::var("HOME") + .map(|h| path_str.replacen("~", &h, 1)) + .unwrap_or_else(|_| path_str.to_string()) + } else { + path_str.to_string() + }; if path_str.is_empty() { return "Usage: play [now|next|last] \n".to_string(); @@ -390,7 +410,9 @@ fn process_command( } if let Some(track) = q.track_at(q.position()) { audio.play(track.path.clone()); - notification::notify_track(track); + let fmt = + Config::load().ok().and_then(|c| c.display_format.clone()); + notification::notify_track(track, fmt.as_deref()); } format!("Playing now: {}\n", path_str) } @@ -405,7 +427,9 @@ fn process_command( if was_empty && !was_playing { let track = Track::from_path(path.clone()); audio.play(path); - notification::notify_track(&track); + let fmt = + Config::load().ok().and_then(|c| c.display_format.clone()); + notification::notify_track(&track, fmt.as_deref()); format!("Playing: {}\n", path_str) } else { format!("Queued: {}\n", path_str) @@ -431,7 +455,10 @@ fn process_command( } if let Some(track) = q.track_at(q.position()) { audio.play(track.path.clone()); - notification::notify_track(track); + let fmt = Config::load() + .ok() + .and_then(|c| c.display_format.clone()); + notification::notify_track(track, fmt.as_deref()); } format!( "Playing now: {} tracks from {}\n", @@ -459,7 +486,10 @@ fn process_command( && let Some(track) = q.current() { audio.play(track.path.clone()); - notification::notify_track(track); + let fmt = Config::load() + .ok() + .and_then(|c| c.display_format.clone()); + notification::notify_track(track, fmt.as_deref()); } format!("Queued {} tracks from: {}\n", files.len(), path_str) } @@ -512,9 +542,13 @@ fn process_command( q.shuffled_indices().to_vec() }; let is_playing = audio.is_playing(); + let fmt = Config::load().ok().and_then(|c| c.display_format.clone()); for (display_idx, &track_idx) in indices.iter().enumerate() { if let Some(track) = q.track_at(track_idx) { - let track_str = track.display_string(display_idx, q.len()); + let track_str = match fmt.as_deref() { + Some(f) => track.format(f), + None => track.display_string(display_idx, q.len()), + }; if track_idx == playing_track_idx && is_playing { output.push_str(&format!("> {} (playing)\n", track_str)); } else { -- cgit v1.2.3