mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
This commit is contained in:
parent
573534a9a6
commit
447638ee71
30 changed files with 824 additions and 548 deletions
|
|
@ -18,8 +18,8 @@ mod arranger_view; pub use self::arranger_view::*;
|
|||
|
||||
def_sizes_iter!(ScenesSizes => Scene);
|
||||
def_sizes_iter!(TracksSizes => Track);
|
||||
def_sizes_iter!(InputsSizes => JackMidiIn);
|
||||
def_sizes_iter!(OutputsSizes => JackMidiOut);
|
||||
def_sizes_iter!(InputsSizes => MidiInput);
|
||||
def_sizes_iter!(OutputsSizes => MidiOutput);
|
||||
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
|
||||
|
||||
pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
||||
|
|
|
|||
|
|
@ -1,23 +1,4 @@
|
|||
use crate::*;
|
||||
|
||||
#[tengri_proc::expose]
|
||||
impl Arrangement {
|
||||
fn _todo_usize_stub_ (&self) -> usize { todo!() }
|
||||
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
|
||||
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
|
||||
fn _todo_opt_item_theme_stub (&self) -> Option<ItemTheme> { todo!() }
|
||||
fn select_nothing (&self) -> Selection {
|
||||
Selection::Nothing
|
||||
}
|
||||
}
|
||||
|
||||
dsl!(TrackCommand: |self: Arrangement, iter|self.take(iter));
|
||||
dsl!(MidiInputCommand: |self: Arrangement, iter|self.take(iter));
|
||||
dsl!(MidiOutputCommand: |self: Arrangement, iter|self.take(iter));
|
||||
dsl!(DeviceCommand: |self: Arrangement, iter|self.take(iter));
|
||||
dsl!(SceneCommand: |self: Arrangement, iter|self.take(iter));
|
||||
dsl!(ClipCommand: |self: Arrangement, iter|self.take(iter));
|
||||
|
||||
#[tengri_proc::command(Arrangement)]
|
||||
impl ArrangementCommand {
|
||||
fn home (arranger: &mut Arrangement) -> Perhaps<Self> {
|
||||
|
|
@ -173,7 +154,7 @@ impl ArrangementCommand {
|
|||
Ok(None)
|
||||
}
|
||||
fn output_add (arranger: &mut Arrangement) -> Perhaps<Self> {
|
||||
arranger.midi_outs.push(JackMidiOut::new(
|
||||
arranger.midi_outs.push(MidiOutput::new(
|
||||
arranger.jack(),
|
||||
format!("/M{}", arranger.midi_outs.len() + 1),
|
||||
&[]
|
||||
|
|
@ -181,7 +162,7 @@ impl ArrangementCommand {
|
|||
Ok(None)
|
||||
}
|
||||
fn input_add (arranger: &mut Arrangement) -> Perhaps<Self> {
|
||||
arranger.midi_ins.push(JackMidiIn::new(
|
||||
arranger.midi_ins.push(MidiInput::new(
|
||||
arranger.jack(),
|
||||
format!("M{}/", arranger.midi_ins.len() + 1),
|
||||
&[]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,47 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Arrangement {
|
||||
has!(Jack: |self: Arrangement|self.jack);
|
||||
has!(Clock: |self: Arrangement|self.clock);
|
||||
has!(Selection: |self: Arrangement|self.selection);
|
||||
has!(Vec<MidiInput>: |self: Arrangement|self.midi_ins);
|
||||
has!(Vec<MidiOutput>: |self: Arrangement|self.midi_outs);
|
||||
has!(Vec<Scene>: |self: Arrangement|self.scenes);
|
||||
has!(Vec<Track>: |self: Arrangement|self.tracks);
|
||||
has!(Measure<TuiOut>: |self: Arrangement|self.size);
|
||||
has!(Option<MidiEditor>: |self: Arrangement|self.editor);
|
||||
maybe_has!(Track: |self: Arrangement|
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Track>>::get(self).get(index)).flatten() };
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Track>>::get_mut(self).get_mut(index)).flatten() });
|
||||
maybe_has!(Scene: |self: Arrangement|
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get(self).get(index)).flatten() };
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get_mut(self).get_mut(index)).flatten() });
|
||||
from_dsl!(MidiInputCommand: |state: Arrangement, iter|state.selected_midi_in().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
from_dsl!(MidiOutputCommand: |state: Arrangement, iter|state.selected_midi_out().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
from_dsl!(DeviceCommand: |state: Arrangement, iter|state.selected_device().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
from_dsl!(TrackCommand: |state: Arrangement, iter|state.selected_track().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
from_dsl!(SceneCommand: |state: Arrangement, iter|state.selected_scene().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
from_dsl!(ClipCommand: |state: Arrangement, iter|state.selected_clip().as_ref()
|
||||
.map(|t|FromDsl::take_from(t, iter)).transpose().map(|x|x.flatten()));
|
||||
#[tengri_proc::expose] impl Arrangement {
|
||||
fn selected_midi_in (&self) -> Option<MidiInput> { todo!() }
|
||||
fn selected_midi_out (&self) -> Option<MidiOutput> { todo!() }
|
||||
fn selected_device (&self) -> Option<Device> { todo!() }
|
||||
fn selected_track (&self) -> Option<Track> { todo!() }
|
||||
fn selected_scene (&self) -> Option<Scene> { todo!() }
|
||||
fn selected_clip (&self) -> Option<MidiClip> { todo!() }
|
||||
fn _todo_usize_stub_ (&self) -> usize { todo!() }
|
||||
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
|
||||
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
|
||||
fn _todo_opt_item_theme_stub (&self) -> Option<ItemTheme> { todo!() }
|
||||
fn select_nothing (&self) -> Selection {
|
||||
Selection::Nothing
|
||||
}
|
||||
}
|
||||
#[derive(Default, Debug)] pub struct Arrangement {
|
||||
/// Project name.
|
||||
pub name: Arc<str>,
|
||||
/// Base color.
|
||||
|
|
@ -13,13 +53,13 @@ pub struct Arrangement {
|
|||
/// Allows one MIDI clip to be edited
|
||||
pub editor: Option<MidiEditor>,
|
||||
/// List of global midi inputs
|
||||
pub midi_ins: Vec<JackMidiIn>,
|
||||
pub midi_ins: Vec<MidiInput>,
|
||||
/// List of global midi outputs
|
||||
pub midi_outs: Vec<JackMidiOut>,
|
||||
pub midi_outs: Vec<MidiOutput>,
|
||||
/// List of global audio inputs
|
||||
pub audio_ins: Vec<JackAudioIn>,
|
||||
pub audio_ins: Vec<AudioInput>,
|
||||
/// List of global audio outputs
|
||||
pub audio_outs: Vec<JackAudioOut>,
|
||||
pub audio_outs: Vec<AudioOutput>,
|
||||
/// Last track number (to avoid duplicate port names)
|
||||
pub track_last: usize,
|
||||
/// List of tracks
|
||||
|
|
@ -40,23 +80,6 @@ pub struct Arrangement {
|
|||
/// Display size of clips area
|
||||
pub inner_size: Measure<TuiOut>,
|
||||
}
|
||||
|
||||
has!(Jack: |self: Arrangement|self.jack);
|
||||
has!(Clock: |self: Arrangement|self.clock);
|
||||
has!(Selection: |self: Arrangement|self.selection);
|
||||
has!(Vec<JackMidiIn>: |self: Arrangement|self.midi_ins);
|
||||
has!(Vec<JackMidiOut>: |self: Arrangement|self.midi_outs);
|
||||
has!(Vec<Scene>: |self: Arrangement|self.scenes);
|
||||
has!(Vec<Track>: |self: Arrangement|self.tracks);
|
||||
has!(Measure<TuiOut>: |self: Arrangement|self.size);
|
||||
has!(Option<MidiEditor>: |self: Arrangement|self.editor);
|
||||
maybe_has!(Track: |self: Arrangement|
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Track>>::get(self).get(index)).flatten() };
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Track>>::get_mut(self).get_mut(index)).flatten() });
|
||||
maybe_has!(Scene: |self: Arrangement|
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get(self).get(index)).flatten() };
|
||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get_mut(self).get_mut(index)).flatten() });
|
||||
|
||||
impl Arrangement {
|
||||
/// Width of display
|
||||
pub fn w (&self) -> u16 {
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ pub struct Clock {
|
|||
/// Size of buffer in samples
|
||||
pub chunk: Arc<AtomicUsize>,
|
||||
/// For syncing the clock to an external source
|
||||
pub midi_in: Arc<RwLock<Option<JackMidiIn>>>,
|
||||
pub midi_in: Arc<RwLock<Option<MidiInput>>>,
|
||||
/// For syncing other devices to this clock
|
||||
pub midi_out: Arc<RwLock<Option<JackMidiOut>>>,
|
||||
pub midi_out: Arc<RwLock<Option<MidiOutput>>>,
|
||||
/// For emitting a metronome
|
||||
pub click_out: Arc<RwLock<Option<JackAudioOut>>>,
|
||||
pub click_out: Arc<RwLock<Option<AudioOutput>>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Clock {
|
||||
|
|
@ -56,9 +56,9 @@ impl Clock {
|
|||
offset: Arc::new(Moment::zero(&timebase)),
|
||||
started: RwLock::new(None).into(),
|
||||
timebase,
|
||||
midi_in: Arc::new(RwLock::new(Some(JackMidiIn::new(jack, "M/clock", &[])?))),
|
||||
midi_out: Arc::new(RwLock::new(Some(JackMidiOut::new(jack, "clock/M", &[])?))),
|
||||
click_out: Arc::new(RwLock::new(Some(JackAudioOut::new(jack, "click", &[])?))),
|
||||
midi_in: Arc::new(RwLock::new(Some(MidiInput::new(jack, "M/clock", &[])?))),
|
||||
midi_out: Arc::new(RwLock::new(Some(MidiOutput::new(jack, "clock/M", &[])?))),
|
||||
click_out: Arc::new(RwLock::new(Some(AudioOutput::new(jack, "click", &[])?))),
|
||||
};
|
||||
if let Some(bpm) = bpm {
|
||||
clock.timebase.bpm.set(bpm);
|
||||
|
|
|
|||
|
|
@ -44,25 +44,25 @@ impl Device {
|
|||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
pub fn midi_ins (&self) -> &[JackMidiIn] {
|
||||
pub fn midi_ins (&self) -> &[MidiInput] {
|
||||
match self {
|
||||
//Self::Sampler(Sampler { midi_in, .. }) => &[midi_in],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn midi_outs (&self) -> &[JackMidiOut] {
|
||||
pub fn midi_outs (&self) -> &[MidiOutput] {
|
||||
match self {
|
||||
Self::Sampler(_) => &[],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_ins (&self) -> &[JackAudioIn] {
|
||||
pub fn audio_ins (&self) -> &[AudioInput] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_ins, .. }) => audio_ins.as_slice(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_outs (&self) -> &[JackAudioOut] {
|
||||
pub fn audio_outs (&self) -> &[AudioOutput] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_outs, .. }) => audio_outs.as_slice(),
|
||||
_ => todo!()
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
use crate::*;
|
||||
|
||||
content!(TuiOut: |self: Dialog| match self {
|
||||
Self::Menu(_) =>
|
||||
self.view_dialog_menu().boxed(),
|
||||
Self::Help(offset) =>
|
||||
self.view_dialog_help(*offset).boxed(),
|
||||
Self::Browser(target, browser) =>
|
||||
self.view_dialog_browser(target, browser).boxed(),
|
||||
Self::Options =>
|
||||
self.view_dialog_options().boxed(),
|
||||
Self::Device(index) =>
|
||||
self.view_dialog_device(*index).boxed(),
|
||||
Self::Message(message) =>
|
||||
self.view_dialog_message(message).boxed(),
|
||||
});
|
||||
impl Content<TuiOut> for Dialog {
|
||||
fn content (&self) -> impl Render<TuiOut> + '_ {
|
||||
Some(match self {
|
||||
Self::Menu(_) => self.view_dialog_menu().boxed(),
|
||||
_ => "kyp".boxed()
|
||||
})
|
||||
//Self::Help(offset) =>
|
||||
//self.view_dialog_help(*offset).boxed(),
|
||||
//Self::Browser(target, browser) =>
|
||||
//self.view_dialog_browser(target, browser).boxed(),
|
||||
//Self::Options =>
|
||||
//self.view_dialog_options().boxed(),
|
||||
//Self::Device(index) =>
|
||||
//self.view_dialog_device(*index).boxed(),
|
||||
//Self::Message(message) =>
|
||||
//self.view_dialog_message(message).boxed(),
|
||||
//})
|
||||
}
|
||||
}
|
||||
|
||||
content!(TuiOut: |self: Message| match self {
|
||||
Self::FailedToAddDevice => "Failed to add device."
|
||||
|
|
@ -25,7 +30,7 @@ impl Dialog {
|
|||
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
|
||||
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
|
||||
}
|
||||
pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content<TuiOut> + use<'a> {
|
||||
pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content<TuiOut> + 'a {
|
||||
Bsp::s(Tui::bold(true, "Help"), "FIXME")
|
||||
//Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1,
|
||||
//move||self.config.keys.layers.iter()
|
||||
|
|
|
|||
|
|
@ -81,9 +81,6 @@ impl PoolCommand {
|
|||
|
||||
}
|
||||
|
||||
dsl!(BrowserCommand: |self: Pool, iter|Ok(self.browser
|
||||
.as_ref().map(|p|p.take(iter)).transpose()?.flatten()));
|
||||
|
||||
#[tengri_proc::command(Pool)]
|
||||
impl PoolClipCommand {
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ pub struct Pool {
|
|||
/// Embedded file browser
|
||||
pub browser: Option<Browser>,
|
||||
}
|
||||
|
||||
from_dsl!(BrowserCommand: |state: Pool, iter|Ok(state.browser
|
||||
.as_ref()
|
||||
.map(|p|FromDsl::take_from(p, iter))
|
||||
.transpose()?
|
||||
.flatten()));
|
||||
impl Default for Pool {
|
||||
fn default () -> Self {
|
||||
use PoolMode::*;
|
||||
|
|
|
|||
|
|
@ -63,21 +63,17 @@ impl SamplerCommand {
|
|||
fn record_begin (sampler: &mut Sampler, slot: usize) -> Perhaps<Self> {
|
||||
sampler.recording = Some((
|
||||
slot,
|
||||
Arc::new(RwLock::new(Sample::new(
|
||||
Some(Arc::new(RwLock::new(Sample::new(
|
||||
"Sample", 0, 0, vec![vec![];sampler.audio_ins.len()]
|
||||
)))
|
||||
))))
|
||||
));
|
||||
Ok(None)
|
||||
}
|
||||
fn record_finish (sampler: &mut Sampler) -> Perhaps<Self> {
|
||||
let recording = sampler.recording.take();
|
||||
let _sample = if let Some((index, sample)) = recording {
|
||||
let old = sampler.mapped[index].clone();
|
||||
sampler.mapped[index] = Some(sample);
|
||||
old
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let _prev_sample = sampler.recording.as_mut().map(|(index, sample)|{
|
||||
std::mem::swap(sample, &mut sampler.mapped[*index]);
|
||||
sample
|
||||
}); // TODO: undo
|
||||
Ok(None)
|
||||
}
|
||||
fn record_cancel (sampler: &mut Sampler) -> Perhaps<Self> {
|
||||
|
|
|
|||
|
|
@ -28,23 +28,25 @@ impl Sampler {
|
|||
|
||||
/// Record from inputs to sample
|
||||
fn record_into (&mut self, scope: &ProcessScope) {
|
||||
let mut sample = self.recording
|
||||
.as_mut().expect("no recording sample").1
|
||||
.write().unwrap();
|
||||
if sample.channels.len() != self.audio_ins.len() {
|
||||
panic!("channel count mismatch");
|
||||
if let Some(ref sample) = self.recording.as_ref().expect("no recording sample").1 {
|
||||
let mut sample = sample.write().unwrap();
|
||||
if sample.channels.len() != self.audio_ins.len() {
|
||||
panic!("channel count mismatch");
|
||||
}
|
||||
let samples_with_meters = self.audio_ins.iter()
|
||||
.zip(self.input_meters.iter_mut())
|
||||
.zip(sample.channels.iter_mut());
|
||||
let mut length = 0;
|
||||
for ((input, meter), channel) in samples_with_meters {
|
||||
let slice = input.port().as_slice(scope);
|
||||
length = length.max(slice.len());
|
||||
*meter = to_rms(slice);
|
||||
channel.extend_from_slice(slice);
|
||||
}
|
||||
sample.end += length;
|
||||
} else {
|
||||
panic!("tried to record into the void")
|
||||
}
|
||||
let samples_with_meters = self.audio_ins.iter()
|
||||
.zip(self.input_meters.iter_mut())
|
||||
.zip(sample.channels.iter_mut());
|
||||
let mut length = 0;
|
||||
for ((input, meter), channel) in samples_with_meters {
|
||||
let slice = input.port().as_slice(scope);
|
||||
length = length.max(slice.len());
|
||||
*meter = to_rms(slice);
|
||||
channel.extend_from_slice(slice);
|
||||
}
|
||||
sample.end += length;
|
||||
}
|
||||
|
||||
/// Update input meters
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ pub struct Sampler {
|
|||
/// Device color.
|
||||
pub color: ItemTheme,
|
||||
/// Audio input ports. Samples get recorded here.
|
||||
pub audio_ins: Vec<JackAudioIn>,
|
||||
pub audio_ins: Vec<AudioInput>,
|
||||
/// Audio input meters.
|
||||
pub input_meters: Vec<f32>,
|
||||
/// Sample currently being recorded.
|
||||
pub recording: Option<(usize, Arc<RwLock<Sample>>)>,
|
||||
pub recording: Option<(usize, Option<Arc<RwLock<Sample>>>)>,
|
||||
/// Recording buffer.
|
||||
pub buffer: Vec<Vec<f32>>,
|
||||
/// Samples mapped to MIDI notes.
|
||||
|
|
@ -22,11 +22,11 @@ pub struct Sampler {
|
|||
/// Sample currently being edited.
|
||||
pub editing: Option<Arc<RwLock<Sample>>>,
|
||||
/// MIDI input port. Triggers sample playback.
|
||||
pub midi_in: JackMidiIn,
|
||||
pub midi_in: MidiInput,
|
||||
/// Collection of currently playing instances of samples.
|
||||
pub voices: Arc<RwLock<Vec<Voice>>>,
|
||||
/// Audio output ports. Voices get played here.
|
||||
pub audio_outs: Vec<JackAudioOut>,
|
||||
pub audio_outs: Vec<AudioOutput>,
|
||||
/// Audio output meters.
|
||||
pub output_meters: Vec<f32>,
|
||||
/// How to mix the voices.
|
||||
|
|
@ -58,14 +58,14 @@ impl Sampler {
|
|||
let name = name.as_ref();
|
||||
Ok(Self {
|
||||
name: name.into(),
|
||||
midi_in: JackMidiIn::new(jack, format!("M/{name}"), midi_from)?,
|
||||
midi_in: MidiInput::new(jack, format!("M/{name}"), midi_from)?,
|
||||
audio_ins: vec![
|
||||
JackAudioIn::new(jack, &format!("L/{name}"), audio_from[0])?,
|
||||
JackAudioIn::new(jack, &format!("R/{name}"), audio_from[1])?,
|
||||
AudioInput::new(jack, &format!("L/{name}"), audio_from[0])?,
|
||||
AudioInput::new(jack, &format!("R/{name}"), audio_from[1])?,
|
||||
],
|
||||
audio_outs: vec![
|
||||
JackAudioOut::new(jack, &format!("{name}/L"), audio_to[0])?,
|
||||
JackAudioOut::new(jack, &format!("{name}/R"), audio_to[1])?,
|
||||
AudioOutput::new(jack, &format!("{name}/L"), audio_to[0])?,
|
||||
AudioOutput::new(jack, &format!("{name}/R"), audio_to[1])?,
|
||||
],
|
||||
input_meters: vec![0.0;2],
|
||||
output_meters: vec![0.0;2],
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ impl Sampler {
|
|||
|
||||
pub fn view_sample (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||
Outer(true, Style::default().fg(Tui::g(96)))
|
||||
.enclose(Fill::xy(draw_viewer(if let Some((_, sample)) = &self.recording {
|
||||
.enclose(Fill::xy(draw_viewer(if let Some((_, Some(sample))) = &self.recording {
|
||||
Some(sample)
|
||||
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||
Some(sample)
|
||||
|
|
@ -109,7 +109,7 @@ impl Sampler {
|
|||
}
|
||||
|
||||
pub fn view_sample_info (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||
Fill::x(Fixed::y(1, draw_info(if let Some((_, sample)) = &self.recording {
|
||||
Fill::x(Fixed::y(1, draw_info(if let Some((_, Some(sample))) = &self.recording {
|
||||
Some(sample)
|
||||
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||
Some(sample)
|
||||
|
|
@ -119,7 +119,7 @@ impl Sampler {
|
|||
}
|
||||
|
||||
pub fn view_sample_status (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||
Fixed::x(20, draw_info_v(if let Some((_, sample)) = &self.recording {
|
||||
Fixed::x(20, draw_info_v(if let Some((_, Some(sample))) = &self.recording {
|
||||
Some(sample)
|
||||
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||
Some(sample)
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ pub struct Sequencer {
|
|||
/// Send all notes off
|
||||
pub reset: bool, // TODO?: after Some(nframes)
|
||||
/// Record from MIDI ports to current sequence.
|
||||
pub midi_ins: Vec<JackMidiIn>,
|
||||
pub midi_ins: Vec<MidiInput>,
|
||||
/// Play from current sequence to MIDI ports
|
||||
pub midi_outs: Vec<JackMidiOut>,
|
||||
pub midi_outs: Vec<MidiOutput>,
|
||||
/// Notes currently held at input
|
||||
pub notes_in: Arc<RwLock<[bool; 128]>>,
|
||||
/// Notes currently held at output
|
||||
|
|
@ -79,8 +79,8 @@ impl Sequencer {
|
|||
let _name = name.as_ref();
|
||||
let clock = clock.cloned().unwrap_or_default();
|
||||
Ok(Self {
|
||||
midi_ins: vec![JackMidiIn::new(jack, format!("M/{}", name.as_ref()), midi_from)?,],
|
||||
midi_outs: vec![JackMidiOut::new(jack, format!("{}/M", name.as_ref()), midi_to)?, ],
|
||||
midi_ins: vec![MidiInput::new(jack, format!("M/{}", name.as_ref()), midi_from)?,],
|
||||
midi_outs: vec![MidiOutput::new(jack, format!("{}/M", name.as_ref()), midi_to)?, ],
|
||||
play_clip: clip.map(|clip|(Moment::zero(&clock.timebase), Some(clip.clone()))),
|
||||
clock,
|
||||
reset: true,
|
||||
|
|
@ -102,8 +102,8 @@ impl std::fmt::Debug for Sequencer {
|
|||
}
|
||||
|
||||
has!(Clock: |self: Sequencer|self.clock);
|
||||
has!(Vec<JackMidiIn>: |self:Sequencer| self.midi_ins);
|
||||
has!(Vec<JackMidiOut>: |self:Sequencer| self.midi_outs);
|
||||
has!(Vec<MidiInput>: |self:Sequencer| self.midi_ins);
|
||||
has!(Vec<MidiOutput>: |self:Sequencer| self.midi_outs);
|
||||
|
||||
impl MidiMonitor for Sequencer {
|
||||
fn notes_in (&self) -> &Arc<RwLock<[bool; 128]>> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue