1use super::*;
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq)]
12pub enum ClockRate {
13 R32000,
15 R44100,
17 R48000,
19 R88200,
21 R96000,
23 R176400,
25 R192000,
27 AnyLow,
29 AnyMid,
31 AnyHigh,
33 None,
35 Reserved(u8),
37}
38
39impl ClockRate {
40 const R32000_VAL: u8 = 0x00;
41 const R44100_VAL: u8 = 0x01;
42 const R48000_VAL: u8 = 0x02;
43 const R88200_VAL: u8 = 0x03;
44 const R96000_VAL: u8 = 0x04;
45 const R176400_VAL: u8 = 0x05;
46 const R192000_VAL: u8 = 0x06;
47 const ANY_LOW_VAL: u8 = 0x07;
48 const ANY_MID_VAL: u8 = 0x08;
49 const ANY_HIGH_VAL: u8 = 0x09;
50 const NONE_VAL: u8 = 0x0a;
51}
52
53impl Default for ClockRate {
54 fn default() -> Self {
55 ClockRate::Reserved(0xff)
56 }
57}
58
59pub(crate) fn serialize_clock_rate(rate: &ClockRate, val: &mut u8) -> Result<(), String> {
60 *val = match *rate {
61 ClockRate::R32000 => ClockRate::R32000_VAL,
62 ClockRate::R44100 => ClockRate::R44100_VAL,
63 ClockRate::R48000 => ClockRate::R48000_VAL,
64 ClockRate::R88200 => ClockRate::R88200_VAL,
65 ClockRate::R96000 => ClockRate::R96000_VAL,
66 ClockRate::R176400 => ClockRate::R176400_VAL,
67 ClockRate::R192000 => ClockRate::R192000_VAL,
68 ClockRate::AnyLow => ClockRate::ANY_LOW_VAL,
69 ClockRate::AnyMid => ClockRate::ANY_MID_VAL,
70 ClockRate::AnyHigh => ClockRate::ANY_HIGH_VAL,
71 ClockRate::None => ClockRate::NONE_VAL,
72 ClockRate::Reserved(val) => val,
73 };
74
75 Ok(())
76}
77
78pub(crate) fn deserialize_clock_rate(rate: &mut ClockRate, val: &u8) -> Result<(), String> {
79 *rate = match *val {
80 ClockRate::R32000_VAL => ClockRate::R32000,
81 ClockRate::R44100_VAL => ClockRate::R44100,
82 ClockRate::R48000_VAL => ClockRate::R48000,
83 ClockRate::R88200_VAL => ClockRate::R88200,
84 ClockRate::R96000_VAL => ClockRate::R96000,
85 ClockRate::R176400_VAL => ClockRate::R176400,
86 ClockRate::R192000_VAL => ClockRate::R192000,
87 ClockRate::ANY_LOW_VAL => ClockRate::AnyLow,
88 ClockRate::ANY_MID_VAL => ClockRate::AnyMid,
89 ClockRate::ANY_HIGH_VAL => ClockRate::AnyHigh,
90 ClockRate::NONE_VAL => ClockRate::None,
91 _ => ClockRate::Reserved(*val),
92 };
93
94 Ok(())
95}
96
97#[derive(Debug, Copy, Clone, PartialEq, Eq)]
99pub enum ClockSource {
100 Aes1,
102 Aes2,
104 Aes3,
106 Aes4,
108 AesAny,
110 Adat,
112 Tdif,
114 WordClock,
116 Arx1,
118 Arx2,
120 Arx3,
122 Arx4,
124 Internal,
126 Reserved(u8),
128}
129
130impl Default for ClockSource {
131 fn default() -> Self {
132 ClockSource::Reserved(0xff)
133 }
134}
135
136impl ClockSource {
137 const AES1_VAL: u8 = 0x00;
138 const AES2_VAL: u8 = 0x01;
139 const AES3_VAL: u8 = 0x02;
140 const AES4_VAL: u8 = 0x03;
141 const AES_ANY_VAL: u8 = 0x04;
142 const ADAT_VAL: u8 = 0x05;
143 const TDIF_VAL: u8 = 0x06;
144 const WORD_CLOCK_VAL: u8 = 0x07;
145 const ARX1_VAL: u8 = 0x08;
146 const ARX2_VAL: u8 = 0x09;
147 const ARX3_VAL: u8 = 0x0a;
148 const ARX4_VAL: u8 = 0x0b;
149 const INTERNAL_VAL: u8 = 0x0c;
150}
151
152pub(crate) fn serialize_clock_source(src: &ClockSource, val: &mut u8) -> Result<(), String> {
153 *val = match *src {
154 ClockSource::Aes1 => ClockSource::AES1_VAL,
155 ClockSource::Aes2 => ClockSource::AES2_VAL,
156 ClockSource::Aes3 => ClockSource::AES3_VAL,
157 ClockSource::Aes4 => ClockSource::AES4_VAL,
158 ClockSource::AesAny => ClockSource::AES_ANY_VAL,
159 ClockSource::Adat => ClockSource::ADAT_VAL,
160 ClockSource::Tdif => ClockSource::TDIF_VAL,
161 ClockSource::WordClock => ClockSource::WORD_CLOCK_VAL,
162 ClockSource::Arx1 => ClockSource::ARX1_VAL,
163 ClockSource::Arx2 => ClockSource::ARX2_VAL,
164 ClockSource::Arx3 => ClockSource::ARX3_VAL,
165 ClockSource::Arx4 => ClockSource::ARX4_VAL,
166 ClockSource::Internal => ClockSource::INTERNAL_VAL,
167 ClockSource::Reserved(src_val) => src_val,
168 };
169
170 Ok(())
171}
172
173pub(crate) fn deserialize_clock_source(src: &mut ClockSource, val: &u8) -> Result<(), String> {
174 *src = match *val {
175 ClockSource::AES1_VAL => ClockSource::Aes1,
176 ClockSource::AES2_VAL => ClockSource::Aes2,
177 ClockSource::AES3_VAL => ClockSource::Aes3,
178 ClockSource::AES4_VAL => ClockSource::Aes4,
179 ClockSource::AES_ANY_VAL => ClockSource::AesAny,
180 ClockSource::ADAT_VAL => ClockSource::Adat,
181 ClockSource::TDIF_VAL => ClockSource::Tdif,
182 ClockSource::WORD_CLOCK_VAL => ClockSource::WordClock,
183 ClockSource::ARX1_VAL => ClockSource::Arx1,
184 ClockSource::ARX2_VAL => ClockSource::Arx2,
185 ClockSource::ARX3_VAL => ClockSource::Arx3,
186 ClockSource::ARX4_VAL => ClockSource::Arx4,
187 ClockSource::INTERNAL_VAL => ClockSource::Internal,
188 _ => ClockSource::Reserved(*val),
189 };
190 Ok(())
191}
192
193#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
195pub struct ClockConfig {
196 pub rate: ClockRate,
198 pub src: ClockSource,
200}
201
202impl ClockConfig {
203 const SIZE: usize = 4;
204
205 const SRC_MASK: u32 = 0x000000ff;
206 const SRC_SHIFT: usize = 0;
207 const RATE_MASK: u32 = 0x0000ff00;
208 const RATE_SHIFT: usize = 8;
209}
210
211fn serialize_clock_config(config: &ClockConfig, raw: &mut [u8]) -> Result<(), String> {
212 assert!(raw.len() >= ClockConfig::SIZE);
213
214 let mut src_val = 0u8;
215 serialize_clock_source(&config.src, &mut src_val)?;
216
217 let mut rate_val = 0u8;
218 serialize_clock_rate(&config.rate, &mut rate_val)?;
219
220 let val = (((rate_val as u32) << ClockConfig::RATE_SHIFT) & ClockConfig::RATE_MASK)
221 | (((src_val as u32) << ClockConfig::SRC_SHIFT) & ClockConfig::SRC_MASK);
222
223 serialize_u32(&val, raw);
224
225 Ok(())
226}
227
228fn deserialize_clock_config(config: &mut ClockConfig, raw: &[u8]) -> Result<(), String> {
229 assert!(raw.len() >= ClockConfig::SIZE);
230
231 let mut val = 0u32;
232 deserialize_u32(&mut val, raw);
233
234 let src_val = ((val & ClockConfig::SRC_MASK) >> ClockConfig::SRC_SHIFT) as u8;
235 let rate_val = ((val & ClockConfig::RATE_MASK) >> ClockConfig::RATE_SHIFT) as u8;
236
237 deserialize_clock_source(&mut config.src, &src_val)?;
238 deserialize_clock_rate(&mut config.rate, &rate_val)?;
239
240 Ok(())
241}
242
243#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
245pub struct ClockStatus {
246 pub src_is_locked: bool,
248 pub rate: ClockRate,
250}
251
252impl ClockStatus {
253 const SIZE: usize = 4;
254
255 const SRC_LOCKED: u32 = 0x00000001;
256 const RATE_MASK: u32 = 0x0000ff00;
257 const RATE_SHIFT: usize = 8;
258}
259
260fn serialize_clock_status(status: &ClockStatus, raw: &mut [u8]) -> Result<(), String> {
261 assert!(raw.len() >= ClockStatus::SIZE);
262
263 let mut val = 0u32;
264 if status.src_is_locked {
265 val |= ClockStatus::SRC_LOCKED;
266 }
267
268 let mut rate_bit = 0u8;
269 serialize_clock_rate(&status.rate, &mut rate_bit)?;
270 val |= ((rate_bit as u32) << ClockStatus::RATE_SHIFT) & ClockStatus::RATE_MASK;
271
272 serialize_u32(&val, raw);
273
274 Ok(())
275}
276
277fn deserialize_clock_status(status: &mut ClockStatus, raw: &[u8]) -> Result<(), String> {
278 assert!(raw.len() >= ClockStatus::SIZE);
279
280 let mut val = 0u32;
281 deserialize_u32(&mut val, raw);
282
283 status.src_is_locked = (val & ClockStatus::SRC_LOCKED) > 0;
284
285 let rate_val = ((val & ClockStatus::RATE_MASK) >> ClockStatus::RATE_SHIFT) as u8;
286 deserialize_clock_rate(&mut status.rate, &rate_val)?;
287
288 Ok(())
289}
290
291#[derive(Default, Debug, Clone, PartialEq, Eq)]
293pub struct ExternalSourceStates {
294 pub sources: Vec<ClockSource>,
296 pub locked: Vec<bool>,
298 pub slipped: Vec<bool>,
301}
302
303#[derive(Default, Debug, Clone, PartialEq, Eq)]
305pub struct GlobalParameters {
306 pub owner: u64,
308 pub latest_notification: u32,
310 pub nickname: String,
313 pub clock_config: ClockConfig,
315 pub enable: bool,
317 pub clock_status: ClockStatus,
319 pub external_source_states: ExternalSourceStates,
321 pub current_rate: u32,
323 pub version: u32,
325 pub avail_rates: Vec<ClockRate>,
327 pub avail_sources: Vec<ClockSource>,
329 pub clock_source_labels: Vec<(ClockSource, String)>,
331}
332
333pub trait TcatGlobalSectionSpecification {
335 const AVAILABLE_CLOCK_SOURCE_OVERRIDE: Option<&'static [ClockSource]> = None;
337
338 const CLOCK_SOURCE_LABEL_TABLE: &'static [ClockSource] = &[
341 ClockSource::Aes1,
342 ClockSource::Aes2,
343 ClockSource::Aes3,
344 ClockSource::Aes4,
345 ClockSource::AesAny,
346 ClockSource::Adat,
347 ClockSource::Tdif,
348 ClockSource::WordClock,
349 ClockSource::Arx1,
350 ClockSource::Arx2,
351 ClockSource::Arx3,
352 ClockSource::Arx4,
353 ClockSource::Internal,
354 ];
355}
356
357const CLOCK_SOURCE_STREAM_LABEL_TABLE: [(ClockSource, &'static str); 4] = [
358 (ClockSource::Arx1, "Stream-1"),
359 (ClockSource::Arx2, "Stream-2"),
360 (ClockSource::Arx3, "Stream-3"),
361 (ClockSource::Arx4, "Stream-4"),
362];
363
364const CLOCK_CAPS_RATE_TABLE: [ClockRate; 11] = [
365 ClockRate::R32000,
366 ClockRate::R44100,
367 ClockRate::R48000,
368 ClockRate::R88200,
369 ClockRate::R96000,
370 ClockRate::R176400,
371 ClockRate::R192000,
372 ClockRate::AnyLow,
373 ClockRate::AnyMid,
374 ClockRate::AnyHigh,
375 ClockRate::None,
376];
377
378const CLOCK_CAPS_SRC_TABLE: [ClockSource; 13] = [
379 ClockSource::Aes1,
380 ClockSource::Aes2,
381 ClockSource::Aes3,
382 ClockSource::Aes4,
383 ClockSource::AesAny,
384 ClockSource::Adat,
385 ClockSource::Tdif,
386 ClockSource::WordClock,
387 ClockSource::Arx1,
388 ClockSource::Arx2,
389 ClockSource::Arx3,
390 ClockSource::Arx4,
391 ClockSource::Internal,
392];
393
394const EXTERNAL_CLOCK_SOURCE_TABLE: [ClockSource; 11] = [
395 ClockSource::Aes1,
396 ClockSource::Aes2,
397 ClockSource::Aes3,
398 ClockSource::Aes4,
399 ClockSource::Adat,
400 ClockSource::Tdif,
401 ClockSource::Arx1,
402 ClockSource::Arx2,
403 ClockSource::Arx3,
404 ClockSource::Arx4,
405 ClockSource::WordClock,
406];
407
408impl<O: TcatOperation + TcatGlobalSectionSpecification> TcatSectionSerdes<GlobalParameters> for O {
409 const MIN_SIZE: usize = 96;
410
411 const ERROR_TYPE: GeneralProtocolError = GeneralProtocolError::Global;
412
413 fn serialize(params: &GlobalParameters, raw: &mut [u8]) -> Result<(), String> {
414 let val = ((params.owner & 0xffffffff00000000) >> 32) as u32;
415 serialize_u32(&val, &mut raw[..4]);
416 let val = (params.owner & 0x00000000ffffffff) as u32;
417 serialize_u32(&val, &mut raw[4..8]);
418
419 serialize_u32(¶ms.latest_notification, &mut raw[8..12]);
420
421 raw[12..76].fill(0x00);
422 serialize_label(¶ms.nickname, &mut raw[12..76])?;
423
424 serialize_clock_config(¶ms.clock_config, &mut raw[76..80])?;
425
426 serialize_bool(¶ms.enable, &mut raw[80..84]);
427
428 serialize_clock_status(¶ms.clock_status, &mut raw[84..88])?;
429
430 let mut locked_bits = 0u32;
431 let mut slipped_bits = 0u32;
432 params
433 .external_source_states
434 .sources
435 .iter()
436 .zip(¶ms.external_source_states.locked)
437 .zip(¶ms.external_source_states.slipped)
438 .for_each(|((source, &locked), &slipped)| {
439 EXTERNAL_CLOCK_SOURCE_TABLE
440 .iter()
441 .enumerate()
442 .find(|(_, s)| source.eq(s))
443 .map(|(i, _)| {
444 if locked {
445 locked_bits |= 1 << i;
446 }
447 if slipped {
448 slipped_bits |= 1 << i;
449 }
450 });
451 });
452 let val = (slipped_bits << 16) | locked_bits;
453 serialize_u32(&val, &mut raw[88..92]);
454
455 serialize_u32(¶ms.current_rate, &mut raw[92..96]);
456
457 if raw.len() > 96 {
458 serialize_u32(¶ms.version, &mut raw[96..100]);
459
460 let mut rate_bits = 0u32;
461 params.avail_rates.iter().for_each(|avail_rate| {
462 CLOCK_CAPS_RATE_TABLE
463 .iter()
464 .enumerate()
465 .find(|(_, r)| avail_rate.eq(r))
466 .map(|(i, _)| rate_bits |= 1 << i);
467 });
468
469 let mut src_bits = 0u32;
470 params.avail_sources.iter().for_each(|avail_source| {
471 CLOCK_CAPS_SRC_TABLE
472 .iter()
473 .enumerate()
474 .find(|(_, s)| avail_source.eq(s))
475 .map(|(i, _)| src_bits |= 1 << i);
476 });
477 let val = (src_bits << 16) | rate_bits;
478 serialize_u32(&val, &mut raw[100..104]);
479
480 let labels: Vec<&str> = Self::CLOCK_SOURCE_LABEL_TABLE
481 .iter()
482 .map(|source| {
483 params
484 .clock_source_labels
485 .iter()
486 .find(|(s, _)| source.eq(s))
487 .map(|(_, l)| l.as_str())
488 .unwrap_or("unused")
489 })
490 .collect();
491 serialize_labels(&labels, &mut raw[104..360])?;
492 }
493
494 Ok(())
495 }
496
497 fn deserialize(params: &mut GlobalParameters, raw: &[u8]) -> Result<(), String> {
498 let mut val = 0u32;
499
500 let (version, avail_rates, avail_srcs, src_labels) = if raw.len() > 96 {
503 let mut labels = Vec::new();
504 deserialize_labels(&mut labels, &raw[104..360])?;
505
506 let mut labels: Vec<(ClockSource, String)> = Self::CLOCK_SOURCE_LABEL_TABLE
507 .iter()
508 .cloned()
509 .zip(labels.into_iter())
510 .collect();
511
512 deserialize_u32(&mut val, &raw[100..104]);
513 let rate_bits = (val & 0x0000ffff) as u16;
514 let src_bits = ((val & 0xffff0000) >> 16) as u16;
515
516 let avail_rates = CLOCK_CAPS_RATE_TABLE
517 .iter()
518 .enumerate()
519 .filter(|(i, _)| rate_bits & (1 << i) > 0)
520 .map(|(_, &r)| r)
521 .collect();
522
523 labels
527 .iter_mut()
528 .filter(|(src, _)| {
529 CLOCK_CAPS_SRC_TABLE
530 .iter()
531 .enumerate()
532 .find(|(i, s)| src.eq(s) && (src_bits & (1 << i)) > 0)
533 .is_some()
534 })
535 .for_each(|(src, label)| {
536 CLOCK_SOURCE_STREAM_LABEL_TABLE
537 .iter()
538 .find(|(s, _)| src.eq(&s))
539 .map(|(_, l)| *label = l.to_string());
540 });
541
542 let avail_srcs = if let Some(table) = Self::AVAILABLE_CLOCK_SOURCE_OVERRIDE {
545 table.to_vec()
546 } else {
547 CLOCK_CAPS_SRC_TABLE
548 .iter()
549 .enumerate()
550 .filter(|(i, _)| src_bits & (1 << i) > 0)
551 .filter(|(_, src)| {
552 CLOCK_SOURCE_STREAM_LABEL_TABLE
555 .iter()
556 .find(|(s, _)| src.eq(&s))
557 .is_none()
558 })
559 .filter(|(_, src)| {
560 labels
561 .iter()
562 .filter(|(_, label)| label.to_lowercase() != "unused")
563 .find(|(s, _)| s.eq(&src))
564 .is_some()
565 })
566 .map(|(_, &src)| src)
567 .collect()
568 };
569
570 labels.retain(|(src, label)| {
571 label.to_lowercase() != "unused"
572 && (CLOCK_SOURCE_STREAM_LABEL_TABLE
573 .iter()
574 .find(|(s, _)| src.eq(&s))
575 .is_some()
576 || avail_srcs.iter().find(|s| src.eq(s)).is_some())
577 });
578
579 deserialize_u32(&mut val, &raw[96..100]);
580 let version = val;
581
582 (version, avail_rates, avail_srcs, labels)
583 } else {
584 let src_labels = vec![
585 (ClockSource::Arx1, "Stream-1".to_string()),
586 (ClockSource::Internal, "internal".to_string()),
587 ];
588 let avail_rates = vec![ClockRate::R44100, ClockRate::R48000];
589 let avail_srcs = vec![ClockSource::Internal];
590 let version = 0;
591
592 (version, avail_rates, avail_srcs, src_labels)
593 };
594
595 deserialize_u32(&mut val, &raw[..4]);
596 params.owner = (val as u64) << 32;
597 deserialize_u32(&mut val, &raw[4..8]);
598 params.owner |= val as u64;
599
600 deserialize_u32(&mut params.latest_notification, &raw[8..12]);
601
602 deserialize_label(&mut params.nickname, &raw[12..76])?;
603
604 deserialize_clock_config(&mut params.clock_config, &raw[76..80])?;
605
606 deserialize_bool(&mut params.enable, &raw[80..84]);
607
608 deserialize_clock_status(&mut params.clock_status, &raw[84..88])?;
609
610 deserialize_u32(&mut val, &raw[88..92]);
611 let locked_bits = (val & 0x0000ffff) as u16;
612 let slipped_bits = ((val & 0xffff0000) >> 16) as u16;
613
614 let srcs: Vec<ClockSource> = EXTERNAL_CLOCK_SOURCE_TABLE
615 .iter()
616 .filter(|src| src_labels.iter().find(|(s, _)| src.eq(&s)).is_some())
617 .copied()
618 .collect();
619 let locked: Vec<bool> = EXTERNAL_CLOCK_SOURCE_TABLE
620 .iter()
621 .enumerate()
622 .filter(|(_, src)| srcs.iter().find(|s| src.eq(s)).is_some())
623 .map(|(i, _)| locked_bits & (1 << i) > 0)
624 .collect();
625 let slipped: Vec<bool> = EXTERNAL_CLOCK_SOURCE_TABLE
626 .iter()
627 .enumerate()
628 .filter(|(_, src)| srcs.iter().find(|s| src.eq(s)).is_some())
629 .map(|(i, _)| slipped_bits & (1 << i) > 0)
630 .collect();
631
632 params.external_source_states.sources = srcs;
633 params.external_source_states.locked = locked;
634 params.external_source_states.slipped = slipped;
635
636 deserialize_u32(&mut params.current_rate, &raw[92..96]);
637
638 params.version = version;
639 params.avail_rates = avail_rates;
640 params.avail_sources = avail_srcs;
641 params.clock_source_labels = src_labels;
642
643 Ok(())
644 }
645}
646
647impl<O: TcatOperation + TcatSectionSerdes<GlobalParameters>> TcatSectionOperation<GlobalParameters>
648 for O
649{
650}
651
652impl<O: TcatOperation + TcatSectionSerdes<GlobalParameters>>
653 TcatMutableSectionOperation<GlobalParameters> for O
654{
655}
656
657impl<O: TcatSectionOperation<GlobalParameters>> TcatNotifiedSectionOperation<GlobalParameters>
658 for O
659{
660 const NOTIFY_FLAG: u32 = NOTIFY_LOCK_CHG | NOTIFY_CLOCK_ACCEPTED | NOTIFY_EXT_STATUS;
661}
662
663impl<O: TcatSectionOperation<GlobalParameters>> TcatFluctuatedSectionOperation<GlobalParameters>
664 for O
665{
666 const FLUCTUATED_OFFSETS: &'static [usize] = &[
667 88, ];
669}
670
671pub const NICKNAME_MAX_SIZE: usize = 64;
673
674#[cfg(test)]
675mod test {
676 use super::*;
677
678 struct Protocol;
679
680 impl TcatOperation for Protocol {}
681
682 impl TcatGlobalSectionSpecification for Protocol {}
683
684 #[test]
685 fn global_params_serdes() {
686 let raw = [
687 0xff, 0xc1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x6b, 0x73,
688 0x65, 0x44, 0x4b, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x6e, 0x6f, 0x00, 0x36, 0x74, 0x6b,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x01, 0x00,
694 0x04, 0x00, 0x13, 0x00, 0x00, 0x7e, 0x73, 0x75, 0x6e, 0x55, 0x55, 0x5c, 0x64, 0x65,
695 0x65, 0x73, 0x75, 0x6e, 0x6e, 0x55, 0x5c, 0x64, 0x64, 0x65, 0x73, 0x75, 0x75, 0x6e,
696 0x55, 0x5c, 0x5c, 0x64, 0x65, 0x73, 0x73, 0x75, 0x6e, 0x55, 0x55, 0x5c, 0x64, 0x65,
697 0x65, 0x73, 0x75, 0x6e, 0x6e, 0x55, 0x5c, 0x64, 0x64, 0x65, 0x73, 0x75, 0x75, 0x6e,
698 0x55, 0x5c, 0x5c, 0x64, 0x65, 0x73, 0x73, 0x75, 0x6e, 0x55, 0x55, 0x5c, 0x64, 0x65,
699 0x65, 0x73, 0x75, 0x6e, 0x6e, 0x55, 0x5c, 0x64, 0x64, 0x65, 0x73, 0x75, 0x75, 0x6e,
700 0x55, 0x5c, 0x5c, 0x64, 0x65, 0x73, 0x45, 0x54, 0x4e, 0x49, 0x4c, 0x41, 0x4e, 0x52,
701 0x00, 0x00, 0x5c, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 ];
714 let mut params = GlobalParameters::default();
715 Protocol::deserialize(&mut params, &raw).unwrap();
716
717 assert_eq!(params.owner, 0xffc1000100000000);
718 assert_eq!(params.latest_notification, 0x00000010);
719 assert_eq!(params.nickname, "DesktopKonnekt6");
720 assert_eq!(
721 params.clock_config,
722 ClockConfig {
723 rate: ClockRate::R48000,
724 src: ClockSource::Internal
725 }
726 );
727 assert_eq!(params.enable, false);
728 assert_eq!(
729 params.clock_status,
730 ClockStatus {
731 src_is_locked: true,
732 rate: ClockRate::R48000
733 }
734 );
735 assert_eq!(
736 params.external_source_states,
737 ExternalSourceStates {
738 sources: vec![ClockSource::Arx1, ClockSource::Arx2],
739 locked: vec![false, false],
740 slipped: vec![false, false],
741 }
742 );
743 assert_eq!(params.current_rate, 48000);
744 assert_eq!(params.version, 0x01000400);
745 assert_eq!(
746 params.avail_rates,
747 vec![
748 ClockRate::R44100,
749 ClockRate::R48000,
750 ClockRate::R88200,
751 ClockRate::R96000,
752 ClockRate::R176400,
753 ClockRate::R192000
754 ]
755 );
756 assert_eq!(params.avail_sources, vec![ClockSource::Internal]);
757 assert_eq!(
758 params.clock_source_labels,
759 vec![
760 (ClockSource::Arx1, "Stream-1".to_string()),
761 (ClockSource::Arx2, "Stream-2".to_string()),
762 (ClockSource::Internal, "INTERNAL".to_string()),
763 ]
764 );
765
766 let mut r = vec![0u8; raw.len()];
767 Protocol::serialize(¶ms, &mut r).unwrap();
768
769 assert_eq!(r[..100], raw[..100]);
771 }
772
773 #[test]
774 fn global_old_params_serdes() {
775 let raw = [
776 0xff, 0xc1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x73, 0x65,
777 0x6c, 0x41, 0x4d, 0x20, 0x73, 0x69, 0x69, 0x74, 0x6c, 0x75, 0x00, 0x78, 0x69, 0x4d,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80,
783 ];
784 let mut params = GlobalParameters::default();
785 Protocol::deserialize(&mut params, &raw).unwrap();
786
787 assert_eq!(params.owner, 0xffc1000100000000);
788 assert_eq!(params.latest_notification, 0x00000020);
789 assert_eq!(params.nickname, "Alesis MultiMix");
790 assert_eq!(
791 params.clock_config,
792 ClockConfig {
793 rate: ClockRate::R48000,
794 src: ClockSource::Internal
795 }
796 );
797 assert_eq!(params.enable, false);
798 assert_eq!(
799 params.clock_status,
800 ClockStatus {
801 src_is_locked: true,
802 rate: ClockRate::R48000
803 }
804 );
805 assert_eq!(
806 params.external_source_states,
807 ExternalSourceStates {
808 sources: vec![ClockSource::Arx1],
809 locked: vec![false],
810 slipped: vec![false],
811 }
812 );
813 assert_eq!(params.current_rate, 48000);
814 assert_eq!(params.version, 0);
815 assert_eq!(
816 params.avail_rates,
817 vec![ClockRate::R44100, ClockRate::R48000,]
818 );
819 assert_eq!(params.avail_sources, vec![ClockSource::Internal]);
820 assert_eq!(
821 params.clock_source_labels,
822 vec![
823 (ClockSource::Arx1, "Stream-1".to_string()),
824 (ClockSource::Internal, "internal".to_string()),
825 ]
826 );
827
828 let mut r = vec![0u8; raw.len()];
829 Protocol::serialize(¶ms, &mut r).unwrap();
830
831 assert_eq!(r, raw);
832 }
833}