diff --git a/crates/tek_mixer/src/lib.rs b/crates/tek_mixer/src/lib.rs index ca66359b..ebd1aa12 100644 --- a/crates/tek_mixer/src/lib.rs +++ b/crates/tek_mixer/src/lib.rs @@ -10,8 +10,8 @@ pub(crate) use std::ffi::OsString; pub(crate) use std::fs::read_dir; submod! { - mixer mixer_snd - track track_edn - plugin plugin_snd plugin_edn plugin_lv2 plugin_lv2_gui plugin_vst2 plugin_vst3 - sampler sampler_snd sampler_edn + 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.rs b/crates/tek_mixer/src/mixer.rs index 21384ea7..11b80376 100644 --- a/crates/tek_mixer/src/mixer.rs +++ b/crates/tek_mixer/src/mixer.rs @@ -27,70 +27,107 @@ impl Mixer { self.tracks.get(self.selected_track) } } -impl Content for Mixer { - type Engine = Tui; - fn content (&self) -> impl Widget { - Stack::right(|add| { - for channel in self.tracks.iter() { - add(channel)?; - } - Ok(()) - }) - } -} - -impl Handle for Mixer { - fn handle (&mut self, engine: &TuiInput) -> Perhaps { - if let TuiEvent::Input(crossterm::event::Event::Key(event)) = engine.event() { - - match event.code { - //KeyCode::Char('c') => { - //if event.modifiers == KeyModifiers::CONTROL { - //self.exit(); - //} - //}, - KeyCode::Down => { - self.selected_track = (self.selected_track + 1) % self.tracks.len(); - println!("{}", self.selected_track); - return Ok(Some(true)) - }, - KeyCode::Up => { - if self.selected_track == 0 { - self.selected_track = self.tracks.len() - 1; - } else { - self.selected_track -= 1; - } - println!("{}", self.selected_track); - return Ok(Some(true)) - }, - KeyCode::Left => { - if self.selected_column == 0 { - self.selected_column = 6 - } else { - self.selected_column -= 1; - } - return Ok(Some(true)) - }, - KeyCode::Right => { - if self.selected_column == 6 { - self.selected_column = 0 - } else { - self.selected_column += 1; - } - return Ok(Some(true)) - }, - _ => { - println!("\n{event:?}"); - } - } - - } - Ok(None) - } -} //pub const ACTIONS: [(&'static str, &'static str);2] = [ //("+/-", "Adjust"), //("Ins/Del", "Add/remove track"), //]; + +/// A sequencer track. +#[derive(Debug)] +pub struct Track { + pub name: String, + /// Inputs and outputs of 1st and last device + pub ports: JackPorts, + /// Device chain + pub devices: Vec>, + /// Device selector + pub device: usize, +} + +impl Track { + pub fn new (name: &str) -> Usually { + Ok(Self { + name: name.to_string(), + ports: JackPorts::default(), + devices: vec![], + device: 0, + }) + } + fn get_device_mut (&self, i: usize) -> Option>>> { + self.devices.get(i).map(|d|d.state.write().unwrap()) + } + pub fn device_mut (&self) -> Option>>> { + self.get_device_mut(self.device) + } + /// Add a device to the end of the chain. + pub fn append_device (&mut self, device: JackDevice) -> Usually<&mut JackDevice> { + self.devices.push(device); + let index = self.devices.len() - 1; + Ok(&mut self.devices[index]) + } + pub fn add_device (&mut self, device: JackDevice) { + self.devices.push(device); + } + //pub fn connect_first_device (&self) -> Usually<()> { + //if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) { + //device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?; + //} + //Ok(()) + //} + //pub fn connect_last_device (&self, app: &Track) -> Usually<()> { + //Ok(match self.devices.get(self.devices.len().saturating_sub(1)) { + //Some(device) => { + //app.audio_out(0).map(|left|device.connect_audio_out(0, &left)).transpose()?; + //app.audio_out(1).map(|right|device.connect_audio_out(1, &right)).transpose()?; + //() + //}, + //None => () + //}) + //} +} + + + +pub struct TrackView<'a, E: Engine> { + pub chain: Option<&'a Track>, + pub direction: Direction, + pub focused: bool, + pub entered: bool, +} + +impl<'a> Widget for TrackView<'a, Tui> { + type Engine = Tui; + fn layout (&self, area: [u16;2]) -> Perhaps<[u16;2]> { + todo!() + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + todo!(); + //let mut area = to.area(); + //if let Some(chain) = self.chain { + //match self.direction { + //Direction::Down => area.width = area.width.min(40), + //Direction::Right => area.width = area.width.min(10), + //_ => { unimplemented!() }, + //} + //to.fill_bg(to.area(), Nord::bg_lo(self.focused, self.entered)); + //let mut split = Stack::new(self.direction); + //for device in chain.devices.as_slice().iter() { + //split = split.add_ref(device); + //} + //let (area, areas) = split.render_areas(to)?; + //if self.focused && self.entered && areas.len() > 0 { + //Corners(Style::default().green().not_dim()).draw(to.with_rect(areas[0]))?; + //} + //Ok(Some(area)) + //} else { + //let [x, y, width, height] = area; + //let label = "No chain selected"; + //let x = x + (width - label.len() as u16) / 2; + //let y = y + height / 2; + //to.blit(&label, x, y, Some(Style::default().dim().bold()))?; + //Ok(Some(area)) + //} + } +} diff --git a/crates/tek_mixer/src/mixer_cmd.rs b/crates/tek_mixer/src/mixer_cmd.rs new file mode 100644 index 00000000..559f2896 --- /dev/null +++ b/crates/tek_mixer/src/mixer_cmd.rs @@ -0,0 +1,87 @@ +use crate::*; + +impl Handle for Mixer { + fn handle (&mut self, engine: &TuiInput) -> Perhaps { + if let TuiEvent::Input(crossterm::event::Event::Key(event)) = engine.event() { + + match event.code { + //KeyCode::Char('c') => { + //if event.modifiers == KeyModifiers::CONTROL { + //self.exit(); + //} + //}, + KeyCode::Down => { + self.selected_track = (self.selected_track + 1) % self.tracks.len(); + println!("{}", self.selected_track); + return Ok(Some(true)) + }, + KeyCode::Up => { + if self.selected_track == 0 { + self.selected_track = self.tracks.len() - 1; + } else { + self.selected_track -= 1; + } + println!("{}", self.selected_track); + return Ok(Some(true)) + }, + KeyCode::Left => { + if self.selected_column == 0 { + self.selected_column = 6 + } else { + self.selected_column -= 1; + } + return Ok(Some(true)) + }, + KeyCode::Right => { + if self.selected_column == 6 { + self.selected_column = 0 + } else { + self.selected_column += 1; + } + return Ok(Some(true)) + }, + _ => { + println!("\n{event:?}"); + } + } + + } + Ok(None) + } +} +impl Handle for Track { + fn handle (&mut self, from: &TuiInput) -> Perhaps { + match from.event() { + //, NONE, "chain_cursor_up", "move cursor up", || { + key!(KeyCode::Up) => { + Ok(Some(true)) + }, + // , NONE, "chain_cursor_down", "move cursor down", || { + key!(KeyCode::Down) => { + Ok(Some(true)) + }, + // Left, NONE, "chain_cursor_left", "move cursor left", || { + key!(KeyCode::Left) => { + //if let Some(track) = app.arranger.track_mut() { + //track.device = track.device.saturating_sub(1); + //return Ok(true) + //} + Ok(Some(true)) + }, + // , NONE, "chain_cursor_right", "move cursor right", || { + key!(KeyCode::Right) => { + //if let Some(track) = app.arranger.track_mut() { + //track.device = (track.device + 1).min(track.devices.len().saturating_sub(1)); + //return Ok(true) + //} + Ok(Some(true)) + }, + // , NONE, "chain_mode_switch", "switch the display mode", || { + key!(KeyCode::Char('`')) => { + //app.chain_mode = !app.chain_mode; + Ok(Some(true)) + }, + _ => Ok(None) + } + } +} diff --git a/crates/tek_mixer/src/track_edn.rs b/crates/tek_mixer/src/mixer_edn.rs similarity index 100% rename from crates/tek_mixer/src/track_edn.rs rename to crates/tek_mixer/src/mixer_edn.rs diff --git a/crates/tek_mixer/src/mixer_tui.rs b/crates/tek_mixer/src/mixer_tui.rs new file mode 100644 index 00000000..fb38f458 --- /dev/null +++ b/crates/tek_mixer/src/mixer_tui.rs @@ -0,0 +1,38 @@ +use crate::*; + +impl Content for Mixer { + type Engine = Tui; + fn content (&self) -> impl Widget { + Stack::right(|add| { + for channel in self.tracks.iter() { + add(channel)?; + } + Ok(()) + }) + } +} + +impl Content for Track { + type Engine = Tui; + fn content (&self) -> impl Widget { + TrackView { + chain: Some(&self), + direction: tek_core::Direction::Right, + focused: true, + entered: true, + //pub channels: u8, + //pub input_ports: Vec>, + //pub pre_gain_meter: f64, + //pub gain: f64, + //pub insert_ports: Vec>, + //pub return_ports: Vec>, + //pub post_gain_meter: f64, + //pub post_insert_meter: f64, + //pub level: f64, + //pub pan: f64, + //pub output_ports: Vec>, + //pub post_fader_meter: f64, + //pub route: String, + } + } +} diff --git a/crates/tek_mixer/src/plugin.rs b/crates/tek_mixer/src/plugin.rs index 8a54a769..a21cd781 100644 --- a/crates/tek_mixer/src/plugin.rs +++ b/crates/tek_mixer/src/plugin.rs @@ -60,120 +60,3 @@ pub enum PluginKind { }, VST3, } - -impl Handle for Plugin { - fn handle (&mut self, from: &TuiInput) -> Perhaps { - match from.event() { - key!(KeyCode::Up) => { - self.selected = self.selected.saturating_sub(1); - Ok(Some(true)) - }, - key!(KeyCode::Down) => { - self.selected = (self.selected + 1).min(match &self.plugin { - Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1, - _ => unimplemented!() - }); - Ok(Some(true)) - }, - key!(KeyCode::PageUp) => { - self.selected = self.selected.saturating_sub(8); - Ok(Some(true)) - }, - key!(KeyCode::PageDown) => { - self.selected = (self.selected + 10).min(match &self.plugin { - Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1, - _ => unimplemented!() - }); - Ok(Some(true)) - }, - key!(KeyCode::Char(',')) => { - match self.plugin.as_mut() { - Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => { - let index = port_list[self.selected].index; - if let Some(value) = instance.control_input(index) { - instance.set_control_input(index, value - 0.01); - } - }, - _ => {} - } - Ok(Some(true)) - }, - key!(KeyCode::Char('.')) => { - match self.plugin.as_mut() { - Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => { - let index = port_list[self.selected].index; - if let Some(value) = instance.control_input(index) { - instance.set_control_input(index, value + 0.01); - } - }, - _ => {} - } - Ok(Some(true)) - }, - key!(KeyCode::Char('g')) => { - match self.plugin { - Some(PluginKind::LV2(ref mut plugin)) => { - plugin.ui_thread = Some(run_lv2_ui(LV2PluginUI::new()?)?); - }, - Some(_) => unreachable!(), - None => {} - } - Ok(Some(true)) - }, - _ => Ok(None) - } - } -} - -impl Widget for Plugin { - type Engine = Tui; - fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { - Ok(Some(to)) - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - let area = to.area(); - let [x, y, _, height] = area; - let mut width = 20u16; - match &self.plugin { - Some(PluginKind::LV2(LV2Plugin { port_list, instance, .. })) => { - let start = self.selected.saturating_sub((height as usize / 2).saturating_sub(1)); - let end = start + height as usize - 2; - //draw_box(buf, Rect { x, y, width, height }); - for i in start..end { - if let Some(port) = port_list.get(i) { - let value = if let Some(value) = instance.control_input(port.index) { - value - } else { - port.default_value - }; - //let label = &format!("C·· M·· {:25} = {value:.03}", port.name); - let label = &format!("{:25} = {value:.03}", port.name); - width = width.max(label.len() as u16 + 4); - let style = if i == self.selected { - Some(Style::default().green()) - } else { - None - } ; - to.blit(&label, x + 2, y + 1 + i as u16 - start as u16, style); - } else { - break - } - } - }, - _ => {} - }; - draw_header(self, to, x, y, width)?; - Ok(()) - } -} - -fn draw_header (state: &Plugin, to: &mut TuiOutput, x: u16, y: u16, w: u16) -> Usually { - let style = Style::default().gray(); - let label1 = format!(" {}", state.name); - to.blit(&label1, x + 1, y, Some(style.white().bold())); - if let Some(ref path) = state.path { - let label2 = format!("{}…", &path[..((w as usize - 10).min(path.len()))]); - to.blit(&label2, x + 2 + label1.len() as u16, y, Some(style.not_dim())); - } - Ok(Rect { x, y, width: w, height: 1 }) -} diff --git a/crates/tek_mixer/src/plugin_cmd.rs b/crates/tek_mixer/src/plugin_cmd.rs new file mode 100644 index 00000000..2ecbebd7 --- /dev/null +++ b/crates/tek_mixer/src/plugin_cmd.rs @@ -0,0 +1,64 @@ +use crate::*; +impl Handle for Plugin { + fn handle (&mut self, from: &TuiInput) -> Perhaps { + match from.event() { + key!(KeyCode::Up) => { + self.selected = self.selected.saturating_sub(1); + Ok(Some(true)) + }, + key!(KeyCode::Down) => { + self.selected = (self.selected + 1).min(match &self.plugin { + Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1, + _ => unimplemented!() + }); + Ok(Some(true)) + }, + key!(KeyCode::PageUp) => { + self.selected = self.selected.saturating_sub(8); + Ok(Some(true)) + }, + key!(KeyCode::PageDown) => { + self.selected = (self.selected + 10).min(match &self.plugin { + Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1, + _ => unimplemented!() + }); + Ok(Some(true)) + }, + key!(KeyCode::Char(',')) => { + match self.plugin.as_mut() { + Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => { + let index = port_list[self.selected].index; + if let Some(value) = instance.control_input(index) { + instance.set_control_input(index, value - 0.01); + } + }, + _ => {} + } + Ok(Some(true)) + }, + key!(KeyCode::Char('.')) => { + match self.plugin.as_mut() { + Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => { + let index = port_list[self.selected].index; + if let Some(value) = instance.control_input(index) { + instance.set_control_input(index, value + 0.01); + } + }, + _ => {} + } + Ok(Some(true)) + }, + key!(KeyCode::Char('g')) => { + match self.plugin { + Some(PluginKind::LV2(ref mut plugin)) => { + plugin.ui_thread = Some(run_lv2_ui(LV2PluginUI::new()?)?); + }, + Some(_) => unreachable!(), + None => {} + } + Ok(Some(true)) + }, + _ => Ok(None) + } + } +} diff --git a/crates/tek_mixer/src/plugin_tui.rs b/crates/tek_mixer/src/plugin_tui.rs new file mode 100644 index 00000000..da9defc5 --- /dev/null +++ b/crates/tek_mixer/src/plugin_tui.rs @@ -0,0 +1,53 @@ +use crate::*; +impl Widget for Plugin { + type Engine = Tui; + fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + Ok(Some(to)) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + let area = to.area(); + let [x, y, _, height] = area; + let mut width = 20u16; + match &self.plugin { + Some(PluginKind::LV2(LV2Plugin { port_list, instance, .. })) => { + let start = self.selected.saturating_sub((height as usize / 2).saturating_sub(1)); + let end = start + height as usize - 2; + //draw_box(buf, Rect { x, y, width, height }); + for i in start..end { + if let Some(port) = port_list.get(i) { + let value = if let Some(value) = instance.control_input(port.index) { + value + } else { + port.default_value + }; + //let label = &format!("C·· M·· {:25} = {value:.03}", port.name); + let label = &format!("{:25} = {value:.03}", port.name); + width = width.max(label.len() as u16 + 4); + let style = if i == self.selected { + Some(Style::default().green()) + } else { + None + } ; + to.blit(&label, x + 2, y + 1 + i as u16 - start as u16, style); + } else { + break + } + } + }, + _ => {} + }; + draw_header(self, to, x, y, width)?; + Ok(()) + } +} + +fn draw_header (state: &Plugin, to: &mut TuiOutput, x: u16, y: u16, w: u16) -> Usually { + let style = Style::default().gray(); + let label1 = format!(" {}", state.name); + to.blit(&label1, x + 1, y, Some(style.white().bold())); + if let Some(ref path) = state.path { + let label2 = format!("{}…", &path[..((w as usize - 10).min(path.len()))]); + to.blit(&label2, x + 2 + label1.len() as u16, y, Some(style.not_dim())); + } + Ok(Rect { x, y, width: w, height: 1 }) +} diff --git a/crates/tek_mixer/src/sampler.rs b/crates/tek_mixer/src/sampler.rs index 9d8565fd..6270d37c 100644 --- a/crates/tek_mixer/src/sampler.rs +++ b/crates/tek_mixer/src/sampler.rs @@ -104,49 +104,6 @@ impl Sampler { } } } -impl Handle for Sampler { - fn handle (&mut self, from: &TuiInput) -> Perhaps { - match from.event() { - key!(KeyCode::Up) => { - self.cursor.0 = if self.cursor.0 == 0 { - self.mapped.len() + self.unmapped.len() - 1 - } else { - self.cursor.0 - 1 - }; - Ok(Some(true)) - }, - key!(KeyCode::Down) => { - self.cursor.0 = (self.cursor.0 + 1) % (self.mapped.len() + self.unmapped.len()); - Ok(Some(true)) - }, - key!(KeyCode::Char('p')) => { - if let Some(sample) = self.sample() { - self.voices.write().unwrap().push(Sample::play(sample, 0, &100.into())); - } - Ok(Some(true)) - }, - key!(KeyCode::Char('a')) => { - let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); - *self.modal.lock().unwrap() = Some(Exit::boxed(AddSampleModal::new(&sample, &self.voices)?)); - self.unmapped.push(sample); - Ok(Some(true)) - }, - key!(KeyCode::Char('r')) => { - if let Some(sample) = self.sample() { - *self.modal.lock().unwrap() = Some(Exit::boxed(AddSampleModal::new(&sample, &self.voices)?)); - } - Ok(Some(true)) - }, - key!(KeyCode::Enter) => { - if let Some(sample) = self.sample() { - self.editing = Some(sample.clone()); - } - Ok(Some(true)) - } - _ => Ok(None) - } - } -} impl Widget for Sampler { type Engine = Tui; @@ -326,14 +283,6 @@ impl Widget for AddSampleModal { } } -impl Handle for AddSampleModal { - fn handle (&mut self, from: &TuiInput) -> Perhaps { - if from.handle_keymap(self, KEYMAP_ADD_SAMPLE)? { - return Ok(Some(true)) - } - Ok(Some(true)) - } -} impl AddSampleModal { pub fn new ( diff --git a/crates/tek_mixer/src/sampler_cmd.rs b/crates/tek_mixer/src/sampler_cmd.rs new file mode 100644 index 00000000..a1b9e16a --- /dev/null +++ b/crates/tek_mixer/src/sampler_cmd.rs @@ -0,0 +1,52 @@ +use crate::*; +impl Handle for Sampler { + fn handle (&mut self, from: &TuiInput) -> Perhaps { + match from.event() { + key!(KeyCode::Up) => { + self.cursor.0 = if self.cursor.0 == 0 { + self.mapped.len() + self.unmapped.len() - 1 + } else { + self.cursor.0 - 1 + }; + Ok(Some(true)) + }, + key!(KeyCode::Down) => { + self.cursor.0 = (self.cursor.0 + 1) % (self.mapped.len() + self.unmapped.len()); + Ok(Some(true)) + }, + key!(KeyCode::Char('p')) => { + if let Some(sample) = self.sample() { + self.voices.write().unwrap().push(Sample::play(sample, 0, &100.into())); + } + Ok(Some(true)) + }, + key!(KeyCode::Char('a')) => { + let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); + *self.modal.lock().unwrap() = Some(Exit::boxed(AddSampleModal::new(&sample, &self.voices)?)); + self.unmapped.push(sample); + Ok(Some(true)) + }, + key!(KeyCode::Char('r')) => { + if let Some(sample) = self.sample() { + *self.modal.lock().unwrap() = Some(Exit::boxed(AddSampleModal::new(&sample, &self.voices)?)); + } + Ok(Some(true)) + }, + key!(KeyCode::Enter) => { + if let Some(sample) = self.sample() { + self.editing = Some(sample.clone()); + } + Ok(Some(true)) + } + _ => Ok(None) + } + } +} +impl Handle for AddSampleModal { + fn handle (&mut self, from: &TuiInput) -> Perhaps { + if from.handle_keymap(self, KEYMAP_ADD_SAMPLE)? { + return Ok(Some(true)) + } + Ok(Some(true)) + } +} diff --git a/crates/tek_mixer/src/track.rs b/crates/tek_mixer/src/track.rs deleted file mode 100644 index 21d7b168..00000000 --- a/crates/tek_mixer/src/track.rs +++ /dev/null @@ -1,157 +0,0 @@ -use crate::*; -use tek_core::edn; - -/// A sequencer track. -#[derive(Debug)] -pub struct Track { - pub name: String, - /// Inputs and outputs of 1st and last device - pub ports: JackPorts, - /// Device chain - pub devices: Vec>, - /// Device selector - pub device: usize, -} -impl Track { - pub fn new (name: &str) -> Usually { - Ok(Self { - name: name.to_string(), - ports: JackPorts::default(), - devices: vec![], - device: 0, - }) - } - fn get_device_mut (&self, i: usize) -> Option>>> { - self.devices.get(i).map(|d|d.state.write().unwrap()) - } - pub fn device_mut (&self) -> Option>>> { - self.get_device_mut(self.device) - } - /// Add a device to the end of the chain. - pub fn append_device (&mut self, device: JackDevice) -> Usually<&mut JackDevice> { - self.devices.push(device); - let index = self.devices.len() - 1; - Ok(&mut self.devices[index]) - } - pub fn add_device (&mut self, device: JackDevice) { - self.devices.push(device); - } - //pub fn connect_first_device (&self) -> Usually<()> { - //if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) { - //device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?; - //} - //Ok(()) - //} - //pub fn connect_last_device (&self, app: &Track) -> Usually<()> { - //Ok(match self.devices.get(self.devices.len().saturating_sub(1)) { - //Some(device) => { - //app.audio_out(0).map(|left|device.connect_audio_out(0, &left)).transpose()?; - //app.audio_out(1).map(|right|device.connect_audio_out(1, &right)).transpose()?; - //() - //}, - //None => () - //}) - //} -} - -impl Handle for Track { - fn handle (&mut self, from: &TuiInput) -> Perhaps { - match from.event() { - //, NONE, "chain_cursor_up", "move cursor up", || { - key!(KeyCode::Up) => { - Ok(Some(true)) - }, - // , NONE, "chain_cursor_down", "move cursor down", || { - key!(KeyCode::Down) => { - Ok(Some(true)) - }, - // Left, NONE, "chain_cursor_left", "move cursor left", || { - key!(KeyCode::Left) => { - //if let Some(track) = app.arranger.track_mut() { - //track.device = track.device.saturating_sub(1); - //return Ok(true) - //} - Ok(Some(true)) - }, - // , NONE, "chain_cursor_right", "move cursor right", || { - key!(KeyCode::Right) => { - //if let Some(track) = app.arranger.track_mut() { - //track.device = (track.device + 1).min(track.devices.len().saturating_sub(1)); - //return Ok(true) - //} - Ok(Some(true)) - }, - // , NONE, "chain_mode_switch", "switch the display mode", || { - key!(KeyCode::Char('`')) => { - //app.chain_mode = !app.chain_mode; - Ok(Some(true)) - }, - _ => Ok(None) - } - } -} - -impl Content for Track { - type Engine = Tui; - fn content (&self) -> impl Widget { - TrackView { - chain: Some(&self), - direction: tek_core::Direction::Right, - focused: true, - entered: true, - //pub channels: u8, - //pub input_ports: Vec>, - //pub pre_gain_meter: f64, - //pub gain: f64, - //pub insert_ports: Vec>, - //pub return_ports: Vec>, - //pub post_gain_meter: f64, - //pub post_insert_meter: f64, - //pub level: f64, - //pub pan: f64, - //pub output_ports: Vec>, - //pub post_fader_meter: f64, - //pub route: String, - } - } -} -pub struct TrackView<'a, E: Engine> { - pub chain: Option<&'a Track>, - pub direction: Direction, - pub focused: bool, - pub entered: bool, -} -impl<'a> Widget for TrackView<'a, Tui> { - type Engine = Tui; - fn layout (&self, area: [u16;2]) -> Perhaps<[u16;2]> { - todo!() - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - todo!(); - //let mut area = to.area(); - //if let Some(chain) = self.chain { - //match self.direction { - //Direction::Down => area.width = area.width.min(40), - //Direction::Right => area.width = area.width.min(10), - //_ => { unimplemented!() }, - //} - //to.fill_bg(to.area(), Nord::bg_lo(self.focused, self.entered)); - //let mut split = Stack::new(self.direction); - //for device in chain.devices.as_slice().iter() { - //split = split.add_ref(device); - //} - //let (area, areas) = split.render_areas(to)?; - //if self.focused && self.entered && areas.len() > 0 { - //Corners(Style::default().green().not_dim()).draw(to.with_rect(areas[0]))?; - //} - //Ok(Some(area)) - //} else { - //let [x, y, width, height] = area; - //let label = "No chain selected"; - //let x = x + (width - label.len() as u16) / 2; - //let y = y + height / 2; - //to.blit(&label, x, y, Some(Style::default().dim().bold()))?; - //Ok(Some(area)) - //} - } -}