diff --git a/src/client/app.rs b/src/client/app.rs index b65e11c..451c678 100644 --- a/src/client/app.rs +++ b/src/client/app.rs @@ -73,5 +73,7 @@ impl App { pub fn on_tab(&mut self) {} - pub fn on_tick(&mut self, duration: Duration) {} + pub fn on_tick(&mut self, duration: Duration) { + self.push_message(Message::new(MessageType::StateFetch, None)); + } } diff --git a/src/client/request_queue.rs b/src/client/request_queue.rs index 302785e..3d901ea 100644 --- a/src/client/request_queue.rs +++ b/src/client/request_queue.rs @@ -21,6 +21,10 @@ pub fn request_queue_cleaner( if should_connect { *state.lock().unwrap() = None; stream = Some(connect()); + queue + .lock() + .unwrap() + .push(Message::new(MessageType::StateFetch, None)); should_connect = false; } match stream.as_mut() { @@ -40,12 +44,6 @@ pub fn request_queue_cleaner( } } - // HACK: keep updating state - queue - .lock() - .unwrap() - .push(Message::new(MessageType::StateFetch, None)); - let sleep_duration = message_rate .checked_sub(last_tick.elapsed()) .unwrap_or_else(|| Duration::from_secs(0)); diff --git a/src/client/ui.rs b/src/client/ui.rs index b7aacac..4e2c087 100644 --- a/src/client/ui.rs +++ b/src/client/ui.rs @@ -1,14 +1,18 @@ -use ratatui::{prelude::*, widgets::*}; +use ratatui::{ + prelude::*, + widgets::{block::Title, *}, +}; +use rmp::ServerState; use super::app::App; pub fn draw(f: &mut Frame, app: &mut App) { - if app.connected() { + if let Some(state) = app.state.lock().unwrap().as_ref() { let chunks = Layout::default() .constraints([Constraint::Min(3), Constraint::Length(2)].as_ref()) .split(f.size()); - draw_playlist(f, app, chunks[0]); - draw_player(f, app, chunks[1]); + draw_playlist(f, state, chunks[0]); + draw_player(f, state, chunks[1]); } else { draw_no_connection(f); } @@ -17,6 +21,9 @@ pub fn draw(f: &mut Frame, app: &mut App) { static PRIMARY_COLOR: Color = Color::Rgb(200, 150, 70); static SECONDARY_COLOR: Color = Color::Rgb(200, 200, 200); +static PRIMARY_CONTRAST: Color = Color::Black; +static CLEAR_CONTRAST: Color = Color::Rgb(100, 100, 100); + fn draw_no_connection(f: &mut Frame) { let message = "Not connected"; let width = message.len() as u16 + 4; @@ -40,7 +47,7 @@ fn draw_no_connection(f: &mut Frame) { ); } -fn draw_playlist(f: &mut Frame, app: &App, area: Rect) { +fn draw_playlist(f: &mut Frame, state: &ServerState, area: Rect) { let playlist = List::new(vec![]) .block( Block::default() @@ -51,21 +58,62 @@ fn draw_playlist(f: &mut Frame, app: &App, area: Rect) { f.render_widget(playlist, area); } -fn draw_player(f: &mut Frame, app: &App, area: Rect) { - let title_content = vec![ +fn draw_player(f: &mut Frame, state: &ServerState, area: Rect) { + fn decorate_bool(span: Span, value: bool) -> Span { + match value { + true => return span.bg(PRIMARY_COLOR).fg(PRIMARY_CONTRAST), + false => return span.fg(CLEAR_CONTRAST), + } + } + + let track_title = vec![ Span::from("[ "), Span::from("??").fg(PRIMARY_COLOR), Span::from(" ]"), ]; + let mut block = Block::default() + .borders(Borders::TOP) + .border_style(Style::default().fg(SECONDARY_COLOR)) + .title(track_title); + + // Horrible to look at, worse to write + let param_titles: Vec = vec![ + ( + state.playlist_params.next, + vec![ + Span::from("NE"), + Span::from("X").underlined(), + Span::from("T"), + ], + ), + ( + state.playlist_params.shuffle, + vec![Span::from("S").underlined(), Span::from("UFFLE")], + ), + ( + state.playlist_params.repeat, + vec![Span::from("R").underlined(), Span::from("EPEAT")], + ), + ] + .iter() + .map(|(value, spans)| { + spans + .iter() + .map(|span| decorate_bool(span.clone(), *value)) + .collect::<Vec<_>>() + }) + .map(|spans| Title::from([&[Span::from(" ")], spans.as_slice(), &[Span::from(" ")]].concat())) + .collect(); + + for title in param_titles { + block = block.title(title); + } + + let block = block.title_position(block::Position::Top); + let player = Gauge::default() - .block( - Block::default() - .borders(Borders::TOP) - .border_style(Style::default().fg(SECONDARY_COLOR)) - .title(title_content) - .title_position(block::Position::Top), - ) + .block(block) .gauge_style(Style::default().fg(PRIMARY_COLOR)) .ratio(0.25) .label("[ PAUSED ]"); diff --git a/src/main.rs b/src/main.rs index 34cc0b2..8ecf7da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,11 +31,11 @@ pub struct CliArgs { client_only: bool, /// time in ms between two ticks. - #[argh(option, default = "250")] + #[argh(option, default = "100")] tick_rate: u64, /// interval in ms for clearing the request queue. - #[argh(option, default = "50")] + #[argh(option, default = "100")] message_rate: u64, /// whether unicode symbols are used to improve the overall look of the app diff --git a/src/server.rs b/src/server.rs index 8c6f38f..a3e9314 100644 --- a/src/server.rs +++ b/src/server.rs @@ -119,10 +119,10 @@ fn session_handler(mut stream: LocalSocketStream, server: Arc<Mutex<Server>>) { return; } error => { - eprintln!("[{session_id}] rx {error:?}"); + eprintln!("[{session_id}] rx Error {error:?}"); let body = bincode::serialize(&error).unwrap(); let message = Message::new(MessageType::ProtocolError, Some(&body)); - println!("[{session_id}] tx {message}"); + eprintln!("[{session_id}] tx {message}"); rmp::protocol::send(&mut stream, &message).unwrap(); } },