mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Let spirc handle unavailable tracks
This commit is contained in:
parent
902440925d
commit
14709b9f8d
2 changed files with 66 additions and 57 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue