mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: rebinding commands...
This commit is contained in:
parent
4fb703d05d
commit
744ce21e24
3 changed files with 171 additions and 122 deletions
|
|
@ -25,6 +25,54 @@ pub trait HasClips {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PoolModel {
|
||||
pub visible: bool,
|
||||
/// Collection of clips
|
||||
pub clips: Arc<RwLock<Vec<Arc<RwLock<MidiClip>>>>>,
|
||||
/// Selected clip
|
||||
pub clip: AtomicUsize,
|
||||
/// Mode switch
|
||||
pub mode: Option<PoolMode>,
|
||||
}
|
||||
impl Default for PoolModel {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
visible: true,
|
||||
clips: Arc::from(RwLock::from(vec![])),
|
||||
clip: 0.into(),
|
||||
mode: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
from!(|clip:&Arc<RwLock<MidiClip>>|PoolModel = {
|
||||
let model = Self::default();
|
||||
model.clips.write().unwrap().push(clip.clone());
|
||||
model.clip.store(1, Relaxed);
|
||||
model
|
||||
});
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum PoolCommand {
|
||||
Show(bool),
|
||||
/// Update the contents of the clip pool
|
||||
Clip(MidiPoolCommand),
|
||||
/// Select a clip from the clip pool
|
||||
Select(usize),
|
||||
/// Rename a clip
|
||||
Rename(ClipRenameCommand),
|
||||
/// Change the length of a clip
|
||||
Length(ClipLengthCommand),
|
||||
/// Import from file
|
||||
Import(FileBrowserCommand),
|
||||
/// Export to file
|
||||
Export(FileBrowserCommand),
|
||||
}
|
||||
impl PoolCommand {
|
||||
pub fn from_edn <'a> (head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum MidiPoolCommand {
|
||||
Add(usize, MidiClip),
|
||||
|
|
@ -42,6 +90,20 @@ impl MidiPoolCommand {
|
|||
}
|
||||
}
|
||||
|
||||
/// Modes for clip pool
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PoolMode {
|
||||
/// Renaming a pattern
|
||||
Rename(usize, Arc<str>),
|
||||
/// Editing the length of a pattern
|
||||
Length(usize, usize, ClipLengthFocus),
|
||||
/// Load clip from disk
|
||||
Import(usize, FileBrowser),
|
||||
/// Save clip to disk
|
||||
Export(usize, FileBrowser),
|
||||
}
|
||||
|
||||
|
||||
impl<T: HasClips> Command<T> for MidiPoolCommand {
|
||||
fn execute (self, model: &mut T) -> Perhaps<Self> {
|
||||
use MidiPoolCommand::*;
|
||||
|
|
@ -108,38 +170,6 @@ impl<T: HasClips> Command<T> for MidiPoolCommand {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PoolModel {
|
||||
pub visible: bool,
|
||||
/// Collection of clips
|
||||
pub clips: Arc<RwLock<Vec<Arc<RwLock<MidiClip>>>>>,
|
||||
/// Selected clip
|
||||
pub clip: AtomicUsize,
|
||||
/// Mode switch
|
||||
pub mode: Option<PoolMode>,
|
||||
/// Rendered size
|
||||
size: Measure<TuiOut>,
|
||||
/// Scroll offset
|
||||
scroll: usize,
|
||||
}
|
||||
impl Default for PoolModel {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
visible: true,
|
||||
clips: Arc::from(RwLock::from(vec![])),
|
||||
clip: 0.into(),
|
||||
scroll: 0,
|
||||
mode: None,
|
||||
size: Measure::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
from!(|clip:&Arc<RwLock<MidiClip>>|PoolModel = {
|
||||
let mut model = Self::default();
|
||||
model.clips.write().unwrap().push(clip.clone());
|
||||
model.clip.store(1, Relaxed);
|
||||
model
|
||||
});
|
||||
|
||||
pub struct PoolView<'a>(pub bool, pub &'a PoolModel);
|
||||
render!(TuiOut: (self: PoolView<'a>) => {
|
||||
|
|
@ -167,41 +197,6 @@ render!(TuiOut: (self: PoolView<'a>) => {
|
|||
})))))
|
||||
});
|
||||
|
||||
/// Modes for clip pool
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PoolMode {
|
||||
/// Renaming a pattern
|
||||
Rename(usize, Arc<str>),
|
||||
/// Editing the length of a pattern
|
||||
Length(usize, usize, ClipLengthFocus),
|
||||
/// Load clip from disk
|
||||
Import(usize, FileBrowser),
|
||||
/// Save clip to disk
|
||||
Export(usize, FileBrowser),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum PoolCommand {
|
||||
Show(bool),
|
||||
/// Update the contents of the clip pool
|
||||
Clip(MidiPoolCommand),
|
||||
/// Select a clip from the clip pool
|
||||
Select(usize),
|
||||
/// Rename a clip
|
||||
Rename(ClipRenameCommand),
|
||||
/// Change the length of a clip
|
||||
Length(ClipLengthCommand),
|
||||
/// Import from file
|
||||
Import(FileBrowserCommand),
|
||||
/// Export to file
|
||||
Export(FileBrowserCommand),
|
||||
}
|
||||
impl PoolCommand {
|
||||
pub fn from_edn <'a> (head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
command!(|self:PoolCommand, state: PoolModel|{
|
||||
use PoolCommand::*;
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,54 @@ impl TrackCommand {
|
|||
StopAll,
|
||||
Clear,
|
||||
}
|
||||
command!(|self: AppCommand, state: App|match self {
|
||||
Self::Clear => { todo!() },
|
||||
Self::Clock(cmd) => cmd.delegate(state, Self::Clock)?,
|
||||
Self::History(delta) => { todo!("undo/redo") },
|
||||
Self::Select(s) => { state.selected = s; None },
|
||||
Self::Scene(cmd) => cmd.delegate(state, Self::Scene)?,
|
||||
Self::Track(cmd) => cmd.delegate(state, Self::Track)?,
|
||||
Self::Zoom(_) => { todo!(); },
|
||||
|
||||
Self::Editor(cmd) =>
|
||||
state.editor.as_mut().map(|editor|cmd.delegate(editor, Self::Editor)).transpose()?.flatten(),
|
||||
Self::Sampler(cmd) =>
|
||||
state.sampler.as_mut().map(|sampler|cmd.delegate(sampler, Self::Sampler)).transpose()?.flatten(),
|
||||
Self::Enqueue(clip) =>
|
||||
state.player.as_mut().map(|player|{player.enqueue_next(clip.as_ref());None}).flatten(),
|
||||
Self::StopAll => {
|
||||
for track in 0..state.tracks.len() { state.tracks[track].player.enqueue_next(None); }
|
||||
None
|
||||
},
|
||||
Self::Color(palette) => {
|
||||
let old = state.color;
|
||||
state.color = palette;
|
||||
Some(Self::Color(old))
|
||||
},
|
||||
|
||||
Self::Pool(cmd) => match cmd {
|
||||
// autoselect: automatically load selected clip in editor
|
||||
PoolCommand::Select(_) => {
|
||||
let undo = cmd.delegate(&mut state.pool, Self::Pool)?;
|
||||
state.editor.set_clip(state.pool.clip().as_ref());
|
||||
undo
|
||||
},
|
||||
// update color in all places simultaneously
|
||||
PoolCommand::Clip(PoolCmd::SetColor(index, _)) => {
|
||||
let undo = cmd.delegate(&mut state.pool, Self::Pool)?;
|
||||
state.editor.set_clip(state.pool.clip().as_ref());
|
||||
undo
|
||||
},
|
||||
_ => cmd.delegate(&mut state.pool, Self::Pool)?
|
||||
},
|
||||
|
||||
Self::Compact(compact) => if state.compact != compact {
|
||||
state.compact = compact;
|
||||
Some(Self::Compact(!compact))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
});
|
||||
|
||||
command!(|self: SequencerCommand, state: Sequencer|match self {
|
||||
Self::Clock(cmd) => cmd.delegate(state, Self::Clock)?,
|
||||
|
|
|
|||
117
tek/src/model.rs
117
tek/src/model.rs
|
|
@ -86,62 +86,11 @@ impl App {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[derive(Default)] pub struct Sequencer {
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub compact: bool,
|
||||
pub editor: MidiEditor,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub player: MidiPlayer,
|
||||
pub pool: PoolModel,
|
||||
pub selectors: bool,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
pub transport: bool,
|
||||
}
|
||||
has_size!(<TuiOut>|self:Sequencer|&self.size);
|
||||
has_clock!(|self:Sequencer|&self.player.clock);
|
||||
has_clips!(|self:Sequencer|self.pool.clips);
|
||||
has_editor!(|self:Sequencer|self.editor);
|
||||
has_size!(<TuiOut>|self: App|&self.size);
|
||||
has_clock!(|self: App|&self.clock);
|
||||
has_clips!(|self: App|self.pool.clips);
|
||||
has_editor!(|self: App|self.editor);
|
||||
|
||||
#[derive(Default)] pub struct Groovebox {
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub compact: bool,
|
||||
pub editor: MidiEditor,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub player: MidiPlayer,
|
||||
pub pool: PoolModel,
|
||||
pub sampler: Sampler,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
}
|
||||
has_clock!(|self: Groovebox|self.player.clock());
|
||||
|
||||
#[derive(Default)] pub struct Arranger {
|
||||
pub clock: Clock,
|
||||
pub color: ItemPalette,
|
||||
pub compact: bool,
|
||||
pub editing: AtomicBool,
|
||||
pub editor: MidiEditor,
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub midi_ins: Vec<JackPort<MidiIn>>,
|
||||
pub midi_outs: Vec<JackPort<MidiOut>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub pool: PoolModel,
|
||||
pub scenes: Vec<ArrangerScene>,
|
||||
pub selected: ArrangerSelection,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub splits: [u16;2],
|
||||
pub tracks: Vec<ArrangerTrack>,
|
||||
}
|
||||
has_clock!(|self: Arranger|&self.clock);
|
||||
has_clips!(|self: Arranger|self.pool.clips);
|
||||
has_editor!(|self: Arranger|self.editor);
|
||||
#[derive(Debug)] pub struct ArrangerTrack {
|
||||
/// Name of track
|
||||
pub name: Arc<str>,
|
||||
|
|
@ -217,3 +166,61 @@ impl ArrangerSelection {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)] pub struct Sequencer {
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub compact: bool,
|
||||
pub editor: MidiEditor,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub player: MidiPlayer,
|
||||
pub pool: PoolModel,
|
||||
pub selectors: bool,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
pub transport: bool,
|
||||
}
|
||||
has_size!(<TuiOut>|self:Sequencer|&self.size);
|
||||
has_clock!(|self:Sequencer|&self.player.clock);
|
||||
has_clips!(|self:Sequencer|self.pool.clips);
|
||||
has_editor!(|self:Sequencer|self.editor);
|
||||
has_player!(|self:Sequencer|self.player);
|
||||
|
||||
#[derive(Default)] pub struct Groovebox {
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub compact: bool,
|
||||
pub editor: MidiEditor,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub player: MidiPlayer,
|
||||
pub pool: PoolModel,
|
||||
pub sampler: Sampler,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
}
|
||||
has_clock!(|self: Groovebox|self.player.clock());
|
||||
|
||||
#[derive(Default)] pub struct Arranger {
|
||||
pub clock: Clock,
|
||||
pub color: ItemPalette,
|
||||
pub compact: bool,
|
||||
pub editing: AtomicBool,
|
||||
pub editor: MidiEditor,
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub midi_ins: Vec<JackPort<MidiIn>>,
|
||||
pub midi_outs: Vec<JackPort<MidiOut>>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub perf: PerfModel,
|
||||
pub pool: PoolModel,
|
||||
pub scenes: Vec<ArrangerScene>,
|
||||
pub selected: ArrangerSelection,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub splits: [u16;2],
|
||||
pub tracks: Vec<ArrangerTrack>,
|
||||
}
|
||||
has_clock!(|self: Arranger|&self.clock);
|
||||
has_clips!(|self: Arranger|self.pool.clips);
|
||||
has_editor!(|self: Arranger|self.editor);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue