mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
109 lines
3.3 KiB
Rust
109 lines
3.3 KiB
Rust
use crate::*;
|
|
|
|
//impl_port!(MidiInput: MidiOut -> MidiIn |j, n|j.register_port::<MidiOut>(n));
|
|
|
|
#[derive(Debug)] pub struct MidiInput {
|
|
/// Handle to JACK client, for receiving reconnect events.
|
|
jack: Jack<'static>,
|
|
/// Port name
|
|
name: Arc<str>,
|
|
/// Port handle.
|
|
port: Port<MidiIn>,
|
|
/// List of currently held notes.
|
|
held: Arc<RwLock<[bool;128]>>,
|
|
/// List of ports to connect to.
|
|
pub connections: Vec<Connect>,
|
|
}
|
|
has!(Jack<'static>: |self: MidiInput|self.jack);
|
|
impl JackPort for MidiInput {
|
|
type Port = MidiIn;
|
|
type Pair = MidiOut;
|
|
fn name (&self) -> &Arc<str> {
|
|
&self.name
|
|
}
|
|
fn port (&self) -> &Port<Self::Port> {
|
|
&self.port
|
|
}
|
|
fn port_mut (&mut self) -> &mut Port<Self::Port> {
|
|
&mut self.port
|
|
}
|
|
fn into_port (self) -> Port<Self::Port> {
|
|
self.port
|
|
}
|
|
fn connections (&self) -> &[Connect] {
|
|
self.connections.as_slice()
|
|
}
|
|
fn new (jack: &Jack<'static>, name: &impl AsRef<str>, connect: &[Connect])
|
|
-> Usually<Self> where Self: Sized
|
|
{
|
|
let port = Self {
|
|
port: Self::register(jack, name)?,
|
|
jack: jack.clone(),
|
|
name: name.as_ref().into(),
|
|
connections: connect.to_vec(),
|
|
held: Arc::new(RwLock::new([false;128]))
|
|
};
|
|
port.connect_to_matching()?;
|
|
Ok(port)
|
|
}
|
|
}
|
|
impl MidiInput {
|
|
pub fn parsed <'a> (&'a self, scope: &'a ProcessScope) -> impl Iterator<Item=(usize, LiveEvent<'a>, &'a [u8])> {
|
|
parse_midi_input(self.port().iter(scope))
|
|
}
|
|
}
|
|
|
|
#[tengri_proc::command(MidiInput)]
|
|
impl MidiInputCommand {
|
|
//fn _todo_ (_port: &mut MidiInput) -> Perhaps<Self> { Ok(None) }
|
|
}
|
|
|
|
impl<T: Has<Vec<MidiInput>>> HasMidiIns for T {
|
|
fn midi_ins (&self) -> &Vec<MidiInput> {
|
|
self.get()
|
|
}
|
|
fn midi_ins_mut (&mut self) -> &mut Vec<MidiInput> {
|
|
self.get_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, &Arc<str>, &[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.name(), input.connections(), y, y + height);
|
|
y += height;
|
|
data
|
|
})
|
|
}
|
|
}
|
|
|
|
pub type CollectedMidiInput<'a> = Vec<Vec<(u32, Result<LiveEvent<'a>, MidiError>)>>;
|
|
|
|
impl<T: HasMidiIns + HasJack<'static>> AddMidiIn for T {
|
|
fn midi_in_add (&mut self) -> Usually<()> {
|
|
let index = self.midi_ins().len();
|
|
let port = MidiInput::new(self.jack(), &format!("M/{index}"), &[])?;
|
|
self.midi_ins_mut().push(port);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// May create new MIDI input ports.
|
|
pub trait AddMidiIn {
|
|
fn midi_in_add (&mut self) -> Usually<()>;
|
|
}
|