use midir::MidiOutputConnection;
use std::time::{Duration, Instant};
use crate::{all_sound_off, file::MidiFile, LyricaError};
pub struct MidiPlayer {
maybe_midi_file: Option<MidiFile>,
connection: MidiOutputConnection,
last_update_time: Instant,
}
impl MidiPlayer {
pub fn new(connection: MidiOutputConnection) -> Self {
Self {
maybe_midi_file: None,
connection,
last_update_time: Instant::now(),
}
}
pub fn set_midi_file(&mut self, midi_file: MidiFile) -> Result<(), LyricaError> {
all_sound_off(&mut self.connection)?;
self.maybe_midi_file = Some(midi_file);
Ok(())
}
pub fn set_paused(&mut self, paused: bool) -> Result<(), LyricaError> {
if let Some(midi_file) = &mut self.maybe_midi_file {
midi_file.set_paused(paused, &mut self.connection)?;
}
self.last_update_time = Instant::now();
Ok(())
}
pub fn is_finished(&self) -> bool {
match &self.maybe_midi_file {
Some(midi_file) => midi_file.is_finished(),
None => true,
}
}
pub fn set_loop_point(&mut self, loop_point: Option<f64>) {
if let Some(midi_file) = &mut self.maybe_midi_file {
midi_file.set_loop_point(loop_point);
}
}
pub fn seek_to(&mut self, seconds: f64) -> Result<(), LyricaError> {
if let Some(midi_file) = &mut self.maybe_midi_file {
midi_file.seek_to(seconds, &mut self.connection)?;
}
Ok(())
}
pub fn update(&mut self) -> Result<(), LyricaError> {
let now = Instant::now();
let delta_time = now.duration_since(self.last_update_time);
if delta_time < Duration::from_micros(50) {
return Ok(());
}
if let Some(midi_file) = &mut self.maybe_midi_file {
midi_file.update(delta_time, &mut self.connection)?;
}
self.last_update_time = now;
Ok(())
}
}