1use super::{Diff, EventQueue, Patch, PatchError, PathBuilder};
4use crate::{
5 clock::{DurationSamples, DurationSeconds, InstantSamples, InstantSeconds},
6 collector::ArcGc,
7 diff::{Notify, RealtimeClone, notify::NotifyID},
8 dsp::volume::Volume,
9 event::{NodeEventType, ParamData},
10 vector::{Vec2, Vec3},
11};
12
13#[cfg(feature = "scheduled_events")]
14use crate::clock::EventInstant;
15
16#[cfg(feature = "musical_transport")]
17use crate::clock::{DurationMusical, InstantMusical};
18
19impl Diff for () {
20 fn diff<E: EventQueue>(&self, _baseline: &Self, _path: PathBuilder, _event_queue: &mut E) {}
21}
22
23impl Patch for () {
24 type Patch = ();
25
26 fn patch(data: &ParamData, _path: &[u32]) -> Result<Self::Patch, PatchError> {
27 match data {
28 ParamData::None => Ok(()),
29 _ => Err(PatchError::InvalidData),
30 }
31 }
32
33 fn apply(&mut self, _patch: Self::Patch) {}
34}
35
36macro_rules! primitive_diff {
37 ($ty:ty, $variant:ident) => {
38 impl Diff for $ty {
39 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
40 if self != baseline {
41 event_queue.push_param(*self, path);
42 }
43 }
44 }
45
46 impl Patch for $ty {
47 type Patch = Self;
48
49 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
50 match data {
51 ParamData::$variant(value) => Ok((*value).into()),
52 _ => Err(PatchError::InvalidData),
53 }
54 }
55
56 fn apply(&mut self, value: Self::Patch) {
57 *self = value;
58 }
59 }
60
61 impl Diff for Option<$ty> {
62 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
63 if self != baseline {
64 event_queue.push_param(*self, path);
65 }
66 }
67 }
68
69 impl Patch for Option<$ty> {
70 type Patch = Self;
71
72 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
73 match data {
74 ParamData::$variant(value) => Ok(Some((*value).into())),
75 ParamData::None => Ok(None),
76 _ => Err(PatchError::InvalidData),
77 }
78 }
79
80 fn apply(&mut self, value: Self::Patch) {
81 *self = value;
82 }
83 }
84 };
85
86 ($ty:ty, $cast:ty, $variant:ident) => {
87 impl Diff for $ty {
88 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
89 if self != baseline {
90 event_queue.push_param(*self as $cast, path);
91 }
92 }
93 }
94
95 impl Patch for $ty {
96 type Patch = Self;
97
98 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
99 match data {
100 ParamData::$variant(value) => Ok(value.clone() as $ty),
101 _ => Err(PatchError::InvalidData),
102 }
103 }
104
105 fn apply(&mut self, value: Self::Patch) {
106 *self = value;
107 }
108 }
109
110 impl Diff for Option<$ty> {
111 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
112 if self != baseline {
113 event_queue.push_param(self.map(|v| v as $cast), path);
114 }
115 }
116 }
117
118 impl Patch for Option<$ty> {
119 type Patch = Self;
120
121 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
122 match data {
123 ParamData::$variant(value) => Ok(Some(value.clone() as $ty)),
124 ParamData::None => Ok(None),
125 _ => Err(PatchError::InvalidData),
126 }
127 }
128
129 fn apply(&mut self, value: Self::Patch) {
130 *self = value;
131 }
132 }
133 };
134}
135
136primitive_diff!(bool, Bool);
137primitive_diff!(u8, u32, U32);
138primitive_diff!(u16, u32, U32);
139primitive_diff!(u32, U32);
140primitive_diff!(u64, U64);
141primitive_diff!(i8, i32, I32);
142primitive_diff!(i16, i32, I32);
143primitive_diff!(i32, I32);
144primitive_diff!(i64, I64);
145primitive_diff!(usize, u64, U64);
146primitive_diff!(isize, i64, I64);
147primitive_diff!(f32, F32);
148primitive_diff!(f64, F64);
149primitive_diff!(Volume, Volume);
150primitive_diff!(InstantSamples, InstantSamples);
151primitive_diff!(DurationSamples, DurationSamples);
152primitive_diff!(InstantSeconds, InstantSeconds);
153primitive_diff!(DurationSeconds, DurationSeconds);
154
155#[cfg(feature = "scheduled_events")]
156primitive_diff!(EventInstant, EventInstant);
157
158#[cfg(feature = "musical_transport")]
159primitive_diff!(InstantMusical, InstantMusical);
160#[cfg(feature = "musical_transport")]
161primitive_diff!(DurationMusical, DurationMusical);
162
163primitive_diff!(Vec2, Vector2D);
164primitive_diff!(Vec3, Vector3D);
165
166#[cfg(feature = "glam-29")]
167primitive_diff!(glam_29::Vec2, Vector2D);
168#[cfg(feature = "glam-29")]
169primitive_diff!(glam_29::Vec3, Vector3D);
170
171#[cfg(feature = "glam-30")]
172primitive_diff!(glam_30::Vec2, Vector2D);
173#[cfg(feature = "glam-30")]
174primitive_diff!(glam_30::Vec3, Vector3D);
175
176#[cfg(feature = "glam-31")]
177primitive_diff!(glam_31::Vec2, Vector2D);
178#[cfg(feature = "glam-31")]
179primitive_diff!(glam_31::Vec3, Vector3D);
180
181#[cfg(feature = "glam-32")]
182primitive_diff!(glam_32::Vec2, Vector2D);
183#[cfg(feature = "glam-32")]
184primitive_diff!(glam_32::Vec3, Vector3D);
185
186impl<A: ?Sized + Send + Sync + 'static> Diff for ArcGc<A> {
187 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
188 if !ArcGc::ptr_eq(self, baseline) {
189 event_queue.push(NodeEventType::Param {
190 data: ParamData::any(self.clone()),
191 path: path.build(),
192 });
193 }
194 }
195}
196
197impl<A: ?Sized + Send + Sync + 'static> Patch for ArcGc<A> {
198 type Patch = Self;
199
200 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
201 if let ParamData::Any(any) = data
202 && let Some(data) = any.downcast_ref::<Self>()
203 {
204 return Ok(data.clone());
205 }
206
207 Err(PatchError::InvalidData)
208 }
209
210 fn apply(&mut self, patch: Self::Patch) {
211 *self = patch;
212 }
213}
214
215impl<T: Send + Sync + RealtimeClone + PartialEq + 'static> Diff for Option<T> {
216 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
217 if self != baseline {
218 event_queue.push_param(ParamData::opt_any(self.clone()), path);
219 }
220 }
221}
222
223impl<T: Send + Sync + RealtimeClone + PartialEq + 'static> Patch for Option<T> {
224 type Patch = Self;
225
226 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
227 Ok(data.downcast_ref::<T>().cloned())
228 }
229
230 fn apply(&mut self, patch: Self::Patch) {
231 *self = patch;
232 }
233}
234
235impl Diff for Notify<()> {
238 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
239 if self != baseline {
240 event_queue.push_param(ParamData::U64(self.id().0), path);
241 }
242 }
243}
244
245impl Patch for Notify<()> {
246 type Patch = Self;
247
248 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
249 match data {
250 ParamData::U64(id) => Ok(Notify::from_raw((), NotifyID(*id))),
251 _ => Err(PatchError::InvalidData),
252 }
253 }
254
255 fn apply(&mut self, value: Self::Patch) {
256 *self = value;
257 }
258}
259
260impl Diff for Notify<bool> {
261 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
262 if self != baseline {
263 let mut bytes: [u8; 20] = [0; 20];
264 bytes[0..size_of::<u64>()].copy_from_slice(&self.id().0.to_ne_bytes());
265 bytes[size_of::<u64>()] = if **self { 1 } else { 0 };
266
267 event_queue.push_param(ParamData::CustomBytes(bytes), path);
268 }
269 }
270}
271
272impl Patch for Notify<bool> {
273 type Patch = Self;
274
275 fn patch(data: &ParamData, _path: &[u32]) -> Result<Self::Patch, PatchError> {
276 match data {
277 ParamData::CustomBytes(bytes) => {
278 let (id_bytes, rest_bytes) = bytes.split_at(size_of::<u64>());
279 let id = u64::from_ne_bytes(id_bytes.try_into().unwrap());
280
281 let value = rest_bytes[0] != 0;
282
283 Ok(Notify::from_raw(value, NotifyID(id)))
284 }
285 _ => Err(PatchError::InvalidData),
286 }
287 }
288
289 fn apply(&mut self, value: Self::Patch) {
290 *self = value;
291 }
292}
293
294macro_rules! trivial_notify {
295 ($ty:path) => {
296 impl Diff for Notify<$ty> {
297 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
298 if self != baseline {
299 let mut bytes: [u8; 20] = [0; 20];
300 bytes[0..8].copy_from_slice(&self.id().0.to_ne_bytes());
301 let value_bytes = self.to_ne_bytes();
302 bytes[8..8 + value_bytes.len()].copy_from_slice(&value_bytes);
303
304 event_queue.push_param(ParamData::CustomBytes(bytes), path);
305 }
306 }
307 }
308
309 impl Patch for Notify<$ty> {
310 type Patch = Self;
311
312 fn patch(data: &ParamData, _path: &[u32]) -> Result<Self::Patch, PatchError> {
313 match data {
314 ParamData::CustomBytes(bytes) => {
315 let (id_bytes, rest_bytes) = bytes.split_at(size_of::<u64>());
316 let id = u64::from_ne_bytes(id_bytes.try_into().unwrap());
317
318 let (value_bytes, _) = rest_bytes.split_at(size_of::<$ty>());
319 let value = <$ty>::from_ne_bytes(value_bytes.try_into().unwrap());
320
321 Ok(Notify::from_raw(value, NotifyID(id)))
322 }
323 _ => Err(PatchError::InvalidData),
324 }
325 }
326
327 fn apply(&mut self, value: Self::Patch) {
328 *self = value;
329 }
330 }
331 };
332}
333
334macro_rules! non_trivial_notify {
335 ($ty:path) => {
336 impl Diff for Notify<$ty> {
337 fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
338 if self != baseline {
339 event_queue.push_param(ParamData::any(self.clone()), path);
340 }
341 }
342 }
343
344 impl Patch for Notify<$ty> {
345 type Patch = Self;
346
347 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
348 data.downcast_ref()
349 .ok_or(super::PatchError::InvalidData)
350 .cloned()
351 }
352
353 fn apply(&mut self, value: Self::Patch) {
354 *self = value;
355 }
356 }
357 };
358}
359
360trivial_notify!(i8);
361trivial_notify!(u8);
362trivial_notify!(i16);
363trivial_notify!(u16);
364trivial_notify!(i32);
365trivial_notify!(u32);
366trivial_notify!(i64);
367trivial_notify!(u64);
368trivial_notify!(f32);
369trivial_notify!(f64);
370
371non_trivial_notify!(Volume);
373non_trivial_notify!(InstantSamples);
374non_trivial_notify!(DurationSamples);
375non_trivial_notify!(InstantSeconds);
376non_trivial_notify!(DurationSeconds);
377
378#[cfg(feature = "musical_transport")]
379non_trivial_notify!(InstantMusical);
380#[cfg(feature = "musical_transport")]
381non_trivial_notify!(DurationMusical);
382
383non_trivial_notify!(Vec2);
384non_trivial_notify!(Vec3);
385
386#[cfg(feature = "glam-29")]
387non_trivial_notify!(glam_29::Vec2);
388#[cfg(feature = "glam-29")]
389non_trivial_notify!(glam_29::Vec3);
390
391#[cfg(feature = "glam-30")]
392non_trivial_notify!(glam_30::Vec2);
393#[cfg(feature = "glam-30")]
394non_trivial_notify!(glam_30::Vec3);
395
396#[cfg(feature = "glam-31")]
397non_trivial_notify!(glam_31::Vec2);
398#[cfg(feature = "glam-31")]
399non_trivial_notify!(glam_31::Vec3);
400
401#[cfg(feature = "glam-32")]
402non_trivial_notify!(glam_32::Vec2);
403#[cfg(feature = "glam-32")]
404non_trivial_notify!(glam_32::Vec3);