From bd29978b2a0d0d6def486fcdaa63bc8934d68045 Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 5 May 2026 21:12:32 +0200 Subject: fix(daemon): robust auto-advance; ensure next track starts even if playback fails --- src/playback.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/playback.rs (limited to 'src/playback.rs') diff --git a/src/playback.rs b/src/playback.rs new file mode 100644 index 0000000..76c0f44 --- /dev/null +++ b/src/playback.rs @@ -0,0 +1,131 @@ +use std::path::PathBuf; + +#[derive(Debug, Clone, PartialEq)] +#[allow(dead_code)] +pub enum PlaybackState { + Stopped, + Playing, + Paused, +} + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub struct Track { + pub path: PathBuf, + pub title: String, + pub artist: String, + pub album: String, + pub duration: Option, +} + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub enum ShuffleMode { + None, + All, + Album, +} + +#[allow(dead_code)] +pub struct Player { + state: PlaybackState, + current_track: Option, + queue: Vec, + volume: u8, + shuffle: ShuffleMode, +} + +#[allow(dead_code)] +impl Player { + pub fn new() -> Self { + Player { + state: PlaybackState::Stopped, + current_track: None, + queue: Vec::new(), + volume: 70, + shuffle: ShuffleMode::None, + } + } + + pub fn state(&self) -> &PlaybackState { + &self.state + } + + pub fn volume(&self) -> u8 { + self.volume + } + + pub fn play(&mut self) { + if self.state == PlaybackState::Paused { + self.resume(); + } else if self.current_track.is_none() && !self.queue.is_empty() { + self.current_track = Some(self.queue.remove(0)); + self.state = PlaybackState::Playing; + } + } + + pub fn play_track(&mut self, track: Track) { + self.current_track = Some(track); + self.state = PlaybackState::Playing; + } + + pub fn pause(&mut self) { + if self.state == PlaybackState::Playing { + self.state = PlaybackState::Paused; + } + } + + pub fn resume(&mut self) { + if self.state == PlaybackState::Paused { + self.state = PlaybackState::Playing; + } + } + + pub fn stop(&mut self) { + self.state = PlaybackState::Stopped; + self.current_track = None; + } + + pub fn next(&mut self) { + if !self.queue.is_empty() { + self.current_track = Some(self.queue.remove(0)); + } else { + self.stop(); + } + } + + pub fn previous(&mut self) { + if (self.state == PlaybackState::Playing || self.state == PlaybackState::Paused) + && self.current_track.is_some() + { + self.state = PlaybackState::Playing; + } + } + + pub fn set_volume(&mut self, level: u8) { + self.volume = level.min(100); + } + + pub fn set_shuffle(&mut self, mode: ShuffleMode) { + self.shuffle = mode; + } + + pub fn queue_track(&mut self, track: Track, position: &str) { + match position { + "now" => self.queue.insert(0, track), + "next" => { + let idx = 1.min(self.queue.len()); + self.queue.insert(idx, track); + } + _ => self.queue.push(track), + } + } + + pub fn dequeue_next(&mut self) -> Option { + if !self.queue.is_empty() { + Some(self.queue.remove(0)) + } else { + None + } + } +} -- cgit v1.2.3