Support playing multiple tracks in a row

This commit is contained in:
Paul Lietar 2015-07-09 23:09:40 +01:00
parent 506f3e624e
commit 1d76658fdf
2 changed files with 39 additions and 15 deletions

View file

@ -22,7 +22,9 @@ pub struct PlayerState {
status: PlayStatus, status: PlayStatus,
position_ms: u32, position_ms: u32,
position_measured_at: i64, position_measured_at: i64,
update_time: i64 update_time: i64,
end_of_track: bool
} }
struct PlayerInternal<'s> { struct PlayerInternal<'s> {
@ -49,6 +51,7 @@ impl <'s> Player<'s> {
position_ms: 0, position_ms: 0,
position_measured_at: 0, position_measured_at: 0,
update_time: util::now_ms(), update_time: util::now_ms(),
end_of_track: false,
}), Condvar::new())); }), Condvar::new()));
let internal = PlayerInternal { let internal = PlayerInternal {
@ -90,6 +93,7 @@ impl <'s> PlayerInternal<'s> {
if state.status == PlayStatus::kPlayStatusPlay { if state.status == PlayStatus::kPlayStatusPlay {
stream.stop().unwrap(); stream.stop().unwrap();
} }
state.end_of_track = false;
state.status = PlayStatus::kPlayStatusLoading; state.status = PlayStatus::kPlayStatusLoading;
state.position_ms = position; state.position_ms = position;
state.position_measured_at = util::now_ms(); state.position_measured_at = util::now_ms();
@ -174,6 +178,7 @@ impl <'s> PlayerInternal<'s> {
None => { None => {
self.update(|state| { self.update(|state| {
state.status = PlayStatus::kPlayStatusStop; state.status = PlayStatus::kPlayStatusStop;
state.end_of_track = true;
return true; return true;
}); });
@ -273,5 +278,9 @@ impl SpircState for PlayerState {
fn update_time(&self) -> i64 { fn update_time(&self) -> i64 {
return self.update_time; return self.update_time;
} }
fn end_of_track(&self) -> bool {
return self.end_of_track;
}
} }

View file

@ -33,7 +33,8 @@ pub struct SpircManager<'s, D: SpircDelegate> {
last_command_ident: String, last_command_ident: String,
last_command_msgid: u32, last_command_msgid: u32,
track: Option<SpotifyId> tracks: Vec<SpotifyId>,
index: u32
} }
pub trait SpircDelegate { pub trait SpircDelegate {
@ -54,6 +55,7 @@ pub trait SpircState {
fn status(&self) -> PlayStatus; fn status(&self) -> PlayStatus;
fn position(&self) -> (u32, i64); fn position(&self) -> (u32, i64);
fn update_time(&self) -> i64; fn update_time(&self) -> i64;
fn end_of_track(&self) -> bool;
} }
impl <'s, D: SpircDelegate> SpircManager<'s, D> { 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_ident: String::new(),
last_command_msgid: 0, last_command_msgid: 0,
track: None tracks: Vec::new(),
index: 0
} }
} }
@ -108,12 +111,19 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
} }
}, },
update_time = updates.recv() => { update_time = updates.recv() => {
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.state_update_id = update_time.unwrap();
self.notify(None); self.notify(None);
} }
} }
} }
} }
}
fn handle(&mut self, frame: protocol::spirc::Frame) { fn handle(&mut self, frame: protocol::spirc::Frame) {
if frame.get_recipient().len() > 0 { if frame.get_recipient().len() > 0 {
@ -130,11 +140,16 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
self.became_active_at = util::now_ms(); 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; let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
self.track = Some(track); let track = self.tracks[self.index as usize];
self.delegate.load(track, play, frame.get_state().get_position_ms()); let position = frame.get_state().get_position_ms();
self.delegate.load(track, play, position);
} }
protocol::spirc::MessageType::kMessageTypePlay => { protocol::spirc::MessageType::kMessageTypePlay => {
self.delegate.play(); self.delegate.play();
@ -190,12 +205,12 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
position_ms: position_ms, position_ms: position_ms,
position_measured_at: position_measured_at as u64, position_measured_at: position_measured_at as u64,
playing_track_index: 0, playing_track_index: self.index,
track => [ track: self.tracks.iter().map(|track| {
@{ protobuf_init!(protocol::spirc::TrackRef::new(), {
gid: self.track.unwrap().to_raw().to_vec() gid: track.to_raw().to_vec()
} })
], }).collect(),
shuffle: self.shuffle, shuffle: self.shuffle,
repeat: self.repeat, repeat: self.repeat,