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:
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -328,6 +328,9 @@ fn main() {
|
||||
queue.next(false);
|
||||
}
|
||||
}
|
||||
Event::Queue(event) => {
|
||||
queue.handle_event(event);
|
||||
}
|
||||
Event::SessionDied => spotify.start_worker(None),
|
||||
}
|
||||
}
|
||||
|
||||
17
src/queue.rs
17
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<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()
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user