Add support for replacing tracks. Make a builder out of send_cmd.

This commit is contained in:
Simon Persson 2016-02-17 15:24:40 +01:00
parent 08cb429a0c
commit 5e3404137f

View file

@ -1,5 +1,5 @@
use eventual::Async; use eventual::Async;
use protobuf::{self, Message}; use protobuf::{self, Message, RepeatedField};
use util; use util;
use session::Session; use session::Session;
@ -116,34 +116,54 @@ impl SpircManager {
pub fn send_play(&mut self, recipient: &str) { pub fn send_play(&mut self, recipient: &str) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
send_cmd(&mut *internal, CommandSender::new(&mut *internal,
protocol::spirc::MessageType::kMessageTypePlay, protocol::spirc::MessageType::kMessageTypePlay)
Some(recipient), .recipient(recipient)
None); .send();
} }
pub fn send_pause(&mut self, recipient: &str) { pub fn send_pause(&mut self, recipient: &str) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
send_cmd(&mut *internal, CommandSender::new(&mut *internal,
protocol::spirc::MessageType::kMessageTypePause, protocol::spirc::MessageType::kMessageTypePause)
Some(recipient), .recipient(recipient)
None); .send();
} }
pub fn send_prev(&mut self, recipient: &str) { pub fn send_prev(&mut self, recipient: &str) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
send_cmd(&mut *internal, CommandSender::new(&mut *internal,
protocol::spirc::MessageType::kMessageTypePrev, protocol::spirc::MessageType::kMessageTypePrev)
Some(recipient), .recipient(recipient)
None); .send();
} }
pub fn send_next(&mut self, recipient: &str) { pub fn send_next(&mut self, recipient: &str) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
send_cmd(&mut *internal, CommandSender::new(&mut *internal,
protocol::spirc::MessageType::kMessageTypeNext, protocol::spirc::MessageType::kMessageTypeNext)
Some(recipient), .recipient(recipient)
None); .send();
}
pub fn send_replace_tracks<S: AsRef<str>, I: Iterator<Item = S>>(&mut self,
recipient: &str,
track_ids: I) {
let tracks: Vec<protocol::spirc::TrackRef> = track_ids.map(|i| {
protobuf_init!(protocol::spirc::TrackRef::new(), { gid: SpotifyId::from_base62(i.as_ref()).to_raw().to_vec()})
})
.collect();
let state = protobuf_init!(protocol::spirc::State::new(), {
track: RepeatedField::from_vec(tracks)
});
let mut internal = self.0.lock().unwrap();
CommandSender::new(&mut *internal,
protocol::spirc::MessageType::kMessageTypeReplace)
.recipient(recipient)
.state(state)
.send();
} }
} }
@ -241,28 +261,37 @@ impl SpircInternal {
} }
fn notify(&mut self, hello: bool, recipient: Option<&str>) { fn notify(&mut self, hello: bool, recipient: Option<&str>) {
send_cmd(self, let cs = CommandSender::new(self,
if hello { if hello {
MessageType::kMessageTypeHello MessageType::kMessageTypeHello
} else { } else {
MessageType::kMessageTypeNotify MessageType::kMessageTypeNotify
}, });
recipient, if let Some(s) = recipient {
None); cs.recipient(&s)
.send()
} else {
cs.send()
}
} }
fn notify_with_player_state(&mut self, fn notify_with_player_state(&mut self,
hello: bool, hello: bool,
recipient: Option<&str>, recipient: Option<&str>,
player_state: &PlayerState) { player_state: &PlayerState) {
send_cmd(self, let cs = CommandSender::new(self,
if hello { if hello {
MessageType::kMessageTypeHello MessageType::kMessageTypeHello
} else { } else {
MessageType::kMessageTypeNotify MessageType::kMessageTypeNotify
}, })
recipient, .player_state(player_state);
Some(player_state)); if let Some(s) = recipient {
cs.recipient(&s)
.send()
} else {
cs.send()
}
} }
fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State { fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State {
@ -355,42 +384,81 @@ impl SpircInternal {
} }
} }
fn send_cmd(spirc_internal: &mut SpircInternal, struct CommandSender<'a> {
cmd: protocol::spirc::MessageType, spirc_internal: &'a mut SpircInternal,
recipient: Option<&str>, cmd: protocol::spirc::MessageType,
player_state: Option<&PlayerState>) { recipient: Option<&'a str>,
let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { player_state: Option<&'a PlayerState>,
version: 1, state: Option<protocol::spirc::State>,
ident: spirc_internal.ident.clone(), }
protocol_version: "2.0.0".to_owned(),
seq_nr: { spirc_internal.seq_nr += 1; spirc_internal.seq_nr },
typ: cmd,
recipient: protobuf::RepeatedField::from_vec(
recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
),
});
if let Some(s) = player_state { impl<'a> CommandSender<'a> {
pkt.set_device_state(spirc_internal.device_state(s)); fn new(spirc_internal: &'a mut SpircInternal,
pkt.set_state_update_id(s.update_time() as i64); cmd: protocol::spirc::MessageType)
if spirc_internal.is_active { -> CommandSender {
pkt.set_state(spirc_internal.spirc_state(s)); CommandSender {
} spirc_internal: spirc_internal,
} else { cmd: cmd,
let s = &*spirc_internal.player.state(); recipient: None,
pkt.set_device_state(spirc_internal.device_state(s)); player_state: None,
pkt.set_state_update_id(s.update_time() as i64); state: None,
if spirc_internal.is_active {
pkt.set_state(spirc_internal.spirc_state(s));
} }
} }
spirc_internal.session fn recipient(mut self, r: &'a str) -> CommandSender {
.mercury(MercuryRequest { self.recipient = Some(r);
method: MercuryMethod::SEND, self
uri: spirc_internal.uri(), }
content_type: None,
payload: vec![pkt.write_to_bytes().unwrap()], fn player_state(mut self, s: &'a PlayerState) -> CommandSender {
}) self.player_state = Some(s);
.fire(); self
}
fn state(mut self, s: protocol::spirc::State) -> CommandSender<'a> {
self.state = Some(s);
self
}
fn send(self) {
let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
version: 1,
ident: self.spirc_internal.ident.clone(),
protocol_version: "2.0.0".to_owned(),
seq_nr: { self.spirc_internal.seq_nr += 1; self.spirc_internal.seq_nr },
typ: self.cmd,
recipient: protobuf::RepeatedField::from_vec(
self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
),
});
if let Some(s) = self.player_state {
pkt.set_device_state(self.spirc_internal.device_state(s));
pkt.set_state_update_id(s.update_time() as i64);
if self.spirc_internal.is_active {
pkt.set_state(self.spirc_internal.spirc_state(s));
}
} else {
let s = &*self.spirc_internal.player.state();
pkt.set_device_state(self.spirc_internal.device_state(s));
pkt.set_state_update_id(s.update_time() as i64);
if self.spirc_internal.is_active {
pkt.set_state(self.spirc_internal.spirc_state(s));
}
}
if let Some(s) = self.state {
pkt.set_state(s);
}
self.spirc_internal
.session
.mercury(MercuryRequest {
method: MercuryMethod::SEND,
uri: self.spirc_internal.uri(),
content_type: None,
payload: vec![pkt.write_to_bytes().unwrap()],
})
.fire();
}
} }