mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-10-08 18:56:42 +02:00
collect tek_view, tek_ctrl
This commit is contained in:
parent
c5d6ce24b2
commit
186b81f29c
47 changed files with 2665 additions and 2893 deletions
173
src/project.rs
173
src/project.rs
|
|
@ -1,173 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl AsRef<Option<Project>> for App {
|
||||
fn as_ref (&self) -> &Option<Project> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<Option<Project>> for App {
|
||||
fn as_mut (&mut self) -> &mut Option<Project> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasProject: AsRef<Option<Project>> + AsMut<Option<Project>> {}
|
||||
|
||||
impl<T: AsRef<Option<Project>> + AsMut<Option<Project>>> HasProject for T {}
|
||||
|
||||
impl<T: HasProject> ProjectController for T {}
|
||||
|
||||
#[tek_proc::commands(ProjectCommand)]
|
||||
pub trait ProjectController: HasProject {
|
||||
|
||||
#[command(LoadLast = "load-last")]
|
||||
fn load_last (&mut self) -> Perhaps<ProjectCommand> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[command(Load = "load")]
|
||||
fn load (&mut self) -> Perhaps<ProjectCommand> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Arranger.
|
||||
///
|
||||
/// ```
|
||||
/// let arranger = tek::Project::default();
|
||||
/// ```
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Project {
|
||||
/// JACK client handle.
|
||||
pub jack: Jack<'static>,
|
||||
/// Project name.
|
||||
pub name: Arc<str>,
|
||||
/// Base color.
|
||||
pub color: ItemTheme,
|
||||
/// FIXME a render of the project arrangement, redrawn on update.
|
||||
/// TODO rename to "render_cache" or smth
|
||||
pub arranger: Arc<RwLock<Buffer>>,
|
||||
/// Display size
|
||||
pub size: Sizer,
|
||||
/// Display size of clips area
|
||||
pub size_inner: Sizer,
|
||||
/// Selected UI element
|
||||
pub selection: Selection,
|
||||
/// Source of time
|
||||
#[cfg(feature = "clock")] pub clock: Clock,
|
||||
/// Allows one MIDI clip to be edited
|
||||
#[cfg(feature = "editor")] pub editor: Option<MidiEditor>,
|
||||
/// List of global midi inputs
|
||||
#[cfg(feature = "port")] pub midi_ins: Vec<MidiInput>,
|
||||
/// List of global midi outputs
|
||||
#[cfg(feature = "port")] pub midi_outs: Vec<MidiOutput>,
|
||||
/// List of global audio inputs
|
||||
#[cfg(feature = "port")] pub audio_ins: Vec<AudioInput>,
|
||||
/// List of global audio outputs
|
||||
#[cfg(feature = "port")] pub audio_outs: Vec<AudioOutput>,
|
||||
/// Last track number (to avoid duplicate port names)
|
||||
#[cfg(feature = "track")] pub track_last: usize,
|
||||
/// List of tracks
|
||||
#[cfg(feature = "track")] pub tracks: Vec<Track>,
|
||||
/// Scroll offset of tracks
|
||||
#[cfg(feature = "track")] pub track_scroll: usize,
|
||||
/// List of scenes
|
||||
#[cfg(feature = "scene")] pub scenes: Vec<Scene>,
|
||||
/// Scroll offset of scenes
|
||||
#[cfg(feature = "scene")] pub scene_scroll: usize,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
|
||||
/// Create a new arrangement.
|
||||
pub fn new (
|
||||
jack: &Jack<'static>,
|
||||
name: Arc<str>,
|
||||
clock: Clock,
|
||||
tracks: impl Iterator<Item = Track>,
|
||||
scenes: impl Iterator<Item = Scene>,
|
||||
midi_ins: impl Iterator<Item = MidiInput>,
|
||||
midi_outs: impl Iterator<Item = MidiOutput>,
|
||||
audio_ins: impl Iterator<Item = AudioInput>,
|
||||
audio_outs: impl Iterator<Item = AudioOutput>,
|
||||
) -> Self {
|
||||
Self {
|
||||
jack: jack.clone(),
|
||||
color: ItemTheme::random(),
|
||||
selection: Selection::TrackClip { track: 0, scene: 0 },
|
||||
tracks: tracks.collect(),
|
||||
scenes: scenes.collect(),
|
||||
midi_ins: midi_ins.collect(),
|
||||
midi_outs: midi_outs.collect(),
|
||||
audio_ins: audio_ins.collect(),
|
||||
audio_outs: audio_outs.collect(),
|
||||
size_inner: Sizer(Arc::new(40.into()), Arc::new(25.into())),
|
||||
clock,
|
||||
name,
|
||||
..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)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasJack<'static> for Project { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||
impl_has!(Jack<'static>: |self: Project| self.jack);
|
||||
impl_has!(Sizer: |self: Project| self.size);
|
||||
impl_has!(Clock: |self: Project| self.clock);
|
||||
impl_has!(Selection: |self: Project| self.selection);
|
||||
impl_has!(Vec<Scene>: |self: Project| self.scenes);
|
||||
impl_as_ref_opt!(Scene: |self: Project| self.selected_scene());
|
||||
impl_as_mut_opt!(Scene: |self: Project| self.selected_scene_mut());
|
||||
impl_as_ref!(Option<MidiEditor>: |self: Project| &self.editor);
|
||||
impl_as_mut!(Option<MidiEditor>: |self: Project| &mut self.editor);
|
||||
|
||||
pub fn swap_value <T: Clone + PartialEq, U> (
|
||||
target: &mut T, value: &T, returned: impl Fn(T)->U
|
||||
) -> Perhaps<U> {
|
||||
if *target == *value {
|
||||
Ok(None)
|
||||
} else {
|
||||
let mut value = value.clone();
|
||||
std::mem::swap(target, &mut value);
|
||||
Ok(Some(returned(value)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_bool <U> (
|
||||
target: &mut bool, value: &Option<bool>, returned: impl Fn(Option<bool>)->U
|
||||
) -> Perhaps<U> {
|
||||
let mut value = value.unwrap_or(!*target);
|
||||
if value == *target {
|
||||
Ok(None)
|
||||
} else {
|
||||
std::mem::swap(target, &mut value);
|
||||
Ok(Some(returned(Some(value))))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue