1
0
Fork 0
mirror of https://github.com/alemidev/scope-tui.git synced 2024-11-14 18:59:19 +01:00

feat: update ratatui, allow optional legends

This commit is contained in:
əlemi 2024-02-09 19:59:43 +01:00
parent ab2d4a0af8
commit 0d4975b189
Signed by: alemi
GPG key ID: A4895B84D311642C
5 changed files with 51 additions and 46 deletions

View file

@ -17,8 +17,8 @@ derive_more = "0.99.17"
thiserror = "1.0.48" thiserror = "1.0.48"
rustfft = "6.1.0" rustfft = "6.1.0"
# for TUI backend # for TUI backend
ratatui = { version = "0.23.0", features = ["all-widgets"], optional = true } ratatui = { version = "0.26", features = ["all-widgets"], optional = true }
crossterm = { version = "0.25", optional = true } crossterm = { version = "0.27", optional = true }
# for pulseaudio # for pulseaudio
libpulse-binding = { version = "2.0", optional = true } libpulse-binding = { version = "2.0", optional = true }
libpulse-simple-binding = { version = "2.25", optional = true } libpulse-simple-binding = { version = "2.25", optional = true }

View file

@ -47,7 +47,7 @@ pub trait DisplayMode {
} }
pub struct DataSet { pub struct DataSet {
name: String, name: Option<String>,
data: Vec<(f64, f64)>, data: Vec<(f64, f64)>,
marker_type: Marker, marker_type: Marker,
graph_type: GraphType, graph_type: GraphType,
@ -56,8 +56,11 @@ pub struct DataSet {
impl<'a> From::<&'a DataSet> for Dataset<'a> { impl<'a> From::<&'a DataSet> for Dataset<'a> {
fn from(ds: &'a DataSet) -> Dataset<'a> { fn from(ds: &'a DataSet) -> Dataset<'a> {
Dataset::default() let mut out = Dataset::default(); // TODO creating a binding is kinda ugly, is it avoidable?
.name(ds.name.clone()) if let Some(name) = &ds.name {
out = out.name(name.clone());
}
out
.marker(ds.marker_type) .marker(ds.marker_type)
.graph_type(ds.graph_type) .graph_type(ds.graph_type)
.style(Style::default().fg(ds.color)) .style(Style::default().fg(ds.color))
@ -65,9 +68,10 @@ impl<'a> From::<&'a DataSet> for Dataset<'a> {
} }
} }
// TODO this is pretty ugly but I need datasets which own the data
impl DataSet { impl DataSet {
pub fn new( pub fn new(
name: String, name: Option<String>,
data: Vec<(f64, f64)>, data: Vec<(f64, f64)>,
marker_type: Marker, marker_type: Marker,
graph_type: GraphType, graph_type: GraphType,

View file

@ -58,7 +58,7 @@ impl DisplayMode for Oscilloscope {
fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> { fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
vec![ vec![
DataSet::new("".into(), vec![(0.0, 0.0), (cfg.samples as f64, 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(0.0, 0.0), (cfg.samples as f64, 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color),
] ]
} }
@ -78,7 +78,7 @@ impl DisplayMode for Oscilloscope {
} }
if self.triggering { if self.triggering {
out.push(DataSet::new("T".into(), vec![(0.0, self.threshold)], cfg.marker_type, GraphType::Scatter, cfg.labels_color)); out.push(DataSet::new(Some("T".into()), vec![(0.0, self.threshold)], cfg.marker_type, GraphType::Scatter, cfg.labels_color));
} }
for (n, channel) in data.iter().enumerate().rev() { for (n, channel) in data.iter().enumerate().rev() {
@ -94,7 +94,7 @@ impl DisplayMode for Oscilloscope {
if self.peaks { if self.peaks {
out.push(DataSet::new( out.push(DataSet::new(
"".into(), None,
vec![(0.0, min), (0.0, max)], vec![(0.0, min), (0.0, max)],
cfg.marker_type, cfg.marker_type,
GraphType::Scatter, GraphType::Scatter,
@ -103,7 +103,7 @@ impl DisplayMode for Oscilloscope {
} }
out.push(DataSet::new( out.push(DataSet::new(
self.channel_name(n), Some(self.channel_name(n)),
tmp, tmp,
cfg.marker_type, cfg.marker_type,
if cfg.scatter { GraphType::Scatter } else { GraphType::Line }, if cfg.scatter { GraphType::Scatter } else { GraphType::Line },

View file

@ -115,11 +115,12 @@ impl DisplayMode for Spectroscope {
if self.window { if self.window {
chunk = hann_window(chunk.as_slice()); chunk = hann_window(chunk.as_slice());
} }
let max_val = chunk.iter().max_by(|a, b| a.total_cmp(b)).expect("empty dataset?"); let mut max_val = *chunk.iter().max_by(|a, b| a.total_cmp(b)).expect("empty dataset?");
let mut tmp : Vec<Complex<f64>> = chunk.iter().map(|x| Complex { re: *x / *max_val, im: 0.0 }).collect(); if max_val < 1. { max_val = 1.; }
let mut tmp : Vec<Complex<f64>> = chunk.iter().map(|x| Complex { re: *x / max_val, im: 0.0 }).collect();
fft.process(tmp.as_mut_slice()); fft.process(tmp.as_mut_slice());
out.push(DataSet::new( out.push(DataSet::new(
self.channel_name(n), Some(self.channel_name(n)),
tmp[..=tmp.len() / 2] tmp[..=tmp.len() / 2]
.iter() .iter()
.enumerate() .enumerate()
@ -149,37 +150,37 @@ impl DisplayMode for Spectroscope {
fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> { fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
let s = if self.log_y { (cfg.scale as f64 / 10.0).ln() } else { cfg.scale as f64 / 10.0 }; let s = if self.log_y { (cfg.scale as f64 / 10.0).ln() } else { cfg.scale as f64 / 10.0 };
vec![ vec![
DataSet::new("".into(), vec![(0.0, 0.0), ((cfg.samples as f64).ln(), 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(0.0, 0.0), ((cfg.samples as f64).ln(), 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color),
// TODO can we auto generate these? lol... // TODO can we auto generate these? lol...
DataSet::new("".into(), vec![(20.0f64.ln(), 0.0), (20.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(20.0f64.ln(), 0.0), (20.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(30.0f64.ln(), 0.0), (30.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(30.0f64.ln(), 0.0), (30.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(40.0f64.ln(), 0.0), (40.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(40.0f64.ln(), 0.0), (40.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(50.0f64.ln(), 0.0), (50.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(50.0f64.ln(), 0.0), (50.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(60.0f64.ln(), 0.0), (60.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(60.0f64.ln(), 0.0), (60.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(70.0f64.ln(), 0.0), (70.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(70.0f64.ln(), 0.0), (70.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(80.0f64.ln(), 0.0), (80.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(80.0f64.ln(), 0.0), (80.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(90.0f64.ln(), 0.0), (90.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(90.0f64.ln(), 0.0), (90.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(100.0f64.ln(), 0.0), (100.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(100.0f64.ln(), 0.0), (100.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(200.0f64.ln(), 0.0), (200.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(200.0f64.ln(), 0.0), (200.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(300.0f64.ln(), 0.0), (300.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(300.0f64.ln(), 0.0), (300.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(400.0f64.ln(), 0.0), (400.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(400.0f64.ln(), 0.0), (400.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(500.0f64.ln(), 0.0), (500.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(500.0f64.ln(), 0.0), (500.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(600.0f64.ln(), 0.0), (600.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(600.0f64.ln(), 0.0), (600.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(700.0f64.ln(), 0.0), (700.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(700.0f64.ln(), 0.0), (700.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(800.0f64.ln(), 0.0), (800.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(800.0f64.ln(), 0.0), (800.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(900.0f64.ln(), 0.0), (900.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(900.0f64.ln(), 0.0), (900.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(1000.0f64.ln(), 0.0), (1000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(1000.0f64.ln(), 0.0), (1000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(2000.0f64.ln(), 0.0), (2000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(2000.0f64.ln(), 0.0), (2000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(3000.0f64.ln(), 0.0), (3000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(3000.0f64.ln(), 0.0), (3000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(4000.0f64.ln(), 0.0), (4000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(4000.0f64.ln(), 0.0), (4000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(5000.0f64.ln(), 0.0), (5000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(5000.0f64.ln(), 0.0), (5000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(6000.0f64.ln(), 0.0), (6000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(6000.0f64.ln(), 0.0), (6000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(7000.0f64.ln(), 0.0), (7000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(7000.0f64.ln(), 0.0), (7000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(8000.0f64.ln(), 0.0), (8000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(8000.0f64.ln(), 0.0), (8000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(9000.0f64.ln(), 0.0), (9000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(9000.0f64.ln(), 0.0), (9000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(10000.0f64.ln(), 0.0), (10000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(10000.0f64.ln(), 0.0), (10000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(20000.0f64.ln(), 0.0), (20000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(20000.0f64.ln(), 0.0), (20000.0f64.ln(), s)], cfg.marker_type, GraphType::Line, cfg.axis_color),
] ]
} }
} }

View file

@ -36,8 +36,8 @@ impl DisplayMode for Vectorscope {
fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> { fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
vec![ vec![
DataSet::new("".into(), vec![(-(cfg.scale as f64), 0.0), (cfg.scale as f64, 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(-(cfg.scale as f64), 0.0), (cfg.scale as f64, 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color),
DataSet::new("".into(), vec![(0.0, -(cfg.scale as f64)), (0.0, cfg.scale as f64)], cfg.marker_type, GraphType::Line, cfg.axis_color), DataSet::new(None, vec![(0.0, -(cfg.scale as f64)), (0.0, cfg.scale as f64)], cfg.marker_type, GraphType::Line, cfg.axis_color),
] ]
} }
@ -65,14 +65,14 @@ impl DisplayMode for Vectorscope {
// TODO configure splitting in multiple parts? // TODO configure splitting in multiple parts?
let pivot = tmp.len() / 2; let pivot = tmp.len() / 2;
out.push(DataSet::new( out.push(DataSet::new(
self.channel_name((n * 2) + 1), Some(self.channel_name((n * 2) + 1)),
tmp[pivot..].to_vec(), tmp[pivot..].to_vec(),
cfg.marker_type, cfg.marker_type,
if cfg.scatter { GraphType::Scatter } else { GraphType::Line }, if cfg.scatter { GraphType::Scatter } else { GraphType::Line },
cfg.palette((n * 2) + 1), cfg.palette((n * 2) + 1),
)); ));
out.push(DataSet::new( out.push(DataSet::new(
self.channel_name(n * 2), Some(self.channel_name(n * 2)),
tmp[..pivot].to_vec(), tmp[..pivot].to_vec(),
cfg.marker_type, cfg.marker_type,
if cfg.scatter { GraphType::Scatter } else { GraphType::Line }, if cfg.scatter { GraphType::Scatter } else { GraphType::Line },