Let spirc handle unavailable tracks

This commit is contained in:
ashthespy 2020-05-13 11:49:26 +02:00
parent 902440925d
commit 14709b9f8d
2 changed files with 66 additions and 57 deletions

View file

@ -621,26 +621,8 @@ impl SpircTask {
self.play_status = SpircPlayStatus::Stopped; self.play_status = SpircPlayStatus::Stopped;
} }
}, },
PlayerEvent::TimeToPreloadNextTrack { preload_index, .. } => { PlayerEvent::TimeToPreloadNextTrack { .. } => self.handle_preload_next_track(),
match self.play_status { PlayerEvent::Unavailable { track_id, .. } => self.handle_unavalable(track_id),
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 => (),
}
}
_ => (), _ => (),
} }
} }
@ -780,7 +762,7 @@ impl SpircTask {
{ {
if preloading_of_next_track_triggered { if preloading_of_next_track_triggered {
// Get the next track_id in the playlist // 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); self.player.preload(track_id);
} }
} }
@ -902,12 +884,44 @@ impl SpircTask {
} }
} }
fn preview_next_track(&mut self, preview_index: u32) -> Option<SpotifyId> { fn preview_next_track(&mut self) -> Option<SpotifyId> {
trace!("Previewing {:}", preview_index); self.get_track_id_to_play_from_playlist(self.state.get_playing_track_index() + 1)
self.get_track_id_to_play_from_playlist( .and_then(|(track_id, _)| Some(track_id))
self.state.get_playing_track_index() + preview_index, }
)
.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) { 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)> { fn get_track_id_to_play_from_playlist(&self, index: u32) -> Option<(SpotifyId, u32)> {
let tracks_len = self.state.get_track().len() as u32; let tracks_len = self.state.get_track().len() as u32;

View file

@ -99,7 +99,10 @@ pub enum PlayerEvent {
TimeToPreloadNextTrack { TimeToPreloadNextTrack {
play_request_id: u64, play_request_id: u64,
track_id: SpotifyId, track_id: SpotifyId,
preload_index: u32, },
Unavailable {
play_request_id: u64,
track_id: SpotifyId,
}, },
EndOfTrack { EndOfTrack {
play_request_id: u64, play_request_id: u64,
@ -117,6 +120,9 @@ impl PlayerEvent {
Loading { Loading {
play_request_id, .. play_request_id, ..
} }
| Unavailable {
play_request_id, ..
}
| Started { | Started {
play_request_id, .. play_request_id, ..
} }
@ -321,10 +327,6 @@ enum PlayerPreload {
Loading { Loading {
track_id: SpotifyId, track_id: SpotifyId,
loader: Box<dyn Future<Item = PlayerLoadedTrackData, Error = ()>>, loader: Box<dyn Future<Item = PlayerLoadedTrackData, Error = ()>>,
preload_index: u32,
},
Missing {
preload_index: u32,
}, },
Ready { Ready {
track_id: SpotifyId, track_id: SpotifyId,
@ -742,9 +744,7 @@ impl Future for PlayerInternal {
} }
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
Err(_) => { Err(_) => {
warn!("Unable to load <{:?}>", track_id); warn!("Unable to load <{:?}>\nSkipping to next track", track_id);
warn!("Skipping to next track");
trace!("State: {:?}", self.state);
assert!(self.state.is_loading()); assert!(self.state.is_loading());
self.send_event(PlayerEvent::EndOfTrack { self.send_event(PlayerEvent::EndOfTrack {
track_id, track_id,
@ -758,7 +758,6 @@ impl Future for PlayerInternal {
if let PlayerPreload::Loading { if let PlayerPreload::Loading {
ref mut loader, ref mut loader,
track_id, track_id,
preload_index,
} = self.preload } = self.preload
{ {
match loader.poll() { match loader.poll() {
@ -770,9 +769,9 @@ impl Future for PlayerInternal {
} }
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
Err(_) => { Err(_) => {
warn!("Unable to preload {:?}[{}]", track_id, preload_index,); debug!("Unable to preload {:?}", track_id);
// Preemptively fetch next track? self.preload = PlayerPreload::None;
self.preload = PlayerPreload::Missing { preload_index }; // Let Spirc know that the track was unavailable.
if let PlayerState::Playing { if let PlayerState::Playing {
play_request_id, .. play_request_id, ..
} }
@ -780,14 +779,9 @@ impl Future for PlayerInternal {
play_request_id, .. play_request_id, ..
} = self.state } = self.state
{ {
debug!( self.send_event(PlayerEvent::Unavailable {
"Requesting track_id for preload_index: {}",
preload_index + 1
);
self.send_event(PlayerEvent::TimeToPreloadNextTrack {
track_id, track_id,
play_request_id, play_request_id,
preload_index: preload_index + 1,
}); });
} }
} }
@ -877,7 +871,6 @@ impl Future for PlayerInternal {
self.send_event(PlayerEvent::TimeToPreloadNextTrack { self.send_event(PlayerEvent::TimeToPreloadNextTrack {
track_id, track_id,
play_request_id, play_request_id,
preload_index: 1,
}); });
} }
} }
@ -1319,12 +1312,6 @@ impl PlayerInternal {
fn handle_command_preload(&mut self, track_id: SpotifyId) { fn handle_command_preload(&mut self, track_id: SpotifyId) {
debug!("Preloading track"); debug!("Preloading track");
let mut preload_track = true; 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. // check whether the track is already loaded somewhere or being loaded.
if let PlayerPreload::Loading { if let PlayerPreload::Loading {
track_id: currently_loading, track_id: currently_loading,
@ -1366,11 +1353,7 @@ impl PlayerInternal {
// schedule the preload if the current track if desired. // schedule the preload if the current track if desired.
if preload_track { if preload_track {
let loader = self.load_track(track_id, 0); let loader = self.load_track(track_id, 0);
self.preload = PlayerPreload::Loading { self.preload = PlayerPreload::Loading { track_id, loader }
track_id,
loader,
preload_index,
}
} }
} }