mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
Compare commits
7 commits
cdeb355972
...
6f6078e25a
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f6078e25a | |||
| e81ae58ab5 | |||
| ea48dd6fa1 | |||
| decbb177f0 | |||
| d1be569b48 | |||
| d647fc68e9 | |||
| ed926b9444 |
10 changed files with 85 additions and 52 deletions
4
Justfile
4
Justfile
|
|
@ -6,7 +6,7 @@ midi-in := "-i 'Midi-Bridge:.*nanoKEY.*:.*capture.*'"
|
|||
midi-out := "-o 'Midi-Bridge:.*playback.*'"
|
||||
audio-in := "-l 'Komplete Audio 6 Pro:capture_AUX1' -r 'Komplete Audio 6 Pro:capture_AUX1'"
|
||||
audio-out := "-L 'Komplete Audio 6 Pro:playback_AUX1' -R 'Komplete Audio 6 Pro:playback_AUX1'"
|
||||
firefox-in := "-l 'Firefox:output_FL' -r 'Firefox:output_FR'"
|
||||
firefox-in := "-l 'Firefox:output_FL*' -r 'Firefox:output_FR*'"
|
||||
covfig := "CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cov/cargo-test-%p-%m.profraw'"
|
||||
grcov-binary := "--binary-path ./target/coverage/deps/"
|
||||
grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
|
||||
|
|
@ -71,6 +71,8 @@ groovebox:
|
|||
groovebox-ext:
|
||||
reset
|
||||
{{debug}} {{name}} {{bpm}} {{midi-in}} {{midi-out}} {{audio-in}} {{audio-out}} groovebox
|
||||
groovebox-browser:
|
||||
{{debug}} {{name}} {{bpm}} {{audio-in}} groovebox
|
||||
groovebox-release:
|
||||
{{release}} {{name}} {{bpm}} groovebox
|
||||
groovebox-release-ext:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
(@left editor set-time-pos :time-pos-prev)
|
||||
(@shift-left editor set-time-pos :time-pos-prev-fine)
|
||||
(@right editor set-time-pos :time-pos-next)
|
||||
(@shift-right editor set-time-pos :time-pos-next-fine)
|
||||
|
||||
(@equal editor set-time-zoom :time-zoom-prev)
|
||||
(@minus editor set-time-zoom :time-zoom-next)
|
||||
|
|
|
|||
|
|
@ -4,3 +4,5 @@
|
|||
(@right sampler select :sample-to-right)
|
||||
(@r sampler record-toggle :sample-selected)
|
||||
(@shift-R sampler record-cancel)
|
||||
(@p sampler play-sample :sample-selected)
|
||||
(@P sampler stop-sample :sample-selected)
|
||||
|
|
|
|||
|
|
@ -2,19 +2,15 @@ use crate::*;
|
|||
|
||||
#[derive(Debug, Default)] pub struct Track {
|
||||
/// Name of track
|
||||
pub name: Arc<str>,
|
||||
/// Preferred width of track column
|
||||
pub width: usize,
|
||||
pub name: Arc<str>,
|
||||
/// Identifying color of track
|
||||
pub color: ItemTheme,
|
||||
pub color: ItemTheme,
|
||||
/// Preferred width of track column
|
||||
pub width: usize,
|
||||
/// MIDI sequencer state
|
||||
pub sequencer: Sequencer,
|
||||
pub sequencer: Sequencer,
|
||||
/// Device chain
|
||||
pub devices: Vec<Device>,
|
||||
/// Inputs of 1st device
|
||||
pub audio_ins: Vec<JackAudioIn>,
|
||||
/// Outputs of last device
|
||||
pub audio_outs: Vec<JackAudioOut>,
|
||||
pub devices: Vec<Device>,
|
||||
}
|
||||
|
||||
has_clock!(|self: Track|self.sequencer.clock);
|
||||
|
|
@ -58,9 +54,7 @@ impl Track {
|
|||
audio_from: &[&[PortConnect];2],
|
||||
audio_to: &[&[PortConnect];2],
|
||||
) -> Usually<Self> {
|
||||
let mut track = Self::new(
|
||||
name, color, jack, clock, clip, midi_from, midi_to
|
||||
)?;
|
||||
let mut track = Self::new(name, color, jack, clock, clip, midi_from, midi_to)?;
|
||||
track.devices.push(Device::Sampler(Sampler::new(
|
||||
jack,
|
||||
&format!("{}/sampler", name.as_ref()),
|
||||
|
|
|
|||
|
|
@ -571,9 +571,13 @@ impl<'a> ArrangerView<'a> {
|
|||
|
||||
}
|
||||
|
||||
trait ScenesColors<'a> = Iterator<Item=SceneWithColor<'a>>;
|
||||
/// Iterator over scenes with their sizes and colors.
|
||||
pub(crate) trait ScenesColors<'a> =
|
||||
Iterator<Item=SceneWithColor<'a>>;
|
||||
|
||||
type SceneWithColor<'a> = (usize, &'a Scene, usize, usize, Option<ItemTheme>);
|
||||
/// A scene with size and color.
|
||||
pub(crate) type SceneWithColor<'a> =
|
||||
(usize, &'a Scene, usize, usize, Option<ItemTheme>);
|
||||
|
||||
/// Define a type alias for iterators of sized items (columns).
|
||||
macro_rules! def_sizes_iter {
|
||||
|
|
|
|||
|
|
@ -128,11 +128,13 @@ impl Cli {
|
|||
midi_ins,
|
||||
midi_outs,
|
||||
midi_buf: match mode {
|
||||
LaunchMode::Clock
|
||||
| LaunchMode::Sampler => vec![],
|
||||
LaunchMode::Sequencer
|
||||
| LaunchMode::Groovebox
|
||||
| LaunchMode::Arranger {..} => vec![vec![];65536],
|
||||
LaunchMode::Clock |
|
||||
LaunchMode::Sampler =>
|
||||
vec![],
|
||||
LaunchMode::Sequencer |
|
||||
LaunchMode::Groovebox |
|
||||
LaunchMode::Arranger {..} =>
|
||||
vec![vec![];65536],
|
||||
_ => todo!("{mode:?}"),
|
||||
},
|
||||
tracks: match mode {
|
||||
|
|
@ -155,7 +157,7 @@ impl Cli {
|
|||
Some(&clock),
|
||||
clip.as_ref(),
|
||||
midi_froms.as_slice(),
|
||||
midi_froms.as_slice(),
|
||||
midi_tos.as_slice(),
|
||||
audio_froms,
|
||||
audio_tos,
|
||||
)?
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ use crate::*;
|
|||
todo!()
|
||||
}
|
||||
|
||||
fn clip_length (&self) -> usize {
|
||||
self.clip().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1)
|
||||
}
|
||||
|
||||
fn note_length (&self) -> usize {
|
||||
self.get_note_len()
|
||||
}
|
||||
|
|
@ -49,10 +53,19 @@ use crate::*;
|
|||
self.get_time_pos()
|
||||
}
|
||||
fn time_pos_next (&self) -> usize {
|
||||
self.get_time_pos() + self.get_note_len()
|
||||
(self.get_time_pos() + self.get_note_len()) % self.clip_length()
|
||||
}
|
||||
fn time_pos_next_fine (&self) -> usize {
|
||||
(self.get_time_pos() + 1) % self.clip_length()
|
||||
}
|
||||
fn time_pos_prev (&self) -> usize {
|
||||
self.get_time_pos().saturating_sub(self.get_note_len())
|
||||
let step = self.get_note_len();
|
||||
self.get_time_pos().overflowing_sub(step)
|
||||
.0.min(self.clip_length().saturating_sub(step))
|
||||
}
|
||||
fn time_pos_prev_fine (&self) -> usize {
|
||||
self.get_time_pos().overflowing_sub(1)
|
||||
.0.min(self.clip_length().saturating_sub(1))
|
||||
}
|
||||
|
||||
fn time_zoom (&self) -> usize {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ impl MidiEditor {
|
|||
clip.notes[note_end].push(note_off);
|
||||
}
|
||||
if advance {
|
||||
self.set_time_pos(note_end + 1);
|
||||
self.set_time_pos((note_end + 1) % clip.length);
|
||||
}
|
||||
redraw = true;
|
||||
}
|
||||
|
|
@ -69,33 +69,6 @@ impl MidiEditor {
|
|||
self.mode.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clip_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
let (color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.name.clone(), clip.length, clip.looped)
|
||||
} else { (ItemTheme::G[64], String::new().into(), 0, false) };
|
||||
Bsp::e(
|
||||
FieldH(color, "Edit", format!("{name} ({length})")),
|
||||
FieldH(color, "Loop", looped.to_string())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn edit_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.length)
|
||||
} else { (ItemTheme::G[64], 0) };
|
||||
let time_pos = self.get_time_pos();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let time_lock = if self.get_time_lock() { "[lock]" } else { " " };
|
||||
let note_pos = self.get_note_pos();
|
||||
let note_name = format!("{:4}", Note::pitch_to_name(note_pos));
|
||||
let note_pos = format!("{:>3}", note_pos);
|
||||
let note_len = format!("{:>4}", self.get_note_len());
|
||||
Bsp::e(
|
||||
FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")),
|
||||
FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeRange for MidiEditor {
|
||||
|
|
|
|||
|
|
@ -7,3 +7,34 @@ content!(TuiOut: |self: MidiEditor| {
|
|||
//self.autozoom();
|
||||
self.size.of(&self.mode)
|
||||
});
|
||||
|
||||
impl MidiEditor {
|
||||
|
||||
pub fn clip_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
let (color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.name.clone(), clip.length, clip.looped)
|
||||
} else { (ItemTheme::G[64], String::new().into(), 0, false) };
|
||||
Bsp::e(
|
||||
FieldH(color, "Edit", format!("{name} ({length})")),
|
||||
FieldH(color, "Loop", looped.to_string())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn edit_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.length)
|
||||
} else { (ItemTheme::G[64], 0) };
|
||||
let time_pos = self.get_time_pos();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let time_lock = if self.get_time_lock() { "[lock]" } else { " " };
|
||||
let note_pos = self.get_note_pos();
|
||||
let note_name = format!("{:4}", Note::pitch_to_name(note_pos));
|
||||
let note_pos = format!("{:>3}", note_pos);
|
||||
let note_len = format!("{:>4}", self.get_note_len());
|
||||
Bsp::e(
|
||||
FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")),
|
||||
FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")),
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,16 @@ impl SamplerCommand {
|
|||
sampler.recording = None;
|
||||
Ok(None)
|
||||
}
|
||||
fn play_sample (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
||||
if let Some(ref sample) = sampler.mapped[pitch] {
|
||||
sampler.voices.write().unwrap().push(Sample::play(sample, 0, &u7::from(128)));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn stop_sample (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
||||
todo!();
|
||||
Ok(None)
|
||||
}
|
||||
//fn select (&self, state: &mut Sampler, i: usize) -> Option<Self> {
|
||||
//Self::Select(state.set_note_pos(i))
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue