trait Run

This commit is contained in:
🪞👃🪞 2024-07-02 22:25:33 +03:00
parent cc2b59d772
commit 3ae2467acc
11 changed files with 212 additions and 141 deletions

View file

@ -4,7 +4,7 @@ macro_rules! submod {
($($name:ident)*) => { $(mod $name; pub use self::$name::*;)* };
}
submod!( device handle jack keymap note port process render time );
submod!( device handle jack keymap port render run time );
pub use std::error::Error;
pub use std::io::{stdout, Stdout, Write};
@ -31,73 +31,3 @@ pub use ::crossterm::{
pub use ::ratatui::prelude::*;
pub use ::midly::{MidiMessage, live::LiveEvent, num::u7};
pub use crate::{key, keymap};
/// Run a device as the root of the app.
pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box<dyn Error>> {
let device = Arc::new(Mutex::new(device));
let exited = Arc::new(AtomicBool::new(false));
// Spawn input (handle) thread
let _input_thread = {
let poll = std::time::Duration::from_millis(100);
let exited = exited.clone();
let device = device.clone();
spawn(move || loop {
// Exit if flag is set
if exited.fetch_and(true, Ordering::Relaxed) {
break
}
// Listen for events and send them to the main thread
if ::crossterm::event::poll(poll).is_ok() {
let event = ::crossterm::event::read().unwrap();
match event {
Event::Key(KeyEvent {
code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL,
..
}) => {
exited.store(true, Ordering::Relaxed);
},
_ => if device.lock().unwrap().handle(&AppEvent::Input(event)).is_err() {
break
}
}
}
})
};
// Set up terminal
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))?;
// Set up panic hook
let better_panic_handler = better_panic::Settings::auto()
.verbosity(better_panic::Verbosity::Full)
.create_panic_handler();
std::panic::set_hook(Box::new(move |info: &std::panic::PanicInfo|{
stdout().execute(LeaveAlternateScreen).unwrap();
crossterm::terminal::disable_raw_mode().unwrap();
better_panic_handler(info);
}));
// Main (render) loop
let sleep = std::time::Duration::from_millis(16);
loop {
terminal.draw(|frame|{
let area = frame.size();
let buffer = frame.buffer_mut();
device.lock().unwrap().render(buffer, area).expect("Failed to render content.");
}).expect("Failed to render frame");
if exited.fetch_and(true, Ordering::Relaxed) {
break
}
std::thread::sleep(sleep);
};
// Cleanup
stdout().execute(LeaveAlternateScreen)?;
crossterm::terminal::disable_raw_mode()?;
Ok(())
}