use super::*; use std::cmp::Ordering; /// Internal representation of an event, as handled by the audio context. pub struct EventData { pub(crate) event: Event, pub(crate) fire_time: Option, pub(crate) action: Box, } impl EventData { /// Create a representation of an event and its associated handler. /// /// An event handler, `action`, receives an [`EventContext`] and optionally /// produces a new [`Event`] type for itself. Returning `None` will /// maintain the same event type, while removing any [`Delayed`] entries. /// Event handlers will be re-added with their new trigger condition, /// or removed if [`Cancel`]led /// /// [`EventContext`]: EventContext /// [`Event`]: Event /// [`Delayed`]: Event::Delayed /// [`Cancel`]: Event::Cancel pub fn new(event: Event, action: F) -> Self { Self { event, fire_time: None, action: Box::new(action), } } /// Computes the next firing time for a timer event. pub fn compute_activation(&mut self, now: Duration) { match self.event { Event::Periodic(period, phase) => { self.fire_time = Some(now + phase.unwrap_or(period)); }, Event::Delayed(offset) => { self.fire_time = Some(now + offset); }, _ => {}, } } } impl std::fmt::Debug for EventData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { write!( f, "Event {{ event: {:?}, fire_time: {:?}, action: }}", self.event, self.fire_time ) } } /// Events are ordered/compared based on their firing time. impl Ord for EventData { fn cmp(&self, other: &Self) -> Ordering { if self.fire_time.is_some() && other.fire_time.is_some() { let t1 = self .fire_time .as_ref() .expect("T1 known to be well-defined by above."); let t2 = other .fire_time .as_ref() .expect("T2 known to be well-defined by above."); t2.cmp(t1) } else { Ordering::Equal } } } impl PartialOrd for EventData { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl PartialEq for EventData { fn eq(&self, other: &Self) -> bool { self.fire_time == other.fire_time } } impl Eq for EventData {}