mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
134 lines
3.7 KiB
Rust
134 lines
3.7 KiB
Rust
pub use ratatui;
|
|
pub use crossterm;
|
|
pub use jack;
|
|
pub use midly;
|
|
pub use clap;
|
|
pub use std::sync::{Arc, Mutex, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
|
pub use std::collections::BTreeMap;
|
|
pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
|
|
pub use ratatui::prelude::{Rect, Style, Color, Buffer};
|
|
pub use ratatui::style::Stylize;
|
|
pub use clojure_reader::{edn::{read, Edn}, error::Error as EdnError};
|
|
pub use once_cell::sync::Lazy;
|
|
pub use std::sync::atomic::{Ordering, AtomicBool};
|
|
|
|
pub(crate) use std::error::Error;
|
|
pub(crate) use std::io::{stdout};
|
|
pub(crate) use std::thread::{spawn, JoinHandle};
|
|
pub(crate) use std::time::Duration;
|
|
pub(crate) use atomic_float::*;
|
|
//pub(crate) use std::path::PathBuf;
|
|
//pub(crate) use std::fs::read_dir;
|
|
//pub(crate) use std::ffi::OsString;
|
|
|
|
// Non-stdlib dependencies:
|
|
//pub(crate) use microxdg::XdgApp;
|
|
//pub(crate) use midly::{MidiMessage, live::LiveEvent, num::u7};
|
|
pub(crate) use crossterm::{ExecutableCommand};
|
|
use better_panic::{Settings, Verbosity};
|
|
use crossterm::terminal::{
|
|
EnterAlternateScreen, LeaveAlternateScreen,
|
|
enable_raw_mode, disable_raw_mode
|
|
};
|
|
|
|
/// Define and reexport submodules.
|
|
#[macro_export] macro_rules! submod {
|
|
($($name:ident)*) => { $(mod $name; pub use self::$name::*;)* };
|
|
}
|
|
|
|
/// Define and reexport public modules.
|
|
#[macro_export] macro_rules! pubmod {
|
|
($($name:ident)*) => { $(pub mod $name;)* };
|
|
}
|
|
|
|
submod! {
|
|
exit
|
|
handle
|
|
jack_core
|
|
jack_device
|
|
jack_event
|
|
jack_ports
|
|
render
|
|
render_axis
|
|
render_border
|
|
render_collect
|
|
render_fill
|
|
render_layered
|
|
render_split
|
|
render_theme
|
|
time_base
|
|
time_note
|
|
time_tick
|
|
}
|
|
|
|
/// EDN parsing helper.
|
|
#[macro_export] macro_rules! edn {
|
|
($edn:ident { $($pat:pat => $expr:expr),* $(,)? }) => {
|
|
match $edn { $($pat => $expr),* }
|
|
};
|
|
($edn:ident in $args:ident { $($pat:pat => $expr:expr),* $(,)? }) => {
|
|
for $edn in $args {
|
|
edn!($edn { $($pat => $expr),* })
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Standard result type.
|
|
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
|
|
|
/// A UI component.
|
|
pub trait Component: Render + Handle + Sync {
|
|
/// Perform type erasure for collecting heterogeneous components.
|
|
fn boxed (self) -> Box<dyn Component> where Self: Sized + 'static {
|
|
Box::new(self)
|
|
}
|
|
}
|
|
|
|
impl<T: Render + Handle + Sync> Component for T {}
|
|
|
|
/// Marker trait for [Component]s that can [Exit]
|
|
pub trait ExitableComponent: Exit + Component {
|
|
/// Perform type erasure for collecting heterogeneous components.
|
|
fn boxed (self) -> Box<dyn ExitableComponent> where Self: Sized + 'static {
|
|
Box::new(self)
|
|
}
|
|
}
|
|
|
|
impl<T: Exit + Component> ExitableComponent for T {}
|
|
|
|
/// Run the main loop.
|
|
pub fn run <T> (state: Arc<RwLock<T>>) -> Usually<Arc<RwLock<T>>>
|
|
where T: Render + Handle + Send + Sync + Sized + 'static
|
|
{
|
|
let exited = Arc::new(AtomicBool::new(false));
|
|
let _input_thread = input_thread(&exited, &state);
|
|
terminal_setup()?;
|
|
panic_hook_setup();
|
|
let main_thread = render_thread(&exited, &state)?;
|
|
main_thread.join().expect("main thread failed");
|
|
terminal_teardown()?;
|
|
Ok(state)
|
|
}
|
|
|
|
/// Set up panic hook
|
|
pub fn panic_hook_setup () {
|
|
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
|
|
std::panic::set_hook(Box::new(move |info: &std::panic::PanicInfo|{
|
|
stdout().execute(LeaveAlternateScreen).unwrap();
|
|
disable_raw_mode().unwrap();
|
|
better_panic_handler(info);
|
|
}));
|
|
}
|
|
|
|
/// Set up terminal
|
|
pub fn terminal_setup () -> Usually<()> {
|
|
stdout().execute(EnterAlternateScreen)?;
|
|
enable_raw_mode()?;
|
|
Ok(())
|
|
}
|
|
/// Cleanup
|
|
pub fn terminal_teardown () -> Usually<()> {
|
|
stdout().execute(LeaveAlternateScreen)?;
|
|
disable_raw_mode()?;
|
|
Ok(())
|
|
}
|