wip: down to 13 errors

This commit is contained in:
🪞👃🪞 2025-05-14 14:35:19 +03:00
parent 6ce83fb27a
commit ebdb8881e9
19 changed files with 793 additions and 691 deletions

View file

@ -6,27 +6,21 @@ pub struct App {
pub jack: Jack,
/// Port handles
pub ports: std::collections::BTreeMap<u32, Port<Unowned>>,
/// Source of time
pub clock: Clock,
/// Display size
pub size: Measure<TuiOut>,
/// Performance counter
pub perf: PerfModel,
// View and input definition
pub config: Configuration,
/// Undo history
pub history: Vec<AppCommand>,
// Dialog overlay
pub dialog: Option<Dialog>,
/// Browses external resources, such as directories
pub browser: Option<Browser>,
/// Contains all clips in the project
pub pool: Option<Pool>,
/// Contains the currently edited MIDI clip
pub editor: Option<MidiEditor>,
pub config: Configuration,
/// Contains the currently edited musical arrangement
pub arranger: Arrangement,
pub project: Arrangement,
/// Undo history
pub history: Vec<AppCommand>,
// Dialog overlay
pub dialog: Option<Dialog>,
/// Contains the currently edited MIDI clip
pub editor: Option<MidiEditor>,
// Cache of formatted strings
pub view_cache: Arc<RwLock<ViewCache>>,
@ -34,11 +28,12 @@ pub struct App {
pub color: ItemTheme,
}
has!(Option<Selection>: |self: App|self.arrangement.selected);
has!(Vec<JackMidiIn>: |self: App|self.arrangement.midi_ins);
has!(Vec<JackMidiOut>: |self: App|self.arrangement.midi_outs);
has!(Vec<Scene>: |self: App|self.arrangement.scenes);
has!(Vec<Track>: |self: App|self.arrangement.tracks);
has!(Option<Selection>: |self: App|self.project.selected);
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);
impl App {
pub fn toggle_dialog (&mut self, dialog: Option<Dialog>) {
@ -67,11 +62,85 @@ impl App {
}
pub(crate) fn device_add (&mut self, index: usize) -> Usually<()> {
match index {
0 => self.arrangement.device_add_sampler(),
1 => self.arrangement.device_add_lv2(),
0 => self.device_add_sampler(),
1 => self.device_add_lv2(),
_ => unreachable!(),
}
}
fn device_add_lv2 (&mut self) -> Usually<()> {
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();
let sampler = if let Ok(sampler) = Sampler::new(
jack,
&format!("{}/Sampler", Has::<Track>::get(self).name),
&[PortConnect::exact(format!("{name}:{midi}"))],
&[&[], &[]],
&[&[], &[]]
) {
self.dialog = None;
Device::Sampler(sampler)
} else {
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);
Ok(())
}
// Create new clip in pool when entering empty cell
fn clip_auto_create (&mut self) -> Option<Arc<RwLock<MidiClip>>> {
if let Some(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)
&& slot.is_none()
&& let Some(track) = Has::<Vec<Track>>::get_mut(self).get_mut(*track)
{
let (index, mut clip) = 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) {
editor.set_clip(Some(&clip));
}
*slot = Some(clip.clone());
Some(clip)
} else {
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()
{
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());
}
}
}
}
}
/// Various possible dialog overlays
@ -81,8 +150,8 @@ pub enum Dialog {
Menu,
Device(usize),
Message(Message),
Save,
Load,
Save(Browser),
Load(Browser),
Options,
}
@ -234,27 +303,4 @@ impl App {
0
}
}
fn device_add_lv2 (&mut self) -> Usually<()> {
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();
let sampler = if let Ok(sampler) = Sampler::new(
jack,
&format!("{}/Sampler", Has::<Track>::get(self).name),
&[PortConnect::exact(format!("{name}:{midi}"))],
&[&[], &[]],
&[&[], &[]]
) {
self.dialog = None;
Device::Sampler(sampler)
} else {
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);
Ok(())
}
}