diff --git a/crates/tek_mixer/src/lib.rs b/crates/tek_mixer/src/lib.rs index ebd1aa12..d8facd29 100644 --- a/crates/tek_mixer/src/lib.rs +++ b/crates/tek_mixer/src/lib.rs @@ -12,6 +12,5 @@ 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 + 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/sampler.rs b/crates/tek_mixer/src/sampler.rs index 6270d37c..463a1e42 100644 --- a/crates/tek_mixer/src/sampler.rs +++ b/crates/tek_mixer/src/sampler.rs @@ -18,7 +18,9 @@ pub struct Sampler { impl Sampler { pub fn new ( - name: &str, mapped: Option>>> + jack: &Arc>, + name: &str, + mapped: Option>>> ) -> Usually> { Jack::new(name)? .midi_in("midi") @@ -28,7 +30,7 @@ impl Sampler { .audio_out("outR") .run(|ports|Box::new(Self { _engine: Default::default(), - jack: (), + jack: jack.clone(), name: name.into(), cursor: (0, 0), editing: None, @@ -105,61 +107,6 @@ impl Sampler { } } -impl Widget for Sampler { - type Engine = Tui; - fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { - todo!() - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - tui_render_sampler(self, to) - } -} - -pub fn tui_render_sampler (sampler: &Sampler, to: &mut TuiOutput) -> Usually<()> { - let [x, y, _, height] = to.area(); - let style = Style::default().gray(); - let title = format!(" {} ({})", sampler.name, sampler.voices.read().unwrap().len()); - to.blit(&title, x+1, y, Some(style.white().bold().not_dim())); - let mut width = title.len() + 2; - let mut y1 = 1; - let mut j = 0; - for (note, sample) in sampler.mapped.iter() - .map(|(note, sample)|(Some(note), sample)) - .chain(sampler.unmapped.iter().map(|sample|(None, sample))) - { - if y1 >= height { - break - } - let active = j == sampler.cursor.0; - width = width.max( - draw_sample(to, x, y + y1, note, &*sample.read().unwrap(), active)? - ); - y1 = y1 + 1; - j = j + 1; - } - let height = ((2 + y1) as u16).min(height); - //Ok(Some([x, y, (width as u16).min(to.area().w()), height])) - Ok(()) -} - -fn draw_sample ( - to: &mut TuiOutput, x: u16, y: u16, note: Option<&u7>, sample: &Sample, focus: bool -) -> Usually { - let style = if focus { Style::default().green() } else { Style::default() }; - if focus { - to.blit(&"🬴", x+1, y, Some(style.bold())); - } - let label1 = format!("{:3} {:12}", - note.map(|n|n.to_string()).unwrap_or(String::default()), - sample.name); - let label2 = format!("{:>6} {:>6} +0.0", - sample.start, - sample.end); - to.blit(&label1, x+2, y, Some(style.bold())); - to.blit(&label2, x+3+label1.len()as u16, y, Some(style)); - Ok(label1.len() + label2.len() + 4) -} - /// A sound sample. #[derive(Default, Debug)] pub struct Sample { @@ -241,49 +188,6 @@ impl Exit for AddSampleModal { } } -impl Widget for AddSampleModal { - type Engine = Tui; - fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { - todo!() - //Align::Center(()).layout(to) - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - todo!() - //let area = to.area(); - //to.make_dim(); - //let area = center_box( - //area, - //64.max(area.w().saturating_sub(8)), - //20.max(area.w().saturating_sub(8)), - //); - //to.fill_fg(area, Color::Reset); - //to.fill_bg(area, Nord::bg_lo(true, true)); - //to.fill_char(area, ' '); - //to.blit(&format!("{}", &self.dir.to_string_lossy()), area.x()+2, area.y()+1, Some(Style::default().bold()))?; - //to.blit(&"Select sample:", area.x()+2, area.y()+2, Some(Style::default().bold()))?; - //for (i, (is_dir, name)) in self.subdirs.iter() - //.map(|path|(true, path)) - //.chain(self.files.iter().map(|path|(false, path))) - //.enumerate() - //.skip(self.offset) - //{ - //if i >= area.h() as usize - 4 { - //break - //} - //let t = if is_dir { "" } else { "" }; - //let line = format!("{t} {}", name.to_string_lossy()); - //let line = &line[..line.len().min(area.w() as usize - 4)]; - //to.blit(&line, area.x() + 2, area.y() + 3 + i as u16, Some(if i == self.cursor { - //Style::default().green() - //} else { - //Style::default().white() - //}))?; - //} - //Lozenge(Style::default()).draw(to) - } -} - - impl AddSampleModal { pub fn new ( sample: &Arc>, diff --git a/crates/tek_mixer/src/sampler_edn.rs b/crates/tek_mixer/src/sampler_edn.rs index 5a65783b..26ba8994 100644 --- a/crates/tek_mixer/src/sampler_edn.rs +++ b/crates/tek_mixer/src/sampler_edn.rs @@ -27,7 +27,7 @@ impl Sampler { }, _ => panic!("unexpected in sampler {name}: {edn:?}") }); - Self::new(&name, Some(samples)) + Self::new(jack, &name, Some(samples)) } } diff --git a/crates/tek_mixer/src/sampler_tui.rs b/crates/tek_mixer/src/sampler_tui.rs new file mode 100644 index 00000000..0bf8fd9a --- /dev/null +++ b/crates/tek_mixer/src/sampler_tui.rs @@ -0,0 +1,98 @@ +use crate::*; + +impl Widget for Sampler { + type Engine = Tui; + fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + todo!() + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + tui_render_sampler(self, to) + } +} + +pub fn tui_render_sampler (sampler: &Sampler, to: &mut TuiOutput) -> Usually<()> { + let [x, y, _, height] = to.area(); + let style = Style::default().gray(); + let title = format!(" {} ({})", sampler.name, sampler.voices.read().unwrap().len()); + to.blit(&title, x+1, y, Some(style.white().bold().not_dim())); + let mut width = title.len() + 2; + let mut y1 = 1; + let mut j = 0; + for (note, sample) in sampler.mapped.iter() + .map(|(note, sample)|(Some(note), sample)) + .chain(sampler.unmapped.iter().map(|sample|(None, sample))) + { + if y1 >= height { + break + } + let active = j == sampler.cursor.0; + width = width.max( + draw_sample(to, x, y + y1, note, &*sample.read().unwrap(), active)? + ); + y1 = y1 + 1; + j = j + 1; + } + let height = ((2 + y1) as u16).min(height); + //Ok(Some([x, y, (width as u16).min(to.area().w()), height])) + Ok(()) +} + +fn draw_sample ( + to: &mut TuiOutput, x: u16, y: u16, note: Option<&u7>, sample: &Sample, focus: bool +) -> Usually { + let style = if focus { Style::default().green() } else { Style::default() }; + if focus { + to.blit(&"🬴", x+1, y, Some(style.bold())); + } + let label1 = format!("{:3} {:12}", + note.map(|n|n.to_string()).unwrap_or(String::default()), + sample.name); + let label2 = format!("{:>6} {:>6} +0.0", + sample.start, + sample.end); + to.blit(&label1, x+2, y, Some(style.bold())); + to.blit(&label2, x+3+label1.len()as u16, y, Some(style)); + Ok(label1.len() + label2.len() + 4) +} + +impl Widget for AddSampleModal { + type Engine = Tui; + fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + todo!() + //Align::Center(()).layout(to) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + todo!() + //let area = to.area(); + //to.make_dim(); + //let area = center_box( + //area, + //64.max(area.w().saturating_sub(8)), + //20.max(area.w().saturating_sub(8)), + //); + //to.fill_fg(area, Color::Reset); + //to.fill_bg(area, Nord::bg_lo(true, true)); + //to.fill_char(area, ' '); + //to.blit(&format!("{}", &self.dir.to_string_lossy()), area.x()+2, area.y()+1, Some(Style::default().bold()))?; + //to.blit(&"Select sample:", area.x()+2, area.y()+2, Some(Style::default().bold()))?; + //for (i, (is_dir, name)) in self.subdirs.iter() + //.map(|path|(true, path)) + //.chain(self.files.iter().map(|path|(false, path))) + //.enumerate() + //.skip(self.offset) + //{ + //if i >= area.h() as usize - 4 { + //break + //} + //let t = if is_dir { "" } else { "" }; + //let line = format!("{t} {}", name.to_string_lossy()); + //let line = &line[..line.len().min(area.w() as usize - 4)]; + //to.blit(&line, area.x() + 2, area.y() + 3 + i as u16, Some(if i == self.cursor { + //Style::default().green() + //} else { + //Style::default().white() + //}))?; + //} + //Lozenge(Style::default()).draw(to) + } +}