Skip to main content

clack_common/events/spaces/
core.rs

1use crate::events::event_types::*;
2use crate::events::{Event, EventSpace, UnknownEvent};
3use std::ffi::CStr;
4use std::fmt::{Debug, Formatter};
5
6/// Core CLAP event set.
7///
8/// This enum represents the standard events defined in the CLAP specification
9/// (e.g. [`NoteOnEvent`], [`ParamValueEvent`]).
10///
11/// It can be constructed from an [`UnknownEvent`] when the event is one of the core types.
12///
13/// # Example
14/// Converting from [`UnknownEvent`] to a [`CoreEventSpace`]:
15/// ```no_run
16/// use clack_common::events::UnknownEvent;
17/// use clack_common::events::spaces::CoreEventSpace;
18///
19/// fn handle_event(event: &UnknownEvent) {
20///     if let Some(ev) = event.as_core_event() {
21///         match ev {
22///             CoreEventSpace::NoteOn(note) => { /* handle note‑on */ }
23///             CoreEventSpace::ParamValue(param) => { /* handle param change */ }
24///             _ => {}
25///         }
26///     }
27/// }
28/// ```
29#[derive(Copy, Clone, PartialEq)]
30pub enum CoreEventSpace<'a> {
31    /// A note-on event (key press / attack)
32    NoteOn(&'a NoteOnEvent),
33    /// A note-off event (key release)
34    NoteOff(&'a NoteOffEvent),
35    /// A note choke (forcibly ends a note)
36    NoteChoke(&'a NoteChokeEvent),
37    /// A note end (natural end of note)
38    NoteEnd(&'a NoteEndEvent),
39    /// A note expression change (e.g. per-note pitch)
40    NoteExpression(&'a NoteExpressionEvent),
41    /// A parameter value change
42    ParamValue(&'a ParamValueEvent),
43    /// A parameter modulation change
44    ParamMod(&'a ParamModEvent),
45    /// Begin of a gesture (automation touch)
46    ParamGestureBegin(&'a ParamGestureBeginEvent),
47    /// End of a gesture (automation release)
48    ParamGestureEnd(&'a ParamGestureEndEvent),
49    /// Transport info (playhead, tempo, etc.)
50    Transport(&'a TransportEvent),
51    /// MIDI 1.0 event
52    Midi(&'a MidiEvent),
53    /// MIDI 2.0 event
54    Midi2(&'a Midi2Event),
55    /// MIDI SysEx event
56    MidiSysEx(&'a MidiSysExEvent),
57}
58
59// SAFETY: The core event space has the empty C string for a name.
60unsafe impl<'a> EventSpace<'a> for CoreEventSpace<'a> {
61    const NAME: &'static CStr = c"";
62
63    /// Attempts to reinterpret a raw [`UnknownEvent`] as one of the core event types.
64    ///
65    /// Returns `None` if the event does not belong to this event space.
66    unsafe fn from_unknown(event: &'a UnknownEvent) -> Option<Self> {
67        use CoreEventSpace::*;
68
69        match event.header().type_id() {
70            NoteOnEvent::TYPE_ID => Some(NoteOn(event.as_event_unchecked())),
71            NoteOffEvent::TYPE_ID => Some(NoteOff(event.as_event_unchecked())),
72            NoteChokeEvent::TYPE_ID => Some(NoteChoke(event.as_event_unchecked())),
73            NoteEndEvent::TYPE_ID => Some(NoteEnd(event.as_event_unchecked())),
74            NoteExpressionEvent::TYPE_ID => Some(NoteExpression(event.as_event_unchecked())),
75            ParamValueEvent::TYPE_ID => Some(ParamValue(event.as_event_unchecked())),
76            ParamModEvent::TYPE_ID => Some(ParamMod(event.as_event_unchecked())),
77            TransportEvent::TYPE_ID => Some(Transport(event.as_event_unchecked())),
78            MidiEvent::TYPE_ID => Some(Midi(event.as_event_unchecked())),
79            Midi2Event::TYPE_ID => Some(Midi2(event.as_event_unchecked())),
80            MidiSysExEvent::TYPE_ID => Some(MidiSysEx(event.as_event_unchecked())),
81            _ => None,
82        }
83    }
84
85    #[inline]
86    fn as_unknown(&self) -> &'a UnknownEvent {
87        match self {
88            CoreEventSpace::NoteOn(e) => e.as_unknown(),
89            CoreEventSpace::NoteOff(e) => e.as_unknown(),
90            CoreEventSpace::NoteChoke(e) => e.as_unknown(),
91            CoreEventSpace::NoteEnd(e) => e.as_unknown(),
92            CoreEventSpace::NoteExpression(e) => e.as_unknown(),
93            CoreEventSpace::ParamValue(e) => e.as_unknown(),
94            CoreEventSpace::ParamMod(e) => e.as_unknown(),
95            CoreEventSpace::Transport(e) => e.as_unknown(),
96            CoreEventSpace::Midi(e) => e.as_unknown(),
97            CoreEventSpace::Midi2(e) => e.as_unknown(),
98            CoreEventSpace::MidiSysEx(e) => e.as_unknown(),
99            CoreEventSpace::ParamGestureBegin(e) => e.as_unknown(),
100            CoreEventSpace::ParamGestureEnd(e) => e.as_unknown(),
101        }
102    }
103}
104
105impl Debug for CoreEventSpace<'_> {
106    #[inline]
107    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
108        match self {
109            CoreEventSpace::NoteOn(e) => Debug::fmt(e, f),
110            CoreEventSpace::NoteOff(e) => Debug::fmt(e, f),
111            CoreEventSpace::NoteChoke(e) => Debug::fmt(e, f),
112            CoreEventSpace::NoteEnd(e) => Debug::fmt(e, f),
113            CoreEventSpace::NoteExpression(e) => Debug::fmt(e, f),
114            CoreEventSpace::ParamValue(e) => Debug::fmt(e, f),
115            CoreEventSpace::ParamMod(e) => Debug::fmt(e, f),
116            CoreEventSpace::ParamGestureBegin(e) => Debug::fmt(e, f),
117            CoreEventSpace::ParamGestureEnd(e) => Debug::fmt(e, f),
118            CoreEventSpace::Transport(e) => Debug::fmt(e, f),
119            CoreEventSpace::Midi(e) => Debug::fmt(e, f),
120            CoreEventSpace::Midi2(e) => Debug::fmt(e, f),
121            CoreEventSpace::MidiSysEx(e) => Debug::fmt(e, f),
122        }
123    }
124}