Compare commits

..

4 commits

Author SHA1 Message Date
stop screaming
7b8a48ad09 shell: add cloc
Some checks are pending
/ build (push) Waiting to run
2026-02-20 16:38:10 +02:00
stop screaming
49a5451af2 refactor(app) what is UP with that init 2026-02-20 14:50:42 +02:00
stop screaming
9b4f7f25c1 refactor: decided i don't like the deps/ subdir any longer 2026-02-20 14:50:19 +02:00
stop screaming
6411a82279 fix: checks, tests 2026-02-20 14:25:35 +02:00
52 changed files with 62 additions and 47 deletions

8
.gitmodules vendored
View file

@ -3,11 +3,11 @@
url = https://codeberg.org/unspeaker/rust-jack url = https://codeberg.org/unspeaker/rust-jack
branch = timebase branch = timebase
[submodule "tengri"] [submodule "tengri"]
path = deps/tengri path = tengri
url = ../tengri/ url = https://codeberg.org/unspeaker/tengri
[submodule "deps/rust-jack"] [submodule "deps/rust-jack"]
path = deps/rust-jack path = rust-jack
url = https://codeberg.org/unspeaker/rust-jack url = https://codeberg.org/unspeaker/rust-jack
[submodule "deps/dizzle"] [submodule "deps/dizzle"]
path = deps/dizzle path = dizzle
url = ssh://git@codeberg.org/unspeaker/dizzle.git url = ssh://git@codeberg.org/unspeaker/dizzle.git

View file

@ -1,7 +1,7 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = [ "./app", "./engine", "./device" ] members = [ "./app", "./engine", "./device" ]
exclude = [ "./deps/tengri", "./deps/dizzle" ] exclude = [ "./tengri", "./dizzle" ]
[workspace.package] [workspace.package]
edition = "2024" edition = "2024"
@ -15,14 +15,14 @@ inherits = "test"
lto = false lto = false
[workspace.dependencies.tengri] [workspace.dependencies.tengri]
path = "./deps/tengri/tengri" path = "./tengri/tengri"
features = [ "tui", "dsl" ] features = [ "tui", "dsl" ]
[workspace.dependencies.tengri_proc] [workspace.dependencies.tengri_proc]
path = "./deps/tengri/proc" path = "./tengri/proc"
[workspace.dependencies.jack] [workspace.dependencies.jack]
path = "./deps/rust-jack" path = "./rust-jack"
[workspace.dependencies] [workspace.dependencies]
tek = { path = "./tek" } tek = { path = "./tek" }

View file

@ -908,50 +908,66 @@ pub mod glue {
midi_from, midi_from_re, midi_to, midi_to_re, midi_from, midi_from_re, midi_to, midi_to_re,
left_from, right_from, left_to, right_to, .. left_from, right_from, left_to, right_to, ..
} = &self.action { } = &self.action {
let name = name.as_ref().map_or("tek", |x|x.as_str());
let jack = Jack::new(&name)?; // Connect to JACK
let name = name.as_ref().map_or("tek", |x|x.as_str());
let jack = Jack::new(&name)?;
// Collect MIDI IO:
let midi_ins = Connect::collect(&midi_from, &[] as &[&str], &midi_from_re).iter().enumerate()
.map(|(index, connect)|jack.midi_in(&format!("M/{index}"), &[connect.clone()]))
.collect::<Result<Vec<_>, _>>()?;
let midi_outs = Connect::collect(&midi_to, &[] as &[&str], &midi_to_re).iter().enumerate()
.map(|(index, connect)|jack.midi_out(&format!("{index}/M"), &[connect.clone()]))
.collect::<Result<Vec<_>, _>>()?;
// TODO: Collect audio IO:
let empty = &[] as &[&str]; let empty = &[] as &[&str];
let left_froms = Connect::collect(&left_from, empty, empty); let left_froms = Connect::collect(&left_from, empty, empty);
let left_tos = Connect::collect(&left_to, empty, empty); let left_tos = Connect::collect(&left_to, empty, empty);
let right_froms = Connect::collect(&right_from, empty, empty); let right_froms = Connect::collect(&right_from, empty, empty);
let right_tos = Connect::collect(&right_to, empty, empty); let right_tos = Connect::collect(&right_to, empty, empty);
let _audio_froms = &[left_froms.as_slice(), right_froms.as_slice()]; let _audio_froms = &[left_froms.as_slice(), right_froms.as_slice()];
let _audio_tos = &[left_tos.as_slice(), right_tos.as_slice()]; let _audio_tos = &[left_tos.as_slice(), right_tos.as_slice()];
let mut midi_ins = vec![];
let mut midi_outs = vec![]; // Create initial project:
for (index, connect) in Connect::collect(&midi_from, &[] as &[&str], &midi_from_re).iter().enumerate() { let clock = Clock::new(&jack, *bpm)?;
midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?); let mut project = Arrangement::new(&jack, None, clock, vec![], vec![],
} midi_ins, midi_outs);
for (index, connect) in Connect::collect(&midi_to, &[] as &[&str], &midi_to_re).iter().enumerate() {
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
};
let clock = Clock::new(
&jack, *bpm
)?;
let mut project = Arrangement::new(
&jack, None, clock, vec![], vec![], midi_ins, midi_outs
);
project.tracks_add(tracks.unwrap_or(0), None, &[], &[])?; project.tracks_add(tracks.unwrap_or(0), None, &[], &[])?;
project.scenes_add(scenes.unwrap_or(0))?; project.scenes_add(scenes.unwrap_or(0))?;
if matches!(self.action, Action::Status) { if matches!(self.action, Action::Status) {
// Show status and exit
self.show_status(&project); self.show_status(&project);
} else { } else {
// Initialize the app state
let app = App::new(&jack, project, config, ":menu"); let app = App::new(&jack, project, config, ":menu");
let client = jack.run(move|jack|{
jack.sync_lead(*sync_lead, |mut state|{
let clock = app.clock();
clock.playhead.update_from_sample(state.position.frame() as f64);
state.position.bbt = Some(clock.bbt());
state.position
})?;
jack.sync_follow(*sync_follow)?;
Ok(app)
})?;
if matches!(self.action, Action::Headless) { if matches!(self.action, Action::Headless) {
// TODO: Headless mode (daemon + client over IPC, then over network...)
println!("todo headless"); println!("todo headless");
} else { } else {
Tui::run(&client)?;
// Run the [Tui] and [Jack] threads with the [App] state.
Tui::run(true, jack.run(move|jack|{
jack.sync_lead(*sync_lead, |mut state|{
let clock = app.clock();
clock.playhead.update_from_sample(state.position.frame() as f64);
state.position.bbt = Some(clock.bbt());
state.position
})?;
jack.sync_follow(*sync_follow)?;
Ok(app)
})?)?;
} }
} }
} }
Ok(()) Ok(())

1
deps/tengri vendored

@ -1 +0,0 @@
Subproject commit ce2eeaee7fc23c3f3683cee310a9117d764409cb

View file

@ -370,7 +370,7 @@ impl Arrangement {
} }
} }
pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> { pub fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
let left = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y(""))); let left = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y("")));
let right = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y(""))); let right = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y("")));
Bsp::e(left, Bsp::w(right, Tui::fg_bg(fg, bg, content))) Bsp::e(left, Bsp::w(right, Tui::fg_bg(fg, bg, content)))

View file

@ -292,7 +292,7 @@ pub fn view_status (
))) )))
} }
pub(crate) fn button_play_pause (playing: bool) -> impl Content<TuiOut> { pub fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
let compact = true;//self.is_editing(); let compact = true;//self.is_editing();
Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) }, Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
Either::new(compact, Either::new(compact,

View file

@ -1,5 +1,5 @@
//! ``` //! ```
//! let sample = Sample::new("test", 0, 0, vec![]); //! let sample = tek_device::Sample::new("test", 0, 0, vec![]);
//! ``` //! ```
use crate::*; use crate::*;

View file

@ -1,24 +1,22 @@
//! MIDI sequencer //! MIDI sequencer
//! ``` //! ```
//! use crate::*; //! let clip = tek_device::MidiClip::default();
//!
//! let clip = MidiClip::default();
//! println!("Empty clip: {clip:?}"); //! println!("Empty clip: {clip:?}");
//! //!
//! let clip = MidiClip::stop_all(); //! let clip = tek_device::MidiClip::stop_all();
//! println!("Panic clip: {clip:?}"); //! println!("Panic clip: {clip:?}");
//! //!
//! let mut clip = MidiClip::new("clip", true, 1, None, None); //! let mut clip = tek_device::MidiClip::new("clip", true, 1, None, None);
//! clip.set_length(96); //! clip.set_length(96);
//! clip.toggle_loop(); //! clip.toggle_loop();
//! clip.record_event(12, MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }); //! clip.record_event(12, midly::MidiMessage::NoteOn { key: 36.into(), vel: 100.into() });
//! assert!(clip.contains_note_on(36.into(), 6, 18)); //! assert!(clip.contains_note_on(36.into(), 6, 18));
//! assert_eq!(&clip.notes, &clip.duplicate().notes); //! assert_eq!(&clip.notes, &clip.duplicate().notes);
//! //!
//! let clip = std::sync::Arc::new(clip); //! let clip = std::sync::Arc::new(clip);
//! assert_eq!(clip.clone(), clip); //! assert_eq!(clip.clone(), clip);
//! //!
//! let sequencer = Sequencer::default(); //! let sequencer = tek_device::Sequencer::default();
//! println!("{sequencer:?}"); //! println!("{sequencer:?}");
//! ``` //! ```

View file

View file

@ -8,6 +8,7 @@
pkgs.freetype pkgs.freetype
pkgs.libclang pkgs.libclang
pkgs.mold pkgs.mold
pkgs.cloc
]; ];
buildInputs = [ buildInputs = [
pkgs.jack2 pkgs.jack2

1
tengri Submodule

@ -0,0 +1 @@
Subproject commit 04db6f4af549012a4ffab3f06af3d2d6694cf811