From 14709b9f8deeba75f7de808dc3421f962a1a49c9 Mon Sep 17 00:00:00 2001 From: ashthespy Date: Wed, 13 May 2020 11:49:26 +0200 Subject: [PATCH] Let spirc handle unavailable tracks --- connect/src/spirc.rs | 80 ++++++++++++++++++++++++++++-------------- playback/src/player.rs | 43 +++++++---------------- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index 06bf37fc..76ce456e 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -621,26 +621,8 @@ impl SpircTask { self.play_status = SpircPlayStatus::Stopped; } }, - PlayerEvent::TimeToPreloadNextTrack { preload_index, .. } => { - match self.play_status { - SpircPlayStatus::Paused { - ref mut preloading_of_next_track_triggered, - .. - } - | SpircPlayStatus::Playing { - ref mut preloading_of_next_track_triggered, - .. - } => { - *preloading_of_next_track_triggered = true; - if let Some(track_id) = self.preview_next_track(preload_index) { - self.player.preload(track_id); - } - } - SpircPlayStatus::LoadingPause { .. } - | SpircPlayStatus::LoadingPlay { .. } - | SpircPlayStatus::Stopped => (), - } - } + PlayerEvent::TimeToPreloadNextTrack { .. } => self.handle_preload_next_track(), + PlayerEvent::Unavailable { track_id, .. } => self.handle_unavalable(track_id), _ => (), } } @@ -780,7 +762,7 @@ impl SpircTask { { if preloading_of_next_track_triggered { // Get the next track_id in the playlist - if let Some(track_id) = self.preview_next_track(1) { + if let Some(track_id) = self.preview_next_track() { self.player.preload(track_id); } } @@ -902,12 +884,44 @@ impl SpircTask { } } - fn preview_next_track(&mut self, preview_index: u32) -> Option { - trace!("Previewing {:}", preview_index); - self.get_track_id_to_play_from_playlist( - self.state.get_playing_track_index() + preview_index, - ) - .and_then(|(track_id, _)| Some(track_id)) + fn preview_next_track(&mut self) -> Option { + self.get_track_id_to_play_from_playlist(self.state.get_playing_track_index() + 1) + .and_then(|(track_id, _)| Some(track_id)) + } + + fn handle_preload_next_track(&mut self) { + // Requests the player thread to preload the next track + match self.play_status { + SpircPlayStatus::Paused { + ref mut preloading_of_next_track_triggered, + .. + } + | SpircPlayStatus::Playing { + ref mut preloading_of_next_track_triggered, + .. + } => { + *preloading_of_next_track_triggered = true; + if let Some(track_id) = self.preview_next_track() { + self.player.preload(track_id); + } + } + SpircPlayStatus::LoadingPause { .. } + | SpircPlayStatus::LoadingPlay { .. } + | SpircPlayStatus::Stopped => (), + } + } + + fn handle_unavalable(&mut self, track_id: SpotifyId) { + let unavalable_index = self.get_track_index_for_spotify_id( + &track_id, + self.state.get_playing_track_index() as usize, + ); + if let Some(index) = unavalable_index { + // TODO: Or mark it as NonPlayable? + debug!("Removing unavailable track_ref at {:?}", index); + self.state.mut_track().remove(index); + } + self.handle_preload_next_track(); } fn handle_next(&mut self) { @@ -1141,6 +1155,18 @@ impl SpircTask { }) } + fn get_track_index_for_spotify_id( + &self, + track_id: &SpotifyId, + start_index: usize, + ) -> Option { + let index = self.state.get_track()[start_index..] + .iter() + .position(|track_ref| self.get_spotify_id_for_track(track_ref) == Ok(*track_id)); + + index + } + fn get_track_id_to_play_from_playlist(&self, index: u32) -> Option<(SpotifyId, u32)> { let tracks_len = self.state.get_track().len() as u32; diff --git a/playback/src/player.rs b/playback/src/player.rs index 4ea50419..ef576073 100644 --- a/playback/src/player.rs +++ b/playback/src/player.rs @@ -99,7 +99,10 @@ pub enum PlayerEvent { TimeToPreloadNextTrack { play_request_id: u64, track_id: SpotifyId, - preload_index: u32, + }, + Unavailable { + play_request_id: u64, + track_id: SpotifyId, }, EndOfTrack { play_request_id: u64, @@ -117,6 +120,9 @@ impl PlayerEvent { Loading { play_request_id, .. } + | Unavailable { + play_request_id, .. + } | Started { play_request_id, .. } @@ -321,10 +327,6 @@ enum PlayerPreload { Loading { track_id: SpotifyId, loader: Box>, - preload_index: u32, - }, - Missing { - preload_index: u32, }, Ready { track_id: SpotifyId, @@ -742,9 +744,7 @@ impl Future for PlayerInternal { } Ok(Async::NotReady) => (), Err(_) => { - warn!("Unable to load <{:?}>", track_id); - warn!("Skipping to next track"); - trace!("State: {:?}", self.state); + warn!("Unable to load <{:?}>\nSkipping to next track", track_id); assert!(self.state.is_loading()); self.send_event(PlayerEvent::EndOfTrack { track_id, @@ -758,7 +758,6 @@ impl Future for PlayerInternal { if let PlayerPreload::Loading { ref mut loader, track_id, - preload_index, } = self.preload { match loader.poll() { @@ -770,9 +769,9 @@ impl Future for PlayerInternal { } Ok(Async::NotReady) => (), Err(_) => { - warn!("Unable to preload {:?}[{}]", track_id, preload_index,); - // Preemptively fetch next track? - self.preload = PlayerPreload::Missing { preload_index }; + debug!("Unable to preload {:?}", track_id); + self.preload = PlayerPreload::None; + // Let Spirc know that the track was unavailable. if let PlayerState::Playing { play_request_id, .. } @@ -780,14 +779,9 @@ impl Future for PlayerInternal { play_request_id, .. } = self.state { - debug!( - "Requesting track_id for preload_index: {}", - preload_index + 1 - ); - self.send_event(PlayerEvent::TimeToPreloadNextTrack { + self.send_event(PlayerEvent::Unavailable { track_id, play_request_id, - preload_index: preload_index + 1, }); } } @@ -877,7 +871,6 @@ impl Future for PlayerInternal { self.send_event(PlayerEvent::TimeToPreloadNextTrack { track_id, play_request_id, - preload_index: 1, }); } } @@ -1319,12 +1312,6 @@ impl PlayerInternal { fn handle_command_preload(&mut self, track_id: SpotifyId) { debug!("Preloading track"); let mut preload_track = true; - let preload_index = match self.preload { - PlayerPreload::Loading { preload_index, .. } => preload_index, - // The last preload was missing, so increment it - PlayerPreload::Missing { preload_index, .. } => preload_index + 1, - _ => 1, - }; // check whether the track is already loaded somewhere or being loaded. if let PlayerPreload::Loading { track_id: currently_loading, @@ -1366,11 +1353,7 @@ impl PlayerInternal { // schedule the preload if the current track if desired. if preload_track { let loader = self.load_track(track_id, 0); - self.preload = PlayerPreload::Loading { - track_id, - loader, - preload_index, - } + self.preload = PlayerPreload::Loading { track_id, loader } } }