arranger: spawning clips once again!1

This commit is contained in:
🪞👃🪞 2025-05-17 12:22:43 +03:00
parent b663c53b0a
commit 48603e4812
6 changed files with 41 additions and 18 deletions

View file

@ -1,7 +1,7 @@
(@c color) (@c color)
(@q launch) (@q launch)
(@t select :select-track-header) (@t select :select-track-header)
(@tab edit :clip) (@tab edit :clip-selected)
(@shift-I input add) (@shift-I input add)
(@shift-O output add) (@shift-O output add)
(@shift-S scene add) (@shift-S scene add)

View file

@ -18,6 +18,20 @@ 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 edit (app: &mut App) -> Perhaps<Self> {
let selection = app.selection().clone();
Ok(match selection {
Selection::TrackClip { track, scene } => {
let clip = &mut app.scenes_mut()[scene].clips[track];
if clip.is_none() {
*clip = Some(Default::default());
}
app.editor = clip.as_ref().map(|c|c.into());
None
}
_ => None
})
}
fn dialog (app: &mut App, dialog: Option<Dialog>) -> Perhaps<Self> { fn dialog (app: &mut App, dialog: Option<Dialog>) -> Perhaps<Self> {
app.toggle_dialog(dialog); app.toggle_dialog(dialog);
Ok(None) Ok(None)

View file

@ -3,25 +3,25 @@ use crate::*;
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct App { pub struct App {
/// Must not be dropped for the duration of the process /// Must not be dropped for the duration of the process
pub jack: Jack, pub jack: Jack,
/// Port handles /// Port handles
pub ports: std::collections::BTreeMap<u32, Port<Unowned>>, pub ports: std::collections::BTreeMap<u32, Port<Unowned>>,
/// Display size /// Display size
pub size: Measure<TuiOut>, pub size: Measure<TuiOut>,
/// Performance counter /// Performance counter
pub perf: PerfModel, pub perf: PerfModel,
// View and input definition // View and input definition
pub config: Configuration, pub config: Configuration,
/// Contains all recently created clips.
pub pool: Pool,
/// Contains the currently edited musical arrangement /// Contains the currently edited musical arrangement
pub project: Arrangement, pub project: Arrangement,
/// Undo history /// Undo history
pub history: Vec<AppCommand>, pub history: Vec<AppCommand>,
// Dialog overlay // Dialog overlay
pub dialog: Option<Dialog>, pub dialog: Option<Dialog>,
/// Contains the currently edited MIDI clip /// Contains the currently edited MIDI clip
pub editor: Option<MidiEditor>, pub editor: Option<MidiEditor>,
// Cache of formatted strings // Cache of formatted strings
pub view_cache: Arc<RwLock<ViewCache>>, pub view_cache: Arc<RwLock<ViewCache>>,
/// Base color. /// Base color.
@ -29,6 +29,7 @@ pub struct App {
} }
has!(Jack: |self: App|self.jack); has!(Jack: |self: App|self.jack);
has!(Pool: |self: App|self.pool);
has!(Clock: |self: App|self.project.clock); has!(Clock: |self: App|self.project.clock);
has!(Selection: |self: App|self.project.selection); has!(Selection: |self: App|self.project.selection);
has!(Vec<JackMidiIn>: |self: App|self.project.midi_ins); has!(Vec<JackMidiIn>: |self: App|self.project.midi_ins);
@ -39,16 +40,15 @@ has!(Measure<TuiOut>: |self: App|self.size);
maybe_has!(Track: |self: App| maybe_has!(Track: |self: App|
{ MaybeHas::<Track>::get(&self.project) }; { MaybeHas::<Track>::get(&self.project) };
{ MaybeHas::<Track>::get_mut(&mut self.project) }); { MaybeHas::<Track>::get_mut(&mut self.project) });
impl HasTrackScroll for App {
fn track_scroll (&self) -> usize { self.project.track_scroll() }
}
maybe_has!(Scene: |self: App| maybe_has!(Scene: |self: App|
{ MaybeHas::<Scene>::get(&self.project) }; { MaybeHas::<Scene>::get(&self.project) };
{ MaybeHas::<Scene>::get_mut(&mut self.project) }); { MaybeHas::<Scene>::get_mut(&mut self.project) });
impl HasSceneScroll for App { impl HasSceneScroll for App {
fn scene_scroll (&self) -> usize { self.project.scene_scroll() } fn scene_scroll (&self) -> usize { self.project.scene_scroll() }
} }
impl HasTrackScroll for App {
fn track_scroll (&self) -> usize { self.project.track_scroll() }
}
has_clips!(|self: App|self.project.pool.clips); has_clips!(|self: App|self.project.pool.clips);
has_editor!(|self: App|{ has_editor!(|self: App|{
editor = self.editor; editor = self.editor;
@ -312,7 +312,7 @@ impl App {
fn select_track_prev (&self) -> Selection { fn select_track_prev (&self) -> Selection {
self.selection().track_prev() self.selection().track_prev()
} }
fn clip_selection (&self) -> Option<Arc<RwLock<MidiClip>>> { fn clip_selected (&self) -> Option<Arc<RwLock<MidiClip>>> {
match self.selection() { match self.selection() {
Selection::TrackClip { track, scene } => self.scenes()[*scene].clips[*track].clone(), Selection::TrackClip { track, scene } => self.scenes()[*scene].clips[*track].clone(),
_ => None _ => None

View file

@ -168,11 +168,11 @@ impl Arrangement {
mins: &[PortConnect], mins: &[PortConnect],
mouts: &[PortConnect], mouts: &[PortConnect],
) -> Usually<(usize, &mut Track)> { ) -> Usually<(usize, &mut Track)> {
self.track_last += 1;
let name: Arc<str> = name.map_or_else( let name: Arc<str> = name.map_or_else(
||format!("Track{:02}", self.track_last).into(), ||format!("t{:02}", self.track_last).into(),
|x|x.to_string().into() |x|x.to_string().into()
); );
self.track_last += 1;
let mut track = Track { let mut track = Track {
width: (name.len() + 2).max(12), width: (name.len() + 2).max(12),
color: color.unwrap_or_else(ItemTheme::random), color: color.unwrap_or_else(ItemTheme::random),

View file

@ -28,7 +28,7 @@ pub trait HasScenes: Has<Vec<Scene>> + Send + Sync {
} }
/// Generate the default name for a new scene /// Generate the default name for a new scene
fn scene_default_name (&self) -> Arc<str> { fn scene_default_name (&self) -> Arc<str> {
format!("Sc{:3>}", self.scenes().len() + 1).into() format!("s{:3>}", self.scenes().len() + 1).into()
} }
fn scene_longest_name (&self) -> usize { fn scene_longest_name (&self) -> usize {
self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max) self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max)

View file

@ -207,8 +207,12 @@ pub trait TracksView: HasSize<TuiOut> + HasTrackScroll + HasSelection + HasMidiI
.tracks_with_sizes(&self.selection(), None) .tracks_with_sizes(&self.selection(), None)
.skip(self.track_scroll()) .skip(self.track_scroll())
{ {
(add)(&Fixed::x(track.width as u16, add(&Fixed::x(track.width as u16,
Tui::bg(track.color.base.rgb, Align::nw(Tui::fg( Tui::bg(if self.selection().track() == Some(index) {
track.color.light.rgb
} else {
track.color.base.rgb
}, Align::nw(Tui::fg(
Rgb(255, 255, 255), Tui::bold(true, Rgb(255, 255, 255), Tui::bold(true,
format!("{}", track.name))))))); format!("{}", track.name)))))));
} }
@ -424,18 +428,23 @@ pub trait ClipsView: TracksView + ScenesView + Send + Sync {
(None, ItemTheme::G[32]) (None, ItemTheme::G[32])
}; };
let fg = theme.lightest.rgb; let fg = theme.lightest.rgb;
let mut outline = theme.base.rgb;
let bg = if self.selection().track() == Some(track_index) let bg = if self.selection().track() == Some(track_index)
&& self.selection().scene() == Some(scene_index) && self.selection().scene() == Some(scene_index)
{ {
outline = theme.lightest.rgb;
theme.light.rgb theme.light.rgb
} else if self.selection().track() == Some(track_index) } else if self.selection().track() == Some(track_index)
|| self.selection().scene() == Some(scene_index) || self.selection().scene() == Some(scene_index)
{ {
outline = theme.darkest.rgb;
theme.base.rgb theme.base.rgb
} else { } else {
theme.dark.rgb theme.dark.rgb
}; };
cell(&Fixed::xy(track.width as u16, 2, Tui::fg_bg(fg, bg, Align::nw(name.unwrap_or(" ---- ".into()))))); cell(&Fixed::xy(track.width as u16, 2, Bsp::b(
Fill::xy(Outer(true, Style::default().fg(outline))),
Fill::xy(Align::nw(Tui::fg_bg(fg, bg, Align::nw(name.unwrap_or(" ---- ".into()))))))));
//let (name, theme) = if let Some(clip) = &scene.clips.get(track_index).flatten() { //let (name, theme) = if let Some(clip) = &scene.clips.get(track_index).flatten() {
//let clip = clip.read().unwrap(); //let clip = clip.read().unwrap();
//(Some(clip.name.clone()), clip.color) //(Some(clip.name.clone()), clip.color)