use crate::*; /// The source of time. /// /// ``` /// let clock = tek_device::Clock::default(); /// ``` #[derive(Clone, Default)] pub struct Clock { /// JACK transport handle. pub transport: Arc>, /// Global temporal resolution (shared by [Moment] fields) pub timebase: Arc, /// Current global sample and usec (monotonic from JACK clock) pub global: Arc, /// Global sample and usec at which playback started pub started: Arc>>, /// Playback offset (when playing not from start) pub offset: Arc, /// Current playhead position pub playhead: Arc, /// Note quantization factor pub quant: Arc, /// Launch quantization factor pub sync: Arc, /// Size of buffer in samples pub chunk: Arc, // Cache of formatted strings pub view_cache: Arc>, /// For syncing the clock to an external source #[cfg(feature = "port")] pub midi_in: Arc>>, /// For syncing other devices to this clock #[cfg(feature = "port")] pub midi_out: Arc>>, /// For emitting a metronome #[cfg(feature = "port")] pub click_out: Arc>>, } /// Contains memoized renders of clock values. /// /// Performance optimization. #[derive(Debug)] pub struct ClockView { pub sr: Memo, String>, pub buf: Memo, String>, pub lat: Memo, String>, pub bpm: Memo, String>, pub beat: Memo, String>, pub time: Memo, String>, } /// Arranger. /// /// ``` /// let arranger = tek_device::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: Measure, /// Display size of clips area pub size_inner: Measure, /// 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, } /// Browses for phrase to import/export /// /// ``` /// let browser = tek_device::Browser::default(); /// ``` #[derive(Debug, Clone, Default, PartialEq)] pub struct Browse { pub cwd: PathBuf, pub dirs: Vec<(OsString, String)>, pub files: Vec<(OsString, String)>, pub filter: String, pub index: usize, pub scroll: usize, pub size: Measure, } #[derive(Default)] pub(crate) struct EntriesIterator<'a> { pub browser: &'a Browse, pub offset: usize, pub length: usize, pub index: usize, } #[derive(Clone, Debug)] pub enum BrowseTarget { SaveProject, LoadProject, ImportSample(Arc>>), ExportSample(Arc>>), ImportClip(Arc>>), ExportClip(Arc>>), } /// A MIDI sequence. /// /// ``` /// let clip = tek_device::MidiClip::default(); /// ``` #[derive(Debug, Clone, Default)] pub struct MidiClip { pub uuid: uuid::Uuid, /// Name of clip pub name: Arc, /// Temporal resolution in pulses per quarter note pub ppq: usize, /// Length of clip in pulses pub length: usize, /// Notes in clip pub notes: MidiData, /// Whether to loop the clip or play it once pub looped: bool, /// Start of loop pub loop_start: usize, /// Length of loop pub loop_length: usize, /// All notes are displayed with minimum length pub percussive: bool, /// Identifying color of clip pub color: ItemTheme, } /// A device that can be plugged into the chain. /// /// ``` /// let device = tek_engie::Device::default(); /// ``` #[derive(Debug, Default)] pub enum Device { #[default] Bypass, Mute, #[cfg(feature = "sampler")] Sampler(Sampler), #[cfg(feature = "lv2")] // TODO Lv2(Lv2), #[cfg(feature = "vst2")] // TODO Vst2, #[cfg(feature = "vst3")] // TODO Vst3, #[cfg(feature = "clap")] // TODO Clap, #[cfg(feature = "sf2")] // TODO Sf2, } /// Some sort of wrapper? pub struct DeviceAudio<'a>(pub &'a mut Device); /// Contains state for viewing and editing a clip. /// /// ``` /// let mut editor = tek_device::MidiEditor { /// mode: PianoHorizontal::new(Some(&Arc::new(RwLock::new(MidiClip::stop_all())))), /// size: Default::default(), /// //keys: Default::default(), /// }; /// let _ = editor.put_note(true); /// let _ = editor.put_note(false); /// let _ = editor.clip_status(); /// let _ = editor.edit_status(); /// ``` pub struct MidiEditor { /// Size of editor on screen pub size: Measure, /// View mode and state of editor pub mode: PianoHorizontal, } /// A clip, rendered as a horizontal piano roll. /// /// ``` /// let piano = tek_device::PianoHorizontal::default(); /// ``` #[derive(Clone, Default)] pub struct PianoHorizontal { pub clip: Option>>, /// Buffer where the whole clip is rerendered on change pub buffer: Arc>, /// Size of actual notes area pub size: Measure, /// The display window pub range: MidiSelection, /// The note cursor pub point: MidiCursor, /// The highlight color palette pub color: ItemTheme, /// Width of the keyboard pub keys_width: u16, } /// 12 piano keys, some highlighted. /// /// ``` /// let keys = tek_device::OctaveVertical::default(); /// ``` #[derive(Copy, Clone)] pub struct OctaveVertical { pub on: [bool; 12], pub colors: [Color; 3] } /// A LV2 plugin. #[derive(Debug)] #[cfg(feature = "lv2")] pub struct Lv2 { /// JACK client handle (needs to not be dropped for standalone mode to work). pub jack: Jack<'static>, pub name: Arc, pub path: Option>, pub selected: usize, pub mapping: bool, pub midi_ins: Vec>, pub midi_outs: Vec>, pub audio_ins: Vec>, pub audio_outs: Vec>, pub lv2_world: livi::World, pub lv2_instance: livi::Instance, pub lv2_plugin: livi::Plugin, pub lv2_features: Arc, pub lv2_port_list: Vec, pub lv2_input_buffer: Vec, pub lv2_ui_thread: Option>, } /// A LV2 plugin's X11 UI. #[cfg(feature = "lv2_gui")] pub struct LV2PluginUI { pub window: Option } #[derive(Debug, Default)] pub enum MeteringMode { #[default] Rms, Log10, } #[derive(Debug, Default, Clone)] pub struct Log10Meter(pub f32); #[derive(Debug, Default, Clone)] pub struct RmsMeter(pub f32); #[derive(Debug, Default)] pub enum MixingMode { #[default] Summing, Average, } /// A clip pool. /// /// ``` /// let pool = tek_device::Pool::default(); /// ``` #[derive(Debug)] pub struct Pool { pub visible: bool, /// Selected clip pub clip: AtomicUsize, /// Mode switch pub mode: Option, /// Embedded file browse #[cfg(feature = "browse")] pub browse: Option, /// Collection of MIDI clips. #[cfg(feature = "clip")] pub clips: Arc>>>>, /// Collection of sound samples. #[cfg(feature = "sampler")] pub samples: Arc>>>>, } /// Displays and edits clip length. #[derive(Clone, Debug, Default)] pub struct ClipLength { /// Pulses per beat (quaver) pub ppq: usize, /// Beats per bar pub bpb: usize, /// Length of clip in pulses pub pulses: usize, /// Selected subdivision pub focus: Option, } /// Some sort of wrapper again? pub struct PoolView<'a>(pub &'a Pool); /// Audio input port. #[derive(Debug)] pub struct AudioInput { /// Handle to JACK client, for receiving reconnect events. pub jack: Jack<'static>, /// Port name pub name: Arc, /// Port handle. pub port: Port, /// List of ports to connect to. pub connections: Vec, } /// Audio output port. #[derive(Debug)] pub struct AudioOutput { /// Handle to JACK client, for receiving reconnect events. pub jack: Jack<'static>, /// Port name pub name: Arc, /// Port handle. pub port: Port, /// List of ports to connect to. pub connections: Vec, } /// MIDI input port. #[derive(Debug)] pub struct MidiInput { /// Handle to JACK client, for receiving reconnect events. pub jack: Jack<'static>, /// Port name pub name: Arc, /// Port handle. pub port: Port, /// List of currently held notes. pub held: Arc>, /// List of ports to connect to. pub connections: Vec, } /// MIDI output port. #[derive(Debug)] pub struct MidiOutput { /// Handle to JACK client, for receiving reconnect events. pub jack: Jack<'static>, /// Port name pub name: Arc, /// Port handle. pub port: Port, /// List of ports to connect to. pub connections: Vec, /// List of currently held notes. pub held: Arc>, /// Buffer pub note_buffer: Vec, /// Buffer pub output_buffer: Vec>>, } /// Port connection manager. /// /// ``` /// let connect = tek_engine::Connect::default(); /// ``` #[derive(Clone, Debug, Default)] pub struct Connect { pub name: Option, pub scope: Option, pub status: Arc, Arc, ConnectStatus)>>>, pub info: Arc, } /// Plays [Voice]s from [Sample]s. /// /// ``` /// let sampler = tek_device::Sampler::default(); /// ``` #[derive(Debug, Default)] pub struct Sampler { /// Name of sampler. pub name: Arc, /// Device color. pub color: ItemTheme, /// Audio input ports. Samples get recorded here. #[cfg(feature = "port")] pub audio_ins: Vec, /// Audio input meters. #[cfg(feature = "meter")] pub input_meters: Vec, /// Sample currently being recorded. pub recording: Option<(usize, Option>>)>, /// Recording buffer. pub buffer: Vec>, /// Samples mapped to MIDI notes. pub mapped: [Option>>;128], /// Samples that are not mapped to MIDI notes. pub unmapped: Vec>>, /// Sample currently being edited. pub editing: Option>>, /// MIDI input port. Triggers sample playback. #[cfg(feature = "port")] pub midi_in: Option, /// Collection of currently playing instances of samples. pub voices: Arc>>, /// Audio output ports. Voices get played here. #[cfg(feature = "port")] pub audio_outs: Vec, /// Audio output meters. #[cfg(feature = "meter")] pub output_meters: Vec, /// How to mix the voices. pub mixing_mode: MixingMode, /// How to meter the inputs and outputs. pub metering_mode: MeteringMode, /// Fixed gain applied to all output. pub output_gain: f32, /// Currently active modal, if any. pub mode: Option, /// Size of rendered sampler. pub size: Measure, /// Lowest note displayed. pub note_lo: AtomicUsize, /// Currently selected note. pub note_pt: AtomicUsize, /// Selected note as row/col. pub cursor: (AtomicUsize, AtomicUsize), } /// A sound cut. /// /// ``` /// let sample = tek_device::Sample::default(); /// let sample = tek_device::Sample::new("test", 0, 0, vec![]); /// ``` #[derive(Default, Debug)] pub struct Sample { pub name: Arc, pub start: usize, pub end: usize, pub channels: Vec>, pub rate: Option, pub gain: f32, pub color: ItemTheme, } /// A currently playing instance of a sample. #[derive(Default, Debug, Clone)] pub struct Voice { pub sample: Arc>, pub after: usize, pub position: usize, pub velocity: f32, } pub struct AddSampleModal { pub exited: bool, pub dir: PathBuf, pub subdirs: Vec, pub files: Vec, pub cursor: usize, pub offset: usize, pub sample: Arc>, pub voices: Arc>>, pub _search: Option, } /// A scene consists of a set of clips to play together. /// /// ``` /// let scene: tek_device::Scene = Default::default(); /// let _ = scene.pulses(); /// let _ = scene.is_playing(&[]); /// ``` #[derive(Debug, Default)] pub struct Scene { /// Name of scene pub name: Arc, /// Identifying color of scene pub color: ItemTheme, /// Clips in scene, one per track pub clips: Vec>>>, } /// 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 }, } /// Contains state for playing a clip /// /// ``` /// let clip = tek_device::MidiClip::default(); /// println!("Empty clip: {clip:?}"); /// /// let clip = tek_device::MidiClip::stop_all(); /// println!("Panic clip: {clip:?}"); /// /// let mut clip = tek_device::MidiClip::new("clip", true, 1, None, None); /// clip.set_length(96); /// clip.toggle_loop(); /// clip.record_event(12, midly::MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }); /// assert!(clip.contains_note_on(36.into(), 6, 18)); /// assert_eq!(&clip.notes, &clip.duplicate().notes); /// /// let clip = std::sync::Arc::new(clip); /// assert_eq!(clip.clone(), clip); /// /// let sequencer = tek_device::Sequencer::default(); /// println!("{sequencer:?}"); /// ``` pub struct Sequencer { /// State of clock and playhead #[cfg(feature = "clock")] pub clock: Clock, /// Start time and clip being played #[cfg(feature = "clip")] pub play_clip: Option<(Moment, Option>>)>, /// Start time and next clip #[cfg(feature = "clip")] pub next_clip: Option<(Moment, Option>>)>, /// Record from MIDI ports to current sequence. #[cfg(feature = "port")] pub midi_ins: Vec, /// Play from current sequence to MIDI ports #[cfg(feature = "port")] pub midi_outs: Vec, /// Play input through output. pub monitoring: bool, /// Write input to sequence. pub recording: bool, /// Overdub input to sequence. pub overdub: bool, /// Send all notes off pub reset: bool, // TODO?: after Some(nframes) /// Notes currently held at input pub notes_in: Arc>, /// Notes currently held at output pub notes_out: Arc>, /// MIDI output buffer pub note_buf: Vec, /// MIDI output buffer pub midi_buf: Vec>>, } /// A track consists of a sequencer and zero or more devices chained after it. /// /// ``` /// let track: tek_device::Track = Default::default(); /// ``` #[derive(Debug, Default)] pub struct Track { /// Name of track pub name: Arc, /// 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, } // Commands supported by [Browse] //#[derive(Debug, Clone, PartialEq)] //pub enum BrowseCommand { //Begin, //Cancel, //Confirm, //Select(usize), //Chdir(PathBuf), //Filter(Arc), //} /// Modes for clip pool #[derive(Debug, Clone)] pub enum PoolMode { /// Renaming a pattern Rename(usize, Arc), /// Editing the length of a pattern Length(usize, usize, ClipLengthFocus), /// Load clip from disk Import(usize, Browse), /// Save clip to disk Export(usize, Browse), } /// Focused field of `ClipLength` #[derive(Copy, Clone, Debug)] pub enum ClipLengthFocus { /// Editing the number of bars Bar, /// Editing the number of beats Beat, /// Editing the number of ticks Tick, } #[derive(Clone, Debug, PartialEq)] pub enum ConnectName { /** Exact match */ Exact(Arc), /** Match regular expression */ RegExp(Arc), } #[derive(Clone, Copy, Debug, PartialEq)] pub enum ConnectScope { One, All } #[derive(Clone, Copy, Debug, PartialEq)] pub enum ConnectStatus { Missing, Disconnected, Connected, Mismatch, } #[derive(Debug)] pub enum SamplerMode { // Load sample from path Import(usize, Browse), }