mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-03-13 11:50:44 +01:00
use new AsRefOpt/AsMutOpt glue traits
This commit is contained in:
parent
6295f2e601
commit
ab90129f4c
7 changed files with 661 additions and 740 deletions
|
|
@ -50,7 +50,6 @@ proptest-derive = { version = "^0.5.1" }
|
|||
|
||||
[features]
|
||||
default = ["cli", "arranger", "sampler"]
|
||||
|
||||
arranger = ["port", "editor", "sequencer", "track", "scene", "clip", "select"]
|
||||
browse = []
|
||||
clap = []
|
||||
|
|
|
|||
2
Justfile
2
Justfile
|
|
@ -2,7 +2,7 @@ export RUSTFLAGS := "--cfg procmacro2_semver_exempt -Zmacro-backtrace -Clink-arg
|
|||
export RUST_BACKTRACE := "1"
|
||||
|
||||
default +ARGS="new":
|
||||
target/debug/tek {{ARGS}}
|
||||
cargo run -- {{ARGS}}
|
||||
|
||||
doc +ARGS="":
|
||||
cargo doc --open -j4 --document-private-items {{ARGS}}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ pub(crate) use tengri::{
|
|||
pub(crate) use ConnectName::*;
|
||||
pub(crate) use ConnectScope::*;
|
||||
pub(crate) use ConnectStatus::*;
|
||||
pub(crate) use JackState::*;
|
||||
|
||||
/// Command-line entrypoint.
|
||||
#[cfg(feature = "cli")] pub fn main () -> Usually<()> {
|
||||
|
|
@ -70,7 +69,7 @@ pub(crate) use JackState::*;
|
|||
/// Create a new application from a backend, project, config, and mode
|
||||
///
|
||||
/// ```
|
||||
/// let jack = tek::Jack::new(&"test_tek").expect("failed to connect to jack");
|
||||
/// let jack = tek::tengri::Jack::new(&"test_tek").expect("failed to connect to jack");
|
||||
/// let proj = tek::Arrangement::default();
|
||||
/// let mut conf = tek::Config::default();
|
||||
/// conf.add("(mode hello)");
|
||||
|
|
|
|||
1237
app/tek_impls.rs
1237
app/tek_impls.rs
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@ use builder_pattern::Builder;
|
|||
/// Total state
|
||||
///
|
||||
/// ```
|
||||
/// use tek::{TracksView, ScenesView, AddScene};
|
||||
/// use tek::{HasTracks, HasScenes, TracksView, ScenesView};
|
||||
/// let mut app = tek::App::default();
|
||||
/// let _ = app.scene_add(None, None).unwrap();
|
||||
/// let _ = app.update_clock();
|
||||
|
|
|
|||
154
app/tek_trait.rs
154
app/tek_trait.rs
|
|
@ -125,24 +125,55 @@ pub trait HasMidiClip {
|
|||
fn clip (&self) -> Option<Arc<RwLock<MidiClip>>>;
|
||||
}
|
||||
pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
||||
fn clock_mut (&mut self) -> &mut Clock { self.as_mut() }
|
||||
fn clock (&self) -> &Clock { self.as_ref() }
|
||||
fn clock_mut (&mut self) -> &mut Clock { self.as_mut() }
|
||||
}
|
||||
pub trait HasDevices: AsRef<Vec<Device>> + AsMut<Vec<Device>> {
|
||||
fn devices_mut (&mut self) -> &mut Vec<Device> { self.as_mut() }
|
||||
fn devices (&self) -> &Vec<Device> { self.as_ref() }
|
||||
}
|
||||
pub trait HasSelection: AsRef<Selection> + AsMut<Selection> {
|
||||
fn selection_mut (&mut self) -> &mut Selection { self.as_mut() }
|
||||
fn selection (&self) -> &Selection { self.as_ref() }
|
||||
fn devices_mut (&mut self) -> &mut Vec<Device> { self.as_mut() }
|
||||
}
|
||||
pub trait HasSequencer: AsRef<Sequencer> + AsMut<Sequencer> {
|
||||
fn sequencer_mut (&mut self) -> &mut Sequencer { self.as_mut() }
|
||||
fn sequencer (&self) -> &Sequencer { self.as_ref() }
|
||||
}
|
||||
pub trait HasScene: AsRef<Option<Scene>> + AsMut<Option<Scene>> {
|
||||
fn scene_mut (&mut self) -> &mut Option<Scene> { self.as_mut() }
|
||||
fn scene (&self) -> Option<&Scene> { self.as_ref() }
|
||||
pub trait HasSceneScroll: HasScenes { fn scene_scroll (&self) -> usize; }
|
||||
pub trait HasTrackScroll: HasTracks { fn track_scroll (&self) -> usize; }
|
||||
pub trait HasScene: AsRefOpt<Scene> + AsMutOpt<Scene> {
|
||||
fn scene_mut (&mut self) -> Option<&mut Scene> { self.as_mut_opt() }
|
||||
fn scene (&self) -> Option<&Scene> { self.as_ref_opt() }
|
||||
}
|
||||
pub trait HasSelection: AsRef<Selection> + AsMut<Selection> {
|
||||
fn selection (&self) -> &Selection { self.as_ref() }
|
||||
fn selection_mut (&mut self) -> &mut Selection { self.as_mut() }
|
||||
/// Get the active track
|
||||
#[cfg(feature = "track")]
|
||||
fn selected_track (&self) -> Option<&Track> where Self: HasTracks {
|
||||
let index = self.selection().track()?;
|
||||
self.tracks().get(index)
|
||||
}
|
||||
/// Get a mutable reference to the active track
|
||||
#[cfg(feature = "track")]
|
||||
fn selected_track_mut (&mut self) -> Option<&mut Track> where Self: HasTracks {
|
||||
let index = self.selection().track()?;
|
||||
self.tracks_mut().get_mut(index)
|
||||
}
|
||||
/// Get the active scene
|
||||
#[cfg(feature = "scene")]
|
||||
fn selected_scene (&self) -> Option<&Scene> where Self: HasScenes {
|
||||
let index = self.selection().scene()?;
|
||||
self.scenes().get(index)
|
||||
}
|
||||
/// Get a mutable reference to the active scene
|
||||
#[cfg(feature = "scene")]
|
||||
fn selected_scene_mut (&mut self) -> Option<&mut Scene> where Self: HasScenes {
|
||||
let index = self.selection().scene()?;
|
||||
self.scenes_mut().get_mut(index)
|
||||
}
|
||||
/// Get the active clip
|
||||
#[cfg(feature = "clip")]
|
||||
fn selected_clip (&self) -> Option<Arc<RwLock<MidiClip>>> where Self: HasScenes + HasTracks {
|
||||
self.selected_scene()?.clips.get(self.selection().track()?)?.clone()
|
||||
}
|
||||
}
|
||||
pub trait HasScenes: AsRef<Vec<Scene>> + AsMut<Vec<Scene>> {
|
||||
fn scenes (&self) -> &Vec<Scene> { self.as_ref() }
|
||||
|
|
@ -150,12 +181,30 @@ pub trait HasScenes: AsRef<Vec<Scene>> + AsMut<Vec<Scene>> {
|
|||
/// Generate the default name for a new scene
|
||||
fn scene_default_name (&self) -> Arc<str> { format!("s{:3>}", self.scenes().len() + 1).into() }
|
||||
fn scene_longest_name (&self) -> usize { self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max) }
|
||||
}
|
||||
pub trait HasSceneScroll: HasScenes {
|
||||
fn scene_scroll (&self) -> usize;
|
||||
}
|
||||
pub trait HasTrackScroll: HasTracks {
|
||||
fn track_scroll (&self) -> usize;
|
||||
/// Add multiple scenes
|
||||
fn scenes_add (&mut self, n: usize) -> Usually<()> where Self: HasTracks {
|
||||
let scene_color_1 = ItemColor::random();
|
||||
let scene_color_2 = ItemColor::random();
|
||||
for i in 0..n {
|
||||
let _ = self.scene_add(None, Some(
|
||||
scene_color_1.mix(scene_color_2, i as f32 / n as f32).into()
|
||||
))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Add a scene
|
||||
fn scene_add (&mut self, name: Option<&str>, color: Option<ItemTheme>)
|
||||
-> Usually<(usize, &mut Scene)> where Self: HasTracks
|
||||
{
|
||||
let scene = Scene {
|
||||
name: name.map_or_else(||self.scene_default_name(), |x|x.to_string().into()),
|
||||
clips: vec![None;self.tracks().len()],
|
||||
color: color.unwrap_or_else(ItemTheme::random),
|
||||
};
|
||||
self.scenes_mut().push(scene);
|
||||
let index = self.scenes().len() - 1;
|
||||
Ok((index, &mut self.scenes_mut()[index]))
|
||||
}
|
||||
}
|
||||
pub trait HasWidth {
|
||||
const MIN_WIDTH: usize;
|
||||
|
|
@ -170,39 +219,26 @@ pub trait HasMidiBuffers {
|
|||
}
|
||||
|
||||
/// ```
|
||||
/// use tek::{MidiEditor, HasEditor, tengri::Has};
|
||||
/// use tek::{*, tengri::*};
|
||||
///
|
||||
/// let mut host = TestEditorHost(Some(MidiEditor::default()));
|
||||
/// struct TestEditorHost(Option<MidiEditor>);
|
||||
/// impl AsRef<Option<MidiEditor>> for TestEditorHost {
|
||||
/// fn get (&self) -> &Option<MidiEditor> { &self.0 }
|
||||
/// fn get_mut (&mut self) -> &mut Option<MidiEditor> { &mut self.0 }
|
||||
/// }
|
||||
/// struct Test(Option<MidiEditor>);
|
||||
/// impl_as_ref_opt!(MidiEditor: |self: Test|self.0.as_ref());
|
||||
/// impl_as_mut_opt!(MidiEditor: |self: Test|self.0.as_mut());
|
||||
///
|
||||
/// let mut host = Test(Some(MidiEditor::default()));
|
||||
/// let _ = host.editor();
|
||||
/// let _ = host.editor_mut();
|
||||
/// let _ = host.is_editing();
|
||||
/// let _ = host.editor_w();
|
||||
/// let _ = host.editor_h();
|
||||
/// ```
|
||||
pub trait HasEditor: AsRef<Option<MidiEditor>> {
|
||||
fn editor (&self) -> Option<&MidiEditor> {
|
||||
self.get().as_ref()
|
||||
}
|
||||
fn editor_mut (&mut self) -> Option<&mut MidiEditor> {
|
||||
self.get_mut().as_mut()
|
||||
}
|
||||
fn is_editing (&self) -> bool {
|
||||
self.editor().is_some()
|
||||
}
|
||||
fn editor_w (&self) -> usize {
|
||||
self.editor().map(|e|e.size.w()).unwrap_or(0) as usize
|
||||
}
|
||||
fn editor_h (&self) -> usize {
|
||||
self.editor().map(|e|e.size.h()).unwrap_or(0) as usize
|
||||
}
|
||||
pub trait HasEditor: AsRefOpt<MidiEditor> + AsMutOpt<MidiEditor> {
|
||||
fn editor (&self) -> Option<&MidiEditor> { self.as_ref_opt() }
|
||||
fn editor_mut (&mut self) -> Option<&mut MidiEditor> { self.as_mut_opt() }
|
||||
fn is_editing (&self) -> bool { self.editor().is_some() }
|
||||
fn editor_w (&self) -> usize { self.editor().map(|e|e.size.w()).unwrap_or(0) as usize }
|
||||
fn editor_h (&self) -> usize { self.editor().map(|e|e.size.h()).unwrap_or(0) as usize }
|
||||
}
|
||||
|
||||
pub trait HasClips {
|
||||
fn clips <'a> (&'a self) -> std::sync::RwLockReadGuard<'a, ClipPool>;
|
||||
fn clips_mut <'a> (&'a self) -> std::sync::RwLockWriteGuard<'a, ClipPool>;
|
||||
|
|
@ -212,7 +248,6 @@ pub trait HasClips {
|
|||
(self.clips().len() - 1, clip)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for thing that may receive MIDI.
|
||||
pub trait HasMidiIns {
|
||||
fn midi_ins (&self) -> &Vec<MidiInput>;
|
||||
|
|
@ -237,7 +272,6 @@ pub trait HasMidiIns {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for thing that may output MIDI.
|
||||
pub trait HasMidiOuts {
|
||||
fn midi_outs (&self) -> &Vec<MidiOutput>;
|
||||
|
|
@ -259,9 +293,7 @@ pub trait HasMidiOuts {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<Vec<Track>> + AsMut<Vec<Track>> + Send + Sync> HasTracks for T {}
|
||||
pub trait HasTracks: AsRef<Vec<Track>> + AsMut<Vec<Track>> + Send + Sync {
|
||||
pub trait HasTracks: AsRef<Vec<Track>> + AsMut<Vec<Track>> {
|
||||
fn tracks (&self) -> &Vec<Track> { self.as_ref() }
|
||||
fn tracks_mut (&mut self) -> &mut Vec<Track> { self.as_mut() }
|
||||
/// Run audio callbacks for every track and every device
|
||||
|
|
@ -292,10 +324,9 @@ pub trait HasTracks: AsRef<Vec<Track>> + AsMut<Vec<Track>> + Send + Sync {
|
|||
/// Spacing between tracks.
|
||||
const TRACK_SPACING: usize = 0;
|
||||
}
|
||||
|
||||
pub trait HasTrack {
|
||||
fn track (&self) -> Option<&Track>;
|
||||
fn track_mut (&mut self) -> Option<&mut Track>;
|
||||
pub trait HasTrack: AsRefOpt<Track> + AsMutOpt<Track> {
|
||||
fn track (&self) -> Option<&Track> { self.as_ref_opt() }
|
||||
fn track_mut (&mut self) -> Option<&mut Track> { self.as_mut_opt() }
|
||||
#[cfg(feature = "port")] fn view_midi_ins_status <'a> (&'a self, theme: ItemTheme) -> impl Content<TuiOut> + 'a {
|
||||
self.track().map(move|track|view_ports_status(theme, "MIDI ins: ", &track.sequencer.midi_ins))
|
||||
}
|
||||
|
|
@ -523,33 +554,6 @@ pub trait MidiViewer: Measured<TuiOut> + MidiRange + MidiPoint + Debug + Send +
|
|||
}
|
||||
}
|
||||
|
||||
pub trait AddScene: HasScenes + HasTracks {
|
||||
/// Add multiple scenes
|
||||
fn scenes_add (&mut self, n: usize) -> Usually<()> {
|
||||
let scene_color_1 = ItemColor::random();
|
||||
let scene_color_2 = ItemColor::random();
|
||||
for i in 0..n {
|
||||
let _ = self.scene_add(None, Some(
|
||||
scene_color_1.mix(scene_color_2, i as f32 / n as f32).into()
|
||||
))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Add a scene
|
||||
fn scene_add (&mut self, name: Option<&str>, color: Option<ItemTheme>)
|
||||
-> Usually<(usize, &mut Scene)>
|
||||
{
|
||||
let scene = Scene {
|
||||
name: name.map_or_else(||self.scene_default_name(), |x|x.to_string().into()),
|
||||
clips: vec![None;self.tracks().len()],
|
||||
color: color.unwrap_or_else(ItemTheme::random),
|
||||
};
|
||||
self.scenes_mut().push(scene);
|
||||
let index = self.scenes().len() - 1;
|
||||
Ok((index, &mut self.scenes_mut()[index]))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ClipsView: TracksView + ScenesView {
|
||||
|
||||
fn view_scenes_clips <'a> (&'a self)
|
||||
|
|
|
|||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
|||
Subproject commit c1b727bafc27dc715d7239a0bc63a1cdfe962bc2
|
||||
Subproject commit d1c08df5351ce8c3913723602a05268d593c9a45
|
||||
Loading…
Add table
Add a link
Reference in a new issue