mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
panic hook; two sequencers
This commit is contained in:
parent
0ee9e58dc7
commit
abee6cc2c8
16 changed files with 927 additions and 828 deletions
104
src/engine.rs
104
src/engine.rs
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue