diff --git a/src/main.rs b/src/main.rs index 038d2cea..defac467 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,8 @@ use librespot::cache::{Cache, DefaultCache, NoCache}; use librespot::player::Player; use librespot::session::{Bitrate, Config, Session}; use librespot::mixer::softmixer::SoftMixer; +use librespot::mixer::Mixer; + use librespot::version; fn usage(program: &str, opts: &getopts::Options) -> String { @@ -60,7 +62,7 @@ fn list_backends() { } } -fn setup(args: &[String]) -> (Session, Player) { +fn setup(args: &[String]) -> (Session, Player, Box) { let mut opts = getopts::Options::new(); opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE") .reqopt("n", "name", "Device name", "NAME") @@ -124,18 +126,18 @@ fn setup(args: &[String]) -> (Session, Player) { let mixer = SoftMixer::new(); let device_name = matches.opt_str("device"); - let player = Player::new(session.clone(), Box::new(mixer), move || { + let player = Player::new(session.clone(), move || { (backend)(device_name.as_ref().map(AsRef::as_ref)) }); - (session, player) + (session, player, Box::new(mixer)) } fn main() { let args: Vec = std::env::args().collect(); - let (session, player) = setup(&args); + let (session, player, mixer) = setup(&args); - let spirc = SpircManager::new(session.clone(), player); + let spirc = SpircManager::new(session.clone(), player, mixer); let spirc_signal = spirc.clone(); thread::spawn(move || spirc.run()); diff --git a/src/mixer/mod.rs b/src/mixer/mod.rs index 27bbdacd..285bde0c 100644 --- a/src/mixer/mod.rs +++ b/src/mixer/mod.rs @@ -6,7 +6,7 @@ pub trait Mixer { fn init(&mut self); fn inuse(&mut self); fn release(&mut self); - fn set(&mut self, volume: u16); + fn set_volume(&mut self, volume: u16); fn volume(&self) -> u16; fn apply_volume<'a>(&mut self, data: &'a [i16]) -> Cow<'a, [i16]> { Cow::Borrowed(data) diff --git a/src/mixer/softmixer.rs b/src/mixer/softmixer.rs index 2dedf67b..8a36fa90 100644 --- a/src/mixer/softmixer.rs +++ b/src/mixer/softmixer.rs @@ -23,7 +23,7 @@ impl Mixer for SoftMixer { fn release(&mut self) { } - fn set(&mut self, volume: u16) { + fn set_volume(&mut self, volume: u16) { self.volume = volume; } diff --git a/src/player.rs b/src/player.rs index 430a38d6..bc38263b 100644 --- a/src/player.rs +++ b/src/player.rs @@ -7,7 +7,6 @@ use vorbis; use audio_decrypt::AudioDecrypt; use audio_backend::Sink; -use mixer::Mixer; use metadata::{FileFormat, Track, TrackRef}; use session::{Bitrate, Session}; use util::{self, ReadSeek, SpotifyId, Subfile}; @@ -48,8 +47,6 @@ pub struct PlayerState { pub status: PlayStatus, pub position_ms: u32, pub position_measured_at: i64, - pub update_time: i64, - pub volume: u16, pub track: Option, pub end_of_track: bool, @@ -68,24 +65,20 @@ enum PlayerCommand { Load(SpotifyId, bool, u32), Play, Pause, - Volume(u16), Stop, Seek(u32), SeekAt(u32, i64), } impl Player { - pub fn new(session: Session, mixer: Box, sink_builder: F) -> Player - where F: FnOnce() -> Box + Send + 'static, - M: Mixer + Send + 'static { + pub fn new(session: Session, sink_builder: F) -> Player + where F: FnOnce() -> Box + Send + 'static { let (cmd_tx, cmd_rx) = mpsc::channel(); let state = Arc::new(Mutex::new(PlayerState { status: PlayStatus::kPlayStatusStop, position_ms: 0, position_measured_at: 0, - update_time: util::now_ms(), - volume: mixer.volume(), track: None, end_of_track: false, })); @@ -99,7 +92,7 @@ impl Player { observers: observers.clone(), }; - thread::spawn(move || internal.run(sink_builder(), mixer)); + thread::spawn(move || internal.run(sink_builder())); Player { commands: cmd_tx, @@ -140,10 +133,6 @@ impl Player { self.state.lock().unwrap().clone() } - pub fn volume(&self, vol: u16) { - self.command(PlayerCommand::Volume(vol)); - } - pub fn add_observer(&self, observer: PlayerObserver) { self.observers.lock().unwrap().push(observer); } @@ -216,7 +205,7 @@ fn run_onstop(session: &Session) { } impl PlayerInternal { - fn run(self, mut sink: Box, mut mixer: Box) { + fn run(self, mut sink: Box) { let mut decoder = None; loop { @@ -321,7 +310,6 @@ impl PlayerInternal { Some(PlayerCommand::Pause) => { self.update(|state| { state.status = PlayStatus::kPlayStatusPause; - state.update_time = util::now_ms(); state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32; state.position_measured_at = util::now_ms(); true @@ -330,13 +318,6 @@ impl PlayerInternal { sink.stop().unwrap(); run_onstop(&self.session); } - Some(PlayerCommand::Volume(vol)) => { - mixer.set(vol); - self.update(|state| { - state.volume = mixer.volume(); - true - }); - } Some(PlayerCommand::Stop) => { self.update(|state| { if state.status == PlayStatus::kPlayStatusPlay { @@ -359,7 +340,8 @@ impl PlayerInternal { match packet { Some(Ok(packet)) => { - let buffer = mixer.apply_volume(&packet.data); + //let buffer = mixer.apply_volume(&packet.data); + let buffer = Cow::Borrowed(&packet.data); sink.write(&buffer).unwrap(); self.update(|state| { @@ -395,7 +377,6 @@ impl PlayerInternal { let observers = self.observers.lock().unwrap(); if update { - guard.update_time = util::now_ms(); let state = guard.clone(); drop(guard); @@ -415,14 +396,6 @@ impl PlayerState { (self.position_ms, self.position_measured_at) } - pub fn volume(&self) -> u16 { - self.volume - } - - pub fn update_time(&self) -> i64 { - self.update_time - } - pub fn end_of_track(&self) -> bool { self.end_of_track } diff --git a/src/spirc.rs b/src/spirc.rs index 674fd47a..6688e834 100644 --- a/src/spirc.rs +++ b/src/spirc.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use mercury::{MercuryRequest, MercuryMethod}; use player::{Player, PlayerState}; +use mixer::Mixer; use session::Session; use util; use util::SpotifyId; @@ -20,6 +21,7 @@ pub struct SpircManager(Arc>); struct SpircInternal { player: Player, session: Session, + mixer: Box, seq_nr: u32, @@ -43,14 +45,26 @@ struct SpircInternal { devices: HashMap, } +#[derive(Clone)] +pub struct State { + pub status: PlayStatus, + pub position_ms: u32, + pub position_measured_at: i64, + pub update_time: i64, + pub volume: u16, + pub track: Option, + pub end_of_track: bool, +} + impl SpircManager { - pub fn new(session: Session, player: Player) -> SpircManager { + pub fn new(session: Session, player: Player, mixer: Box) -> SpircManager { let ident = session.device_id().to_owned(); let name = session.config().device_name.clone(); SpircManager(Arc::new(Mutex::new(SpircInternal { player: player, session: session, + mixer: mixer, seq_nr: 0, @@ -184,7 +198,7 @@ impl SpircInternal { let track = self.tracks[self.index as usize]; self.player.load(track, true, 0); } else { - self.notify_with_player_state(false, None, player_state); + self.notify(false, None); } } @@ -253,7 +267,7 @@ impl SpircInternal { } } MessageType::kMessageTypeVolume => { - self.player.volume(frame.get_volume() as u16); + self.mixer.set_volume(frame.get_volume() as u16); } MessageType::kMessageTypeGoodbye => { if frame.has_ident() { @@ -287,30 +301,11 @@ impl SpircInternal { cs.send(); } - fn notify_with_player_state(&mut self, - hello: bool, - recipient: Option<&str>, - player_state: &PlayerState) { - let mut cs = CommandSender::new(self, - if hello { - MessageType::kMessageTypeHello - } else { - MessageType::kMessageTypeNotify - }) - .player_state(player_state); - if let Some(s) = recipient { - cs = cs.recipient(&s); - } - cs.send(); - } - - fn spirc_state(&self, player_state: &PlayerState) -> protocol::spirc::State { - let (position_ms, position_measured_at) = player_state.position(); - + fn spirc_state(&self, state: &State) -> protocol::spirc::State { protobuf_init!(protocol::spirc::State::new(), { - status: player_state.status(), - position_ms: position_ms, - position_measured_at: position_measured_at as u64, + status: state.status, + position_ms: state.position_ms, + position_measured_at: state.position_measured_at as u64, playing_track_index: self.index, track: self.tracks.iter().map(|track| { @@ -329,12 +324,12 @@ impl SpircInternal { }) } - fn device_state(&self, player_state: &PlayerState) -> protocol::spirc::DeviceState { + fn device_state(&self, state: &State) -> protocol::spirc::DeviceState { protobuf_init!(protocol::spirc::DeviceState::new(), { sw_version: version::version_string(), is_active: self.is_active, can_play: self.can_play, - volume: player_state.volume() as u32, + volume: state.volume as u32, name: self.name.clone(), error_code: 0, became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 }, @@ -398,7 +393,6 @@ struct CommandSender<'a> { spirc_internal: &'a mut SpircInternal, cmd: MessageType, recipient: Option<&'a str>, - player_state: Option<&'a PlayerState>, state: Option, } @@ -408,7 +402,6 @@ impl<'a> CommandSender<'a> { spirc_internal: spirc_internal, cmd: cmd, recipient: None, - player_state: None, state: None, } } @@ -418,21 +411,21 @@ impl<'a> CommandSender<'a> { 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 state = self.player_state.map_or_else(|| { - Cow::Owned(self.spirc_internal.player.state()) - }, |s| { - Cow::Borrowed(s) + //TODO: get data + let state = Cow::Owned(State { + status: PlayStatus::kPlayStatusStop, + position_ms: 0, + position_measured_at: 0, + update_time: util::now_ms(), + volume: 0, + track: None, + end_of_track: false, }); let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), { @@ -445,7 +438,7 @@ impl<'a> CommandSender<'a> { self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![]) ), device_state: self.spirc_internal.device_state(&state), - state_update_id: state.update_time() + state_update_id: state.update_time }); if self.spirc_internal.is_active {