use crate::*; use KeyCode::Char; pub struct SamplerTui { pub state: Sampler, pub cursor: (usize, usize), pub editing: Option>>, pub mode: Option, /// Size of actual notes area pub size: Measure, /// Lowest note displayed pub note_lo: AtomicUsize, pub note_pt: AtomicUsize, pub color: ItemPalette } impl SamplerTui { /// Immutable reference to sample at cursor. pub fn sample (&self) -> Option<&Arc>> { for (i, sample) in self.state.mapped.iter().enumerate() { if i == self.cursor.0 { return sample.as_ref() } } for (i, sample) in self.state.unmapped.iter().enumerate() { if i + self.state.mapped.len() == self.cursor.0 { return Some(sample) } } None } } //from_jack!(|jack|SamplerTui{ //Self { //cursor: (0, 0), //editing: None, //mode: None, //size: Measure::new(), //note_lo: 36.into(), //note_pt: 36.into(), //color: ItemPalette::from(Color::Rgb(64, 128, 32)), //state: Sampler::new(jack, &"sampler", &[], &[&[], &[]], &[&[], &[]])?, //} //}); render!(|self: SamplerTui|{ let keys_width = 5; let keys = move||"";//SamplerKeys(self); let fg = self.color.base.rgb; let bg = self.color.darkest.rgb; let border = Fill::wh(Outer(Style::default().fg(fg).bg(bg))); let with_border = |x|lay!([border, Fill::wh(&x)]); let with_size = |x|lay!([self.size, x]); Tui::bg(bg, Fill::wh(with_border(Bsp::s( Tui::fg(self.color.light.rgb, Tui::bold(true, "Sampler")), with_size(Tui::shrink_y(1, Bsp::e( Fixed::w(keys_width, keys()), Fill::wh(render(|to: &mut TuiOutput|Ok({ let x = to.area.x(); let bg_base = self.color.darkest.rgb; let bg_selected = self.color.darker.rgb; let style_empty = Style::default().fg(self.color.base.rgb); let style_full = Style::default().fg(self.color.lighter.rgb); let note_hi = self.note_hi(); let note_pt = self.note_point(); for y in 0..self.size.h() { let note = note_hi - y as usize; let bg = if note == note_pt { bg_selected } else { bg_base }; let style = Some(style_empty.bg(bg)); to.blit(&" (no sample) ", x, to.area.y() + y as u16, style) } }))) ))), )))) }); impl NoteRange for SamplerTui { fn note_lo (&self) -> &AtomicUsize { &self.note_lo } fn note_axis (&self) -> &AtomicUsize { &self.size.y } } impl NotePoint for SamplerTui { fn note_len (&self) -> usize {0/*TODO*/} fn set_note_len (&self, x: usize) {} fn note_point (&self) -> usize { self.note_pt.load(Relaxed) } fn set_note_point (&self, x: usize) { self.note_pt.store(x, Relaxed); } } pub enum SamplerMode { // Load sample from path Import(usize, FileBrowser), } handle!(|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input)); pub enum SamplerTuiCommand { Import(FileBrowserCommand), SelectNote(usize), SelectField(usize), Sample(SamplerCommand), } input_to_command!(SamplerTuiCommand: |state: SamplerTui, input|match state.mode { Some(SamplerMode::Import(..)) => Self::Import( FileBrowserCommand::input_to_command(state, input)? ), _ => match input.event() { // load sample key_pat!(Shift-Char('L')) => { Self::Import(FileBrowserCommand::Begin) }, key_pat!(KeyCode::Up) => { Self::SelectNote(state.note_point().overflowing_add(1).0.min(127)) }, key_pat!(KeyCode::Down) => { Self::SelectNote(state.note_point().overflowing_sub(1).0.min(127)) }, _ => return None } //key_pat!(KeyCode::Char('p')) => if let Some(sample) = self.sample() { //voices.write().unwrap().push(Sample::play(sample, 0, &100.into())); //}, //key_pat!(KeyCode::Char('a')) => { //let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); //self.mode = None;//Some(Exit::boxed(AddSampleModal::new(&sample, &voices)?)); //unmapped.push(sample); //}, //key_pat!(KeyCode::Char('r')) => if let Some(sample) = self.sample() { //self.mode = None;//Some(Exit::boxed(AddSampleModal::new(&sample, &voices)?)); //}, //key_pat!(KeyCode::Enter) => if let Some(sample) = self.sample() { //self.editing = Some(sample.clone()); //}, //_ => { //return Ok(None) //} //} }); command!(|self: SamplerTuiCommand, state: SamplerTui|match self { Self::Import(FileBrowserCommand::Begin) => { let voices = &state.state.voices; let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); state.mode = Some(SamplerMode::Import(0, FileBrowser::new(None)?)); None }, Self::SelectNote(index) => { let old = state.note_point(); state.set_note_point(index); Some(Self::SelectNote(old)) }, Self::Sample(cmd) => cmd.execute(&mut state.state)?.map(Self::Sample), _ => todo!() });