|  | @@ -9,7 +9,11 @@ use rand;
 | 
	
		
			
				|  |  |  use rand::seq::SliceRandom;
 | 
	
		
			
				|  |  |  use serde_json;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use context::StationContext;
 | 
	
		
			
				|  |  | +use crate::context::StationContext;
 | 
	
		
			
				|  |  | +use crate::playback::mixer::Mixer;
 | 
	
		
			
				|  |  | +use crate::playback::player::Player;
 | 
	
		
			
				|  |  | +use crate::protocol;
 | 
	
		
			
				|  |  | +use crate::protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
 | 
	
		
			
				|  |  |  use librespot_core::config::ConnectConfig;
 | 
	
		
			
				|  |  |  use librespot_core::mercury::MercuryError;
 | 
	
		
			
				|  |  |  use librespot_core::session::Session;
 | 
	
	
		
			
				|  | @@ -17,14 +21,10 @@ use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
 | 
	
		
			
				|  |  |  use librespot_core::util::SeqGenerator;
 | 
	
		
			
				|  |  |  use librespot_core::version;
 | 
	
		
			
				|  |  |  use librespot_core::volume::Volume;
 | 
	
		
			
				|  |  | -use playback::mixer::Mixer;
 | 
	
		
			
				|  |  | -use playback::player::Player;
 | 
	
		
			
				|  |  | -use protocol;
 | 
	
		
			
				|  |  | -use protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub struct SpircTask {
 | 
	
		
			
				|  |  |      player: Player,
 | 
	
		
			
				|  |  | -    mixer: Box<Mixer>,
 | 
	
		
			
				|  |  | +    mixer: Box<dyn Mixer>,
 | 
	
		
			
				|  |  |      config: SpircTaskConfig,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      sequence: SeqGenerator<u32>,
 | 
	
	
		
			
				|  | @@ -33,15 +33,15 @@ pub struct SpircTask {
 | 
	
		
			
				|  |  |      device: DeviceState,
 | 
	
		
			
				|  |  |      state: State,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    subscription: Box<Stream<Item = Frame, Error = MercuryError>>,
 | 
	
		
			
				|  |  | -    sender: Box<Sink<SinkItem = Frame, SinkError = MercuryError>>,
 | 
	
		
			
				|  |  | +    subscription: Box<dyn Stream<Item = Frame, Error = MercuryError>>,
 | 
	
		
			
				|  |  | +    sender: Box<dyn Sink<SinkItem = Frame, SinkError = MercuryError>>,
 | 
	
		
			
				|  |  |      commands: mpsc::UnboundedReceiver<SpircCommand>,
 | 
	
		
			
				|  |  | -    end_of_track: Box<Future<Item = (), Error = oneshot::Canceled>>,
 | 
	
		
			
				|  |  | +    end_of_track: Box<dyn Future<Item = (), Error = oneshot::Canceled>>,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      shutdown: bool,
 | 
	
		
			
				|  |  |      session: Session,
 | 
	
		
			
				|  |  | -    context_fut: Box<Future<Item = serde_json::Value, Error = MercuryError>>,
 | 
	
		
			
				|  |  | -    autoplay_fut: Box<Future<Item = String, Error = MercuryError>>,
 | 
	
		
			
				|  |  | +    context_fut: Box<dyn Future<Item = serde_json::Value, Error = MercuryError>>,
 | 
	
		
			
				|  |  | +    autoplay_fut: Box<dyn Future<Item = String, Error = MercuryError>>,
 | 
	
		
			
				|  |  |      context: Option<StationContext>,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -221,7 +221,7 @@ impl Spirc {
 | 
	
		
			
				|  |  |          config: ConnectConfig,
 | 
	
		
			
				|  |  |          session: Session,
 | 
	
		
			
				|  |  |          player: Player,
 | 
	
		
			
				|  |  | -        mixer: Box<Mixer>,
 | 
	
		
			
				|  |  | +        mixer: Box<dyn Mixer>,
 | 
	
		
			
				|  |  |      ) -> (Spirc, SpircTask) {
 | 
	
		
			
				|  |  |          debug!("new Spirc[{}]", session.session_id());
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -526,7 +526,8 @@ impl SpircTask {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if self.state.get_track().len() > 0 {
 | 
	
		
			
				|  |  |                      let now = self.now_ms();
 | 
	
		
			
				|  |  | -                    self.state.set_position_ms(frame.get_state().get_position_ms());
 | 
	
		
			
				|  |  | +                    self.state
 | 
	
		
			
				|  |  | +                        .set_position_ms(frame.get_state().get_position_ms());
 | 
	
		
			
				|  |  |                      self.state.set_position_measured_at(now as u64);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
 | 
	
	
		
			
				|  | @@ -689,7 +690,8 @@ impl SpircTask {
 | 
	
		
			
				|  |  |              tracks_len - new_index < CONTEXT_FETCH_THRESHOLD
 | 
	
		
			
				|  |  |          );
 | 
	
		
			
				|  |  |          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:"))
 | 
	
		
			
				|  |  |              && ((self.state.get_track().len() as u32) - new_index) < CONTEXT_FETCH_THRESHOLD
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              self.context_fut = self.resolve_station(&context_uri);
 | 
	
	
		
			
				|  | @@ -785,13 +787,16 @@ impl SpircTask {
 | 
	
		
			
				|  |  |          self.state.get_position_ms() + diff as u32
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn resolve_station(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
 | 
	
		
			
				|  |  | +    fn resolve_station(
 | 
	
		
			
				|  |  | +        &self,
 | 
	
		
			
				|  |  | +        uri: &str,
 | 
	
		
			
				|  |  | +    ) -> Box<dyn Future<Item = serde_json::Value, Error = MercuryError>> {
 | 
	
		
			
				|  |  |          let radio_uri = format!("hm://radio-apollo/v3/stations/{}", uri);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          self.resolve_uri(&radio_uri)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn resolve_autoplay_uri(&self, uri: &str) -> Box<Future<Item = String, Error = MercuryError>> {
 | 
	
		
			
				|  |  | +    fn resolve_autoplay_uri(&self, uri: &str) -> Box<dyn 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| {
 | 
	
	
		
			
				|  | @@ -806,11 +811,14 @@ impl SpircTask {
 | 
	
		
			
				|  |  |          }))
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
 | 
	
		
			
				|  |  | +    fn resolve_uri(&self, uri: &str) -> Box<dyn Future<Item = serde_json::Value, Error = MercuryError>> {
 | 
	
		
			
				|  |  |          let request = self.session.mercury().get(uri);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          Box::new(request.and_then(move |response| {
 | 
	
		
			
				|  |  | -            let data = response.payload.first().expect("Empty payload on context uri");
 | 
	
		
			
				|  |  | +            let data = response
 | 
	
		
			
				|  |  | +                .payload
 | 
	
		
			
				|  |  | +                .first()
 | 
	
		
			
				|  |  | +                .expect("Empty payload on context uri");
 | 
	
		
			
				|  |  |              let response: serde_json::Value = serde_json::from_slice(&data).unwrap();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Ok(response)
 | 
	
	
		
			
				|  | @@ -828,7 +836,8 @@ impl SpircTask {
 | 
	
		
			
				|  |  |                  track_vec.drain(0..head);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              track_vec.extend_from_slice(&new_tracks);
 | 
	
		
			
				|  |  | -            self.state.set_track(protobuf::RepeatedField::from_vec(track_vec));
 | 
	
		
			
				|  |  | +            self.state
 | 
	
		
			
				|  |  | +                .set_track(protobuf::RepeatedField::from_vec(track_vec));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              // Update playing index
 | 
	
		
			
				|  |  |              if let Some(new_index) = self
 | 
	
	
		
			
				|  | @@ -849,7 +858,9 @@ impl SpircTask {
 | 
	
		
			
				|  |  |          let context_uri = frame.get_state().get_context_uri().to_owned();
 | 
	
		
			
				|  |  |          let tracks = frame.get_state().get_track();
 | 
	
		
			
				|  |  |          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);
 | 
	
		
			
				|  |  |          } else if self.config.autoplay {
 | 
	
		
			
				|  |  |              info!("Fetching autoplay context uri");
 |