use crate::{
channel::Channel,
events::LiveEvent,
prelude::{BytesText, Tempo, TimeSignature, TrackEvent, TrackMessage},
};
#[doc = r#"
A set of track events
"#]
#[derive(Debug, Clone, PartialEq)]
pub struct Track<'a> {
info: TrackInfo<'a>,
events: Vec<TimedEvent<LiveEvent<'a>>>,
}
impl<'a> Track<'a> {
pub fn new(events: Vec<TrackEvent<'a>>) -> Self {
let mut info = TrackInfo::default();
let mut track_events = Vec::with_capacity(events.len());
let mut time_accumulated = None;
for event in events {
let delta_ticks = event.delta_ticks();
let accumulated_ticks = if let Some(tick_acc) = &mut time_accumulated {
*tick_acc += delta_ticks;
*tick_acc
} else {
time_accumulated = Some(delta_ticks);
delta_ticks
};
let event: LiveEvent = match event.into_event() {
TrackMessage::ChannelVoice(cvm) => cvm.into(),
TrackMessage::SystemExclusive(sysex) => sysex.into(),
TrackMessage::Meta(meta) => {
meta.adjust_track_info(&mut info);
continue;
}
};
track_events.push(TimedEvent::new(accumulated_ticks, event));
}
Self {
info,
events: track_events,
}
}
pub fn info(&self) -> &TrackInfo<'a> {
&self.info
}
pub fn events(&self) -> &[TimedEvent<LiveEvent<'a>>] {
self.events.as_slice()
}
}
#[allow(missing_docs)]
#[derive(Default, Debug, Clone, PartialEq)]
pub struct TrackInfo<'a> {
pub time_signature: TimeSignature<'a>,
pub name: Option<BytesText<'a>>,
pub device: Option<BytesText<'a>>,
pub track_info: Option<u16>,
pub channel: Option<Channel>,
pub tempo: Tempo,
}
#[doc = r#"
A wrapper around some type with an associated time
"#]
#[derive(Debug, Clone, PartialEq)]
pub struct TimedEvent<T> {
accumulated_ticks: u32,
event: T,
}
impl<T> TimedEvent<T> {
pub fn new(accumulated_ticks: u32, event: T) -> Self {
Self {
accumulated_ticks,
event,
}
}
pub fn accumulated_ticks(&self) -> u32 {
self.accumulated_ticks
}
pub fn event(&self) -> &T {
&self.event
}
}
#[test]
fn get_accumulated_ticks() {}