From f347ca838b3ff325d0566203eee2a22682ec8a88 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 13 Jul 2024 16:26:27 +0300 Subject: [PATCH] add Justfile and tweak things --- Justfile | 6 +++ src/main.rs | 63 +++++++++++++++--------------- src/model.rs | 89 +++++++++++++++++++++++-------------------- src/model/track.rs | 3 +- src/view/transport.rs | 20 +++++----- 5 files changed, 95 insertions(+), 86 deletions(-) create mode 100644 Justfile diff --git a/Justfile b/Justfile new file mode 100644 index 00000000..9db61252 --- /dev/null +++ b/Justfile @@ -0,0 +1,6 @@ +default: + just -l +status: + cargo c + cloc --by-file src/ + git status diff --git a/src/main.rs b/src/main.rs index 24bd17f4..b5697f94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,40 +17,37 @@ use crate::{core::*, model::*}; /// Application entrypoint. pub fn main () -> Usually<()> { - run(App::from_edn(include_str!("../demos/project.edn"))?.activate(Some(|app: &Arc>| { - - let (midi_in, mut midi_outs) = { - let app = app.read().unwrap(); - let jack = app.jack.as_ref().unwrap(); - let midi_in = jack.register_port("midi-in", MidiIn)?; - let midi_outs = app.arranger.tracks.iter() - .map(|t|Some(jack.register_port(&t.name, MidiOut).unwrap())) - .collect::>(); - (midi_in, midi_outs) - }; - - { - let mut app = app.write().unwrap(); - let jack = app.jack.as_ref().unwrap(); - for name in app.midi_ins.iter() { - for port in jack.client().ports(Some(name), None, PortFlags::empty()).iter() { - if let Some(port) = jack.client().port_by_name(port) { - jack.client().connect_ports(&port, &midi_in)?; + run(App::from_edn(include_str!("../demos/project.edn"))? + .activate(Some(|app: &Arc>|Ok({ + let (midi_in, mut midi_outs) = { + let app = app.read().unwrap(); + let jack = app.jack.as_ref().unwrap(); + let midi_in = jack.register_port("midi-in", MidiIn)?; + let midi_outs = app.arranger.tracks.iter() + .map(|t|Some(jack.register_port(&t.name, MidiOut).unwrap())) + .collect::>(); + (midi_in, midi_outs) + }; + { + let mut app = app.write().unwrap(); + let jack = app.jack.as_ref().unwrap(); + for name in app.midi_ins.iter() { + let ports = jack.client().ports(Some(name), None, PortFlags::empty()); + for port in ports.iter() { + if let Some(port) = jack.client().port_by_name(port) { + jack.client().connect_ports(&port, &midi_in)?; + } } } - } - app.midi_in = Some(Arc::new(midi_in)); - for (index, track) in app.arranger.tracks.iter_mut().enumerate() { - track.midi_out = midi_outs[index].take(); - } - for track in app.arranger.tracks.iter() { - track.connect_first_device()?; - track.connect_last_device(&app)?; - } - } - - Ok(()) - - }))?)?; + app.midi_in = Some(Arc::new(midi_in)); + for (index, track) in app.arranger.tracks.iter_mut().enumerate() { + track.midi_out = midi_outs[index].take(); + } + for track in app.arranger.tracks.iter() { + track.connect_first_device()?; + track.connect_last_device(&app)?; + } + }; + })))?)?; Ok(()) } diff --git a/src/model.rs b/src/model.rs index ee9160dd..bf760d9f 100644 --- a/src/model.rs +++ b/src/model.rs @@ -6,41 +6,42 @@ use crate::{core::*, view::*}; /// Root of application state. pub struct App { + /// Optional modal dialog + pub modal: Option>, + /// Whether the currently focused section has input priority + pub entered: bool, + /// Currently focused section + pub section: AppFocus, + /// Transport model and view. + pub transport: TransportToolbar, + /// Arraneger model and view. + pub arranger: Arranger, /// Main JACK client. - pub jack: Option, + pub jack: Option, /// Map of external MIDI outs in the jack graph /// to internal MIDI ins of this app. - pub midi_in: Option>>, + pub midi_in: Option>>, /// Names of ports to connect to main MIDI IN. - pub midi_ins: Vec, + pub midi_ins: Vec, /// Display mode of chain section - pub chain_mode: bool, - /// Display mode of sequencer seciton - pub seq_mode: bool, - /// Display buffer for sequencer - pub seq_buf: BufferedSequencerView, - /// Optional modal dialog - pub modal: Option>, - /// Display position of cursor within note range - pub note_cursor: usize, - /// Range of notes to display - pub note_start: usize, - /// Display position of cursor within time range - pub time_cursor: usize, + pub chain_mode: bool, /// Paths to user directories - xdg: Option>, + xdg: Option>, /// Main audio outputs. - pub audio_outs: Vec>>, + pub audio_outs: Vec>>, /// Number of frames requested by process callback - chunk_size: usize, - /// Transport model and view. - pub transport: TransportToolbar, - /// Arraneger model and view. - pub arranger: Arranger, - /// Currently focused section - pub section: AppFocus, - /// Whether the current focus section has input priority - pub entered: bool, + chunk_size: usize, + + /// Display mode of sequencer seciton + pub seq_mode: bool, + /// Display buffer for sequencer + pub seq_buf: BufferedSequencerView, + /// Display position of cursor within note range + pub note_cursor: usize, + /// Range of notes to display + pub note_start: usize, + /// Display position of cursor within time range + pub time_cursor: usize, } impl App { @@ -49,25 +50,27 @@ impl App { let first_run = crate::config::AppPaths::new(&xdg)?.should_create(); let jack = JackClient::Inactive(Client::new("tek", ClientOptions::NO_START_SERVER)?.0); Ok(Self { - transport: TransportToolbar::new(Some(jack.transport())), - arranger: Arranger::new(), + modal: first_run.then(||{ + Exit::boxed(crate::config::SetupModal(Some(xdg.clone()), false)) + }), + + entered: true, + section: AppFocus::default(), + transport: TransportToolbar::new(Some(jack.transport())), + arranger: Arranger::new(), + jack: Some(jack), audio_outs: vec![], chain_mode: false, chunk_size: 0, - entered: true, - jack: Some(jack), - midi_in: None, - midi_ins: vec![], + midi_in: None, + midi_ins: vec![], + xdg: Some(xdg), + + seq_mode: false, + seq_buf: BufferedSequencerView::new(96, 16384), note_cursor: 0, - note_start: 2, - section: AppFocus::default(), - seq_mode: false, - seq_buf: BufferedSequencerView::new(96, 16384), + note_start: 2, time_cursor: 0, - modal: first_run.then( - ||Exit::boxed(crate::config::SetupModal(Some(xdg.clone()), false)) - ), - xdg: Some(xdg), }) } } @@ -133,9 +136,13 @@ impl App { /// Different sections of the UI that may be focused. #[derive(PartialEq, Clone, Copy)] pub enum AppFocus { + /// The transport is selected. Transport, + /// The arranger is selected. Arranger, + /// The sequencer is selected. Sequencer, + /// The device chain is selected. Chain, } diff --git a/src/model/track.rs b/src/model/track.rs index c7e47933..c24d5c49 100644 --- a/src/model/track.rs +++ b/src/model/track.rs @@ -22,8 +22,7 @@ pub struct Track { /// Device selector pub device: usize, /// Send all notes off - /// FIXME: Some(nframes)? - pub reset: bool, + pub reset: bool, // TODO?: after Some(nframes) /// Highlight keys on piano roll. pub notes_in: [bool;128], /// Highlight keys on piano roll. diff --git a/src/view/transport.rs b/src/view/transport.rs index 785558f4..14a4b615 100644 --- a/src/view/transport.rs +++ b/src/view/transport.rs @@ -1,16 +1,16 @@ use crate::{core::*,view::*,model::*}; render!(TransportToolbar |self, buf, area| { + let mut area = area; + area.height = 2; let gray = Style::default().gray(); let not_dim = Style::default().not_dim(); let not_dim_bold = not_dim.bold(); - - let mut area = area; - area.height = 2; - let ppq = self.ppq(); - let bpm = self.bpm(); - let pulse = self.pulse(); - let usecs = self.usecs(); + let corners = Corners(Style::default().green().not_dim()); + let ppq = self.ppq(); + let bpm = self.bpm(); + let pulse = self.pulse(); + let usecs = self.usecs(); let Self { quant, sync, focused, entered, .. } = self; fill_bg(buf, area, Nord::bg_lo(*focused, *entered)); Split::right([ @@ -40,7 +40,7 @@ render!(TransportToolbar |self, buf, area| { let width = format!("{}.{:03}", bpm, bpm % 1).blit(buf, x, y + 1, Some(not_dim_bold))?.width; let area = Rect { x, y, width: (width + 2).max(10), height: 2 }; if self.focused && self.entered && self.selected == TransportFocus::BPM { - Corners(Style::default().green().not_dim()).draw(buf, Rect { x: area.x - 1, ..area })?; + corners.draw(buf, Rect { x: area.x - 1, ..area })?; } Ok(area) }, @@ -51,7 +51,7 @@ render!(TransportToolbar |self, buf, area| { let width = ppq_to_name(*quant).blit(buf, x, y + 1, Some(not_dim_bold))?.width; let area = Rect { x, y, width: (width + 2).max(10), height: 2 }; if self.focused && self.entered && self.selected == TransportFocus::Quant { - Corners(Style::default().green().not_dim()).draw(buf, Rect { x: area.x - 1, ..area })?; + corners.draw(buf, Rect { x: area.x - 1, ..area })?; } Ok(area) }, @@ -62,7 +62,7 @@ render!(TransportToolbar |self, buf, area| { let width = ppq_to_name(*sync).blit(buf, x, y + 1, Some(not_dim_bold))?.width; let area = Rect { x, y, width: (width + 2).max(10), height: 2 }; if self.focused && self.entered && self.selected == TransportFocus::Sync { - Corners(Style::default().green().not_dim()).draw(buf, Rect { x: area.x - 1, ..area })?; + corners.draw(buf, Rect { x: area.x - 1, ..area })?; } Ok(area) },