add Justfile and tweak things

This commit is contained in:
🪞👃🪞 2024-07-13 16:26:27 +03:00
parent a017d2ca51
commit f347ca838b
5 changed files with 95 additions and 86 deletions

6
Justfile Normal file
View file

@ -0,0 +1,6 @@
default:
just -l
status:
cargo c
cloc --by-file src/
git status

View file

@ -17,40 +17,37 @@ use crate::{core::*, model::*};
/// Application entrypoint. /// Application entrypoint.
pub fn main () -> Usually<()> { pub fn main () -> Usually<()> {
run(App::from_edn(include_str!("../demos/project.edn"))?.activate(Some(|app: &Arc<RwLock<App>>| { run(App::from_edn(include_str!("../demos/project.edn"))?
.activate(Some(|app: &Arc<RwLock<App>>|Ok({
let (midi_in, mut midi_outs) = { let (midi_in, mut midi_outs) = {
let app = app.read().unwrap(); let app = app.read().unwrap();
let jack = app.jack.as_ref().unwrap(); let jack = app.jack.as_ref().unwrap();
let midi_in = jack.register_port("midi-in", MidiIn)?; let midi_in = jack.register_port("midi-in", MidiIn)?;
let midi_outs = app.arranger.tracks.iter() let midi_outs = app.arranger.tracks.iter()
.map(|t|Some(jack.register_port(&t.name, MidiOut).unwrap())) .map(|t|Some(jack.register_port(&t.name, MidiOut).unwrap()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
(midi_in, midi_outs) (midi_in, midi_outs)
}; };
{
{ let mut app = app.write().unwrap();
let mut app = app.write().unwrap(); let jack = app.jack.as_ref().unwrap();
let jack = app.jack.as_ref().unwrap(); for name in app.midi_ins.iter() {
for name in app.midi_ins.iter() { let ports = jack.client().ports(Some(name), None, PortFlags::empty());
for port in jack.client().ports(Some(name), None, PortFlags::empty()).iter() { for port in ports.iter() {
if let Some(port) = jack.client().port_by_name(port) { if let Some(port) = jack.client().port_by_name(port) {
jack.client().connect_ports(&port, &midi_in)?; jack.client().connect_ports(&port, &midi_in)?;
}
} }
} }
} app.midi_in = Some(Arc::new(midi_in));
app.midi_in = Some(Arc::new(midi_in)); for (index, track) in app.arranger.tracks.iter_mut().enumerate() {
for (index, track) in app.arranger.tracks.iter_mut().enumerate() { track.midi_out = midi_outs[index].take();
track.midi_out = midi_outs[index].take(); }
} for track in app.arranger.tracks.iter() {
for track in app.arranger.tracks.iter() { track.connect_first_device()?;
track.connect_first_device()?; track.connect_last_device(&app)?;
track.connect_last_device(&app)?; }
} };
} })))?)?;
Ok(())
}))?)?;
Ok(()) Ok(())
} }

View file

@ -6,41 +6,42 @@ use crate::{core::*, view::*};
/// Root of application state. /// Root of application state.
pub struct App { pub struct App {
/// Optional modal dialog
pub modal: Option<Box<dyn Exit>>,
/// 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. /// Main JACK client.
pub jack: Option<JackClient>, pub jack: Option<JackClient>,
/// Map of external MIDI outs in the jack graph /// Map of external MIDI outs in the jack graph
/// to internal MIDI ins of this app. /// to internal MIDI ins of this app.
pub midi_in: Option<Arc<Port<MidiIn>>>, pub midi_in: Option<Arc<Port<MidiIn>>>,
/// Names of ports to connect to main MIDI IN. /// Names of ports to connect to main MIDI IN.
pub midi_ins: Vec<String>, pub midi_ins: Vec<String>,
/// Display mode of chain section /// Display mode of chain section
pub chain_mode: bool, 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<Box<dyn Exit>>,
/// 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,
/// Paths to user directories /// Paths to user directories
xdg: Option<Arc<XdgApp>>, xdg: Option<Arc<XdgApp>>,
/// Main audio outputs. /// Main audio outputs.
pub audio_outs: Vec<Arc<Port<Unowned>>>, pub audio_outs: Vec<Arc<Port<Unowned>>>,
/// Number of frames requested by process callback /// Number of frames requested by process callback
chunk_size: usize, chunk_size: usize,
/// Transport model and view.
pub transport: TransportToolbar, /// Display mode of sequencer seciton
/// Arraneger model and view. pub seq_mode: bool,
pub arranger: Arranger, /// Display buffer for sequencer
/// Currently focused section pub seq_buf: BufferedSequencerView,
pub section: AppFocus, /// Display position of cursor within note range
/// Whether the current focus section has input priority pub note_cursor: usize,
pub entered: bool, /// Range of notes to display
pub note_start: usize,
/// Display position of cursor within time range
pub time_cursor: usize,
} }
impl App { impl App {
@ -49,25 +50,27 @@ impl App {
let first_run = crate::config::AppPaths::new(&xdg)?.should_create(); let first_run = crate::config::AppPaths::new(&xdg)?.should_create();
let jack = JackClient::Inactive(Client::new("tek", ClientOptions::NO_START_SERVER)?.0); let jack = JackClient::Inactive(Client::new("tek", ClientOptions::NO_START_SERVER)?.0);
Ok(Self { Ok(Self {
transport: TransportToolbar::new(Some(jack.transport())), modal: first_run.then(||{
arranger: Arranger::new(), 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![], audio_outs: vec![],
chain_mode: false, chain_mode: false,
chunk_size: 0, chunk_size: 0,
entered: true, midi_in: None,
jack: Some(jack), midi_ins: vec![],
midi_in: None, xdg: Some(xdg),
midi_ins: vec![],
seq_mode: false,
seq_buf: BufferedSequencerView::new(96, 16384),
note_cursor: 0, note_cursor: 0,
note_start: 2, note_start: 2,
section: AppFocus::default(),
seq_mode: false,
seq_buf: BufferedSequencerView::new(96, 16384),
time_cursor: 0, 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. /// Different sections of the UI that may be focused.
#[derive(PartialEq, Clone, Copy)] #[derive(PartialEq, Clone, Copy)]
pub enum AppFocus { pub enum AppFocus {
/// The transport is selected.
Transport, Transport,
/// The arranger is selected.
Arranger, Arranger,
/// The sequencer is selected.
Sequencer, Sequencer,
/// The device chain is selected.
Chain, Chain,
} }

View file

@ -22,8 +22,7 @@ pub struct Track {
/// Device selector /// Device selector
pub device: usize, pub device: usize,
/// Send all notes off /// Send all notes off
/// FIXME: Some(nframes)? pub reset: bool, // TODO?: after Some(nframes)
pub reset: bool,
/// Highlight keys on piano roll. /// Highlight keys on piano roll.
pub notes_in: [bool;128], pub notes_in: [bool;128],
/// Highlight keys on piano roll. /// Highlight keys on piano roll.

View file

@ -1,16 +1,16 @@
use crate::{core::*,view::*,model::*}; use crate::{core::*,view::*,model::*};
render!(TransportToolbar |self, buf, area| { render!(TransportToolbar |self, buf, area| {
let mut area = area;
area.height = 2;
let gray = Style::default().gray(); let gray = Style::default().gray();
let not_dim = Style::default().not_dim(); let not_dim = Style::default().not_dim();
let not_dim_bold = not_dim.bold(); let not_dim_bold = not_dim.bold();
let corners = Corners(Style::default().green().not_dim());
let mut area = area; let ppq = self.ppq();
area.height = 2; let bpm = self.bpm();
let ppq = self.ppq(); let pulse = self.pulse();
let bpm = self.bpm(); let usecs = self.usecs();
let pulse = self.pulse();
let usecs = self.usecs();
let Self { quant, sync, focused, entered, .. } = self; let Self { quant, sync, focused, entered, .. } = self;
fill_bg(buf, area, Nord::bg_lo(*focused, *entered)); fill_bg(buf, area, Nord::bg_lo(*focused, *entered));
Split::right([ 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 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 }; let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
if self.focused && self.entered && self.selected == TransportFocus::BPM { 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) 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 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 }; let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
if self.focused && self.entered && self.selected == TransportFocus::Quant { 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) 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 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 }; let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
if self.focused && self.entered && self.selected == TransportFocus::Sync { 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) Ok(area)
}, },