mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
switchable monitoring
This commit is contained in:
parent
e30dd94d23
commit
edadfde1a4
5 changed files with 94 additions and 107 deletions
|
|
@ -1,10 +1,9 @@
|
|||
use crate::core::*;
|
||||
use crate::layout::*;
|
||||
|
||||
mod keys; use self::keys::*;
|
||||
mod handle; pub use self::handle::*;
|
||||
mod process; pub use self::process::*;
|
||||
mod phrase; pub use self::phrase::*;
|
||||
mod keys; use self::keys::*;
|
||||
mod handle; pub use self::handle::*;
|
||||
mod phrase; pub use self::phrase::*;
|
||||
|
||||
pub mod horizontal;
|
||||
pub mod vertical;
|
||||
|
|
@ -58,21 +57,18 @@ impl Sequencer {
|
|||
) -> Usually<DynamicDevice<Self>> {
|
||||
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||
let transport = client.transport();
|
||||
DynamicDevice::new(render, handle, process, Self {
|
||||
name: name.into(),
|
||||
midi_in: client.register_port("in", MidiIn::default())?,
|
||||
midi_out: client.register_port("out", MidiOut::default())?,
|
||||
|
||||
timebase: timebase.clone(),
|
||||
sequence: Some(0),
|
||||
phrases: phrases.unwrap_or_else(||vec![
|
||||
Phrase::new("Phrase0", 4 * timebase.ppq() as usize, None)
|
||||
]),
|
||||
DynamicDevice::new(render, handle, Self::process, Self {
|
||||
name: name.into(),
|
||||
timebase: timebase.clone(),
|
||||
phrases: phrases.unwrap_or_else(||vec![Phrase::default()]),
|
||||
sequence: Some(0),
|
||||
|
||||
transport,
|
||||
playing: TransportState::Starting,
|
||||
midi_in: client.register_port("in", MidiIn::default())?,
|
||||
monitoring: true,
|
||||
recording: true,
|
||||
midi_out: client.register_port("out", MidiOut::default())?,
|
||||
playing: TransportState::Starting,
|
||||
overdub: true,
|
||||
|
||||
view: SequencerView::Horizontal,
|
||||
|
|
@ -88,6 +84,61 @@ impl Sequencer {
|
|||
pub fn phrase <'a> (&'a self) -> Option<&'a Phrase> {
|
||||
self.phrases.get(self.sequence?)
|
||||
}
|
||||
|
||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
// Get currently playing phrase
|
||||
if self.sequence.is_none() {
|
||||
return Control::Continue
|
||||
}
|
||||
let phrase = self.phrases.get_mut(self.sequence.unwrap());
|
||||
if phrase.is_none() {
|
||||
return Control::Continue
|
||||
}
|
||||
let phrase = phrase.unwrap();
|
||||
// Prepare output buffer and transport
|
||||
let frame = scope.last_frame_time() as usize;//transport.pos.frame() as usize;
|
||||
let frames = scope.n_frames() as usize;
|
||||
let mut output: Vec<Option<Vec<Vec<u8>>>> = vec![None;frames];
|
||||
// Check transport self. If starting or stopping, send "all notes off":
|
||||
let transport = self.transport.query().unwrap();
|
||||
if transport.state != self.playing {
|
||||
all_notes_off(&mut output);
|
||||
}
|
||||
self.playing = transport.state;
|
||||
// Play from phrase into output buffer
|
||||
if self.playing == TransportState::Rolling {
|
||||
phrase.process_out(
|
||||
&mut output,
|
||||
&mut self.notes_on,
|
||||
&self.timebase,
|
||||
frame,
|
||||
frames
|
||||
);
|
||||
}
|
||||
// Play from input to monitor, and record into phrase.
|
||||
phrase.process_in(
|
||||
self.midi_in.iter(scope),
|
||||
&mut self.notes_on,
|
||||
if self.monitoring { Some(&mut output) } else { None },
|
||||
self.recording && self.playing == TransportState::Rolling,
|
||||
&self.timebase,
|
||||
frame,
|
||||
);
|
||||
// Write to port from output buffer
|
||||
// (containing notes from sequence and/or monitor)
|
||||
let mut writer = self.midi_out.writer(scope);
|
||||
for time in 0..scope.n_frames() {
|
||||
if let Some(Some(frame)) = output.get_mut(time as usize) {
|
||||
for event in frame.iter() {
|
||||
writer.write(&::jack::RawMidi { time, bytes: &event })
|
||||
.expect(&format!("{event:?}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
impl PortList for Sequencer {
|
||||
fn midi_ins (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_in.name()?]) }
|
||||
|
|
@ -168,3 +219,14 @@ pub fn contains_note_on (sequence: &Phrase, k: u7, start: usize, end: usize) ->
|
|||
}
|
||||
return false
|
||||
}
|
||||
/// Add "all notes off" to the start of a buffer.
|
||||
pub fn all_notes_off (output: &mut MIDIChunk) {
|
||||
output[0] = Some(vec![]);
|
||||
if let Some(Some(frame)) = output.get_mut(0) {
|
||||
let mut buf = vec![];
|
||||
let msg = MidiMessage::Controller { controller: 123.into(), value: 0.into() };
|
||||
let evt = LiveEvent::Midi { channel: 0.into(), message: msg };
|
||||
evt.write(&mut buf).unwrap();
|
||||
frame.push(buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue