diff --git a/src/events.rs b/src/events.rs index 6e6f95c..652e3e5 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,10 +1,12 @@ use crossbeam_channel::{unbounded, Receiver, Sender, TryIter}; use cursive::{CbSink, Cursive}; +use crate::queue::QueueEvent; use crate::spotify::PlayerEvent; pub enum Event { Player(PlayerEvent), + Queue(QueueEvent), SessionDied, } diff --git a/src/main.rs b/src/main.rs index cdae2a2..602f2df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -328,6 +328,9 @@ fn main() { queue.next(false); } } + Event::Queue(event) => { + queue.handle_event(event); + } Event::SessionDied => spotify.start_worker(None), } } diff --git a/src/queue.rs b/src/queue.rs index 837679f..a9f24ce 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -21,6 +21,11 @@ pub enum RepeatSetting { RepeatTrack, } +#[derive(Clone, Debug, PartialEq)] +pub enum QueueEvent { + PreloadTrackRequest, +} + pub struct Queue { pub queue: Arc>>, random_order: RwLock>>, @@ -383,6 +388,18 @@ impl Queue { } } + pub fn handle_event(&self, event: QueueEvent) { + match event { + QueueEvent::PreloadTrackRequest => { + if let Some(next_index) = self.next_index() { + let track = self.queue.read().unwrap()[next_index].clone(); + debug!("Preloading track {} as requested by librespot", track); + self.spotify.preload(&track); + } + } + } + } + pub fn get_spotify(&self) -> Spotify { self.spotify.clone() } diff --git a/src/spotify.rs b/src/spotify.rs index fe43f0b..96750ea 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -842,6 +842,10 @@ impl Spotify { self.send_worker(WorkerCommand::SetVolume(Self::log_scale(volume))); } + pub fn preload(&self, track: &Playable) { + self.send_worker(WorkerCommand::Preload(track.clone())); + } + pub fn shutdown(&self) { self.send_worker(WorkerCommand::Shutdown); } diff --git a/src/spotify_worker.rs b/src/spotify_worker.rs index 2e3d44c..8e556e2 100644 --- a/src/spotify_worker.rs +++ b/src/spotify_worker.rs @@ -1,5 +1,6 @@ use crate::events::{Event, EventManager}; use crate::playable::Playable; +use crate::queue::QueueEvent; use crate::spotify::{PlayerEvent, Spotify}; use futures::channel::{mpsc, oneshot}; use futures::compat::Stream01CompatExt; @@ -25,6 +26,7 @@ pub(crate) enum WorkerCommand { Seek(u32), SetVolume(u16), RequestToken(oneshot::Sender), + Preload(Playable), Shutdown, } @@ -126,6 +128,12 @@ impl futures::Future for Worker { self.token_task = Spotify::get_token(&self.session, sender); progress = true; } + WorkerCommand::Preload(playable) => { + if let Ok(id) = SpotifyId::from_uri(&playable.uri()) { + debug!("Preloading {:?}", id); + self.player.preload(id); + } + } WorkerCommand::Shutdown => { self.player.stop(); self.session.shutdown(); @@ -173,6 +181,10 @@ impl futures::Future for Worker { self.events.send(Event::Player(PlayerEvent::FinishedTrack)); progress = true; } + LibrespotPlayerEvent::TimeToPreloadNextTrack { .. } => { + self.events + .send(Event::Queue(QueueEvent::PreloadTrackRequest)); + } _ => {} } }