Improved next/prev handling for queued tracks.

1) A queued track is removed once it has become the current track.
   Note that the track doesn't need to actually play i.e. it could
   have been immediately skipped over with 'next()'. This is
   implemented in 'consume_queue()'.

2) Queued tracks are always positioned immediately after the current
   track. 1) ensures this is true for 'next()' but 'prev()' requires
   all the queued tracks are actually moved for this to remain the
   case.

Also fixed the case where 'prev()' on the first track would incorrectly
wrap back around to the last track even when repeat was disabled. The
correct behaviour is to remain on the first track and just seek to the
start.

For example, with the following tracks and repeat enabled:

TrackA, TrackB, TrackC-Q, TrackD-Q, TrackE
        ^^^^^^

Here, the result of 'prev' changes the current track from TrackB to
TrackA and the queued tracks (TrackC, TrackD) move to the position
immediately after TrackA:

TrackA, TrackC-Q, TrackD-Q, TrackB, TrackE
^^^^^^

Calling 'prev' again results in the current track wrapping back around
to TrackE and the queued tracks moving after that same track:

TrackA, TrackB, TrackE, TrackC-Q, TrackD-Q
                ^^^^^^
This commit is contained in:
Nick Steel 2018-02-01 00:02:12 +00:00
parent 977a6db3ef
commit b9b8e110df

View file

@ -514,35 +514,66 @@ impl SpircTask {
} }
} }
fn handle_next(&mut self) { fn consume_queue(&mut self) -> bool {
let current_index = self.state.get_playing_track_index(); let current_index = self.state.get_playing_track_index() as usize;
let num_tracks = self.state.get_track().len() as u32; if self.state.get_track()[current_index].get_queued() {
let new_index = (current_index + 1) % num_tracks; self.state.mut_track().remove(current_index);
return true
let mut was_last_track = (current_index + 1) >= num_tracks; }
if self.state.get_repeat() { false
was_last_track = false;
} }
fn handle_next(&mut self) {
let current_index = self.state.get_playing_track_index();
let mut new_index = if self.consume_queue() {
current_index
} else {
current_index + 1
};
let mut continue_playing = true;
if new_index >= self.state.get_track().len() as u32 {
new_index = 0; // Loop around back to start
continue_playing = self.state.get_repeat();
}
self.state.set_playing_track_index(new_index); self.state.set_playing_track_index(new_index);
self.state.set_position_ms(0); self.state.set_position_ms(0);
self.state.set_position_measured_at(now_ms() as u64); self.state.set_position_measured_at(now_ms() as u64);
self.load_track(!was_last_track); self.load_track(continue_playing);
} }
fn handle_prev(&mut self) { fn handle_prev(&mut self) {
// Previous behaves differently based on the position // Previous behaves differently based on the position
// Under 3s it goes to the previous song // Under 3s it goes to the previous song (starts playing)
// Over 3s it seeks to zero // Over 3s it seeks to zero (retains previous play status)
if self.position() < 3000 { if self.position() < 3000 {
let current_index = self.state.get_playing_track_index(); let current_index = self.state.get_playing_track_index() as usize;
let mut q_tracks = Vec::new();
let new_index = if current_index == 0 { {
self.state.get_track().len() as u32 - 1 // Extract any queued tracks.
let q_index = if self.consume_queue() {
current_index
} else { } else {
current_index - 1 current_index + 1
}; };
let tracks = self.state.mut_track();
while q_index < tracks.len() && tracks[q_index].get_queued() {
q_tracks.push(tracks.remove(q_index));
}
}
let new_index = if current_index > 0 {
current_index - 1
} else if self.state.get_repeat() {
self.state.get_track().len() - 1
} else {
0
} as u32;
// Reposition queued tracks to be next.
let mut pos = (new_index + 1) as usize;
for track in q_tracks.into_iter() {
self.state.mut_track().insert(pos, track);
pos += 1;
}
self.state.set_playing_track_index(new_index); self.state.set_playing_track_index(new_index);
self.state.set_position_ms(0); self.state.set_position_ms(0);