change Device from trait to enum

This commit is contained in:
🪞👃🪞 2025-04-24 22:30:43 +03:00
parent 866d88c8ec
commit 1cc3a58826
8 changed files with 150 additions and 92 deletions

View file

@ -15,6 +15,8 @@ view!(TuiOut: |self: Tek| self.size.of(View(self, self.view)); {
().boxed(),//self.view_sample(self.is_editing()).boxed(),
":sampler" =>
().boxed(),//self.view_sampler(self.is_editing(), &self.editor).boxed(),
":samples-grid" =>
self.tracks[0].sampler(0).map(|s|s.view_grid()).boxed(),
":status" =>
self.view_status().boxed(),
":pool" => self.pool.as_ref()

View file

@ -1,10 +1 @@
use crate::*;
pub trait Device: Send + Sync + std::fmt::Debug {
fn boxed <'a> (self) -> Box<dyn Device + 'a> where Self: Sized + 'a { Box::new(self) }
}
impl Device for Sampler {}
#[cfg(feature = "host")]
impl Device for Plugin {}

View file

@ -247,60 +247,6 @@ impl HasSelection for Tek {
fn selected_mut (&mut self) -> &mut Selection { &mut self.selected }
}
pub trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync {
fn midi_ins (&self) -> &Vec<JackMidiIn>;
fn midi_outs (&self) -> &Vec<JackMidiOut>;
fn tracks (&self) -> &Vec<Track>;
fn tracks_mut (&mut self) -> &mut Vec<Track>;
fn track_longest (&self) -> usize {
self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max)
}
const WIDTH_OFFSET: usize = 1;
fn track_next_name (&self) -> Arc<str> {
format!("Track{:02}", self.tracks().len() + 1).into()
}
fn track (&self) -> Option<&Track> {
self.selected().track().and_then(|s|self.tracks().get(s))
}
fn track_mut (&mut self) -> Option<&mut Track> {
self.selected().track().and_then(|s|self.tracks_mut().get_mut(s))
}
}
#[derive(Debug, Default)] pub struct Track {
/// Name of track
pub name: Arc<str>,
/// Preferred width of track column
pub width: usize,
/// Identifying color of track
pub color: ItemPalette,
/// MIDI player state
pub player: MidiPlayer,
/// Device chain
pub devices: Vec<Box<dyn Device>>,
/// Inputs of 1st device
pub audio_ins: Vec<JackAudioIn>,
/// Outputs of last device
pub audio_outs: Vec<JackAudioOut>,
}
has_clock!(|self: Track|self.player.clock);
has_player!(|self: Track|self.player);
impl Track {
const MIN_WIDTH: usize = 9;
fn width_inc (&mut self) { self.width += 1; }
fn width_dec (&mut self) { if self.width > Track::MIN_WIDTH { self.width -= 1; } }
}
impl HasTracks for Tek {
fn midi_ins (&self) -> &Vec<JackMidiIn> { &self.midi_ins }
fn midi_outs (&self) -> &Vec<JackMidiOut> { &self.midi_outs }
fn tracks (&self) -> &Vec<Track> { &self.tracks }
fn tracks_mut (&mut self) -> &mut Vec<Track> { &mut self.tracks }
}
pub trait HasScenes: HasSelection + HasEditor + Send + Sync {
fn scenes (&self) -> &Vec<Scene>;
fn scenes_mut (&mut self) -> &mut Vec<Scene>;
@ -361,3 +307,97 @@ impl HasScenes for Tek {
fn scenes (&self) -> &Vec<Scene> { &self.scenes }
fn scenes_mut (&mut self) -> &mut Vec<Scene> { &mut self.scenes }
}
pub trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync {
fn midi_ins (&self) -> &Vec<JackMidiIn>;
fn midi_outs (&self) -> &Vec<JackMidiOut>;
fn tracks (&self) -> &Vec<Track>;
fn tracks_mut (&mut self) -> &mut Vec<Track>;
fn track_longest (&self) -> usize {
self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max)
}
const WIDTH_OFFSET: usize = 1;
fn track_next_name (&self) -> Arc<str> {
format!("Track{:02}", self.tracks().len() + 1).into()
}
fn track (&self) -> Option<&Track> {
self.selected().track().and_then(|s|self.tracks().get(s))
}
fn track_mut (&mut self) -> Option<&mut Track> {
self.selected().track().and_then(|s|self.tracks_mut().get_mut(s))
}
}
#[derive(Debug, Default)] pub struct Track {
/// Name of track
pub name: Arc<str>,
/// Preferred width of track column
pub width: usize,
/// Identifying color of track
pub color: ItemPalette,
/// MIDI player state
pub player: MidiPlayer,
/// Device chain
pub devices: Vec<Device>,
/// Inputs of 1st device
pub audio_ins: Vec<JackAudioIn>,
/// Outputs of last device
pub audio_outs: Vec<JackAudioOut>,
}
has_clock!(|self: Track|self.player.clock);
has_player!(|self: Track|self.player);
impl Track {
pub const MIN_WIDTH: usize = 9;
pub fn width_inc (&mut self) {
self.width += 1;
}
pub fn width_dec (&mut self) {
if self.width > Track::MIN_WIDTH {
self.width -= 1;
}
}
pub fn sequencer (&self, mut nth: usize) -> Option<&MidiPlayer> {
for device in self.devices.iter() {
match device {
Device::Sequencer(s) => if nth == 0 {
return Some(s);
} else {
nth -= 1;
},
_ => {}
}
}
None
}
pub fn sampler (&self, mut nth: usize) -> Option<&Sampler> {
for device in self.devices.iter() {
match device {
Device::Sampler(s) => if nth == 0 {
return Some(s);
} else {
nth -= 1;
},
_ => {}
}
}
None
}
}
impl HasTracks for Tek {
fn midi_ins (&self) -> &Vec<JackMidiIn> { &self.midi_ins }
fn midi_outs (&self) -> &Vec<JackMidiOut> { &self.midi_outs }
fn tracks (&self) -> &Vec<Track> { &self.tracks }
fn tracks_mut (&mut self) -> &mut Vec<Track> { &mut self.tracks }
}
#[derive(Debug)]
pub enum Device {
Sequencer(MidiPlayer),
Sampler(Sampler),
#[cfg(feature="host")]
Plugin(Plugin),
}

View file

@ -4,7 +4,7 @@ edition = { workspace = true }
version = { workspace = true }
[dependencies]
tek = { workspace = true }
tek = { workspace = true }
clap = { workspace = true }
[[bin]]

View file

@ -128,19 +128,51 @@ impl Cli {
keys_scene: SourceIter(include_str!("./edn/arranger_keys_scene.edn")),
keys_mix: SourceIter(include_str!("./edn/arranger_keys_mix.edn")),
tracks: match mode {
Mode::Sequencer => vec![Track::default()],
Mode::Groovebox | Mode::Sampler => vec![Track {
devices: vec![
Device::boxed(Sampler::new(
jack,
&"sampler",
midi_froms.as_slice(),
audio_froms,
audio_tos
)?)
],
..Track::default()
}],
Mode::Sequencer => vec![
Track {
devices: vec![
Device::Sequencer(
MidiPlayer::default()
),
],
..Track::default()
},
],
Mode::Groovebox => vec![
Track {
devices: vec![
Device::Sequencer(
MidiPlayer::default()
),
Device::Sampler(Sampler::new(
jack,
&"sampler",
midi_froms.as_slice(),
audio_froms,
audio_tos
)?)
],
..Track::default()
}
],
Mode::Sampler => vec![
Track {
devices: vec![
Device::Sampler(Sampler::new(
jack,
&"sampler",
midi_froms.as_slice(),
audio_froms,
audio_tos
)?)
],
..Track::default()
}
],
_ => vec![]
},
scenes,

View file

@ -20,7 +20,8 @@ pub trait MidiPlaybackApi: HasPlayClip + HasClock + HasMidiOuts {
fn clear (
&mut self, scope: &ProcessScope, out: &mut [Vec<Vec<u8>>], reset: bool
) {
for frame in &mut out[0..scope.n_frames() as usize] {
let n_frames = (scope.n_frames() as usize).min(out.len());
for frame in &mut out[0..n_frames] {
frame.clear();
}
if reset {

View file

@ -6,20 +6,6 @@ provide!(f32: |self: Sampler| {});
provide!(u7: |self: Sampler| {});
provide!(usize: |self: Sampler| {});
//handle!(TuiIn: |self: Sampler, input|SamplerCommand::execute_with_state(self, input.event()));
//input_to_command!(SamplerCommand: |state: Sampler, input: Event|match state.mode{
//Some(SamplerMode::Import(..)) => Self::Import(
//FileBrowserCommand::input_to_command(state, input)?
//),
//_ => match input {
//// load sample
//kpat!(Shift-Char('L')) => Self::Import(FileBrowserCommand::Begin),
//kpat!(KeyCode::Up) => Self::Select(state.note_pos().overflowing_add(1).0.min(127)),
//kpat!(KeyCode::Down) => Self::Select(state.note_pos().overflowing_sub(1).0.min(127)),
//_ => return None
//}
//});
defcom! { |self, state: Sampler|
SamplerCommand {

View file

@ -1,5 +1,11 @@
use crate::*;
impl Sampler {
pub fn view_grid (&self) -> impl Content<TuiOut> {
"sampler grid view"
}
}
content!(TuiOut: |self: Sampler| {
let keys_width = 5;
let keys = move||"";//SamplerKeys(self);