tek/crates/app/src/audio.rs
2025-05-10 20:45:18 +03:00

92 lines
3.1 KiB
Rust

use crate::*;
audio!(
|self: App, client, scope|{
let t0 = self.perf.get_t0();
self.clock().update_from_scope(scope).unwrap();
let midi_in = self.collect_midi_input(scope);
self.update_editor_cursor(&midi_in);
let result = self.render_tracks(client, scope);
self.perf.update_from_jack_scope(t0, scope);
result
};
|self, event|{
use JackEvent::*;
match event {
SampleRate(sr) => { self.clock.timebase.sr.set(sr as f64); },
PortRegistration(id, true) => {
//let port = self.jack().port_by_id(id);
//println!("\rport add: {id} {port:?}");
//println!("\rport add: {id}");
},
PortRegistration(id, false) => {
/*println!("\rport del: {id}")*/
},
PortsConnected(a, b, true) => { /*println!("\rport conn: {a} {b}")*/ },
PortsConnected(a, b, false) => { /*println!("\rport disc: {a} {b}")*/ },
ClientRegistration(id, true) => {},
ClientRegistration(id, false) => {},
ThreadInit => {},
XRun => {},
GraphReorder => {},
_ => { panic!("{event:?}"); }
}
}
);
type CollectedMidiInput<'a> = Vec<Vec<(u32, Result<LiveEvent<'a>, MidiError>)>>;
impl App {
/// Collect MIDI input from app ports (TODO preallocate large buffers)
fn collect_midi_input <'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<_>>()
}
/// Update cursor in MIDI editor
fn update_editor_cursor (&self, midi_in: &CollectedMidiInput) {
if let Some(editor) = &self.editor {
let mut pitch: Option<u7> = None;
for port in midi_in.iter() {
for event in port.iter() {
if let (_, Ok(LiveEvent::Midi {message: MidiMessage::NoteOn {ref key, ..}, ..}))
= event
{
pitch = Some(key.clone());
}
}
}
if let Some(pitch) = pitch {
editor.set_note_pos(pitch.as_int() as usize);
}
}
}
/// Run audio callbacks for every track and every device
fn render_tracks (&mut self, client: &Client, scope: &ProcessScope) -> Control {
for track in self.tracks.iter_mut() {
if Control::Quit == PlayerAudio(
track.sequencer_mut(), &mut self.note_buf, &mut self.midi_buf
).process(client, scope) {
return Control::Quit
}
for device in track.devices.iter_mut() {
if Control::Quit == DeviceAudio(device).process(client, scope) {
return Control::Quit
}
}
}
Control::Continue
}
}
impl HasJack for App {
fn jack (&self) -> &Jack {
&self.jack
}
}