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, 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::>()) .collect::>() } /// Update cursor in MIDI editor fn update_editor_cursor (&self, midi_in: &CollectedMidiInput) { if let Some(editor) = &self.editor { let mut pitch: Option = 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 } }