mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
remove those two pesky status widgets to the trait
This commit is contained in:
parent
acfaf757ec
commit
efbabe6248
13 changed files with 145 additions and 162 deletions
|
|
@ -1847,3 +1847,63 @@ from_edn!("mixer/track" => |jack: &Arc<RwLock<JackConnection>>, args| -> MixerTr
|
||||||
//key(Char('<')) => todo!("transport seek beat"),
|
//key(Char('<')) => todo!("transport seek beat"),
|
||||||
//key(Char('>')) => todo!("transport seek beat"),
|
//key(Char('>')) => todo!("transport seek beat"),
|
||||||
//});
|
//});
|
||||||
|
|
||||||
|
//#[derive(Debug)]
|
||||||
|
//pub struct MIDIPlayer {
|
||||||
|
///// Global timebase
|
||||||
|
//pub clock: Arc<Clock>,
|
||||||
|
///// Start time and clip being played
|
||||||
|
//pub play_clip: Option<(Moment, Option<Arc<RwLock<Clip>>>)>,
|
||||||
|
///// Start time and next clip
|
||||||
|
//pub next_clip: Option<(Moment, Option<Arc<RwLock<Clip>>>)>,
|
||||||
|
///// Play input through output.
|
||||||
|
//pub monitoring: bool,
|
||||||
|
///// Write input to sequence.
|
||||||
|
//pub recording: bool,
|
||||||
|
///// Overdub input to sequence.
|
||||||
|
//pub overdub: bool,
|
||||||
|
///// Send all notes off
|
||||||
|
//pub reset: bool, // TODO?: after Some(nframes)
|
||||||
|
///// Record from MIDI ports to current sequence.
|
||||||
|
//pub midi_inputs: Vec<Port<MidiIn>>,
|
||||||
|
///// Play from current sequence to MIDI ports
|
||||||
|
//pub midi_outputs: Vec<Port<MidiOut>>,
|
||||||
|
///// MIDI output buffer
|
||||||
|
//pub midi_note: Vec<u8>,
|
||||||
|
///// MIDI output buffer
|
||||||
|
//pub midi_chunk: Vec<Vec<Vec<u8>>>,
|
||||||
|
///// Notes currently held at input
|
||||||
|
//pub notes_in: Arc<RwLock<[bool; 128]>>,
|
||||||
|
///// Notes currently held at output
|
||||||
|
//pub notes_out: Arc<RwLock<[bool; 128]>>,
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// Methods used primarily by the process callback
|
||||||
|
//impl MIDIPlayer {
|
||||||
|
//pub fn new (
|
||||||
|
//jack: &Arc<RwLock<JackConnection>>,
|
||||||
|
//clock: &Arc<Clock>,
|
||||||
|
//name: &str
|
||||||
|
//) -> Usually<Self> {
|
||||||
|
//let jack = jack.read().unwrap();
|
||||||
|
//Ok(Self {
|
||||||
|
//clock: clock.clone(),
|
||||||
|
//clip: None,
|
||||||
|
//next_clip: None,
|
||||||
|
//notes_in: Arc::new(RwLock::new([false;128])),
|
||||||
|
//notes_out: Arc::new(RwLock::new([false;128])),
|
||||||
|
//monitoring: false,
|
||||||
|
//recording: false,
|
||||||
|
//overdub: true,
|
||||||
|
//reset: true,
|
||||||
|
//midi_note: Vec::with_capacity(8),
|
||||||
|
//midi_chunk: vec![Vec::with_capacity(16);16384],
|
||||||
|
//midi_outputs: vec![
|
||||||
|
//jack.client().register_port(format!("{name}_out0").as_str(), MidiOut::default())?
|
||||||
|
//],
|
||||||
|
//midi_inputs: vec![
|
||||||
|
//jack.client().register_port(format!("{name}_in0").as_str(), MidiIn::default())?
|
||||||
|
//],
|
||||||
|
//})
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,12 @@ mod midi_pitch; pub use midi_pitch::*;
|
||||||
mod midi_range; pub use midi_range::*;
|
mod midi_range; pub use midi_range::*;
|
||||||
mod midi_point; pub use midi_point::*;
|
mod midi_point; pub use midi_point::*;
|
||||||
mod midi_view; pub use midi_view::*;
|
mod midi_view; pub use midi_view::*;
|
||||||
mod midi_select; pub use midi_select::*;
|
|
||||||
|
|
||||||
mod midi_pool; pub use midi_pool::*;
|
mod midi_pool; pub use midi_pool::*;
|
||||||
mod midi_pool_tui; pub use midi_pool_tui::*;
|
mod midi_pool_tui; pub use midi_pool_tui::*;
|
||||||
mod midi_pool_cmd; pub use midi_pool_cmd::*;
|
mod midi_pool_cmd; pub use midi_pool_cmd::*;
|
||||||
|
|
||||||
mod midi_editor; pub use midi_editor::*;
|
mod midi_edit; pub use midi_edit::*;
|
||||||
mod midi_edit_cmd; pub use midi_edit_cmd::*;
|
mod midi_edit_cmd; pub use midi_edit_cmd::*;
|
||||||
mod midi_edit_tui; pub use midi_edit_tui::*;
|
mod midi_edit_tui; pub use midi_edit_tui::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,53 @@ pub trait HasPlayClip: HasClock {
|
||||||
*self.next_clip_mut() = Some((instant, clip.cloned()));
|
*self.next_clip_mut() = Some((instant, clip.cloned()));
|
||||||
*self.reset_mut() = true;
|
*self.reset_mut() = true;
|
||||||
}
|
}
|
||||||
|
fn play_status (&self) -> impl Content<TuiOut> {
|
||||||
|
let (name, color): (Arc<str>, ItemPalette) = if let Some((_, Some(clip))) = self.play_clip() {
|
||||||
|
let MidiClip { ref name, color, .. } = *clip.read().unwrap();
|
||||||
|
(name.clone(), color)
|
||||||
|
} else {
|
||||||
|
("".into(), TuiTheme::g(64).into())
|
||||||
|
};
|
||||||
|
let time: String = self.pulses_since_start_looped()
|
||||||
|
.map(|(times, time)|format!("{:>3}x {:>}", times+1.0, self.clock().timebase.format_beats_1(time)))
|
||||||
|
.unwrap_or_else(||String::from(" ")).into();
|
||||||
|
FieldV(color, "Now:", format!("{} {}", time, name))
|
||||||
|
}
|
||||||
|
fn next_status (&self) -> impl Content<TuiOut> {
|
||||||
|
let mut time: Arc<str> = String::from("--.-.--").into();
|
||||||
|
let mut name: Arc<str> = String::from("").into();
|
||||||
|
let mut color = ItemPalette::from(TuiTheme::g(64));
|
||||||
|
let clock = self.clock();
|
||||||
|
if let Some((t, Some(clip))) = self.next_clip() {
|
||||||
|
let clip = clip.read().unwrap();
|
||||||
|
name = clip.name.clone();
|
||||||
|
color = clip.color.clone();
|
||||||
|
time = {
|
||||||
|
let target = t.pulse.get();
|
||||||
|
let current = clock.playhead.pulse.get();
|
||||||
|
if target > current {
|
||||||
|
let remaining = target - current;
|
||||||
|
format!("-{:>}", clock.timebase.format_beats_1(remaining))
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}.into()
|
||||||
|
} else if let Some((t, Some(clip))) = self.play_clip() {
|
||||||
|
let clip = clip.read().unwrap();
|
||||||
|
if clip.looped {
|
||||||
|
name = clip.name.clone();
|
||||||
|
color = clip.color.clone();
|
||||||
|
let target = t.pulse.get() + clip.length as f64;
|
||||||
|
let current = clock.playhead.pulse.get();
|
||||||
|
if target > current {
|
||||||
|
time = format!("-{:>}", clock.timebase.format_beats_0(
|
||||||
|
target - current
|
||||||
|
)).into()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
name = "Stop".to_string().into();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FieldV(color, "Next:", format!("{} {}", time, name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub struct Note;
|
pub struct Note;
|
||||||
|
|
||||||
impl Note {
|
impl Note {
|
||||||
|
|
|
||||||
|
|
@ -217,63 +217,3 @@ impl HasPlayClip for MidiPlayer {
|
||||||
&mut self.next_clip
|
&mut self.next_clip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[derive(Debug)]
|
|
||||||
//pub struct MIDIPlayer {
|
|
||||||
///// Global timebase
|
|
||||||
//pub clock: Arc<Clock>,
|
|
||||||
///// Start time and clip being played
|
|
||||||
//pub play_clip: Option<(Moment, Option<Arc<RwLock<Clip>>>)>,
|
|
||||||
///// Start time and next clip
|
|
||||||
//pub next_clip: Option<(Moment, Option<Arc<RwLock<Clip>>>)>,
|
|
||||||
///// Play input through output.
|
|
||||||
//pub monitoring: bool,
|
|
||||||
///// Write input to sequence.
|
|
||||||
//pub recording: bool,
|
|
||||||
///// Overdub input to sequence.
|
|
||||||
//pub overdub: bool,
|
|
||||||
///// Send all notes off
|
|
||||||
//pub reset: bool, // TODO?: after Some(nframes)
|
|
||||||
///// Record from MIDI ports to current sequence.
|
|
||||||
//pub midi_inputs: Vec<Port<MidiIn>>,
|
|
||||||
///// Play from current sequence to MIDI ports
|
|
||||||
//pub midi_outputs: Vec<Port<MidiOut>>,
|
|
||||||
///// MIDI output buffer
|
|
||||||
//pub midi_note: Vec<u8>,
|
|
||||||
///// MIDI output buffer
|
|
||||||
//pub midi_chunk: Vec<Vec<Vec<u8>>>,
|
|
||||||
///// Notes currently held at input
|
|
||||||
//pub notes_in: Arc<RwLock<[bool; 128]>>,
|
|
||||||
///// Notes currently held at output
|
|
||||||
//pub notes_out: Arc<RwLock<[bool; 128]>>,
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// Methods used primarily by the process callback
|
|
||||||
//impl MIDIPlayer {
|
|
||||||
//pub fn new (
|
|
||||||
//jack: &Arc<RwLock<JackConnection>>,
|
|
||||||
//clock: &Arc<Clock>,
|
|
||||||
//name: &str
|
|
||||||
//) -> Usually<Self> {
|
|
||||||
//let jack = jack.read().unwrap();
|
|
||||||
//Ok(Self {
|
|
||||||
//clock: clock.clone(),
|
|
||||||
//clip: None,
|
|
||||||
//next_clip: None,
|
|
||||||
//notes_in: Arc::new(RwLock::new([false;128])),
|
|
||||||
//notes_out: Arc::new(RwLock::new([false;128])),
|
|
||||||
//monitoring: false,
|
|
||||||
//recording: false,
|
|
||||||
//overdub: true,
|
|
||||||
//reset: true,
|
|
||||||
//midi_note: Vec::with_capacity(8),
|
|
||||||
//midi_chunk: vec![Vec::with_capacity(16);16384],
|
|
||||||
//midi_outputs: vec![
|
|
||||||
//jack.client().register_port(format!("{name}_out0").as_str(), MidiOut::default())?
|
|
||||||
//],
|
|
||||||
//midi_inputs: vec![
|
|
||||||
//jack.client().register_port(format!("{name}_in0").as_str(), MidiIn::default())?
|
|
||||||
//],
|
|
||||||
//})
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use KeyCode::*;
|
use KeyCode::*;
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)] pub enum PoolCommand {
|
||||||
pub enum PoolCommand {
|
|
||||||
Show(bool),
|
Show(bool),
|
||||||
/// Update the contents of the clip pool
|
/// Update the contents of the clip pool
|
||||||
Clip(PoolClipCommand),
|
Clip(PoolClipCommand),
|
||||||
|
|
@ -16,13 +15,16 @@ pub enum PoolCommand {
|
||||||
/// Export to file
|
/// Export to file
|
||||||
Export(FileBrowserCommand),
|
Export(FileBrowserCommand),
|
||||||
}
|
}
|
||||||
impl EdnCommand<MidiPool> for PoolCommand {
|
edn_command!(PoolCommand: |state: MidiPool| {
|
||||||
fn from_edn <'a> (state: &MidiPool, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self {
|
("show" [a: bool] Self::Show(a.expect("no flag")))
|
||||||
todo!()
|
("select" [i: usize] Self::Select(i.expect("no index")))
|
||||||
}
|
("clip" [a, ..b] Self::Clip(PoolClipCommand::from_edn(state, &a.to_ref(), b)))
|
||||||
}
|
("rename" [a, ..b] Self::Rename(ClipRenameCommand::from_edn(state, &a.to_ref(), b)))
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
("length" [a, ..b] Self::Length(ClipRenameCommand::from_edn(state, &a.to_ref(), b)))
|
||||||
pub enum PoolClipCommand {
|
("import" [a, ..b] Self::Import(FileBrowserCommand::from_edn(state, &a.to_ref(), b)))
|
||||||
|
("export" [a, ..b] Self::Export(FileBrowserCommand::from_edn(state, &a.to_ref(), b)))
|
||||||
|
});
|
||||||
|
#[derive(Clone, Debug, PartialEq)] pub enum PoolClipCommand {
|
||||||
Add(usize, MidiClip),
|
Add(usize, MidiClip),
|
||||||
Delete(usize),
|
Delete(usize),
|
||||||
Swap(usize, usize),
|
Swap(usize, usize),
|
||||||
|
|
@ -32,11 +34,16 @@ pub enum PoolClipCommand {
|
||||||
SetLength(usize, usize),
|
SetLength(usize, usize),
|
||||||
SetColor(usize, ItemColor),
|
SetColor(usize, ItemColor),
|
||||||
}
|
}
|
||||||
impl PoolClipCommand {
|
edn_command!(PoolClipCommand: |state: MidiPool| {
|
||||||
pub fn from_edn <'a> (head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self {
|
("add" [i: usize, c: MidiClip] Self::Add(i.expect("no index"), c.expect("no clip")))
|
||||||
todo!()
|
("delete" [i: usize] Self::Delete(i.expect("no index")))
|
||||||
}
|
("swap" [a: usize, b: usize] Self::Swap(a.expect("no index"), b.expect("no index")))
|
||||||
}
|
("import" [i: usize, p: PathBuf] Self::Import(i.expect("no index"), p.expect("no path")))
|
||||||
|
("export" [i: usize, p: PathBuf] Self::Export(i.expect("no index"), p.expect("no path")))
|
||||||
|
("set-name" [i: usize, n: Arc<str>] Self::SetName(i.expect("no index"), n.expect("no name")))
|
||||||
|
("set-length" [i: usize, l: usize] Self::SetLength(i.expect("no index"), l.expect("no length")))
|
||||||
|
("set-color" [i: usize, c: ItemColor] Self::SetColor(i.expect("no index"), c.expect("no color")))
|
||||||
|
});
|
||||||
impl<T: HasClips> Command<T> for PoolClipCommand {
|
impl<T: HasClips> Command<T> for PoolClipCommand {
|
||||||
fn execute (self, model: &mut T) -> Perhaps<Self> {
|
fn execute (self, model: &mut T) -> Perhaps<Self> {
|
||||||
use PoolClipCommand::*;
|
use PoolClipCommand::*;
|
||||||
|
|
@ -102,7 +109,7 @@ impl<T: HasClips> Command<T> for PoolClipCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command!(|self:PoolCommand, state: MidiPool|{
|
command!(|self: PoolCommand, state: MidiPool|{
|
||||||
use PoolCommand::*;
|
use PoolCommand::*;
|
||||||
match self {
|
match self {
|
||||||
Show(visible) => {
|
Show(visible) => {
|
||||||
|
|
|
||||||
13
midi/src/midi_pool_keys.edn
Normal file
13
midi/src/midi_pool_keys.edn
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
(:n clip/rename/begin)
|
||||||
|
(:t clip/length/begin)
|
||||||
|
(:m clip/import/begin)
|
||||||
|
(:x clip/export/begin)
|
||||||
|
(:c clip/color/random)
|
||||||
|
(:bracket-open clip/select/prev)
|
||||||
|
(:bracket-close clip/select/next)
|
||||||
|
(:lt clip/move/prev)
|
||||||
|
(:gt clip/move/next)
|
||||||
|
(:del clip/delete)
|
||||||
|
(:shift-a clip/add)
|
||||||
|
(:i clip/insert)
|
||||||
|
(:d clip/duplicate)
|
||||||
0
midi/src/midi_pool_view.edn
Normal file
0
midi/src/midi_pool_view.edn
Normal file
|
|
@ -1,70 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
pub struct ClipSelected {
|
|
||||||
pub(crate) title: &'static str,
|
|
||||||
pub(crate) name: Arc<str>,
|
|
||||||
pub(crate) color: ItemPalette,
|
|
||||||
pub(crate) time: Arc<str>,
|
|
||||||
}
|
|
||||||
content!(TuiOut: |self: ClipSelected|FieldV(
|
|
||||||
self.color,
|
|
||||||
self.title,
|
|
||||||
format!("{} {}", self.time, self.name)
|
|
||||||
));
|
|
||||||
impl ClipSelected {
|
|
||||||
/// Shows currently playing clip with beats elapsed
|
|
||||||
pub fn play_clip <T: HasPlayClip + HasClock> (state: &T) -> Self {
|
|
||||||
let (name, color) = if let Some((_, Some(clip))) = state.play_clip() {
|
|
||||||
let MidiClip { ref name, color, .. } = *clip.read().unwrap();
|
|
||||||
(name.clone().into(), color)
|
|
||||||
} else {
|
|
||||||
("".to_string().into(), TuiTheme::g(64).into())
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
title: "Now",
|
|
||||||
name,
|
|
||||||
color,
|
|
||||||
time: state.pulses_since_start_looped()
|
|
||||||
.map(|(times, time)|format!("{:>3}x {:>}",
|
|
||||||
times+1.0,
|
|
||||||
state.clock().timebase.format_beats_1(time)))
|
|
||||||
.unwrap_or_else(||String::from(" ")).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Shows next clip with beats remaining until switchover
|
|
||||||
pub fn next_clip <T: HasPlayClip> (state: &T) -> Self {
|
|
||||||
let mut time: Arc<str> = String::from("--.-.--").into();
|
|
||||||
let mut name: Arc<str> = String::from("").into();
|
|
||||||
let mut color = ItemPalette::from(TuiTheme::g(64));
|
|
||||||
if let Some((t, Some(clip))) = state.next_clip() {
|
|
||||||
let clip = clip.read().unwrap();
|
|
||||||
name = clip.name.clone();
|
|
||||||
color = clip.color.clone();
|
|
||||||
time = {
|
|
||||||
let target = t.pulse.get();
|
|
||||||
let current = state.clock().playhead.pulse.get();
|
|
||||||
if target > current {
|
|
||||||
let remaining = target - current;
|
|
||||||
format!("-{:>}", state.clock().timebase.format_beats_1(remaining))
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
}
|
|
||||||
}.into()
|
|
||||||
} else if let Some((t, Some(clip))) = state.play_clip() {
|
|
||||||
let clip = clip.read().unwrap();
|
|
||||||
if clip.looped {
|
|
||||||
name = clip.name.clone();
|
|
||||||
color = clip.color.clone();
|
|
||||||
let target = t.pulse.get() + clip.length as f64;
|
|
||||||
let current = state.clock().playhead.pulse.get();
|
|
||||||
if target > current {
|
|
||||||
time = format!("-{:>}", state.clock().timebase.format_beats_0(
|
|
||||||
target - current
|
|
||||||
)).into()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
name = "Stop".to_string().into();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Self { title: "Next", time, name, color, }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
(:n clip/rename/begin)
|
|
||||||
(:t clip/length/begin)
|
|
||||||
(:m clip/import/begin)
|
|
||||||
(:x clip/export/begin)
|
|
||||||
(:c clip/color/random)
|
|
||||||
(:bracket-open clip/select/prev)
|
|
||||||
(:bracket-close clip/select/next)
|
|
||||||
(:lt clip/move/prev)
|
|
||||||
(:gt clip/move/next)
|
|
||||||
(:del clip/delete)
|
|
||||||
(:shift-a clip/add)
|
|
||||||
(:i clip/insert)
|
|
||||||
(:d clip/duplicate)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue