diff --git a/Cargo.lock b/Cargo.lock index 555d3b3..5b8cf14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1551,7 +1551,7 @@ dependencies = [ [[package]] name = "mpd_info_screen" -version = "0.2.18" +version = "0.2.19" dependencies = [ "ggez", "image 0.24.1", diff --git a/Cargo.toml b/Cargo.toml index b0d82f8..e0f9b1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mpd_info_screen" -version = "0.2.18" +version = "0.2.19" edition = "2018" description = "Displays info on currently playing music from an MPD daemon" license = "MIT" diff --git a/README.md b/README.md index 0654193..9089cad 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ counter, and the filename currently being played # Usage - mpd_info_screen 0.2.18 + mpd_info_screen 0.2.19 USAGE: mpd_info_screen [FLAGS] [OPTIONS] [port] diff --git a/src/display.rs b/src/display.rs index c30f7ac..ebc5c2b 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,5 +1,5 @@ use crate::debug_log::{self, log}; -use crate::mpd_handler::{InfoFromShared, MPDHandler, MPDHandlerState}; +use crate::mpd_handler::{InfoFromShared, MPDHandler, MPDHandlerState, MPDPlayState}; use crate::Opt; use ggez::event::{self, EventHandler}; use ggez::graphics::{ @@ -77,6 +77,7 @@ pub struct MPDDisplay { text_bg_mesh: Option, hide_text: bool, tried_album_art_in_dir: bool, + mpd_play_state: MPDPlayState, } impl MPDDisplay { @@ -109,6 +110,7 @@ impl MPDDisplay { text_bg_mesh: None, hide_text: false, tried_album_art_in_dir: false, + mpd_play_state: MPDPlayState::Playing, } } @@ -573,43 +575,56 @@ impl EventHandler for MPDDisplay { .mpd_handler .as_ref() .unwrap() - .get_current_song_info() + .get_mpd_handler_shared_state() .ok(); if let Some(shared) = &self.shared { if self.notice_text.contents() != shared.error_text { self.notice_text = Text::new(TextFragment::new(shared.error_text.clone())); } - if !shared.title.is_empty() { - self.title_text = Text::new(shared.title.clone()); - } else { - self.dirty_flag - .as_ref() - .unwrap() - .store(true, Ordering::Relaxed); - } - if !shared.artist.is_empty() { - self.artist_text = Text::new(shared.artist.clone()); - } else { - self.dirty_flag - .as_ref() - .unwrap() - .store(true, Ordering::Relaxed); - } - if !shared.filename.is_empty() { - if self.filename_text.contents() != shared.filename { + if shared.mpd_play_state != MPDPlayState::Playing { + if shared.mpd_play_state == MPDPlayState::Stopped { + self.title_text = Text::new(""); + self.artist_text = Text::new(""); + self.filename_text = Text::new(""); + self.timer = 0.0; + self.length = 0.0; self.album_art = None; - self.tried_album_art_in_dir = false; } - self.filename_text = Text::new(shared.filename.clone()); + self.mpd_play_state = shared.mpd_play_state; } else { - self.dirty_flag - .as_ref() - .unwrap() - .store(true, Ordering::Relaxed); + self.mpd_play_state = MPDPlayState::Playing; + if !shared.title.is_empty() { + self.title_text = Text::new(shared.title.clone()); + } else { + self.dirty_flag + .as_ref() + .unwrap() + .store(true, Ordering::Relaxed); + } + if !shared.artist.is_empty() { + self.artist_text = Text::new(shared.artist.clone()); + } else { + self.dirty_flag + .as_ref() + .unwrap() + .store(true, Ordering::Relaxed); + } + if !shared.filename.is_empty() { + if self.filename_text.contents() != shared.filename { + self.album_art = None; + self.tried_album_art_in_dir = false; + } + self.filename_text = Text::new(shared.filename.clone()); + } else { + self.dirty_flag + .as_ref() + .unwrap() + .store(true, Ordering::Relaxed); + } + self.timer = shared.pos; + self.length = shared.length; + self.refresh_text_transforms(ctx)?; } - self.timer = shared.pos; - self.length = shared.length; - self.refresh_text_transforms(ctx)?; } else { log( "Failed to acquire read lock for getting shared data", @@ -648,7 +663,10 @@ impl EventHandler for MPDDisplay { fn draw(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> { graphics::clear(ctx, Color::BLACK); - if self.album_art.is_some() && self.album_art_draw_transform.is_some() { + if self.mpd_play_state != MPDPlayState::Stopped + && self.album_art.is_some() + && self.album_art_draw_transform.is_some() + { self.album_art.as_ref().unwrap().draw( ctx, DrawParam { @@ -661,7 +679,8 @@ impl EventHandler for MPDDisplay { if !self.hide_text { self.notice_text.draw(ctx, DrawParam::default())?; - if self.is_valid && self.is_initialized { + if self.mpd_play_state != MPDPlayState::Stopped && self.is_valid && self.is_initialized + { if let Some(mesh) = &self.text_bg_mesh { mesh.draw(ctx, DrawParam::default())?; } @@ -696,13 +715,15 @@ impl EventHandler for MPDDisplay { )?; } - self.timer_text.draw( - ctx, - DrawParam { - trans: self.timer_transform, - ..Default::default() - }, - )?; + if self.mpd_play_state == MPDPlayState::Playing { + self.timer_text.draw( + ctx, + DrawParam { + trans: self.timer_transform, + ..Default::default() + }, + )?; + } } } diff --git a/src/mpd_handler.rs b/src/mpd_handler.rs index fc922a3..8d9f5b1 100644 --- a/src/mpd_handler.rs +++ b/src/mpd_handler.rs @@ -11,7 +11,7 @@ const SLEEP_DURATION: Duration = Duration::from_millis(100); const POLL_DURATION: Duration = Duration::from_secs(5); const BUF_SIZE: usize = 1024 * 4; -#[derive(Debug, PartialEq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] enum PollState { None, Password, @@ -21,6 +21,13 @@ enum PollState { ReadPictureInDir, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum MPDPlayState { + Playing, + Paused, + Stopped, +} + #[derive(Debug, Clone)] pub struct InfoFromShared { pub filename: String, @@ -29,6 +36,7 @@ pub struct InfoFromShared { pub length: f64, pub pos: f64, pub error_text: String, + pub mpd_play_state: MPDPlayState, } #[derive(Clone)] @@ -66,6 +74,7 @@ pub struct MPDHandlerState { dirty_flag: Arc, pub stop_flag: Arc, log_level: LogLevel, + mpd_play_state: MPDPlayState, } fn check_next_chars( @@ -267,6 +276,7 @@ impl MPDHandler { dirty_flag: Arc::new(AtomicBool::new(true)), stop_flag: Arc::new(AtomicBool::new(false)), log_level, + mpd_play_state: MPDPlayState::Stopped, })), }; @@ -285,7 +295,7 @@ impl MPDHandler { Ok(s) } - pub fn get_current_song_info(&self) -> Result { + pub fn get_mpd_handler_shared_state(&self) -> Result { if let Ok(read_lock) = self.state.try_read() { return Ok(InfoFromShared { filename: read_lock.current_song_filename.clone(), @@ -295,6 +305,7 @@ impl MPDHandler { pos: read_lock.current_song_position + read_lock.song_pos_get_time.elapsed().as_secs_f64(), error_text: read_lock.error_text.clone(), + mpd_play_state: read_lock.mpd_play_state, }); } @@ -468,6 +479,8 @@ impl MPDHandler { } let mut buf_vec: Vec = Vec::from(&buf[0..read_amount]); + let mut got_mpd_state: MPDPlayState = MPDPlayState::Playing; + 'handle_buf: loop { if write_handle.current_binary_size > 0 { if write_handle.current_binary_size <= buf_vec.len() { @@ -600,6 +613,40 @@ impl MPDHandler { _ => (), } write_handle.poll_state = PollState::None; + } else if line.starts_with("state: ") { + let remaining = line.split_off(7); + let remaining = remaining.trim(); + if remaining == "stop" { + write_handle.current_song_filename.clear(); + write_handle.art_data.clear(); + write_handle.art_data_size = 0; + write_handle.art_data_type.clear(); + write_handle.can_get_album_art = true; + write_handle.can_get_album_art_in_dir = true; + write_handle.current_song_title.clear(); + write_handle.current_song_artist.clear(); + write_handle.current_song_length = 0.0; + write_handle.current_song_position = 0.0; + write_handle.did_check_overtime = false; + write_handle.force_get_status = true; + } + if remaining == "stop" || remaining == "pause" { + got_mpd_state = if remaining == "stop" { + MPDPlayState::Stopped + } else { + MPDPlayState::Paused + }; + write_handle.error_text.clear(); + write_handle + .error_text + .push_str(&format!("MPD has {:?}", got_mpd_state)); + log( + format!("MPD is {:?}", got_mpd_state), + LogState::Warning, + write_handle.log_level, + ); + break 'handle_buf; + } } else if line.starts_with("file: ") { let song_file = line.split_off(6); if song_file != write_handle.current_song_filename { @@ -699,6 +746,20 @@ impl MPDHandler { } } // 'handle_buf: loop + if got_mpd_state != write_handle.mpd_play_state { + write_handle.dirty_flag.store(true, Ordering::Relaxed); + if got_mpd_state == MPDPlayState::Playing { + write_handle.error_text.clear(); + } + } + write_handle.mpd_play_state = got_mpd_state; + if got_mpd_state != MPDPlayState::Playing { + write_handle.poll_state = PollState::None; + write_handle.song_pos_get_time = Instant::now(); + write_handle.current_song_length = 30.0; + write_handle.current_song_position = 0.0; + } + Ok(()) } @@ -738,6 +799,7 @@ impl MPDHandler { } else if write_handle.can_get_status && (write_handle.song_title_get_time.elapsed() > POLL_DURATION || write_handle.force_get_current_song) + && write_handle.mpd_play_state == MPDPlayState::Playing { write_handle.force_get_current_song = false; let write_result = write_handle.stream.write(b"currentsong\n");