fix setting colors

This commit is contained in:
🪞👃🪞 2025-01-27 22:48:30 +01:00
parent a16e5361d1
commit 0999c42f12
10 changed files with 93 additions and 48 deletions

View file

@ -86,7 +86,7 @@ macro_rules! transform_xy_unit {
let u = iter.next().expect("no unit specified");
let c = iter.next().expect("no content specified");
let u = state.get(&u.value).expect("no unit provided");
let c = state.get_content(&c.value).expect("not content provided");
let c = state.get_content(&c.value).expect("no content provided");
return Some(match k {
$x => Self::x(u, c),
$y => Self::y(u, c),
@ -99,7 +99,7 @@ macro_rules! transform_xy_unit {
let c = iter.next().expect("no content specified");
let u = state.get(&u.value).expect("no unit provided");
let v = state.get(&v.value).expect("no unit provided");
let c = state.get_content(&c.value).expect("not content provided");
let c = state.get_content(&c.value).expect("no content provided");
return Some(Self::xy(u, v, c))
}
}

View file

@ -44,9 +44,9 @@ pub struct TekCli {
/// Multi-track MIDI sequencer.
Arranger {
/// Number of scenes
#[arg(short = 'y', long, default_value_t = 1)] scenes: usize,
#[arg(short = 'y', long, default_value_t = 12)] scenes: usize,
/// Number of tracks
#[arg(short = 'x', long, default_value_t = 1)] tracks: usize,
#[arg(short = 'x', long, default_value_t = 16)] tracks: usize,
/// Width of tracks
#[arg(short = 'w', long, default_value_t = 12)] track_width: usize,
},

View file

@ -55,7 +55,8 @@ atom_command!(TekCommand: |app: Tek| {
("zoom" [z: usize] Some(Self::Zoom(z)))
("edit" [] Some(Self::Edit(None)))
("edit" [c: bool] Some(Self::Edit(c)))
("color" [c: Color] Some(Self::Color(c.map(ItemPalette::from).unwrap_or_default())))
("color" [c: Color] Some(Self::Color(ItemPalette::random())))
("color" [c: Color] Some(Self::Color(c.map(ItemPalette::from).expect("no color"))))
("enqueue" [c: Arc<RwLock<MidiClip>>] Some(Self::Enqueue(c)))
("clip" [,..a] ClipCommand::try_from_expr(app, a).map(Self::Clip))
("clock" [,..a] ClockCommand::try_from_expr(app.clock(), a).map(Self::Clock))
@ -107,7 +108,7 @@ command!(|self: TekCommand, app: Tek|match self {
let (index, mut clip) = pool.add_new_clip();
// autocolor: new clip colors from scene and track color
clip.write().unwrap().color = ItemColor::random_near(
app.tracks[t.saturating_sub(1)].color.base.mix(
app.tracks[t].color.base.mix(
scene.color.base,
0.5
),
@ -146,20 +147,16 @@ command!(|self: TekCommand, app: Tek|match self {
old
},
Track(t) => {
let t = t.saturating_sub(1);
let old = app.tracks[t].color;
app.tracks[t].color = palette;
old
}
Scene(s) => {
let s = s.saturating_sub(1);
let old = app.scenes[s].color;
app.scenes[s].color = palette;
old
}
Clip(t, s) => {
let t = t.saturating_sub(1);
let s = s.saturating_sub(1);
if let Some(ref clip) = app.scenes[s].clips[t] {
let mut clip = clip.write().unwrap();
let old = clip.color;
@ -229,9 +226,9 @@ atom_command!(TrackCommand: |app: Tek| {
("add" [] Some(Self::Add))
("size" [a: usize] Some(Self::SetSize(a.unwrap())))
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
("color" [a: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random())))
("del" [a: usize] Some(Self::Del(a.unwrap().saturating_sub(1))))
("stop" [a: usize] Some(Self::Stop(a.unwrap().saturating_sub(1))))
("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemPalette::random())))
("del" [a: usize] Some(Self::Del(a.unwrap())))
("stop" [a: usize] Some(Self::Stop(a.unwrap())))
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
("play" [] Some(Self::TogglePlay))
("solo" [] Some(Self::ToggleSolo))
@ -289,8 +286,8 @@ atom_command!(SceneCommand: |app: Tek| {
("add" [] Some(Self::Add))
("del" [a: usize] Some(Self::Del(0)))
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
("color" [a: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random())))
("enqueue" [a: usize] Some(Self::Enqueue(a.unwrap().saturating_sub(1))))
("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemPalette::G[128])))
("enqueue" [a: usize] Some(Self::Enqueue(a.unwrap())))
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
});
command!(|self: SceneCommand, app: Tek|match self {
@ -327,12 +324,12 @@ command!(|self: SceneCommand, app: Tek|match self {
SetColor(usize, usize, ItemPalette),
}
atom_command!(ClipCommand: |app: Tek| {
("get" [a: usize ,b: usize] Some(Self::Get(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1))))
("put" [a: usize, b: usize, c: Option<Arc<RwLock<MidiClip>>>] Some(Self::Put(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap())))
("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1))))
("get" [a: usize, b: usize] Some(Self::Get(a.unwrap(), b.unwrap())))
("put" [a: usize, b: usize, c: Option<Arc<RwLock<MidiClip>>>] Some(Self::Put(a.unwrap(), b.unwrap(), c.unwrap())))
("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap(), b.unwrap())))
("edit" [a: Option<Arc<RwLock<MidiClip>>>] Some(Self::Edit(a.unwrap())))
("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap())))
("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), ItemPalette::random())))
("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap(), b.unwrap(), c.unwrap())))
("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap(), b.unwrap(), ItemPalette::random())))
});
command!(|self: ClipCommand, app: Tek|match self {
Self::Get(track, scene) => { todo!() },
@ -345,5 +342,14 @@ command!(|self: ClipCommand, app: Tek|match self {
app.tracks[track].player.enqueue_next(app.scenes[scene].clips[track].as_ref());
None
},
Self::SetColor(track, scene, color) => {
app.scenes[scene].clips[track].as_ref().map(|clip|{
let mut clip = clip.write().unwrap();
let old = clip.color.clone();
clip.color = color.clone();
panic!("{color:?} {old:?}");
Self::SetColor(track, scene, old)
})
},
_ => None
});

View file

@ -1,4 +1,4 @@
(@q clip launch :track :scene)
(@q clip enqueue :track :scene)
(@c clip color :track :scene)
(@g clip get)
(@p clip put)

View file

@ -20,8 +20,9 @@ view!(TuiOut: |self: Tek| self.size.of(View(self, self.view)); {
":sampler" => ().boxed(),//self.view_sampler(self.is_editing(), &self.editor).boxed(),
":scene-add" => self.view_scene_add().boxed(),
":scenes" => self.view_scenes().boxed(),
":status" => self.view_editor().boxed(),
":toolbar" => self.view_clock().boxed(),
":transport" => self.view_transport().boxed(),
":status" => self.view_status().boxed(),
":tracks" => self.view_tracks().boxed(),
});
provide_num!(u16: |self: Tek| {
@ -50,8 +51,6 @@ impl Tek {
pub(crate) fn w (&self) -> u16 { self.size.w() as u16 }
pub(crate) fn h (&self) -> u16 { self.size.h() as u16 }
pub(crate) fn w_sidebar (&self) -> u16 { self.w() / if self.is_editing() { 16 } else { 8 } as u16 }
pub(crate) fn w_tracks_area (&self) -> u16 { self.w().saturating_sub(2 * self.w_sidebar()) }
pub(crate) fn h_tracks_area (&self) -> u16 { self.h().saturating_sub(self.h_inputs() + self.h_outputs() + 10) }
pub(crate) fn row <'a> (
&'a self,
w: u16,
@ -77,10 +76,10 @@ impl Tek {
c: impl Content<TuiOut> + 'a,
) -> impl Content<TuiOut> + 'a {
Fixed::y(h, Bsp::a(
Fill::x(Align::n(Fixed::x(w, Align::x(Tui::bg(Green, b))))),
Fill::x(Align::n(Fixed::x(w, Align::x(Tui::bg(Reset, b))))),
Bsp::a(
Fill::x(Align::nw(Fixed::x(self.w_sidebar() as u16, Tui::bg(Red, a)))),
Fill::x(Align::ne(Fixed::x(self.w_sidebar() as u16, Tui::bg(Yellow, c)))),
Fill::x(Align::nw(Fixed::x(self.w_sidebar() as u16, Tui::bg(Reset, a)))),
Fill::x(Align::ne(Fixed::x(self.w_sidebar() as u16, Tui::bg(Reset, c)))),
),
))
}

View file

@ -1,5 +1,4 @@
(bsp/n
(fixed/y 2 :toolbar)
(fill/xy (bsp/a
(fill/xy (align/e :pool))
(bsp/s :inputs (bsp/s :tracks (bsp/n :outputs :scenes))))))
(bsp/n (fixed/y 1 :transport)
(bsp/s (fixed/y 1 :status)
(fill/xy (bsp/a (fill/xy (align/e :pool))
(bsp/s :inputs (bsp/s :tracks (bsp/n :outputs :scenes)))))))

View file

@ -46,6 +46,32 @@ impl Tek {
)))
)
}
pub(crate) fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
self.update_clock();
let theme = ItemPalette::G[96];
let fmtd = self.fmtd.read().unwrap();
Tui::bg(Black, row!(Bsp::a(
Fill::xy(Align::w(self.view_play_pause())),
Fill::xy(Align::e(row!(
FieldH(theme, "BPM", fmtd.bpm.view.clone()),
FieldH(theme, "Beat", fmtd.beat.view.clone()),
FieldH(theme, "Time", fmtd.time.view.clone())
)))
)))
}
pub(crate) fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
self.update_clock();
let theme = ItemPalette::G[96];
let fmtd = self.fmtd.read().unwrap();
Tui::bg(Black, row!(Bsp::a(
Fill::xy(Align::w(FieldH(theme, "Sel", self.selected.describe(&self.tracks, &self.scenes)))),
Fill::xy(Align::e(row!(
FieldH(theme, "SR", fmtd.sr.view.clone()),
FieldH(theme, "Buf", fmtd.buf.view.clone()),
FieldH(theme, "Lat", fmtd.lat.view.clone()),
)))
)))
}
fn view_play_pause (&self) -> impl Content<TuiOut> + use<'_> {
let playing = self.clock.is_rolling();
let compact = true;//self.is_editing();

View file

@ -1,15 +1,18 @@
use crate::*;
impl Tek {
const H_SCENE: usize = 2;
const H_EDITOR: usize = 15;
pub(crate) fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 {
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)}
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
}
pub(crate) fn scenes_sizes (&self, editing: bool, height: usize, larger: usize) -> impl ScenesSizes<'_> {
let mut y = 0;
let (selected_track, selected_scene) = match self.selected() {
Selection::Track(t) => (Some(*t), None),
Selection::Scene(s) => (None, Some(*s)),
Selection::Clip(t, s) => (Some(*t), Some(*s)),
_ => (None, None)
};
let mut y = 0;
self.scenes().iter().enumerate().map(move|(s, scene)|{
let active = editing && selected_track.is_some() && selected_scene == Some(s);
let height = if active { larger } else { height };
@ -19,22 +22,24 @@ impl Tek {
pub fn view_scenes (&self) -> impl Content<TuiOut> + use<'_> {
let w_full = self.w();
let w = self.w_tracks_area();
let h = self.h_tracks_area();
let h_area = self.h_tracks_area();
let editing = self.is_editing();
let selected_track = self.selected().track();
let selected_scene = self.selected().scene();
let h = self.h_scenes(editing, Self::H_SCENE, Self::H_EDITOR);
let scene_names = Map::new(
move||self.scenes_with_colors(editing, h),
move||self.scenes_with_colors(editing, h_area),
move|(s, scene, y1, y2, prev): SceneColor, _|self.view_scene_name(
w_full, (1 + y2 - y1) as u16, y1 as u16, s, scene, prev));
let scene_clips = self.per_track(move|t, track|Map::new(
move||self.scenes_with_track_colors(editing, h, t),
move||self.scenes_with_track_colors(editing, h_area, t),
move|(s, scene, y1, y2, prev): SceneColor, _|self.view_scene_clip(
w, (1 + y2 - y1) as u16, y1 as u16,
scene, prev, s, t, editing, selected_track == Some(t), selected_scene)));
Tui::bg(Black, self.row_top(self.w_tracks_area(), h, scene_names, scene_clips, ())) }
Tui::bg(Reset, Fixed::y(self.h_tracks_area(),
self.row(self.w_tracks_area(), h, scene_names, scene_clips, ()))) }
fn scenes_with_colors (&self, editing: bool, h: u16) -> impl ScenesColors<'_> {
self.scenes_sizes(editing, 2, 15).map_while(
self.scenes_sizes(editing, Self::H_SCENE, Self::H_EDITOR).map_while(
move|(s, scene, y1, y2)|if y2 as u16 > h {
None
} else { Some((s, scene, y1, y2, if s == 0 {
@ -50,9 +55,9 @@ impl Tek {
let fg = scene.color.lightest.rgb;
let name = Some(scene.name.clone());
let cell = self.view_scene_cell(true, s, &bg, prev, name, "", fg);
map_south(offset, height, Fixed::y(height, cell)) }
Fill::x(map_south(offset, height, Fixed::y(height, cell))) }
fn scenes_with_track_colors (&self, editing: bool, h: u16, t: usize) -> impl ScenesColors<'_> {
self.scenes_sizes(editing, 2, 15).map_while(
self.scenes_sizes(editing, Self::H_SCENE, Self::H_EDITOR).map_while(
move|(s, scene, y1, y2)|if y2 as u16 > h {
None
} else { Some((s, scene, y1, y2, if s == 0 {
@ -92,8 +97,12 @@ impl Tek {
let neighbor = same_track && scene > 0 && selected_scene == Some(scene - 1);
let is_last = scene == self.scenes.len().saturating_sub(1);
let colors = Self::colors(color, prev, selected, neighbor, is_last);
let content = Fill::x(Align::w(Tui::fg(fg, Tui::bold(true, Bsp::e(icon, name)))));
Phat { width: 0, height: 0, selected, content, colors, } }
Self::cell(icon, name, colors) }
fn cell <'a> (
icon: &'a str, name: Option<Arc<str>>, colors: [Color;4]
) -> impl Content<TuiOut> + use<'a> {
let content = Fill::x(Align::w(Tui::bold(true, Bsp::e(icon, name))));
Phat { width: 0, height: 0, content, colors, } }
const TAB: &str = " Tab";
pub fn view_scene_add (&self) -> impl Content<TuiOut> + use<'_> {
let data = (self.selected().scene().unwrap_or(0), self.scenes().len());

View file

@ -1,5 +1,15 @@
use crate::*;
impl Tek {
pub(crate) fn w_tracks_area (&self) -> u16 {
self.w().saturating_sub(2 * self.w_sidebar())
}
pub(crate) fn w_tracks (&self, editing: bool, bigger: usize) -> u16 {
self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
}
pub(crate) fn h_tracks_area (&self) -> u16 {
self.h().saturating_sub(self.h_inputs() + self.h_outputs() + 10)
}
pub fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
let w = (self.size.w() as u16).saturating_sub(2 * self.w_sidebar());
let data = (self.selected.track().unwrap_or(0), self.tracks().len());
@ -27,15 +37,12 @@ impl Tek {
let width = self.w_tracks_area();
let filter = move|(t, track, x1, x2)|if x2 as u16 >= width {None} else {Some((t, track, x1, x2))};
let tracks = move||self.tracks_sizes(self.is_editing(), self.editor_w()).map_while(filter);
Align::x(Tui::bg(Green, Map::new(tracks, move|(index, track, x1, x2), _|{
Align::x(Tui::bg(Reset, Map::new(tracks, move|(index, track, x1, x2), _|{
let width = (x2 - x1) as u16;
map_east(x1 as u16, width, Fixed::x(width, Tui::fg_bg(
track.color.lightest.rgb,
track.color.base.rgb,
f(index, track)))) }))) }
pub(crate) fn w_tracks (&self, editing: bool, bigger: usize) -> u16 {
self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
}
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize) -> impl TracksSizes<'a> {
let mut x = 0;
let active = match self.selected() {

View file

@ -116,7 +116,6 @@ pub struct Phat<T> {
pub height: u16,
pub content: T,
pub colors: [Color;4],
pub selected: bool,
}
impl<T> Phat<T> {
/// A phat line