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}