wip: 284 errors, later

This commit is contained in:
okay stopped screaming 2026-03-21 23:53:24 +02:00
parent 244e2b388e
commit 60dbd89fc9
9 changed files with 250 additions and 254 deletions

View file

@ -1,8 +1,7 @@
use crate::*;
use ::std::sync::{Arc, RwLock}; use ::std::sync::{Arc, RwLock};
use ::tengri::{space::east, color::ItemTheme}; use ::tengri::{space::east, color::ItemTheme};
use ::tengri::{draw::*, term::*}; use ::tengri::{draw::*, term::*};
use crate::device::{MidiInput, MidiOutput, AudioInput, AudioOutput}; use crate::{*, device::*, sequence::*, clock::*, select::*, sample::*};
impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &self.jack } } impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &self.jack } }
/// Arranger. /// Arranger.
@ -50,6 +49,40 @@ impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &sel
#[cfg(feature = "scene")] pub scene_scroll: usize, #[cfg(feature = "scene")] pub scene_scroll: usize,
} }
/// A track consists of a sequencer and zero or more devices chained after it.
///
/// ```
/// let track: tek::Track = Default::default();
/// ```
#[derive(Debug, Default)] pub struct Track {
/// Name of track
pub name: Arc<str>,
/// Identifying color of track
pub color: ItemTheme,
/// Preferred width of track column
pub width: usize,
/// MIDI sequencer state
pub sequencer: Sequencer,
/// Device chain
pub devices: Vec<Device>,
}
/// A scene consists of a set of clips to play together.
///
/// ```
/// let scene: tek::Scene = Default::default();
/// let _ = scene.pulses();
/// let _ = scene.is_playing(&[]);
/// ```
#[derive(Debug, Default)] pub struct Scene {
/// Name of scene
pub name: Arc<str>,
/// Identifying color of scene
pub color: ItemTheme,
/// Clips in scene, one per track
pub clips: Vec<Option<Arc<RwLock<MidiClip>>>>,
}
impl_has!(Jack<'static>: |self: Arrangement| self.jack); impl_has!(Jack<'static>: |self: Arrangement| self.jack);
impl_has!(Measure<Tui>: |self: Arrangement| self.size); impl_has!(Measure<Tui>: |self: Arrangement| self.size);
impl_has!(Vec<Track>: |self: Arrangement| self.tracks); impl_has!(Vec<Track>: |self: Arrangement| self.tracks);
@ -63,7 +96,6 @@ impl_as_mut_opt!(MidiEditor: |self: Arrangement| self.editor.as_mut());
impl_as_ref_opt!(Track: |self: Arrangement| self.selected_track()); impl_as_ref_opt!(Track: |self: Arrangement| self.selected_track());
impl_as_mut_opt!(Track: |self: Arrangement| self.selected_track_mut()); impl_as_mut_opt!(Track: |self: Arrangement| self.selected_track_mut());
impl <T: AsRef<Selection>+AsMut<Selection>> HasSelection for T {}
impl <T: AsRef<Vec<Scene>>+AsMut<Vec<Scene>>> HasScenes for T {} impl <T: AsRef<Vec<Scene>>+AsMut<Vec<Scene>>> HasScenes for T {}
impl <T: AsRef<Vec<Track>>+AsMut<Vec<Track>>> HasTracks for T {} impl <T: AsRef<Vec<Track>>+AsMut<Vec<Track>>> HasTracks for T {}
impl <T: AsRefOpt<Scene>+AsMutOpt<Scene>+Send+Sync> HasScene for T {} impl <T: AsRefOpt<Scene>+AsMutOpt<Scene>+Send+Sync> HasScene for T {}
@ -141,47 +173,6 @@ pub trait ClipsView: TracksView + ScenesView {
} }
/// Represents the current user selection in the arranger
#[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection {
#[default]
/// Nothing is selected
Nothing,
/// The whole mix is selected
Mix,
/// A MIDI input is selected.
Input(usize),
/// A MIDI output is selected.
Output(usize),
/// A scene is selected.
#[cfg(feature = "scene")] Scene(usize),
/// A track is selected.
#[cfg(feature = "track")] Track(usize),
/// A clip (track × scene) is selected.
#[cfg(feature = "track")] TrackClip { track: usize, scene: usize },
/// A track's MIDI input connection is selected.
#[cfg(feature = "track")] TrackInput { track: usize, port: usize },
/// A track's MIDI output connection is selected.
#[cfg(feature = "track")] TrackOutput { track: usize, port: usize },
/// A track device slot is selected.
#[cfg(feature = "track")] TrackDevice { track: usize, device: usize },
}
/// A scene consists of a set of clips to play together.
///
/// ```
/// let scene: tek::Scene = Default::default();
/// let _ = scene.pulses();
/// let _ = scene.is_playing(&[]);
/// ```
#[derive(Debug, Default)] pub struct Scene {
/// Name of scene
pub name: Arc<str>,
/// Identifying color of scene
pub color: ItemTheme,
/// Clips in scene, one per track
pub clips: Vec<Option<Arc<RwLock<MidiClip>>>>,
}
pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll + Measured<Tui> { pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll + Measured<Tui> {
fn tracks_width_available (&self) -> u16 { fn tracks_width_available (&self) -> u16 {
@ -330,39 +321,6 @@ pub trait HasScene: AsRefOpt<Scene> + AsMutOpt<Scene> {
fn scene_mut (&mut self) -> Option<&mut Scene> { self.as_mut_opt() } fn scene_mut (&mut self) -> Option<&mut Scene> { self.as_mut_opt() }
fn scene (&self) -> Option<&Scene> { self.as_ref_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>> { pub trait HasScenes: AsRef<Vec<Scene>> + AsMut<Vec<Scene>> {
fn scenes (&self) -> &Vec<Scene> { self.as_ref() } fn scenes (&self) -> &Vec<Scene> { self.as_ref() }
fn scenes_mut (&mut self) -> &mut Vec<Scene> { self.as_mut() } fn scenes_mut (&mut self) -> &mut Vec<Scene> { self.as_mut() }
@ -599,104 +557,6 @@ pub trait HasTrack: AsRefOpt<Track> + AsMutOpt<Track> {
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() } fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
} }
impl Selection {
pub fn describe (
&self,
#[cfg(feature = "track")] tracks: &[Track],
#[cfg(feature = "scene")] scenes: &[Scene],
) -> Arc<str> {
use Selection::*;
format!("{}", match self {
Mix => "Everything".to_string(),
#[cfg(feature = "scene")] Scene(s) =>
scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name)).unwrap_or_else(||"S??".into()),
#[cfg(feature = "track")] Track(t) =>
tracks.get(*t).map(|track|format!("T{t}: {}", &track.name)).unwrap_or_else(||"T??".into()),
TrackClip { track, scene } => match (tracks.get(*track), scenes.get(*scene)) {
(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{track} S{scene}: Empty"),
},
_ => todo!()
}).into()
}
#[cfg(feature = "scene")] pub fn scene (&self) -> Option<usize> {
use Selection::*;
match self { Scene(scene) | TrackClip { scene, .. } => Some(*scene), _ => None }
}
#[cfg(feature = "scene")] pub fn select_scene (&self, scene_count: usize) -> Self {
use Selection::*;
match self {
Mix | Track(_) => Scene(0),
Scene(s) => Scene((s + 1) % scene_count),
TrackClip { scene, .. } => Track(*scene),
_ => todo!(),
}
}
#[cfg(feature = "scene")] pub fn select_scene_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Scene(0),
Track(t) => TrackClip { track: *t, scene: 0 },
Scene(s) => if s + 1 < len { Scene(s + 1) } else { Mix },
TrackClip { track, scene } => if scene + 1 < len { TrackClip { track: *track, scene: scene + 1 } } else { Track(*track) },
_ => todo!()
}
}
#[cfg(feature = "scene")] pub fn select_scene_prev (&self) -> Self {
use Selection::*;
match self {
Mix | Scene(0) => Mix,
Scene(s) => Scene(s - 1),
Track(t) => Track(*t),
TrackClip { track, scene: 0 } => Track(*track),
TrackClip { track, scene } => TrackClip { track: *track, scene: scene - 1 },
_ => todo!()
}
}
#[cfg(feature = "track")] pub fn track (&self) -> Option<usize> {
use Selection::*;
if let Track(track)|TrackClip{track,..}|TrackInput{track,..}|TrackOutput{track,..}|TrackDevice{track,..} = self {
Some(*track)
} else {
None
}
}
#[cfg(feature = "track")] pub fn select_track (&self, track_count: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
Scene(_) => Mix,
Track(t) => Track((t + 1) % track_count),
TrackClip { track, .. } => Track(*track),
_ => todo!(),
}
}
#[cfg(feature = "track")] pub fn select_track_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
Scene(s) => TrackClip { track: 0, scene: *s },
Track(t) => if t + 1 < len { Track(t + 1) } else { Mix },
TrackClip {track, scene} => if track + 1 < len { TrackClip { track: track + 1, scene: *scene } } else { Scene(*scene) },
_ => todo!()
}
}
#[cfg(feature = "track")] pub fn select_track_prev (&self) -> Self {
use Selection::*;
match self {
Mix => Mix,
Scene(s) => Scene(*s),
Track(0) => Mix,
Track(t) => Track(t - 1),
TrackClip { track: 0, scene } => Scene(*scene),
TrackClip { track: t, scene } => TrackClip { track: t - 1, scene: *scene },
_ => todo!()
}
}
}
impl Arrangement { impl Arrangement {
/// Create a new arrangement. /// Create a new arrangement.
pub fn new ( pub fn new (

View file

@ -1,7 +1,4 @@
use crate::*; use crate::{*, clock::*, sequence::*, sample::*};
use ::std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::*}};
use crate::sequence::MidiClip;
use crate::sample::Sample;
def_command!(FileBrowserCommand: |sampler: Sampler|{ def_command!(FileBrowserCommand: |sampler: Sampler|{
//("begin" [] Some(Self::Begin)) //("begin" [] Some(Self::Begin))

View file

@ -1,5 +1,4 @@
use crate::*; use crate::{*, arrange::*, clock::*, config::*, device::*};
use crate::*;
/// The command-line interface descriptor. /// The command-line interface descriptor.
/// ///

View file

@ -1,4 +1,7 @@
use crate::*; use crate::*;
use ConnectName::*;
use ConnectScope::*;
use ConnectStatus::*;
def_command!(DeviceCommand: |device: Device| {}); def_command!(DeviceCommand: |device: Device| {});
@ -620,3 +623,48 @@ impl<T: AsRef<Vec<Device>> + AsMut<Vec<Device>>> HasDevices for T {
self.as_mut() self.as_mut()
} }
} }
/// Trait for thing that may receive MIDI.
pub trait HasMidiIns {
fn midi_ins (&self) -> &Vec<MidiInput>;
fn midi_ins_mut (&mut self) -> &mut Vec<MidiInput>;
/// Collect MIDI input from app ports (TODO preallocate large buffers)
fn midi_input_collect <'a> (&'a self, scope: &'a ProcessScope) -> CollectedMidiInput<'a> {
self.midi_ins().iter()
.map(|port|port.port().iter(scope)
.map(|RawMidi { time, bytes }|(time, LiveEvent::parse(bytes)))
.collect::<Vec<_>>())
.collect::<Vec<_>>()
}
fn midi_ins_with_sizes <'a> (&'a self) ->
impl Iterator<Item=(usize, &'a Arc<str>, &'a [Connect], usize, usize)> + Send + Sync + 'a
{
let mut y = 0;
self.midi_ins().iter().enumerate().map(move|(i, input)|{
let height = 1 + input.connections().len();
let data = (i, input.port_name(), input.connections(), y, y + height);
y += height;
data
})
}
}
/// Trait for thing that may output MIDI.
pub trait HasMidiOuts {
fn midi_outs (&self) -> &Vec<MidiOutput>;
fn midi_outs_mut (&mut self) -> &mut Vec<MidiOutput>;
fn midi_outs_with_sizes <'a> (&'a self) ->
impl Iterator<Item=(usize, &'a Arc<str>, &'a [Connect], usize, usize)> + Send + Sync + 'a
{
let mut y = 0;
self.midi_outs().iter().enumerate().map(move|(i, output)|{
let height = 1 + output.connections().len();
let data = (i, output.port_name(), output.connections(), y, y + height);
y += height;
data
})
}
fn midi_outs_emit (&mut self, scope: &ProcessScope) {
for port in self.midi_outs_mut().iter_mut() {
port.buffer_emit(scope)
}
}
}

View file

@ -1,4 +1,4 @@
use crate::*; use crate::{*, menu::*};
/// Various possible dialog modes. /// Various possible dialog modes.
/// ///

View file

@ -1,6 +1,4 @@
use crate::*; use crate::{*, device::*, browse::*, mix::*};
use ::std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::*}};
use crate::device::{MidiInput, MidiOutput, AudioInput, AudioOutput};
def_command!(SamplerCommand: |sampler: Sampler| { def_command!(SamplerCommand: |sampler: Sampler| {
RecordToggle { slot: usize } => { RecordToggle { slot: usize } => {

161
src/select.rs Normal file
View file

@ -0,0 +1,161 @@
use crate::*;
/// Represents the current user selection in the arranger
#[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection {
#[default]
/// Nothing is selected
Nothing,
/// The whole mix is selected
Mix,
/// A MIDI input is selected.
Input(usize),
/// A MIDI output is selected.
Output(usize),
/// A scene is selected.
#[cfg(feature = "scene")] Scene(usize),
/// A track is selected.
#[cfg(feature = "track")] Track(usize),
/// A clip (track × scene) is selected.
#[cfg(feature = "track")] TrackClip { track: usize, scene: usize },
/// A track's MIDI input connection is selected.
#[cfg(feature = "track")] TrackInput { track: usize, port: usize },
/// A track's MIDI output connection is selected.
#[cfg(feature = "track")] TrackOutput { track: usize, port: usize },
/// A track device slot is selected.
#[cfg(feature = "track")] TrackDevice { track: usize, device: usize },
}
impl Selection {
pub fn describe (
&self,
#[cfg(feature = "track")] tracks: &[Track],
#[cfg(feature = "scene")] scenes: &[Scene],
) -> Arc<str> {
use Selection::*;
format!("{}", match self {
Mix => "Everything".to_string(),
#[cfg(feature = "scene")] Scene(s) =>
scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name)).unwrap_or_else(||"S??".into()),
#[cfg(feature = "track")] Track(t) =>
tracks.get(*t).map(|track|format!("T{t}: {}", &track.name)).unwrap_or_else(||"T??".into()),
TrackClip { track, scene } => match (tracks.get(*track), scenes.get(*scene)) {
(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{track} S{scene}: Empty"),
},
_ => todo!()
}).into()
}
#[cfg(feature = "scene")] pub fn scene (&self) -> Option<usize> {
use Selection::*;
match self { Scene(scene) | TrackClip { scene, .. } => Some(*scene), _ => None }
}
#[cfg(feature = "scene")] pub fn select_scene (&self, scene_count: usize) -> Self {
use Selection::*;
match self {
Mix | Track(_) => Scene(0),
Scene(s) => Scene((s + 1) % scene_count),
TrackClip { scene, .. } => Track(*scene),
_ => todo!(),
}
}
#[cfg(feature = "scene")] pub fn select_scene_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Scene(0),
Track(t) => TrackClip { track: *t, scene: 0 },
Scene(s) => if s + 1 < len { Scene(s + 1) } else { Mix },
TrackClip { track, scene } => if scene + 1 < len { TrackClip { track: *track, scene: scene + 1 } } else { Track(*track) },
_ => todo!()
}
}
#[cfg(feature = "scene")] pub fn select_scene_prev (&self) -> Self {
use Selection::*;
match self {
Mix | Scene(0) => Mix,
Scene(s) => Scene(s - 1),
Track(t) => Track(*t),
TrackClip { track, scene: 0 } => Track(*track),
TrackClip { track, scene } => TrackClip { track: *track, scene: scene - 1 },
_ => todo!()
}
}
#[cfg(feature = "track")] pub fn track (&self) -> Option<usize> {
use Selection::*;
if let Track(track)|TrackClip{track,..}|TrackInput{track,..}|TrackOutput{track,..}|TrackDevice{track,..} = self {
Some(*track)
} else {
None
}
}
#[cfg(feature = "track")] pub fn select_track (&self, track_count: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
Scene(_) => Mix,
Track(t) => Track((t + 1) % track_count),
TrackClip { track, .. } => Track(*track),
_ => todo!(),
}
}
#[cfg(feature = "track")] pub fn select_track_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
Scene(s) => TrackClip { track: 0, scene: *s },
Track(t) => if t + 1 < len { Track(t + 1) } else { Mix },
TrackClip {track, scene} => if track + 1 < len { TrackClip { track: track + 1, scene: *scene } } else { Scene(*scene) },
_ => todo!()
}
}
#[cfg(feature = "track")] pub fn select_track_prev (&self) -> Self {
use Selection::*;
match self {
Mix => Mix,
Scene(s) => Scene(*s),
Track(0) => Mix,
Track(t) => Track(t - 1),
TrackClip { track: 0, scene } => Scene(*scene),
TrackClip { track: t, scene } => TrackClip { track: t - 1, scene: *scene },
_ => todo!()
}
}
}
impl <T: AsRef<Selection>+AsMut<Selection>> HasSelection for T {}
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()
}
}

View file

@ -1,5 +1,4 @@
use crate::*; use crate::{*, device::*};
use ::std::sync::{Arc, RwLock};
def_command!(MidiEditCommand: |editor: MidiEditor| { def_command!(MidiEditCommand: |editor: MidiEditor| {
Show { clip: Option<Arc<RwLock<MidiClip>>> } => { Show { clip: Option<Arc<RwLock<MidiClip>>> } => {
@ -155,24 +154,6 @@ pub struct Sequencer {
pub midi_buf: Vec<Vec<Vec<u8>>>, pub midi_buf: Vec<Vec<Vec<u8>>>,
} }
/// A track consists of a sequencer and zero or more devices chained after it.
///
/// ```
/// let track: tek::Track = Default::default();
/// ```
#[derive(Debug, Default)] pub struct Track {
/// Name of track
pub name: Arc<str>,
/// Identifying color of track
pub color: ItemTheme,
/// Preferred width of track column
pub width: usize,
/// MIDI sequencer state
pub sequencer: Sequencer,
/// Device chain
pub devices: Vec<Device>,
}
pub trait HasPlayClip: HasClock { pub trait HasPlayClip: HasClock {
@ -423,51 +404,6 @@ pub trait HasEditor: AsRefOpt<MidiEditor> + AsMutOpt<MidiEditor> {
fn editor_w (&self) -> usize { self.editor().map(|e|e.size.w()).unwrap_or(0) as usize } 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 } fn editor_h (&self) -> usize { self.editor().map(|e|e.size.h()).unwrap_or(0) as usize }
} }
/// Trait for thing that may receive MIDI.
pub trait HasMidiIns {
fn midi_ins (&self) -> &Vec<MidiInput>;
fn midi_ins_mut (&mut self) -> &mut Vec<MidiInput>;
/// Collect MIDI input from app ports (TODO preallocate large buffers)
fn midi_input_collect <'a> (&'a self, scope: &'a ProcessScope) -> CollectedMidiInput<'a> {
self.midi_ins().iter()
.map(|port|port.port().iter(scope)
.map(|RawMidi { time, bytes }|(time, LiveEvent::parse(bytes)))
.collect::<Vec<_>>())
.collect::<Vec<_>>()
}
fn midi_ins_with_sizes <'a> (&'a self) ->
impl Iterator<Item=(usize, &'a Arc<str>, &'a [Connect], usize, usize)> + Send + Sync + 'a
{
let mut y = 0;
self.midi_ins().iter().enumerate().map(move|(i, input)|{
let height = 1 + input.connections().len();
let data = (i, input.port_name(), input.connections(), y, y + height);
y += height;
data
})
}
}
/// Trait for thing that may output MIDI.
pub trait HasMidiOuts {
fn midi_outs (&self) -> &Vec<MidiOutput>;
fn midi_outs_mut (&mut self) -> &mut Vec<MidiOutput>;
fn midi_outs_with_sizes <'a> (&'a self) ->
impl Iterator<Item=(usize, &'a Arc<str>, &'a [Connect], usize, usize)> + Send + Sync + 'a
{
let mut y = 0;
self.midi_outs().iter().enumerate().map(move|(i, output)|{
let height = 1 + output.connections().len();
let data = (i, output.port_name(), output.connections(), y, y + height);
y += height;
data
})
}
fn midi_outs_emit (&mut self, scope: &ProcessScope) {
for port in self.midi_outs_mut().iter_mut() {
port.buffer_emit(scope)
}
}
}
pub trait HasMidiClip { pub trait HasMidiClip {
fn clip (&self) -> Option<Arc<RwLock<MidiClip>>>; fn clip (&self) -> Option<Arc<RwLock<MidiClip>>>;
} }

View file

@ -52,6 +52,7 @@ pub mod mode;
pub mod plugin; pub mod plugin;
pub mod sample; pub mod sample;
pub mod sequence; pub mod sequence;
pub mod select;
pub mod view; pub mod view;
use clap::{self, Parser, Subcommand}; use clap::{self, Parser, Subcommand};
@ -965,10 +966,6 @@ impl <T: AsRef<Sequencer>+AsMut<Sequencer>> HasSequencer for T {}
impl <T: AsRefOpt<MidiEditor>+AsMutOpt<MidiEditor>> HasEditor for T {} impl <T: AsRefOpt<MidiEditor>+AsMutOpt<MidiEditor>> HasEditor for T {}
impl <T: NotePoint+TimePoint> MidiPoint for T {} impl <T: NotePoint+TimePoint> MidiPoint for T {}
impl <T: TimeRange+NoteRange> MidiRange for T {} impl <T: TimeRange+NoteRange> MidiRange for T {}
impl Gettable<bool> for AtomicBool { fn get (&self) -> bool { self.load(Relaxed) } }
impl InteriorMutable<bool> for AtomicBool { fn set (&self, value: bool) -> bool { self.swap(value, Relaxed) } }
impl Gettable<usize> for AtomicUsize { fn get (&self) -> usize { self.load(Relaxed) } }
impl InteriorMutable<usize> for AtomicUsize { fn set (&self, value: usize) -> usize { self.swap(value, Relaxed) } }
impl HasClipsSize for App { fn clips_size (&self) -> &Measure<Tui> { &self.project.size_inner } } impl HasClipsSize for App { fn clips_size (&self) -> &Measure<Tui> { &self.project.size_inner } }
impl HasJack<'static> for App { fn jack (&self) -> &Jack<'static> { &self.jack } } impl HasJack<'static> for App { fn jack (&self) -> &Jack<'static> { &self.jack } }
impl_default!(AppCommand: Self::Nop); impl_default!(AppCommand: Self::Nop);