Remove the SpircDelegate abstraction

This commit is contained in:
Paul Lietar 2016-01-20 14:11:49 +00:00
parent 303121032d
commit 463ce97661
2 changed files with 74 additions and 101 deletions

View file

@ -8,7 +8,7 @@ use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session}; use session::{Bitrate, Session};
use audio_decrypt::AudioDecrypt; use audio_decrypt::AudioDecrypt;
use util::{self, SpotifyId, Subfile}; use util::{self, SpotifyId, Subfile};
use spirc::{SpircState, SpircDelegate, PlayStatus}; use spirc::PlayStatus;
pub struct Player { pub struct Player {
state: Arc<(Mutex<PlayerState>, Condvar)>, state: Arc<(Mutex<PlayerState>, Condvar)>,
@ -72,6 +72,54 @@ impl Player {
fn command(&self, cmd: PlayerCommand) { fn command(&self, cmd: PlayerCommand) {
self.commands.send(cmd).unwrap(); self.commands.send(cmd).unwrap();
} }
pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
self.command(PlayerCommand::Load(track, start_playing, position_ms));
}
pub fn play(&self) {
self.command(PlayerCommand::Play)
}
pub fn pause(&self) {
self.command(PlayerCommand::Pause)
}
pub fn stop(&self) {
self.command(PlayerCommand::Stop)
}
pub fn seek(&self, position_ms: u32) {
self.command(PlayerCommand::Seek(position_ms));
}
pub fn state(&self) -> MutexGuard<PlayerState> {
self.state.0.lock().unwrap()
}
pub fn volume(&self, vol: u16) {
self.command(PlayerCommand::Volume(vol));
}
pub fn updates(&self) -> mpsc::Receiver<i64> {
let state = self.state.clone();
let (update_tx, update_rx) = mpsc::channel();
thread::spawn(move || {
let mut guard = state.0.lock().unwrap();
let mut last_update;
loop {
last_update = guard.update_time;
update_tx.send(guard.update_time).unwrap();
while last_update >= guard.update_time {
guard = state.1.wait(guard).unwrap();
}
}
});
update_rx
}
} }
impl PlayerInternal { impl PlayerInternal {
@ -268,76 +316,24 @@ impl PlayerInternal {
} }
} }
impl SpircDelegate for Player { impl PlayerState {
type State = PlayerState; pub fn status(&self) -> PlayStatus {
fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
self.command(PlayerCommand::Load(track, start_playing, position_ms));
}
fn play(&self) {
self.command(PlayerCommand::Play)
}
fn pause(&self) {
self.command(PlayerCommand::Pause)
}
fn stop(&self) {
self.command(PlayerCommand::Stop)
}
fn seek(&self, position_ms: u32) {
self.command(PlayerCommand::Seek(position_ms));
}
fn state(&self) -> MutexGuard<Self::State> {
self.state.0.lock().unwrap()
}
fn volume(&self, vol: u16) {
self.command(PlayerCommand::Volume(vol));
}
fn updates(&self) -> mpsc::Receiver<i64> {
let state = self.state.clone();
let (update_tx, update_rx) = mpsc::channel();
thread::spawn(move || {
let mut guard = state.0.lock().unwrap();
let mut last_update;
loop {
last_update = guard.update_time;
update_tx.send(guard.update_time).unwrap();
while last_update >= guard.update_time {
guard = state.1.wait(guard).unwrap();
}
}
});
update_rx
}
}
impl SpircState for PlayerState {
fn status(&self) -> PlayStatus {
self.status self.status
} }
fn position(&self) -> (u32, i64) { pub fn position(&self) -> (u32, i64) {
(self.position_ms, self.position_measured_at) (self.position_ms, self.position_measured_at)
} }
fn volume(&self) -> u16 { pub fn volume(&self) -> u16 {
self.volume self.volume
} }
fn update_time(&self) -> i64 { pub fn update_time(&self) -> i64 {
self.update_time self.update_time
} }
fn end_of_track(&self) -> bool { pub fn end_of_track(&self) -> bool {
self.end_of_track self.end_of_track
} }
} }

View file

@ -1,18 +1,18 @@
use eventual::Async; use eventual::Async;
use protobuf::{self, Message}; use protobuf::{self, Message};
use std::sync::{mpsc, MutexGuard};
use util; use util;
use session::Session; use session::Session;
use util::SpotifyId; use util::SpotifyId;
use util::version::version_string; use util::version::version_string;
use mercury::{MercuryRequest, MercuryMethod}; use mercury::{MercuryRequest, MercuryMethod};
use player::Player;
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use librespot_protocol::spirc::PlayStatus; pub use librespot_protocol::spirc::PlayStatus;
pub struct SpircManager<D: SpircDelegate> { pub struct SpircManager {
delegate: D, player: Player,
session: Session, session: Session,
state_update_id: i64, state_update_id: i64,
@ -36,36 +36,13 @@ pub struct SpircManager<D: SpircDelegate> {
index: u32, index: u32,
} }
pub trait SpircDelegate { impl SpircManager {
type State : SpircState; pub fn new(session: Session, player: Player) -> SpircManager {
fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32);
fn play(&self);
fn pause(&self);
fn seek(&self, position_ms: u32);
fn volume(&self, vol: u16);
fn stop(&self);
fn state(&self) -> MutexGuard<Self::State>;
fn updates(&self) -> mpsc::Receiver<i64>;
}
pub trait SpircState {
fn status(&self) -> PlayStatus;
fn position(&self) -> (u32, i64);
fn update_time(&self) -> i64;
fn end_of_track(&self) -> bool;
fn volume(&self) -> u16;
}
impl<D: SpircDelegate> SpircManager<D> {
pub fn new(session: Session, delegate: D) -> SpircManager<D> {
let ident = session.0.data.read().unwrap().device_id.clone(); let ident = session.0.data.read().unwrap().device_id.clone();
let name = session.0.config.device_name.clone(); let name = session.0.config.device_name.clone();
SpircManager { SpircManager {
delegate: delegate, player: player,
session: session, session: session,
state_update_id: 0, state_update_id: 0,
@ -99,7 +76,7 @@ impl<D: SpircDelegate> SpircManager<D> {
.unwrap() .unwrap()
.canonical_username .canonical_username
.clone())); .clone()));
let updates = self.delegate.updates(); let updates = self.player.updates();
self.notify(true, None); self.notify(true, None);
@ -122,11 +99,11 @@ impl<D: SpircDelegate> SpircManager<D> {
} }
}, },
update_time = updates.recv() => { update_time = updates.recv() => {
let end_of_track = self.delegate.state().end_of_track(); let end_of_track = self.player.state().end_of_track();
if end_of_track { if end_of_track {
self.index = (self.index + 1) % self.tracks.len() as u32; self.index = (self.index + 1) % self.tracks.len() as u32;
let track = self.tracks[self.index as usize]; let track = self.tracks[self.index as usize];
self.delegate.load(track, true, 0); self.player.load(track, true, 0);
} else { } else {
self.state_update_id = update_time.unwrap(); self.state_update_id = update_time.unwrap();
self.notify(false, None); self.notify(false, None);
@ -156,26 +133,26 @@ impl<D: SpircDelegate> SpircManager<D> {
let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay; let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
let track = self.tracks[self.index as usize]; let track = self.tracks[self.index as usize];
let position = frame.get_state().get_position_ms(); let position = frame.get_state().get_position_ms();
self.delegate.load(track, play, position); self.player.load(track, play, position);
} }
protocol::spirc::MessageType::kMessageTypePlay => { protocol::spirc::MessageType::kMessageTypePlay => {
self.delegate.play(); self.player.play();
} }
protocol::spirc::MessageType::kMessageTypePause => { protocol::spirc::MessageType::kMessageTypePause => {
self.delegate.pause(); self.player.pause();
} }
protocol::spirc::MessageType::kMessageTypeNext => { protocol::spirc::MessageType::kMessageTypeNext => {
self.index = (self.index + 1) % self.tracks.len() as u32; self.index = (self.index + 1) % self.tracks.len() as u32;
let track = self.tracks[self.index as usize]; let track = self.tracks[self.index as usize];
self.delegate.load(track, true, 0); self.player.load(track, true, 0);
} }
protocol::spirc::MessageType::kMessageTypePrev => { protocol::spirc::MessageType::kMessageTypePrev => {
self.index = (self.index - 1) % self.tracks.len() as u32; self.index = (self.index - 1) % self.tracks.len() as u32;
let track = self.tracks[self.index as usize]; let track = self.tracks[self.index as usize];
self.delegate.load(track, true, 0); self.player.load(track, true, 0);
} }
protocol::spirc::MessageType::kMessageTypeSeek => { protocol::spirc::MessageType::kMessageTypeSeek => {
self.delegate.seek(frame.get_position()); self.player.seek(frame.get_position());
} }
protocol::spirc::MessageType::kMessageTypeReplace => { protocol::spirc::MessageType::kMessageTypeReplace => {
self.reload_tracks(&frame); self.reload_tracks(&frame);
@ -183,11 +160,11 @@ impl<D: SpircDelegate> SpircManager<D> {
protocol::spirc::MessageType::kMessageTypeNotify => { protocol::spirc::MessageType::kMessageTypeNotify => {
if self.is_active && frame.get_device_state().get_is_active() { if self.is_active && frame.get_device_state().get_is_active() {
self.is_active = false; self.is_active = false;
self.delegate.stop(); self.player.stop();
} }
} }
protocol::spirc::MessageType::kMessageTypeVolume => { protocol::spirc::MessageType::kMessageTypeVolume => {
self.delegate.volume(frame.get_volume() as u16); self.player.volume(frame.get_volume() as u16);
} }
_ => (), _ => (),
} }
@ -238,7 +215,7 @@ impl<D: SpircDelegate> SpircManager<D> {
} }
fn spirc_state(&self) -> protocol::spirc::State { fn spirc_state(&self) -> protocol::spirc::State {
let state = self.delegate.state(); let state = self.player.state();
let (position_ms, position_measured_at) = state.position(); let (position_ms, position_measured_at) = state.position();
protobuf_init!(protocol::spirc::State::new(), { protobuf_init!(protocol::spirc::State::new(), {
@ -268,7 +245,7 @@ impl<D: SpircDelegate> SpircManager<D> {
sw_version: version_string(), sw_version: version_string(),
is_active: self.is_active, is_active: self.is_active,
can_play: self.can_play, can_play: self.can_play,
volume: self.delegate.state().volume() as u32, volume: self.player.state().volume() as u32,
name: self.name.clone(), name: self.name.clone(),
error_code: 0, error_code: 0,
became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 }, became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },