From 958d0c74d4ee590a7d3484a65b15da2736944869 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Sat, 13 Feb 2016 02:09:15 +0100 Subject: [PATCH 1/9] Maintain list of connected devices. --- src/spirc.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/spirc.rs b/src/spirc.rs index 887f277..121164d 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -9,6 +9,7 @@ use mercury::{MercuryRequest, MercuryMethod}; use player::{Player, PlayerState}; use std::sync::{Mutex, Arc}; +use std::collections::HashMap; use protocol; pub use protocol::spirc::PlayStatus; @@ -37,6 +38,8 @@ struct SpircInternal { tracks: Vec, index: u32, + + devices: HashMap, } impl SpircManager { @@ -66,6 +69,8 @@ impl SpircManager { tracks: Vec::new(), index: 0, + + devices: HashMap::new(), }))) } @@ -118,7 +123,7 @@ impl SpircInternal { } } - fn handle(&mut self, frame: protocol::spirc::Frame) { + fn handle(&mut self, mut frame: protocol::spirc::Frame) { if frame.get_ident() == self.ident || (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) { return; @@ -128,6 +133,11 @@ impl SpircInternal { self.last_command_ident = frame.get_ident().to_owned(); self.last_command_msgid = frame.get_seq_nr(); } + + if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() { + self.devices.insert(frame.take_ident(), frame.take_device_state().take_name()); + } + match frame.get_typ() { protocol::spirc::MessageType::kMessageTypeHello => { self.notify(false, Some(frame.get_ident())); @@ -172,6 +182,10 @@ impl SpircInternal { self.is_active = false; self.player.stop(); } + + if frame.has_ident() && frame.has_goodbye() { + self.devices.remove(&frame.take_ident()); + } } protocol::spirc::MessageType::kMessageTypeVolume => { self.player.volume(frame.get_volume() as u16); From 5a19d382708adc76b4395d9ae3676f607da1a9d8 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Tue, 16 Feb 2016 22:25:55 +0100 Subject: [PATCH 2/9] Refactor notify/notify_with_player_state. --- src/spirc.rs | 123 ++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 66 deletions(-) diff --git a/src/spirc.rs b/src/spirc.rs index 121164d..4e54be8 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -12,7 +12,7 @@ use std::sync::{Mutex, Arc}; use std::collections::HashMap; use protocol; -pub use protocol::spirc::PlayStatus; +pub use protocol::spirc::{PlayStatus, MessageType}; pub struct SpircManager(Arc>); @@ -204,78 +204,29 @@ impl SpircInternal { .collect(); } - // FIXME: this entire function is duplicated in notify_with_player_state, but the borrow - // checker makes it hard to refactor fn notify(&mut self, hello: bool, recipient: Option<&str>) { - let player_state = self.player.state(); - - let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { - version: 1, - ident: self.ident.clone(), - protocol_version: "2.0.0".to_owned(), - seq_nr: { self.seq_nr += 1; self.seq_nr }, - typ: if hello { - protocol::spirc::MessageType::kMessageTypeHello - } else { - protocol::spirc::MessageType::kMessageTypeNotify - }, - - device_state: self.device_state(&player_state), - recipient: protobuf::RepeatedField::from_vec( - recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![]) - ), - state_update_id: player_state.update_time() as i64 - }); - - if self.is_active { - pkt.set_state(self.spirc_state(&player_state)); - } - - self.session - .mercury(MercuryRequest { - method: MercuryMethod::SEND, - uri: self.uri(), - content_type: None, - payload: vec![pkt.write_to_bytes().unwrap()], - }) - .await() - .unwrap(); + send_cmd(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }, + recipient, + None); } fn notify_with_player_state(&mut self, hello: bool, recipient: Option<&str>, player_state: &PlayerState) { - let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { - version: 1, - ident: self.ident.clone(), - protocol_version: "2.0.0".to_owned(), - seq_nr: { self.seq_nr += 1; self.seq_nr }, - typ: if hello { - protocol::spirc::MessageType::kMessageTypeHello - } else { - protocol::spirc::MessageType::kMessageTypeNotify - }, - - device_state: self.device_state(&player_state), - recipient: protobuf::RepeatedField::from_vec( - recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![]) - ), - state_update_id: player_state.update_time() as i64 - }); - - if self.is_active { - pkt.set_state(self.spirc_state(&player_state)); - } - - self.session - .mercury(MercuryRequest { - method: MercuryMethod::SEND, - uri: self.uri(), - content_type: None, - payload: vec![pkt.write_to_bytes().unwrap()], - }) - .fire(); + send_cmd(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }, + recipient, + Some(player_state)); } fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State { @@ -367,3 +318,43 @@ impl SpircInternal { format!("hm://remote/user/{}", self.session.username()) } } + +fn send_cmd(spirc_internal: &mut SpircInternal, + cmd: protocol::spirc::MessageType, + recipient: Option<&str>, + player_state: Option<&PlayerState>) { + let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { + version: 1, + 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 { + pkt.set_device_state(spirc_internal.device_state(s)); + pkt.set_state_update_id(s.update_time() as i64); + if spirc_internal.is_active { + pkt.set_state(spirc_internal.spirc_state(s)); + } + } else { + let s = &*spirc_internal.player.state(); + pkt.set_device_state(spirc_internal.device_state(s)); + pkt.set_state_update_id(s.update_time() as i64); + if spirc_internal.is_active { + pkt.set_state(spirc_internal.spirc_state(s)); + } + } + + spirc_internal.session + .mercury(MercuryRequest { + method: MercuryMethod::SEND, + uri: spirc_internal.uri(), + content_type: None, + payload: vec![pkt.write_to_bytes().unwrap()], + }) + .fire(); +} From 677173d01b2acde2b29ed9d0e35d0b4d3eec7566 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Tue, 16 Feb 2016 22:26:51 +0100 Subject: [PATCH 3/9] Export devices. --- src/spirc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/spirc.rs b/src/spirc.rs index 4e54be8..723853f 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -109,6 +109,10 @@ impl SpircManager { self.0.lock().unwrap().handle(frame); } } + + pub fn devices(&self) -> HashMap { + self.0.lock().unwrap().devices.clone() + } } impl SpircInternal { From 08cb429a0c4b84008b1e605b9d17017194504ff5 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Tue, 16 Feb 2016 22:52:55 +0100 Subject: [PATCH 4/9] Add functions for sending commands to other clients. --- src/spirc.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/spirc.rs b/src/spirc.rs index 723853f..5c3a873 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -113,6 +113,38 @@ impl SpircManager { pub fn devices(&self) -> HashMap { self.0.lock().unwrap().devices.clone() } + + pub fn send_play(&mut self, recipient: &str) { + let mut internal = self.0.lock().unwrap(); + send_cmd(&mut *internal, + protocol::spirc::MessageType::kMessageTypePlay, + Some(recipient), + None); + } + + pub fn send_pause(&mut self, recipient: &str) { + let mut internal = self.0.lock().unwrap(); + send_cmd(&mut *internal, + protocol::spirc::MessageType::kMessageTypePause, + Some(recipient), + None); + } + + pub fn send_prev(&mut self, recipient: &str) { + let mut internal = self.0.lock().unwrap(); + send_cmd(&mut *internal, + protocol::spirc::MessageType::kMessageTypePrev, + Some(recipient), + None); + } + + pub fn send_next(&mut self, recipient: &str) { + let mut internal = self.0.lock().unwrap(); + send_cmd(&mut *internal, + protocol::spirc::MessageType::kMessageTypeNext, + Some(recipient), + None); + } } impl SpircInternal { From 5e3404137f223feecf0ecdcfcb91048fb4402dc4 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Wed, 17 Feb 2016 15:24:40 +0100 Subject: [PATCH 5/9] Add support for replacing tracks. Make a builder out of send_cmd. --- src/spirc.rs | 202 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 135 insertions(+), 67 deletions(-) diff --git a/src/spirc.rs b/src/spirc.rs index 5c3a873..28831c2 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -1,5 +1,5 @@ use eventual::Async; -use protobuf::{self, Message}; +use protobuf::{self, Message, RepeatedField}; use util; use session::Session; @@ -116,34 +116,54 @@ impl SpircManager { pub fn send_play(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - send_cmd(&mut *internal, - protocol::spirc::MessageType::kMessageTypePlay, - Some(recipient), - None); + CommandSender::new(&mut *internal, + protocol::spirc::MessageType::kMessageTypePlay) + .recipient(recipient) + .send(); } pub fn send_pause(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - send_cmd(&mut *internal, - protocol::spirc::MessageType::kMessageTypePause, - Some(recipient), - None); + CommandSender::new(&mut *internal, + protocol::spirc::MessageType::kMessageTypePause) + .recipient(recipient) + .send(); } pub fn send_prev(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - send_cmd(&mut *internal, - protocol::spirc::MessageType::kMessageTypePrev, - Some(recipient), - None); + CommandSender::new(&mut *internal, + protocol::spirc::MessageType::kMessageTypePrev) + .recipient(recipient) + .send(); } pub fn send_next(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - send_cmd(&mut *internal, - protocol::spirc::MessageType::kMessageTypeNext, - Some(recipient), - None); + CommandSender::new(&mut *internal, + protocol::spirc::MessageType::kMessageTypeNext) + .recipient(recipient) + .send(); + } + + pub fn send_replace_tracks, I: Iterator>(&mut self, + recipient: &str, + track_ids: I) { + let tracks: Vec = 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>) { - send_cmd(self, - if hello { - MessageType::kMessageTypeHello - } else { - MessageType::kMessageTypeNotify - }, - recipient, - None); + let cs = CommandSender::new(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }); + if let Some(s) = recipient { + cs.recipient(&s) + .send() + } else { + cs.send() + } } fn notify_with_player_state(&mut self, hello: bool, recipient: Option<&str>, player_state: &PlayerState) { - send_cmd(self, - if hello { - MessageType::kMessageTypeHello - } else { - MessageType::kMessageTypeNotify - }, - recipient, - Some(player_state)); + let cs = CommandSender::new(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }) + .player_state(player_state); + if let Some(s) = recipient { + cs.recipient(&s) + .send() + } else { + cs.send() + } } fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State { @@ -355,42 +384,81 @@ impl SpircInternal { } } -fn send_cmd(spirc_internal: &mut SpircInternal, - cmd: protocol::spirc::MessageType, - recipient: Option<&str>, - player_state: Option<&PlayerState>) { - let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { - version: 1, - 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![]) - ), - }); +struct CommandSender<'a> { + spirc_internal: &'a mut SpircInternal, + cmd: protocol::spirc::MessageType, + recipient: Option<&'a str>, + player_state: Option<&'a PlayerState>, + state: Option, +} - if let Some(s) = player_state { - pkt.set_device_state(spirc_internal.device_state(s)); - pkt.set_state_update_id(s.update_time() as i64); - if spirc_internal.is_active { - pkt.set_state(spirc_internal.spirc_state(s)); - } - } else { - let s = &*spirc_internal.player.state(); - pkt.set_device_state(spirc_internal.device_state(s)); - pkt.set_state_update_id(s.update_time() as i64); - if spirc_internal.is_active { - pkt.set_state(spirc_internal.spirc_state(s)); +impl<'a> CommandSender<'a> { + fn new(spirc_internal: &'a mut SpircInternal, + cmd: protocol::spirc::MessageType) + -> CommandSender { + CommandSender { + spirc_internal: spirc_internal, + cmd: cmd, + recipient: None, + player_state: None, + state: None, } } - spirc_internal.session - .mercury(MercuryRequest { - method: MercuryMethod::SEND, - uri: spirc_internal.uri(), - content_type: None, - payload: vec![pkt.write_to_bytes().unwrap()], - }) - .fire(); + fn recipient(mut self, r: &'a str) -> CommandSender { + self.recipient = Some(r); + self + } + + fn player_state(mut self, s: &'a PlayerState) -> CommandSender { + self.player_state = Some(s); + 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(); + } } From 8e0325c2979c8be7b6d37c80cd62b9694506a43d Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Wed, 17 Feb 2016 20:35:31 +0100 Subject: [PATCH 6/9] Add function for sending load comand. --- src/spirc.rs | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/spirc.rs b/src/spirc.rs index 28831c2..16c26a2 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -146,18 +146,10 @@ impl SpircManager { .send(); } - pub fn send_replace_tracks, I: Iterator>(&mut self, - recipient: &str, - track_ids: I) { - let tracks: Vec = 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) - }); - + pub fn send_replace_tracks>(&mut self, + recipient: &str, + track_ids: I) { + let state = track_ids_to_state(track_ids); let mut internal = self.0.lock().unwrap(); CommandSender::new(&mut *internal, protocol::spirc::MessageType::kMessageTypeReplace) @@ -165,6 +157,18 @@ impl SpircManager { .state(state) .send(); } + + pub fn send_load_tracks>(&mut self, + recipient: &str, + track_ids: I) { + let state = track_ids_to_state(track_ids); + let mut internal = self.0.lock().unwrap(); + CommandSender::new(&mut *internal, + protocol::spirc::MessageType::kMessageTypeLoad) + .recipient(recipient) + .state(state) + .send(); + } } impl SpircInternal { @@ -462,3 +466,14 @@ impl<'a> CommandSender<'a> { .fire(); } } + +fn track_ids_to_state>(track_ids: I) -> protocol::spirc::State { + let tracks: Vec = + track_ids.map(|i| { + protobuf_init!(protocol::spirc::TrackRef::new(), { gid: i.to_raw().to_vec()}) + }) + .collect(); + protobuf_init!(protocol::spirc::State::new(), { + track: RepeatedField::from_vec(tracks) + }) +} From 906241b92e987607ebd02f5cae2da9a0652f5f59 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Wed, 17 Feb 2016 20:35:52 +0100 Subject: [PATCH 7/9] Export the current queue. --- src/spirc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/spirc.rs b/src/spirc.rs index 16c26a2..d777947 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -169,6 +169,10 @@ impl SpircManager { .state(state) .send(); } + + pub fn get_queue(&self) -> Vec { + self.0.lock().unwrap().tracks.clone() + } } impl SpircInternal { From c98ff9bd5417ac2c0b1203e06d5d65602452b648 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Wed, 17 Feb 2016 20:47:55 +0100 Subject: [PATCH 8/9] Make SpricManager cloneable to simplify for clients. --- src/spirc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/spirc.rs b/src/spirc.rs index d777947..e630471 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -14,6 +14,7 @@ use std::collections::HashMap; use protocol; pub use protocol::spirc::{PlayStatus, MessageType}; +#[derive(Clone)] pub struct SpircManager(Arc>); struct SpircInternal { From 3ccb2e2a1035192889033b2fe7f5626787798261 Mon Sep 17 00:00:00 2001 From: Simon Persson Date: Fri, 19 Feb 2016 00:02:41 +0100 Subject: [PATCH 9/9] Clean up before merging. --- src/spirc.rs | 122 +++++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 71 deletions(-) diff --git a/src/spirc.rs b/src/spirc.rs index e630471..596d4c3 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -117,32 +117,28 @@ impl SpircManager { pub fn send_play(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypePlay) + CommandSender::new(&mut *internal, MessageType::kMessageTypePlay) .recipient(recipient) .send(); } pub fn send_pause(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypePause) + CommandSender::new(&mut *internal, MessageType::kMessageTypePause) .recipient(recipient) .send(); } pub fn send_prev(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypePrev) + CommandSender::new(&mut *internal, MessageType::kMessageTypePrev) .recipient(recipient) .send(); } pub fn send_next(&mut self, recipient: &str) { let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypeNext) + CommandSender::new(&mut *internal, MessageType::kMessageTypeNext) .recipient(recipient) .send(); } @@ -152,8 +148,7 @@ impl SpircManager { track_ids: I) { let state = track_ids_to_state(track_ids); let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypeReplace) + CommandSender::new(&mut *internal, MessageType::kMessageTypeReplace) .recipient(recipient) .state(state) .send(); @@ -164,8 +159,7 @@ impl SpircManager { track_ids: I) { let state = track_ids_to_state(track_ids); let mut internal = self.0.lock().unwrap(); - CommandSender::new(&mut *internal, - protocol::spirc::MessageType::kMessageTypeLoad) + CommandSender::new(&mut *internal, MessageType::kMessageTypeLoad) .recipient(recipient) .state(state) .send(); @@ -188,7 +182,7 @@ impl SpircInternal { } } - fn handle(&mut self, mut frame: protocol::spirc::Frame) { + fn handle(&mut self, frame: protocol::spirc::Frame) { if frame.get_ident() == self.ident || (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) { return; @@ -200,14 +194,15 @@ impl SpircInternal { } if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() { - self.devices.insert(frame.take_ident(), frame.take_device_state().take_name()); + self.devices.insert(frame.get_ident().into(), + frame.get_device_state().get_name().into()); } match frame.get_typ() { - protocol::spirc::MessageType::kMessageTypeHello => { + MessageType::kMessageTypeHello => { self.notify(false, Some(frame.get_ident())); } - protocol::spirc::MessageType::kMessageTypeLoad => { + MessageType::kMessageTypeLoad => { if !self.is_active { self.is_active = true; self.became_active_at = util::now_ms(); @@ -220,41 +215,42 @@ impl SpircInternal { let position = frame.get_state().get_position_ms(); self.player.load(track, play, position); } - protocol::spirc::MessageType::kMessageTypePlay => { + MessageType::kMessageTypePlay => { self.player.play(); } - protocol::spirc::MessageType::kMessageTypePause => { + MessageType::kMessageTypePause => { self.player.pause(); } - protocol::spirc::MessageType::kMessageTypeNext => { + MessageType::kMessageTypeNext => { self.index = (self.index + 1) % self.tracks.len() as u32; let track = self.tracks[self.index as usize]; self.player.load(track, true, 0); } - protocol::spirc::MessageType::kMessageTypePrev => { + MessageType::kMessageTypePrev => { self.index = (self.index - 1) % self.tracks.len() as u32; let track = self.tracks[self.index as usize]; self.player.load(track, true, 0); } - protocol::spirc::MessageType::kMessageTypeSeek => { + MessageType::kMessageTypeSeek => { self.player.seek(frame.get_position()); } - protocol::spirc::MessageType::kMessageTypeReplace => { + MessageType::kMessageTypeReplace => { self.reload_tracks(&frame); } - protocol::spirc::MessageType::kMessageTypeNotify => { + MessageType::kMessageTypeNotify => { if self.is_active && frame.get_device_state().get_is_active() { self.is_active = false; self.player.stop(); } - - if frame.has_ident() && frame.has_goodbye() { - self.devices.remove(&frame.take_ident()); - } } - protocol::spirc::MessageType::kMessageTypeVolume => { + MessageType::kMessageTypeVolume => { self.player.volume(frame.get_volume() as u16); } + MessageType::kMessageTypeGoodbye => { + if frame.has_ident() { + self.devices.remove(frame.get_ident()); + } + } _ => (), } } @@ -270,37 +266,33 @@ impl SpircInternal { } fn notify(&mut self, hello: bool, recipient: Option<&str>) { - let cs = CommandSender::new(self, - if hello { - MessageType::kMessageTypeHello - } else { - MessageType::kMessageTypeNotify - }); + let mut cs = CommandSender::new(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }); if let Some(s) = recipient { - cs.recipient(&s) - .send() - } else { - cs.send() + cs = cs.recipient(&s); } + cs.send(); } fn notify_with_player_state(&mut self, hello: bool, recipient: Option<&str>, player_state: &PlayerState) { - let cs = CommandSender::new(self, - if hello { - MessageType::kMessageTypeHello - } else { - MessageType::kMessageTypeNotify - }) - .player_state(player_state); + let mut cs = CommandSender::new(self, + if hello { + MessageType::kMessageTypeHello + } else { + MessageType::kMessageTypeNotify + }) + .player_state(player_state); if let Some(s) = recipient { - cs.recipient(&s) - .send() - } else { - cs.send() + cs = cs.recipient(&s); } + cs.send(); } fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State { @@ -395,16 +387,14 @@ impl SpircInternal { struct CommandSender<'a> { spirc_internal: &'a mut SpircInternal, - cmd: protocol::spirc::MessageType, + cmd: MessageType, recipient: Option<&'a str>, player_state: Option<&'a PlayerState>, state: Option, } impl<'a> CommandSender<'a> { - fn new(spirc_internal: &'a mut SpircInternal, - cmd: protocol::spirc::MessageType) - -> CommandSender { + fn new(spirc_internal: &'a mut SpircInternal, cmd: MessageType) -> CommandSender { CommandSender { spirc_internal: spirc_internal, cmd: cmd, @@ -430,34 +420,24 @@ impl<'a> CommandSender<'a> { } fn send(self) { + let internal_player_state = self.spirc_internal.player.state(); + let s = self.player_state.unwrap_or(&*internal_player_state); + 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( + recipient: RepeatedField::from_vec( self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![]) ), + device_state: self.spirc_internal.device_state(s), + state_update_id: s.update_time() as i64, }); - 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); + if self.spirc_internal.is_active { + pkt.set_state(self.spirc_internal.spirc_state(s)); } self.spirc_internal