use super::{DBusError, LoopStatus, Metadata, PlaybackStatus, Player, Progress};
#[derive(Debug)]
pub enum Event {
PlayerShutDown,
Paused,
Playing,
Stopped,
LoopingChanged(LoopStatus),
ShuffleToggled(bool),
VolumeChanged(f64),
PlaybackRateChanged(f64),
TrackChanged(Metadata),
}
#[derive(Debug)]
pub struct PlayerEvents<'a> {
player: &'a Player<'a>,
buffer: Vec<Event>,
last_progress: Progress,
}
impl<'a> PlayerEvents<'a> {
pub fn new(player: &'a Player<'a>) -> Result<PlayerEvents<'a>, DBusError> {
let progress = Progress::from_player(player)?;
Ok(PlayerEvents {
player,
buffer: Vec::new(),
last_progress: progress,
})
}
fn read_events(&mut self) -> Result<(), DBusError> {
self.player.process_events_blocking_until_dirty();
if !self.player.is_running() {
self.buffer.push(Event::PlayerShutDown);
return Ok(());
}
let new_progress = Progress::from_player(self.player)?;
self.detect_playback_status_events(&new_progress);
self.detect_loop_status_events(&new_progress);
self.detect_shuffle_events(&new_progress);
self.detect_volume_events(&new_progress);
self.detect_playback_rate_events(&new_progress);
self.detect_metadata_events(&new_progress);
self.last_progress = new_progress;
Ok(())
}
fn detect_playback_status_events(&mut self, new_progress: &Progress) {
match new_progress.playback_status() {
status if self.last_progress.playback_status() == status => {}
PlaybackStatus::Playing => self.buffer.push(Event::Playing),
PlaybackStatus::Paused => self.buffer.push(Event::Paused),
PlaybackStatus::Stopped => self.buffer.push(Event::Stopped),
}
}
fn detect_loop_status_events(&mut self, new_progress: &Progress) {
let loop_status = new_progress.loop_status();
if self.last_progress.loop_status() != loop_status {
self.buffer.push(Event::LoopingChanged(loop_status));
}
}
fn detect_shuffle_events(&mut self, new_progress: &Progress) {
let status = new_progress.shuffle();
if self.last_progress.shuffle() != status {
self.buffer.push(Event::ShuffleToggled(status));
}
}
fn detect_volume_events(&mut self, new_progress: &Progress) {
let volume = new_progress.current_volume();
if self.last_progress.current_volume() != volume {
self.buffer.push(Event::VolumeChanged(volume));
}
}
fn detect_playback_rate_events(&mut self, new_progress: &Progress) {
let rate = new_progress.playback_rate();
if self.last_progress.playback_rate() != rate {
self.buffer.push(Event::PlaybackRateChanged(rate));
}
}
fn detect_metadata_events(&mut self, new_progress: &Progress) {
let metadata = new_progress.metadata();
if self.last_progress.metadata().track_id() != metadata.track_id() {
self.buffer
.push(Event::TrackChanged(metadata.clone_without_rest()));
}
}
}
impl<'a> Iterator for PlayerEvents<'a> {
type Item = Result<Event, DBusError>;
fn next(&mut self) -> Option<Self::Item> {
while self.buffer.is_empty() {
if !self.player.is_running() {
return None;
}
match self.read_events() {
Ok(_) => {}
Err(err) => return Some(Err(err)),
};
}
let event = self.buffer.remove(0);
Some(Ok(event))
}
}