fcb_looper/audio_engine/src/process_handler.rs
2025-06-13 16:35:19 +02:00

147 lines
3.9 KiB
Rust

use crate::*;
const COLS: usize = 5;
const ROWS: usize = 5;
pub struct ProcessHandler<F: ChunkFactory> {
osc: OscController,
ports: JackPorts,
metronome: Metronome,
track_matrix: TrackMatrix<F, COLS, ROWS>,
selected_row: usize,
selected_column: usize,
}
impl<F: ChunkFactory> ProcessHandler<F> {
pub fn new(
client: &jack::Client,
ports: JackPorts,
chunk_factory: F,
beep_samples: Arc<AudioChunk>,
state: &State,
osc: OscController,
post_record_controller: PostRecordController,
) -> Result<Self> {
let track_matrix = TrackMatrix::new(
client,
chunk_factory,
state,
post_record_controller,
)?;
Ok(Self {
osc,
ports,
metronome: Metronome::new(beep_samples, state),
track_matrix,
selected_row: 0,
selected_column: 0,
})
}
pub fn ports(&self) -> &JackPorts {
&self.ports
}
pub fn handle_button_1(&mut self) -> Result<()> {
self.track_matrix.handle_record_button(self.selected_column, self.selected_row)
}
pub fn handle_button_2(&mut self) -> Result<()> {
self.track_matrix.handle_play_button(self.selected_column, self.selected_row)
}
pub fn handle_button_3(&mut self) -> Result<()> {
Ok(())
}
pub fn handle_button_4(&mut self) -> Result<()> {
Ok(())
}
pub fn handle_button_5(&mut self) -> Result<()> {
self.track_matrix.handle_clear_button(self.selected_column, self.selected_row)
}
pub fn handle_button_6(&mut self) -> Result<()> {
self.selected_column = 0;
self.osc.selected_column_changed(self.selected_column)?;
Ok(())
}
pub fn handle_button_7(&mut self) -> Result<()> {
self.selected_column = 1;
self.osc.selected_column_changed(self.selected_column)?;
Ok(())
}
pub fn handle_button_8(&mut self) -> Result<()> {
self.selected_column = 2;
self.osc.selected_column_changed(self.selected_column)?;
Ok(())
}
pub fn handle_button_9(&mut self) -> Result<()> {
self.selected_column = 3;
self.osc.selected_column_changed(self.selected_column)?;
Ok(())
}
pub fn handle_button_10(&mut self) -> Result<()> {
self.selected_column = 4;
self.osc.selected_column_changed(self.selected_column)?;
Ok(())
}
pub fn handle_button_up(&mut self) -> Result<()> {
if self.selected_row == 0 {
self.selected_row = ROWS - 1;
} else {
self.selected_row -= 1;
}
self.osc.selected_row_changed(self.selected_row)?;
Ok(())
}
pub fn handle_button_down(&mut self) -> Result<()> {
self.selected_row = (self.selected_row + 1) % ROWS;
self.osc.selected_row_changed(self.selected_row)?;
Ok(())
}
}
impl<F: ChunkFactory> jack::ProcessHandler for ProcessHandler<F> {
fn process(&mut self, client: &jack::Client, ps: &jack::ProcessScope) -> jack::Control {
if let Err(e) = self.process_with_error_handling(client, ps) {
log::error!("Error processing audio: {}", e);
jack::Control::Quit
} else {
jack::Control::Continue
}
}
}
impl<F: ChunkFactory> ProcessHandler<F> {
fn process_with_error_handling(
&mut self,
client: &jack::Client,
ps: &jack::ProcessScope,
) -> Result<()> {
// Process metronome and get beat timing information
let timing = self.metronome.process(ps, &mut self.ports)?;
// Process MIDI
midi::process_events(self, ps)?;
// Process audio
self.track_matrix.process(
client,
ps,
&mut self.ports,
&timing,
&mut self.osc,
)?;
Ok(())
}
}