use crate::Conductor;
use crate::Instruction;
use crate::MidiController;
use crate::MidiMessage;
use crate::MidiOut;
use crate::bpm::Bpm;
use alloc::collections::vec_deque::VecDeque;
use alloc::{vec, vec::Vec};
const DEFAULT_BPM: u8 = 120;
pub struct Context {
bpm: Bpm,
step: u32,
running: bool,
on_pause: bool,
pause: bool,
sys_instructions: Vec<Instruction>,
}
pub type InputQueue = VecDeque<
MidiMessage, >;
impl Default for Context {
fn default() -> Self {
Self {
bpm: Bpm::new(DEFAULT_BPM),
step: 0,
running: true,
on_pause: true,
pause: false,
sys_instructions: vec![],
}
}
}
impl Context {
pub fn set_bpm(&mut self, bpm: u8) {
self.bpm.set_bpm(bpm);
}
pub fn get_bpm(&self) -> u8 {
self.bpm.get_bpm()
}
pub fn get_period_us(&self) -> u64 {
self.bpm.get_period_us()
}
pub fn quit(&mut self) {
self.running = false
}
pub fn pause(&mut self) {
self.on_pause = true;
self.pause = true;
self.sys_instructions.push(Instruction::StopAllNotes);
self.sys_instructions.push(Instruction::Stop);
}
pub fn resume(&mut self) {
self.on_pause = false;
self.sys_instructions.push(Instruction::Continue);
}
pub fn start(&mut self) {
self.step = 0;
self.on_pause = false;
self.sys_instructions.push(Instruction::Start);
}
pub fn get_step(&self) -> u32 {
self.step
}
pub fn init(
&mut self,
conductor: &mut impl Conductor,
controller: &mut MidiController<impl MidiOut>,
) {
conductor
.init(self)
.into_iter()
.for_each(|instruction| controller.execute(instruction));
}
pub fn process_pre_tick(
&mut self,
conductor: &mut impl Conductor,
controller: &mut MidiController<impl MidiOut>,
) {
core::mem::take(&mut self.sys_instructions)
.into_iter()
.for_each(|instruction| controller.execute(instruction));
if self.on_pause {
conductor.update(self);
} else {
conductor
.update(self)
.into_iter()
.for_each(|instruction| controller.execute(instruction));
};
}
pub fn process_post_tick(&mut self, controller: &mut MidiController<impl MidiOut>) {
controller.send_clock();
if !self.on_pause {
self.step += 1;
controller.update(self.step);
} else if self.pause {
self.pause = false;
}
}
pub fn is_running(&self) -> bool {
self.running
}
pub fn is_paused(&self) -> bool {
self.on_pause
}
pub fn handle_input(
&mut self,
conductor: &mut impl Conductor,
controller: &mut MidiController<impl MidiOut>,
input_queue: &mut InputQueue,
) {
if self.is_paused() {
input_queue
.drain(..)
.flat_map(|message| conductor.handle_input(message, self))
.for_each(drop);
} else {
input_queue
.drain(..)
.flat_map(|message| conductor.handle_input(message, self))
.for_each(|instruction| controller.execute(instruction));
}
}
}