Added playlist params to ui
parent
484d0a0bf2
commit
4ba9d6cf12
|
|
@ -73,5 +73,7 @@ impl App {
|
||||||
|
|
||||||
pub fn on_tab(&mut self) {}
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ pub fn request_queue_cleaner(
|
||||||
if should_connect {
|
if should_connect {
|
||||||
*state.lock().unwrap() = None;
|
*state.lock().unwrap() = None;
|
||||||
stream = Some(connect());
|
stream = Some(connect());
|
||||||
|
queue
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push(Message::new(MessageType::StateFetch, None));
|
||||||
should_connect = false;
|
should_connect = false;
|
||||||
}
|
}
|
||||||
match stream.as_mut() {
|
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
|
let sleep_duration = message_rate
|
||||||
.checked_sub(last_tick.elapsed())
|
.checked_sub(last_tick.elapsed())
|
||||||
.unwrap_or_else(|| Duration::from_secs(0));
|
.unwrap_or_else(|| Duration::from_secs(0));
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,18 @@
|
||||||
use ratatui::{prelude::*, widgets::*};
|
use ratatui::{
|
||||||
|
prelude::*,
|
||||||
|
widgets::{block::Title, *},
|
||||||
|
};
|
||||||
|
use rmp::ServerState;
|
||||||
|
|
||||||
use super::app::App;
|
use super::app::App;
|
||||||
|
|
||||||
pub fn draw<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
pub fn draw<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
||||||
if app.connected() {
|
if let Some(state) = app.state.lock().unwrap().as_ref() {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.constraints([Constraint::Min(3), Constraint::Length(2)].as_ref())
|
.constraints([Constraint::Min(3), Constraint::Length(2)].as_ref())
|
||||||
.split(f.size());
|
.split(f.size());
|
||||||
draw_playlist(f, app, chunks[0]);
|
draw_playlist(f, state, chunks[0]);
|
||||||
draw_player(f, app, chunks[1]);
|
draw_player(f, state, chunks[1]);
|
||||||
} else {
|
} else {
|
||||||
draw_no_connection(f);
|
draw_no_connection(f);
|
||||||
}
|
}
|
||||||
|
|
@ -17,6 +21,9 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
||||||
static PRIMARY_COLOR: Color = Color::Rgb(200, 150, 70);
|
static PRIMARY_COLOR: Color = Color::Rgb(200, 150, 70);
|
||||||
static SECONDARY_COLOR: Color = Color::Rgb(200, 200, 200);
|
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<B: Backend>(f: &mut Frame<B>) {
|
fn draw_no_connection<B: Backend>(f: &mut Frame<B>) {
|
||||||
let message = "Not connected";
|
let message = "Not connected";
|
||||||
let width = message.len() as u16 + 4;
|
let width = message.len() as u16 + 4;
|
||||||
|
|
@ -40,7 +47,7 @@ fn draw_no_connection<B: Backend>(f: &mut Frame<B>) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_playlist<B: Backend>(f: &mut Frame<B>, app: &App, area: Rect) {
|
fn draw_playlist<B: Backend>(f: &mut Frame<B>, state: &ServerState, area: Rect) {
|
||||||
let playlist = List::new(vec![])
|
let playlist = List::new(vec![])
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
|
|
@ -51,21 +58,62 @@ fn draw_playlist<B: Backend>(f: &mut Frame<B>, app: &App, area: Rect) {
|
||||||
f.render_widget(playlist, area);
|
f.render_widget(playlist, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_player<B: Backend>(f: &mut Frame<B>, app: &App, area: Rect) {
|
fn draw_player<B: Backend>(f: &mut Frame<B>, state: &ServerState, area: Rect) {
|
||||||
let title_content = vec![
|
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("[ "),
|
||||||
Span::from("??").fg(PRIMARY_COLOR),
|
Span::from("??").fg(PRIMARY_COLOR),
|
||||||
Span::from(" ]"),
|
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<Title> = 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()
|
let player = Gauge::default()
|
||||||
.block(
|
.block(block)
|
||||||
Block::default()
|
|
||||||
.borders(Borders::TOP)
|
|
||||||
.border_style(Style::default().fg(SECONDARY_COLOR))
|
|
||||||
.title(title_content)
|
|
||||||
.title_position(block::Position::Top),
|
|
||||||
)
|
|
||||||
.gauge_style(Style::default().fg(PRIMARY_COLOR))
|
.gauge_style(Style::default().fg(PRIMARY_COLOR))
|
||||||
.ratio(0.25)
|
.ratio(0.25)
|
||||||
.label("[ PAUSED ]");
|
.label("[ PAUSED ]");
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ pub struct CliArgs {
|
||||||
client_only: bool,
|
client_only: bool,
|
||||||
|
|
||||||
/// time in ms between two ticks.
|
/// time in ms between two ticks.
|
||||||
#[argh(option, default = "250")]
|
#[argh(option, default = "100")]
|
||||||
tick_rate: u64,
|
tick_rate: u64,
|
||||||
|
|
||||||
/// interval in ms for clearing the request queue.
|
/// interval in ms for clearing the request queue.
|
||||||
#[argh(option, default = "50")]
|
#[argh(option, default = "100")]
|
||||||
message_rate: u64,
|
message_rate: u64,
|
||||||
|
|
||||||
/// whether unicode symbols are used to improve the overall look of the app
|
/// whether unicode symbols are used to improve the overall look of the app
|
||||||
|
|
|
||||||
|
|
@ -119,10 +119,10 @@ fn session_handler(mut stream: LocalSocketStream, server: Arc<Mutex<Server>>) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error => {
|
error => {
|
||||||
eprintln!("[{session_id}] rx {error:?}");
|
eprintln!("[{session_id}] rx Error {error:?}");
|
||||||
let body = bincode::serialize(&error).unwrap();
|
let body = bincode::serialize(&error).unwrap();
|
||||||
let message = Message::new(MessageType::ProtocolError, Some(&body));
|
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();
|
rmp::protocol::send(&mut stream, &message).unwrap();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue