use Command::delegate, extract SamplerStatus

This commit is contained in:
🪞👃🪞 2025-01-02 16:01:40 +01:00
parent 92459b5f82
commit 42e2ef2a50
4 changed files with 58 additions and 68 deletions

View file

@ -96,7 +96,7 @@ impl OutputStats {
format!("{:.0}Hz", rate)
},
buffer_size: format!("{chunk}"),
latency: format!("{}", chunk as f64 / rate * 1000.),
latency: format!("{:.3}ms", chunk as f64 / rate * 1000.),
}
}
}

View file

@ -102,7 +102,7 @@ render!(Tui: (self: Groovebox) => {
let w = self.size.w();
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
let pool_w = if self.pool.visible { phrase_w } else { 0 };
let sampler_w = if self.pool.visible { phrase_w } else { 0 };
let sampler_w = if self.pool.visible { phrase_w } else { 4 };
let sample_h = if self.pool.visible { 8 } else { 0 };
let note_pt = self.editor.note_point();
let color = self.player.play_phrase().as_ref()
@ -120,35 +120,32 @@ render!(Tui: (self: Groovebox) => {
))),
))),
Bsp::n(
Bsp::s(
Fixed::y(1, self.sampler.mapped[note_pt].as_ref().map(|sample|format!(
"Sample {}-{}",
sample.read().unwrap().start,
sample.read().unwrap().end,
))),
Bsp::a(
Outer(Style::default().fg(TuiTheme::g(128))),
Fill::x(Fixed::y(sample_h, if let Some((_, sample)) = &self.sampler.recording {
SampleViewer(Some(sample.clone()))
} else if let Some(sample) = &self.sampler.mapped[note_pt] {
SampleViewer(Some(sample.clone()))
} else {
SampleViewer(None)
})),
),
Bsp::a(
Outer(Style::default().fg(TuiTheme::g(128))),
Fill::x(Fixed::y(sample_h, if let Some((_, sample)) = &self.sampler.recording {
SampleViewer(Some(sample.clone()))
} else if let Some(sample) = &self.sampler.mapped[note_pt] {
SampleViewer(Some(sample.clone()))
} else {
SampleViewer(None)
})),
),
Bsp::w(
Fixed::x(pool_w, Align::e(Fill::y(PoolView(&self.pool)))),
Fill::xy(Bsp::e(
Fixed::x(sampler_w, sampler),
Bsp::s(
selector,
Bsp::n(
MidiEditStatus(&self.editor),
&self.editor,
Bsp::n(
Bsp::e(
Fixed::y(1, SamplerStatus(&self.sampler, note_pt)),
MidiEditStatus(&self.editor),
),
Bsp::w(
Fixed::x(pool_w, Align::e(Fill::y(PoolView(&self.pool)))),
Fill::xy(Bsp::e(
Fixed::x(sampler_w, sampler),
Bsp::s(
selector,
&self.editor,
),
),
),
))
)
),
)
)
))
@ -215,39 +212,37 @@ input_to_command!(GrooveboxCommand: <Tui>|state: Groovebox, input|match input.ev
});
command!(|self: GrooveboxCommand, state: Groovebox|match self {
Self::History(delta) => {
todo!("undo/redo")
},
Self::Enqueue(phrase) => {
state.player.enqueue_next(phrase.as_ref());
None
},
Self::Pool(cmd) => {
let mut default = |cmd: PoolCommand|cmd
.execute(&mut state.pool)
.map(|x|x.map(Self::Pool));
match cmd {
// autoselect: automatically load selected phrase in editor
PoolCommand::Select(_) => {
let undo = default(cmd)?;
let undo = cmd.delegate(&mut state.pool, Self::Pool)?;
state.editor.set_phrase(Some(state.pool.phrase()));
undo
},
// update color in all places simultaneously
PoolCommand::Phrase(SetColor(index, _)) => {
let undo = default(cmd)?;
let undo = cmd.delegate(&mut state.pool, Self::Pool)?;
state.editor.set_phrase(Some(state.pool.phrase()));
undo
},
_ => default(cmd)?
_ => cmd.delegate(&mut state.pool, Self::Pool)?
}
},
Self::Editor(cmd) => {
let default = ||cmd.execute(&mut state.editor).map(|x|x.map(Self::Editor));
match cmd {
_ => default()?
}
cmd.delegate(&mut state.editor, Self::Editor)?
},
Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock),
Self::Sampler(cmd) => cmd.execute(&mut state.sampler)?.map(Self::Sampler),
Self::Enqueue(phrase) => {
state.player.enqueue_next(phrase.as_ref());
None
Self::Clock(cmd) => {
cmd.delegate(state, Self::Clock)?
},
Self::History(delta) => {
todo!("undo/redo")
Self::Sampler(cmd) => {
cmd.delegate(&mut state.sampler, Self::Sampler)?
},
});

View file

@ -1,3 +1,11 @@
mod sample; pub use self::sample::*;
mod voice; pub use self::voice::*;
mod sampler_tui; pub use self::sampler_tui::*;
mod sampler_status; pub use self::sampler_status::*;
mod sample_import; pub use self::sample_import::*;
mod sample_list; pub use self::sample_list::*;
mod sample_viewer; pub use self::sample_viewer::*;
use crate::*;
use KeyCode::Char;
use std::fs::File;
@ -13,28 +21,6 @@ use symphonia::{
default::get_codecs,
};
pub mod sample;
pub(crate) use self::sample::*;
pub use self::sample::Sample;
pub mod voice;
pub(crate) use self::voice::*;
pub use self::voice::Voice;
pub mod sampler_tui;
pub(crate) use self::sampler_tui::*;
pub use self::sampler_tui::SamplerTui;
pub mod sample_import;
pub(crate) use self::sample_import::*;
pub mod sample_list;
pub(crate) use self::sample_list::*;
pub use self::sample_list::SampleList;
pub mod sample_viewer;
pub(crate) use self::sample_viewer::*;
pub use self::sample_viewer::SampleViewer;
/// The sampler plugin plays sounds.
#[derive(Debug)]

View file

@ -0,0 +1,9 @@
use crate::*;
pub struct SamplerStatus<'a>(pub &'a Sampler, pub usize);
render!(Tui: (self: SamplerStatus<'a>) => self.0.mapped[self.1].as_ref().map(|sample|format!(
"Sample {}-{}",
sample.read().unwrap().start,
sample.read().unwrap().end,
)).unwrap_or_else(||"No sample".to_string()));