wip: down to 13 errors

This commit is contained in:
🪞👃🪞 2025-05-14 14:35:19 +03:00
parent 6ce83fb27a
commit ebdb8881e9
19 changed files with 793 additions and 691 deletions

View file

@ -189,7 +189,7 @@ macro_rules! impl_port {
type Pair = $Pair;
fn port (&self) -> &Port<$Spec> { &self.port }
}
impl JackPortConnect<&str> for $Name {
impl JackPortConnect<&str> for $Name {
fn connect_to (&self, to: &str) -> Usually<PortConnectStatus> {
self.with_client(|c|if let Some(ref port) = c.port_by_name(to.as_ref()) {
self.connect_to(port)
@ -233,5 +233,3 @@ impl_port!(JackAudioIn: AudioIn -> AudioOut |j, n|j.register_port::<AudioIn>(n
impl_port!(JackAudioOut: AudioOut -> AudioIn |j, n|j.register_port::<AudioOut>(n));
impl_port!(JackMidiIn: MidiIn -> MidiOut |j, n|j.register_port::<MidiIn>(n));
impl_port!(JackMidiOut: MidiOut -> MidiIn |j, n|j.register_port::<MidiOut>(n));

View file

@ -18,6 +18,16 @@ pub trait Has<T>: Send + Sync {
fn get_mut (&mut self) -> &mut T;
}
pub trait MaybeHas<T>: Send + Sync {
fn get (&self) -> Option<&T>;
}
impl<T, U: Has<Option<T>>> MaybeHas<T> for U {
fn get (&self) -> Option<&T> {
Has::<Option<T>>::get(self).as_ref()
}
}
#[macro_export] macro_rules! has {
($T:ty: |$self:ident : $S:ty| $x:expr) => {
impl Has<$T> for $S {

View file

@ -9,17 +9,9 @@ pub use ::midly::{
live::*,
};
mod midi_in; pub use self::midi_in::*;
mod midi_out; pub use self::midi_out::*;
/// Update notes_in array
pub fn update_keys (keys: &mut[bool;128], message: &MidiMessage) {
match message {
MidiMessage::NoteOn { key, .. } => { keys[key.as_int() as usize] = true; }
MidiMessage::NoteOff { key, .. } => { keys[key.as_int() as usize] = false; },
_ => {}
}
}
mod midi_in; pub use self::midi_in::*;
mod midi_out; pub use self::midi_out::*;
mod midi_hold; pub use self::midi_hold::*;
/// Return boxed iterator of MIDI events
pub fn parse_midi_input <'a> (input: ::jack::MidiIter<'a>) -> Box<dyn Iterator<Item=(usize, LiveEvent<'a>, &'a [u8])> + 'a> {

View file

@ -0,0 +1,10 @@
use crate::*;
/// Update notes_in array
pub fn update_keys (keys: &mut[bool;128], message: &MidiMessage) {
match message {
MidiMessage::NoteOn { key, .. } => { keys[key.as_int() as usize] = true; }
MidiMessage::NoteOff { key, .. } => { keys[key.as_int() as usize] = false; },
_ => {}
}
}

View file

@ -1,5 +1,11 @@
use crate::*;
impl JackMidiIn {
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(JackMidiIn)]
impl MidiInputCommand {
}

View file

@ -1,5 +1,151 @@
use crate::*;
#[derive(Debug)] pub struct JackMidiOut {
/// Handle to JACK client, for receiving reconnect events.
jack: Jack,
/// Port name
name: Arc<str>,
/// Port handle.
port: Port<MidiOut>,
/// List of ports to connect to.
conn: Vec<PortConnect>,
/// List of currently held notes.
held: Arc<RwLock<[bool;128]>>,
/// Buffer
note_buffer: Vec<u8>,
/// Buffer
output_buffer: Vec<Vec<Vec<u8>>>,
}
has!(Jack: |self: JackMidiOut|self.jack);
impl JackMidiOut {
pub fn new (jack: &Jack, name: impl AsRef<str>, connect: &[PortConnect])
-> Usually<Self>
{
let jack = jack.clone();
let port = jack.register_port::<MidiOut>(name.as_ref())?;
let name = name.as_ref().into();
let conn = connect.to_vec();
let port = Self {
jack,
port,
name,
conn,
held: Arc::new([false;128].into()),
note_buffer: vec![0;8],
output_buffer: vec![vec![];65536],
};
port.connect_to_matching()?;
Ok(port)
}
pub fn name (&self) -> &Arc<str> {
&self.name
}
pub fn port (&self) -> &Port<MidiOut> {
&self.port
}
pub fn port_mut (&mut self) -> &mut Port<MidiOut> {
&mut self.port
}
pub fn into_port (self) -> Port<MidiOut> {
self.port
}
pub fn close (self) -> Usually<()> {
let Self { jack, port, .. } = self;
Ok(jack.with_client(|client|client.unregister_port(port))?)
}
/// Clear the section of the output buffer that we will be using,
/// emitting "all notes off" at start of buffer if requested.
pub fn buffer_clear (&mut self, scope: &ProcessScope, reset: bool) {
let n_frames = (scope.n_frames() as usize).min(self.output_buffer.len());
for frame in &mut self.output_buffer[0..n_frames] {
frame.clear();
}
if reset {
all_notes_off(&mut self.output_buffer);
}
}
/// Write a note to the output buffer
pub fn buffer_write <'a> (
&'a mut self,
sample: usize,
event: LiveEvent,
) {
self.note_buffer.fill(0);
event.write(&mut self.note_buffer).expect("failed to serialize MIDI event");
self.output_buffer[sample].push(self.note_buffer.clone());
// Update the list of currently held notes.
if let LiveEvent::Midi { ref message, .. } = event {
update_keys(&mut*self.held.write().unwrap(), message);
}
}
/// Write a chunk of MIDI data from the output buffer to the output port.
pub fn buffer_emit (&mut self, scope: &ProcessScope) {
let samples = scope.n_frames() as usize;
let mut writer = self.port.writer(scope);
for (time, events) in self.output_buffer.iter().enumerate().take(samples) {
for bytes in events.iter() {
writer.write(&RawMidi { time: time as u32, bytes }).unwrap_or_else(|_|{
panic!("Failed to write MIDI data: {bytes:?}");
});
}
}
}
}
impl AsRef<Port<MidiOut>> for JackMidiOut {
fn as_ref (&self) -> &Port<MidiOut> {
&self.port
}
}
impl JackPort for JackMidiOut {
type Port = MidiOut;
type Pair = MidiIn;
fn port (&self) -> &Port<MidiOut> { &self.port }
}
impl JackPortConnect<&str> for JackMidiOut {
fn connect_to (&self, to: &str) -> Usually<PortConnectStatus> {
self.with_client(|c|if let Some(ref port) = c.port_by_name(to.as_ref()) {
self.connect_to(port)
} else {
Ok(Missing)
})
}
}
impl JackPortConnect<&Port<Unowned>> for JackMidiOut {
fn connect_to (&self, port: &Port<Unowned>) -> Usually<PortConnectStatus> {
self.with_client(|c|Ok(if let Ok(_) = c.connect_ports(&self.port, port) {
Connected
} else if let Ok(_) = c.connect_ports(port, &self.port) {
Connected
} else {
Mismatch
}))
}
}
impl JackPortConnect<&Port<MidiIn>> for JackMidiOut {
fn connect_to (&self, port: &Port<MidiIn>) -> Usually<PortConnectStatus> {
self.with_client(|c|Ok(if let Ok(_) = c.connect_ports(&self.port, port) {
Connected
} else if let Ok(_) = c.connect_ports(port, &self.port) {
Connected
} else {
Mismatch
}))
}
}
impl JackPortAutoconnect for JackMidiOut {
fn conn (&self) -> &[PortConnect] {
&self.conn
}
}
#[tengri_proc::command(JackMidiOut)]
impl MidiOutputCommand {
}
@ -29,6 +175,11 @@ pub trait HasMidiOuts {
data
})
}
fn midi_outs_emit (&mut self, scope: &ProcessScope) {
for port in self.midi_outs_mut().iter_mut() {
port.buffer_emit(scope)
}
}
}
/// Trail for thing that may gain new MIDI ports.