#![allow(dead_code)]
use super::{
music_time::MusicTime, music_time_counter::MusicTimeCounter, time_signature::TimeSignature,
};
use std::time::{Duration, SystemTime};
const STRING_PANIC_TIME_FLOW: &str = "Hello John Titor, you reversed time!";
pub trait MusicTimerState {
fn on_beat_interval(&mut self, current_time: &MusicTime);
fn on_beat(&mut self, current_time: &MusicTime);
fn on_bar(&mut self, current_time: &MusicTime);
}
pub struct MusicTimerEngine {
total_time: Duration,
previous_time: Duration,
start_time: SystemTime,
event_trigger_time: Duration,
music_counter: MusicTimeCounter,
event_trigger_target: Duration,
previous_music_time: MusicTime,
}
impl MusicTimerEngine {
pub fn new(time_signature: TimeSignature, bpm: f32) -> Self {
let music_counter = MusicTimeCounter::new(time_signature);
let event_trigger_target = music_counter.beat_interval_target_frames(bpm);
MusicTimerEngine {
total_time: Duration::default(),
previous_time: Duration::default(),
start_time: SystemTime::now(),
event_trigger_time: event_trigger_target,
music_counter,
event_trigger_target,
previous_music_time: MusicTime::new(0, 0, 0),
}
}
pub fn pulse<TimerState: MusicTimerState>(&mut self, state: &mut TimerState) {
self.previous_time = self.total_time;
self.total_time = SystemTime::now()
.duration_since(self.start_time)
.expect(STRING_PANIC_TIME_FLOW);
let time_delta = self.total_time - self.previous_time;
self.event_trigger_time += time_delta;
let is_beat_interval_advanced = self.event_trigger_time >= self.event_trigger_target;
if is_beat_interval_advanced {
let current_time = self.music_counter.current_time();
state.on_beat_interval(¤t_time);
let is_beat_changed =
self.previous_music_time.get_beat() != self.music_counter.current_time().get_beat();
if is_beat_changed {
state.on_beat(¤t_time);
}
let is_bar_changed =
self.previous_music_time.get_bar() != self.music_counter.current_time().get_bar();
if is_bar_changed {
state.on_bar(¤t_time);
}
self.previous_music_time = self.music_counter.current_time().clone();
self.music_counter.advance_beat_interval();
let initial_d = self.event_trigger_time - self.event_trigger_target;
self.event_trigger_time = initial_d;
}
}
pub fn get_beat_interval_duration(&self) -> Duration {
self.event_trigger_target
}
pub fn get_current_time(&self) -> &MusicTime {
self.music_counter.current_time()
}
pub fn set_music_timer(&mut self, time: MusicTime) -> &mut Self {
self.music_counter.set_current_time(time);
self
}
}