Compare commits

...

4 commits

Author SHA1 Message Date
7b432d12b4 replace track_next_name with monotonic counter
Some checks are pending
/ build (push) Waiting to run
2025-05-01 01:23:12 +03:00
3c2d490f83 track: remove ports on delete 2025-05-01 01:20:12 +03:00
80964d5b4a jack: add Port::close 2025-05-01 01:19:01 +03:00
57e0f64056 bump tengri 2025-05-01 01:18:37 +03:00
4 changed files with 40 additions and 15 deletions

View file

@ -26,6 +26,8 @@ pub struct Tek {
pub note_buf: Vec<u8>, pub note_buf: Vec<u8>,
/// Buffer for writing a chunk of midi events /// Buffer for writing a chunk of midi events
pub midi_buf: Vec<Vec<Vec<u8>>>, pub midi_buf: Vec<Vec<Vec<u8>>>,
/// Last track number (to avoid duplicate port names)
pub track_last: usize,
/// List of tracks /// List of tracks
pub tracks: Vec<Track>, pub tracks: Vec<Track>,
/// Scroll offset of tracks /// Scroll offset of tracks
@ -87,12 +89,21 @@ impl Tek {
mins: &[PortConnect], mins: &[PortConnect],
mouts: &[PortConnect], mouts: &[PortConnect],
) -> Usually<(usize, &mut Track)> { ) -> 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<str> = name.map_or_else(
||format!("Track{:02}", self.track_last).into(),
|x|x.to_string().into()
);
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),
player: MidiPlayer::new( player: MidiPlayer::new(
&format!("{name}"), self.jack(), Some(self.clock()), None, mins, mouts &format!("{name}"),
self.jack(),
Some(self.clock()),
None,
mins,
mouts
)?, )?,
name, name,
..Default::default() ..Default::default()
@ -120,11 +131,22 @@ impl Tek {
} }
/// Delete a track /// Delete a track
pub fn track_del (&mut self, index: usize) { pub fn track_del (&mut self, index: usize) -> Usually<()> {
self.tracks_mut().remove(index); let exists = self.tracks().get(index).is_some();
for scene in self.scenes_mut().iter_mut() { if exists {
scene.clips.remove(index); 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 /// 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) self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max)
} }
const WIDTH_OFFSET: usize = 1; const WIDTH_OFFSET: usize = 1;
fn track_next_name (&self) -> Arc<str> {
format!("Track{:02}", self.tracks().len() + 1).into()
}
fn track (&self) -> Option<&Track> { fn track (&self) -> Option<&Track> {
self.selected().track().and_then(|s|self.tracks().get(s)) self.selected().track().and_then(|s|self.tracks().get(s))
} }

View file

@ -55,7 +55,7 @@ impl HasJack for &Jack {
/// Wraps [JackState] and through it [jack::Client]. /// Wraps [JackState] and through it [jack::Client].
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct Jack { pub struct Jack {
state: Arc<RwLock<JackState>> pub state: Arc<RwLock<JackState>>
} }
impl Jack { impl Jack {
@ -99,7 +99,8 @@ impl Jack {
/// This is a connection which may be [Inactive], [Activating], or [Active]. /// This is a connection which may be [Inactive], [Activating], or [Active].
/// In the [Active] and [Inactive] states, [JackState::client] returns a /// In the [Active] and [Inactive] states, [JackState::client] returns a
/// [jack::Client], which you can use to talk to the JACK API. /// [jack::Client], which you can use to talk to the JACK API.
#[derive(Debug, Default)] enum JackState { #[derive(Debug, Default)]
pub enum JackState {
/// Unused /// Unused
#[default] Inert, #[default] Inert,
/// Before activation. /// Before activation.

View file

@ -14,9 +14,6 @@ macro_rules! impl_port {
} }
impl AsRef<Port<$Spec>> for $Name { fn as_ref (&self) -> &Port<$Spec> { &self.port } } impl AsRef<Port<$Spec>> for $Name { fn as_ref (&self) -> &Port<$Spec> { &self.port } }
impl $Name { impl $Name {
pub fn name (&self) -> &Arc<str> { &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<str>, connect: &[PortConnect]) pub fn new ($jack: &Jack, name: impl AsRef<str>, connect: &[PortConnect])
-> Usually<Self> -> Usually<Self>
{ {
@ -29,6 +26,14 @@ macro_rules! impl_port {
port.connect_to_matching()?; port.connect_to_matching()?;
Ok(port) Ok(port)
} }
pub fn name (&self) -> &Arc<str> { &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 HasJack for $Name { fn jack (&self) -> &Jack { &self.jack } }
impl JackPort for $Name { impl JackPort for $Name {

2
deps/tengri vendored

@ -1 +1 @@
Subproject commit 44ebe17c665b3a65e7a3a0020eff290093fc7ed2 Subproject commit 2b208e3c497d595f7dad5a6d190dfe08f7fb9dc0