fcb_looper/src/audio_engine.rs
2025-06-05 19:37:35 +02:00

91 lines
2.7 KiB
Rust

mod allocator;
mod audio_chunk;
mod chunk_factory;
mod looper_error;
mod midi;
mod notification_handler;
mod process_handler;
mod track;
use std::sync::Arc;
use allocator::Allocator;
use audio_chunk::AudioChunk;
use chunk_factory::ChunkFactory;
use looper_error::LooperError;
use looper_error::Result;
use notification_handler::JackNotification;
use notification_handler::NotificationHandler;
use process_handler::ProcessHandler;
use track::Track;
use track::TrackState;
pub struct JackPorts {
pub audio_in: jack::Port<jack::AudioIn>,
pub audio_out: jack::Port<jack::AudioOut>,
pub midi_in: jack::Port<jack::MidiIn>,
}
#[tokio::main]
async fn main() {
simple_logger::SimpleLogger::new().init().expect("Could not initialize logger");
let (jack_client, ports) = setup_jack();
let (allocator, factory_handle) = Allocator::spawn(jack_client.sample_rate(), 3);
let process_handler = ProcessHandler::new(ports, allocator)
.expect("Could not create process handler");
let notification_handler = NotificationHandler::new();
let mut notification_channel = notification_handler.subscribe();
let _async_client = jack_client
.activate_async(notification_handler, process_handler)
.expect("Could not activate Jack");
tokio::select! {
notification = notification_channel.recv() => {
match notification {
Ok(JackNotification::Shutdown {reason, status}) => {
log::error!("Jack shutdown: {reason} {status:?}");
}
Err(e) => {
log::error!("NotificationHandler stopped: {e}");
}
}
}
_ = factory_handle => {
log::error!("Allocator was dropped");
}
_ = tokio::signal::ctrl_c() => {
log::info!("Stopping");
}
}
}
fn setup_jack() -> (jack::Client, JackPorts) {
let (jack_client, jack_status) =
jack::Client::new("looper", jack::ClientOptions::NO_START_SERVER)
.expect("Could not create Jack client");
if !jack_status.is_empty() {
panic!("Could not start jack client: {jack_status:?}");
}
let audio_in = jack_client
.register_port("audio_in", jack::AudioIn::default())
.expect("Could not create audio_in port");
let audio_out = jack_client
.register_port("audio_out", jack::AudioOut::default())
.expect("Could not create audio_out port");
let midi_in = jack_client
.register_port("midi_in", jack::MidiIn::default())
.expect("Could not create midi_in port");
let ports = JackPorts {
audio_in,
audio_out,
midi_in,
};
(jack_client, ports)
}