panic hook; two sequencers

This commit is contained in:
🪞👃🪞 2024-06-07 15:37:27 +03:00
parent 0ee9e58dc7
commit abee6cc2c8
16 changed files with 927 additions and 828 deletions

View file

@ -25,49 +25,52 @@ pub enum Event {
}
pub struct Engine {
exited: Arc<AtomicBool>,
sender: Sender<Event>,
receiver: Receiver<Event>,
exited: Arc<AtomicBool>,
sender: Sender<Event>,
receiver: Receiver<Event>,
pub jack_client: Jack<Notifications>,
}
pub fn jack_client <N: NotificationHandler + Sync + 'static> (
name: &str,
pub fn activate_jack_client <N: NotificationHandler + Sync + 'static> (
client: Client,
notifications: N,
handler: BoxedProcessHandler
handler: BoxedProcessHandler
) -> Result<Jack<N>, Box<dyn Error>> {
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
Ok(client.activate_async(notifications, ClosureProcessHandler::new(handler))?)
}
pub trait Component: Exitable + WidgetRef + HandleInput + Send + 'static {}
impl<T: Exitable + WidgetRef + HandleInput + Send + 'static> Component for T {}
impl Engine {
pub fn new (name: Option<&str>) -> Result<Self, Box<dyn Error>> {
let (sender, receiver) = mpsc::channel::<self::Event>();
let exited = Arc::new(AtomicBool::new(false));
let (client, _status) = Client::new(name.unwrap_or("engine"), ClientOptions::NO_START_SERVER)?;
Ok(Self {
jack_client: jack_client(
name.unwrap_or("blinkenlive"),
Notifications(sender.clone()),
Box::new({
let sender = sender.clone();
let exited = exited.clone();
move |_client: &Client, _ps: &ProcessScope| -> Control {
if exited.fetch_and(true, Ordering::Relaxed) {
Control::Quit
} else {
sender.send(Event::Update).unwrap();
Control::Continue
}
}}))?,
exited,
sender,
receiver,
sender: sender.clone(),
exited: exited.clone(),
jack_client: activate_jack_client(
client,
Notifications(sender.clone()),
Box::new(move |_client: &Client, _ps: &ProcessScope| -> Control {
if exited.fetch_and(true, Ordering::Relaxed) {
Control::Quit
} else {
sender.send(Event::Update).unwrap();
Control::Continue
}
})
)?
})
}
pub fn run <T: Exitable + WidgetRef + HandleInput + Send + 'static> (
&mut self, mut state: T,
pub fn run (
&mut self,
mut state: impl Component,
) -> Result<(), Box<dyn Error>> {
let state = Arc::new(Mutex::new(state));
@ -93,29 +96,28 @@ impl Engine {
})
};
let render_thread = {
stdout().queue(EnterAlternateScreen)?.flush()?;
enable_raw_mode()?;
let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))?;
let sleep = std::time::Duration::from_millis(16);
let exited = self.exited.clone();
spawn(move || loop {
terminal.draw(|frame|{
let area = frame.size();
frame.render_widget(
&*state.lock().unwrap(),
area
);
});
if state.lock().unwrap().exited() {
exited.store(true, Ordering::Relaxed);
break
}
std::thread::sleep(sleep);
})
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))?;
let sleep = std::time::Duration::from_millis(16);
let exited = self.exited.clone();
std::panic::set_hook(Box::new(panic_hook));
loop {
terminal.draw(|frame|{
let area = frame.size();
frame.render_widget(
&*state.lock().unwrap(),
area
);
}).expect("Failed to render frame");
if state.lock().unwrap().exited() {
exited.store(true, Ordering::Relaxed);
break
}
std::thread::sleep(sleep);
};
render_thread.join();
//render_thread.join().expect("Failed to join render thread");
stdout()
.queue(crossterm::terminal::LeaveAlternateScreen)?
@ -127,6 +129,16 @@ impl Engine {
}
fn panic_hook (info: &std::panic::PanicInfo) {
stdout()
.execute(crossterm::terminal::LeaveAlternateScreen)
.unwrap();
crossterm::terminal::disable_raw_mode()
.unwrap();
writeln!(std::io::stderr(), "{}", info);
writeln!(std::io::stderr(), "{:?}", ::backtrace::Backtrace::new());
}
pub struct Notifications(mpsc::Sender<self::Event>);
impl NotificationHandler for Notifications {