last small wave of 15 errors?

This commit is contained in:
🪞👃🪞 2025-05-14 17:15:27 +03:00
parent 4fe51b5267
commit 872c2d94d6
11 changed files with 181 additions and 189 deletions

View file

@ -28,12 +28,14 @@ pub struct App {
pub color: ItemTheme,
}
has!(Option<Selection>: |self: App|self.project.selection);
has!(Vec<JackMidiIn>: |self: App|self.project.midi_ins);
has!(Vec<JackMidiOut>: |self: App|self.project.midi_outs);
has!(Vec<Scene>: |self: App|self.project.scenes);
has!(Vec<Track>: |self: App|self.project.tracks);
has!(Clock: |self: App|self.project.clock);
has!(Jack: |self: App|self.jack);
has!(Clock: |self: App|self.project.clock);
has!(Selection: |self: App|self.project.selection);
has!(Vec<JackMidiIn>: |self: App|self.project.midi_ins);
has!(Vec<JackMidiOut>: |self: App|self.project.midi_outs);
has!(Vec<Scene>: |self: App|self.project.scenes);
has!(Vec<Track>: |self: App|self.project.tracks);
has_size!(<TuiOut>|self: App|&self.size);
has_clips!(|self: App|self.project.pool.clips);
has_editor!(|self: App|{
@ -46,24 +48,28 @@ has_editor!(|self: App|{
(5 + (time_len / time_zoom)).min(size.saturating_sub(20)).max(16)
};
editor_h = 15;
is_editing = self.editing.load(Relaxed);
is_editing = self.editor.is_some();
});
impl App {
pub fn toggle_dialog (&mut self, dialog: Option<Dialog>) {
self.dialog = if self.dialog == dialog {
None
} else {
dialog
}
pub fn toggle_dialog (&mut self, mut dialog: Option<Dialog>) -> Option<Dialog> {
std::mem::swap(&mut self.dialog, &mut dialog);
dialog
}
pub fn toggle_editor (&mut self, value: Option<bool>) {
self.editing.store(value.unwrap_or_else(||!self.is_editing()), Relaxed);
self.arranger.map(|arranger|if value {
arranger.clip_auto_create();
//FIXME: self.editing.store(value.unwrap_or_else(||!self.is_editing()), Relaxed);
let value = value.unwrap_or_else(||!self.editor.is_some());
if value {
self.clip_auto_create();
} else {
arranger.clip_auto_remove();
});
self.clip_auto_remove();
}
}
pub fn browser (&self) -> Option<&Browser> {
self.dialog.as_ref().and_then(|dialog|match dialog {
Dialog::Save(b) | Dialog::Load(b) => Some(b),
_ => None
})
}
pub(crate) fn device_pick (&mut self, index: usize) {
self.dialog = Some(Dialog::Device(index));
@ -85,15 +91,14 @@ impl App {
todo!();
Ok(())
}
fn device_add_sampler (&mut self, jack: &Jack) -> Usually<usize> {
let name = jack.with_client(|c|c.name().to_string());
let midi = self.track().expect("no active track").sequencer.midi_outs[0].name();
fn device_add_sampler (&mut self) -> Usually<()> {
let name = self.jack.with_client(|c|c.name().to_string());
let midi = self.project.track().expect("no active track").sequencer.midi_outs[0].name();
let track = self.track().expect("no active track");
let port = format!("{}/Sampler", &track.name);
let connect = PortConnect::exact(format!("{name}:{midi}"));
let sampler = if let Ok(sampler) = Sampler::new(
jack,
&format!("{}/Sampler", Has::<Track>::get(self).name),
&[PortConnect::exact(format!("{name}:{midi}"))],
&[&[], &[]],
&[&[], &[]]
&self.jack, &port, &[connect], &[&[], &[]], &[&[], &[]]
) {
self.dialog = None;
Device::Sampler(sampler)
@ -101,22 +106,23 @@ impl App {
self.dialog = Some(Dialog::Message(Message::FailedToAddDevice));
return Err("failed to add device".into())
};
Has::<Track>::get_mut(self).expect("no active track").devices.push(sampler);
let track = self.track_mut().expect("no active track");
track.devices.push(sampler);
Ok(())
}
// Create new clip in pool when entering empty cell
fn clip_auto_create (&mut self) -> Option<Arc<RwLock<MidiClip>>> {
if let Some(Selection::TrackClip { track, scene }) = self.get()
&& let Some(scene) = Has::<Vec<Scene>>::get_mut(self).get_mut(scene)
if let Selection::TrackClip { track, scene } = *self.selection()
&& let Some(scene) = self.project.scenes.get_mut(scene)
&& let Some(slot) = scene.clips.get_mut(track)
&& slot.is_none()
&& let Some(track) = Has::<Vec<Track>>::get_mut(self).get_mut(track)
&& let Some(track) = self.project.tracks.get_mut(track)
{
let (index, mut clip) = self.arranger.pool.add_new_clip();
let (index, mut clip) = self.project.pool.add_new_clip();
// autocolor: new clip colors from scene and track color
let color = track.color.base.mix(scene.color.base, 0.5);
clip.write().unwrap().color = ItemColor::random_near(color, 0.2).into();
if let Some(ref mut editor) = Has::<Option<MidiEditor>>::get_mut(self) {
if let Some(ref mut editor) = self.editor {
editor.set_clip(Some(&clip));
}
*slot = Some(clip.clone());
@ -125,37 +131,24 @@ impl App {
None
}
}
}
#[cfg(all(feature = "pool", feature = "editor"))]
pub trait AutoRemove:
Has<Vec<Scene>> +
Has<Vec<Track>> +
Has<Option<MidiEditor>> +
Has<Option<Selection>> +
Has<Option<Pool>> +
Send + Sync
{
// Remove clip from arrangement when exiting empty clip editor
fn clip_auto_remove (&mut self) {
if let Some(ref mut pool) = Has::<Option<Pool>>::get(self)
&& let Some(Selection::TrackClip { track, scene }) = self.get()
&& let Some(scene) = Has::<Vec<Scene>>::get_mut(self).get_mut(*scene)
&& let Some(slot) = scene.clips.get_mut(*track)
&& let Some(clip) = slot.as_mut()
if let Selection::TrackClip { track, scene } = *self.selection()
&& let Some(scene) = self.project.scenes.get_mut(scene)
&& let Some(slot) = scene.clips.get_mut(track)
&& let Some(clip) = slot.as_mut()
{
let mut swapped = None;
if clip.read().unwrap().count_midi_messages() == 0 {
std::mem::swap(&mut swapped, slot);
}
if let Some(clip) = swapped {
pool.delete_clip(&clip.read().unwrap());
self.project.pool.delete_clip(&clip.read().unwrap());
}
}
}
}
/// Various possible dialog overlays
#[derive(Clone, Debug)]
pub enum Dialog {
@ -197,7 +190,7 @@ impl App {
matches!(self.dialog, Some(Dialog::Device(..)))
}
fn focus_browser (&self) -> bool {
self.browser.is_visible
self.browser().is_some()
}
fn focus_clip (&self) -> bool {
!self.is_editing() && self.selection().is_clip()
@ -212,16 +205,16 @@ impl App {
!self.is_editing() && self.selection().is_mix()
}
fn focus_pool_import (&self) -> bool {
matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Import(..)))
matches!(self.project.pool.mode, Some(PoolMode::Import(..)))
}
fn focus_pool_export (&self) -> bool {
matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Export(..)))
matches!(self.project.pool.mode, Some(PoolMode::Export(..)))
}
fn focus_pool_rename (&self) -> bool {
matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Rename(..)))
matches!(self.project.pool.mode, Some(PoolMode::Rename(..)))
}
fn focus_pool_length (&self) -> bool {
matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..)))
matches!(self.project.pool.mode, Some(PoolMode::Length(..)))
}
fn dialog_device (&self) -> Dialog {
Dialog::Device(0) // TODO
@ -239,10 +232,10 @@ impl App {
Dialog::Menu
}
fn dialog_save (&self) -> Dialog {
Dialog::Save
Dialog::Save(Default::default())
}
fn dialog_load (&self) -> Dialog {
Dialog::Load
Dialog::Load(Default::default())
}
fn dialog_options (&self) -> Dialog {
Dialog::Options
@ -251,13 +244,13 @@ impl App {
Some((self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into())
}
fn scene_count (&self) -> usize {
self.scenes.len()
self.scenes().len()
}
fn scene_selection (&self) -> Option<usize> {
self.selection().scene()
}
fn track_count (&self) -> usize {
self.tracks.len()
self.tracks().len()
}
fn track_selection (&self) -> Option<usize> {
self.selection().track()
@ -279,7 +272,7 @@ impl App {
}
fn clip_selection (&self) -> Option<Arc<RwLock<MidiClip>>> {
match self.selection() {
Selection::TrackClip { track, scene } => self.scenes()[scene].clips[track].clone(),
Selection::TrackClip { track, scene } => self.scenes()[*scene].clips[*track].clone(),
_ => None
}
}