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 = "midi_events")]
85 MIDI(MidiMessage<'static>),
86}
87
88impl NodeEventType {
89 pub fn custom<T: Send + 'static>(value: T) -> Self {
90 Self::Custom(OwnedGc::new(Box::new(value)))
91 }
92
93 pub fn custom_boxed<T: Send + 'static>(value: Box<T>) -> Self {
94 Self::Custom(OwnedGc::new(value))
95 }
96
97 pub fn downcast_ref<T: Send + 'static>(&self) -> Option<&T> {
102 if let Self::Custom(owned) = self {
103 owned.as_ref().downcast_ref()
104 } else {
105 None
106 }
107 }
108
109 pub fn downcast_mut<T: Send + 'static>(&mut self) -> Option<&mut T> {
114 if let Self::Custom(owned) = self {
115 owned.as_mut().downcast_mut()
116 } else {
117 None
118 }
119 }
120
121 pub fn downcast_swap<T: Send + 'static>(&mut self, value: &mut T) -> bool {
131 if let Some(v) = self.downcast_mut::<T>() {
132 core::mem::swap(v, value);
133 true
134 } else {
135 false
136 }
137 }
138
139 pub fn downcast_into_owned<T: Send + 'static>(&mut self, value: &mut OwnedGc<T>) -> bool {
149 if let Some(v) = self.downcast_mut::<T>() {
150 value.swap(v);
151 true
152 } else {
153 false
154 }
155 }
156}
157
158impl core::fmt::Debug for NodeEventType {
159 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
160 match self {
161 NodeEventType::Param { data, path } => f
162 .debug_struct("Param")
163 .field("data", &data)
164 .field("path", &path)
165 .finish(),
166 NodeEventType::Custom(_) => f.debug_tuple("Custom").finish_non_exhaustive(),
167 NodeEventType::CustomBytes(f0) => f.debug_tuple("CustomBytes").field(&f0).finish(),
168 NodeEventType::SetBypassed(b) => f.debug_tuple("SetBypassed").field(&b).finish(),
169 #[cfg(feature = "midi_events")]
170 NodeEventType::MIDI(f0) => f.debug_tuple("MIDI").field(&f0).finish(),
171 }
172 }
173}
174
175#[derive(Clone, Debug)]
177#[non_exhaustive]
178pub enum ParamData {
179 F32(f32),
180 F64(f64),
181 I32(i32),
182 U32(u32),
183 I64(i64),
184 U64(u64),
185 Bool(bool),
186 Volume(Volume),
187 Vector2D(Vec2),
188 Vector3D(Vec3),
189
190 #[cfg(feature = "scheduled_events")]
191 EventInstant(EventInstant),
192 InstantSeconds(InstantSeconds),
193 DurationSeconds(DurationSeconds),
194 InstantSamples(InstantSamples),
195 DurationSamples(DurationSamples),
196 #[cfg(feature = "musical_transport")]
197 InstantMusical(InstantMusical),
198 #[cfg(feature = "musical_transport")]
199 DurationMusical(DurationMusical),
200
201 Any(ArcGc<dyn Any + Send + Sync>),
203
204 CustomBytes([u8; 20]),
206
207 None,
209}
210
211impl ParamData {
212 pub fn any<T: Send + Sync + 'static>(value: T) -> Self {
214 Self::Any(ArcGc::new_any(value))
215 }
216
217 pub fn opt_any<T: Any + Send + Sync + 'static>(value: Option<T>) -> Self {
219 if let Some(value) = value {
220 Self::any(value)
221 } else {
222 Self::None
223 }
224 }
225
226 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
231 match self {
232 Self::Any(any) => any.downcast_ref(),
233 _ => None,
234 }
235 }
236}
237
238macro_rules! param_data_from {
239 ($ty:ty, $variant:ident) => {
240 impl From<$ty> for ParamData {
241 fn from(value: $ty) -> Self {
242 Self::$variant(value.into())
243 }
244 }
245
246 impl TryInto<$ty> for &ParamData {
247 type Error = crate::diff::PatchError;
248
249 fn try_into(self) -> Result<$ty, crate::diff::PatchError> {
250 match self {
251 ParamData::$variant(value) => Ok((*value).into()),
252 _ => Err(crate::diff::PatchError::InvalidData),
253 }
254 }
255 }
256
257 impl From<Option<$ty>> for ParamData {
258 fn from(value: Option<$ty>) -> Self {
259 if let Some(value) = value {
260 Self::$variant(value.into())
261 } else {
262 Self::None
263 }
264 }
265 }
266
267 impl TryInto<Option<$ty>> for &ParamData {
268 type Error = crate::diff::PatchError;
269
270 fn try_into(self) -> Result<Option<$ty>, crate::diff::PatchError> {
271 match self {
272 ParamData::$variant(value) => Ok(Some((*value).into())),
273 ParamData::None => Ok(None),
274 _ => Err(crate::diff::PatchError::InvalidData),
275 }
276 }
277 }
278
279 impl From<Notify<$ty>> for ParamData {
280 fn from(value: Notify<$ty>) -> Self {
281 Self::$variant((*value).into())
282 }
283 }
284
285 impl TryInto<Notify<$ty>> for &ParamData {
286 type Error = crate::diff::PatchError;
287
288 fn try_into(self) -> Result<Notify<$ty>, crate::diff::PatchError> {
289 match self {
290 ParamData::$variant(value) => Ok(Notify::new((*value).into())),
291 _ => Err(crate::diff::PatchError::InvalidData),
292 }
293 }
294 }
295 };
296}
297
298param_data_from!(Volume, Volume);
299param_data_from!(f32, F32);
300param_data_from!(f64, F64);
301param_data_from!(i32, I32);
302param_data_from!(u32, U32);
303param_data_from!(i64, I64);
304param_data_from!(u64, U64);
305param_data_from!(bool, Bool);
306param_data_from!(Vec2, Vector2D);
307param_data_from!(Vec3, Vector3D);
308#[cfg(feature = "scheduled_events")]
309param_data_from!(EventInstant, EventInstant);
310param_data_from!(InstantSeconds, InstantSeconds);
311param_data_from!(DurationSeconds, DurationSeconds);
312param_data_from!(InstantSamples, InstantSamples);
313param_data_from!(DurationSamples, DurationSamples);
314#[cfg(feature = "musical_transport")]
315param_data_from!(InstantMusical, InstantMusical);
316#[cfg(feature = "musical_transport")]
317param_data_from!(DurationMusical, DurationMusical);
318
319#[cfg(feature = "glam-29")]
320param_data_from!(glam_29::Vec2, Vector2D);
321#[cfg(feature = "glam-29")]
322param_data_from!(glam_29::Vec3, Vector3D);
323
324#[cfg(feature = "glam-30")]
325param_data_from!(glam_30::Vec2, Vector2D);
326#[cfg(feature = "glam-30")]
327param_data_from!(glam_30::Vec3, Vector3D);
328
329#[cfg(feature = "glam-31")]
330param_data_from!(glam_31::Vec2, Vector2D);
331#[cfg(feature = "glam-31")]
332param_data_from!(glam_31::Vec3, Vector3D);
333
334#[cfg(feature = "glam-32")]
335param_data_from!(glam_32::Vec2, Vector2D);
336#[cfg(feature = "glam-32")]
337param_data_from!(glam_32::Vec3, Vector3D);
338
339impl From<()> for ParamData {
340 fn from(_value: ()) -> Self {
341 Self::None
342 }
343}
344
345impl TryInto<()> for &ParamData {
346 type Error = crate::diff::PatchError;
347
348 fn try_into(self) -> Result<(), crate::diff::PatchError> {
349 match self {
350 ParamData::None => Ok(()),
351 _ => Err(crate::diff::PatchError::InvalidData),
352 }
353 }
354}
355
356impl From<Notify<()>> for ParamData {
357 fn from(_value: Notify<()>) -> Self {
358 Self::None
359 }
360}
361
362impl TryInto<Notify<()>> for &ParamData {
363 type Error = crate::diff::PatchError;
364
365 fn try_into(self) -> Result<Notify<()>, crate::diff::PatchError> {
366 match self {
367 ParamData::None => Ok(Notify::new(())),
368 _ => Err(crate::diff::PatchError::InvalidData),
369 }
370 }
371}
372
373#[cfg(feature = "scheduled_events")]
375pub struct ScheduledEventEntry {
376 pub event: NodeEvent,
377 pub is_pre_process: bool,
378}
379
380pub struct ProcEvents<'a> {
382 immediate_event_buffer: &'a mut [Option<NodeEvent>],
383 #[cfg(feature = "scheduled_events")]
384 scheduled_event_arena: &'a mut [Option<ScheduledEventEntry>],
385 indices: &'a mut Vec<ProcEventsIndex>,
386}
387
388impl<'a> ProcEvents<'a> {
389 pub fn new(
390 immediate_event_buffer: &'a mut [Option<NodeEvent>],
391 #[cfg(feature = "scheduled_events")] scheduled_event_arena: &'a mut [Option<
392 ScheduledEventEntry,
393 >],
394 indices: &'a mut Vec<ProcEventsIndex>,
395 ) -> Self {
396 Self {
397 immediate_event_buffer,
398 #[cfg(feature = "scheduled_events")]
399 scheduled_event_arena,
400 indices,
401 }
402 }
403
404 pub fn num_events(&self) -> usize {
405 self.indices.len()
406 }
407
408 pub fn is_empty(&self) -> bool {
409 self.indices.is_empty()
410 }
411
412 pub fn drain<'b>(&'b mut self) -> impl IntoIterator<Item = NodeEventType> + use<'b> {
414 self.indices.drain(..).map(|index_type| match index_type {
415 ProcEventsIndex::Immediate(i) => {
416 self.immediate_event_buffer[i as usize]
417 .take()
418 .unwrap()
419 .event
420 }
421 #[cfg(feature = "scheduled_events")]
422 ProcEventsIndex::Scheduled(i) => {
423 self.scheduled_event_arena[i as usize]
424 .take()
425 .unwrap()
426 .event
427 .event
428 }
429 })
430 }
431
432 #[cfg(feature = "scheduled_events")]
440 pub fn drain_with_timestamps<'b>(
441 &'b mut self,
442 ) -> impl IntoIterator<Item = (NodeEventType, Option<EventInstant>)> + use<'b> {
443 self.indices.drain(..).map(|index_type| match index_type {
444 ProcEventsIndex::Immediate(i) => {
445 let event = self.immediate_event_buffer[i as usize].take().unwrap();
446
447 (event.event, event.time)
448 }
449 ProcEventsIndex::Scheduled(i) => {
450 let event = self.scheduled_event_arena[i as usize].take().unwrap();
451
452 (event.event.event, event.event.time)
453 }
454 })
455 }
456
457 pub fn drain_patches<'b, T: crate::diff::Patch>(
489 &'b mut self,
490 ) -> impl IntoIterator<Item = <T as crate::diff::Patch>::Patch> + use<'b, T> {
491 self.drain().into_iter().filter_map(|e| T::patch_event(&e))
495 }
496
497 #[cfg(feature = "scheduled_events")]
534 pub fn drain_patches_with_timestamps<'b, T: crate::diff::Patch>(
535 &'b mut self,
536 ) -> impl IntoIterator<Item = (<T as crate::diff::Patch>::Patch, Option<EventInstant>)> + use<'b, T>
537 {
538 self.drain_with_timestamps()
542 .into_iter()
543 .filter_map(|(e, timestamp)| T::patch_event(&e).map(|patch| (patch, timestamp)))
544 }
545}
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq)]
549pub enum ProcEventsIndex {
550 Immediate(u32),
551 #[cfg(feature = "scheduled_events")]
552 Scheduled(u32),
553}