use crate::*; pub struct TrackMatrix { chunk_factory: F, columns: [Column; COLS], scratch_pad: Box<[f32]>, } impl TrackMatrix { pub fn new(client: &jack::Client, chunk_factory: F, state: &State) -> Result { let columns = std::array::from_fn(|_| Column::new(state.metronome.frames_per_beat)); Ok(Self { chunk_factory, columns, scratch_pad: vec![0.0; client.buffer_size() as usize].into_boxed_slice(), }) } pub fn handle_record_button( &mut self, last_volume_setting: f32, controllers: &TrackControllers, ) -> Result<()> { self.columns[controllers.column()].handle_record_button(last_volume_setting, controllers) } pub fn handle_play_button(&mut self, controllers: &TrackControllers) -> Result<()> { self.columns[controllers.column()].handle_play_button(controllers) } pub fn handle_clear_button(&mut self, controllers: &TrackControllers) -> Result<()> { self.columns[controllers.column()].handle_clear_button(controllers) } pub fn handle_volume_update( &mut self, new_volume: f32, controllers: &TrackControllers, ) -> Result<()> { self.columns[controllers.column()].handle_volume_update(new_volume, controllers) } pub fn is_all_tracks_cleared(&self) -> bool { self.columns .iter() .all(|column| column.is_all_tracks_cleared()) } pub fn set_frames_per_beat(&mut self, new_frames_per_beat: usize) { for column in &mut self.columns { column.set_frames_per_beat(new_frames_per_beat); } } pub fn process( &mut self, ps: &jack::ProcessScope, ports: &mut JackPorts, timing: &BufferTiming, controllers: &MatrixControllers, ) -> Result<()> { // Check for consolidation response if let Some(response) = controllers.try_recv_post_record_response() { self.columns[response.column] .set_consolidated_buffer(response.row, response.consolidated_buffer)?; } // Handle xruns if timing.missed_frames > 0 { for (i, column) in &mut self.columns.iter_mut().enumerate() { let controllers = controllers.to_column_controllers(i); column.handle_xrun(&timing, &mut self.chunk_factory, &controllers)?; } } // Process audio let input_buffer = ports.audio_in.as_slice(ps); let output_buffer = ports.audio_out.as_mut_slice(ps); output_buffer.fill(0.0); for (i, column) in &mut self.columns.iter_mut().enumerate() { let controllers = controllers.to_column_controllers(i); column.process( &timing, input_buffer, output_buffer, &mut self.scratch_pad, &mut self.chunk_factory, &controllers, )?; } Ok(()) } }