wip: refactor pt.4, reduce number of files

This commit is contained in:
🪞👃🪞 2024-11-10 01:03:47 +01:00
parent adf5b3f0f8
commit 8c37c95cc6
60 changed files with 2185 additions and 2187 deletions

View file

@ -1,292 +1,23 @@
pub(crate) use tek_core::*;
pub(crate) use tek_core::jack::{TransportState, Port, MidiIn, MidiOut};
pub(crate) use tek_core::midly::{MidiMessage, num::u7};
pub(crate) use tek_core::jack::*;
pub(crate) use tek_core::midly::{*, live::LiveEvent, num::u7};
pub(crate) use std::thread::JoinHandle;
pub(crate) use std::fmt::{Debug, Formatter, Error};
submod! {
clock
mixer
phrase
plugin
pool
sampler
sample
scene
sequencer
track
transport
voice
api_cmd
api_edn
}
/// A timer with starting point, current time, and quantization
#[derive(Default, Debug)]
pub struct Clock {
/// Playback state
pub playing: RwLock<Option<TransportState>>,
/// Global sample and usec at which playback started
pub started: RwLock<Option<(usize, usize)>>,
/// Current moment in time
pub current: Instant,
/// Note quantization factor
pub quant: Quantize,
/// Launch quantization factor
pub sync: LaunchSync,
}
impl Clock {
#[inline] pub fn timebase (&self) -> &Arc<Timebase> {
&self.current.timebase
}
#[inline] pub fn pulse (&self) -> f64 {
self.current.pulse.get()
}
#[inline] pub fn quant (&self) -> f64 {
self.quant.get()
}
#[inline] pub fn sync (&self) -> f64 {
self.sync.get()
}
#[inline] pub fn next_launch_pulse (&self) -> usize {
let sync = self.sync.get() as usize;
let pulse = self.current.pulse.get() as usize;
if pulse % sync == 0 { pulse } else { (pulse / sync + 1) * sync }
}
}
pub struct TransportToolbar {
pub jack: Arc<RwLock<JackClient>>,
/// JACK transport handle.
pub transport: jack::Transport,
/// Current sample rate, tempo, and PPQ.
pub clock: Arc<Clock>,
/// Enable metronome?
pub metronome: bool,
}
pub struct Arrangement {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Arc<RwLock<JackClient>>,
/// Global timebase
pub clock: Arc<Clock>,
/// Name of arranger
pub name: Arc<RwLock<String>>,
/// Collection of phrases.
pub phrases: Arc<RwLock<Vec<Phrase>>>,
/// Collection of tracks.
pub tracks: Vec<Sequencer>,
/// Collection of scenes.
pub scenes: Vec<Scene>,
}
#[derive(Debug)]
pub struct Sequencer {
/// Name of track
pub name: Arc<RwLock<String>>,
/// Preferred width of track column
pub width: usize,
/// Identifying color of track
pub color: ItemColor,
/// MIDI player/recorder
pub player: PhrasePlayer,
}
/// Phrase player.
#[derive(Debug)]
pub struct PhrasePlayer {
/// Global timebase
pub clock: Arc<Clock>,
/// Start time and phrase being played
pub phrase: Option<(Instant, Option<Arc<RwLock<Phrase>>>)>,
/// Start time and next phrase
pub next_phrase: Option<(Instant, Option<Arc<RwLock<Phrase>>>)>,
/// 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)
/// Record from MIDI ports to current sequence.
pub midi_inputs: Vec<Port<MidiIn>>,
/// Play from current sequence to MIDI ports
pub midi_outputs: Vec<Port<MidiOut>>,
/// MIDI output buffer
pub midi_note: Vec<u8>,
/// MIDI output buffer
pub midi_chunk: Vec<Vec<Vec<u8>>>,
/// Notes currently held at input
pub notes_in: Arc<RwLock<[bool; 128]>>,
/// Notes currently held at output
pub notes_out: Arc<RwLock<[bool; 128]>>,
}
#[derive(Default, Debug, Clone)]
pub struct Scene {
/// Name of scene
pub name: Arc<RwLock<String>>,
/// Clips in scene, one per track
pub clips: Vec<Option<Arc<RwLock<Phrase>>>>,
/// Identifying color of scene
pub color: ItemColor,
}
/// A MIDI sequence.
#[derive(Debug, Clone, Default)]
pub struct Phrase {
pub uuid: uuid::Uuid,
/// Name of phrase
pub name: String,
/// Temporal resolution in pulses per quarter note
pub ppq: usize,
/// Length of phrase in pulses
pub length: usize,
/// Notes in phrase
pub notes: PhraseData,
/// Whether to loop the phrase or play it once
pub loop_on: 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 phrase
pub color: ItemColorTriplet,
}
/// MIDI message structural
pub type PhraseData = Vec<Vec<MidiMessage>>;
#[derive(Debug)]
pub struct Mixer {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Arc<RwLock<JackClient>>,
pub name: String,
pub tracks: Vec<MixerTrack>,
pub selected_track: usize,
pub selected_column: usize,
}
/// A mixer track.
#[derive(Debug)]
pub struct MixerTrack {
pub name: String,
/// Inputs and outputs of 1st and last device
pub ports: JackPorts,
/// Device chain
pub devices: Vec<JackClient>,
}
/// The sampler plugin plays sounds.
#[derive(Debug)]
pub struct Sampler {
pub jack: Arc<RwLock<JackClient>>,
pub name: String,
pub mapped: BTreeMap<u7, Arc<RwLock<Sample>>>,
pub unmapped: Vec<Arc<RwLock<Sample>>>,
pub voices: Arc<RwLock<Vec<Voice>>>,
pub ports: JackPorts,
pub buffer: Vec<Vec<f32>>,
pub output_gain: f32
}
/// A sound sample.
#[derive(Default, Debug)]
pub struct Sample {
pub name: String,
pub start: usize,
pub end: usize,
pub channels: Vec<Vec<f32>>,
pub rate: Option<usize>,
}
/// A currently playing instance of a sample.
#[derive(Default, Debug, Clone)]
pub struct Voice {
pub sample: Arc<RwLock<Sample>>,
pub after: usize,
pub position: usize,
pub velocity: f32,
}
/// A plugin device.
#[derive(Debug)]
pub struct Plugin {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Arc<RwLock<JackClient>>,
pub name: String,
pub path: Option<String>,
pub plugin: Option<PluginKind>,
pub selected: usize,
pub mapping: bool,
pub ports: JackPorts,
}
impl Plugin {
pub fn new_lv2 (
jack: &Arc<RwLock<JackClient>>,
name: &str,
path: &str,
) -> Usually<JackDevice> {
let plugin = LV2Plugin::new(path)?;
jack_from_lv2(name, &plugin.plugin)?.run(|ports|Box::new(Self {
jack: jack.clone(),
name: name.into(),
path: Some(String::from(path)),
plugin: Some(PluginKind::LV2(plugin)),
selected: 0,
mapping: false,
ports
}))
}
}
/// Supported plugin formats.
#[derive(Default)]
pub enum PluginKind {
#[default] None,
LV2(LV2Plugin),
VST2 { instance: ::vst::host::PluginInstance },
VST3,
}
impl std::fmt::Debug for PluginKind {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{}", match self {
Self::None => "(none)",
Self::LV2(_) => "LV2",
Self::VST2{..} => "VST2",
Self::VST3 => "VST3",
})
}
}
/// A LV2 plugin.
#[derive(Debug)]
pub struct LV2Plugin {
pub world: livi::World,
pub instance: livi::Instance,
pub plugin: livi::Plugin,
pub features: Arc<livi::Features>,
pub port_list: Vec<livi::Port>,
pub input_buffer: Vec<livi::event::LV2AtomSequence>,
pub ui_thread: Option<JoinHandle<()>>,
}
impl LV2Plugin {
const INPUT_BUFFER: usize = 1024;
pub fn new (uri: &str) -> Usually<Self> {
let world = livi::World::with_load_bundle(&uri);
let features = world
.build_features(livi::FeaturesBuilder {
min_block_length: 1,
max_block_length: 65536,
});
let plugin = world
.iter_plugins()
.nth(0)
.expect(&format!("plugin not found: {uri}"));
Ok(Self {
instance: unsafe {
plugin
.instantiate(features.clone(), 48000.0)
.expect(&format!("instantiate failed: {uri}"))
},
port_list: plugin.ports().collect::<Vec<_>>(),
input_buffer: Vec::with_capacity(Self::INPUT_BUFFER),
ui_thread: None,
world,
features,
plugin,
})
}
api_jack
}