use crate::*; /// Arranger. /// /// ``` /// let arranger = tek::Arrangement::default(); /// ``` #[derive(Default, Debug)] pub struct Arrangement { /// Project name. pub name: Arc, /// Base color. pub color: ItemTheme, /// JACK client handle. pub jack: Jack<'static>, /// FIXME a render of the project arrangement, redrawn on update. /// TODO rename to "render_cache" or smth pub arranger: Arc>, /// Display size pub size: Sizer, /// Display size of clips area pub size_inner: Sizer, /// Source of time #[cfg(feature = "clock")] pub clock: Clock, /// Allows one MIDI clip to be edited #[cfg(feature = "editor")] pub editor: Option, /// List of global midi inputs #[cfg(feature = "port")] pub midi_ins: Vec, /// List of global midi outputs #[cfg(feature = "port")] pub midi_outs: Vec, /// List of global audio inputs #[cfg(feature = "port")] pub audio_ins: Vec, /// List of global audio outputs #[cfg(feature = "port")] pub audio_outs: Vec, /// Selected UI element #[cfg(feature = "select")] pub selection: Selection, /// Last track number (to avoid duplicate port names) #[cfg(feature = "track")] pub track_last: usize, /// List of tracks #[cfg(feature = "track")] pub tracks: Vec, /// Scroll offset of tracks #[cfg(feature = "track")] pub track_scroll: usize, /// List of scenes #[cfg(feature = "scene")] pub scenes: Vec, /// Scroll offset of scenes #[cfg(feature = "scene")] pub scene_scroll: usize, } impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &self.jack } } impl_has!(Jack<'static>: |self: Arrangement| self.jack); impl_has!(Sizer: |self: Arrangement| self.size); impl_has!(Vec: |self: Arrangement| self.midi_ins); impl_has!(Vec: |self: Arrangement| self.midi_outs); impl_has!(Clock: |self: Arrangement| self.clock); impl_has!(Selection: |self: Arrangement| self.selection); impl_as_ref_opt!(MidiEditor: |self: Arrangement| self.editor.as_ref()); impl_as_mut_opt!(MidiEditor: |self: Arrangement| self.editor.as_mut()); impl Arrangement { /// Create a new arrangement. pub fn new ( jack: &Jack<'static>, name: Option>, clock: Clock, tracks: Vec, scenes: Vec, midi_ins: Vec, midi_outs: Vec, ) -> Self { Self { clock, tracks, scenes, midi_ins, midi_outs, jack: jack.clone(), name: name.unwrap_or_default(), color: ItemTheme::random(), selection: Selection::TrackClip { track: 0, scene: 0 }, ..Default::default() } } /// Width of display pub fn w (&self) -> u16 { self.size.w() as u16 } /// Width allocated for sidebar. pub fn w_sidebar (&self, is_editing: bool) -> u16 { self.w() / if is_editing { 16 } else { 8 } as u16 } /// Width available to display tracks. pub fn w_tracks_area (&self, is_editing: bool) -> u16 { self.w().saturating_sub(self.w_sidebar(is_editing)) } /// Height of display pub fn h (&self) -> u16 { self.size.h() as u16 } /// Height taken by visible device slots. pub fn h_devices (&self) -> u16 { 2 //1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0) } /// Get the first sampler of the active track #[cfg(feature = "sampler")] pub fn sampler (&self) -> Option<&Sampler> { self.selected_track()?.sampler(0) } /// Get the first sampler of the active track #[cfg(feature = "sampler")] pub fn sampler_mut (&mut self) -> Option<&mut Sampler> { self.selected_track_mut()?.sampler_mut(0) } } #[cfg(feature = "clip")] mod clip; #[cfg(feature = "clip")] pub use self::clip::*; #[cfg(feature = "scene")] mod scene; #[cfg(feature = "scene")] pub use self::scene::*; #[cfg(feature = "track")] mod track; #[cfg(feature = "track")] pub use self::track::*; #[cfg(feature = "select")] mod select; #[cfg(feature = "select")] pub use self::select::*;