systematizing jack handlers

This commit is contained in:
🪞👃🪞 2024-06-14 16:54:28 +03:00
parent d627d257ad
commit 4ae62c5bc2
10 changed files with 342 additions and 208 deletions

View file

@ -7,7 +7,7 @@ pub const ACTIONS: [(&'static str, &'static str);2] = [
pub struct Sampler {
name: String,
jack: Jack<self::Notifications>,
jack: Jack<SamplerJack>,
samples: Arc<Mutex<Vec<Sample>>>,
selected_sample: usize,
selected_column: usize,
@ -23,57 +23,65 @@ impl Sampler {
];
let samples = Arc::new(Mutex::new(samples));
let input = client.register_port("trigger", ::jack::MidiIn::default())?;
let handler: BoxedProcessHandler = Box::new({
let exited = exited.clone();
let jack = SamplerJack.activate(client, ClosureProcessHandler::new({
let exited = exited.clone();
let samples = samples.clone();
Box::new(move |_: &Client, scope: &ProcessScope| -> Control {
if exited.fetch_and(true, Ordering::Relaxed) {
return Control::Quit
}
let mut samples = samples.lock().unwrap();
for event in input.iter(scope) {
let len = 3.min(event.bytes.len());
let mut data = [0; 3];
data[..len].copy_from_slice(&event.bytes[..len]);
if (data[0] >> 4) == 0b1001 { // note on
let channel = data[0] & 0b00001111;
let note = data[1];
let velocity = data[2];
for sample in samples.iter_mut() {
if /*sample.trigger.0 == channel &&*/ sample.trigger.1 == note {
sample.play(velocity);
}
}
}
for sample in samples.iter_mut() {
if let Some(playing) = sample.playing {
for (index, value) in sample.port.as_mut_slice(scope).iter_mut().enumerate() {
*value = *sample.data[0].get(playing + index).unwrap_or(&0f32);
}
if playing + scope.n_frames() as usize > sample.data[0].len() {
sample.playing = None
} else {
sample.playing = Some(playing + scope.n_frames() as usize)
}
}
}
}
Box::new(move |client: &Client, scope: &ProcessScope|{
process(client, scope, &exited, &samples, &input);
Control::Continue
})
});
}) as BoxedProcessHandler
}))?;
Ok(DynamicDevice::new(render, handle, |_|{}, Self {
name: name.into(),
selected_sample: 0,
selected_column: 0,
samples,
jack: client.activate_async(
self::Notifications,
ClosureProcessHandler::new(handler)
)?,
jack,
}))
}
}
pub fn process (
client: &Client,
scope: &ProcessScope,
exited: &Arc<AtomicBool>,
samples: &Arc<Mutex<Vec<Sample>>>,
input: &Port<MidiIn>
) -> Control {
if exited.fetch_and(true, Ordering::Relaxed) {
return Control::Quit
}
let mut samples = samples.lock().unwrap();
for event in input.iter(scope) {
let len = 3.min(event.bytes.len());
let mut data = [0; 3];
data[..len].copy_from_slice(&event.bytes[..len]);
if (data[0] >> 4) == 0b1001 { // note on
let channel = data[0] & 0b00001111;
let note = data[1];
let velocity = data[2];
for sample in samples.iter_mut() {
if /*sample.trigger.0 == channel &&*/ sample.trigger.1 == note {
sample.play(velocity);
}
}
}
for sample in samples.iter_mut() {
if let Some(playing) = sample.playing {
for (index, value) in sample.port.as_mut_slice(scope).iter_mut().enumerate() {
*value = *sample.data[0].get(playing + index).unwrap_or(&0f32);
}
if playing + scope.n_frames() as usize > sample.data[0].len() {
sample.playing = None
} else {
sample.playing = Some(playing + scope.n_frames() as usize)
}
}
}
}
Control::Continue
}
pub struct Sample {
port: Port<AudioOut>,
name: String,
@ -217,9 +225,17 @@ pub fn handle (state: &mut Sampler, event: &EngineEvent) -> Result<(), Box<dyn E
Ok(())
}
pub struct Notifications;
pub struct SamplerJack;
impl NotificationHandler for Notifications {
impl SamplerJack {
fn activate <P> (self, client: Client, handler: P) -> Usually<AsyncClient<Self, P>>
where P: 'static + Send + ::jack::ProcessHandler
{
Ok(client.activate_async(self, handler)?)
}
}
impl NotificationHandler for SamplerJack {
fn thread_init (&self, _: &Client) {
}