mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-04-03 21:00:44 +02:00
Compare commits
4 commits
cb17cdb8bc
...
7b8a48ad09
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b8a48ad09 | ||
|
|
49a5451af2 | ||
|
|
9b4f7f25c1 | ||
|
|
6411a82279 |
52 changed files with 62 additions and 47 deletions
8
.gitmodules
vendored
8
.gitmodules
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
|
|
||||||
72
app/tek.rs
72
app/tek.rs
|
|
@ -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
deps/tengri
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit ce2eeaee7fc23c3f3683cee310a9117d764409cb
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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::*;
|
||||||
|
|
|
||||||
|
|
@ -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:?}");
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
1
tengri
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 04db6f4af549012a4ffab3f06af3d2d6694cf811
|
||||||
0
deps/vst/.gitignore → vst/.gitignore
vendored
0
deps/vst/.gitignore → vst/.gitignore
vendored
Loading…
Add table
Add a link
Reference in a new issue