mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Remove the SpircDelegate abstraction
This commit is contained in:
parent
303121032d
commit
463ce97661
2 changed files with 74 additions and 101 deletions
114
src/player.rs
114
src/player.rs
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
61
src/spirc.rs
61
src/spirc.rs
|
@ -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 },
|
||||||
|
|
Loading…
Reference in a new issue