Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Closure Callbacks

Closure callbacks allow you to define functionality inline.

Process Closure

Audio and midi processing can be defined through closures. This involves:

  1. Creating a closure that captures the appropriate state (including JACK ports) and
  2. Activating it within a client.
#![allow(unused)]
fn main() {
// 1. Create the client.
let (client, _status) =
    jack::Client::new("silence", jack::ClientOptions::default()).unwrap();

// 2. Define the state.
let mut output = client.register_port("out", jack::AudioOut::default());
let silence_value = 0.0;

// 3. Define the closure. Use `move` to capture the required state.
let process_callback = move |_: &jack::Client, ps: &jack::ProcessScope| -> jack::Control {
    output.as_mut_slice(ps).fill(silence_value);
    jack::Control::Continue
};

// 4. Start processing.
let process = jack::contrib::ClosureProcessHandler::new(process_callback);
let active_client = client.activate_async((), process).unwrap();
}

State + Process Closure + Buffer Closure

jack::contrib::ClosureProcessHandler also allows defining a buffer size callback that can share state with the process callback. The buffer size callback is useful as it allows the handler to adapt to any changes in the buffer size.

#![allow(unused)]
fn main() {
// 1. Create the client.
let (client, _status) =
    jack::Client::new("silence", jack::ClientOptions::default()).unwrap();

// 2. Define the state.
struct State {
    silence: Vec<f32>,
    output: jack::Port<jack::AudioOut>,
}
let state = State {
    silence: Vec::new(),
    output: client
        .register_port("out", jack::AudioOut::default())
        .unwrap(),
};

// 3. Define the state and closure.
let process_callback = |state: &mut State, _: &jack::Client, ps: &jack::ProcessScope| {
    state
        .output
        .as_mut_slice(ps)
        .copy_from_slice(state.silence.as_slice());
    jack::Control::Continue
};
let buffer_callback = |state: &mut State, _: &jack::Client, len: jack::Frames| {
    state.silence = vec![0f32; len as usize];
    jack::Control::Continue
};

// 4. Start processing.
let process =
    jack::contrib::ClosureProcessHandler::with_state(state, process_callback, buffer_callback);
let active_client = client.activate_async((), process).unwrap();
}