add new Selection variants

This commit is contained in:
🪞👃🪞 2025-05-01 16:18:00 +03:00
parent 7b432d12b4
commit 8adbdc5bc7
4 changed files with 161 additions and 109 deletions

View file

@ -23,7 +23,7 @@ expose!([self: Tek]
(":track" self.selected.track())) (":track" self.selected.track()))
([MaybeClip] ([MaybeClip]
(":clip" match self.selected { (":clip" match self.selected {
Selection::Clip(t, s) => self.scenes[s].clips[t].clone(), Selection::TrackClip { track, scene } => self.scenes[scene].clips[track].clone(),
_ => None _ => None
})) }))
([Selection] ([Selection]
@ -70,7 +70,7 @@ impose!([app: Tek]
(0, 0) => Self::Select(Selection::Mix), (0, 0) => Self::Select(Selection::Mix),
(t, 0) => Self::Select(Selection::Track(t)), (t, 0) => Self::Select(Selection::Track(t)),
(0, s) => Self::Select(Selection::Scene(s)), (0, s) => Self::Select(Selection::Scene(s)),
(t, s) => Self::Select(Selection::Clip(t, s)) }))) (t, s) => Self::Select(Selection::TrackClip { track: t, scene: s }) })))
(ClipCommand: (ClipCommand:
("edit" [a: MaybeClip] Some(Self::Edit(a.unwrap()))) ("edit" [a: MaybeClip] Some(Self::Edit(a.unwrap())))

View file

@ -121,10 +121,11 @@ impl Tek {
/// Add and focus a track /// Add and focus a track
pub(crate) fn track_add_focus (&mut self) -> Usually<usize> { pub(crate) fn track_add_focus (&mut self) -> Usually<usize> {
use Selection::*;
let index = self.track_add(None, None, &[], &[])?.0; let index = self.track_add(None, None, &[], &[])?.0;
self.selected = match self.selected { self.selected = match self.selected {
Selection::Track(t) => Selection::Track(index), Track(_) => Track(index),
Selection::Clip(t, s) => Selection::Clip(index, s), TrackClip { track, scene } => TrackClip { track: index, scene },
_ => self.selected _ => self.selected
}; };
Ok(index) Ok(index)
@ -177,10 +178,11 @@ impl Tek {
/// Add and focus an empty scene /// Add and focus an empty scene
pub fn scene_add_focus (&mut self) -> Usually<usize> { pub fn scene_add_focus (&mut self) -> Usually<usize> {
use Selection::*;
let index = self.scene_add(None, None)?.0; let index = self.scene_add(None, None)?.0;
self.selected = match self.selected { self.selected = match self.selected {
Selection::Scene(s) => Selection::Scene(index), Scene(_) => Scene(index),
Selection::Clip(t, s) => Selection::Clip(t, index), TrackClip { track, scene } => TrackClip { track, scene: index },
_ => self.selected _ => self.selected
}; };
Ok(index) Ok(index)
@ -215,15 +217,15 @@ impl Tek {
// Create new clip in pool when entering empty cell // Create new clip in pool when entering empty cell
pub fn clip_auto_create (&mut self) { pub fn clip_auto_create (&mut self) {
if let Some(ref pool) = self.pool if let Some(ref pool) = self.pool
&& let Selection::Clip(t, s) = self.selected && let Selection::TrackClip { track, scene } = self.selected
&& let Some(scene) = self.scenes.get_mut(s) && let Some(scene) = self.scenes.get_mut(scene)
&& let Some(slot) = scene.clips.get_mut(t) && let Some(slot) = scene.clips.get_mut(track)
&& slot.is_none() && slot.is_none()
{ {
let (index, mut clip) = pool.add_new_clip(); let (index, mut clip) = pool.add_new_clip();
// autocolor: new clip colors from scene and track color // autocolor: new clip colors from scene and track color
clip.write().unwrap().color = ItemColor::random_near( clip.write().unwrap().color = ItemColor::random_near(
self.tracks[t].color.base.mix( self.tracks[track].color.base.mix(
scene.color.base, scene.color.base,
0.5 0.5
), ),
@ -239,9 +241,9 @@ impl Tek {
// Remove clip from arrangement when exiting empty clip editor // Remove clip from arrangement when exiting empty clip editor
pub fn clip_auto_remove (&mut self) { pub fn clip_auto_remove (&mut self) {
if let Some(ref mut pool) = self.pool if let Some(ref mut pool) = self.pool
&& let Selection::Clip(t, s) = self.selected && let Selection::TrackClip { track, scene } = self.selected
&& let Some(scene) = self.scenes.get_mut(s) && let Some(scene) = self.scenes.get_mut(scene)
&& let Some(slot) = scene.clips.get_mut(t) && let Some(slot) = scene.clips.get_mut(track)
&& let Some(clip) = slot.as_mut() && let Some(clip) = slot.as_mut()
{ {
let mut swapped = None; let mut swapped = None;
@ -304,8 +306,10 @@ impl Tek {
// autoedit: load focused clip in editor. // autoedit: load focused clip in editor.
if let Some(ref mut editor) = self.editor { if let Some(ref mut editor) = self.editor {
editor.set_clip(match self.selected { editor.set_clip(match self.selected {
Selection::Clip(t, s) if let Some(Some(Some(clip))) = self Selection::TrackClip { track, scene }
.scenes.get(s).map(|s|s.clips.get(t)) => Some(clip), if let Some(Some(Some(clip))) = self
.scenes.get(scene)
.map(|s|s.clips.get(track)) => Some(clip),
_ => None _ => None
}); });
} }
@ -320,14 +324,15 @@ impl Tek {
/// Launch a clip or scene /// Launch a clip or scene
pub(crate) fn launch (&mut self) { pub(crate) fn launch (&mut self) {
use Selection::*;
match self.selected { match self.selected {
Selection::Track(t) => { Track(t) => {
self.tracks[t].player.enqueue_next(None) self.tracks[t].player.enqueue_next(None)
}, },
Selection::Clip(t, s) => { TrackClip { track, scene } => {
self.tracks[t].player.enqueue_next(self.scenes[s].clips[t].as_ref()) self.tracks[track].player.enqueue_next(self.scenes[scene].clips[track].as_ref())
}, },
Selection::Scene(s) => { Scene(s) => {
for t in 0..self.tracks.len() { for t in 0..self.tracks.len() {
self.tracks[t].player.enqueue_next(self.scenes[s].clips[t].as_ref()) self.tracks[t].player.enqueue_next(self.scenes[s].clips[t].as_ref())
} }
@ -348,25 +353,26 @@ impl Tek {
/// Set the color of the selected entity /// Set the color of the selected entity
pub fn set_color (&mut self, palette: Option<ItemTheme>) -> Option<ItemTheme> { pub fn set_color (&mut self, palette: Option<ItemTheme>) -> Option<ItemTheme> {
use Selection::*;
let palette = palette.unwrap_or_else(||ItemTheme::random()); let palette = palette.unwrap_or_else(||ItemTheme::random());
Some(match self.selected { Some(match self.selected {
Selection::Mix => { Mix => {
let old = self.color; let old = self.color;
self.color = palette; self.color = palette;
old old
}, },
Selection::Track(t) => { Scene(s) => {
let old = self.tracks[t].color;
self.tracks[t].color = palette;
old
}
Selection::Scene(s) => {
let old = self.scenes[s].color; let old = self.scenes[s].color;
self.scenes[s].color = palette; self.scenes[s].color = palette;
old old
} }
Selection::Clip(t, s) => { Track(t) => {
if let Some(ref clip) = self.scenes[s].clips[t] { let old = self.tracks[t].color;
self.tracks[t].color = palette;
old
}
TrackClip { track, scene } => {
if let Some(ref clip) = self.scenes[scene].clips[track] {
let mut clip = clip.write().unwrap(); let mut clip = clip.write().unwrap();
let old = clip.color; let old = clip.color;
clip.color = palette; clip.color = palette;
@ -374,7 +380,8 @@ impl Tek {
} else { } else {
return None return None
} }
} },
_ => todo!()
}) })
} }
@ -426,12 +433,22 @@ pub enum Modal {
pub enum Selection { pub enum Selection {
/// The whole mix is selected /// The whole mix is selected
#[default] Mix, #[default] Mix,
/// A track is selected. /// A MIDI input is selected.
Track(usize), Input(usize),
/// A MIDI output is selected.
Output(usize),
/// A scene is selected. /// A scene is selected.
Scene(usize), Scene(usize),
/// A track is selected.
Track(usize),
/// A clip (track × scene) is selected. /// A clip (track × scene) is selected.
Clip(usize, usize), TrackClip { track: usize, scene: usize },
/// A track's MIDI input connection is selected.
TrackInput { track: usize, port: usize },
/// A track's MIDI output connection is selected.
TrackOutput { track: usize, port: usize },
/// A track device slot is selected.
TrackDevice { track: usize, device: usize },
} }
/// Focus identification methods /// Focus identification methods
@ -446,70 +463,101 @@ impl Selection {
matches!(self, Self::Scene(_)) matches!(self, Self::Scene(_))
} }
pub fn is_clip (&self) -> bool { pub fn is_clip (&self) -> bool {
matches!(self, Self::Clip(_, _)) matches!(self, Self::TrackClip {..})
} }
pub fn track (&self) -> Option<usize> { pub fn track (&self) -> Option<usize> {
use Selection::*; use Selection::*;
match self { Clip(t, _) => Some(*t), Track(t) => Some(*t), _ => None } match self {
Track(track)
| TrackClip { track, .. }
| TrackInput { track, .. }
| TrackOutput { track, .. }
| TrackDevice { track, .. } => Some(*track),
_ => None
}
} }
pub fn track_next (&self, len: usize) -> Self { pub fn track_next (&self, len: usize) -> Self {
use Selection::*;
match self { match self {
Selection::Mix => Selection::Track(0), Mix => Track(0),
Selection::Track(t) if t + 1 < len => Selection::Track(t + 1), Scene(s) => TrackClip { track: 0, scene: *s },
Selection::Track(t) => Selection::Mix, Track(t) => if t + 1 < len {
Selection::Scene(s) => Selection::Clip(0, *s), Track(t + 1)
Selection::Clip(t, s) if t + 1 < len => Selection::Clip(t + 1, *s), } else {
Selection::Clip(t, s) => Selection::Scene(*s), Mix
},
TrackClip {track, scene} => if track + 1 < len {
TrackClip { track: track + 1, scene: *scene }
} else {
Scene(*scene)
},
_ => todo!()
} }
} }
pub fn track_prev (&self) -> Self { pub fn track_prev (&self) -> Self {
use Selection::*;
match self { match self {
Selection::Mix => Selection::Mix, Mix => Mix,
Selection::Scene(s) => Selection::Scene(*s), Scene(s) => Scene(*s),
Selection::Track(0) => Selection::Mix, Track(0) => Mix,
Selection::Track(t) => Selection::Track(t - 1), Track(t) => Track(t - 1),
Selection::Clip(0, s) => Selection::Scene(*s), TrackClip { track: 0, scene } => Scene(*scene),
Selection::Clip(t, s) => Selection::Clip(t - 1, *s), TrackClip { track: t, scene } => TrackClip { track: t - 1, scene: *scene },
_ => todo!()
} }
} }
pub fn scene (&self) -> Option<usize> { pub fn scene (&self) -> Option<usize> {
use Selection::*; use Selection::*;
match self { Clip(_, s) => Some(*s), Scene(s) => Some(*s), _ => None } match self {
Scene(scene) | TrackClip { scene, .. } => Some(*scene),
_ => None
}
} }
pub fn scene_next (&self, len: usize) -> Self { pub fn scene_next (&self, len: usize) -> Self {
use Selection::*;
match self { match self {
Selection::Mix => Selection::Scene(0), Mix => Scene(0),
Selection::Track(t) => Selection::Clip(*t, 0), Track(t) => TrackClip { track: *t, scene: 0 },
Selection::Scene(s) if s + 1 < len => Selection::Scene(s + 1), Scene(s) => if s + 1 < len {
Selection::Scene(s) => Selection::Mix, Scene(s + 1)
Selection::Clip(t, s) if s + 1 < len => Selection::Clip(*t, s + 1), } else {
Selection::Clip(t, s) => Selection::Track(*t), Mix
},
TrackClip { track, scene } => if scene + 1 < len {
TrackClip { track: *track, scene: scene + 1 }
} else {
Track(*track)
},
_ => todo!()
} }
} }
pub fn scene_prev (&self) -> Self { pub fn scene_prev (&self) -> Self {
use Selection::*;
match self { match self {
Selection::Mix => Selection::Mix, Mix | Scene(0) => Mix,
Selection::Track(t) => Selection::Track(*t), Scene(s) => Scene(s - 1),
Selection::Scene(0) => Selection::Mix, Track(t) => Track(*t),
Selection::Scene(s) => Selection::Scene(s - 1), TrackClip { track, scene: 0 } => Track(*track),
Selection::Clip(t, 0) => Selection::Track(*t), TrackClip { track, scene } => TrackClip { track: *track, scene: scene - 1 },
Selection::Clip(t, s) => Selection::Clip(*t, s - 1), _ => todo!()
} }
} }
pub fn describe (&self, tracks: &[Track], scenes: &[Scene]) -> Arc<str> { pub fn describe (&self, tracks: &[Track], scenes: &[Scene]) -> Arc<str> {
use Selection::*;
format!("{}", match self { format!("{}", match self {
Self::Mix => "Everything".to_string(), Mix => "Everything".to_string(),
Self::Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name)) Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name))
.unwrap_or_else(||"T??".into()),
Self::Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name))
.unwrap_or_else(||"S??".into()), .unwrap_or_else(||"S??".into()),
Self::Clip(t, s) => match (tracks.get(*t), scenes.get(*s)) { Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name))
(Some(_), Some(scene)) => match scene.clip(*t) { .unwrap_or_else(||"T??".into()),
Some(clip) => format!("T{t} S{s} C{}", &clip.read().unwrap().name), TrackClip { track, scene } => match (tracks.get(*track), scenes.get(*scene)) {
None => format!("T{t} S{s}: Empty") (Some(_), Some(s)) => match s.clip(*track) {
Some(clip) => format!("T{track} S{scene} C{}", &clip.read().unwrap().name),
None => format!("T{track} S{scene}: Empty")
}, },
_ => format!("T{t} S{s}: Empty"), _ => format!("T{track} S{scene}: Empty"),
} },
_ => todo!()
}).into() }).into()
} }
} }

View file

@ -181,11 +181,12 @@ impl Tek {
} }
pub(crate) fn tracks_with_sizes (&self) -> impl TracksSizes<'_> { pub(crate) fn tracks_with_sizes (&self) -> impl TracksSizes<'_> {
use Selection::*;
let mut x = 0; let mut x = 0;
let editing = self.is_editing(); let editing = self.is_editing();
let active = match self.selected() { let active = match self.selected() {
Selection::Track(t) if editing => Some(t), Track(t) if editing => Some(t),
Selection::Clip(t, _) if editing => Some(t), TrackClip { track, .. } if editing => Some(track),
_ => None _ => None
}; };
let bigger = self.editor_w(); let bigger = self.editor_w();
@ -200,10 +201,11 @@ impl Tek {
pub(crate) fn scenes_with_sizes (&self, editing: bool, height: usize, larger: usize) pub(crate) fn scenes_with_sizes (&self, editing: bool, height: usize, larger: usize)
-> impl ScenesSizes<'_> -> impl ScenesSizes<'_>
{ {
use Selection::*;
let (selected_track, selected_scene) = match self.selected() { let (selected_track, selected_scene) = match self.selected() {
Selection::Track(t) => (Some(*t), None), Track(t) => (Some(*t), None),
Selection::Scene(s) => (None, Some(*s)), Scene(s) => (None, Some(*s)),
Selection::Clip(t, s) => (Some(*t), Some(*s)), TrackClip { track, scene } => (Some(*track), Some(*scene)),
_ => (None, None) _ => (None, None)
}; };
let mut y = 0; let mut y = 0;
@ -304,8 +306,10 @@ impl<'a> ArrangerView<'a> {
/// Render input matrix. /// Render input matrix.
pub(crate) fn inputs (&'a self) -> impl Content<TuiOut> + 'a { pub(crate) fn inputs (&'a self) -> impl Content<TuiOut> + 'a {
Tui::bg(Color::Reset, Tui::bg(Color::Reset, Bsp::s(
Bsp::s(Bsp::s(self.input_routes(), self.input_ports()), self.input_intos())) Bsp::s(self.input_routes(), self.input_ports()),
self.input_intos()
))
} }
fn input_routes (&'a self) -> impl Content<TuiOut> + 'a { fn input_routes (&'a self) -> impl Content<TuiOut> + 'a {
@ -313,13 +317,12 @@ impl<'a> ArrangerView<'a> {
.left(self.width_side, .left(self.width_side,
io_ports(Tui::g(224), Tui::g(32), ||self.app.inputs_with_sizes())) io_ports(Tui::g(224), Tui::g(32), ||self.app.inputs_with_sizes()))
.middle(self.width_mid, .middle(self.width_mid,
per_track_top( per_track_top(self.width_mid, ||self.app.tracks_with_sizes(),
self.width_mid, move|_, &Track { color, .. }|io_conns(
||self.app.tracks_with_sizes(), color.dark.rgb,
move|_, &Track { color, .. }|{ color.darker.rgb,
io_conns(color.dark.rgb, color.darker.rgb, ||self.app.inputs_with_sizes()) ||self.app.inputs_with_sizes()
} )))
))
} }
fn input_ports (&'a self) -> impl Content<TuiOut> + 'a { fn input_ports (&'a self) -> impl Content<TuiOut> + 'a {
@ -353,14 +356,12 @@ impl<'a> ArrangerView<'a> {
fn input_intos (&'a self) -> impl Content<TuiOut> + 'a { fn input_intos (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(2) Tryptich::top(2)
.left(self.width_side, .left(self.width_side,
Bsp::s(Align::e("Input:"), Align::e("Into:"))) Bsp::s(Align::e("Input:"), Align::e("Into clip:")))
.middle(self.width_mid, .middle(self.width_mid,
per_track_top( per_track_top(
self.width_mid, self.width_mid,
||self.app.tracks_with_sizes(), ||self.app.tracks_with_sizes(),
|_, _|{ |_, _|Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ ")))))
Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ ")))
}))
} }
/// Render output matrix. /// Render output matrix.
@ -370,20 +371,17 @@ impl<'a> ArrangerView<'a> {
Bsp::s(self.output_ports(), self.output_conns()), Bsp::s(self.output_ports(), self.output_conns()),
))) )))
} }
fn output_nexts (&'a self) -> impl Content<TuiOut> + 'a { fn output_nexts (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(2) Tryptich::top(2)
.left(self.width_side, Align::ne("From:")) .left(self.width_side, Align::ne("From clip:"))
.middle(self.width_mid, per_track_top( .middle(self.width_mid, per_track_top(
self.width_mid, self.width_mid,
||self.tracks_with_sizes_scrolled(), ||self.tracks_with_sizes_scrolled(),
|_, _|{ |_, _|Tui::bg(Reset, Align::c(Bsp::s(" ------ ", OctaveVertical::default())))))
Tui::bg(Reset, Align::c(Bsp::s(" ------ ", OctaveVertical::default())))
}))
} }
fn output_froms (&'a self) -> impl Content<TuiOut> + 'a { fn output_froms (&'a self) -> impl Content<TuiOut> + 'a {
Tryptich::top(2) Tryptich::top(2)
.left(self.width_side, Align::ne("Next:")) .left(self.width_side, Align::ne("Next clip:"))
.middle(self.width_mid, per_track_top( .middle(self.width_mid, per_track_top(
self.width_mid, self.width_mid,
||self.tracks_with_sizes_scrolled(), ||self.tracks_with_sizes_scrolled(),
@ -412,7 +410,11 @@ impl<'a> ArrangerView<'a> {
let solo = false; let solo = false;
let mute = if mute { White } else { t.color.darkest.rgb }; let mute = if mute { White } else { t.color.darkest.rgb };
let solo = if solo { White } else { t.color.darkest.rgb }; let solo = if solo { White } else { t.color.darkest.rgb };
let bg_1 = if self.track_selected == Some(i) { t.color.light.rgb } else { t.color.base.rgb }; let bg_1 = if self.track_selected == Some(i) {
t.color.light.rgb
} else {
t.color.base.rgb
};
let bg_2 = if i > 0 { t.color.base.rgb } else { Reset }; let bg_2 = if i > 0 { t.color.base.rgb } else { Reset };
let mute = Tui::fg_bg(mute, bg_1, "Play "); let mute = Tui::fg_bg(mute, bg_1, "Play ");
let solo = Tui::fg_bg(solo, bg_1, "Solo "); let solo = Tui::fg_bg(solo, bg_1, "Solo ");
@ -740,8 +742,9 @@ pub(crate) fn heading <'a> (
pub(crate) fn io_ports <'a, T: PortsSizes<'a>> ( pub(crate) fn io_ports <'a, T: PortsSizes<'a>> (
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
) -> impl Content<TuiOut> + 'a { ) -> impl Content<TuiOut> + 'a {
Map::new(iter, Map::new(iter, move|(
move|(index, name, connections, y, y2): (usize, &'a Arc<str>, &'a [PortConnect], usize, usize), _| index, name, connections, y, y2
): (usize, &'a Arc<str>, &'a [PortConnect], usize, usize), _|
map_south(y as u16, (y2-y) as u16, Bsp::s( map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(" 󰣲 ", name))))), Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(" 󰣲 ", name))))),
Map::new(||connections.iter(), move|connect: &'a PortConnect, index|map_south(index as u16, 1, Map::new(||connections.iter(), move|connect: &'a PortConnect, index|map_south(index as u16, 1,
@ -752,8 +755,9 @@ pub(crate) fn io_ports <'a, T: PortsSizes<'a>> (
pub(crate) fn io_conns <'a, T: PortsSizes<'a>> ( pub(crate) fn io_conns <'a, T: PortsSizes<'a>> (
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
) -> impl Content<TuiOut> + 'a { ) -> impl Content<TuiOut> + 'a {
Map::new(iter, Map::new(iter, move|(
move|(index, name, connections, y, y2): (usize, &'a Arc<str>, &'a [PortConnect], usize, usize), _| index, name, connections, y, y2
): (usize, &'a Arc<str>, &'a [PortConnect], usize, usize), _|
map_south(y as u16, (y2-y) as u16, Bsp::s( map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, wrap(bg, fg, Fill::x(Align::w("▞▞▞▞ ▞▞▞▞"))))), Fill::x(Tui::bold(true, wrap(bg, fg, Fill::x(Align::w("▞▞▞▞ ▞▞▞▞"))))),
Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1, Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1,

View file

@ -185,12 +185,12 @@ impl Cli {
_ => vec![] _ => vec![]
}, },
scenes, scenes,
selected: Selection::Clip(0, 0), selected: Selection::TrackClip { track: 0, scene: 0 },
..Default::default() ..Default::default()
}; };
if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode { if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode {
app.arranger = Default::default(); app.arranger = Default::default();
app.selected = Selection::Clip(1, 1); app.selected = Selection::TrackClip { track: 1, scene: 1 };
app.scenes_add(scenes)?; app.scenes_add(scenes)?;
app.tracks_add(tracks, Some(track_width), &[], &[])?; app.tracks_add(tracks, Some(track_width), &[], &[])?;
} }