Skip to main content

clack_common/events/io/
input.rs

1use crate::events::UnknownEvent;
2use crate::events::io::EventBatcher;
3use crate::events::io::implementation::{InputEventBuffer, raw_input_events};
4use crate::utils::usize_to_clap_size;
5use clap_sys::events::clap_input_events;
6use std::fmt::{Debug, Formatter};
7use std::marker::PhantomData;
8use std::ops::{Index, Range};
9
10/// An input list of timestamped events.
11///
12/// `InputEvents`s are always ordered: an event at index `i` will always have a timestamp smaller than
13/// or equal to the timestamp of the next event at index `i + 1`.
14///
15/// `InputEvents`s do not own the event data, they are only lightweight wrappers around a compatible
16/// event buffer (i.e. [`InputEventBuffer`]), see [`InputEvents::from_buffer`] as the default implementation.
17///
18/// Unlike [`Vec`s](Vec) or slices, `InputEvents` only support retrieving an event from
19/// its index ([`get`](InputEvents::get)). It also implements a few extra features for convenience,
20/// such as [`Iterator`](IntoIterator).
21///
22/// # Example
23///```
24/// use clack_common::events::{Event, EventHeader, Pckn};
25/// use clack_common::events::event_types::NoteOnEvent;
26/// use clack_common::events::io::{EventBuffer, InputEvents};
27///
28/// let event = NoteOnEvent::new(0, Pckn::new(0u16, 0u16, 12u16, 60u32), 4.2);
29/// let buf = [event];
30/// let mut input_events = InputEvents::from_buffer(&buf);
31///
32/// assert_eq!(1, input_events.len());
33/// assert_eq!(&event, input_events[0].as_event().unwrap());
34/// ```
35#[repr(C)]
36pub struct InputEvents<'a> {
37    inner: clap_input_events,
38    _lifetime: PhantomData<(&'a clap_input_events, *const ())>,
39}
40
41impl<'a> InputEvents<'a> {
42    /// Creates a shared reference to an [`InputEvents`] list from a given C FFI-compatible pointer.
43    ///
44    /// # Safety
45    /// The caller must ensure the given pointer is valid for the lifetime `'a`.
46    #[inline]
47    pub const unsafe fn from_raw(raw: &'a clap_input_events) -> &'a Self {
48        &*(raw as *const _ as *const _)
49    }
50
51    /// Returns a C FFI-compatible pointer to this event list.
52    ///
53    /// This pointer is only valid until the list is dropped.
54    #[inline]
55    pub const fn as_raw(&self) -> &clap_input_events {
56        &self.inner
57    }
58
59    /// Returns an [`InputEvents`] from a reference [`InputEventBuffer`] implementation.
60    ///
61    /// The most common [`InputEventBuffer`] implementors are the
62    /// [`EventBuffer`](crate::events::io::EventBuffer), and arrays or slices of either any
63    /// [`Event`](crate::events::Event) type, or of [`UnknownEvent`] references.
64    ///
65    /// See the [`InputEventBuffer`] implementation docs for a list of all types that can be used
66    /// by default.
67    #[inline]
68    pub const fn from_buffer<I: InputEventBuffer>(buffer: &'a I) -> Self {
69        Self {
70            inner: raw_input_events(buffer),
71            _lifetime: PhantomData,
72        }
73    }
74
75    /// Returns an [`InputEvents`] that is always empty.
76    ///
77    /// # Example
78    ///
79    /// ```
80    /// use clack_common::events::io::InputEvents;
81    ///
82    /// let no_events = InputEvents::empty();
83    /// assert_eq!(0, no_events.len());
84    /// assert!(no_events.get(0).is_none());
85    /// ```
86    #[inline]
87    pub const fn empty() -> InputEvents<'static> {
88        InputEvents::from_buffer::<[&UnknownEvent; 0]>(&[])
89    }
90
91    /// Returns the number of events in the list.
92    #[inline]
93    pub fn len(&self) -> u32 {
94        match self.inner.size {
95            None => 0,
96            // SAFETY: this function pointer is safely initialized by from_raw or from_buffer
97            Some(s) => unsafe { s(&self.inner) },
98        }
99    }
100
101    /// Returns `true` if there are no events in the list.
102    #[inline]
103    pub fn is_empty(&self) -> bool {
104        self.len() == 0
105    }
106
107    /// Attempts to retrieve an event from the list using its `index`.
108    ///
109    /// If no event is found at the given `index`, `None` is returned.
110    ///
111    /// Implementors of this method *SHOULD* always return an event if the `index` is in bounds
112    /// (`0..len`), and *SOULD NOT* return one if the `index` is out of bounds. However, this isn't
113    /// a guarantee.
114    ///
115    /// Because incorrect implementations can be found in the wild, users of this method should
116    /// always check the returned `Option`, and skip if `None` is returned while
117    /// getting an expected event using an index that is in bounds.
118    ///
119    /// This also means that users should *not* rely on this method returning `None` to stop an
120    /// iteration, or `Some` to continue it. Always rely on the value of [`len`](InputEvents::len)
121    /// first if you wish to iterate manually.
122    ///
123    /// # Panics
124    ///
125    /// While this method itself does not panic, some hosts (e.g. Bitwig) may elect to crash the
126    /// the plugin if the given `index` is out of bounds.
127    ///
128    /// Therefore, users should be careful while calling this method. Always check the value of
129    /// [`len`](InputEvents::len) before attempting to call this method, to ensure that `index` is
130    /// always in bounds.
131    ///
132    /// # See also
133    ///
134    /// Use the [`iter`](InputEvents::iter) method to iterate on all input events, which handles
135    /// all of the above edge-cases.
136    #[inline]
137    pub fn get(&self, index: u32) -> Option<&UnknownEvent> {
138        // SAFETY: this function pointer is safely initialized by from_raw or from_buffer
139        let event = unsafe { self.inner.get?(&self.inner, index) };
140        if event.is_null() {
141            return None;
142        };
143
144        // SAFETY: the returned event pointer is guaranteed to be valid by from_raw or from_buffer
145        unsafe { Some(UnknownEvent::from_raw(event)) }
146    }
147
148    /// Returns an iterator over all the events in this [`InputEvents`].
149    #[inline]
150    pub fn iter(&self) -> InputEventsIter<'_> {
151        InputEventsIter {
152            list: self,
153            range: 0..self.len(),
154        }
155    }
156
157    /// Returns an iterator over a specific sub-range of the events in this [`InputEvents`].
158    ///
159    /// If the given `range` is out of bounds, then `None` is returned.
160    #[inline]
161    pub fn iter_range(&self, range: Range<u32>) -> Option<InputEventsIter<'_>> {
162        let len = self.len();
163        if range.start > len || range.end > len {
164            None
165        } else {
166            Some(InputEventsIter { list: self, range })
167        }
168    }
169
170    /// Returns an iterator that batches all events for easier processing alongside sample buffers.
171    ///
172    /// This iterator will split the stream of events into multiple
173    /// [`EventBatch`es](crate::events::io::EventBatch), so that:
174    /// * Each batch will only have events on its very first sample.
175    /// * All events that happen on the same sample are batched together.
176    ///
177    /// This makes batch processing of audio samples easier, while still being able to handle
178    /// incoming events that may happen on each sample.
179    ///
180    /// See the [`EventBatch`](crate::events::io::EventBatch) documentation for more information.
181    ///
182    /// # Visual example
183    ///
184    /// In this example, a plugin will receive a buffer of audio samples (represented with `.`s),
185    /// alongside multiple input events (represented by `E`s), which happen at precise,
186    /// sample-accurate times.
187    ///
188    /// The timeline of a processing chunk might look like something like this:
189    ///
190    ///```text
191    ///
192    ///         E           E         E         E         
193    ///                     E                   E         
194    ///                                         E         
195    /// . . . . . . . . . . . . . . . . . . . . . . . . .
196    /// ```
197    ///
198    /// While some events are happening at the same time, there are some parts of the sample buffer
199    /// where no event is occurring, which could be processed efficiently all at once.
200    ///
201    /// The [`EventBatcher`] finds these, and splits the stream into multiple
202    /// [`EventBatch`es](crate::events::io::EventBatch) where events only happen at the beginning of
203    /// each batch.
204    ///
205    /// ```text
206    ///|       |E          |E        |E        |E        |
207    ///|       |           |E        |         |E        |
208    ///|       |           |         |         |E        |
209    ///|. . . .|. . . . . .|. . . . .|. . . . .|. . . . .|
210    ///| batch |   batch   |  batch  |  batch  |  batch  |
211    /// ```
212    ///
213    /// # Example
214    ///
215    /// This example shows how to efficiently process the event batches alongside an audio buffer.
216    ///
217    /// ```
218    /// use clack_common::events::io::InputEvents;
219    /// # use clack_common::events::UnknownEvent;
220    ///
221    /// # fn batch_process(input_events: InputEvents, audio_buffer: &[f32]) {
222    /// let input_events: InputEvents = /* ... */
223    /// # input_events;
224    /// let audio_buffer: &[f32] = /* ... */
225    /// # audio_buffer;
226    ///
227    /// for event_bach in input_events.batch() {
228    ///     // First, handle all events that could affect audio processing.
229    ///     // (e.g. note on/off, parameter changes, etc.)
230    ///    for event in event_bach.events() {
231    ///        // (Handle the event...)
232    ///    }
233    ///
234    ///    // Now, we can process the whole audio batch
235    ///    let audio_batch: &[f32] = &audio_buffer[event_bach.sample_bounds()];
236    ///    // (Process the audio samples...)
237    /// }
238    /// # }
239    /// # let events: [&UnknownEvent; 0] = []; batch_process(InputEvents::from_buffer(&events), &[]);
240    /// ```
241    ///
242    ///
243    #[inline]
244    pub fn batch(&self) -> EventBatcher<'_> {
245        EventBatcher::new(self)
246    }
247}
248
249impl<'a> IntoIterator for &'a InputEvents<'a> {
250    type Item = &'a UnknownEvent;
251    type IntoIter = InputEventsIter<'a>;
252
253    #[inline]
254    fn into_iter(self) -> Self::IntoIter {
255        self.iter()
256    }
257}
258
259impl<'a, I: InputEventBuffer> From<&'a I> for InputEvents<'a> {
260    #[inline]
261    fn from(implementation: &'a I) -> Self {
262        Self::from_buffer(implementation)
263    }
264}
265
266impl InputEventBuffer for InputEvents<'_> {
267    #[inline]
268    fn len(&self) -> u32 {
269        InputEvents::len(self)
270    }
271
272    #[inline]
273    fn get(&self, index: u32) -> Option<&UnknownEvent> {
274        InputEvents::get(self, index)
275    }
276}
277
278const INDEX_ERROR: &str = "Indexed InputEvents list out of bounds";
279
280impl Index<usize> for InputEvents<'_> {
281    type Output = UnknownEvent;
282
283    #[inline]
284    fn index(&self, index: usize) -> &Self::Output {
285        self.get(usize_to_clap_size(index)).expect(INDEX_ERROR)
286    }
287}
288
289impl Debug for InputEvents<'_> {
290    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
291        let mut list = f.debug_list();
292        for event in self {
293            if let Some(event) = event.as_core_event() {
294                list.entry(&event);
295            } else {
296                list.entry(&event);
297            }
298        }
299
300        list.finish()
301    }
302}
303
304/// Immutable [`InputEvents`] iterator.
305#[must_use = "iterators are lazy and do nothing unless consumed"]
306pub struct InputEventsIter<'a> {
307    list: &'a InputEvents<'a>,
308    range: Range<u32>,
309}
310
311impl<'a> InputEventsIter<'a> {
312    #[inline]
313    pub(crate) const fn new(list: &'a InputEvents<'a>, range: Range<u32>) -> Self {
314        Self { list, range }
315    }
316}
317
318impl Clone for InputEventsIter<'_> {
319    #[inline]
320    fn clone(&self) -> Self {
321        InputEventsIter {
322            list: self.list,
323            range: self.range.start..self.range.end,
324        }
325    }
326}
327
328impl<'a> Iterator for InputEventsIter<'a> {
329    type Item = &'a UnknownEvent;
330
331    fn next(&mut self) -> Option<Self::Item> {
332        self.range.next().and_then(|i| self.list.get(i))
333    }
334
335    #[inline]
336    fn size_hint(&self) -> (usize, Option<usize>) {
337        self.range.size_hint()
338    }
339}
340
341impl ExactSizeIterator for InputEventsIter<'_> {
342    #[inline]
343    fn len(&self) -> usize {
344        self.range.len()
345    }
346}
347
348impl DoubleEndedIterator for InputEventsIter<'_> {
349    #[inline]
350    fn next_back(&mut self) -> Option<Self::Item> {
351        self.range.next_back().and_then(|i| self.list.get(i))
352    }
353}
354
355#[cfg(test)]
356mod test {
357    extern crate static_assertions as sa;
358    use super::*;
359
360    sa::assert_not_impl_any!(InputEvents<'static>: Send, Sync);
361}