use stopwatch2::Stopwatch;
use crate::{
library::{Playlist, Song},
player::{
LOG,
PlayerState,
RepeatMode,
source::GSTSource
}
};
pub struct BackgroundPlayer {
pub queue: Playlist,
pub song: Song,
pub state: PlayerState,
pub repeat: RepeatMode,
pub position: usize,
timer: Stopwatch,
seeked_time: u64,
source: GSTSource
}
impl BackgroundPlayer {
pub fn new() -> BackgroundPlayer {
BackgroundPlayer {
song: Song::empty(),
queue: Playlist::new("_"),
position: usize::MAX,
state: PlayerState::Stopped,
repeat: RepeatMode::Once,
timer: Stopwatch::default(),
seeked_time: 0,
source: GSTSource::new()
}
}
pub fn load_list(&mut self, list: &Playlist) {
self.queue = list.clone();
self.song = list.songs[0].clone();
self.position = 0;
self.play();
}
pub fn cycle_repeat(&mut self) {
let new_mode = match self.repeat {
RepeatMode::All => RepeatMode::Once,
RepeatMode::Once => RepeatMode::One,
RepeatMode::One => RepeatMode::All
};
self.repeat = new_mode;
}
pub fn play(&mut self) {
if self.song.name.is_empty() { return; }
self.seeked_time = 0;
self.timer = Stopwatch::default();
self.timer.start();
self.state = PlayerState::Playing;
self.song = self.queue.songs[self.position].clone();
self.source.set_song(&self.song);
LOG.line_basic(format!("Playing {} by {}...", self.song.name, self.song.artist), true);
}
pub fn restart(&mut self) {
self.timer = Stopwatch::default();
self.timer.start();
self.seeked_time = 0;
self.source.set_song(&self.song);
LOG.line_basic("Restarting current song...", true);
}
pub fn next(&mut self) {
if self.position == self.queue.songs.len() - 1 {
match self.repeat {
RepeatMode::All => {
self.position = 0;
self.song = self.queue.songs[0].clone();
self.play();
return;
}
RepeatMode::Once => {
self.timer = Stopwatch::default();
self.seeked_time = 0;
self.position = 0;
self.song = self.queue.songs[0].clone();
self.source.set_song(&self.queue.songs[0]);
self.silent_pause();
return;
}
RepeatMode::One => { }
}
}
self.player_stop();
self.timer = Stopwatch::default();
if self.repeat != RepeatMode::One {
self.position += 1;
self.song = self.queue.songs[self.position].clone();
self.play();
}
else if self.repeat == RepeatMode::One {
self.restart();
}
}
pub fn prev(&mut self) {
if self.position == 0 {
self.position = self.queue.songs.len() - 1;
}
else {
self.position -= 1;
}
self.player_stop();
self.song = self.queue.songs[self.position].clone();
self.play();
}
pub fn resume(&mut self) {
if let PlayerState::Paused(_) = self.state {
self.timer.start();
self.state = PlayerState::Playing;
self.source.play();
}
LOG.line_basic("Resuming current song...", true);
}
pub fn pause(&mut self) {
self.silent_pause();
LOG.line_basic("Pausing current song...", true);
}
fn silent_pause(&mut self) {
self.timer.stop();
self.state = PlayerState::Paused(self.seeked_time + self.timer.elapsed().as_secs());
self.source.pause();
}
pub fn stop(&mut self) {
if self.is_stopped() { return; }
self.player_stop();
self.queue = Playlist::new("_");
self.song = Song::empty();
self.position = usize::MAX;
self.state = PlayerState::Stopped;
self.timer.stop();
self.timer = Stopwatch::default();
LOG.line_basic("Stopping player...", true);
}
pub fn shuffle_queue(&mut self) {
LOG.line_basic("Shuffling play queue...", true);
if self.state == PlayerState::Stopped {
return;
}
self.queue.shuffle(self.position);
self.position = 0;
}
pub fn cur_time_secs(&self) -> u64 {
if let PlayerState::Paused(elapsed) = self.state {
elapsed
}
else if self.state == PlayerState::Stopped {
0
}
else {
self.seeked_time + self.timer.elapsed().as_secs()
}
}
pub fn is_paused(&self) -> bool { matches!(self.state, PlayerState::Paused(_)) }
pub fn is_stopped(&self) -> bool { self.state == PlayerState::Stopped }
pub fn set_pos(&mut self, song: &Song) {
self.player_stop();
for (i, s) in self.queue.songs.iter().enumerate() {
if s == song {
self.position = i;
}
}
self.song = song.clone();
self.play()
}
pub fn auto_advance(&mut self) {
if self.state == PlayerState::Playing && self.timer.elapsed().as_secs() + self.seeked_time >= self.song.duration {
self.next();
}
}
pub fn find_pos(&mut self) {
for (i, song) in self.queue.songs.iter().enumerate() {
if *song == self.song {
self.position = i;
}
}
}
pub fn seek(&mut self, time: u64) {
self.silent_pause();
self.timer = Stopwatch::default();
self.seeked_time = time;
if time >= self.song.duration {
self.next();
return;
}
self.source.seek(time);
}
fn player_stop(&mut self) { self.source.stop(); }
}