From 876533f116c716565a2eab0c605cc718dcd03ff9 Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Sat, 21 Sep 2024 13:29:47 +0200 Subject: [PATCH] fix: Handle librespot `Seeked` events With librespot 0.5 the `PlayerEvent` behavior for track seeking seems to have changed slightly and there is now a dedicated event. This broke seeking in tracks. With this change the dedicated event is processed and track position changes should be picked up again. --- src/spotify_worker.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/spotify_worker.rs b/src/spotify_worker.rs index 8caab167..929473d4 100644 --- a/src/spotify_worker.rs +++ b/src/spotify_worker.rs @@ -32,6 +32,12 @@ pub(crate) enum WorkerCommand { Shutdown, } +enum PlayerStatus { + Playing, + Paused, + Stopped, +} + pub struct Worker { events: EventManager, player_events: UnboundedReceiverStream, @@ -39,7 +45,7 @@ pub struct Worker { session: Session, player: Arc, token_task: Pin + Send>>, - active: bool, + player_status: PlayerStatus, mixer: Arc, } @@ -59,7 +65,7 @@ impl Worker { player, session, token_task: Box::pin(futures::future::pending()), - active: false, + player_status: PlayerStatus::Stopped, mixer, } } @@ -142,7 +148,7 @@ impl Worker { let playback_start = SystemTime::now() - position; self.events .send(Event::Player(PlayerEvent::Playing(playback_start))); - self.active = true; + self.player_status = PlayerStatus::Playing; } Some(LibrespotPlayerEvent::Paused { play_request_id: _, @@ -152,11 +158,11 @@ impl Worker { let position = Duration::from_millis(position_ms as u64); self.events .send(Event::Player(PlayerEvent::Paused(position))); - self.active = false; + self.player_status = PlayerStatus::Paused; } Some(LibrespotPlayerEvent::Stopped { .. }) => { self.events.send(Event::Player(PlayerEvent::Stopped)); - self.active = false; + self.player_status = PlayerStatus::Stopped; } Some(LibrespotPlayerEvent::EndOfTrack { .. }) => { self.events.send(Event::Player(PlayerEvent::FinishedTrack)); @@ -165,15 +171,29 @@ impl Worker { self.events .send(Event::Queue(QueueEvent::PreloadTrackRequest)); } + Some(LibrespotPlayerEvent::Seeked { play_request_id: _, track_id: _, position_ms}) => { + let position = Duration::from_millis(position_ms as u64); + let event = match self.player_status { + PlayerStatus::Playing => { + let playback_start = SystemTime::now() - position; + PlayerEvent::Playing(playback_start) + }, + PlayerStatus::Paused => PlayerEvent::Paused(position), + PlayerStatus::Stopped => PlayerEvent::Stopped, + }; + self.events.send(Event::Player(event)); + } + Some(event) => { + debug!("Unhandled player event: {event:?}"); + } None => { warn!("Librespot player event channel died, terminating worker"); break }, - _ => {} }, // Update animated parts of the UI (e.g. statusbar during playback). _ = ui_refresh.tick() => { - if self.active { + if !matches!(self.player_status, PlayerStatus::Stopped) { self.events.trigger(); } },