mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
Compare commits
4 commits
997d67a487
...
cdeb355972
| Author | SHA1 | Date | |
|---|---|---|---|
| cdeb355972 | |||
| 85a144798b | |||
| e00d870d70 | |||
| 4e2702f69e |
11 changed files with 130 additions and 95 deletions
|
|
@ -3,15 +3,16 @@
|
||||||
(info "A sequencer with built-in sampler.")
|
(info "A sequencer with built-in sampler.")
|
||||||
|
|
||||||
(view
|
(view
|
||||||
(bsp/a :view-dialog
|
(bsp/a :view-dialog
|
||||||
(bsp/s (fixed/y 1 :view-transport)
|
(bsp/s (fixed/y 1 :view-transport)
|
||||||
(bsp/n (fixed/y 1 :view-status)
|
(bsp/n (fixed/y 1 :view-status)
|
||||||
(bsp/w :view-meters-output
|
(bsp/w :view-meters-output
|
||||||
(bsp/e :view-meters-input
|
(bsp/e :view-meters-input
|
||||||
(bsp/n (fixed/y 5 :view-sample-viewer)
|
(bsp/n :view-sample-info
|
||||||
(bsp/w (fixed/x :w-sidebar :view-pool)
|
(bsp/n (fixed/y 5 :view-sample-viewer)
|
||||||
(bsp/e :view-samples-keys
|
(bsp/w (fixed/x :w-sidebar :view-pool)
|
||||||
(fill/y :view-editor))))))))))
|
(bsp/e :view-samples-keys
|
||||||
|
(fill/y :view-editor)))))))))))
|
||||||
|
|
||||||
(keys
|
(keys
|
||||||
(layer-if :focus-pool-import "./keys_pool_file.edn")
|
(layer-if :focus-pool-import "./keys_pool_file.edn")
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,24 @@
|
||||||
(@up editor note-pos :note-pos-next)
|
(@left editor set-time-pos :time-pos-prev)
|
||||||
(@down editor note-pos :note-pos-prev)
|
(@right editor set-time-pos :time-pos-next)
|
||||||
(@pgup editor note-pos :note-pos-next-octave)
|
|
||||||
(@pgdn editor note-pos :note-pos-prev-octave)
|
|
||||||
|
|
||||||
(@comma editor note-len :note-len-prev)
|
(@equal editor set-time-zoom :time-zoom-prev)
|
||||||
(@period editor note-len :note-len-next)
|
(@minus editor set-time-zoom :time-zoom-next)
|
||||||
(@lt editor note-len :note-len-prev)
|
(@plus editor set-time-zoom :time-zoom-next-fine)
|
||||||
(@gt editor note-len :note-len-next)
|
(@underscore editor set-time-zoom :time-zoom-prev-fine)
|
||||||
|
|
||||||
(@plus editor note-range :note-range-next)
|
(@z editor set-time-lock)
|
||||||
(@underscore editor note-range :note-range-prev)
|
|
||||||
|
|
||||||
(@left editor time-pos :time-pos-prev)
|
(@up editor set-note-pos :note-pos-next)
|
||||||
(@right editor time-pos :time-pos-next)
|
(@down editor set-note-pos :note-pos-prev)
|
||||||
|
(@pgup editor set-note-pos :note-pos-next-octave)
|
||||||
|
(@pgdn editor set-note-pos :note-pos-prev-octave)
|
||||||
|
|
||||||
(@equal editor time-zoom :time-zoom-prev)
|
(@comma editor set-note-len :note-len-prev)
|
||||||
(@minus editor time-zoom :time-zoom-next)
|
(@period editor set-note-len :note-len-next)
|
||||||
|
(@lt editor set-note-len :note-len-prev)
|
||||||
|
(@gt editor set-note-len :note-len-next)
|
||||||
|
|
||||||
(@z editor time-lock)
|
(@a editor append-note :true)
|
||||||
|
(@enter editor append-note :false)
|
||||||
(@enter editor note-put)
|
(@del editor delete-note)
|
||||||
(@shift-enter editor note-append)
|
(@shift-del editor delete-note)
|
||||||
(@del editor note-del)
|
|
||||||
(@shift-del editor note-del)
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
(@esc menu)
|
(@esc toggle-menu)
|
||||||
(@f1 help)
|
(@f1 toggle-help)
|
||||||
|
|
||||||
(@u undo 1)
|
(@u undo 1)
|
||||||
(@shift-u redo 1)
|
(@shift-u redo 1)
|
||||||
|
|
|
||||||
|
|
@ -203,11 +203,11 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tengri_proc::command(App)] impl AppCommand {
|
#[tengri_proc::command(App)] impl AppCommand {
|
||||||
fn toggle_help (app: &mut App, value: bool) -> Perhaps<Self> {
|
fn toggle_help (app: &mut App) -> Perhaps<Self> {
|
||||||
app.toggle_dialog(Some(Dialog::Help));
|
app.toggle_dialog(Some(Dialog::Help));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn toggle_menu (app: &mut App, value: bool) -> Perhaps<Self> {
|
fn toggle_menu (app: &mut App) -> Perhaps<Self> {
|
||||||
app.toggle_dialog(Some(Dialog::Menu));
|
app.toggle_dialog(Some(Dialog::Menu));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +280,7 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
|
||||||
// update linked sampler after editor action
|
// update linked sampler after editor action
|
||||||
app.sampler_mut().map(|sampler|match command {
|
app.sampler_mut().map(|sampler|match command {
|
||||||
// autoselect: automatically select sample in sampler
|
// autoselect: automatically select sample in sampler
|
||||||
MidiEditCommand::NotePos { pos } => { sampler.set_note_pos(pos); },
|
MidiEditCommand::SetNotePos { pos } => { sampler.set_note_pos(pos); },
|
||||||
_ => {}
|
_ => {}
|
||||||
});
|
});
|
||||||
undo
|
undo
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@ impl App {
|
||||||
pub fn view_sample_viewer (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_sample_viewer (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.sampler().map(|s|s.view_sample(self.editor().unwrap().get_note_pos()))
|
self.sampler().map(|s|s.view_sample(self.editor().unwrap().get_note_pos()))
|
||||||
}
|
}
|
||||||
|
pub fn view_sample_info (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
self.sampler().map(|s|s.view_sample_info(self.editor().unwrap().get_note_pos()))
|
||||||
|
}
|
||||||
|
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
self.sampler().map(|s|s.view_meters_input())
|
||||||
|
}
|
||||||
|
pub fn view_meters_output (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
self.sampler().map(|s|s.view_meters_output())
|
||||||
|
}
|
||||||
pub fn view_dialog (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_dialog (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
When::new(self.dialog.is_some(), Bsp::b(
|
When::new(self.dialog.is_some(), Bsp::b(
|
||||||
Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")),
|
Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")),
|
||||||
|
|
@ -56,12 +65,6 @@ impl App {
|
||||||
)))
|
)))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
self.sampler().map(|s|s.view_meters_input())
|
|
||||||
}
|
|
||||||
pub fn view_meters_output (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
self.sampler().map(|s|s.view_meters_output())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
|
||||||
|
|
@ -111,10 +111,10 @@ impl Cli {
|
||||||
_ => todo!("{mode:?}"),
|
_ => todo!("{mode:?}"),
|
||||||
};
|
};
|
||||||
let config = Configuration::new(&config_path, false)?;
|
let config = Configuration::new(&config_path, false)?;
|
||||||
|
let clock = Clock::new(jack, self.bpm)?;
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
color: ItemTheme::random(),
|
color: ItemTheme::random(),
|
||||||
clock: Clock::new(jack, self.bpm)?,
|
|
||||||
pool: match mode {
|
pool: match mode {
|
||||||
LaunchMode::Sequencer | LaunchMode::Groovebox => clip.as_ref().map(Into::into),
|
LaunchMode::Sequencer | LaunchMode::Groovebox => clip.as_ref().map(Into::into),
|
||||||
LaunchMode::Arranger { .. } => Some(Default::default()),
|
LaunchMode::Arranger { .. } => Some(Default::default()),
|
||||||
|
|
@ -141,7 +141,7 @@ impl Cli {
|
||||||
&name,
|
&name,
|
||||||
None,
|
None,
|
||||||
jack,
|
jack,
|
||||||
None,
|
Some(&clock),
|
||||||
clip.as_ref(),
|
clip.as_ref(),
|
||||||
midi_froms.as_slice(),
|
midi_froms.as_slice(),
|
||||||
midi_tos.as_slice()
|
midi_tos.as_slice()
|
||||||
|
|
@ -152,7 +152,7 @@ impl Cli {
|
||||||
&name,
|
&name,
|
||||||
None,
|
None,
|
||||||
jack,
|
jack,
|
||||||
None,
|
Some(&clock),
|
||||||
clip.as_ref(),
|
clip.as_ref(),
|
||||||
midi_froms.as_slice(),
|
midi_froms.as_slice(),
|
||||||
midi_froms.as_slice(),
|
midi_froms.as_slice(),
|
||||||
|
|
@ -165,6 +165,7 @@ impl Cli {
|
||||||
scenes,
|
scenes,
|
||||||
selected: Selection::TrackClip { track: 0, scene: 0 },
|
selected: Selection::TrackClip { track: 0, scene: 0 },
|
||||||
config,
|
config,
|
||||||
|
clock,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode {
|
if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode {
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,6 @@ use crate::*;
|
||||||
fn _todo_opt_clip_stub (&self) -> Option<Arc<RwLock<MidiClip>>> {
|
fn _todo_opt_clip_stub (&self) -> Option<Arc<RwLock<MidiClip>>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn time_lock (&self) -> bool {
|
|
||||||
self.get_time_lock()
|
|
||||||
}
|
|
||||||
fn time_lock_toggled (&self) -> bool {
|
|
||||||
!self.get_time_lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn note_length (&self) -> usize {
|
fn note_length (&self) -> usize {
|
||||||
self.get_note_len()
|
self.get_note_len()
|
||||||
|
|
@ -55,10 +49,10 @@ use crate::*;
|
||||||
self.get_time_pos()
|
self.get_time_pos()
|
||||||
}
|
}
|
||||||
fn time_pos_next (&self) -> usize {
|
fn time_pos_next (&self) -> usize {
|
||||||
self.get_time_pos() + self.time_zoom()
|
self.get_time_pos() + self.get_note_len()
|
||||||
}
|
}
|
||||||
fn time_pos_prev (&self) -> usize {
|
fn time_pos_prev (&self) -> usize {
|
||||||
self.get_time_pos().saturating_sub(self.time_zoom())
|
self.get_time_pos().saturating_sub(self.get_note_len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn time_zoom (&self) -> usize {
|
fn time_zoom (&self) -> usize {
|
||||||
|
|
@ -67,29 +61,37 @@ use crate::*;
|
||||||
fn time_zoom_next (&self) -> usize {
|
fn time_zoom_next (&self) -> usize {
|
||||||
self.get_time_zoom() + 1
|
self.get_time_zoom() + 1
|
||||||
}
|
}
|
||||||
|
fn time_zoom_next_fine (&self) -> usize {
|
||||||
|
self.get_time_zoom() + 1
|
||||||
|
}
|
||||||
fn time_zoom_prev (&self) -> usize {
|
fn time_zoom_prev (&self) -> usize {
|
||||||
self.get_time_zoom().saturating_sub(1).max(1)
|
self.get_time_zoom().saturating_sub(1).max(1)
|
||||||
}
|
}
|
||||||
|
fn time_zoom_prev_fine (&self) -> usize {
|
||||||
|
self.get_time_zoom().saturating_sub(1).max(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time_lock (&self) -> bool {
|
||||||
|
self.get_time_lock()
|
||||||
|
}
|
||||||
|
fn time_lock_toggled (&self) -> bool {
|
||||||
|
!self.get_time_lock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tengri_proc::command(MidiEditor)] impl MidiEditCommand {
|
#[tengri_proc::command(MidiEditor)] impl MidiEditCommand {
|
||||||
// TODO: 1-9 seek markers that by default start every 8th of the clip
|
fn append_note (editor: &mut MidiEditor, advance: bool) -> Perhaps<Self> {
|
||||||
fn note_append (editor: &mut MidiEditor) -> Perhaps<Self> {
|
editor.put_note(advance);
|
||||||
editor.put_note(true);
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn note_put (editor: &mut MidiEditor) -> Perhaps<Self> {
|
fn delete_note (_editor: &mut MidiEditor) -> Perhaps<Self> {
|
||||||
editor.put_note(false);
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
fn note_del (_editor: &mut MidiEditor) -> Perhaps<Self> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn note_pos (editor: &mut MidiEditor, pos: usize) -> Perhaps<Self> {
|
fn set_note_pos (editor: &mut MidiEditor, pos: usize) -> Perhaps<Self> {
|
||||||
editor.set_note_pos(pos.min(127));
|
editor.set_note_pos(pos.min(127));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn note_len (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
fn set_note_len (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
||||||
//let note_len = editor.get_note_len();
|
//let note_len = editor.get_note_len();
|
||||||
//let time_zoom = editor.get_time_zoom();
|
//let time_zoom = editor.get_time_zoom();
|
||||||
editor.set_note_len(value);
|
editor.set_note_len(value);
|
||||||
|
|
@ -98,24 +100,24 @@ use crate::*;
|
||||||
//}
|
//}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn note_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
fn set_note_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
||||||
editor.set_note_lo(value.min(127));
|
editor.set_note_lo(value.min(127));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn time_pos (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
fn set_time_pos (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
||||||
editor.set_time_pos(value);
|
editor.set_time_pos(value);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn time_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
fn set_time_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
||||||
editor.set_time_start(value);
|
editor.set_time_start(value);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn time_zoom (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
fn set_time_zoom (editor: &mut MidiEditor, value: usize) -> Perhaps<Self> {
|
||||||
editor.set_time_zoom(value);
|
editor.set_time_zoom(value);
|
||||||
editor.redraw();
|
editor.redraw();
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn time_lock (editor: &mut MidiEditor, value: bool) -> Perhaps<Self> {
|
fn set_time_lock (editor: &mut MidiEditor, value: bool) -> Perhaps<Self> {
|
||||||
editor.set_time_lock(value);
|
editor.set_time_lock(value);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
@ -123,4 +125,5 @@ use crate::*;
|
||||||
editor.set_clip(clip.as_ref());
|
editor.set_clip(clip.as_ref());
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
// TODO: 1-9 seek markers that by default start every 8th of the clip
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ impl MidiEditor {
|
||||||
clip.notes[note_end].push(note_off);
|
clip.notes[note_end].push(note_off);
|
||||||
}
|
}
|
||||||
if advance {
|
if advance {
|
||||||
self.set_time_pos(note_end);
|
self.set_time_pos(note_end + 1);
|
||||||
}
|
}
|
||||||
redraw = true;
|
redraw = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::*;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Sampler {
|
pub struct Sampler {
|
||||||
/// Name of sampler.
|
/// Name of sampler.
|
||||||
pub name: String,
|
pub name: Arc<str>,
|
||||||
/// Device color.
|
/// Device color.
|
||||||
pub color: ItemTheme,
|
pub color: ItemTheme,
|
||||||
/// Audio input ports. Samples get recorded here.
|
/// Audio input ports. Samples get recorded here.
|
||||||
|
|
@ -55,7 +55,7 @@ impl Default for Sampler {
|
||||||
input_meters: vec![0.0;2],
|
input_meters: vec![0.0;2],
|
||||||
output_meters: vec![0.0;2],
|
output_meters: vec![0.0;2],
|
||||||
audio_outs: vec![],
|
audio_outs: vec![],
|
||||||
name: "tek_sampler".to_string(),
|
name: "tek_sampler".into(),
|
||||||
mapped: [const { None };128],
|
mapped: [const { None };128],
|
||||||
unmapped: vec![],
|
unmapped: vec![],
|
||||||
voices: Arc::new(RwLock::new(vec![])),
|
voices: Arc::new(RwLock::new(vec![])),
|
||||||
|
|
|
||||||
|
|
@ -100,33 +100,46 @@ impl Sampler {
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status (&self, index: usize) -> impl Content<TuiOut> {
|
pub fn view_sample_info (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
Fill::x(Fixed::y(1, draw_info(if let Some((_, sample)) = &self.recording {
|
||||||
|
Some(sample)
|
||||||
|
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||||
|
Some(sample)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view_status (&self, index: usize) -> impl Content<TuiOut> {
|
||||||
draw_status(self.mapped[index].as_ref())
|
draw_status(self.mapped[index].as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.input_meters.iter(), |value, _index|{
|
draw_meters(&self.input_meters)
|
||||||
Fill::y(RmsMeter(*value))
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_meters_output (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_meters_output (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.output_meters.iter(), |value, _index|{
|
draw_meters(&self.output_meters)
|
||||||
Fill::y(RmsMeter(*value))
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_meters (meters: &[f32]) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
Tui::bg(Black, Fixed::x(2, Map::east(1, ||meters.iter(), |value, _index|{
|
||||||
|
Fill::y(RmsMeter(*value))
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
fn draw_list_item (sample: &Option<Arc<RwLock<Sample>>>) -> String {
|
fn draw_list_item (sample: &Option<Arc<RwLock<Sample>>>) -> String {
|
||||||
if let Some(sample) = sample {
|
if let Some(sample) = sample {
|
||||||
let sample = sample.read().unwrap();
|
let sample = sample.read().unwrap();
|
||||||
format!("{:8} {:3} {:6}-{:6}/{:6}",
|
format!("{:8}", sample.name)
|
||||||
sample.name,
|
//format!("{:8} {:3} {:6}-{:6}/{:6}",
|
||||||
sample.gain,
|
//sample.name,
|
||||||
sample.start,
|
//sample.gain,
|
||||||
sample.end,
|
//sample.start,
|
||||||
sample.channels[0].len()
|
//sample.end,
|
||||||
)
|
//sample.channels[0].len()
|
||||||
|
//)
|
||||||
} else {
|
} else {
|
||||||
String::from("........")
|
String::from("........")
|
||||||
}
|
}
|
||||||
|
|
@ -187,6 +200,21 @@ fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> +
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_info (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
When(sample.is_some(), Thunk::new(move||{
|
||||||
|
let sample = sample.unwrap().read().unwrap();
|
||||||
|
let theme = ItemTheme::G[96];
|
||||||
|
row!(
|
||||||
|
FieldH(theme, "Name", format!("{:<10}", sample.name.clone())),
|
||||||
|
FieldH(theme, "Length", format!("{:<8}", sample.channels[0].len())),
|
||||||
|
FieldH(theme, "Start", format!("{:<8}", sample.start)),
|
||||||
|
FieldH(theme, "End", format!("{:<8}", sample.end)),
|
||||||
|
FieldH(theme, "Transpose", " 0 "),
|
||||||
|
FieldH(theme, "Gain", format!("{}", sample.gain)),
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn draw_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> {
|
fn draw_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> {
|
||||||
Tui::bold(true, Tui::fg(Tui::g(224), sample
|
Tui::bold(true, Tui::fg(Tui::g(224), sample
|
||||||
.map(|sample|{
|
.map(|sample|{
|
||||||
|
|
|
||||||
|
|
@ -18,29 +18,29 @@ pub trait HasSequencer {
|
||||||
/// Contains state for playing a clip
|
/// Contains state for playing a clip
|
||||||
pub struct Sequencer {
|
pub struct Sequencer {
|
||||||
/// State of clock and playhead
|
/// State of clock and playhead
|
||||||
pub clock: Clock,
|
pub clock: Clock,
|
||||||
/// Start time and clip being played
|
/// Start time and clip being played
|
||||||
pub play_clip: Option<(Moment, Option<Arc<RwLock<MidiClip>>>)>,
|
pub play_clip: Option<(Moment, Option<Arc<RwLock<MidiClip>>>)>,
|
||||||
/// Start time and next clip
|
/// Start time and next clip
|
||||||
pub next_clip: Option<(Moment, Option<Arc<RwLock<MidiClip>>>)>,
|
pub next_clip: Option<(Moment, Option<Arc<RwLock<MidiClip>>>)>,
|
||||||
/// Play input through output.
|
/// Play input through output.
|
||||||
pub monitoring: bool,
|
pub monitoring: bool,
|
||||||
/// Write input to sequence.
|
/// Write input to sequence.
|
||||||
pub recording: bool,
|
pub recording: bool,
|
||||||
/// Overdub input to sequence.
|
/// Overdub input to sequence.
|
||||||
pub overdub: bool,
|
pub overdub: bool,
|
||||||
/// Send all notes off
|
/// Send all notes off
|
||||||
pub reset: bool, // TODO?: after Some(nframes)
|
pub reset: bool, // TODO?: after Some(nframes)
|
||||||
/// Record from MIDI ports to current sequence.
|
/// Record from MIDI ports to current sequence.
|
||||||
pub midi_ins: Vec<JackMidiIn>,
|
pub midi_ins: Vec<JackMidiIn>,
|
||||||
/// Play from current sequence to MIDI ports
|
/// Play from current sequence to MIDI ports
|
||||||
pub midi_outs: Vec<JackMidiOut>,
|
pub midi_outs: Vec<JackMidiOut>,
|
||||||
/// Notes currently held at input
|
/// Notes currently held at input
|
||||||
pub notes_in: Arc<RwLock<[bool; 128]>>,
|
pub notes_in: Arc<RwLock<[bool; 128]>>,
|
||||||
/// Notes currently held at output
|
/// Notes currently held at output
|
||||||
pub notes_out: Arc<RwLock<[bool; 128]>>,
|
pub notes_out: Arc<RwLock<[bool; 128]>>,
|
||||||
/// MIDI output buffer
|
/// MIDI output buffer
|
||||||
pub note_buf: Vec<u8>,
|
pub note_buf: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Sequencer {
|
impl Default for Sequencer {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue