From 1d76658fdf397c79157811314b0cdf393c17121f Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Thu, 9 Jul 2015 23:09:40 +0100 Subject: [PATCH] Support playing multiple tracks in a row --- src/player.rs | 11 ++++++++++- src/spirc.rs | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/player.rs b/src/player.rs index d55eae0e..b3766c5c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -22,7 +22,9 @@ pub struct PlayerState { status: PlayStatus, position_ms: u32, position_measured_at: i64, - update_time: i64 + update_time: i64, + + end_of_track: bool } struct PlayerInternal<'s> { @@ -49,6 +51,7 @@ impl <'s> Player<'s> { position_ms: 0, position_measured_at: 0, update_time: util::now_ms(), + end_of_track: false, }), Condvar::new())); let internal = PlayerInternal { @@ -90,6 +93,7 @@ impl <'s> PlayerInternal<'s> { if state.status == PlayStatus::kPlayStatusPlay { stream.stop().unwrap(); } + state.end_of_track = false; state.status = PlayStatus::kPlayStatusLoading; state.position_ms = position; state.position_measured_at = util::now_ms(); @@ -174,6 +178,7 @@ impl <'s> PlayerInternal<'s> { None => { self.update(|state| { state.status = PlayStatus::kPlayStatusStop; + state.end_of_track = true; return true; }); @@ -273,5 +278,9 @@ impl SpircState for PlayerState { fn update_time(&self) -> i64 { return self.update_time; } + + fn end_of_track(&self) -> bool { + return self.end_of_track; + } } diff --git a/src/spirc.rs b/src/spirc.rs index 17256bc6..6f6db7a0 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -33,7 +33,8 @@ pub struct SpircManager<'s, D: SpircDelegate> { last_command_ident: String, last_command_msgid: u32, - track: Option + tracks: Vec, + index: u32 } pub trait SpircDelegate { @@ -54,6 +55,7 @@ pub trait SpircState { fn status(&self) -> PlayStatus; fn position(&self) -> (u32, i64); fn update_time(&self) -> i64; + fn end_of_track(&self) -> bool; } impl <'s, D: SpircDelegate> SpircManager<'s, D> { @@ -82,7 +84,8 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> { last_command_ident: String::new(), last_command_msgid: 0, - track: None + tracks: Vec::new(), + index: 0 } } @@ -108,8 +111,15 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> { } }, update_time = updates.recv() => { - self.state_update_id = update_time.unwrap(); - self.notify(None); + let end_of_track = self.delegate.state().end_of_track(); + if end_of_track { + self.index = (self.index + 1) % self.tracks.len() as u32; + let track = self.tracks[self.index as usize]; + self.delegate.load(track, true, 0); + } else { + self.state_update_id = update_time.unwrap(); + self.notify(None); + } } } } @@ -130,11 +140,16 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> { self.became_active_at = util::now_ms(); } - let index = frame.get_state().get_playing_track_index() as usize; - let track = SpotifyId::from_raw(frame.get_state().get_track()[index].get_gid()); + + self.index = frame.get_state().get_playing_track_index(); + self.tracks = frame.get_state().get_track().iter() + .map(|track| SpotifyId::from_raw(track.get_gid())) + .collect(); + let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay; - self.track = Some(track); - self.delegate.load(track, play, frame.get_state().get_position_ms()); + let track = self.tracks[self.index as usize]; + let position = frame.get_state().get_position_ms(); + self.delegate.load(track, play, position); } protocol::spirc::MessageType::kMessageTypePlay => { self.delegate.play(); @@ -190,12 +205,12 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> { position_ms: position_ms, position_measured_at: position_measured_at as u64, - playing_track_index: 0, - track => [ - @{ - gid: self.track.unwrap().to_raw().to_vec() - } - ], + playing_track_index: self.index, + track: self.tracks.iter().map(|track| { + protobuf_init!(protocol::spirc::TrackRef::new(), { + gid: track.to_raw().to_vec() + }) + }).collect(), shuffle: self.shuffle, repeat: self.repeat,