use crate::dynamic::window_top_btm::pixel_buf::PixelBuf;
use minifb::{Window, WindowOptions};
use plotters::chart::{ChartBuilder, ChartState};
use plotters::coord::cartesian::Cartesian2d;
use plotters::coord::types::RangedCoordf64;
use plotters::coord::Shift;
use plotters::drawing::{DrawingArea, IntoDrawingArea};
use plotters::style::{IntoFont, WHITE};
use plotters_bitmap::bitmap_pixel::BGRXPixel;
use plotters_bitmap::BitMapBackend;
use std::borrow::{Borrow, BorrowMut};
use std::ops::Range;
pub const DEFAULT_W: usize = 1280;
pub const DEFAULT_H: usize = 720;
#[allow(clippy::type_complexity, clippy::too_many_arguments)]
pub fn setup_window(
name: &str,
preferred_height: Option<usize>,
preferred_width: Option<usize>,
preferred_x_range: Option<Range<f64>>,
preferred_y_range: Option<Range<f64>>,
x_desc: &str,
y_desc: &str,
audio_buffer_len: usize,
time_per_sample: f64,
) -> (
Window,
ChartState<Cartesian2d<RangedCoordf64, RangedCoordf64>>,
ChartState<Cartesian2d<RangedCoordf64, RangedCoordf64>>,
PixelBuf,
) {
let height = preferred_height.unwrap_or(DEFAULT_H);
let width = preferred_width.unwrap_or(DEFAULT_W);
let mut window =
Window::new(&String::from(name), width, height, WindowOptions::default()).unwrap();
let x_range_top = -(audio_buffer_len as f64 * time_per_sample)..0.0;
let y_range_top = -1.0..1.01;
let x_range_btm = preferred_x_range.unwrap_or_else(|| x_range_top.clone());
let y_range_btm = preferred_y_range.unwrap_or_else(|| y_range_top.clone());
let mut pixel_buf = PixelBuf(vec![0_u32; width * height]);
let (top_drawing_area, btm_drawing_area) =
get_drawing_areas(pixel_buf.borrow_mut(), width, height);
let top_chart = draw_chart(
top_drawing_area,
x_range_top,
y_range_top,
"time (seconds)",
"amplitude",
);
let btm_chart = draw_chart(btm_drawing_area, x_range_btm, y_range_btm, x_desc, y_desc);
window
.update_with_buffer(pixel_buf.borrow(), width, height)
.unwrap();
(window, top_chart, btm_chart, pixel_buf)
}
pub fn get_drawing_areas(
pixel_buf: &mut [u8],
width: usize,
height: usize,
) -> (
DrawingArea<BitMapBackend<BGRXPixel>, Shift>,
DrawingArea<BitMapBackend<BGRXPixel>, Shift>,
) {
let root_drawing_area = BitMapBackend::<BGRXPixel>::with_buffer_and_format(
pixel_buf.borrow_mut(),
(width as u32, height as u32),
)
.unwrap()
.into_drawing_area();
let (top_drawing_area, btm_drawing_area) =
root_drawing_area.split_vertically((height / 2) as f64);
(top_drawing_area, btm_drawing_area)
}
fn draw_chart<'a>(
drawing_area: DrawingArea<BitMapBackend<BGRXPixel>, Shift>,
x_range: Range<f64>,
y_range: Range<f64>,
x_desc: &'a str,
y_desc: &'a str,
) -> ChartState<Cartesian2d<RangedCoordf64, RangedCoordf64>> {
let mut chart = ChartBuilder::on(&drawing_area)
.margin(10)
.set_all_label_area_size(60)
.build_cartesian_2d(x_range, y_range)
.unwrap();
chart
.configure_mesh()
.label_style(("sans-serif", 15).into_font().color(&WHITE))
.x_desc(x_desc)
.y_desc(y_desc)
.x_labels(10)
.y_labels(10)
.axis_style(&WHITE)
.draw()
.unwrap();
chart.into_chart_state()
}
#[cfg(test)]
mod tests {
use minifb::Key;
#[ignore]
#[test]
fn test_minifb_window() {
let (mut window, _, _, _) = super::setup_window(
"Test",
None,
None,
Some(-5.0..0.0),
Some(0.0..5.01),
"x-axis",
"y-axis",
(44100 * 5_usize).next_power_of_two(),
1.0 / 44100.0,
);
while window.is_open() && !window.is_key_down(Key::Escape) {
window.update();
}
}
}