From ae493cd221e4f27c8c7f86b858dd68bb91f88265 Mon Sep 17 00:00:00 2001 From: alemidev Date: Mon, 26 Dec 2022 03:12:20 +0100 Subject: [PATCH] feat: key to toggle UI, hide title when no ui --- Cargo.toml | 2 +- README.md | 1 + src/app.rs | 18 +++++----- src/main.rs | 102 ++++++++++++++++++++++++++++++---------------------- 4 files changed, 70 insertions(+), 53 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 98848f7..e5c2e07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "scope-tui" version = "0.1.3" edition = "2021" authors = [ "alemi " ] -description = "A simple audio visualization tool for the terminal built with tui-rs and libpulse-simple-binding, inspired from cava" +description = "A simple oscilloscope/vectorscope for the terminal, inspired by cava" keywords = ["tui", "terminal", "audio", "visualization", "scope", "dashboard"] repository = "https://github.com/alemidev/scope-tui" readme = "README.md" diff --git a/README.md b/README.md index e669776..7379e0e 100644 --- a/README.md +++ b/README.md @@ -39,4 +39,5 @@ To change audio buffer size, the PulseAudio client must be restarted. Because of * Use `-` and `=` to decrease or increase range (`_` and `+` for smaller steps) * Use `v` to toggle vectorscope mode * Use `s` to toggle scatter mode +* Use `h` to toggle interface * Decrease/increase terminal font size to increase/decrease scope resolution. diff --git a/src/app.rs b/src/app.rs index a9f5133..88872c1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,7 +2,7 @@ use tui::{style::Color, widgets::GraphType, symbols}; // use crate::parser::SampleParser; -pub enum Axis { +pub enum Dimension { X, Y } @@ -63,14 +63,14 @@ pub struct App { impl App { fn update_values(&mut self) { if self.cfg.vectorscope { - self.names.x = "- left".into(); + self.names.x = "left -".into(); self.names.y = "| right".into(); self.bounds.x = [-(self.cfg.scale as f64), self.cfg.scale as f64]; self.bounds.y = [-(self.cfg.scale as f64), self.cfg.scale as f64]; self.references.x = vec![(-(self.cfg.scale as f64), 0.0), (self.cfg.scale as f64, 0.0)]; self.references.y = vec![(0.0, -(self.cfg.scale as f64)), (0.0, self.cfg.scale as f64)]; } else { - self.names.x = "- time".into(); + self.names.x = "time -".into(); self.names.y = "| amplitude".into(); self.bounds.x = [0.0, self.cfg.width as f64]; self.bounds.y = [-(self.cfg.scale as f64), self.cfg.scale as f64]; @@ -80,17 +80,17 @@ impl App { } } - pub fn bounds(&self, axis: Axis) -> [f64;2] { + pub fn bounds(&self, axis: &Dimension) -> [f64;2] { match axis { - Axis::X => self.bounds.x, - Axis::Y => self.bounds.y, + Dimension::X => self.bounds.x, + Dimension::Y => self.bounds.y, } } - pub fn name(&self, axis: Axis) -> &str { + pub fn name(&self, axis: &Dimension) -> &str { match axis { - Axis::X => self.names.x.as_str(), - Axis::Y => self.names.y.as_str(), + Dimension::X => self.names.x.as_str(), + Dimension::Y => self.names.y.as_str(), } } diff --git a/src/main.rs b/src/main.rs index 85d405c..6e21ff1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use tui::{ backend::{CrosstermBackend, Backend}, widgets::{Block, Chart, Axis, Dataset, GraphType}, // layout::{Layout, Constraint, Direction}, - Terminal, text::Span, style::{Style, Color, Modifier}, symbols + Terminal, text::Span, style::{Style, Color, Modifier}, symbols, layout::Alignment }; use crossterm::{ event::{self, DisableMouseCapture, Event, KeyCode, KeyModifiers}, @@ -70,29 +70,6 @@ struct Args { no_braille: bool, } -fn poll_event() -> Result, std::io::Error> { - if event::poll(Duration::from_millis(0))? { - Ok(Some(event::read()?)) - } else { - Ok(None) - } -} - -fn data_set<'a>( - name: &'a str, - data: &'a [(f64, f64)], - marker_type: symbols::Marker, - graph_type: GraphType, - axis_color: Color -) -> Dataset<'a> { - Dataset::default() - .name(name) - .marker(marker_type) - .graph_type(graph_type) - .style(Style::default().fg(axis_color)) - .data(&data) -} - fn main() -> Result<(), io::Error> { let mut args = Args::parse(); @@ -216,7 +193,6 @@ fn run_app(args: Args, terminal: &mut Terminal) -> Result<(), io datasets.push(data_set("L", &left, app.cfg.marker_type, app.graph_type(), app.cfg.primary_color)); } - fps += 1; if last_poll.elapsed().as_secs() >= 1 { @@ -228,24 +204,9 @@ fn run_app(args: Args, terminal: &mut Terminal) -> Result<(), io terminal.draw(|f| { let size = f.size(); let chart = Chart::new(datasets) - .block(Block::default().title( - Span::styled( - format!( - "TUI {} -- {} mode -- range {} -- {} samples -- {:.1} kHz -- {} fps", - if app.vectorscope() { "Vectorscope" } else { "Oscilloscope" }, - if app.scatter() { "scatter" } else { "line" }, - app.scale(), app.width(), args.sample_rate as f32 / 1000.0, framerate, - ), - Style::default().add_modifier(Modifier::BOLD).fg(Color::Yellow)) - )) - .x_axis(Axis::default() - .title(Span::styled(app.name(app::Axis::X), Style::default().fg(Color::Cyan))) - .style(Style::default().fg(app.cfg.axis_color)) - .bounds(app.bounds(app::Axis::X))) // TODO allow to have axis sometimes? - .y_axis(Axis::default() - .title(Span::styled(app.name(app::Axis::Y), Style::default().fg(Color::Cyan))) - .style(Style::default().fg(app.cfg.axis_color)) - .bounds(app.bounds(app::Axis::Y))); + .block(block(&app, args.sample_rate as f32, framerate)) + .x_axis(axis(&app, app::Dimension::X)) // TODO allow to have axis sometimes? + .y_axis(axis(&app, app::Dimension::Y)); f.render_widget(chart, size) })?; @@ -267,6 +228,7 @@ fn run_app(args: Args, terminal: &mut Terminal) -> Result<(), io KeyCode::Char('_') => app.update_scale(100), KeyCode::Char('v') => app.set_vectorscope(!app.vectorscope()), KeyCode::Char('s') => app.set_scatter(!app.scatter()), + KeyCode::Char('h') => app.cfg.references = !app.cfg.references, _ => {}, } } @@ -276,3 +238,57 @@ fn run_app(args: Args, terminal: &mut Terminal) -> Result<(), io Ok(()) } + + +// TODO these functions probably shouldn't be here + +fn poll_event() -> Result, std::io::Error> { + if event::poll(Duration::from_millis(0))? { + Ok(Some(event::read()?)) + } else { + Ok(None) + } +} + +fn data_set<'a>( + name: &'a str, + data: &'a [(f64, f64)], + marker_type: symbols::Marker, + graph_type: GraphType, + axis_color: Color +) -> Dataset<'a> { + Dataset::default() + .name(name) + .marker(marker_type) + .graph_type(graph_type) + .style(Style::default().fg(axis_color)) + .data(&data) +} + +fn axis(app: &App, dim: app::Dimension) -> Axis { + let mut a = Axis::default(); + if app.cfg.references { + a = a.title(Span::styled(app.name(&dim), Style::default().fg(Color::Cyan))); + } + a.style(Style::default().fg(app.cfg.axis_color)) + .bounds(app.bounds(&dim)) +} + +fn block(app: &App, sample_rate: f32, framerate: u32) -> Block { + let mut b = Block::default(); + + if app.cfg.references { + b = b.title( + Span::styled( + format!( + "TUI {} -- {} mode -- range {} -- {} samples -- {:.1} kHz -- {} fps", + if app.vectorscope() { "Vectorscope" } else { "Oscilloscope" }, + if app.scatter() { "scatter" } else { "line" }, + app.scale(), app.width(), sample_rate / 1000.0, framerate, + ), + Style::default().add_modifier(Modifier::BOLD).fg(Color::Yellow)) + ).title_alignment(Alignment::Center); + } + + b +}