use std::fmt::Debug;
use crate::prelude::*;
#[doc = r#"
Identifies some event emitted by a track in a MIDI file.
# Overview
All MIDI track events have an associated `delta_time`. This
identifies the amount of time since the previous event.
"#]
#[derive(Clone, PartialEq)]
pub struct TrackEvent<'a> {
delta_ticks: u32,
event: TrackMessage<'a>,
}
impl Debug for TrackEvent<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Track Event {{ delta_time: 0x{:02X}, event: {:?} }}",
self.delta_ticks, self.event
)
}
}
impl<'a> TrackEvent<'a> {
pub fn new(delta_time: u32, event: TrackMessage<'a>) -> Self {
Self {
delta_ticks: delta_time,
event,
}
}
pub(crate) fn read<'slc, 'r, R>(
reader: &'r mut Reader<R>,
running_status: &mut Option<u8>,
) -> ReadResult<Self>
where
R: MidiSource<'slc>,
'slc: 'a,
{
let delta_ticks = crate::reader::decode_varlen(reader)?;
let next_event = reader.read_next()?;
let message = match next_event {
0xF0 => {
let mut data = reader.read_varlen_slice()?;
if !data.is_empty() {
data.truncate(1);
}
TrackMessage::SystemExclusive(SystemExclusiveMessage::new(data))
}
0xFF => TrackMessage::Meta(MetaMessage::read(reader)?),
byte => {
let status = if byte >> 7 == 1 {
*running_status = Some(byte);
byte
} else if let Some(prev_status) = running_status {
reader.state.decrement_offset(1);
*prev_status
} else {
return Err(inv_data(reader, "Invalid MIDI event triggered"));
};
let status = StatusByte::try_from(status).unwrap();
TrackMessage::ChannelVoice(ChannelVoiceMessage::read(status, reader)?)
}
};
Ok(Self {
delta_ticks,
event: message,
})
}
pub fn delta_ticks(&self) -> u32 {
self.delta_ticks
}
pub fn event(&self) -> &TrackMessage<'a> {
&self.event
}
pub fn into_event(self) -> TrackMessage<'a> {
self.event
}
}