Browse Source

Let spirc handle unavailable tracks

ashthespy 4 years ago
parent
commit
14709b9f8d
2 changed files with 66 additions and 57 deletions
  1. 53 27
      connect/src/spirc.rs
  2. 13 30
      playback/src/player.rs

+ 53 - 27
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<SpotifyId> {
-        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<SpotifyId> {
+        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<usize> {
+        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;
 

+ 13 - 30
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<dyn Future<Item = PlayerLoadedTrackData, Error = ()>>,
-        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 }
         }
     }