tek/src/sampler/sampler_tui.rs

155 lines
5.4 KiB
Rust

use crate::*;
use KeyCode::Char;
pub struct SamplerTui {
pub state: Sampler,
pub cursor: (usize, usize),
pub editing: Option<Arc<RwLock<Sample>>>,
pub mode: Option<SamplerMode>,
/// Size of actual notes area
pub size: Measure<Tui>,
/// 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<RwLock<Sample>>> {
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!(<Tui>|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::xy(Outer(Style::default().fg(fg).bg(bg)));
let with_border = |x|lay!([border, Fill::xy(&x)]);
let with_size = |x|lay!([self.size, x]);
Tui::bg(bg, Fill::xy(with_border(Bsp::s(
Tui::fg(self.color.light.rgb, Tui::bold(true, "Sampler")),
with_size(Shrink::y(1, Bsp::e(
Fixed::x(keys_width, keys()),
Fill::xy(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!(<Tui>|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input));
pub enum SamplerTuiCommand {
Import(FileBrowserCommand),
SelectNote(usize),
SelectField(usize),
Sample(SamplerCommand),
}
input_to_command!(SamplerTuiCommand: <Tui>|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!()
});