use std::time::Duration;
use color_eyre::Result;
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
use itertools::Itertools;
use rand::{rng, Rng};
use ratatui::{DefaultTerminal, Frame};
use tui_equalizer::{Band, Equalizer};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
fn run(mut terminal: DefaultTerminal) -> Result<()> {
let width = terminal.size()?.width;
let mut current_bands = random_bands(width);
let mut next_bands = random_bands(width);
let mut last_time = std::time::Instant::now();
const UPDATE_INTERVAL: Duration = Duration::from_millis(500);
loop {
let percent = last_time.elapsed().as_secs_f64() / UPDATE_INTERVAL.as_secs_f64();
let interpolated = interpolate(¤t_bands, &next_bands, percent);
if percent >= 1.0 {
last_time = std::time::Instant::now();
current_bands = interpolated.clone();
next_bands = random_bands(width);
}
terminal.draw(|frame| draw(frame, ¤t_bands, &interpolated))?;
if handle_input()? == Command::Quit {
break Ok(());
}
}
}
fn interpolate(current: &Vec<Band>, next: &Vec<Band>, percent: f64) -> Vec<Band> {
let interpolated = current
.iter()
.zip(next.iter())
.map(|(current, next)| Band {
value: current.value + (next.value - current.value) * percent.clamp(0.0, 1.0),
})
.collect_vec();
interpolated
}
fn random_bands(count: u16) -> Vec<Band> {
(0..count / 2)
.map(|_| Band::from(rng().random_range(0.1..1.0)))
.collect_vec()
}
fn draw(frame: &mut Frame, current: &[Band], bands: &[Band]) {
let size = frame.area();
frame.render_widget(
Equalizer {
bands: current.to_vec(),
brightness: 0.15,
},
size,
);
frame.render_widget(
Equalizer {
bands: bands.to_vec(),
brightness: 1.0,
},
size,
);
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum Command {
Noop,
Quit,
}
fn handle_input() -> Result<Command> {
if !event::poll(Duration::from_secs_f64(1.0 / 60.0))? {
return Ok(Command::Noop);
}
match event::read()? {
Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
KeyCode::Char('q') => Ok(Command::Quit),
_ => Ok(Command::Noop),
},
_ => Ok(Command::Noop),
}
}