mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Fix panic when retrying a track that already failed
This commit is contained in:
parent
ab67370dc8
commit
e627cb4b35
1 changed files with 34 additions and 27 deletions
|
@ -14,7 +14,10 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use futures_util::{future, stream::futures_unordered::FuturesUnordered, StreamExt, TryFutureExt};
|
use futures_util::{
|
||||||
|
future, future::FusedFuture, stream::futures_unordered::FuturesUnordered, StreamExt,
|
||||||
|
TryFutureExt,
|
||||||
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use symphonia::core::io::MediaSource;
|
use symphonia::core::io::MediaSource;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
@ -499,7 +502,7 @@ enum PlayerPreload {
|
||||||
None,
|
None,
|
||||||
Loading {
|
Loading {
|
||||||
track_id: SpotifyId,
|
track_id: SpotifyId,
|
||||||
loader: Pin<Box<dyn Future<Output = Result<PlayerLoadedTrackData, ()>> + Send>>,
|
loader: Pin<Box<dyn FusedFuture<Output = Result<PlayerLoadedTrackData, ()>> + Send>>,
|
||||||
},
|
},
|
||||||
Ready {
|
Ready {
|
||||||
track_id: SpotifyId,
|
track_id: SpotifyId,
|
||||||
|
@ -515,7 +518,7 @@ enum PlayerState {
|
||||||
track_id: SpotifyId,
|
track_id: SpotifyId,
|
||||||
play_request_id: u64,
|
play_request_id: u64,
|
||||||
start_playback: bool,
|
start_playback: bool,
|
||||||
loader: Pin<Box<dyn Future<Output = Result<PlayerLoadedTrackData, ()>> + Send>>,
|
loader: Pin<Box<dyn FusedFuture<Output = Result<PlayerLoadedTrackData, ()>> + Send>>,
|
||||||
},
|
},
|
||||||
Paused {
|
Paused {
|
||||||
track_id: SpotifyId,
|
track_id: SpotifyId,
|
||||||
|
@ -571,6 +574,7 @@ impl PlayerState {
|
||||||
matches!(self, Stopped)
|
matches!(self, Stopped)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
fn is_loading(&self) -> bool {
|
fn is_loading(&self) -> bool {
|
||||||
use self::PlayerState::*;
|
use self::PlayerState::*;
|
||||||
matches!(self, Loading { .. })
|
matches!(self, Loading { .. })
|
||||||
|
@ -1026,6 +1030,9 @@ impl Future for PlayerInternal {
|
||||||
play_request_id,
|
play_request_id,
|
||||||
} = self.state
|
} = self.state
|
||||||
{
|
{
|
||||||
|
// The loader may be terminated if we are trying to load the same track
|
||||||
|
// as before, and that track failed to open before.
|
||||||
|
if !loader.as_mut().is_terminated() {
|
||||||
match loader.as_mut().poll(cx) {
|
match loader.as_mut().poll(cx) {
|
||||||
Poll::Ready(Ok(loaded_track)) => {
|
Poll::Ready(Ok(loaded_track)) => {
|
||||||
self.start_playback(
|
self.start_playback(
|
||||||
|
@ -1044,7 +1051,6 @@ impl Future for PlayerInternal {
|
||||||
"Skipping to next track, unable to load track <{:?}>: {:?}",
|
"Skipping to next track, unable to load track <{:?}>: {:?}",
|
||||||
track_id, e
|
track_id, e
|
||||||
);
|
);
|
||||||
debug_assert!(self.state.is_loading());
|
|
||||||
self.send_event(PlayerEvent::Unavailable {
|
self.send_event(PlayerEvent::Unavailable {
|
||||||
track_id,
|
track_id,
|
||||||
play_request_id,
|
play_request_id,
|
||||||
|
@ -1053,6 +1059,7 @@ impl Future for PlayerInternal {
|
||||||
Poll::Pending => (),
|
Poll::Pending => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handle pending preload requests.
|
// handle pending preload requests.
|
||||||
if let PlayerPreload::Loading {
|
if let PlayerPreload::Loading {
|
||||||
|
@ -2000,7 +2007,7 @@ impl PlayerInternal {
|
||||||
&mut self,
|
&mut self,
|
||||||
spotify_id: SpotifyId,
|
spotify_id: SpotifyId,
|
||||||
position_ms: u32,
|
position_ms: u32,
|
||||||
) -> impl Future<Output = Result<PlayerLoadedTrackData, ()>> + Send + 'static {
|
) -> impl FusedFuture<Output = Result<PlayerLoadedTrackData, ()>> + Send + 'static {
|
||||||
// This method creates a future that returns the loaded stream and associated info.
|
// This method creates a future that returns the loaded stream and associated info.
|
||||||
// Ideally all work should be done using asynchronous code. However, seek() on the
|
// Ideally all work should be done using asynchronous code. However, seek() on the
|
||||||
// audio stream is implemented in a blocking fashion. Thus, we can't turn it into future
|
// audio stream is implemented in a blocking fashion. Thus, we can't turn it into future
|
||||||
|
|
Loading…
Reference in a new issue