diff --git a/src/lyrics.rs b/src/lyrics.rs index 0d759a2..973f72d 100644 --- a/src/lyrics.rs +++ b/src/lyrics.rs @@ -35,9 +35,8 @@ pub trait LyricsTrait { type Error; fn new(layout: LyricsLayout) -> std::result::Result where Self: Sized; - fn is_showing(&self) -> Result { Ok(false) } - fn reset(&mut self) -> Result<(), Self::Error> { Ok(()) } - fn start(&mut self, _lyrics: Vec<(u32, String)>) -> Result<(), Self::Error> { Ok(()) } + fn begin(&mut self, _lyrics: impl IntoIterator) -> Result<(), Self::Error> { Ok(()) } + fn end(&mut self) -> Result<(), Self::Error> { Ok(()) } fn update(&mut self, _time: Duration) -> Result<(), Self::Error> { Ok(()) } fn set_layout(&mut self, _layout: LyricsLayout) -> Result<(), Self::Error> { Ok(()) } } @@ -87,7 +86,7 @@ mod xosd { let (o1, o2, o3) = match v { VerticalAlign::Top => (0, small, small + big), - VerticalAlign::Center => (big, 0, -big), + VerticalAlign::Center => ((small + big) / 2, 0, -(small + big) / 2), VerticalAlign::Bottom => (small + big, small, 0), }; @@ -100,7 +99,12 @@ mod xosd { #[inline(always)] fn show(xosd: &mut Xosd, string: Option) -> Result<()> { - xosd.display(0, Command::String(string.unwrap_or_default()))?; + if let Some(string) = string { + xosd.display(0, Command::String(string))?; + } + else if xosd.onscreen()? { + xosd.hide()?; + } Ok(()) } @@ -125,16 +129,35 @@ mod xosd { } pub struct XosdLyrics { - lines: Vec<(u32, String)>, - index: usize, - showing: bool, - hidden: bool, + lines: Vec<(Duration, String)>, + index: Option, layout: LyricsLayout, prev: Xosd, curr: Xosd, next: Xosd, } + impl XosdLyrics { + #[inline(always)] + fn update_text(&mut self) -> Result<()> { + if self.layout.visible { + if let Some(index) = self.index { + show(&mut self.prev, (index > 1).then(|| self.lines[index - 2].1[1..].to_string()))?; + show(&mut self.curr, (index > 0).then(|| self.lines[index - 1].1[1..].to_string()))?; + show(&mut self.next, (index < self.lines.len()).then(|| self.lines[index].1[1..].to_string()))?; + + return Ok(()); + } + } + + show(&mut self.prev, None)?; + show(&mut self.curr, None)?; + show(&mut self.next, None)?; + + Ok(()) + } + } + impl LyricsTrait for XosdLyrics { type Error = Error; @@ -144,9 +167,7 @@ mod xosd { Ok(Self { lines: Vec::new(), - index: usize::MAX, - showing: false, - hidden: false, + index: None, layout, prev, curr, @@ -155,7 +176,7 @@ mod xosd { } #[inline(always)] - fn set_layout(&mut self, layout: LyricsLayout) -> std::result::Result<(), Self::Error> { + fn set_layout(&mut self, layout: LyricsLayout) -> Result<()> { if self.layout.visible != layout.visible { self.layout.visible = layout.visible; } @@ -168,59 +189,37 @@ mod xosd { self.next = next; self.layout = layout; - self.index = usize::MAX; + self.update_text()?; } Ok(()) } #[inline(always)] - fn is_showing(&self) -> std::result::Result { - Ok(self.showing) - } - - #[inline(always)] - fn reset(&mut self) -> std::result::Result<(), Self::Error> { - if self.showing { - show(&mut self.prev, None)?; - show(&mut self.curr, None)?; - show(&mut self.next, None)?; - - self.showing = false; - } + fn begin(&mut self, lyrics: impl IntoIterator) -> Result<()> { + self.lines = lyrics.into_iter().collect(); + self.lines.sort_by_key(|&(t, _)| t); + self.index = Some(0); + self.update_text()?; Ok(()) } #[inline(always)] - fn start(&mut self, lyrics: Vec<(u32, String)>) -> std::result::Result<(), Self::Error> { - self.lines = lyrics; - self.lines.sort_by_key(|&(t, _)| t); - self.index = usize::MAX; + fn end(&mut self) -> Result<()> { + self.index = None; + self.update_text()?; Ok(()) } #[inline(always)] fn update(&mut self, time: Duration) -> Result<()> { - if self.layout.visible { - let i = self.lines.partition_point(|&(t, _)| time.as_millis() > t as u128); - - if self.hidden || i != self.index { - self.index = i; - self.hidden = false; - - show(&mut self.prev, (i > 1).then(|| self.lines[i - 2].1[1..].to_string()))?; - show(&mut self.curr, (i > 0).then(|| self.lines[i - 1].1[1..].to_string()))?; - show(&mut self.next, (i < self.lines.len()).then(|| self.lines[i].1[1..].to_string()))?; - } - } - else if !self.hidden { - show(&mut self.prev, None)?; - show(&mut self.curr, None)?; - show(&mut self.next, None)?; - - self.hidden = true; + let i = self.lines.partition_point(|&(t, _)| time > t); + + if self.index.is_some_and(|index| i != index) { + self.index.replace(i); + self.update_text()?; } Ok(()) diff --git a/src/main.rs b/src/main.rs index 092452b..4a57058 100644 --- a/src/main.rs +++ b/src/main.rs @@ -244,44 +244,15 @@ impl App { } } PlayerState::Finished => { - if let Some(lyrics) = &mut app.lyrics { - if let Err(e) = lyrics.reset() { - println!("RUST-ERROR: Failed to reset lyrics {}", e) - } - } - app.player.idle(); - if app.stop_next { + if app.stop_next || app.playlist.poll().map(str::to_string).map(|s| app.play(&s)).is_none() { app.stop_next = false; + ["STOP"].gui_write_if(&mut app); println!("STATUS: Idle"); - } - else { - app.poll(); - } - - if let PlayerState::Idle = app.player.get_state() { - if let Some(lyrics) = &mut app.lyrics { - match lyrics.is_showing() { - Ok(true) => if let Err(e) = lyrics.reset() { - println!("RUST-ERROR: Failed to reset lyrics {}", e) - } - Ok(false) => {} - Err(e) => println!("RUST-ERROR: Failed to retrieve lyrics status {}", e) - } - } - } - } - PlayerState::Idle => { - if let Some(lyrics) = &mut app.lyrics { - match lyrics.is_showing() { - Ok(true) => if let Err(e) = lyrics.reset() { - println!("RUST-ERROR: Failed to reset lyrics {}", e) - } - Ok(false) => {} - Err(e) => println!("RUST-ERROR: Failed to retrieve lyrics status {}", e) - } + + app.end_lyrics(); } } _ => {} @@ -336,7 +307,7 @@ impl App { self.request_duration = true; self.show_lyrics(song); } - "STOP" => self.player.stop(), + "STOP" => { self.player.stop(); self.end_lyrics() } "REPLAY" => if let Some(song) = self.playlist.get_history().get_current().cloned() { self.play(&song) } "PREV" => if let Some(song) = self.playlist.look_back() { self.play(&song); } "SKIP" => self.player.skip(), @@ -411,6 +382,7 @@ impl App { if comb == self.stop_player { ["STOP"].gui_write_if(self); self.player.stop(); + self.end_lyrics(); } if comb == self.volume_increase { @@ -624,7 +596,7 @@ impl App { match Tag::read_from_path(path) { Ok(tag) => { if let Some(l) = tag.synchronised_lyrics().find(|l| l.lang == "eng") { - if let Err(e) = lyrics.start(l.content.clone()) { + if let Err(e) = lyrics.begin(l.content.iter().map(|(t, s)| (Duration::from_millis((*t).into()), s.clone()))) { println!("RUST-ERROR: Failed to display lyrics {}", e) } } @@ -635,12 +607,13 @@ impl App { } #[inline(always)] - fn poll(&mut self) { - if let Some(song) = self.playlist.poll().map(str::to_string) { - self.play(&song); - } - else { - println!("STATUS: Idle"); + fn end_lyrics(&mut self) { + println!("ended"); + + if let Some(lyrics) = &mut self.lyrics { + if let Err(e) = lyrics.end() { + println!("RUST-ERROR: Failed to reset lyrics {}", e) + } } } }