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