1use {
111 super::{super::tcat::global_section::*, *},
112 std::ops::Range,
113};
114
115#[derive(Default, Debug)]
117pub struct FStudioProtocol;
118
119impl TcatOperation for FStudioProtocol {}
120
121impl TcatGlobalSectionSpecification for FStudioProtocol {
123 const CLOCK_SOURCE_LABEL_TABLE: &'static [ClockSource] = &[
124 ClockSource::Aes1,
125 ClockSource::Adat,
126 ClockSource::WordClock,
127 ClockSource::Arx1,
128 ClockSource::Arx2,
129 ClockSource::Arx3,
130 ClockSource::Arx4,
131 ClockSource::Internal,
132 ];
133}
134
135impl FStudioOperation for FStudioProtocol {}
136
137const OFFSET: usize = 0x00700000;
138
139const MIXER_PHYS_SRC_PARAMS_OFFSET: usize = 0x0038;
140const MIXER_STREAM_SRC_PARAMS_OFFSET: usize = 0x07d0;
141const MIXER_SELECTABLE_SRC_PARAMS_OFFSET: usize = 0x0c08;
142const OUTPUT_PARAMS_OFFSET: usize = 0x0f68;
143const MIXER_OUTPUT_PARAMS_OFFSET: usize = 0x1040;
144const OUTPUT_SRC_OFFSET: usize = 0x10ac;
145const OUTPUT_ASSIGN_OFFSET: usize = 0x10f4;
146const OUTPUT_BNC_TERMINATE_OFFSET: usize = 0x1118;
147const MIXER_EXPANSION_MODE_OFFSET: usize = 0x1128;
148const MIXER_SRC_LINK_OFFSET: usize = 0x112c;
149const OUTPUT_LINK_OFFSET: usize = 0x1150;
150const METER_OFFSET: usize = 0x13e8;
151
152const OUTPUT_PARAMS_SIZE: usize = 4 * 3 * (8 + 8 + 2);
154const OUTPUT_SRC_SIZE: usize = 4 * (8 + 8 + 2);
156const OUTPUT_ASSIGN_SIZE: usize = 4 * 4;
158const OUTPUT_BNC_TERMINATE_SIZE: usize = 4;
159const OUTPUT_LINK_SIZE: usize = 4;
161
162const MIXER_PHYS_SRC_PARAMS_SIZE: usize = 4 * 9 * 3 * (8 + 8 + 2);
164const MIXER_STREAM_SRC_PARAMS_SIZE: usize = 4 * 9 * 3 * 10;
166const MIXER_SELECTABLE_SRC_PARAMS_SIZE: usize = 4 * 9 * 3 * 8;
168const MIXER_OUTPUT_PARAMS_SIZE: usize = 4 * 9 * 3;
170const MIXER_EXPANSION_MODE_SIZE: usize = 4;
171const MIXER_SRC_LINK_SIZE: usize = 4 * 9;
173
174pub trait FStudioParametersSerdes<T> {
176 const NAME: &'static str;
178
179 const OFFSET_RANGES: &'static [Range<usize>];
181
182 fn serialize_params(params: &T, raw: &mut [u8]) -> Result<(), String>;
184
185 fn deserialize_params(params: &mut T, raw: &[u8]) -> Result<(), String>;
187}
188
189fn compute_params_size(ranges: &[Range<usize>]) -> usize {
190 ranges
191 .iter()
192 .fold(0usize, |size, range| size + range.end - range.start)
193}
194
195fn generate_err(name: &str, cause: &str, raw: &[u8]) -> Error {
196 let msg = format!("params: {}, cause: {}, raw: {:02x?}", name, cause, raw);
197 Error::new(GeneralProtocolError::VendorDependent, &msg)
198}
199
200pub trait FStudioOperation: TcatOperation {
202 fn read_parameters(
203 req: &FwReq,
204 node: &FwNode,
205 offset: usize,
206 raw: &mut [u8],
207 timeout_ms: u32,
208 ) -> Result<(), Error> {
209 Self::read(req, node, OFFSET + offset, raw, timeout_ms)
210 }
211
212 fn write_parameters(
213 req: &FwReq,
214 node: &FwNode,
215 offset: usize,
216 raw: &mut [u8],
217 timeout_ms: u32,
218 ) -> Result<(), Error> {
219 Self::write(req, node, OFFSET + offset, raw, timeout_ms)
220 }
221}
222
223pub trait FStudioParametersOperation<T>: FStudioOperation + FStudioParametersSerdes<T> {
225 fn cache_whole_parameters(
227 req: &FwReq,
228 node: &FwNode,
229 params: &mut T,
230 timeout_ms: u32,
231 ) -> Result<(), Error> {
232 let size = compute_params_size(Self::OFFSET_RANGES);
233 let mut raw = vec![0u8; size];
234
235 let mut pos = 0;
236
237 Self::OFFSET_RANGES.iter().try_for_each(|range| {
238 let size = range.end - range.start;
239 Self::read_parameters(
240 req,
241 node,
242 range.start,
243 &mut raw[pos..(pos + size)],
244 timeout_ms,
245 )
246 .map(|_| pos += size)
247 })?;
248
249 Self::deserialize_params(params, &raw)
250 .map_err(|cause| generate_err(Self::NAME, &cause, &raw))
251 }
252}
253
254impl<O: FStudioOperation + FStudioParametersSerdes<T>, T> FStudioParametersOperation<T> for O {}
255
256pub trait FStudioMutableParametersOperation<T>:
258 FStudioOperation + FStudioParametersSerdes<T>
259{
260 fn update_partial_parameters(
262 req: &FwReq,
263 node: &FwNode,
264 params: &T,
265 prev: &mut T,
266 timeout_ms: u32,
267 ) -> Result<(), Error> {
268 let size = compute_params_size(Self::OFFSET_RANGES);
269
270 let mut new = vec![0u8; size];
271 let mut old = vec![0u8; size];
272 Self::serialize_params(params, &mut new)
273 .map_err(|cause| generate_err(Self::NAME, &cause, &new))?;
274 Self::serialize_params(prev, &mut old)
275 .map_err(|cause| generate_err(Self::NAME, &cause, &old))?;
276
277 let mut pos = 0;
278
279 Self::OFFSET_RANGES.iter().try_for_each(|range| {
280 let size = range.end - range.start;
281
282 if new[pos..(pos + size)] != old[pos..(pos + size)] {
283 (0..size).step_by(4).try_for_each(|offset| {
284 let p = pos + offset;
285 if new[p..(p + 4)] != old[p..(p + 4)] {
286 Self::write_parameters(
287 req,
288 node,
289 range.start + offset,
290 &mut new[p..(p + 4)],
291 timeout_ms,
292 )
293 } else {
294 Ok(())
295 }
296 })
297 } else {
298 Ok(())
299 }
300 .map(|_| pos += size)
301 })?;
302
303 Self::deserialize_params(prev, &new).map_err(|cause| generate_err(Self::NAME, &cause, &new))
304 }
305}
306
307#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
309pub struct FStudioMeter {
310 pub analog_inputs: [u8; 8],
312 pub stream_inputs: [u8; 18],
314 pub mixer_outputs: [u8; 18],
316}
317
318impl FStudioMeter {
319 const SIZE: usize = 64;
320}
321
322impl FStudioParametersSerdes<FStudioMeter> for FStudioProtocol {
323 const NAME: &'static str = "meter";
324
325 const OFFSET_RANGES: &'static [Range<usize>] = &[Range {
326 start: METER_OFFSET,
327 end: METER_OFFSET + FStudioMeter::SIZE,
328 }];
329
330 fn serialize_params(params: &FStudioMeter, raw: &mut [u8]) -> Result<(), String> {
331 [
332 (8, ¶ms.analog_inputs[..]),
333 (16, ¶ms.stream_inputs[..]),
334 (40, ¶ms.mixer_outputs[..]),
335 ]
336 .iter()
337 .for_each(|(offset, meters)| {
338 meters.iter().enumerate().for_each(|(i, &meter)| {
339 let pos = *offset + (i / 4) * 4 + (3 - i % 4);
340 raw[pos] = meter;
341 });
342 });
343
344 Ok(())
345 }
346
347 fn deserialize_params(params: &mut FStudioMeter, raw: &[u8]) -> Result<(), String> {
348 [
349 (8, &mut params.analog_inputs[..]),
350 (16, &mut params.stream_inputs[..]),
351 (40, &mut params.mixer_outputs[..]),
352 ]
353 .iter_mut()
354 .for_each(|(offset, meters)| {
355 meters.iter_mut().enumerate().for_each(|(i, meter)| {
356 let pos = *offset + (i / 4) * 4 + (3 - i % 4);
357 *meter = raw[pos];
358 });
359 });
360
361 Ok(())
362 }
363}
364
365#[derive(Debug, Copy, Clone, PartialEq, Eq)]
367pub enum OutputSrc {
368 Analog(usize),
370 Adat0(usize),
372 Spdif(usize),
374 Stream(usize),
376 StreamAdat1(usize),
378 MixerOut(usize),
380}
381
382impl Default for OutputSrc {
383 fn default() -> Self {
384 Self::Analog(0)
385 }
386}
387
388fn serialize_output_source(src: &OutputSrc, raw: &mut [u8]) -> Result<(), String> {
389 assert!(raw.len() >= 4);
390
391 let val = (match src {
392 OutputSrc::Analog(val) => *val,
393 OutputSrc::Adat0(val) => *val + 0x08,
394 OutputSrc::Spdif(val) => *val + 0x10,
395 OutputSrc::Stream(val) => *val + 0x12,
396 OutputSrc::StreamAdat1(val) => *val + 0x1c,
397 OutputSrc::MixerOut(val) => *val + 0x24,
398 }) as u32;
399
400 serialize_u32(&val, raw);
401
402 Ok(())
403}
404
405fn deserialize_output_source(src: &mut OutputSrc, raw: &[u8]) -> Result<(), String> {
406 assert!(raw.len() >= 4);
407
408 let mut val = 0usize;
409 deserialize_usize(&mut val, raw);
410
411 *src = match val {
412 0x00..=0x07 => OutputSrc::Analog(val),
413 0x08..=0x0f => OutputSrc::Adat0(val - 0x08),
414 0x10..=0x11 => OutputSrc::Spdif(val - 0x10),
415 0x12..=0x1b => OutputSrc::Stream(val - 0x12),
416 0x1c..=0x23 => OutputSrc::StreamAdat1(val - 0x1c),
417 0x24..=0x35 => OutputSrc::MixerOut(val - 0x24),
418 _ => Err(format!("Output source not found for value {}", val))?,
419 };
420
421 Ok(())
422}
423
424#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
426pub struct OutputPair {
427 pub volumes: [u8; 2],
429 pub mutes: [bool; 2],
431 pub src: OutputSrc,
433 pub link: bool,
435}
436
437#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
439pub struct OutputParameters {
440 pub pairs: [OutputPair; 9],
442 pub main_assign: AssignTarget,
444 pub headphone_assigns: [AssignTarget; 3],
446 pub bnc_terminate: bool,
448}
449
450impl FStudioParametersSerdes<OutputParameters> for FStudioProtocol {
451 const NAME: &'static str = "output-state";
452
453 const OFFSET_RANGES: &'static [Range<usize>] = &[
454 Range {
455 start: OUTPUT_PARAMS_OFFSET,
456 end: OUTPUT_PARAMS_OFFSET + OUTPUT_PARAMS_SIZE,
457 },
458 Range {
459 start: OUTPUT_SRC_OFFSET,
460 end: OUTPUT_SRC_OFFSET + OUTPUT_SRC_SIZE,
461 },
462 Range {
463 start: OUTPUT_ASSIGN_OFFSET,
464 end: OUTPUT_ASSIGN_OFFSET + OUTPUT_ASSIGN_SIZE,
465 },
466 Range {
467 start: OUTPUT_BNC_TERMINATE_OFFSET,
468 end: OUTPUT_BNC_TERMINATE_OFFSET + OUTPUT_BNC_TERMINATE_SIZE,
469 },
470 Range {
471 start: OUTPUT_LINK_OFFSET,
472 end: OUTPUT_LINK_OFFSET + OUTPUT_LINK_SIZE,
473 },
474 ];
475
476 fn serialize_params(params: &OutputParameters, raw: &mut [u8]) -> Result<(), String> {
477 params.pairs.iter().enumerate().try_for_each(|(i, pair)| {
478 pair.volumes.iter().enumerate().for_each(|(j, vol)| {
479 let pos = 4 * 3 * (i * 2 + j);
480 serialize_u8(vol, &mut raw[pos..(pos + 4)]);
481 });
482
483 pair.mutes.iter().enumerate().for_each(|(j, mute)| {
484 let pos = 4 * (3 * (i * 2 + j) + 2);
485 serialize_bool(mute, &mut raw[pos..(pos + 4)]);
486 });
487
488 let pos = 216 + 4 * i;
489 serialize_output_source(&pair.src, &mut raw[pos..(pos + 4)])
490 })?;
491
492 serialize_assign_target(¶ms.main_assign, &mut raw[288..292])?;
493 serialize_assign_target(¶ms.headphone_assigns[0], &mut raw[292..296])?;
494 serialize_assign_target(¶ms.headphone_assigns[1], &mut raw[296..300])?;
495 serialize_assign_target(¶ms.headphone_assigns[2], &mut raw[300..304])?;
496
497 serialize_bool(¶ms.bnc_terminate, &mut raw[304..308]);
498
499 let mut val = 0u32;
500 params
501 .pairs
502 .iter()
503 .enumerate()
504 .filter(|(_, pair)| pair.link)
505 .for_each(|(i, _)| {
506 val |= 1 << i;
507 });
508 serialize_u32(&val, &mut raw[308..312]);
509
510 Ok(())
511 }
512
513 fn deserialize_params(params: &mut OutputParameters, raw: &[u8]) -> Result<(), String> {
514 params
515 .pairs
516 .iter_mut()
517 .enumerate()
518 .try_for_each(|(i, pair)| {
519 pair.volumes.iter_mut().enumerate().for_each(|(j, vol)| {
520 let pos = 4 * 3 * (i * 2 + j);
521 deserialize_u8(vol, &raw[pos..(pos + 4)]);
522 });
523
524 pair.mutes.iter_mut().enumerate().for_each(|(j, mute)| {
525 let pos = 4 * (3 * (i * 2 + j) + 2);
526 deserialize_bool(mute, &raw[pos..(pos + 4)]);
527 });
528
529 let pos = 216 + 4 * i;
530 deserialize_output_source(&mut pair.src, &raw[pos..(pos + 4)])
531 })?;
532
533 deserialize_assign_target(&mut params.main_assign, &raw[288..292])?;
534 deserialize_assign_target(&mut params.headphone_assigns[0], &raw[292..296])?;
535 deserialize_assign_target(&mut params.headphone_assigns[1], &raw[296..300])?;
536 deserialize_assign_target(&mut params.headphone_assigns[2], &raw[300..304])?;
537
538 deserialize_bool(&mut params.bnc_terminate, &raw[304..308]);
539
540 let mut val = 0u32;
541 deserialize_u32(&mut val, &raw[308..312]);
542 params.pairs.iter_mut().enumerate().for_each(|(i, pair)| {
543 pair.link = (val & (1 << i)) > 0;
544 });
545
546 Ok(())
547 }
548}
549
550impl<O: FStudioOperation + FStudioParametersSerdes<OutputParameters>>
551 FStudioMutableParametersOperation<OutputParameters> for O
552{
553}
554
555#[derive(Debug, Copy, Clone, PartialEq, Eq)]
557pub enum AssignTarget {
558 Analog01,
560 Analog23,
562 Analog56,
564 Analog78,
566 AdatA01,
568 AdatA23,
570 AdatA45,
572 AdatA67,
574 Spdif01,
576}
577
578impl Default for AssignTarget {
579 fn default() -> Self {
580 Self::Analog01
581 }
582}
583
584fn serialize_assign_target(target: &AssignTarget, raw: &mut [u8]) -> Result<(), String> {
585 let val = match target {
586 AssignTarget::Analog01 => 0x00u32,
587 AssignTarget::Analog23 => 0x02,
588 AssignTarget::Analog56 => 0x04,
589 AssignTarget::Analog78 => 0x06,
590 AssignTarget::AdatA01 => 0x08,
591 AssignTarget::AdatA23 => 0x0a,
592 AssignTarget::AdatA45 => 0x0c,
593 AssignTarget::AdatA67 => 0x0e,
594 AssignTarget::Spdif01 => 0x10,
595 };
596
597 serialize_u32(&val, raw);
598
599 Ok(())
600}
601
602fn deserialize_assign_target(target: &mut AssignTarget, raw: &[u8]) -> Result<(), String> {
603 assert!(raw.len() >= 4);
604
605 let mut val = 0u32;
606 deserialize_u32(&mut val, raw);
607
608 *target = match val {
609 0x00 => AssignTarget::Analog01,
610 0x02 => AssignTarget::Analog23,
611 0x04 => AssignTarget::Analog56,
612 0x06 => AssignTarget::Analog78,
613 0x08 => AssignTarget::AdatA01,
614 0x0a => AssignTarget::AdatA23,
615 0x0c => AssignTarget::AdatA45,
616 0x0e => AssignTarget::AdatA67,
617 0x10 => AssignTarget::Spdif01,
618 _ => Err(format!("Assign target not found for value {}", val))?,
619 };
620
621 Ok(())
622}
623
624#[derive(Debug, Copy, Clone, PartialEq, Eq)]
626pub enum ExpansionMode {
627 StreamB0_7,
629 AdatB0_7,
631}
632
633impl Default for ExpansionMode {
634 fn default() -> Self {
635 Self::StreamB0_7
636 }
637}
638
639fn serialize_expansion_mode(mode: &ExpansionMode, raw: &mut [u8]) -> Result<(), String> {
640 assert!(raw.len() >= 4);
641
642 let val = match mode {
643 ExpansionMode::StreamB0_7 => 0u32,
644 ExpansionMode::AdatB0_7 => 1,
645 };
646
647 serialize_u32(&val, raw);
648
649 Ok(())
650}
651
652fn deserialize_expansion_mode(mode: &mut ExpansionMode, raw: &[u8]) -> Result<(), String> {
653 assert!(raw.len() >= 4);
654
655 let mut val = 0u32;
656 deserialize_u32(&mut val, raw);
657
658 *mode = match val {
659 0 => ExpansionMode::StreamB0_7,
660 1 => ExpansionMode::AdatB0_7,
661 _ => Err(format!("Expansion mode not found for value {}", val))?,
662 };
663
664 Ok(())
665}
666
667#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
669pub struct MixerSourcePair {
670 pub gains: [u8; 2],
672 pub balances: [u8; 2],
674 pub mutes: [bool; 2],
676 pub link: bool,
678}
679
680fn serialize_mixer_source_pair(pair: &MixerSourcePair, raw: &mut [u8]) -> Result<(), String> {
681 assert!(raw.len() >= 24);
682
683 serialize_u8(&pair.gains[0], &mut raw[..4]);
684 serialize_u8(&pair.balances[0], &mut raw[4..8]);
685 serialize_bool(&pair.mutes[0], &mut raw[8..12]);
686 serialize_u8(&pair.gains[1], &mut raw[12..16]);
687 serialize_u8(&pair.balances[1], &mut raw[16..20]);
688 serialize_bool(&pair.mutes[1], &mut raw[20..24]);
689
690 Ok(())
691}
692
693fn deserialize_mixer_source_pair(pair: &mut MixerSourcePair, raw: &[u8]) -> Result<(), String> {
694 assert!(raw.len() >= 24);
695
696 deserialize_u8(&mut pair.gains[0], &raw[..4]);
697 deserialize_u8(&mut pair.balances[0], &raw[4..8]);
698 deserialize_bool(&mut pair.mutes[0], &raw[8..12]);
699 deserialize_u8(&mut pair.gains[1], &raw[12..16]);
700 deserialize_u8(&mut pair.balances[1], &raw[16..20]);
701 deserialize_bool(&mut pair.mutes[1], &raw[20..24]);
702
703 Ok(())
704}
705
706#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
708pub struct MixerSources {
709 pub analog_pairs: [MixerSourcePair; 4],
711 pub adat_0_pairs: [MixerSourcePair; 4],
713 pub spdif_pairs: [MixerSourcePair; 1],
715 pub stream_pairs: [MixerSourcePair; 5],
717 pub selectable_pairs: [MixerSourcePair; 4],
720}
721
722#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
724pub struct MixerOutputPair {
725 pub volume: u8,
727 pub mute: bool,
729}
730
731fn serialize_mixer_output_pair(pair: &MixerOutputPair, raw: &mut [u8]) -> Result<(), String> {
732 assert!(raw.len() >= 12);
733
734 serialize_u8(&pair.volume, &mut raw[..4]);
735 serialize_bool(&pair.mute, &mut raw[8..12]);
736
737 Ok(())
738}
739
740fn deserialize_mixer_output_pair(pair: &mut MixerOutputPair, raw: &[u8]) -> Result<(), String> {
741 assert!(raw.len() >= 12);
742
743 deserialize_u8(&mut pair.volume, &raw[..4]);
744 deserialize_bool(&mut pair.mute, &raw[8..12]);
745
746 Ok(())
747}
748
749#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
751pub struct MixerParameters {
752 pub sources: [MixerSources; 9],
754 pub outputs: [MixerOutputPair; 9],
756 pub expansion_mode: ExpansionMode,
759}
760
761impl FStudioParametersSerdes<MixerParameters> for FStudioProtocol {
762 const NAME: &'static str = "mixer-parameters";
763
764 const OFFSET_RANGES: &'static [Range<usize>] = &[
765 Range {
766 start: MIXER_PHYS_SRC_PARAMS_OFFSET,
767 end: MIXER_PHYS_SRC_PARAMS_OFFSET + MIXER_PHYS_SRC_PARAMS_SIZE,
768 },
769 Range {
770 start: MIXER_STREAM_SRC_PARAMS_OFFSET,
771 end: MIXER_STREAM_SRC_PARAMS_OFFSET + MIXER_STREAM_SRC_PARAMS_SIZE,
772 },
773 Range {
774 start: MIXER_SELECTABLE_SRC_PARAMS_OFFSET,
775 end: MIXER_SELECTABLE_SRC_PARAMS_OFFSET + MIXER_SELECTABLE_SRC_PARAMS_SIZE,
776 },
777 Range {
778 start: MIXER_OUTPUT_PARAMS_OFFSET,
779 end: MIXER_OUTPUT_PARAMS_OFFSET + MIXER_OUTPUT_PARAMS_SIZE,
780 },
781 Range {
782 start: MIXER_EXPANSION_MODE_OFFSET,
783 end: MIXER_EXPANSION_MODE_OFFSET + MIXER_EXPANSION_MODE_SIZE,
784 },
785 Range {
786 start: MIXER_SRC_LINK_OFFSET,
787 end: MIXER_SRC_LINK_OFFSET + MIXER_SRC_LINK_SIZE,
788 },
789 ];
790
791 fn serialize_params(params: &MixerParameters, raw: &mut [u8]) -> Result<(), String> {
792 params
793 .sources
794 .iter()
795 .enumerate()
796 .try_for_each(|(i, srcs)| {
797 srcs.analog_pairs
798 .iter()
799 .chain(srcs.adat_0_pairs.iter())
800 .chain(srcs.spdif_pairs.iter())
801 .enumerate()
802 .try_for_each(|(j, pair)| {
803 let pos = 4 * (3 * (i * 18 + j * 2));
804 serialize_mixer_source_pair(pair, &mut raw[pos..(pos + 24)])
805 })?;
806
807 srcs.stream_pairs
808 .iter()
809 .enumerate()
810 .try_for_each(|(j, pair)| {
811 let pos = 4 * (3 * (9 * 18 + i * 10 + j * 2));
812 serialize_mixer_source_pair(pair, &mut raw[pos..(pos + 24)])
813 })?;
814
815 srcs.selectable_pairs
816 .iter()
817 .enumerate()
818 .try_for_each(|(j, pair)| {
819 let pos = 4 * (3 * (9 * 28 + i * 8 + j * 2));
820 serialize_mixer_source_pair(pair, &mut raw[pos..(pos + 24)])
821 })
822 })?;
823
824 params
825 .outputs
826 .iter()
827 .enumerate()
828 .try_for_each(|(i, pair)| {
829 let pos = 4 * 3 * (9 * 36 + i);
830 serialize_mixer_output_pair(pair, &mut raw[pos..(pos + 12)])
831 })?;
832
833 let pos = 4 * (3 * 9 * 36 + 3 * 9);
834 serialize_expansion_mode(¶ms.expansion_mode, &mut raw[pos..(pos + 4)])?;
835
836 params.sources.iter().enumerate().for_each(|(i, srcs)| {
837 let mut val = 0u32;
838
839 srcs.analog_pairs
840 .iter()
841 .chain(srcs.adat_0_pairs.iter())
842 .chain(srcs.spdif_pairs.iter())
843 .enumerate()
844 .filter(|(_, pair)| pair.link)
845 .for_each(|(j, _)| val |= 1 << j);
846
847 srcs.stream_pairs
848 .iter()
849 .chain(srcs.selectable_pairs.iter())
850 .enumerate()
851 .filter(|(_, pair)| pair.link)
852 .for_each(|(j, _)| val |= 1 << (16 + j));
853
854 let pos = 4 * (3 * 9 * 36 + 3 * 9 + 1 + i);
855 serialize_u32(&val, &mut raw[pos..(pos + 4)]);
856 });
857
858 Ok(())
859 }
860
861 fn deserialize_params(params: &mut MixerParameters, raw: &[u8]) -> Result<(), String> {
862 params
863 .sources
864 .iter_mut()
865 .enumerate()
866 .try_for_each(|(i, srcs)| {
867 srcs.analog_pairs
868 .iter_mut()
869 .chain(srcs.adat_0_pairs.iter_mut())
870 .chain(srcs.spdif_pairs.iter_mut())
871 .enumerate()
872 .try_for_each(|(j, pair)| {
873 let pos = 4 * (3 * (i * 18 + j * 2));
874 deserialize_mixer_source_pair(pair, &raw[pos..(pos + 24)])
875 })?;
876
877 srcs.stream_pairs
878 .iter_mut()
879 .enumerate()
880 .try_for_each(|(j, pair)| {
881 let pos = 4 * (3 * (9 * 18 + i * 10 + j * 2));
882 deserialize_mixer_source_pair(pair, &raw[pos..(pos + 24)])
883 })?;
884
885 srcs.selectable_pairs
886 .iter_mut()
887 .enumerate()
888 .try_for_each(|(j, pair)| {
889 let pos = 4 * (3 * (9 * 28 + i * 8 + j * 2));
890 deserialize_mixer_source_pair(pair, &raw[pos..(pos + 24)])
891 })
892 })?;
893
894 params
895 .outputs
896 .iter_mut()
897 .enumerate()
898 .try_for_each(|(i, pair)| {
899 let pos = 4 * 3 * (9 * 36 + i);
900 deserialize_mixer_output_pair(pair, &raw[pos..(pos + 12)])
901 })?;
902
903 let pos = 4 * (3 * 9 * 36 + 3 * 9);
904 deserialize_expansion_mode(&mut params.expansion_mode, &raw[pos..(pos + 4)])?;
905
906 params.sources.iter_mut().enumerate().for_each(|(i, srcs)| {
907 let pos = 4 * (3 * 9 * 36 + 3 * 9 + 1 + i);
908 let mut val = 0u32;
909 deserialize_u32(&mut val, &raw[pos..(pos + 4)]);
910
911 srcs.analog_pairs
912 .iter_mut()
913 .chain(srcs.adat_0_pairs.iter_mut())
914 .chain(srcs.spdif_pairs.iter_mut())
915 .enumerate()
916 .for_each(|(j, pair)| pair.link = val & (1 << j) > 0);
917
918 srcs.stream_pairs
919 .iter_mut()
920 .chain(srcs.selectable_pairs.iter_mut())
921 .enumerate()
922 .for_each(|(j, pair)| pair.link = val & (1 << (16 + j)) > 0);
923 });
924
925 Ok(())
926 }
927}
928
929impl<O: FStudioOperation + FStudioParametersSerdes<MixerParameters>>
930 FStudioMutableParametersOperation<MixerParameters> for O
931{
932}
933
934pub const MIXER_COUNT: usize = 9;
936
937#[cfg(test)]
938mod test {
939 use super::*;
940
941 #[test]
942 fn meter_params_serdes() {
943 let target = FStudioMeter {
944 analog_inputs: [0, 1, 2, 3, 4, 5, 6, 7],
945 stream_inputs: [17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
946 mixer_outputs: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
947 };
948
949 let size = compute_params_size(
950 <FStudioProtocol as FStudioParametersSerdes<FStudioMeter>>::OFFSET_RANGES,
951 );
952 let mut raw = vec![0; size];
953 assert!(FStudioProtocol::serialize_params(&target, &mut raw).is_ok());
954
955 let mut params = FStudioMeter::default();
956 assert!(FStudioProtocol::deserialize_params(&mut params, &raw).is_ok());
957
958 assert_eq!(target, params);
959 }
960
961 #[test]
962 fn output_params_serdes() {
963 let target = OutputParameters {
964 pairs: [Default::default(); 9],
965 main_assign: AssignTarget::AdatA67,
966 headphone_assigns: [
967 AssignTarget::Analog78,
968 AssignTarget::Spdif01,
969 AssignTarget::AdatA45,
970 ],
971 bnc_terminate: true,
972 };
973
974 let size = compute_params_size(
975 <FStudioProtocol as FStudioParametersSerdes<OutputParameters>>::OFFSET_RANGES,
976 );
977 let mut raw = vec![0; size];
978 assert!(FStudioProtocol::serialize_params(&target, &mut raw).is_ok());
979
980 let mut params = OutputParameters::default();
981 assert!(FStudioProtocol::deserialize_params(&mut params, &raw).is_ok());
982
983 assert_eq!(target, params, "{:02x?}", raw);
984 }
985
986 #[test]
987 fn mixer_params_serdes() {
988 let mut target = MixerParameters::default();
989 target.sources.iter_mut().enumerate().for_each(|(i, srcs)| {
990 srcs.analog_pairs
991 .iter_mut()
992 .chain(srcs.adat_0_pairs.iter_mut())
993 .chain(srcs.spdif_pairs.iter_mut())
994 .chain(srcs.stream_pairs.iter_mut())
995 .chain(srcs.selectable_pairs.iter_mut())
996 .enumerate()
997 .for_each(|(j, pair)| {
998 pair.gains[0] = (i * 9 + j * 3) as u8;
999 pair.gains[1] = (i * 11 + j * 1) as u8;
1000 pair.balances[0] = (i * 7 + j * 5) as u8;
1001 pair.balances[1] = (i * 5 + j * 7) as u8;
1002 pair.mutes[0] = (i + j * 2) % 2 > 0;
1003 pair.mutes[1] = (i * 2 + j) % 2 > 0;
1004 pair.link = (i + j) % 2 > 0;
1005 });
1006 });
1007 target.outputs.iter_mut().enumerate().for_each(|(i, pair)| {
1008 pair.volume = 3 * i as u8;
1009 pair.mute = i % 2 > 0;
1010 });
1011 target.expansion_mode = ExpansionMode::AdatB0_7;
1012
1013 let size = compute_params_size(
1014 <FStudioProtocol as FStudioParametersSerdes<MixerParameters>>::OFFSET_RANGES,
1015 );
1016 let mut raw = vec![0; size];
1017 assert!(FStudioProtocol::serialize_params(&target, &mut raw).is_ok());
1018
1019 let mut params = MixerParameters::default();
1020 assert!(FStudioProtocol::deserialize_params(&mut params, &raw).is_ok());
1021
1022 assert_eq!(target, params);
1023 }
1024}