Implement track preloading

Will preload the next track close to the end of the currently playing
track. Should make playback of queued tracks a little smoother.
This commit is contained in:
Henrik Friedrichsen
2021-04-11 15:51:19 +02:00
parent decf7c2aef
commit 98e572169b
5 changed files with 38 additions and 0 deletions

View File

@@ -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,
}

View File

@@ -328,6 +328,9 @@ fn main() {
queue.next(false);
}
}
Event::Queue(event) => {
queue.handle_event(event);
}
Event::SessionDied => spotify.start_worker(None),
}
}

View File

@@ -21,6 +21,11 @@ pub enum RepeatSetting {
RepeatTrack,
}
#[derive(Clone, Debug, PartialEq)]
pub enum QueueEvent {
PreloadTrackRequest,
}
pub struct Queue {
pub queue: Arc<RwLock<Vec<Playable>>>,
random_order: RwLock<Option<Vec<usize>>>,
@@ -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()
}

View File

@@ -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);
}

View File

@@ -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<Token>),
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));
}
_ => {}
}
}