use crate::audio;
use crate::audio::player::AudioPlayerControls;
use crate::common::errors::MyError;
use crate::common::sync::PlaybackClock;
use crossbeam_channel::{select, Receiver};
use std::sync::{Arc, RwLock};
use std::time::Duration;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum State {
Running,
Paused,
Stopped,
}
pub struct Runner {
audio_player: audio::player::AudioPlayer,
state: State,
rx_controls: Receiver<Control>,
subtitle_text: Option<Arc<RwLock<String>>>,
playback_clock: Option<Arc<PlaybackClock>>,
}
#[derive(Debug, PartialEq)]
pub enum Control {
PauseContinue,
Replay,
MuteUnmute,
Exit,
Seek(f64),
SeekAbsolute(f64),
SeekPercent(f64),
CycleSubtitle,
ToggleSubtitle,
AdjustSpeed(f64),
ResetSpeed,
}
impl Runner {
pub fn new(
audio_player: audio::player::AudioPlayer,
rx_controls: Receiver<Control>,
subtitle_text: Option<Arc<RwLock<String>>>,
playback_clock: Option<Arc<PlaybackClock>>,
) -> Self {
Self {
audio_player,
state: State::Running,
rx_controls,
subtitle_text,
playback_clock,
}
}
pub fn run(&mut self, barrier: std::sync::Arc<std::sync::Barrier>) -> Result<(), MyError> {
barrier.wait();
self.audio_player.player.resume()?;
if let Some(ref clock) = self.playback_clock {
clock.set_paused(false);
}
while self.state != State::Stopped {
self.update_subtitle();
self.update_playback_clock();
select! {
recv(self.rx_controls) -> msg => {
match msg.unwrap() {
Control::PauseContinue => {
self.state = match self.state {
State::Running => State::Paused,
State::Paused => State::Running,
State::Stopped => State::Stopped,
};
self.audio_player.player.toggle_play()?;
if let Some(ref clock) = self.playback_clock {
clock.set_paused(self.state == State::Paused);
}
},
Control::MuteUnmute => {
self.audio_player.player.toggle_mute()?;
},
Control::Replay => {
self.audio_player.player.rewind()?;
if let Some(ref clock) = self.playback_clock {
clock.set_position(Duration::ZERO);
}
},
Control::Exit => {
self.state = State::Stopped;
self.audio_player.player.stop()?;
},
Control::Seek(seconds) => {
let _ = self.audio_player.player.seek(seconds);
self.update_playback_clock();
},
Control::SeekAbsolute(seconds) => {
let _ = self.audio_player.player.seek_absolute(seconds);
self.update_playback_clock();
},
Control::SeekPercent(pct) => {
let _ = self.audio_player.player.seek_percent(pct);
self.update_playback_clock();
},
Control::CycleSubtitle => {
let _ = self.audio_player.player.cycle_subtitle();
},
Control::ToggleSubtitle => {
let _ = self.audio_player.player.toggle_subtitle();
},
Control::AdjustSpeed(delta) => {
let current = self.audio_player.player.get_speed();
let new_speed = (current + delta).clamp(0.5, 2.0);
if self.audio_player.player.set_speed(new_speed).is_ok() {
if let Some(ref clock) = self.playback_clock {
clock.set_speed(new_speed as f32);
}
}
},
Control::ResetSpeed => {
if self.audio_player.player.set_speed(1.0).is_ok() {
if let Some(ref clock) = self.playback_clock {
clock.set_speed(1.0);
}
}
},
}
},
default(Duration::from_millis(16)) => {}
}
}
Ok(())
}
fn update_playback_clock(&self) {
if let Some(ref clock) = self.playback_clock {
let pos = self.audio_player.player.get_position();
clock.set_position(pos);
}
}
fn update_subtitle(&mut self) {
if let Some(ref subtitle_lock) = self.subtitle_text {
if let Some(text) = self.audio_player.player.get_subtitle_text() {
if let Ok(mut subtitle) = subtitle_lock.write() {
*subtitle = text;
}
} else if let Ok(mut subtitle) = subtitle_lock.write() {
subtitle.clear();
}
}
}
}