From 70fc3c97d10106a89ed50197e69c362528bd1102 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 9 Nov 2024 19:50:22 +0100 Subject: [PATCH] wip: refactor into api and app --- Cargo.lock | 22 +++ Cargo.toml | 4 +- crates/tek_api/Cargo.toml | 8 + .../sequencer_edn.rs => tek_api/README.md} | 0 .../examples/mixer.edn} | 0 .../examples/sequencer.edn} | 0 crates/tek_api/src/api_cmd.rs | 143 ++++++++++++++++ crates/tek_api/src/api_edn.rs | 158 ++++++++++++++++++ crates/tek_api/src/api_midi.rs | 28 ++++ crates/tek_api/src/lib.rs | 6 + crates/{tek_mixer => tek_app}/Cargo.toml | 15 +- crates/{tek_sequencer => tek_app}/README.md | 22 +++ .../src/arranger.rs | 0 .../src/arranger_cli.rs | 0 .../src/arranger_cmd.rs | 6 +- .../src/arranger_snd.rs | 0 .../src/arranger_tui.rs | 0 .../src/arranger_tui_bar.rs | 0 .../src/arranger_tui_cmd.rs | 4 +- .../src/arranger_tui_col.rs | 0 .../src/arranger_tui_hor.rs | 0 .../src/arranger_tui_ver.rs | 0 crates/tek_app/src/lib.rs | 45 +++++ crates/{tek_mixer => tek_app}/src/mixer.rs | 0 .../{tek_mixer => tek_app}/src/mixer_cli.rs | 0 .../{tek_mixer => tek_app}/src/mixer_cmd.rs | 0 .../{tek_mixer => tek_app}/src/mixer_snd.rs | 0 .../{tek_mixer => tek_app}/src/mixer_tui.rs | 0 crates/{tek_mixer => tek_app}/src/plugin.rs | 0 .../{tek_mixer => tek_app}/src/plugin_cli.rs | 0 .../{tek_mixer => tek_app}/src/plugin_cmd.rs | 0 .../{tek_mixer => tek_app}/src/plugin_lv2.rs | 0 .../src/plugin_lv2_gui.rs | 0 .../{tek_mixer => tek_app}/src/plugin_snd.rs | 0 .../{tek_mixer => tek_app}/src/plugin_tui.rs | 0 .../{tek_mixer => tek_app}/src/plugin_vst2.rs | 0 .../{tek_mixer => tek_app}/src/plugin_vst3.rs | 0 crates/{tek_mixer => tek_app}/src/sampler.rs | 0 .../{tek_mixer => tek_app}/src/sampler_cli.rs | 0 .../{tek_mixer => tek_app}/src/sampler_cmd.rs | 0 .../{tek_mixer => tek_app}/src/sampler_snd.rs | 0 .../{tek_mixer => tek_app}/src/sampler_tui.rs | 0 .../src/sequencer.rs | 0 .../src/sequencer_cli.rs | 0 .../src/sequencer_cmd.rs | 0 .../src/sequencer_snd.rs | 0 .../src/sequencer_tui.rs | 0 .../{tek_mixer => tek_app}/src/track_cli.rs | 0 .../src/transport.rs | 0 .../src/transport_cli.rs | 0 .../src/transport_cmd.rs | 0 .../src/transport_snd.rs | 0 .../src/transport_tui.rs | 0 crates/tek_mixer/README.md | 15 -- crates/tek_mixer/src/lib.rs | 16 -- crates/tek_mixer/src/mixer_edn.rs | 54 ------ crates/tek_mixer/src/plugin_edn.rs | 20 --- crates/tek_mixer/src/sampler_edn.rs | 60 ------- crates/tek_sequencer/Cargo.toml | 23 --- crates/tek_sequencer/src/arranger_edn.rs | 27 --- crates/tek_sequencer/src/lib.rs | 32 ---- 61 files changed, 453 insertions(+), 255 deletions(-) create mode 100644 crates/tek_api/Cargo.toml rename crates/{tek_sequencer/src/sequencer_edn.rs => tek_api/README.md} (100%) rename crates/{tek_mixer/example.edn => tek_api/examples/mixer.edn} (100%) rename crates/{tek_sequencer/example.edn => tek_api/examples/sequencer.edn} (100%) create mode 100644 crates/tek_api/src/api_cmd.rs create mode 100644 crates/tek_api/src/api_edn.rs create mode 100644 crates/tek_api/src/api_midi.rs create mode 100644 crates/tek_api/src/lib.rs rename crates/{tek_mixer => tek_app}/Cargo.toml (70%) rename crates/{tek_sequencer => tek_app}/README.md (62%) rename crates/{tek_sequencer => tek_app}/src/arranger.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_cli.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_cmd.rs (96%) rename crates/{tek_sequencer => tek_app}/src/arranger_snd.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui_bar.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui_cmd.rs (97%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui_col.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui_hor.rs (100%) rename crates/{tek_sequencer => tek_app}/src/arranger_tui_ver.rs (100%) create mode 100644 crates/tek_app/src/lib.rs rename crates/{tek_mixer => tek_app}/src/mixer.rs (100%) rename crates/{tek_mixer => tek_app}/src/mixer_cli.rs (100%) rename crates/{tek_mixer => tek_app}/src/mixer_cmd.rs (100%) rename crates/{tek_mixer => tek_app}/src/mixer_snd.rs (100%) rename crates/{tek_mixer => tek_app}/src/mixer_tui.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_cli.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_cmd.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_lv2.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_lv2_gui.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_snd.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_tui.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_vst2.rs (100%) rename crates/{tek_mixer => tek_app}/src/plugin_vst3.rs (100%) rename crates/{tek_mixer => tek_app}/src/sampler.rs (100%) rename crates/{tek_mixer => tek_app}/src/sampler_cli.rs (100%) rename crates/{tek_mixer => tek_app}/src/sampler_cmd.rs (100%) rename crates/{tek_mixer => tek_app}/src/sampler_snd.rs (100%) rename crates/{tek_mixer => tek_app}/src/sampler_tui.rs (100%) rename crates/{tek_sequencer => tek_app}/src/sequencer.rs (100%) rename crates/{tek_sequencer => tek_app}/src/sequencer_cli.rs (100%) rename crates/{tek_sequencer => tek_app}/src/sequencer_cmd.rs (100%) rename crates/{tek_sequencer => tek_app}/src/sequencer_snd.rs (100%) rename crates/{tek_sequencer => tek_app}/src/sequencer_tui.rs (100%) rename crates/{tek_mixer => tek_app}/src/track_cli.rs (100%) rename crates/{tek_sequencer => tek_app}/src/transport.rs (100%) rename crates/{tek_sequencer => tek_app}/src/transport_cli.rs (100%) rename crates/{tek_sequencer => tek_app}/src/transport_cmd.rs (100%) rename crates/{tek_sequencer => tek_app}/src/transport_snd.rs (100%) rename crates/{tek_sequencer => tek_app}/src/transport_tui.rs (100%) delete mode 100644 crates/tek_mixer/README.md delete mode 100644 crates/tek_mixer/src/lib.rs delete mode 100644 crates/tek_mixer/src/mixer_edn.rs delete mode 100644 crates/tek_mixer/src/plugin_edn.rs delete mode 100644 crates/tek_mixer/src/sampler_edn.rs delete mode 100644 crates/tek_sequencer/Cargo.toml delete mode 100644 crates/tek_sequencer/src/arranger_edn.rs delete mode 100644 crates/tek_sequencer/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 6cf29f30..4c9cc5c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2657,6 +2657,28 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "tek_api" +version = "0.1.0" +dependencies = [ + "tek_core", + "uuid", +] + +[[package]] +name = "tek_app" +version = "0.1.0" +dependencies = [ + "livi", + "suil-rs", + "symphonia", + "tek_api", + "tek_core", + "vst", + "wavers", + "winit", +] + [[package]] name = "tek_core" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 821084a1..66f78292 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,6 @@ resolver = "2" members = [ "crates/tek_core", - "crates/tek_mixer", - "crates/tek_sequencer" + "crates/tek_api", + "crates/tek_app" ] diff --git a/crates/tek_api/Cargo.toml b/crates/tek_api/Cargo.toml new file mode 100644 index 00000000..23d70e54 --- /dev/null +++ b/crates/tek_api/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tek_api" +edition = "2021" +version = "0.1.0" + +[dependencies] +tek_core = { path = "../tek_core" } +uuid = { version = "1.10.0", features = [ "v4" ] } diff --git a/crates/tek_sequencer/src/sequencer_edn.rs b/crates/tek_api/README.md similarity index 100% rename from crates/tek_sequencer/src/sequencer_edn.rs rename to crates/tek_api/README.md diff --git a/crates/tek_mixer/example.edn b/crates/tek_api/examples/mixer.edn similarity index 100% rename from crates/tek_mixer/example.edn rename to crates/tek_api/examples/mixer.edn diff --git a/crates/tek_sequencer/example.edn b/crates/tek_api/examples/sequencer.edn similarity index 100% rename from crates/tek_sequencer/example.edn rename to crates/tek_api/examples/sequencer.edn diff --git a/crates/tek_api/src/api_cmd.rs b/crates/tek_api/src/api_cmd.rs new file mode 100644 index 00000000..9bfd2c44 --- /dev/null +++ b/crates/tek_api/src/api_cmd.rs @@ -0,0 +1,143 @@ +use crate::*; + +#[derive(Clone)] +pub enum ArrangerCommand { + Focus(FocusCommand), + Transport(TransportCommand), + Phrases(PhrasePoolCommand), + Editor(PhraseEditorCommand), + Arrangement(ArrangementCommand), + EditPhrase(Option>>), +} + +#[derive(Clone)] +pub enum ArrangementCommand { + New, + Load, + Save, + ToggleViewMode, + Delete, + Activate, + Increment, + Decrement, + ZoomIn, + ZoomOut, + Go(Direction), + Edit(Option>>), + Scene(SceneCommand), + Track(TrackCommand), + Clip(ClipCommand), +} + +#[derive(Clone)] +pub enum SceneCommand { + Next, + Prev, + Add, + Delete, + MoveForward, + MoveBack, + RandomColor, + SetSize(usize), + SetZoom(usize), +} + +#[derive(Clone)] +pub enum TrackCommand { + Next, + Prev, + Add, + Delete, + MoveForward, + MoveBack, + RandomColor, + SetSize(usize), + SetZoom(usize), +} + +#[derive(Clone)] +pub enum ClipCommand { + SetLoop(bool), + Get(usize, usize), + Put(usize, usize, Option>>), + Edit(Option>>), +} + +#[derive(Clone, PartialEq)] +pub enum SequencerCommand { + Focus(FocusCommand), + Transport(TransportCommand), + Phrases(PhrasePoolCommand), + Editor(PhraseEditorCommand), +} + +#[derive(Clone, PartialEq)] +pub enum PhrasePoolCommand { + Prev, + Next, + MoveUp, + MoveDown, + Delete, + Append, + Insert, + Duplicate, + RandomColor, + Edit, + Import, + Export, + Rename(PhraseRenameCommand), + Length(PhraseLengthCommand), +} + +#[derive(Clone, PartialEq)] +pub enum PhraseRenameCommand { + Begin, + Backspace, + Append(char), + Set(String), + Confirm, + Cancel, +} + +#[derive(Clone, PartialEq)] +pub enum PhraseLengthCommand { + Begin, + Next, + Prev, + Inc, + Dec, + Set(usize), + Confirm, + Cancel, +} + +#[derive(Clone, PartialEq)] +pub enum PhraseEditorCommand { + // TODO: 1-9 seek markers that by default start every 8th of the phrase + ToggleDirection, + EnterEditMode, + ExitEditMode, + NoteAppend, + NoteSet, + NoteCursorSet(usize), + NoteLengthSet(usize), + NoteScrollSet(usize), + TimeCursorSet(usize), + TimeScrollSet(usize), + TimeZoomSet(usize), + Go(Direction), +} + +#[derive(Copy, Clone, PartialEq)] +pub enum TransportCommand { + FocusNext, + FocusPrev, + Play(Option), + Pause(Option), + SeekUsec(f64), + SeekSample(f64), + SeekPulse(f64), + SetBpm(f64), + SetQuant(f64), + SetSync(f64), +} diff --git a/crates/tek_api/src/api_edn.rs b/crates/tek_api/src/api_edn.rs new file mode 100644 index 00000000..b7f5b0ac --- /dev/null +++ b/crates/tek_api/src/api_edn.rs @@ -0,0 +1,158 @@ +use crate::*; + +impl Scene { + pub fn from_edn <'a, 'e> (args: &[Edn<'e>]) -> Usually { + let mut name = None; + let mut clips = vec![]; + edn!(edn in args { + Edn::Map(map) => { + let key = map.get(&Edn::Key(":name")); + if let Some(Edn::Str(n)) = key { + name = Some(*n); + } else { + panic!("unexpected key in scene '{name:?}': {key:?}") + } + }, + Edn::Symbol("_") => { + clips.push(None); + }, + Edn::Int(i) => { + clips.push(Some(*i as usize)); + }, + _ => panic!("unexpected in scene '{name:?}': {edn:?}") + }); + let scene = Self::new(name.unwrap_or(""), clips); + Ok(scene) + } +} + +const SYM_NAME: &'static str = ":name"; +const SYM_GAIN: &'static str = ":gain"; +const SYM_SAMPLER: &'static str = "sampler"; +const SYM_LV2: &'static str = "lv2"; + +impl Track { + pub fn from_edn <'a, 'e> (jack: &Arc>, args: &[Edn<'e>]) -> Usually { + let mut _gain = 0.0f64; + let mut track = Self::new("")?; + #[allow(unused_mut)] + let mut devices: Vec> = vec![]; + edn!(edn in args { + Edn::Map(map) => { + if let Some(Edn::Str(n)) = map.get(&Edn::Key(SYM_NAME)) { + track.name = n.to_string(); + } + if let Some(Edn::Double(g)) = map.get(&Edn::Key(SYM_GAIN)) { + _gain = f64::from(*g); + } + }, + Edn::List(args) => match args.get(0) { + // Add a sampler device to the track + Some(Edn::Symbol(SYM_SAMPLER)) => { + devices.push(Sampler::from_edn(jack, &args[1..])?); + panic!( + "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"sampler\"", + &track.name, + args.get(0).unwrap() + ) + }, + // Add a LV2 plugin to the track. + Some(Edn::Symbol(SYM_LV2)) => { + devices.push(LV2Plugin::from_edn(jack, &args[1..])?); + panic!( + "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"plugin\"", + &track.name, + args.get(0).unwrap() + ) + }, + None => + panic!("empty list track {}", &track.name), + _ => + panic!("unexpected in track {}: {:?}", &track.name, args.get(0).unwrap()) + }, + _ => {} + }); + for device in devices { + track.add_device(device); + } + Ok(track) + } +} + +impl LV2Plugin { + pub fn from_edn <'e, E: Engine> (jack: &Arc>, args: &[Edn<'e>]) -> Usually> { + let mut name = String::new(); + let mut path = String::new(); + edn!(edn in args { + Edn::Map(map) => { + if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { + name = String::from(*n); + } + if let Some(Edn::Str(p)) = map.get(&Edn::Key(":path")) { + path = String::from(*p); + } + }, + _ => panic!("unexpected in lv2 '{name}'"), + }); + Plugin::new_lv2(jack, &name, &path) + } +} + +impl Sampler { + pub fn from_edn <'e> (jack: &Arc>, args: &[Edn<'e>]) -> Usually> { + let mut name = String::new(); + let mut dir = String::new(); + let mut samples = BTreeMap::new(); + edn!(edn in args { + Edn::Map(map) => { + if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { + name = String::from(*n); + } + if let Some(Edn::Str(n)) = map.get(&Edn::Key(":dir")) { + dir = String::from(*n); + } + }, + Edn::List(args) => match args.get(0) { + Some(Edn::Symbol("sample")) => { + let (midi, sample) = Sample::from_edn(jack, &dir, &args[1..])?; + if let Some(midi) = midi { + samples.insert(midi, sample); + } else { + panic!("sample without midi binding: {}", sample.read().unwrap().name); + } + }, + _ => panic!("unexpected in sampler {name}: {args:?}") + }, + _ => panic!("unexpected in sampler {name}: {edn:?}") + }); + Self::new(jack, &name, Some(samples)) + } +} + +impl Sample { + pub fn from_edn <'e> (jack: &Arc>, dir: &str, args: &[Edn<'e>]) -> Usually<(Option, Arc>)> { + let mut name = String::new(); + let mut file = String::new(); + let mut midi = None; + let mut start = 0usize; + edn!(edn in args { + Edn::Map(map) => { + if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { + name = String::from(*n); + } + if let Some(Edn::Str(f)) = map.get(&Edn::Key(":file")) { + file = String::from(*f); + } + if let Some(Edn::Int(i)) = map.get(&Edn::Key(":start")) { + start = *i as usize; + } + if let Some(Edn::Int(m)) = map.get(&Edn::Key(":midi")) { + midi = Some(u7::from(*m as u8)); + } + }, + _ => panic!("unexpected in sample {name}"), + }); + let (end, data) = read_sample_data(&format!("{dir}/{file}"))?; + Ok((midi, Arc::new(RwLock::new(Self::new(&name, start, end, data))))) + } +} diff --git a/crates/tek_api/src/api_midi.rs b/crates/tek_api/src/api_midi.rs new file mode 100644 index 00000000..ff984c64 --- /dev/null +++ b/crates/tek_api/src/api_midi.rs @@ -0,0 +1,28 @@ +use crate::*; +pub(crate) use tek_core::midly::MidiMessage; + +/// MIDI message structural +pub type PhraseData = Vec>; + +/// A MIDI sequence. +#[derive(Debug, Clone)] pub struct Phrase { + pub uuid: uuid::Uuid, + /// Name of phrase + pub name: String, + /// Temporal resolution in pulses per quarter note + pub ppq: usize, + /// Length of phrase in pulses + pub length: usize, + /// Notes in phrase + pub notes: PhraseData, + /// Whether to loop the phrase or play it once + pub loop_on: bool, + /// Start of loop + pub loop_start: usize, + /// Length of loop + pub loop_length: usize, + /// All notes are displayed with minimum length + pub percussive: bool, + /// Identifying color of phrase + pub color: ItemColorTriplet, +} diff --git a/crates/tek_api/src/lib.rs b/crates/tek_api/src/lib.rs new file mode 100644 index 00000000..f909690f --- /dev/null +++ b/crates/tek_api/src/lib.rs @@ -0,0 +1,6 @@ +pub(crate) use tek_core::*; +submod! { + api_cmd + api_edn + api_midi +} diff --git a/crates/tek_mixer/Cargo.toml b/crates/tek_app/Cargo.toml similarity index 70% rename from crates/tek_mixer/Cargo.toml rename to crates/tek_app/Cargo.toml index 173895f8..2e82a635 100644 --- a/crates/tek_mixer/Cargo.toml +++ b/crates/tek_app/Cargo.toml @@ -1,10 +1,11 @@ [package] -name = "tek_mixer" +name = "tek_app" edition = "2021" version = "0.1.0" [dependencies] tek_core = { path = "../tek_core" } +tek_api = { path = "../tek_api" } livi = "0.7.4" suil-rs = { path = "../suil" } @@ -32,3 +33,15 @@ path = "src/sampler_cli.rs" [[bin]] name = "tek_plugin" path = "src/plugin_cli.rs" + +[[bin]] +name = "tek_sequencer" +path = "src/sequencer_cli.rs" + +[[bin]] +name = "tek_arranger" +path = "src/arranger_cli.rs" + +[[bin]] +name = "tek_transport" +path = "src/transport_cli.rs" diff --git a/crates/tek_sequencer/README.md b/crates/tek_app/README.md similarity index 62% rename from crates/tek_sequencer/README.md rename to crates/tek_app/README.md index 80c49196..5aa30847 100644 --- a/crates/tek_sequencer/README.md +++ b/crates/tek_app/README.md @@ -21,3 +21,25 @@ This crate implements time sync and JACK transport control. * Todo: edit numeric values * Todo: jump to time/bbt markers * Todo: count xruns + +--- + +# `tek_mixer` + +// TODO: +// - Meters: propagate clipping: +// - If one stage clips, all stages after it are marked red +// - If one track clips, all tracks that feed from it are marked red? + +# `tek_track` + +--- + +# `tek_sampler` + +This crate implements a sampler device which plays audio files +in response to MIDI notes. + +--- + +# `tek_plugin` diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_app/src/arranger.rs similarity index 100% rename from crates/tek_sequencer/src/arranger.rs rename to crates/tek_app/src/arranger.rs diff --git a/crates/tek_sequencer/src/arranger_cli.rs b/crates/tek_app/src/arranger_cli.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_cli.rs rename to crates/tek_app/src/arranger_cli.rs diff --git a/crates/tek_sequencer/src/arranger_cmd.rs b/crates/tek_app/src/arranger_cmd.rs similarity index 96% rename from crates/tek_sequencer/src/arranger_cmd.rs rename to crates/tek_app/src/arranger_cmd.rs index 2ee8fab0..eaeaa9cc 100644 --- a/crates/tek_sequencer/src/arranger_cmd.rs +++ b/crates/tek_app/src/arranger_cmd.rs @@ -9,7 +9,7 @@ pub enum ArrangerCommand { Arrangement(ArrangementCommand), EditPhrase(Option>>), } -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub enum ArrangementCommand { New, Load, @@ -33,7 +33,7 @@ pub enum ArrangementCommand { GoDown, GoLeft, GoRight, - Edit, + Edit(Option>>), } impl Command> for ArrangerCommand { @@ -75,7 +75,7 @@ impl Command> for ArrangementCommand { New => todo!(), Load => todo!(), Save => todo!(), - Edit => todo!(), + Edit(phrase) => { state.phrase = phrase.clone() }, ToggleViewMode => { state.mode.to_next(); }, Delete => { state.delete(); }, Activate => { state.activate(); }, diff --git a/crates/tek_sequencer/src/arranger_snd.rs b/crates/tek_app/src/arranger_snd.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_snd.rs rename to crates/tek_app/src/arranger_snd.rs diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_app/src/arranger_tui.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_tui.rs rename to crates/tek_app/src/arranger_tui.rs diff --git a/crates/tek_sequencer/src/arranger_tui_bar.rs b/crates/tek_app/src/arranger_tui_bar.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_tui_bar.rs rename to crates/tek_app/src/arranger_tui_bar.rs diff --git a/crates/tek_sequencer/src/arranger_tui_cmd.rs b/crates/tek_app/src/arranger_tui_cmd.rs similarity index 97% rename from crates/tek_sequencer/src/arranger_tui_cmd.rs rename to crates/tek_app/src/arranger_tui_cmd.rs index 6ecc01b6..563f2778 100644 --- a/crates/tek_sequencer/src/arranger_tui_cmd.rs +++ b/crates/tek_app/src/arranger_tui_cmd.rs @@ -78,7 +78,7 @@ impl Handle for Arrangement { } impl InputToCommand> for ArrangementCommand { - fn input_to_command (_: &Arrangement, input: &TuiInput) -> Option { + fn input_to_command (state: &Arrangement, input: &TuiInput) -> Option { use ArrangementCommand::*; match input.event() { key!(KeyCode::Char('`')) => Some(ToggleViewMode), @@ -95,7 +95,7 @@ impl InputToCommand> for ArrangementCommand { key!(KeyCode::Char('c')) => Some(RandomColor), key!(KeyCode::Char('s')) => Some(Put), key!(KeyCode::Char('g')) => Some(Get), - key!(KeyCode::Char('e')) => Some(Edit), + key!(KeyCode::Char('e')) => Some(Edit(state.phrase())), key!(Ctrl-KeyCode::Char('a')) => Some(AddScene), key!(Ctrl-KeyCode::Char('t')) => Some(AddTrack), key!(KeyCode::Char('l')) => Some(ToggleLoop), diff --git a/crates/tek_sequencer/src/arranger_tui_col.rs b/crates/tek_app/src/arranger_tui_col.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_tui_col.rs rename to crates/tek_app/src/arranger_tui_col.rs diff --git a/crates/tek_sequencer/src/arranger_tui_hor.rs b/crates/tek_app/src/arranger_tui_hor.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_tui_hor.rs rename to crates/tek_app/src/arranger_tui_hor.rs diff --git a/crates/tek_sequencer/src/arranger_tui_ver.rs b/crates/tek_app/src/arranger_tui_ver.rs similarity index 100% rename from crates/tek_sequencer/src/arranger_tui_ver.rs rename to crates/tek_app/src/arranger_tui_ver.rs diff --git a/crates/tek_app/src/lib.rs b/crates/tek_app/src/lib.rs new file mode 100644 index 00000000..5b96d426 --- /dev/null +++ b/crates/tek_app/src/lib.rs @@ -0,0 +1,45 @@ +pub(crate) use tek_core::*; +pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers}; +pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; +pub(crate) use tek_core::jack::*; + +pub(crate) use std::collections::BTreeMap; +pub(crate) use std::sync::{Arc, Mutex, RwLock}; +pub(crate) use std::path::PathBuf; +pub(crate) use std::ffi::OsString; +pub(crate) use std::fs::read_dir; + +submod! { + arranger + arranger_cmd + arranger_snd + arranger_tui + arranger_tui_bar + arranger_tui_cmd + arranger_tui_col + arranger_tui_hor + arranger_tui_ver + sequencer + sequencer_cmd + sequencer_snd + sequencer_tui + transport + transport_cmd + transport_snd + transport_tui + mixer + mixer_snd + mixer_cmd + mixer_tui + sampler + sampler_snd + sampler_cmd + plugin + plugin_snd + plugin_cmd + plugin_tui + plugin_lv2 + plugin_lv2_gui + plugin_vst2 + plugin_vst3 +} diff --git a/crates/tek_mixer/src/mixer.rs b/crates/tek_app/src/mixer.rs similarity index 100% rename from crates/tek_mixer/src/mixer.rs rename to crates/tek_app/src/mixer.rs diff --git a/crates/tek_mixer/src/mixer_cli.rs b/crates/tek_app/src/mixer_cli.rs similarity index 100% rename from crates/tek_mixer/src/mixer_cli.rs rename to crates/tek_app/src/mixer_cli.rs diff --git a/crates/tek_mixer/src/mixer_cmd.rs b/crates/tek_app/src/mixer_cmd.rs similarity index 100% rename from crates/tek_mixer/src/mixer_cmd.rs rename to crates/tek_app/src/mixer_cmd.rs diff --git a/crates/tek_mixer/src/mixer_snd.rs b/crates/tek_app/src/mixer_snd.rs similarity index 100% rename from crates/tek_mixer/src/mixer_snd.rs rename to crates/tek_app/src/mixer_snd.rs diff --git a/crates/tek_mixer/src/mixer_tui.rs b/crates/tek_app/src/mixer_tui.rs similarity index 100% rename from crates/tek_mixer/src/mixer_tui.rs rename to crates/tek_app/src/mixer_tui.rs diff --git a/crates/tek_mixer/src/plugin.rs b/crates/tek_app/src/plugin.rs similarity index 100% rename from crates/tek_mixer/src/plugin.rs rename to crates/tek_app/src/plugin.rs diff --git a/crates/tek_mixer/src/plugin_cli.rs b/crates/tek_app/src/plugin_cli.rs similarity index 100% rename from crates/tek_mixer/src/plugin_cli.rs rename to crates/tek_app/src/plugin_cli.rs diff --git a/crates/tek_mixer/src/plugin_cmd.rs b/crates/tek_app/src/plugin_cmd.rs similarity index 100% rename from crates/tek_mixer/src/plugin_cmd.rs rename to crates/tek_app/src/plugin_cmd.rs diff --git a/crates/tek_mixer/src/plugin_lv2.rs b/crates/tek_app/src/plugin_lv2.rs similarity index 100% rename from crates/tek_mixer/src/plugin_lv2.rs rename to crates/tek_app/src/plugin_lv2.rs diff --git a/crates/tek_mixer/src/plugin_lv2_gui.rs b/crates/tek_app/src/plugin_lv2_gui.rs similarity index 100% rename from crates/tek_mixer/src/plugin_lv2_gui.rs rename to crates/tek_app/src/plugin_lv2_gui.rs diff --git a/crates/tek_mixer/src/plugin_snd.rs b/crates/tek_app/src/plugin_snd.rs similarity index 100% rename from crates/tek_mixer/src/plugin_snd.rs rename to crates/tek_app/src/plugin_snd.rs diff --git a/crates/tek_mixer/src/plugin_tui.rs b/crates/tek_app/src/plugin_tui.rs similarity index 100% rename from crates/tek_mixer/src/plugin_tui.rs rename to crates/tek_app/src/plugin_tui.rs diff --git a/crates/tek_mixer/src/plugin_vst2.rs b/crates/tek_app/src/plugin_vst2.rs similarity index 100% rename from crates/tek_mixer/src/plugin_vst2.rs rename to crates/tek_app/src/plugin_vst2.rs diff --git a/crates/tek_mixer/src/plugin_vst3.rs b/crates/tek_app/src/plugin_vst3.rs similarity index 100% rename from crates/tek_mixer/src/plugin_vst3.rs rename to crates/tek_app/src/plugin_vst3.rs diff --git a/crates/tek_mixer/src/sampler.rs b/crates/tek_app/src/sampler.rs similarity index 100% rename from crates/tek_mixer/src/sampler.rs rename to crates/tek_app/src/sampler.rs diff --git a/crates/tek_mixer/src/sampler_cli.rs b/crates/tek_app/src/sampler_cli.rs similarity index 100% rename from crates/tek_mixer/src/sampler_cli.rs rename to crates/tek_app/src/sampler_cli.rs diff --git a/crates/tek_mixer/src/sampler_cmd.rs b/crates/tek_app/src/sampler_cmd.rs similarity index 100% rename from crates/tek_mixer/src/sampler_cmd.rs rename to crates/tek_app/src/sampler_cmd.rs diff --git a/crates/tek_mixer/src/sampler_snd.rs b/crates/tek_app/src/sampler_snd.rs similarity index 100% rename from crates/tek_mixer/src/sampler_snd.rs rename to crates/tek_app/src/sampler_snd.rs diff --git a/crates/tek_mixer/src/sampler_tui.rs b/crates/tek_app/src/sampler_tui.rs similarity index 100% rename from crates/tek_mixer/src/sampler_tui.rs rename to crates/tek_app/src/sampler_tui.rs diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_app/src/sequencer.rs similarity index 100% rename from crates/tek_sequencer/src/sequencer.rs rename to crates/tek_app/src/sequencer.rs diff --git a/crates/tek_sequencer/src/sequencer_cli.rs b/crates/tek_app/src/sequencer_cli.rs similarity index 100% rename from crates/tek_sequencer/src/sequencer_cli.rs rename to crates/tek_app/src/sequencer_cli.rs diff --git a/crates/tek_sequencer/src/sequencer_cmd.rs b/crates/tek_app/src/sequencer_cmd.rs similarity index 100% rename from crates/tek_sequencer/src/sequencer_cmd.rs rename to crates/tek_app/src/sequencer_cmd.rs diff --git a/crates/tek_sequencer/src/sequencer_snd.rs b/crates/tek_app/src/sequencer_snd.rs similarity index 100% rename from crates/tek_sequencer/src/sequencer_snd.rs rename to crates/tek_app/src/sequencer_snd.rs diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_app/src/sequencer_tui.rs similarity index 100% rename from crates/tek_sequencer/src/sequencer_tui.rs rename to crates/tek_app/src/sequencer_tui.rs diff --git a/crates/tek_mixer/src/track_cli.rs b/crates/tek_app/src/track_cli.rs similarity index 100% rename from crates/tek_mixer/src/track_cli.rs rename to crates/tek_app/src/track_cli.rs diff --git a/crates/tek_sequencer/src/transport.rs b/crates/tek_app/src/transport.rs similarity index 100% rename from crates/tek_sequencer/src/transport.rs rename to crates/tek_app/src/transport.rs diff --git a/crates/tek_sequencer/src/transport_cli.rs b/crates/tek_app/src/transport_cli.rs similarity index 100% rename from crates/tek_sequencer/src/transport_cli.rs rename to crates/tek_app/src/transport_cli.rs diff --git a/crates/tek_sequencer/src/transport_cmd.rs b/crates/tek_app/src/transport_cmd.rs similarity index 100% rename from crates/tek_sequencer/src/transport_cmd.rs rename to crates/tek_app/src/transport_cmd.rs diff --git a/crates/tek_sequencer/src/transport_snd.rs b/crates/tek_app/src/transport_snd.rs similarity index 100% rename from crates/tek_sequencer/src/transport_snd.rs rename to crates/tek_app/src/transport_snd.rs diff --git a/crates/tek_sequencer/src/transport_tui.rs b/crates/tek_app/src/transport_tui.rs similarity index 100% rename from crates/tek_sequencer/src/transport_tui.rs rename to crates/tek_app/src/transport_tui.rs diff --git a/crates/tek_mixer/README.md b/crates/tek_mixer/README.md deleted file mode 100644 index c0288a1d..00000000 --- a/crates/tek_mixer/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# `tek_mixer` - -// TODO: -// - Meters: propagate clipping: -// - If one stage clips, all stages after it are marked red -// - If one track clips, all tracks that feed from it are marked red? - -# `tek_track` - -# `tek_sampler` - -This crate implements a sampler device which plays audio files -in response to MIDI notes. - -# `tek_plugin` diff --git a/crates/tek_mixer/src/lib.rs b/crates/tek_mixer/src/lib.rs deleted file mode 100644 index d8facd29..00000000 --- a/crates/tek_mixer/src/lib.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub(crate) use tek_core::*; -pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers}; -pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; -pub(crate) use tek_core::jack::*; - -pub(crate) use std::collections::BTreeMap; -pub(crate) use std::sync::{Arc, Mutex, RwLock}; -pub(crate) use std::path::PathBuf; -pub(crate) use std::ffi::OsString; -pub(crate) use std::fs::read_dir; - -submod! { - mixer mixer_snd mixer_edn mixer_cmd mixer_tui - sampler sampler_snd sampler_edn sampler_cmd - plugin plugin_snd plugin_edn plugin_cmd plugin_tui plugin_lv2 plugin_lv2_gui plugin_vst2 plugin_vst3 -} diff --git a/crates/tek_mixer/src/mixer_edn.rs b/crates/tek_mixer/src/mixer_edn.rs deleted file mode 100644 index 6533df13..00000000 --- a/crates/tek_mixer/src/mixer_edn.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::*; - -const SYM_NAME: &'static str = ":name"; -const SYM_GAIN: &'static str = ":gain"; -const SYM_SAMPLER: &'static str = "sampler"; -const SYM_LV2: &'static str = "lv2"; - -impl Track { - pub fn from_edn <'a, 'e> (jack: &Arc>, args: &[Edn<'e>]) -> Usually { - let mut _gain = 0.0f64; - let mut track = Self::new("")?; - #[allow(unused_mut)] - let mut devices: Vec> = vec![]; - edn!(edn in args { - Edn::Map(map) => { - if let Some(Edn::Str(n)) = map.get(&Edn::Key(SYM_NAME)) { - track.name = n.to_string(); - } - if let Some(Edn::Double(g)) = map.get(&Edn::Key(SYM_GAIN)) { - _gain = f64::from(*g); - } - }, - Edn::List(args) => match args.get(0) { - // Add a sampler device to the track - Some(Edn::Symbol(SYM_SAMPLER)) => { - devices.push(Sampler::from_edn(jack, &args[1..])?); - panic!( - "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"sampler\"", - &track.name, - args.get(0).unwrap() - ) - }, - // Add a LV2 plugin to the track. - Some(Edn::Symbol(SYM_LV2)) => { - devices.push(LV2Plugin::from_edn(jack, &args[1..])?); - panic!( - "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"plugin\"", - &track.name, - args.get(0).unwrap() - ) - }, - None => - panic!("empty list track {}", &track.name), - _ => - panic!("unexpected in track {}: {:?}", &track.name, args.get(0).unwrap()) - }, - _ => {} - }); - for device in devices { - track.add_device(device); - } - Ok(track) - } -} diff --git a/crates/tek_mixer/src/plugin_edn.rs b/crates/tek_mixer/src/plugin_edn.rs deleted file mode 100644 index 9dc6299f..00000000 --- a/crates/tek_mixer/src/plugin_edn.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::*; - -impl LV2Plugin { - pub fn from_edn <'e, E: Engine> (jack: &Arc>, args: &[Edn<'e>]) -> Usually> { - let mut name = String::new(); - let mut path = String::new(); - edn!(edn in args { - Edn::Map(map) => { - if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { - name = String::from(*n); - } - if let Some(Edn::Str(p)) = map.get(&Edn::Key(":path")) { - path = String::from(*p); - } - }, - _ => panic!("unexpected in lv2 '{name}'"), - }); - Plugin::new_lv2(jack, &name, &path) - } -} diff --git a/crates/tek_mixer/src/sampler_edn.rs b/crates/tek_mixer/src/sampler_edn.rs deleted file mode 100644 index 26ba8994..00000000 --- a/crates/tek_mixer/src/sampler_edn.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::*; - -impl Sampler { - pub fn from_edn <'e> (jack: &Arc>, args: &[Edn<'e>]) -> Usually> { - let mut name = String::new(); - let mut dir = String::new(); - let mut samples = BTreeMap::new(); - edn!(edn in args { - Edn::Map(map) => { - if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { - name = String::from(*n); - } - if let Some(Edn::Str(n)) = map.get(&Edn::Key(":dir")) { - dir = String::from(*n); - } - }, - Edn::List(args) => match args.get(0) { - Some(Edn::Symbol("sample")) => { - let (midi, sample) = Sample::from_edn(jack, &dir, &args[1..])?; - if let Some(midi) = midi { - samples.insert(midi, sample); - } else { - panic!("sample without midi binding: {}", sample.read().unwrap().name); - } - }, - _ => panic!("unexpected in sampler {name}: {args:?}") - }, - _ => panic!("unexpected in sampler {name}: {edn:?}") - }); - Self::new(jack, &name, Some(samples)) - } -} - -impl Sample { - pub fn from_edn <'e> (jack: &Arc>, dir: &str, args: &[Edn<'e>]) -> Usually<(Option, Arc>)> { - let mut name = String::new(); - let mut file = String::new(); - let mut midi = None; - let mut start = 0usize; - edn!(edn in args { - Edn::Map(map) => { - if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) { - name = String::from(*n); - } - if let Some(Edn::Str(f)) = map.get(&Edn::Key(":file")) { - file = String::from(*f); - } - if let Some(Edn::Int(i)) = map.get(&Edn::Key(":start")) { - start = *i as usize; - } - if let Some(Edn::Int(m)) = map.get(&Edn::Key(":midi")) { - midi = Some(u7::from(*m as u8)); - } - }, - _ => panic!("unexpected in sample {name}"), - }); - let (end, data) = read_sample_data(&format!("{dir}/{file}"))?; - Ok((midi, Arc::new(RwLock::new(Self::new(&name, start, end, data))))) - } -} diff --git a/crates/tek_sequencer/Cargo.toml b/crates/tek_sequencer/Cargo.toml deleted file mode 100644 index 461b18bc..00000000 --- a/crates/tek_sequencer/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "tek_sequencer" -edition = "2021" -version = "0.1.0" - -[dependencies] -tek_core = { path = "../tek_core" } -uuid = { version = "1.10.0", features = [ "v4" ] } - -[lib] -path = "src/lib.rs" - -[[bin]] -name = "tek_sequencer" -path = "src/sequencer_cli.rs" - -[[bin]] -name = "tek_arranger" -path = "src/arranger_cli.rs" - -[[bin]] -name = "tek_transport" -path = "src/transport_cli.rs" diff --git a/crates/tek_sequencer/src/arranger_edn.rs b/crates/tek_sequencer/src/arranger_edn.rs deleted file mode 100644 index 5d192e04..00000000 --- a/crates/tek_sequencer/src/arranger_edn.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::*; - -impl Scene { - pub fn from_edn <'a, 'e> (args: &[Edn<'e>]) -> Usually { - let mut name = None; - let mut clips = vec![]; - edn!(edn in args { - Edn::Map(map) => { - let key = map.get(&Edn::Key(":name")); - if let Some(Edn::Str(n)) = key { - name = Some(*n); - } else { - panic!("unexpected key in scene '{name:?}': {key:?}") - } - }, - Edn::Symbol("_") => { - clips.push(None); - }, - Edn::Int(i) => { - clips.push(Some(*i as usize)); - }, - _ => panic!("unexpected in scene '{name:?}': {edn:?}") - }); - let scene = Self::new(name.unwrap_or(""), clips); - Ok(scene) - } -} diff --git a/crates/tek_sequencer/src/lib.rs b/crates/tek_sequencer/src/lib.rs deleted file mode 100644 index 2ed8a4f6..00000000 --- a/crates/tek_sequencer/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -/// Phrase editor. - -pub(crate) use tek_core::*; -pub(crate) use tek_core::crossterm::event::KeyCode; -pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; -pub(crate) use tek_core::jack::*; -pub(crate) use std::sync::{Arc, RwLock}; - -submod! { - arranger - arranger_cmd - arranger_snd - arranger_tui - arranger_tui_bar - arranger_tui_cmd - arranger_tui_col - arranger_tui_hor - arranger_tui_ver - sequencer - sequencer_cmd - sequencer_snd - sequencer_tui - transport - transport_cmd - transport_snd - transport_tui -} - -/// Octave number (from -1 to 9) -pub const NTH_OCTAVE: [&'static str;11] = [ - "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" -];