Connect to MPD, update progress bar

devel
~erin 2023-03-21 19:33:19 -04:00
parent 521ca5de0a
commit 1d33339439
Signed by: erin
GPG Key ID: 9A8E308CEFA37A47
3 changed files with 89 additions and 16 deletions

43
Cargo.lock generated
View File

@ -14,6 +14,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bufstream"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
[[package]]
name = "cassowary"
version = "0.3.0"
@ -84,10 +90,21 @@ checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc",
"log",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
[[package]]
name = "mpd"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82"
dependencies = [
"bufstream",
"rustc-serialize",
"time",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
@ -120,6 +137,12 @@ dependencies = [
"bitflags",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -162,6 +185,17 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "time"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
name = "tui"
version = "0.19.0"
@ -187,6 +221,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -286,5 +326,6 @@ name = "xenmotif"
version = "0.1.0"
dependencies = [
"crossterm",
"mpd",
"tui",
]

View File

@ -22,6 +22,7 @@ images = []
[dependencies]
tui = "0.19"
crossterm = "0.25"
mpd = "*"
[profile.release]
strip = true

View File

@ -3,15 +3,23 @@ use crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::{error::Error, io, time::{Duration, Instant}};
use std::{
error::Error,
io,
time::{Duration, Instant},
};
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Alignment, Constraint, Direction, Layout},
style::{Color, Modifier, Style},
text::{Span, Spans},
widgets::{Block, BorderType, Borders, List, ListItem, ListState, Gauge},
widgets::{Block, BorderType, Borders, Gauge, List, ListItem, ListState},
Frame, Terminal,
};
extern crate mpd;
use mpd::Client;
use std::net::TcpStream;
struct StatefulList<T> {
state: ListState,
@ -67,17 +75,15 @@ impl<T> StatefulList<T> {
/// Check the drawing logic for items on how to specify the highlighting style for selected items.
struct App<'a> {
items: StatefulList<(&'a str, usize)>,
mpd_client: Client,
}
impl<'a> App<'a> {
fn new() -> App<'a> {
App {
items: StatefulList::with_items(vec![
("Item0", 1),
("Item1", 2),
("Item2", 3),
]),
}
items: StatefulList::with_items(vec![("Item0", 1), ("Item1", 2), ("Item2", 3)]),
mpd_client: Client::connect("127.0.0.1:6600").unwrap(),
}
}
}
@ -90,8 +96,9 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut terminal = Terminal::new(backend)?;
// create app and run it
let tick_rate = Duration::from_millis(50);
let app = App::new();
let res = run_app(&mut terminal, app);
let res = run_app(&mut terminal, app, tick_rate);
// restore terminal
disable_raw_mode()?;
@ -109,10 +116,15 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App, tick_rate: Duration) -> io::Result<()> {
let mut last_tick = Instant::now();
loop {
terminal.draw(|f| ui(f, &mut app))?;
let timeout = tick_rate
.checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_secs(0));
if crossterm::event::poll(timeout)? {
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => return Ok(()),
@ -122,10 +134,14 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<(
_ => {}
}
}
}
if last_tick.elapsed() >= tick_rate {
// app.on_tick();
last_tick = Instant::now();
}
}
}
fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
// Wrapping block for a group
// Just draw the block and the group on the same area and build the group
@ -143,7 +159,14 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(2)
.constraints([Constraint::Percentage(30), Constraint::Percentage(68), Constraint::Percentage(2)].as_ref())
.constraints(
[
Constraint::Percentage(30),
Constraint::Percentage(68),
Constraint::Percentage(2),
]
.as_ref(),
)
.split(f.size());
// Top two inner blocks
@ -177,7 +200,14 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
let bottom_chunks = Layout::default()
.direction(Direction::Horizontal)
.margin(1)
.constraints([Constraint::Percentage(30), Constraint::Percentage(30), Constraint::Percentage(30)].as_ref())
.constraints(
[
Constraint::Percentage(30),
Constraint::Percentage(30),
Constraint::Percentage(30),
]
.as_ref(),
)
.split(chunks[1]);
// Artist
@ -206,10 +236,11 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
f.render_widget(songs, bottom_chunks[2]);
// Timeline
let time = app.mpd_client.status().unwrap().time.unwrap();
let percent: f64 = (time.0.num_seconds() as f64 / time.1.num_seconds() as f64) * 100.0;
let timeline = Gauge::default()
.block(Block::default().borders(Borders::NONE))
.gauge_style(Style::default().fg(Color::Red))
.percent(50);
.percent(percent as u16);
f.render_widget(timeline, chunks[2]);
}