autocreate on tab

This commit is contained in:
🪞👃🪞 2025-01-16 17:22:20 +01:00
parent c08d1bee5d
commit 2a5af2c753
2 changed files with 65 additions and 49 deletions

View file

@ -1,8 +1,7 @@
use crate::*;
use KeyCode::*;
pub type ClipPool = Vec<Arc<RwLock<MidiClip>>>;
pub trait HasClips {
fn clips <'a> (&'a self) -> std::sync::RwLockReadGuard<'a, ClipPool>;
fn clips <'a> (&'a self) -> std::sync::RwLockReadGuard<'a, ClipPool>;
fn clips_mut <'a> (&'a self) -> std::sync::RwLockWriteGuard<'a, ClipPool>;
fn add_clip (&self) -> (usize, Arc<RwLock<MidiClip>>) {
let clip = Arc::new(RwLock::new(MidiClip::new("Clip", true, 384, None, None)));
@ -13,7 +12,7 @@ pub trait HasClips {
#[macro_export] macro_rules! has_clips {
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => {
impl $(<$($L),*$($T $(: $U)?),*>)? HasClips for $Struct $(<$($L),*$($T),*>)? {
fn clips <'a> (&'a $self) -> std::sync::RwLockReadGuard<'a, ClipPool> {
fn clips <'a> (&'a $self) -> std::sync::RwLockReadGuard<'a, ClipPool> {
$cb.read().unwrap()
}
fn clips_mut <'a> (&'a $self) -> std::sync::RwLockWriteGuard<'a, ClipPool> {
@ -63,26 +62,11 @@ from!(|clip:&Arc<RwLock<MidiClip>>|MidiPool = {
has_clips!(|self: MidiPool|self.clips);
has_clip!(|self: MidiPool|self.clips().get(self.clip_index()).map(|c|c.clone()));
impl MidiPool {
pub(crate) fn clip_index (&self) -> usize {
self.clip.load(Relaxed)
}
pub(crate) fn set_clip_index (&self, value: usize) {
self.clip.store(value, Relaxed);
}
pub(crate) fn mode (&self) -> &Option<PoolMode> {
&self.mode
}
pub(crate) fn mode_mut (&mut self) -> &mut Option<PoolMode> {
&mut self.mode
}
pub fn file_picker (&self) -> Option<&FileBrowser> {
match self.mode {
Some(PoolMode::Import(_, ref file_picker)) => Some(file_picker),
Some(PoolMode::Export(_, ref file_picker)) => Some(file_picker),
_ => None
}
}
pub fn begin_clip_length (&mut self) {
fn clip_index (&self) -> usize { self.clip.load(Relaxed) }
fn set_clip_index (&self, value: usize) { self.clip.store(value, Relaxed); }
fn mode (&self) -> &Option<PoolMode> { &self.mode }
fn mode_mut (&mut self) -> &mut Option<PoolMode> { &mut self.mode }
fn begin_clip_length (&mut self) {
let length = self.clips()[self.clip_index()].read().unwrap().length;
*self.mode_mut() = Some(PoolMode::Length(
self.clip_index(),
@ -90,21 +74,21 @@ impl MidiPool {
ClipLengthFocus::Bar
));
}
pub fn begin_clip_rename (&mut self) {
fn begin_clip_rename (&mut self) {
let name = self.clips()[self.clip_index()].read().unwrap().name.clone();
*self.mode_mut() = Some(PoolMode::Rename(
self.clip_index(),
name
));
}
pub fn begin_import (&mut self) -> Usually<()> {
fn begin_import (&mut self) -> Usually<()> {
*self.mode_mut() = Some(PoolMode::Import(
self.clip_index(),
FileBrowser::new(None)?
));
Ok(())
}
pub fn begin_export (&mut self) -> Usually<()> {
fn begin_export (&mut self) -> Usually<()> {
*self.mode_mut() = Some(PoolMode::Export(
self.clip_index(),
FileBrowser::new(None)?
@ -116,34 +100,34 @@ impl MidiPool {
#[derive(Clone)]
pub struct ClipLength {
/// Pulses per beat (quaver)
pub ppq: usize,
ppq: usize,
/// Beats per bar
pub bpb: usize,
bpb: usize,
/// Length of clip in pulses
pub pulses: usize,
pulses: usize,
/// Selected subdivision
pub focus: Option<ClipLengthFocus>,
focus: Option<ClipLengthFocus>,
}
impl ClipLength {
pub fn new (pulses: usize, focus: Option<ClipLengthFocus>) -> Self {
fn new (pulses: usize, focus: Option<ClipLengthFocus>) -> Self {
Self { ppq: PPQ, bpb: 4, pulses, focus }
}
pub fn bars (&self) -> usize {
fn bars (&self) -> usize {
self.pulses / (self.bpb * self.ppq)
}
pub fn beats (&self) -> usize {
fn beats (&self) -> usize {
(self.pulses % (self.bpb * self.ppq)) / self.ppq
}
pub fn ticks (&self) -> usize {
fn ticks (&self) -> usize {
self.pulses % self.ppq
}
pub fn bars_string (&self) -> Arc<str> {
fn bars_string (&self) -> Arc<str> {
format!("{}", self.bars()).into()
}
pub fn beats_string (&self) -> Arc<str> {
fn beats_string (&self) -> Arc<str> {
format!("{}", self.beats()).into()
}
pub fn ticks_string (&self) -> Arc<str> {
fn ticks_string (&self) -> Arc<str> {
format!("{:>02}", self.ticks()).into()
}
}
@ -158,17 +142,17 @@ pub enum ClipLengthFocus {
Tick,
}
impl ClipLengthFocus {
pub fn next (&mut self) {
fn next (&mut self) {
*self = match self { Self::Bar => Self::Beat, Self::Beat => Self::Tick, Self::Tick => Self::Bar, }
}
pub fn prev (&mut self) {
fn prev (&mut self) {
*self = match self { Self::Bar => Self::Tick, Self::Beat => Self::Bar, Self::Tick => Self::Beat, }
}
}
pub struct PoolView<'a>(pub bool, pub &'a MidiPool);
content!(TuiOut: |self: PoolView<'a>| {
let Self(compact, model) = self;
let MidiPool { clips, mode, .. } = self.1;
let MidiPool { clips, .. } = self.1;
//let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||TuiTheme::g(32).into());
let on_bg = |x|x;//Bsp::b(Repeat(" "), Tui::bg(color.darkest.rgb, x));
let border = |x|x;//Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)).enclose(x);
@ -237,16 +221,30 @@ handle!(TuiIn: |self: MidiPool, input|{
})
});
edn_provide!(bool: |self: MidiPool| {});
edn_provide!(MidiClip: |self: MidiPool| {
":new-clip" => MidiClip::new(
"Clip", true, 4 * PPQ, None, Some(ItemPalette::random())
),
":cloned-clip" => {
impl MidiPool {
pub fn new_clip (&self) -> MidiClip {
MidiClip::new("Clip", true, 4 * PPQ, None, Some(ItemPalette::random()))
}
pub fn cloned_clip (&self) -> MidiClip {
let index = self.clip_index();
let mut clip = self.clips()[index].read().unwrap().duplicate();
clip.color = ItemPalette::random_near(clip.color, 0.25);
clip
}
pub fn add_new_clip (&self) -> (usize, Arc<RwLock<MidiClip>>) {
let clip = Arc::new(RwLock::new(self.new_clip()));
let index = {
let mut clips = self.clips.write().unwrap();
clips.push(clip.clone());
clips.len().saturating_sub(1)
};
self.clip.store(index, Relaxed);
(index, clip)
}
}
edn_provide!(MidiClip: |self: MidiPool| {
":new-clip" => self.new_clip(),
":cloned-clip" => self.cloned_clip(),
});
edn_provide!(PathBuf: |self: MidiPool| {});
edn_provide!(Arc<str>: |self: MidiPool| {});