clap_clap/
events.rs

1//! Events and event lists.
2
3use std::{
4    fmt::{Display, Formatter},
5    mem,
6    ptr::{null_mut, slice_from_raw_parts},
7};
8
9use crate::{
10    ffi::{
11        CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_DONT_RECORD, CLAP_EVENT_IS_LIVE, CLAP_EVENT_MIDI,
12        CLAP_EVENT_MIDI2, CLAP_EVENT_NOTE_CHOKE, CLAP_EVENT_NOTE_END, CLAP_EVENT_NOTE_EXPRESSION,
13        CLAP_EVENT_NOTE_OFF, CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_MOD, CLAP_EVENT_PARAM_VALUE,
14        CLAP_EVENT_TRANSPORT, CLAP_NOTE_EXPRESSION_BRIGHTNESS, CLAP_NOTE_EXPRESSION_EXPRESSION,
15        CLAP_NOTE_EXPRESSION_PAN, CLAP_NOTE_EXPRESSION_PRESSURE, CLAP_NOTE_EXPRESSION_TUNING,
16        CLAP_NOTE_EXPRESSION_VIBRATO, CLAP_NOTE_EXPRESSION_VOLUME,
17        CLAP_TRANSPORT_HAS_BEATS_TIMELINE, CLAP_TRANSPORT_HAS_SECONDS_TIMELINE,
18        CLAP_TRANSPORT_HAS_TEMPO, CLAP_TRANSPORT_HAS_TIME_SIGNATURE, CLAP_TRANSPORT_IS_LOOP_ACTIVE,
19        CLAP_TRANSPORT_IS_PLAYING, CLAP_TRANSPORT_IS_RECORDING, CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL,
20        clap_event_header, clap_event_midi, clap_event_midi2, clap_event_note,
21        clap_event_note_expression, clap_event_param_mod, clap_event_param_value,
22        clap_event_transport, clap_input_events, clap_note_expression, clap_output_events,
23    },
24    fixedpoint::{BeatTime, SecTime},
25    id::ClapId,
26    impl_flags_u32,
27};
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq)]
30#[repr(u32)]
31pub enum EventFlags {
32    /// Indicate a live user event, for example a user turning a physical knob
33    /// or playing a physical key.
34    IsLive = CLAP_EVENT_IS_LIVE,
35    /// Indicate that the event should not be recorded.
36    /// For example this is useful when a parameter changes because of a MIDI
37    /// CC, because if the host records both the MIDI CC automation and the
38    /// parameter automation there will be a conflict.
39    DontRecord = CLAP_EVENT_DONT_RECORD,
40}
41
42impl_flags_u32!(EventFlags);
43
44macro_rules! impl_event_cast_methods {
45    ($name:tt, $name_unchecked:tt, $type:ty, $cast_type:ty, $clap_id:ident $(,)?) => {
46        /// # Safety
47        #[doc = concat!("The caller must ensure that this `Header` has correct \
48            size and type to contain the header and the payload of event of the \
49            returned type: `", stringify!($name), "`.")]
50        pub const unsafe fn $name_unchecked(&self) -> $type {
51            unsafe { <$type>::new_unchecked(self) }
52        }
53
54        pub const fn $name(&self) -> Result<$type, Error> {
55            if self.r#type() != $clap_id as u16 {
56                return Err(Error::OtherType(self.r#type()));
57            }
58            if self.size() != size_of::<$cast_type>() as u32 {
59                return Err(Error::PayloadSize(self.size()));
60            }
61            // SAFETY: We just checked if `self` is an event of type to be cast to.
62            Ok(unsafe { <$type>::new_unchecked(self) })
63        }
64    };
65}
66
67#[derive(Debug, PartialEq)]
68pub struct Header([u8]);
69
70impl Header {
71    /// # Safety
72    ///
73    /// The reference must point to a valid header of a CLAP event. i.e.
74    ///
75    /// 1. The header's field: `size` must indicate the correct size of the
76    ///    event.
77    /// 2. The header's field: `type` must indicate the correct type of the
78    ///    event.
79    /// 3. The entire memory block of size `header.size`, starting from the
80    ///    address of `header` must hold a properly initialized and aligned
81    ///    object whose type is inferred from `header.type`.
82    ///
83    /// This is to make possible to cast `&raw const *header` pointer to
84    /// a pointer to the concrete event type.
85    pub const unsafe fn new_unchecked(header: &clap_event_header) -> &Self {
86        let len = header.size as usize;
87        let data = &raw const *header as *const _;
88        unsafe { &*(slice_from_raw_parts::<u8>(data, len) as *const _) }
89    }
90
91    /// # Safety
92    ///
93    /// The caller must ensure that the cast to a reference of type `T` is safe,
94    /// i.e. that the header and the payload hold together a properly
95    /// initialized and aligned object of type `T`.
96    const unsafe fn cast_unchecked<T>(&self) -> &T {
97        unsafe { &*self.0.as_ptr().cast() }
98    }
99
100    pub const fn as_clap_event_header(&self) -> &clap_event_header {
101        // SAFETY: By construction, a cast to `clap_event_header` from with `self` was
102        // created is safe.
103        unsafe { self.cast_unchecked() }
104    }
105
106    #[doc(hidden)]
107    pub const fn to_bytes(&self) -> &[u8] {
108        &self.0
109    }
110
111    pub const fn flags(&self) -> u32 {
112        self.as_clap_event_header().flags
113    }
114
115    pub const fn size(&self) -> u32 {
116        self.0.len() as u32
117    }
118
119    pub const fn space_id(&self) -> u16 {
120        self.as_clap_event_header().space_id
121    }
122
123    pub const fn time(&self) -> u32 {
124        self.as_clap_event_header().time
125    }
126
127    pub const fn r#type(&self) -> u16 {
128        self.as_clap_event_header().r#type
129    }
130
131    /// # Safety
132    /// The caller must ensure that this `Header` has correct
133    /// size and type to contain the header and the payload of event of the
134    /// returned type: `note`.
135    pub const unsafe fn note_unchecked(&self) -> Note {
136        unsafe { Note::new_unchecked(self) }
137    }
138
139    pub const fn note(&self) -> Result<Note, Error> {
140        if self.r#type() != CLAP_EVENT_NOTE_ON as u16
141            && self.r#type() != CLAP_EVENT_NOTE_OFF as u16
142            && self.r#type() != CLAP_EVENT_NOTE_CHOKE as u16
143            && self.r#type() != CLAP_EVENT_NOTE_END as u16
144        {
145            return Err(Error::OtherType(self.r#type()));
146        }
147
148        if self.size() != size_of::<clap_event_note>() as u32 {
149            return Err(Error::PayloadSize(self.size()));
150        }
151        // SAFETY: We just checked if `self` is an event of type to be cast to.
152        Ok(unsafe { Note::new_unchecked(self) })
153    }
154
155    impl_event_cast_methods!(
156        note_expression,
157        note_expression_unchecked,
158        NoteExpression,
159        clap_event_note_expression,
160        CLAP_EVENT_NOTE_EXPRESSION
161    );
162
163    impl_event_cast_methods!(
164        param_value,
165        param_value_unchecked,
166        ParamValue,
167        clap_event_param_value,
168        CLAP_EVENT_PARAM_VALUE
169    );
170
171    impl_event_cast_methods!(
172        param_mod,
173        param_mod_unchecked,
174        ParamMod,
175        clap_event_param_mod,
176        CLAP_EVENT_PARAM_MOD
177    );
178
179    impl_event_cast_methods!(
180        transport,
181        transport_unchecked,
182        Transport,
183        clap_event_transport,
184        CLAP_EVENT_TRANSPORT
185    );
186
187    impl_event_cast_methods!(midi, midi_unchecked, Midi, clap_event_midi, CLAP_EVENT_MIDI);
188
189    impl_event_cast_methods!(
190        midi2,
191        midi2_unchecked,
192        Midi2,
193        clap_event_midi2,
194        CLAP_EVENT_MIDI2
195    );
196}
197
198pub trait Event {
199    fn header(&self) -> &Header;
200
201    fn to_bytes(&self) -> &[u8] {
202        self.header().to_bytes()
203    }
204}
205
206pub trait EventBuilder {
207    type Event<'a>: Event
208    where
209        Self: 'a;
210
211    fn time(self, value: u32) -> Self;
212    fn space_id(self, value: u16) -> Self;
213    fn flags(self, value: u32) -> Self;
214
215    fn event(&self) -> Self::Event<'_>;
216}
217
218macro_rules! impl_event_const_getter {
219    ($name:tt, $cast_method:ident, $type:ty $(,)?) => {
220        pub const fn $name(&self) -> $type {
221            self.$cast_method().$name
222        }
223    };
224}
225
226macro_rules! impl_event_builder_setter {
227    ($name:tt, $type:ty $(,)*) => {
228        #[must_use]
229        pub const fn $name(self, value: $type) -> Self {
230            let mut build = self;
231            build.0.$name = value;
232            build
233        }
234    };
235}
236
237macro_rules! impl_event_builder {
238    ($type:ty, $event_type:ty, $cast_method:ident $(,)?) => {
239        impl EventBuilder for $type {
240            type Event<'a>
241                = $event_type
242            where
243                Self: 'a;
244
245            fn time(self, value: u32) -> Self {
246                let mut build = self;
247                build.0.header.time = value;
248                build
249            }
250
251            fn space_id(self, value: u16) -> Self {
252                let mut build = self;
253                build.0.header.space_id = value;
254                build
255            }
256
257            fn flags(self, value: u32) -> Self {
258                let mut build = self;
259                build.0.header.flags = value;
260                build
261            }
262
263            fn event(&self) -> Self::Event<'_> {
264                // SAFETY: By construction, `self.header` is a valid header of the event type.
265                let header = unsafe { Header::new_unchecked(&self.0.header) };
266                unsafe { header.$cast_method() }
267            }
268        }
269    };
270}
271
272#[derive(Debug, Copy, Clone, PartialEq)]
273#[repr(u16)]
274pub enum NoteKind {
275    On = CLAP_EVENT_NOTE_ON as u16,
276    Off = CLAP_EVENT_NOTE_OFF as u16,
277    Choke = CLAP_EVENT_NOTE_CHOKE as u16,
278    End = CLAP_EVENT_NOTE_END as u16,
279}
280
281#[derive(Debug, Copy, Clone, PartialEq)]
282pub struct Note<'a> {
283    header: &'a Header,
284    pub kind: NoteKind,
285}
286
287impl<'a> Note<'a> {
288    /// # Safety
289    ///
290    /// The `header` must be a header of type: `clap_event_note`.
291    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
292        // SAFETY: By the constructor safety requirements, the cast is sound,
293        // because NoteKind is repr(u16) and it is a valid note event.
294        let kind: NoteKind = unsafe { mem::transmute(header.r#type()) };
295
296        Self { header, kind }
297    }
298
299    const fn as_clap_event_note(&self) -> &clap_event_note {
300        // SAFETY: By construction, this cast is safe.
301        unsafe { self.header.cast_unchecked() }
302    }
303
304    impl_event_const_getter!(note_id, as_clap_event_note, i32);
305    impl_event_const_getter!(port_index, as_clap_event_note, i16);
306    impl_event_const_getter!(channel, as_clap_event_note, i16);
307    impl_event_const_getter!(key, as_clap_event_note, i16);
308    impl_event_const_getter!(velocity, as_clap_event_note, f64);
309
310    pub const fn build(kind: NoteKind) -> NoteBuilder {
311        NoteBuilder::new(kind)
312    }
313
314    pub fn update(&self) -> NoteBuilder {
315        NoteBuilder::with_note(self)
316    }
317}
318
319impl Event for Note<'_> {
320    fn header(&self) -> &Header {
321        self.header
322    }
323}
324
325#[derive(Debug, Copy, Clone, PartialEq)]
326pub struct NoteBuilder(clap_event_note);
327
328impl NoteBuilder {
329    pub const fn new(kind: NoteKind) -> Self {
330        Self(clap_event_note {
331            header: clap_event_header {
332                size: size_of::<clap_event_note>() as u32,
333                time: 0,
334                space_id: CLAP_CORE_EVENT_SPACE_ID,
335                r#type: kind as u16,
336                flags: 0,
337            },
338            note_id: 0,
339            port_index: 0,
340            channel: 0,
341            key: 0,
342            velocity: 0.0,
343        })
344    }
345
346    pub fn with_note(note: &Note<'_>) -> Self {
347        // SAFETY: ParamValue constructor guarantees that this cast is safe, and we can
348        // copy the object of type: `clap_event_param_value`.
349        Self(*unsafe { note.header().cast_unchecked() })
350    }
351
352    impl_event_builder_setter!(note_id, i32);
353    impl_event_builder_setter!(port_index, i16);
354    impl_event_builder_setter!(channel, i16);
355    impl_event_builder_setter!(key, i16);
356    impl_event_builder_setter!(velocity, f64);
357
358    pub const fn kind(self, value: NoteKind) -> Self {
359        let mut build = self;
360        build.0.header.r#type = value as u16;
361        build
362    }
363}
364
365impl Default for NoteBuilder {
366    fn default() -> Self {
367        Self::new(NoteKind::On)
368    }
369}
370
371impl From<clap_event_note> for NoteBuilder {
372    fn from(value: clap_event_note) -> Self {
373        Self(value)
374    }
375}
376
377impl_event_builder!(NoteBuilder, Note<'a>, note_unchecked);
378
379#[derive(Debug, Copy, Clone, PartialEq)]
380#[repr(u32)]
381pub enum NoteExpressionId {
382    /// with 0 < x <= 4, plain = 20 * log(x)
383    Volume = CLAP_NOTE_EXPRESSION_VOLUME as u32,
384
385    /// pan, 0 left, 0.5 center, 1 right
386    Pan = CLAP_NOTE_EXPRESSION_PAN as u32,
387
388    /// Relative tuning in semitones, from -120 to +120. Semitones are in
389    /// equal temperament and are doubles; the resulting note would be
390    /// retuned by `100 * evt->value` cents.
391    Tuning = CLAP_NOTE_EXPRESSION_TUNING as u32,
392
393    /// 0..1
394    Vibrato = CLAP_NOTE_EXPRESSION_VIBRATO as u32,
395    Expression = CLAP_NOTE_EXPRESSION_EXPRESSION as u32,
396    Brightness = CLAP_NOTE_EXPRESSION_BRIGHTNESS as u32,
397    Pressure = CLAP_NOTE_EXPRESSION_PRESSURE as u32,
398}
399
400#[derive(Debug, Copy, Clone, PartialEq)]
401pub struct NoteExpression<'a> {
402    header: &'a Header,
403}
404
405impl<'a> NoteExpression<'a> {
406    /// # Safety
407    ///
408    /// The `header` must be a header of type: `clap_event_note_expression`.
409    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
410        Self { header }
411    }
412
413    const fn as_clap_event_note_expression(&self) -> &clap_event_note_expression {
414        // SAFETY: By construction, this cast is safe.
415        unsafe { self.header.cast_unchecked() }
416    }
417
418    impl_event_const_getter!(note_id, as_clap_event_note_expression, i32);
419    impl_event_const_getter!(port_index, as_clap_event_note_expression, i16);
420    impl_event_const_getter!(channel, as_clap_event_note_expression, i16);
421    impl_event_const_getter!(key, as_clap_event_note_expression, i16);
422    impl_event_const_getter!(value, as_clap_event_note_expression, f64);
423
424    pub const fn expression_id(&self) -> NoteExpressionId {
425        let id = self.as_clap_event_note_expression().expression_id;
426        // SAFETY: NoteExpressionId is repr(u32) and id is a valid expression_id by
427        // construction.
428        unsafe { mem::transmute(id) }
429    }
430
431    pub const fn build(expression_id: NoteExpressionId) -> NoteExpressionBuilder {
432        NoteExpressionBuilder::new(expression_id)
433    }
434
435    pub fn update(&self) -> NoteExpressionBuilder {
436        NoteExpressionBuilder::with_note_expression(self)
437    }
438}
439
440impl Event for NoteExpression<'_> {
441    fn header(&self) -> &Header {
442        self.header
443    }
444}
445
446#[derive(Debug, Copy, Clone, PartialEq)]
447pub struct NoteExpressionBuilder(clap_event_note_expression);
448
449impl NoteExpressionBuilder {
450    pub const fn new(expression_id: NoteExpressionId) -> Self {
451        Self(clap_event_note_expression {
452            header: clap_event_header {
453                size: size_of::<clap_event_note_expression>() as u32,
454                time: 0,
455                space_id: CLAP_CORE_EVENT_SPACE_ID,
456                r#type: CLAP_EVENT_NOTE_EXPRESSION as u16,
457                flags: 0,
458            },
459            expression_id: expression_id as clap_note_expression,
460            note_id: 0,
461            port_index: 0,
462            channel: 0,
463            key: 0,
464            value: 0.0,
465        })
466    }
467
468    pub fn with_note_expression(expression: &NoteExpression<'_>) -> Self {
469        // SAFETY: NoteExpression constructor guarantees that this cast is safe, and we
470        // can copy the object of type: `clap_event_note_expression`.
471        Self(*unsafe { expression.header().cast_unchecked() })
472    }
473
474    impl_event_builder_setter!(note_id, i32);
475    impl_event_builder_setter!(port_index, i16);
476    impl_event_builder_setter!(channel, i16);
477    impl_event_builder_setter!(key, i16);
478    impl_event_builder_setter!(value, f64);
479
480    pub const fn expression_id(self, value: NoteExpressionId) -> Self {
481        let mut build = self;
482        build.0.expression_id = value as clap_note_expression;
483        build
484    }
485}
486
487impl Default for NoteExpressionBuilder {
488    fn default() -> Self {
489        Self::new(NoteExpressionId::Volume)
490    }
491}
492
493impl From<clap_event_note_expression> for NoteExpressionBuilder {
494    fn from(value: clap_event_note_expression) -> Self {
495        Self(value)
496    }
497}
498
499impl_event_builder!(
500    NoteExpressionBuilder,
501    NoteExpression<'a>,
502    note_expression_unchecked
503);
504
505#[derive(Debug, Copy, Clone, PartialEq)]
506pub struct ParamValue<'a> {
507    header: &'a Header,
508}
509
510impl<'a> ParamValue<'a> {
511    /// # Safety
512    ///
513    /// The `header` must be a header of type: `clap_event_param_value`.
514    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
515        Self { header }
516    }
517
518    const fn as_clap_event_param_value(&self) -> &clap_event_param_value {
519        // SAFETY: By construction, this cast is safe.
520        unsafe { self.header.cast_unchecked() }
521    }
522
523    impl_event_const_getter!(channel, as_clap_event_param_value, i16);
524    impl_event_const_getter!(key, as_clap_event_param_value, i16);
525    impl_event_const_getter!(note_id, as_clap_event_param_value, i32);
526
527    // fn cookie(&self) -> Option<NonNull<c_void>> {
528    //     NonNull::new(self.as_clap_event_param_value().cookie)
529    // }
530
531    pub fn param_id(&self) -> ClapId {
532        self.as_clap_event_param_value()
533            .param_id
534            .try_into()
535            .unwrap_or(ClapId::invalid_id())
536    }
537
538    impl_event_const_getter!(port_index, as_clap_event_param_value, i16);
539    impl_event_const_getter!(value, as_clap_event_param_value, f64);
540
541    pub const fn build() -> ParamValueBuilder {
542        ParamValueBuilder::new()
543    }
544
545    pub fn update(&self) -> ParamValueBuilder {
546        ParamValueBuilder::with_param_value(self)
547    }
548}
549
550impl Event for ParamValue<'_> {
551    fn header(&self) -> &Header {
552        self.header
553    }
554}
555
556#[derive(Debug, Copy, Clone, PartialEq)]
557pub struct ParamValueBuilder(clap_event_param_value);
558
559impl ParamValueBuilder {
560    pub const fn new() -> Self {
561        Self(clap_event_param_value {
562            header: clap_event_header {
563                size: size_of::<clap_event_param_value>() as u32,
564                time: 0,
565                space_id: CLAP_CORE_EVENT_SPACE_ID,
566                r#type: CLAP_EVENT_PARAM_VALUE as u16,
567                flags: 0,
568            },
569            param_id: 0,
570            cookie: null_mut(),
571            note_id: 0,
572            port_index: 0,
573            channel: 0,
574            key: 0,
575            value: 0.0,
576        })
577    }
578
579    pub fn with_param_value(param_value: &ParamValue<'_>) -> Self {
580        // SAFETY: ParamValue constructor guarantees that this cast is safe, and we can
581        // copy the object of type: `clap_event_param_value`.
582        Self(*unsafe { param_value.header().cast_unchecked() })
583    }
584
585    impl_event_builder_setter!(port_index, i16);
586    impl_event_builder_setter!(channel, i16);
587    impl_event_builder_setter!(key, i16);
588    impl_event_builder_setter!(note_id, i32);
589
590    // fn cookie(self, value: NonNull<c_void>) -> Self {
591    //     let mut builder = self;
592    //     builder.0.cookie = value.as_ptr();
593    //     builder
594    // }
595
596    pub fn param_id(self, value: ClapId) -> Self {
597        let mut builder = self;
598        builder.0.param_id = value.into();
599        builder
600    }
601
602    impl_event_builder_setter!(value, f64);
603}
604
605impl Default for ParamValueBuilder {
606    fn default() -> Self {
607        Self::new()
608    }
609}
610
611impl From<clap_event_param_value> for ParamValueBuilder {
612    fn from(value: clap_event_param_value) -> Self {
613        Self(value)
614    }
615}
616
617impl_event_builder!(ParamValueBuilder, ParamValue<'a>, param_value_unchecked);
618
619#[derive(Debug, Copy, Clone, PartialEq)]
620pub struct ParamMod<'a> {
621    header: &'a Header,
622}
623
624impl<'a> ParamMod<'a> {
625    /// # Safety
626    ///
627    /// The `header` must be a header of type: `clap_event_param_mod`.
628    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
629        Self { header }
630    }
631
632    const fn as_clap_event_param_mod(&self) -> &clap_event_param_mod {
633        // SAFETY: By construction, this cast is safe.
634        unsafe { self.header.cast_unchecked() }
635    }
636
637    impl_event_const_getter!(channel, as_clap_event_param_mod, i16);
638    impl_event_const_getter!(key, as_clap_event_param_mod, i16);
639    impl_event_const_getter!(note_id, as_clap_event_param_mod, i32);
640
641    // fn cookie(&self) -> Option<NonNull<c_void>> {
642    //     NonNull::new(self.as_clap_event_param_mod().cookie)
643    // }
644
645    pub fn param_id(&self) -> ClapId {
646        self.as_clap_event_param_mod()
647            .param_id
648            .try_into()
649            .unwrap_or(ClapId::invalid_id())
650    }
651
652    impl_event_const_getter!(port_index, as_clap_event_param_mod, i16);
653    impl_event_const_getter!(amount, as_clap_event_param_mod, f64);
654
655    pub const fn build() -> ParamModBuilder {
656        ParamModBuilder::new()
657    }
658
659    pub fn update(&self) -> ParamModBuilder {
660        ParamModBuilder::with_param_mod(self)
661    }
662}
663
664impl Event for ParamMod<'_> {
665    fn header(&self) -> &Header {
666        self.header
667    }
668}
669
670#[derive(Debug, Copy, Clone, PartialEq)]
671pub struct ParamModBuilder(clap_event_param_mod);
672
673impl ParamModBuilder {
674    pub const fn new() -> Self {
675        Self(clap_event_param_mod {
676            header: clap_event_header {
677                size: size_of::<clap_event_param_mod>() as u32,
678                time: 0,
679                space_id: CLAP_CORE_EVENT_SPACE_ID,
680                r#type: CLAP_EVENT_PARAM_MOD as u16,
681                flags: 0,
682            },
683            param_id: 0,
684            cookie: null_mut(),
685            note_id: 0,
686            port_index: 0,
687            channel: 0,
688            key: 0,
689            amount: 0.0,
690        })
691    }
692
693    pub fn with_param_mod(param_mod: &ParamMod<'_>) -> Self {
694        // SAFETY: ParamValue constructor guarantees that this cast is safe, and we can
695        // copy the object of type: `clap_event_param_mod`.
696        Self(*unsafe { param_mod.header().cast_unchecked() })
697    }
698
699    impl_event_builder_setter!(port_index, i16);
700    impl_event_builder_setter!(channel, i16);
701    impl_event_builder_setter!(key, i16);
702    impl_event_builder_setter!(note_id, i32);
703
704    // fn cookie(self, value: NonNull<c_void>) -> Self {
705    //     let mut builder = self;
706    //     builder.0.cookie = value.as_ptr();
707    //     builder
708    // }
709
710    pub fn param_id(self, value: ClapId) -> Self {
711        let mut builder = self;
712        builder.0.param_id = value.into();
713        builder
714    }
715
716    impl_event_builder_setter!(amount, f64);
717}
718
719impl Default for ParamModBuilder {
720    fn default() -> Self {
721        Self::new()
722    }
723}
724
725impl From<clap_event_param_mod> for ParamModBuilder {
726    fn from(value: clap_event_param_mod) -> Self {
727        Self(value)
728    }
729}
730
731impl_event_builder!(ParamModBuilder, ParamMod<'a>, param_mod_unchecked);
732
733/// Transport flags.
734///
735/// # Example
736///
737/// ```rust
738/// # use clap_clap::events::TransportFlags;
739/// assert_eq!(TransportFlags::HasTempo as u32, 0b1);
740/// assert!(TransportFlags::HasTempo.is_set(0b101));
741/// assert_eq!(TransportFlags::HasTempo.set(0b100), 0b101);
742/// assert_eq!(TransportFlags::HasTempo.clear(0b101), 0b100);
743/// ```
744#[derive(Debug, Copy, Clone, PartialEq, Eq)]
745#[repr(u32)]
746pub enum TransportFlags {
747    HasTempo = CLAP_TRANSPORT_HAS_TEMPO,
748    HasBeatsTimeline = CLAP_TRANSPORT_HAS_BEATS_TIMELINE,
749    HasSecondsTimeline = CLAP_TRANSPORT_HAS_SECONDS_TIMELINE,
750    HasTimeSignature = CLAP_TRANSPORT_HAS_TIME_SIGNATURE,
751    IsPlaying = CLAP_TRANSPORT_IS_PLAYING,
752    IsRecording = CLAP_TRANSPORT_IS_RECORDING,
753    IsLoopActive = CLAP_TRANSPORT_IS_LOOP_ACTIVE,
754    IsWithinPreRoll = CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL,
755}
756
757impl_flags_u32!(TransportFlags);
758
759#[derive(Debug, Copy, Clone, PartialEq)]
760pub struct Transport<'a> {
761    header: &'a Header,
762}
763
764macro_rules! impl_transport_time_getter {
765    ($name:tt, $type:tt $(,)?) => {
766        pub const fn $name(&self) -> $type {
767            $type(self.as_clap_event_transport().$name)
768        }
769    };
770}
771
772impl<'a> Transport<'a> {
773    /// # Safety
774    ///
775    /// The `header` must be a header of type: `clap_event_transport`.
776    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
777        Self { header }
778    }
779
780    const fn as_clap_event_transport(&self) -> &clap_event_transport {
781        // SAFETY: By construction, this cast is safe.
782        unsafe { self.header.cast_unchecked() }
783    }
784
785    impl_transport_time_getter!(song_pos_seconds, SecTime);
786    impl_transport_time_getter!(song_pos_beats, BeatTime);
787    impl_transport_time_getter!(loop_start_beats, BeatTime);
788    impl_transport_time_getter!(loop_end_beats, BeatTime);
789    impl_transport_time_getter!(loop_start_seconds, SecTime);
790    impl_transport_time_getter!(loop_end_seconds, SecTime);
791    impl_transport_time_getter!(bar_start, BeatTime);
792
793    impl_event_const_getter!(flags, as_clap_event_transport, u32);
794    impl_event_const_getter!(tempo, as_clap_event_transport, f64);
795    impl_event_const_getter!(tempo_inc, as_clap_event_transport, f64);
796    impl_event_const_getter!(bar_number, as_clap_event_transport, i32);
797    impl_event_const_getter!(tsig_num, as_clap_event_transport, u16);
798    impl_event_const_getter!(tsig_denom, as_clap_event_transport, u16);
799
800    pub const fn build() -> TransportBuilder {
801        TransportBuilder::new()
802    }
803
804    pub fn update(&self) -> TransportBuilder {
805        TransportBuilder::with_transport(self)
806    }
807}
808
809impl Event for Transport<'_> {
810    fn header(&self) -> &Header {
811        self.header
812    }
813}
814
815macro_rules! impl_transport_time_setter {
816    ($name:tt, $type:tt $(,)?) => {
817        pub const fn $name(self, value: $type) -> Self {
818            let mut build = self;
819            build.0.$name = value.0;
820            build
821        }
822    };
823}
824
825#[derive(Debug, Copy, Clone, PartialEq)]
826pub struct TransportBuilder(clap_event_transport);
827
828impl TransportBuilder {
829    pub const fn new() -> Self {
830        Self(clap_event_transport {
831            header: clap_event_header {
832                size: size_of::<clap_event_transport>() as u32,
833                time: 0,
834                space_id: CLAP_CORE_EVENT_SPACE_ID,
835                r#type: CLAP_EVENT_TRANSPORT as u16,
836                flags: 0,
837            },
838            flags: 0,
839            song_pos_beats: 0,
840            song_pos_seconds: 0,
841            tempo: 0.0,
842            tempo_inc: 0.0,
843            loop_start_beats: 0,
844            loop_end_beats: 0,
845            loop_start_seconds: 0,
846            loop_end_seconds: 0,
847            bar_start: 0,
848            bar_number: 0,
849            tsig_num: 0,
850            tsig_denom: 0,
851        })
852    }
853
854    pub fn with_transport(param_value: &Transport<'_>) -> Self {
855        // SAFETY: Transport constructor guarantees that this cast is safe, and we can
856        // copy the object of type: `clap_event_transport`.
857        Self(*unsafe { param_value.header().cast_unchecked() })
858    }
859
860    impl_transport_time_setter!(song_pos_seconds, SecTime);
861    impl_transport_time_setter!(song_pos_beats, BeatTime);
862    impl_transport_time_setter!(loop_start_beats, BeatTime);
863    impl_transport_time_setter!(loop_end_beats, BeatTime);
864    impl_transport_time_setter!(loop_start_seconds, SecTime);
865    impl_transport_time_setter!(loop_end_seconds, SecTime);
866    impl_transport_time_setter!(bar_start, BeatTime);
867
868    impl_event_builder_setter!(flags, u32);
869    impl_event_builder_setter!(tempo, f64);
870    impl_event_builder_setter!(tempo_inc, f64);
871    impl_event_builder_setter!(bar_number, i32);
872    impl_event_builder_setter!(tsig_num, u16);
873    impl_event_builder_setter!(tsig_denom, u16);
874}
875
876impl Default for TransportBuilder {
877    fn default() -> Self {
878        Self::new()
879    }
880}
881
882impl From<clap_event_transport> for TransportBuilder {
883    fn from(value: clap_event_transport) -> Self {
884        Self(value)
885    }
886}
887
888impl_event_builder!(TransportBuilder, Transport<'a>, transport_unchecked);
889
890#[derive(Debug, Copy, Clone, PartialEq)]
891pub struct Midi<'a> {
892    header: &'a Header,
893}
894
895impl<'a> Midi<'a> {
896    /// # Safety
897    ///
898    /// The `header` must be a header of type: `clap_event_midi`.
899    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
900        Self { header }
901    }
902
903    const fn as_clap_event_midi(&self) -> &clap_event_midi {
904        // SAFETY: By construction, this cast is safe.
905        unsafe { self.header.cast_unchecked() }
906    }
907
908    impl_event_const_getter!(port_index, as_clap_event_midi, u16);
909
910    pub const fn data(&self) -> &[u8; 3] {
911        &self.as_clap_event_midi().data
912    }
913
914    /// # Example
915    ///
916    /// ```rust
917    /// # use clap_clap::events::{Event, EventBuilder,Midi};
918    /// let midi = Midi::build().port_index(1).time(3);
919    /// let event = midi.event();
920    ///
921    /// assert_eq!(event.port_index(), 1);
922    /// assert_eq!(event.header().time(), 3);
923    /// ```
924    pub const fn build() -> MidiBuilder {
925        MidiBuilder::new()
926    }
927
928    /// # Example
929    ///
930    /// ```rust
931    /// # use clap_clap::events::{Event, EventBuilder,Midi};
932    /// let midi = Midi::build().port_index(1).data([1, 2, 3]);
933    /// let event = midi.event();
934    ///
935    /// let other_midi = event.update().data([4, 5, 6]);
936    /// let other_event = other_midi.event();
937    ///
938    /// assert_eq!(event.port_index(), 1);
939    /// assert_eq!(event.data(), &[1, 2, 3]);
940    ///
941    /// assert_eq!(other_event.port_index(), 1);
942    /// assert_eq!(other_event.data(), &[4, 5, 6]);
943    /// ```
944    pub fn update(&self) -> MidiBuilder {
945        MidiBuilder::with_midi(self)
946    }
947}
948
949impl Event for Midi<'_> {
950    fn header(&self) -> &Header {
951        self.header
952    }
953}
954
955#[derive(Debug, Copy, Clone, PartialEq)]
956pub struct MidiBuilder(clap_event_midi);
957
958impl MidiBuilder {
959    pub const fn new() -> Self {
960        Self(clap_event_midi {
961            header: clap_event_header {
962                size: size_of::<clap_event_midi>() as u32,
963                time: 0,
964                space_id: CLAP_CORE_EVENT_SPACE_ID,
965                r#type: CLAP_EVENT_MIDI as u16,
966                flags: 0,
967            },
968            port_index: 0,
969            data: [0; 3],
970        })
971    }
972
973    pub fn with_midi(midi: &Midi<'_>) -> Self {
974        // SAFETY: Midi constructor guarantees that this cast is safe, and we can copy
975        // the object of type: `clap_event_midi`.
976        Self(*unsafe { midi.header().cast_unchecked() })
977    }
978
979    impl_event_builder_setter!(port_index, u16);
980    impl_event_builder_setter!(data, [u8; 3]);
981}
982
983impl Default for MidiBuilder {
984    fn default() -> Self {
985        Self::new()
986    }
987}
988
989impl From<clap_event_midi> for MidiBuilder {
990    fn from(value: clap_event_midi) -> Self {
991        Self(value)
992    }
993}
994
995impl_event_builder!(MidiBuilder, Midi<'a>, midi_unchecked);
996
997#[derive(Debug, Copy, Clone, PartialEq)]
998pub struct Midi2<'a> {
999    header: &'a Header,
1000}
1001
1002impl<'a> Midi2<'a> {
1003    /// # Safety
1004    ///
1005    /// The `header` must be a header of type: `clap_event_midi2`.
1006    pub const unsafe fn new_unchecked(header: &'a Header) -> Self {
1007        Self { header }
1008    }
1009
1010    const fn as_clap_event_midi2(&self) -> &clap_event_midi2 {
1011        // SAFETY: By construction, this cast is safe.
1012        unsafe { self.header.cast_unchecked() }
1013    }
1014
1015    impl_event_const_getter!(port_index, as_clap_event_midi2, u16);
1016
1017    pub const fn data(&self) -> &[u32; 4] {
1018        &self.as_clap_event_midi2().data
1019    }
1020
1021    /// # Example
1022    ///
1023    /// ```rust
1024    /// # use clap_clap::events::{Event, EventBuilder,Midi2};
1025    /// let midi = Midi2::build().port_index(1).time(3);
1026    /// let event = midi.event();
1027    ///
1028    /// assert_eq!(event.port_index(), 1);
1029    /// assert_eq!(event.header().time(), 3);
1030    /// ```
1031    pub const fn build() -> Midi2Builder {
1032        Midi2Builder::new()
1033    }
1034
1035    /// # Example
1036    ///
1037    /// ```rust
1038    /// # use clap_clap::events::{Event, EventBuilder,Midi2};
1039    /// let midi = Midi2::build().port_index(1).data([1, 2, 3, 4]);
1040    /// let event = midi.event();
1041    ///
1042    /// let other_midi = event.update().data([4, 5, 6, 7]);
1043    /// let other_event = other_midi.event();
1044    ///
1045    /// assert_eq!(event.port_index(), 1);
1046    /// assert_eq!(event.data(), &[1, 2, 3, 4]);
1047    ///
1048    /// assert_eq!(other_event.port_index(), 1);
1049    /// assert_eq!(other_event.data(), &[4, 5, 6, 7]);
1050    /// ```
1051    pub fn update(&self) -> Midi2Builder {
1052        Midi2Builder::with_midi2(self)
1053    }
1054}
1055
1056impl Event for Midi2<'_> {
1057    fn header(&self) -> &Header {
1058        self.header
1059    }
1060}
1061
1062#[derive(Debug, Copy, Clone, PartialEq)]
1063pub struct Midi2Builder(clap_event_midi2);
1064
1065impl Midi2Builder {
1066    pub const fn new() -> Self {
1067        Self(clap_event_midi2 {
1068            header: clap_event_header {
1069                size: size_of::<clap_event_midi2>() as u32,
1070                time: 0,
1071                space_id: CLAP_CORE_EVENT_SPACE_ID,
1072                r#type: CLAP_EVENT_MIDI2 as u16,
1073                flags: 0,
1074            },
1075            port_index: 0,
1076            data: [0; 4],
1077        })
1078    }
1079
1080    pub fn with_midi2(midi: &Midi2<'_>) -> Self {
1081        // SAFETY: Midi constructor guarantees that this cast is safe, and we can copy
1082        // the object of type: `clap_event_midi2`.
1083        Self(*unsafe { midi.header().cast_unchecked() })
1084    }
1085
1086    impl_event_builder_setter!(port_index, u16);
1087    impl_event_builder_setter!(data, [u32; 4]);
1088}
1089
1090impl Default for Midi2Builder {
1091    fn default() -> Self {
1092        Self::new()
1093    }
1094}
1095
1096impl From<clap_event_midi2> for Midi2Builder {
1097    fn from(value: clap_event_midi2) -> Self {
1098        Self(value)
1099    }
1100}
1101
1102impl_event_builder!(Midi2Builder, Midi2<'a>, midi2_unchecked);
1103
1104pub struct InputEvents<'a>(&'a clap_input_events);
1105
1106impl<'a> InputEvents<'a> {
1107    /// # Safety
1108    ///
1109    /// The pointers: `list.size` and `list.get` must be Some.
1110    #[doc(hidden)]
1111    pub const unsafe fn new_unchecked(list: &'a clap_input_events) -> Self {
1112        Self(list)
1113    }
1114
1115    pub fn size(&self) -> u32 {
1116        // SAFETY: By construction, the pointer `self.size` is Some.
1117        unsafe { self.0.size.unwrap()(self.0) }
1118    }
1119
1120    /// # Safety
1121    ///
1122    /// The value of `index` must be less than `self.size()`.
1123    pub unsafe fn get_unchecked(&self, index: u32) -> &Header {
1124        // SAFETY: By construction, the pointer `self.get` is Some.
1125        let header = unsafe { &*self.0.get.unwrap()(self.0, index) };
1126        unsafe { Header::new_unchecked(header) }
1127    }
1128
1129    /// # Panic
1130    ///
1131    /// Panic if `index` greater or equal than `self.size()`.
1132    pub fn get(&self, index: u32) -> &Header {
1133        assert!(index < self.size(), "index out of bounds");
1134        unsafe { self.get_unchecked(index) }
1135    }
1136}
1137
1138pub struct OutputEvents<'a> {
1139    list: &'a clap_output_events,
1140    last_time: u32,
1141}
1142
1143impl<'a> OutputEvents<'a> {
1144    /// # Safety
1145    ///
1146    /// The pointer: `list.try_push` must be Some.
1147    #[doc(hidden)]
1148    pub const unsafe fn new_unchecked(list: &'a clap_output_events) -> Self {
1149        Self { list, last_time: 0 }
1150    }
1151
1152    /// # Safety
1153    ///
1154    /// Events must be pushed in sample time order, i.e. `event.header().time()`
1155    /// must not be smaller than the time of the previous event successfully
1156    /// pushed.
1157    pub unsafe fn try_push_unchecked(&mut self, event: impl Event) -> Result<(), Error> {
1158        let time = event.header().time();
1159
1160        if unsafe { self.list.try_push.unwrap()(self.list, event.header().as_clap_event_header()) }
1161        {
1162            self.last_time = time;
1163            Ok(())
1164        } else {
1165            Err(Error::TryPush)
1166        }
1167    }
1168
1169    pub fn try_push(&mut self, event: impl Event) -> Result<(), Error> {
1170        if event.header().time() >= self.last_time {
1171            unsafe { self.try_push_unchecked(event) }
1172        } else {
1173            Err(Error::OutOfOrder {
1174                last_time: self.last_time,
1175            })
1176        }
1177    }
1178}
1179
1180#[derive(Debug, Copy, Clone, PartialEq)]
1181pub enum Error {
1182    OtherType(u16),
1183    PayloadSize(u32),
1184    TryPush,
1185    OutOfOrder { last_time: u32 },
1186}
1187
1188impl Display for Error {
1189    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1190        match self {
1191            Error::PayloadSize(size) => {
1192                write!(f, "payload size for the defined event type: {size}")
1193            }
1194            Error::OtherType(id) => write!(f, "other type, id: {id}"),
1195
1196            Error::TryPush => write!(f, "pushing event failed"),
1197
1198            Error::OutOfOrder { last_time } => {
1199                write!(f, "event out of order, last event's time: {last_time}")
1200            }
1201        }
1202    }
1203}
1204
1205impl std::error::Error for Error {}
1206
1207impl From<Error> for crate::Error {
1208    fn from(value: Error) -> Self {
1209        crate::Error::Events(value)
1210    }
1211}