mirror of
https://github.com/librespot-org/librespot.git
synced 2024-11-08 16:45:43 +00:00
Support playing multiple tracks in a row
This commit is contained in:
parent
506f3e624e
commit
1d76658fdf
2 changed files with 39 additions and 15 deletions
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
src/spirc.rs
43
src/spirc.rs
|
@ -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,8 +111,15 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update_time = updates.recv() => {
|
update_time = updates.recv() => {
|
||||||
self.state_update_id = update_time.unwrap();
|
let end_of_track = self.delegate.state().end_of_track();
|
||||||
self.notify(None);
|
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();
|
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,
|
||||||
|
|
Loading…
Reference in a new issue