1use core::any::Any;
2
3#[cfg(not(feature = "std"))]
4use bevy_platform::prelude::{Box, Vec};
5
6use crate::{
7 clock::{DurationSamples, DurationSeconds, InstantSamples, InstantSeconds},
8 collector::{ArcGc, OwnedGc},
9 diff::{Notify, ParamPath},
10 dsp::volume::Volume,
11 node::NodeID,
12 vector::{Vec2, Vec3},
13};
14
15#[cfg(feature = "midi_events")]
16pub use wmidi;
17#[cfg(feature = "midi_events")]
18use wmidi::MidiMessage;
19
20#[cfg(feature = "scheduled_events")]
21use crate::clock::EventInstant;
22
23#[cfg(feature = "musical_transport")]
24use crate::clock::{DurationMusical, InstantMusical};
25
26#[derive(Debug)]
28pub struct NodeEvent {
29 pub node_id: NodeID,
31 #[cfg(feature = "scheduled_events")]
34 pub time: Option<EventInstant>,
35 pub event: NodeEventType,
37}
38
39impl NodeEvent {
40 pub const fn new(node_id: NodeID, event: NodeEventType) -> Self {
45 Self {
46 node_id,
47 #[cfg(feature = "scheduled_events")]
48 time: None,
49 event,
50 }
51 }
52
53 #[cfg(feature = "scheduled_events")]
60 pub const fn scheduled(node_id: NodeID, time: EventInstant, event: NodeEventType) -> Self {
61 Self {
62 node_id,
63 time: Some(time),
64 event,
65 }
66 }
67}
68
69#[non_exhaustive]
71pub enum NodeEventType {
72 Param {
73 data: ParamData,
75 path: ParamPath,
77 },
78 SetBypassed(bool),
80 Custom(OwnedGc<Box<dyn Any + Send + 'static>>),
82 CustomBytes([u8; 36]),
84 #[cfg(feature = "scheduled_events")]
91 Marker,
92 #[cfg(feature = "midi_events")]
93 MIDI(MidiMessage<'static>),
94}
95
96impl NodeEventType {
97 pub fn custom<T: Send + 'static>(value: T) -> Self {
98 Self::Custom(OwnedGc::new(Box::new(value)))
99 }
100
101 pub fn custom_boxed<T: Send + 'static>(value: Box<T>) -> Self {
102 Self::Custom(OwnedGc::new(value))
103 }
104
105 pub fn downcast_ref<T: Send + 'static>(&self) -> Option<&T> {
110 if let Self::Custom(owned) = self {
111 owned.as_ref().downcast_ref()
112 } else {
113 None
114 }
115 }
116
117 pub fn downcast_mut<T: Send + 'static>(&mut self) -> Option<&mut T> {
122 if let Self::Custom(owned) = self {
123 owned.as_mut().downcast_mut()
124 } else {
125 None
126 }
127 }
128
129 pub fn downcast_swap<T: Send + 'static>(&mut self, value: &mut T) -> bool {
139 if let Some(v) = self.downcast_mut::<T>() {
140 core::mem::swap(v, value);
141 true
142 } else {
143 false
144 }
145 }
146
147 pub fn downcast_into_owned<T: Send + 'static>(&mut self, value: &mut OwnedGc<T>) -> bool {
157 if let Some(v) = self.downcast_mut::<T>() {
158 value.swap(v);
159 true
160 } else {
161 false
162 }
163 }
164}
165
166impl core::fmt::Debug for NodeEventType {
167 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
168 match self {
169 NodeEventType::Param { data, path } => f
170 .debug_struct("Param")
171 .field("data", &data)
172 .field("path", &path)
173 .finish(),
174 NodeEventType::Custom(_) => f.debug_tuple("Custom").finish_non_exhaustive(),
175 NodeEventType::CustomBytes(f0) => f.debug_tuple("CustomBytes").field(&f0).finish(),
176 NodeEventType::SetBypassed(b) => f.debug_tuple("SetBypassed").field(&b).finish(),
177 #[cfg(feature = "scheduled_events")]
178 NodeEventType::Marker => f.write_str("Marker"),
179 #[cfg(feature = "midi_events")]
180 NodeEventType::MIDI(f0) => f.debug_tuple("MIDI").field(&f0).finish(),
181 }
182 }
183}
184
185#[derive(Clone, Debug)]
187#[non_exhaustive]
188pub enum ParamData {
189 F32(f32),
190 F64(f64),
191 I32(i32),
192 U32(u32),
193 I64(i64),
194 U64(u64),
195 Bool(bool),
196 Volume(Volume),
197 Vector2D(Vec2),
198 Vector3D(Vec3),
199
200 #[cfg(feature = "scheduled_events")]
201 EventInstant(EventInstant),
202 InstantSeconds(InstantSeconds),
203 DurationSeconds(DurationSeconds),
204 InstantSamples(InstantSamples),
205 DurationSamples(DurationSamples),
206 #[cfg(feature = "musical_transport")]
207 InstantMusical(InstantMusical),
208 #[cfg(feature = "musical_transport")]
209 DurationMusical(DurationMusical),
210
211 Any(ArcGc<dyn Any + Send + Sync>),
213
214 CustomBytes([u8; 20]),
216
217 None,
219}
220
221impl ParamData {
222 pub fn any<T: Send + Sync + 'static>(value: T) -> Self {
224 Self::Any(ArcGc::new_any(value))
225 }
226
227 pub fn opt_any<T: Any + Send + Sync + 'static>(value: Option<T>) -> Self {
229 if let Some(value) = value {
230 Self::any(value)
231 } else {
232 Self::None
233 }
234 }
235
236 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
241 match self {
242 Self::Any(any) => any.downcast_ref(),
243 _ => None,
244 }
245 }
246}
247
248macro_rules! param_data_from {
249 ($ty:ty, $variant:ident) => {
250 impl From<$ty> for ParamData {
251 fn from(value: $ty) -> Self {
252 Self::$variant(value.into())
253 }
254 }
255
256 impl TryInto<$ty> for &ParamData {
257 type Error = crate::diff::PatchError;
258
259 fn try_into(self) -> Result<$ty, crate::diff::PatchError> {
260 match self {
261 ParamData::$variant(value) => Ok((*value).into()),
262 _ => Err(crate::diff::PatchError::InvalidData),
263 }
264 }
265 }
266
267 impl From<Option<$ty>> for ParamData {
268 fn from(value: Option<$ty>) -> Self {
269 if let Some(value) = value {
270 Self::$variant(value.into())
271 } else {
272 Self::None
273 }
274 }
275 }
276
277 impl TryInto<Option<$ty>> for &ParamData {
278 type Error = crate::diff::PatchError;
279
280 fn try_into(self) -> Result<Option<$ty>, crate::diff::PatchError> {
281 match self {
282 ParamData::$variant(value) => Ok(Some((*value).into())),
283 ParamData::None => Ok(None),
284 _ => Err(crate::diff::PatchError::InvalidData),
285 }
286 }
287 }
288
289 impl From<Notify<$ty>> for ParamData {
290 fn from(value: Notify<$ty>) -> Self {
291 Self::$variant((*value).into())
292 }
293 }
294
295 impl TryInto<Notify<$ty>> for &ParamData {
296 type Error = crate::diff::PatchError;
297
298 fn try_into(self) -> Result<Notify<$ty>, crate::diff::PatchError> {
299 match self {
300 ParamData::$variant(value) => Ok(Notify::new((*value).into())),
301 _ => Err(crate::diff::PatchError::InvalidData),
302 }
303 }
304 }
305 };
306}
307
308param_data_from!(Volume, Volume);
309param_data_from!(f32, F32);
310param_data_from!(f64, F64);
311param_data_from!(i32, I32);
312param_data_from!(u32, U32);
313param_data_from!(i64, I64);
314param_data_from!(u64, U64);
315param_data_from!(bool, Bool);
316param_data_from!(Vec2, Vector2D);
317param_data_from!(Vec3, Vector3D);
318#[cfg(feature = "scheduled_events")]
319param_data_from!(EventInstant, EventInstant);
320param_data_from!(InstantSeconds, InstantSeconds);
321param_data_from!(DurationSeconds, DurationSeconds);
322param_data_from!(InstantSamples, InstantSamples);
323param_data_from!(DurationSamples, DurationSamples);
324#[cfg(feature = "musical_transport")]
325param_data_from!(InstantMusical, InstantMusical);
326#[cfg(feature = "musical_transport")]
327param_data_from!(DurationMusical, DurationMusical);
328
329#[cfg(feature = "glam-29")]
330param_data_from!(glam_29::Vec2, Vector2D);
331#[cfg(feature = "glam-29")]
332param_data_from!(glam_29::Vec3, Vector3D);
333
334#[cfg(feature = "glam-30")]
335param_data_from!(glam_30::Vec2, Vector2D);
336#[cfg(feature = "glam-30")]
337param_data_from!(glam_30::Vec3, Vector3D);
338
339#[cfg(feature = "glam-31")]
340param_data_from!(glam_31::Vec2, Vector2D);
341#[cfg(feature = "glam-31")]
342param_data_from!(glam_31::Vec3, Vector3D);
343
344#[cfg(feature = "glam-32")]
345param_data_from!(glam_32::Vec2, Vector2D);
346#[cfg(feature = "glam-32")]
347param_data_from!(glam_32::Vec3, Vector3D);
348
349impl From<()> for ParamData {
350 fn from(_value: ()) -> Self {
351 Self::None
352 }
353}
354
355impl TryInto<()> for &ParamData {
356 type Error = crate::diff::PatchError;
357
358 fn try_into(self) -> Result<(), crate::diff::PatchError> {
359 match self {
360 ParamData::None => Ok(()),
361 _ => Err(crate::diff::PatchError::InvalidData),
362 }
363 }
364}
365
366impl From<Notify<()>> for ParamData {
367 fn from(_value: Notify<()>) -> Self {
368 Self::None
369 }
370}
371
372impl TryInto<Notify<()>> for &ParamData {
373 type Error = crate::diff::PatchError;
374
375 fn try_into(self) -> Result<Notify<()>, crate::diff::PatchError> {
376 match self {
377 ParamData::None => Ok(Notify::new(())),
378 _ => Err(crate::diff::PatchError::InvalidData),
379 }
380 }
381}
382
383#[cfg(feature = "scheduled_events")]
385pub struct ScheduledEventEntry {
386 pub event: NodeEvent,
387 pub is_pre_process: bool,
388}
389
390pub struct ProcEvents<'a> {
392 immediate_event_buffer: &'a mut [Option<NodeEvent>],
393 #[cfg(feature = "scheduled_events")]
394 scheduled_event_arena: &'a mut [Option<ScheduledEventEntry>],
395 indices: &'a mut Vec<ProcEventsIndex>,
396}
397
398impl<'a> ProcEvents<'a> {
399 pub fn new(
400 immediate_event_buffer: &'a mut [Option<NodeEvent>],
401 #[cfg(feature = "scheduled_events")] scheduled_event_arena: &'a mut [Option<
402 ScheduledEventEntry,
403 >],
404 indices: &'a mut Vec<ProcEventsIndex>,
405 ) -> Self {
406 Self {
407 immediate_event_buffer,
408 #[cfg(feature = "scheduled_events")]
409 scheduled_event_arena,
410 indices,
411 }
412 }
413
414 pub fn num_events(&self) -> usize {
415 self.indices.len()
416 }
417
418 pub fn is_empty(&self) -> bool {
419 self.indices.is_empty()
420 }
421
422 pub fn drain<'b>(&'b mut self) -> impl IntoIterator<Item = NodeEventType> + use<'b> {
424 self.indices.drain(..).map(|index_type| match index_type {
425 ProcEventsIndex::Immediate(i) => {
426 self.immediate_event_buffer[i as usize]
427 .take()
428 .unwrap()
429 .event
430 }
431 #[cfg(feature = "scheduled_events")]
432 ProcEventsIndex::Scheduled(i) => {
433 self.scheduled_event_arena[i as usize]
434 .take()
435 .unwrap()
436 .event
437 .event
438 }
439 })
440 }
441
442 #[cfg(feature = "scheduled_events")]
450 pub fn drain_with_timestamps<'b>(
451 &'b mut self,
452 ) -> impl IntoIterator<Item = (NodeEventType, Option<EventInstant>)> + use<'b> {
453 self.indices.drain(..).map(|index_type| match index_type {
454 ProcEventsIndex::Immediate(i) => {
455 let event = self.immediate_event_buffer[i as usize].take().unwrap();
456
457 (event.event, event.time)
458 }
459 ProcEventsIndex::Scheduled(i) => {
460 let event = self.scheduled_event_arena[i as usize].take().unwrap();
461
462 (event.event.event, event.event.time)
463 }
464 })
465 }
466
467 pub fn drain_patches<'b, T: crate::diff::Patch>(
499 &'b mut self,
500 ) -> impl IntoIterator<Item = <T as crate::diff::Patch>::Patch> + use<'b, T> {
501 self.drain().into_iter().filter_map(|e| T::patch_event(&e))
505 }
506
507 #[cfg(feature = "scheduled_events")]
544 pub fn drain_patches_with_timestamps<'b, T: crate::diff::Patch>(
545 &'b mut self,
546 ) -> impl IntoIterator<Item = (<T as crate::diff::Patch>::Patch, Option<EventInstant>)> + use<'b, T>
547 {
548 self.drain_with_timestamps()
552 .into_iter()
553 .filter_map(|(e, timestamp)| T::patch_event(&e).map(|patch| (patch, timestamp)))
554 }
555}
556
557#[derive(Debug, Clone, Copy, PartialEq, Eq)]
559pub enum ProcEventsIndex {
560 Immediate(u32),
561 #[cfg(feature = "scheduled_events")]
562 Scheduled(u32),
563}