Autoplay similar songs when your music ends

This commit is contained in:
ashthespy 2019-03-24 16:42:00 +01:00
parent 4a04e48f8a
commit ba2639d1df

View file

@ -41,6 +41,7 @@ pub struct SpircTask {
shutdown: bool, shutdown: bool,
session: Session, session: Session,
context_fut: Box<Future<Item = serde_json::Value, Error = MercuryError>>, context_fut: Box<Future<Item = serde_json::Value, Error = MercuryError>>,
autoplay_fut: Box<Future<Item = String, Error = MercuryError>>,
context: Option<StationContext>, context: Option<StationContext>,
} }
@ -268,6 +269,7 @@ impl Spirc {
session: session.clone(), session: session.clone(),
context_fut: Box::new(future::empty()), context_fut: Box::new(future::empty()),
autoplay_fut: Box::new(future::empty()),
context: None, context: None,
}; };
@ -345,7 +347,7 @@ impl Future for SpircTask {
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
Err(oneshot::Canceled) => self.end_of_track = Box::new(future::empty()), Err(oneshot::Canceled) => self.end_of_track = Box::new(future::empty()),
} }
// TODO: Refactor
match self.context_fut.poll() { match self.context_fut.poll() {
Ok(Async::Ready(value)) => { Ok(Async::Ready(value)) => {
let r_context = serde_json::from_value::<StationContext>(value.clone()); let r_context = serde_json::from_value::<StationContext>(value.clone());
@ -378,6 +380,20 @@ impl Future for SpircTask {
error!("ContextError: {:?}", err) error!("ContextError: {:?}", err)
} }
} }
match self.autoplay_fut.poll() {
Ok(Async::Ready(autoplay_station_uri)) => {
info!("Autoplay resolved to <{:?}>", autoplay_station_uri);
self.context_fut = self.resolve_station(&autoplay_station_uri);
progress = true;
self.autoplay_fut = Box::new(future::empty());
}
Ok(Async::NotReady) => (),
Err(err) => {
self.autoplay_fut = Box::new(future::empty());
error!("AutoplayError: {:?}", err)
}
}
} }
let poll_sender = self.sender.poll_complete().unwrap(); let poll_sender = self.sender.poll_complete().unwrap();
@ -657,12 +673,13 @@ impl SpircTask {
fn handle_next(&mut self) { fn handle_next(&mut self) {
let mut new_index = self.consume_queued_track() as u32; let mut new_index = self.consume_queued_track() as u32;
let mut continue_playing = true; let mut continue_playing = true;
let tracks_len = self.state.get_track().len() as u32;
debug!( debug!(
"At track {:?} of {:?} <{:?}> update [{}]", "At track {:?} of {:?} <{:?}> update [{}]",
new_index, new_index,
self.state.get_track().len(), self.state.get_track().len(),
self.state.get_context_uri(), self.state.get_context_uri(),
self.state.get_track().len() as u32 - new_index < CONTEXT_FETCH_THRESHOLD tracks_len - new_index < CONTEXT_FETCH_THRESHOLD
); );
let context_uri = self.state.get_context_uri().to_owned(); let context_uri = self.state.get_context_uri().to_owned();
if (context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:")) if (context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:"))
@ -671,8 +688,14 @@ impl SpircTask {
self.context_fut = self.resolve_station(&context_uri); self.context_fut = self.resolve_station(&context_uri);
self.update_tracks_from_context(); self.update_tracks_from_context();
} }
if new_index == tracks_len - 1 {
if new_index >= self.state.get_track().len() as u32 { // Extend the playlist
// Note: This doesn't seem to reflect in the UI
// the additional tracks in the frame don't show up as with stations
info!("Extending playlist <{}>", context_uri);
self.update_tracks_from_context();
}
if new_index >= tracks_len {
new_index = 0; // Loop around back to start new_index = 0; // Loop around back to start
continue_playing = self.state.get_repeat(); continue_playing = self.state.get_repeat();
} }
@ -761,6 +784,17 @@ impl SpircTask {
self.resolve_uri(&radio_uri) self.resolve_uri(&radio_uri)
} }
fn resolve_autoplay_uri(&self, uri: &str) -> Box<Future<Item = String, Error = MercuryError>> {
let query_uri = format!("hm://autoplay-enabled/query?uri={}", uri);
let request = self.session.mercury().get(query_uri);
Box::new(request.and_then(move |response| {
let data = response.payload.first().expect("Empty autoplay uri").to_vec();
let autoplay_uri = String::from_utf8(data).unwrap();
Ok(autoplay_uri)
}))
}
fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> { fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
let request = self.session.mercury().get(uri); let request = self.session.mercury().get(uri);
@ -793,6 +827,8 @@ impl SpircTask {
{ {
self.state.set_playing_track_index(new_index); self.state.set_playing_track_index(new_index);
} }
} else {
warn!("No context to update from!");
} }
} }
@ -804,6 +840,9 @@ impl SpircTask {
debug!("Frame has {:?} tracks", tracks.len()); debug!("Frame has {:?} tracks", tracks.len());
if context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:") { if context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:") {
self.context_fut = self.resolve_station(&context_uri); self.context_fut = self.resolve_station(&context_uri);
} else {
// Get autoplay_station_uri for regular playlists
self.autoplay_fut = self.resolve_autoplay_uri(&context_uri);
} }
self.state.set_playing_track_index(index); self.state.set_playing_track_index(index);