User quit handling, playlist extending

This commit is contained in:
Muaz Ahmad 2024-11-28 12:16:58 +05:00
parent 85ae8d1624
commit 35184a76b9
6 changed files with 67 additions and 6 deletions

View file

@ -8,6 +8,8 @@ use crate::utils::Error;
#[derive(Deserialize)]
pub struct Settings {
pub subsonic: Subsonic,
#[serde(default = "default_controls")]
pub controls: Controls,
}
#[derive(Deserialize)]
@ -20,6 +22,15 @@ pub struct Subsonic {
pub random_limit: i32,
}
#[derive(Deserialize)]
pub struct Controls {
pub quit: char,
}
fn default_controls() -> Controls {
Controls { quit: 'q' }
}
fn default_random_limit() -> i32 {
10
}

View file

@ -1,7 +1,11 @@
use std::ops::Deref;
use std::process::exit;
use std::sync::mpsc::{channel, Receiver};
use player::errors::PlayerError;
use ssonic::response::PlayQueue;
mod audio;
mod config;
mod player;
@ -22,6 +26,7 @@ fn init() -> Result<Receiver<utils::Error>, utils::Error> {
api_event_chan,
error_in.clone(),
player_events_out,
player_events_in,
)?;
Ok(error_out)
}
@ -36,8 +41,20 @@ fn main() {
Ok(err_chan) => err_chan,
};
match err_chan.recv() {
Err(_) => exit(0),
Err(_) => {
utils::restore();
exit(0)
}
Ok(err) => {
if let Some(e) = err.downcast_ref::<PlayerError>() {
match e {
PlayerError::UserQuit => {
utils::restore();
exit(0)
}
_ => (),
}
}
utils::restore();
eprintln!("{}", err);
exit(1)

View file

@ -1,6 +1,7 @@
#[derive(Debug)]
pub enum PlayerError {
PlaylistEmpty,
UserQuit,
}
impl std::error::Error for PlayerError {}
@ -9,6 +10,7 @@ impl std::fmt::Display for PlayerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::PlaylistEmpty => write!(f, "Playlist empty"),
Self::UserQuit => write!(f, "User quit signalled"),
}
}
}

View file

@ -17,6 +17,7 @@ use crate::{
pub enum PlayerEvent {
AddSongList(Vec<Song>),
UserQuit,
}
pub struct Player {
@ -26,6 +27,7 @@ pub struct Player {
api_chan: Sender<APIEvent>,
error_chan: Sender<Error>,
player_chan: Receiver<PlayerEvent>,
player_chan_in: Sender<PlayerEvent>,
playlist: playlist::Playlist,
}
@ -35,6 +37,7 @@ pub fn init(
api_chan: Sender<APIEvent>,
error_chan: Sender<Error>,
player_chan: Receiver<PlayerEvent>,
player_chan_in: Sender<PlayerEvent>,
) -> Result<(), Error> {
let terminal = ratatui::init();
thread::spawn(move || {
@ -45,6 +48,7 @@ pub fn init(
api_chan,
error_chan: error_chan.clone(),
player_chan,
player_chan_in,
playlist: playlist::Playlist::new(),
};
match player.begin() {
@ -59,6 +63,6 @@ pub fn init(
Ok(())
}
mod errors;
pub mod errors;
mod player;
mod playlist;

View file

@ -1,8 +1,10 @@
use std::{thread, time::Duration};
use std::{sync::mpsc::TryRecvError, time::Duration};
use crossterm::event::{poll, read, Event, KeyCode};
use crate::{ssonic::APIEvent, utils::Error};
use super::Player;
use super::{errors::PlayerError, Player, PlayerEvent};
impl Player {
pub fn begin(&mut self) -> Result<(), Error> {
@ -22,15 +24,36 @@ impl Player {
self.handle_events()?;
self.handle_inputs()?;
self.update()?;
thread::sleep(Duration::from_millis(100));
}
}
fn handle_events(&mut self) -> Result<(), Error> {
loop {
let e = match self.player_chan.try_recv() {
Err(err) if err == TryRecvError::Empty => break,
Err(err) => return Err(Box::new(err)),
Ok(x) => x,
};
match e {
PlayerEvent::UserQuit => return Err(Box::new(PlayerError::UserQuit)),
PlayerEvent::AddSongList(list) => self.playlist.append(list),
_ => unimplemented!(),
}
}
Ok(())
}
fn handle_inputs(&mut self) -> Result<(), Error> {
if poll(Duration::from_millis(100))? {
match read()? {
Event::Key(e) => {
if e.code == KeyCode::Char(self.settings.controls.quit) {
self.player_chan_in.send(PlayerEvent::UserQuit)?
}
}
_ => (),
}
}
Ok(())
}

View file

@ -1,4 +1,4 @@
use std::collections::VecDeque;
use std::{borrow::BorrowMut, collections::VecDeque};
use crate::{ssonic::response::Song, utils::Error};
@ -16,6 +16,10 @@ impl Playlist {
}
}
pub fn append(&mut self, list: Vec<Song>) {
self.song_list.append(VecDeque::from(list).borrow_mut());
}
pub fn new() -> Playlist {
Playlist {
song_list: VecDeque::new(),