diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 7b13bfcf..ce9b5bed 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -26,6 +26,8 @@ pub struct Tek { pub note_buf: Vec, /// Buffer for writing a chunk of midi events pub midi_buf: Vec>>, + /// Last track number (to avoid duplicate port names) + pub track_last: usize, /// List of tracks pub tracks: Vec, /// Scroll offset of tracks @@ -87,12 +89,21 @@ impl Tek { mins: &[PortConnect], mouts: &[PortConnect], ) -> Usually<(usize, &mut Track)> { - let name = name.map_or_else(||self.track_next_name(), |x|x.to_string().into()); + self.track_last += 1; + let name: Arc = name.map_or_else( + ||format!("Track{:02}", self.track_last).into(), + |x|x.to_string().into() + ); let mut track = Track { width: (name.len() + 2).max(12), color: color.unwrap_or_else(ItemTheme::random), player: MidiPlayer::new( - &format!("{name}"), self.jack(), Some(self.clock()), None, mins, mouts + &format!("{name}"), + self.jack(), + Some(self.clock()), + None, + mins, + mouts )?, name, ..Default::default() @@ -120,11 +131,22 @@ impl Tek { } /// Delete a track - pub fn track_del (&mut self, index: usize) { - self.tracks_mut().remove(index); - for scene in self.scenes_mut().iter_mut() { - scene.clips.remove(index); + pub fn track_del (&mut self, index: usize) -> Usually<()> { + let exists = self.tracks().get(index).is_some(); + if exists { + let track = self.tracks_mut().remove(index); + let Track { player: MidiPlayer { midi_ins, midi_outs, .. }, .. } = track; + for port in midi_ins.into_iter() { + port.close()?; + } + for port in midi_outs.into_iter() { + port.close()?; + } + for scene in self.scenes_mut().iter_mut() { + scene.clips.remove(index); + } } + Ok(()) } /// Add multiple scenes @@ -578,9 +600,6 @@ pub trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max) } const WIDTH_OFFSET: usize = 1; - fn track_next_name (&self) -> Arc { - format!("Track{:02}", self.tracks().len() + 1).into() - } fn track (&self) -> Option<&Track> { self.selected().track().and_then(|s|self.tracks().get(s)) } diff --git a/crates/jack/src/jack_client.rs b/crates/jack/src/jack_client.rs index 80b97587..ad89c7ae 100644 --- a/crates/jack/src/jack_client.rs +++ b/crates/jack/src/jack_client.rs @@ -55,7 +55,7 @@ impl HasJack for &Jack { /// Wraps [JackState] and through it [jack::Client]. #[derive(Clone, Debug, Default)] pub struct Jack { - state: Arc> + pub state: Arc> } impl Jack { @@ -99,7 +99,8 @@ impl Jack { /// This is a connection which may be [Inactive], [Activating], or [Active]. /// In the [Active] and [Inactive] states, [JackState::client] returns a /// [jack::Client], which you can use to talk to the JACK API. -#[derive(Debug, Default)] enum JackState { +#[derive(Debug, Default)] +pub enum JackState { /// Unused #[default] Inert, /// Before activation. diff --git a/crates/jack/src/jack_port.rs b/crates/jack/src/jack_port.rs index a5f474ec..5c34b748 100644 --- a/crates/jack/src/jack_port.rs +++ b/crates/jack/src/jack_port.rs @@ -14,9 +14,6 @@ macro_rules! impl_port { } impl AsRef> for $Name { fn as_ref (&self) -> &Port<$Spec> { &self.port } } impl $Name { - pub fn name (&self) -> &Arc { &self.name } - pub fn port (&self) -> &Port<$Spec> { &self.port } - pub fn port_mut (&mut self) -> &mut Port<$Spec> { &mut self.port } pub fn new ($jack: &Jack, name: impl AsRef, connect: &[PortConnect]) -> Usually { @@ -29,6 +26,14 @@ macro_rules! impl_port { port.connect_to_matching()?; Ok(port) } + pub fn name (&self) -> &Arc { &self.name } + pub fn port (&self) -> &Port<$Spec> { &self.port } + pub fn port_mut (&mut self) -> &mut Port<$Spec> { &mut self.port } + pub fn into_port (self) -> Port<$Spec> { self.port } + pub fn close (self) -> Usually<()> { + let Self { jack, port, .. } = self; + Ok(jack.with_client(|client|client.unregister_port(port))?) + } } impl HasJack for $Name { fn jack (&self) -> &Jack { &self.jack } } impl JackPort for $Name { diff --git a/deps/tengri b/deps/tengri index 44ebe17c..2b208e3c 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit 44ebe17c665b3a65e7a3a0020eff290093fc7ed2 +Subproject commit 2b208e3c497d595f7dad5a6d190dfe08f7fb9dc0