1use super::{ch_strip::*, reverb::*, *};
211
212#[derive(Default, Debug)]
214pub struct Studiok48Protocol;
215
216impl TcatOperation for Studiok48Protocol {}
217
218impl TcatGlobalSectionSpecification for Studiok48Protocol {}
219
220pub type Studiok48LineOutLevelSegment = TcKonnektSegment<StudioLineOutLevel>;
222
223pub type Studiok48RemoteSegment = TcKonnektSegment<StudioRemote>;
225
226pub type Studiok48ConfigSegment = TcKonnektSegment<StudioConfig>;
228
229pub type Studiok48MixerStateSegment = TcKonnektSegment<StudioMixerState>;
231
232pub type Studiok48PhysOutSegment = TcKonnektSegment<StudioPhysOut>;
234
235pub type Studiok48ReverbStateSegment = TcKonnektSegment<StudioReverbState>;
237
238pub type Studiok48ChStripStatesSegment = TcKonnektSegment<StudioChStripStates>;
240
241pub type Studiok48HwStateSegment = TcKonnektSegment<StudioHwState>;
245
246pub type Studiok48MixerMeterSegment = TcKonnektSegment<StudioMixerMeter>;
250
251pub type Studiok48ReverbMeterSegment = TcKonnektSegment<StudioReverbMeter>;
255
256pub type Studiok48ChStripMetersSegment = TcKonnektSegment<StudioChStripMeters>;
258
259macro_rules! segment_default {
260 ($p:ty, $t:ty) => {
261 impl Default for TcKonnektSegment<$t> {
262 fn default() -> Self {
263 Self {
264 data: <$t>::default(),
265 raw: vec![0; <$p as TcKonnektSegmentSerdes<$t>>::SIZE],
266 }
267 }
268 }
269 };
270}
271
272segment_default!(Studiok48Protocol, StudioLineOutLevel);
273segment_default!(Studiok48Protocol, StudioRemote);
274segment_default!(Studiok48Protocol, StudioConfig);
275segment_default!(Studiok48Protocol, StudioMixerState);
276segment_default!(Studiok48Protocol, StudioPhysOut);
277segment_default!(Studiok48Protocol, StudioReverbState);
278segment_default!(Studiok48Protocol, StudioChStripStates);
279segment_default!(Studiok48Protocol, StudioHwState);
280segment_default!(Studiok48Protocol, StudioMixerMeter);
281segment_default!(Studiok48Protocol, StudioReverbMeter);
282segment_default!(Studiok48Protocol, StudioChStripMeters);
283
284const STUDIO_LINE_OUT_LEVEL_NOTIFY_FLAG: u32 = 0x00010000;
285const STUDIO_REMOTE_NOTIFY_FLAG: u32 = 0x00020000;
286const STUDIO_CONFIG_NOTIFY_FLAG: u32 = 0x00040000;
287const STUDIO_MIXER_STATE_NOTIFY_FLAG: u32 = 0x00080000;
288const STUDIO_PHYS_OUT_NOTIFY_FLAG: u32 = 0x00100000;
289const STUDIO_REVERB_NOTIFY_CHANGE: u32 = 0x00200000;
290const STUDIO_CH_STRIP_NOTIFY_01_CHANGE: u32 = 0x00400000;
291const STUDIO_CH_STRIP_NOTIFY_23_CHANGE: u32 = 0x00800000;
292const STUDIO_HW_STATE_NOTIFY_FLAG: u32 = 0x04000000;
295#[derive(Debug, Copy, Clone, PartialEq, Eq)]
299pub enum NominalSignalLevel {
300 Professional,
302 Consumer,
304}
305
306impl Default for NominalSignalLevel {
307 fn default() -> Self {
308 NominalSignalLevel::Professional
309 }
310}
311
312const NOMINAL_LEVELS: &[NominalSignalLevel] = &[
313 NominalSignalLevel::Professional,
314 NominalSignalLevel::Consumer,
315];
316
317const NOMINAL_LEVEL_LABEL: &str = "nominal level";
318
319fn serialize_nominal_level(level: &NominalSignalLevel, raw: &mut [u8]) -> Result<(), String> {
320 serialize_position(NOMINAL_LEVELS, level, raw, NOMINAL_LEVEL_LABEL)
321}
322
323fn deserialize_nominal_level(level: &mut NominalSignalLevel, raw: &[u8]) -> Result<(), String> {
324 deserialize_position(NOMINAL_LEVELS, level, raw, NOMINAL_LEVEL_LABEL)
325}
326
327#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
329pub struct StudioLineOutLevel {
330 pub line_45: NominalSignalLevel,
331 pub line_67: NominalSignalLevel,
332 pub line_89: NominalSignalLevel,
333 pub line_1011: NominalSignalLevel,
334}
335
336impl TcKonnektSegmentSerdes<StudioLineOutLevel> for Studiok48Protocol {
337 const NAME: &'static str = "line-output-level";
338 const OFFSET: usize = 0x0000;
339 const SIZE: usize = 20;
340
341 fn serialize(params: &StudioLineOutLevel, raw: &mut [u8]) -> Result<(), String> {
342 serialize_nominal_level(¶ms.line_45, &mut raw[4..8])?;
343 serialize_nominal_level(¶ms.line_67, &mut raw[8..12])?;
344 serialize_nominal_level(¶ms.line_89, &mut raw[12..16])?;
345 serialize_nominal_level(¶ms.line_1011, &mut raw[16..20])?;
346 Ok(())
347 }
348
349 fn deserialize(params: &mut StudioLineOutLevel, raw: &[u8]) -> Result<(), String> {
350 deserialize_nominal_level(&mut params.line_45, &raw[4..8])?;
351 deserialize_nominal_level(&mut params.line_67, &raw[8..12])?;
352 deserialize_nominal_level(&mut params.line_89, &raw[12..16])?;
353 deserialize_nominal_level(&mut params.line_1011, &raw[16..20])?;
354 Ok(())
355 }
356}
357
358impl TcKonnektMutableSegmentOperation<StudioLineOutLevel> for Studiok48Protocol {}
359
360impl TcKonnektNotifiedSegmentOperation<StudioLineOutLevel> for Studiok48Protocol {
361 const NOTIFY_FLAG: u32 = STUDIO_LINE_OUT_LEVEL_NOTIFY_FLAG;
362}
363
364#[derive(Debug, Copy, Clone, PartialEq, Eq)]
366pub enum RemoteEffectButtonMode {
367 Reverb,
369 Midi,
371}
372
373impl Default for RemoteEffectButtonMode {
374 fn default() -> Self {
375 Self::Reverb
376 }
377}
378
379const REMOTE_EFFECT_BUTTON_MODES: &[RemoteEffectButtonMode] =
380 &[RemoteEffectButtonMode::Reverb, RemoteEffectButtonMode::Midi];
381
382const REMOTE_EFFECT_BUTTON_MODE_LABEL: &str = "remote effect button mode";
383
384fn serialize_remote_effect_button_mode(
385 mode: &RemoteEffectButtonMode,
386 raw: &mut [u8],
387) -> Result<(), String> {
388 serialize_position(
389 REMOTE_EFFECT_BUTTON_MODES,
390 mode,
391 raw,
392 REMOTE_EFFECT_BUTTON_MODE_LABEL,
393 )
394}
395
396fn deserialize_remote_effect_button_mode(
397 mode: &mut RemoteEffectButtonMode,
398 raw: &[u8],
399) -> Result<(), String> {
400 deserialize_position(
401 REMOTE_EFFECT_BUTTON_MODES,
402 mode,
403 raw,
404 REMOTE_EFFECT_BUTTON_MODE_LABEL,
405 )
406}
407
408#[derive(Debug, Copy, Clone, PartialEq, Eq)]
410pub enum KnobPushMode {
411 Pan,
413 GainToReverb,
415 GainToAux0,
417 GainToAux1,
419}
420
421impl Default for KnobPushMode {
422 fn default() -> Self {
423 Self::Pan
424 }
425}
426
427const KNOB_PUSH_MODES: &[KnobPushMode] = &[
428 KnobPushMode::Pan,
429 KnobPushMode::GainToReverb,
430 KnobPushMode::GainToAux0,
431 KnobPushMode::GainToAux1,
432];
433
434const KNOB_PUSH_MODE_LABEL: &str = "knob push mode";
435
436fn serialize_knob_push_mode(mode: &KnobPushMode, raw: &mut [u8]) -> Result<(), String> {
437 serialize_position(KNOB_PUSH_MODES, mode, raw, KNOB_PUSH_MODE_LABEL)
438}
439
440fn deserialize_knob_push_mode(mode: &mut KnobPushMode, raw: &[u8]) -> Result<(), String> {
441 deserialize_position(KNOB_PUSH_MODES, mode, raw, KNOB_PUSH_MODE_LABEL)
442}
443
444pub const STUDIO_REMOTE_USER_ASSIGN_COUNT: usize = 6;
446
447#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
449pub struct StudioRemote {
450 pub prog: TcKonnektLoadedProgram,
452 pub user_assigns: [SrcEntry; STUDIO_REMOTE_USER_ASSIGN_COUNT],
454 pub effect_button_mode: RemoteEffectButtonMode,
456 pub fallback_to_master_enable: bool,
458 pub fallback_to_master_duration: u32,
460 pub knob_push_mode: KnobPushMode,
462}
463
464impl TcKonnektSegmentSerdes<StudioRemote> for Studiok48Protocol {
465 const NAME: &'static str = "remote-controller";
466 const OFFSET: usize = 0x0014;
467 const SIZE: usize = 48;
468
469 fn serialize(params: &StudioRemote, raw: &mut [u8]) -> Result<(), String> {
470 serialize_loaded_program(¶ms.prog, &mut raw[..4])?;
471 params
472 .user_assigns
473 .iter()
474 .enumerate()
475 .try_for_each(|(i, assign)| {
476 let pos = 4 + i * 4;
477 serialize_src_entry(assign, &mut raw[pos..(pos + 4)])
478 })?;
479 serialize_remote_effect_button_mode(¶ms.effect_button_mode, &mut raw[28..32])?;
480 serialize_bool(¶ms.fallback_to_master_enable, &mut raw[32..36]);
481 serialize_u32(¶ms.fallback_to_master_duration, &mut raw[36..40]);
482 serialize_knob_push_mode(¶ms.knob_push_mode, &mut raw[40..44])?;
483 Ok(())
484 }
485
486 fn deserialize(params: &mut StudioRemote, raw: &[u8]) -> Result<(), String> {
487 deserialize_loaded_program(&mut params.prog, &raw[..4])?;
488 params
489 .user_assigns
490 .iter_mut()
491 .enumerate()
492 .try_for_each(|(i, assign)| {
493 let pos = 4 + i * 4;
494 deserialize_src_entry(assign, &raw[pos..(pos + 4)])
495 })?;
496 deserialize_remote_effect_button_mode(&mut params.effect_button_mode, &raw[28..32])?;
497 deserialize_bool(&mut params.fallback_to_master_enable, &raw[32..36]);
498 deserialize_u32(&mut params.fallback_to_master_duration, &raw[36..40]);
499 deserialize_knob_push_mode(&mut params.knob_push_mode, &raw[40..44])?;
500 Ok(())
501 }
502}
503
504impl TcKonnektMutableSegmentOperation<StudioRemote> for Studiok48Protocol {}
505
506impl TcKonnektNotifiedSegmentOperation<StudioRemote> for Studiok48Protocol {
507 const NOTIFY_FLAG: u32 = STUDIO_REMOTE_NOTIFY_FLAG;
508}
509
510impl AsRef<TcKonnektLoadedProgram> for StudioRemote {
511 fn as_ref(&self) -> &TcKonnektLoadedProgram {
512 &self.prog
513 }
514}
515
516impl AsMut<TcKonnektLoadedProgram> for StudioRemote {
517 fn as_mut(&mut self) -> &mut TcKonnektLoadedProgram {
518 &mut self.prog
519 }
520}
521
522#[derive(Debug, Copy, Clone, PartialEq, Eq)]
524pub enum OptIfaceMode {
525 Adat,
527 Spdif,
529}
530
531impl Default for OptIfaceMode {
532 fn default() -> Self {
533 Self::Adat
534 }
535}
536
537const OPT_IFACE_MODES: &[OptIfaceMode] = &[OptIfaceMode::Adat, OptIfaceMode::Spdif];
538
539const OPT_IFACE_MODE_LABEL: &str = "optical interface mode";
540
541fn serialize_opt_iface_mode(mode: &OptIfaceMode, raw: &mut [u8]) -> Result<(), String> {
542 serialize_position(OPT_IFACE_MODES, mode, raw, OPT_IFACE_MODE_LABEL)
543}
544
545fn deserialize_opt_iface_mode(mode: &mut OptIfaceMode, raw: &[u8]) -> Result<(), String> {
546 deserialize_position(OPT_IFACE_MODES, mode, raw, OPT_IFACE_MODE_LABEL)
547}
548
549#[derive(Debug, Copy, Clone, PartialEq, Eq)]
551pub enum StudioStandaloneClkSrc {
552 Adat,
554 SpdifOnOpt01,
556 SpdifOnOpt23,
558 SpdifOnCoax,
560 WordClock,
562 Internal,
564}
565
566impl Default for StudioStandaloneClkSrc {
567 fn default() -> Self {
568 Self::Internal
569 }
570}
571
572const STANDALONE_CLOCK_SOURCES: &[StudioStandaloneClkSrc] = &[
573 StudioStandaloneClkSrc::Adat,
574 StudioStandaloneClkSrc::SpdifOnOpt01,
575 StudioStandaloneClkSrc::SpdifOnOpt23,
576 StudioStandaloneClkSrc::SpdifOnCoax,
577 StudioStandaloneClkSrc::WordClock,
578 StudioStandaloneClkSrc::Internal,
579];
580
581const STANDALONE_CLOCK_SOURCE_LABEL: &str = "standalone clock source";
582
583fn serialize_standalone_clock_source(
584 src: &StudioStandaloneClkSrc,
585 raw: &mut [u8],
586) -> Result<(), String> {
587 serialize_position(
588 STANDALONE_CLOCK_SOURCES,
589 src,
590 raw,
591 STANDALONE_CLOCK_SOURCE_LABEL,
592 )
593}
594
595fn deserialize_standalone_clock_source(
596 src: &mut StudioStandaloneClkSrc,
597 raw: &[u8],
598) -> Result<(), String> {
599 deserialize_position(
600 STANDALONE_CLOCK_SOURCES,
601 src,
602 raw,
603 STANDALONE_CLOCK_SOURCE_LABEL,
604 )
605}
606
607#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
609pub struct StudioConfig {
610 pub opt_iface_mode: OptIfaceMode,
612 pub standalone_src: StudioStandaloneClkSrc,
614 pub standalone_rate: TcKonnektStandaloneClockRate,
616 pub clock_recovery: bool,
618 pub midi_send: TcKonnektMidiSender,
620}
621
622impl TcKonnektSegmentSerdes<StudioConfig> for Studiok48Protocol {
623 const NAME: &'static str = "configuration";
624 const OFFSET: usize = 0x0044;
625 const SIZE: usize = 100;
626
627 fn serialize(params: &StudioConfig, raw: &mut [u8]) -> Result<(), String> {
628 serialize_opt_iface_mode(¶ms.opt_iface_mode, &mut raw[..4])?;
629 serialize_standalone_clock_source(¶ms.standalone_src, &mut raw[4..8])?;
630 serialize_standalone_clock_rate(¶ms.standalone_rate, &mut raw[8..12])?;
631 serialize_bool(¶ms.clock_recovery, &mut raw[16..20]);
632 serialize_midi_sender(¶ms.midi_send, &mut raw[52..88])?;
633 Ok(())
634 }
635
636 fn deserialize(params: &mut StudioConfig, raw: &[u8]) -> Result<(), String> {
637 deserialize_opt_iface_mode(&mut params.opt_iface_mode, &raw[..4])?;
638 deserialize_standalone_clock_source(&mut params.standalone_src, &raw[4..8])?;
639 deserialize_standalone_clock_rate(&mut params.standalone_rate, &raw[8..12])?;
640 deserialize_bool(&mut params.clock_recovery, &raw[16..20]);
641 deserialize_midi_sender(&mut params.midi_send, &raw[52..88])?;
642 Ok(())
643 }
644}
645
646impl TcKonnektMutableSegmentOperation<StudioConfig> for Studiok48Protocol {}
647
648impl TcKonnektNotifiedSegmentOperation<StudioConfig> for Studiok48Protocol {
649 const NOTIFY_FLAG: u32 = STUDIO_CONFIG_NOTIFY_FLAG;
650}
651
652impl AsRef<TcKonnektStandaloneClockRate> for StudioConfig {
653 fn as_ref(&self) -> &TcKonnektStandaloneClockRate {
654 &self.standalone_rate
655 }
656}
657
658impl AsMut<TcKonnektStandaloneClockRate> for StudioConfig {
659 fn as_mut(&mut self) -> &mut TcKonnektStandaloneClockRate {
660 &mut self.standalone_rate
661 }
662}
663
664impl AsRef<TcKonnektMidiSender> for StudioConfig {
665 fn as_ref(&self) -> &TcKonnektMidiSender {
666 &self.midi_send
667 }
668}
669
670impl AsMut<TcKonnektMidiSender> for StudioConfig {
671 fn as_mut(&mut self) -> &mut TcKonnektMidiSender {
672 &mut self.midi_send
673 }
674}
675
676#[derive(Debug, Copy, Clone, PartialEq, Eq)]
678pub enum SrcEntry {
679 Unused,
681 Analog(usize), Spdif(usize), Adat(usize), StreamA(usize), StreamB(usize), Mixer(usize), }
694
695impl SrcEntry {
696 const UNUSED: usize = 0x00;
697 const ANALOG_OFFSET: usize = 0x01;
698 const SPDIF_OFFSET: usize = 0x0d;
699 const ADAT_OFFSET: usize = 0x0f;
700 const STREAM_A_OFFSET: usize = 0x37;
701 const STREAM_B_OFFSET: usize = 0x47;
702 const MIXER_OFFSET: usize = 0x55;
703}
704
705impl Default for SrcEntry {
706 fn default() -> Self {
707 SrcEntry::Unused
708 }
709}
710
711fn serialize_src_entry(entry: &SrcEntry, raw: &mut [u8]) -> Result<(), String> {
712 assert!(raw.len() >= 4);
713
714 let val = (match entry {
715 SrcEntry::Unused => SrcEntry::UNUSED,
716 SrcEntry::Analog(ch) => SrcEntry::ANALOG_OFFSET + ch,
717 SrcEntry::Spdif(ch) => SrcEntry::SPDIF_OFFSET + ch,
718 SrcEntry::Adat(ch) => SrcEntry::ADAT_OFFSET + ch,
719 SrcEntry::StreamA(ch) => SrcEntry::STREAM_A_OFFSET + ch,
720 SrcEntry::StreamB(ch) => SrcEntry::STREAM_B_OFFSET + ch,
721 SrcEntry::Mixer(ch) => SrcEntry::MIXER_OFFSET + ch,
722 }) as u32;
723
724 serialize_u32(&val, raw);
725
726 Ok(())
727}
728
729fn deserialize_src_entry(entry: &mut SrcEntry, raw: &[u8]) -> Result<(), String> {
730 assert!(raw.len() >= 4);
731
732 let mut val = 0u32;
733 deserialize_u32(&mut val, raw);
734
735 let v = val as usize;
736 *entry = if v >= SrcEntry::ANALOG_OFFSET && v < SrcEntry::SPDIF_OFFSET {
737 SrcEntry::Analog(v - SrcEntry::ANALOG_OFFSET)
738 } else if v >= SrcEntry::SPDIF_OFFSET && v < SrcEntry::ADAT_OFFSET {
739 SrcEntry::Spdif(v - SrcEntry::SPDIF_OFFSET)
740 } else if v >= SrcEntry::ADAT_OFFSET && v < 0x17 {
741 SrcEntry::Adat(v - SrcEntry::ADAT_OFFSET)
742 } else if v >= SrcEntry::STREAM_A_OFFSET && v < SrcEntry::STREAM_B_OFFSET {
743 SrcEntry::StreamA(v - SrcEntry::STREAM_A_OFFSET)
744 } else if v >= SrcEntry::STREAM_B_OFFSET && v < SrcEntry::MIXER_OFFSET {
745 SrcEntry::StreamB(v - SrcEntry::STREAM_B_OFFSET)
746 } else if v >= SrcEntry::MIXER_OFFSET && v < 0x5d {
747 SrcEntry::Mixer(v - SrcEntry::MIXER_OFFSET)
748 } else {
749 SrcEntry::Unused
750 };
751
752 Ok(())
753}
754
755#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
757pub struct OutPair {
758 pub dim_enabled: bool,
760 pub vol: i32,
762 pub dim_vol: i32,
764}
765
766impl OutPair {
767 const SIZE: usize = 12;
768}
769
770fn serialize_out_pair(pair: &OutPair, raw: &mut [u8]) -> Result<(), String> {
771 assert!(raw.len() >= OutPair::SIZE);
772
773 serialize_bool(&pair.dim_enabled, &mut raw[..4]);
774 serialize_i32(&pair.vol, &mut raw[4..8]);
775 serialize_i32(&pair.dim_vol, &mut raw[8..12]);
776
777 Ok(())
778}
779
780fn deserialize_out_pair(pair: &mut OutPair, raw: &[u8]) -> Result<(), String> {
781 assert!(raw.len() >= OutPair::SIZE);
782
783 deserialize_bool(&mut pair.dim_enabled, &raw[..4]);
784 deserialize_i32(&mut pair.vol, &raw[4..8]);
785 deserialize_i32(&mut pair.dim_vol, &raw[8..12]);
786
787 Ok(())
788}
789
790#[derive(Debug, Copy, Clone, PartialEq, Eq)]
792pub enum MonitorSrcPairMode {
793 Inactive,
795 Active,
797 Fixed,
799}
800
801impl Default for MonitorSrcPairMode {
802 fn default() -> Self {
803 Self::Inactive
804 }
805}
806
807const MONITOR_SRC_PAIR_MODES: &[MonitorSrcPairMode] = &[
808 MonitorSrcPairMode::Inactive,
809 MonitorSrcPairMode::Active,
810 MonitorSrcPairMode::Fixed,
811];
812
813const MONITOR_SRC_PAIR_MODE_LABEL: &str = "monitor source pair mode";
814
815fn serialize_monitor_src_pair_mode(
816 mode: &MonitorSrcPairMode,
817 raw: &mut [u8],
818) -> Result<(), String> {
819 serialize_position(
820 MONITOR_SRC_PAIR_MODES,
821 mode,
822 raw,
823 MONITOR_SRC_PAIR_MODE_LABEL,
824 )
825}
826
827fn deserialize_monitor_src_pair_mode(
828 mode: &mut MonitorSrcPairMode,
829 raw: &[u8],
830) -> Result<(), String> {
831 deserialize_position(
832 MONITOR_SRC_PAIR_MODES,
833 mode,
834 raw,
835 MONITOR_SRC_PAIR_MODE_LABEL,
836 )
837}
838
839#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
841pub struct MonitorSrcParam {
842 pub src: SrcEntry,
844 pub gain_to_main: i32,
846 pub pan_to_main: i32,
848 pub gain_to_reverb: i32,
850 pub gain_to_aux0: i32,
852 pub gain_to_aux1: i32,
854}
855
856impl MonitorSrcParam {
857 const SIZE: usize = 24;
858}
859
860fn serialize_monitor_src_params(params: &MonitorSrcParam, raw: &mut [u8]) -> Result<(), String> {
861 assert!(raw.len() >= MonitorSrcParam::SIZE);
862
863 serialize_src_entry(¶ms.src, &mut raw[..4])?;
864 serialize_i32(¶ms.gain_to_main, &mut raw[4..8]);
865 serialize_i32(¶ms.pan_to_main, &mut raw[8..12]);
866 serialize_i32(¶ms.gain_to_reverb, &mut raw[12..16]);
867 serialize_i32(¶ms.gain_to_aux0, &mut raw[16..20]);
868 serialize_i32(¶ms.gain_to_aux1, &mut raw[20..24]);
869
870 Ok(())
871}
872
873fn deserialize_monitor_src_params(params: &mut MonitorSrcParam, raw: &[u8]) -> Result<(), String> {
874 assert!(raw.len() >= MonitorSrcParam::SIZE);
875
876 deserialize_src_entry(&mut params.src, &raw[..4])?;
877 deserialize_i32(&mut params.gain_to_main, &raw[4..8]);
878 deserialize_i32(&mut params.pan_to_main, &raw[8..12]);
879 deserialize_i32(&mut params.gain_to_reverb, &raw[12..16]);
880 deserialize_i32(&mut params.gain_to_aux0, &raw[16..20]);
881 deserialize_i32(&mut params.gain_to_aux1, &raw[20..24]);
882
883 Ok(())
884}
885
886#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
888pub struct MonitorSrcPair {
889 pub mode: MonitorSrcPairMode,
891 pub stereo_link: bool,
893 pub params: [MonitorSrcParam; 2],
895}
896
897impl MonitorSrcPair {
898 const SIZE: usize = 56;
899}
900
901fn serialize_monitor_src_pair(pair: &MonitorSrcPair, raw: &mut [u8]) -> Result<(), String> {
902 assert!(raw.len() >= MonitorSrcPair::SIZE);
903
904 serialize_monitor_src_pair_mode(&pair.mode, &mut raw[..4])?;
905 serialize_bool(&pair.stereo_link, &mut raw[4..8]);
906 serialize_monitor_src_params(&pair.params[0], &mut raw[8..32])?;
907 serialize_monitor_src_params(&pair.params[1], &mut raw[32..56])?;
908
909 Ok(())
910}
911
912fn deserialize_monitor_src_pair(pair: &mut MonitorSrcPair, raw: &[u8]) -> Result<(), String> {
913 assert!(raw.len() >= MonitorSrcPair::SIZE);
914
915 deserialize_monitor_src_pair_mode(&mut pair.mode, &raw[..4])?;
916 deserialize_bool(&mut pair.stereo_link, &raw[4..8]);
917 deserialize_monitor_src_params(&mut pair.params[0], &raw[8..32])?;
918 deserialize_monitor_src_params(&mut pair.params[1], &raw[32..56])?;
919
920 Ok(())
921}
922
923pub const STUDIO_MIXER_SRC_PAIR_COUNT: usize = 12;
925
926#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
928pub struct StudioMixerState {
929 pub src_pairs: [MonitorSrcPair; STUDIO_MIXER_SRC_PAIR_COUNT],
931 pub mutes: [bool; STUDIO_MIXER_SRC_PAIR_COUNT],
933 pub reverb_return_mute: [bool; 3],
935 pub reverb_return_gain: [i32; 3],
937 pub ch_strip_as_plugin: [bool; 2],
939 pub ch_strip_src: [SrcEntry; 4],
941 pub ch_strip_23_at_mid_rate: bool,
943 pub mixer_out: [OutPair; 3],
945 pub post_fader: [bool; 3],
947 pub enabled: bool,
949}
950
951impl TcKonnektSegmentSerdes<StudioMixerState> for Studiok48Protocol {
952 const NAME: &'static str = "mixer-state";
953 const OFFSET: usize = 0x00a8;
954 const SIZE: usize = 820;
955
956 fn serialize(params: &StudioMixerState, raw: &mut [u8]) -> Result<(), String> {
957 params.src_pairs.iter().enumerate().try_for_each(|(i, p)| {
958 let pos = i * MonitorSrcPair::SIZE;
959 serialize_monitor_src_pair(p, &mut raw[pos..(pos + MonitorSrcPair::SIZE)])
960 })?;
961 let mut val = 0u32;
962 params
963 .mutes
964 .iter()
965 .enumerate()
966 .filter(|(_, &m)| m)
967 .for_each(|(i, _)| {
968 val |= 1 << i;
969 });
970 serialize_u32(&val, &mut raw[672..676]);
971 serialize_bool(¶ms.reverb_return_mute[0], &mut raw[712..716]);
972 serialize_i32(¶ms.reverb_return_gain[0], &mut raw[716..720]);
973 serialize_bool(¶ms.reverb_return_mute[1], &mut raw[720..724]);
974 serialize_i32(¶ms.reverb_return_gain[1], &mut raw[724..728]);
975 serialize_bool(¶ms.reverb_return_mute[2], &mut raw[728..732]);
976 serialize_i32(¶ms.reverb_return_gain[2], &mut raw[732..736]);
977 serialize_bool(¶ms.ch_strip_as_plugin[0], &mut raw[736..740]);
978 serialize_bool(¶ms.ch_strip_as_plugin[1], &mut raw[740..744]);
979 params
980 .ch_strip_src
981 .iter()
982 .enumerate()
983 .try_for_each(|(i, entry)| {
984 let pos = 744 + i * 4;
985 serialize_src_entry(entry, &mut raw[pos..(pos + 4)])
986 })?;
987 serialize_bool(¶ms.ch_strip_23_at_mid_rate, &mut raw[760..764]);
988 serialize_out_pair(¶ms.mixer_out[0], &mut raw[764..776])?;
989 serialize_out_pair(¶ms.mixer_out[1], &mut raw[776..788])?;
990 serialize_out_pair(¶ms.mixer_out[2], &mut raw[788..800])?;
991 serialize_bool(¶ms.post_fader[0], &mut raw[800..804]);
992 serialize_bool(¶ms.post_fader[1], &mut raw[804..808]);
993 serialize_bool(¶ms.post_fader[2], &mut raw[808..812]);
994 serialize_bool(¶ms.enabled, &mut raw[812..816]);
995 Ok(())
996 }
997
998 fn deserialize(params: &mut StudioMixerState, raw: &[u8]) -> Result<(), String> {
999 params
1000 .src_pairs
1001 .iter_mut()
1002 .enumerate()
1003 .try_for_each(|(i, p)| {
1004 let pos = i * MonitorSrcPair::SIZE;
1005 deserialize_monitor_src_pair(p, &raw[pos..(pos + MonitorSrcPair::SIZE)])
1006 })?;
1007 let mut val = 0u32;
1008 deserialize_u32(&mut val, &raw[672..676]);
1009 params.mutes.iter_mut().enumerate().for_each(|(i, m)| {
1010 *m = (val & 1 << i) > 0;
1011 });
1012 deserialize_bool(&mut params.reverb_return_mute[0], &raw[712..716]);
1013 deserialize_i32(&mut params.reverb_return_gain[0], &raw[716..720]);
1014 deserialize_bool(&mut params.reverb_return_mute[1], &raw[720..724]);
1015 deserialize_i32(&mut params.reverb_return_gain[1], &raw[724..728]);
1016 deserialize_bool(&mut params.reverb_return_mute[2], &raw[728..732]);
1017 deserialize_i32(&mut params.reverb_return_gain[2], &raw[732..736]);
1018 deserialize_bool(&mut params.ch_strip_as_plugin[0], &raw[736..740]);
1019 deserialize_bool(&mut params.ch_strip_as_plugin[1], &raw[740..744]);
1020 params
1021 .ch_strip_src
1022 .iter_mut()
1023 .enumerate()
1024 .try_for_each(|(i, entry)| {
1025 let pos = 744 + i * 4;
1026 deserialize_src_entry(entry, &raw[pos..(pos + 4)])
1027 })?;
1028 deserialize_bool(&mut params.ch_strip_23_at_mid_rate, &raw[760..764]);
1029 deserialize_out_pair(&mut params.mixer_out[0], &raw[764..776])?;
1030 deserialize_out_pair(&mut params.mixer_out[1], &raw[776..788])?;
1031 deserialize_out_pair(&mut params.mixer_out[2], &raw[788..800])?;
1032 deserialize_bool(&mut params.post_fader[0], &raw[800..804]);
1033 deserialize_bool(&mut params.post_fader[1], &raw[804..808]);
1034 deserialize_bool(&mut params.post_fader[2], &raw[800..812]);
1035 deserialize_bool(&mut params.enabled, &raw[812..816]);
1036 Ok(())
1037 }
1038}
1039
1040impl TcKonnektMutableSegmentOperation<StudioMixerState> for Studiok48Protocol {}
1041
1042impl TcKonnektNotifiedSegmentOperation<StudioMixerState> for Studiok48Protocol {
1043 const NOTIFY_FLAG: u32 = STUDIO_MIXER_STATE_NOTIFY_FLAG;
1044}
1045
1046#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1048pub struct PhysOutSrcParam {
1049 pub src: SrcEntry,
1051 pub vol: i32,
1053 pub delay: i32,
1055}
1056
1057impl PhysOutSrcParam {
1058 const SIZE: usize = 12;
1059}
1060
1061fn serialize_phys_out_src_params(params: &PhysOutSrcParam, raw: &mut [u8]) -> Result<(), String> {
1062 assert!(raw.len() >= PhysOutSrcParam::SIZE);
1063
1064 serialize_src_entry(¶ms.src, &mut raw[..4])?;
1065 serialize_i32(¶ms.vol, &mut raw[4..8]);
1066 serialize_i32(¶ms.delay, &mut raw[8..12]);
1067
1068 Ok(())
1069}
1070
1071fn deserialize_phys_out_src_params(params: &mut PhysOutSrcParam, raw: &[u8]) -> Result<(), String> {
1072 assert!(raw.len() >= PhysOutSrcParam::SIZE);
1073
1074 deserialize_src_entry(&mut params.src, &raw[..4])?;
1075 deserialize_i32(&mut params.vol, &raw[4..8]);
1076 deserialize_i32(&mut params.delay, &raw[8..12]);
1077
1078 Ok(())
1079}
1080
1081#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1083pub struct PhysOutPairSrc {
1084 pub stereo_link: bool,
1086 pub params: [PhysOutSrcParam; 2],
1088}
1089
1090impl PhysOutPairSrc {
1091 const SIZE: usize = 28;
1092}
1093
1094fn serialize_phys_out_pair_src(src: &PhysOutPairSrc, raw: &mut [u8]) -> Result<(), String> {
1095 assert!(raw.len() >= PhysOutPairSrc::SIZE);
1096
1097 serialize_bool(&src.stereo_link, &mut raw[..4]);
1098 serialize_phys_out_src_params(&src.params[0], &mut raw[4..16])?;
1099 serialize_phys_out_src_params(&src.params[1], &mut raw[16..28])?;
1100
1101 Ok(())
1102}
1103
1104fn deserialize_phys_out_pair_src(src: &mut PhysOutPairSrc, raw: &[u8]) -> Result<(), String> {
1105 assert!(raw.len() >= PhysOutPairSrc::SIZE);
1106
1107 deserialize_bool(&mut src.stereo_link, &raw[..4]);
1108 deserialize_phys_out_src_params(&mut src.params[0], &raw[4..16])?;
1109 deserialize_phys_out_src_params(&mut src.params[1], &raw[16..28])?;
1110
1111 Ok(())
1112}
1113
1114#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1116pub enum CrossOverFreq {
1117 F50,
1119 F80,
1121 F95,
1123 F110,
1125 F115,
1127 F120,
1129}
1130
1131impl Default for CrossOverFreq {
1132 fn default() -> Self {
1133 Self::F50
1134 }
1135}
1136
1137const CROSS_OVER_FREQS: &[CrossOverFreq] = &[
1138 CrossOverFreq::F50,
1139 CrossOverFreq::F80,
1140 CrossOverFreq::F95,
1141 CrossOverFreq::F110,
1142 CrossOverFreq::F115,
1143 CrossOverFreq::F120,
1144];
1145
1146const CROSS_OVER_FREQ_LABEL: &str = "cross over frequency";
1147
1148fn serialize_cross_over_freq(freq: &CrossOverFreq, raw: &mut [u8]) -> Result<(), String> {
1149 serialize_position(CROSS_OVER_FREQS, freq, raw, CROSS_OVER_FREQ_LABEL)
1150}
1151
1152fn deserialize_cross_over_freq(freq: &mut CrossOverFreq, raw: &[u8]) -> Result<(), String> {
1153 deserialize_position(CROSS_OVER_FREQS, freq, raw, CROSS_OVER_FREQ_LABEL)
1154}
1155
1156#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1158pub enum HighPassFreq {
1159 Off,
1161 Above12,
1163 Above24,
1165}
1166
1167impl Default for HighPassFreq {
1168 fn default() -> Self {
1169 HighPassFreq::Off
1170 }
1171}
1172
1173const HIGH_PASS_FREQS: &[HighPassFreq] = &[
1174 HighPassFreq::Off,
1175 HighPassFreq::Above12,
1176 HighPassFreq::Above24,
1177];
1178
1179const HIGH_PASS_FREQ_LABEL: &str = "high pass frequency";
1180
1181fn serialize_high_pass_freq(freq: &HighPassFreq, raw: &mut [u8]) -> Result<(), String> {
1182 serialize_position(HIGH_PASS_FREQS, freq, raw, HIGH_PASS_FREQ_LABEL)
1183}
1184
1185fn deserialize_high_pass_freq(freq: &mut HighPassFreq, raw: &[u8]) -> Result<(), String> {
1186 deserialize_position(HIGH_PASS_FREQS, freq, raw, HIGH_PASS_FREQ_LABEL)
1187}
1188
1189#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1191pub enum LowPassFreq {
1192 Below12,
1194 Below24,
1196}
1197
1198impl Default for LowPassFreq {
1199 fn default() -> Self {
1200 LowPassFreq::Below12
1201 }
1202}
1203
1204fn serialize_low_pass_freq(freq: &LowPassFreq, raw: &mut [u8]) -> Result<(), String> {
1205 assert!(raw.len() >= 4);
1206
1207 let val = match freq {
1208 LowPassFreq::Below12 => 1u32,
1209 LowPassFreq::Below24 => 2,
1210 };
1211 serialize_u32(&val, raw);
1212
1213 Ok(())
1214}
1215
1216fn deserialize_low_pass_freq(freq: &mut LowPassFreq, raw: &[u8]) -> Result<(), String> {
1217 assert!(raw.len() >= 4);
1218
1219 let mut val = 0u32;
1220 deserialize_u32(&mut val, raw);
1221
1222 *freq = match val {
1223 1 => LowPassFreq::Below12,
1224 2 => LowPassFreq::Below24,
1225 _ => Err(format!("low pass frequency not found for value {}", val))?,
1226 };
1227
1228 Ok(())
1229}
1230
1231pub const STUDIO_MAX_SURROUND_CHANNELS: usize = 8;
1233
1234#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1236pub struct OutGroup {
1237 pub assigned_phys_outs: [bool; STUDIO_PHYS_OUT_PAIR_COUNT * 2],
1239 pub bass_management: bool,
1241 pub sub_channel: Option<usize>,
1243 pub main_cross_over_freq: CrossOverFreq,
1246 pub main_level_to_sub: i32,
1248 pub sub_level_to_sub: i32,
1250 pub main_filter_for_main: HighPassFreq,
1252 pub main_filter_for_sub: LowPassFreq,
1254}
1255
1256impl OutGroup {
1257 const SIZE: usize = 36;
1258}
1259
1260fn serialize_out_group(group: &OutGroup, raw: &mut [u8]) -> Result<(), String> {
1261 assert!(raw.len() >= OutGroup::SIZE);
1262
1263 let mut val = 0u32;
1267 group
1268 .assigned_phys_outs
1269 .iter()
1270 .enumerate()
1271 .filter(|(_, &a)| a)
1272 .take(STUDIO_MAX_SURROUND_CHANNELS)
1273 .for_each(|(i, _)| {
1274 val |= 1 << i;
1275 });
1276 serialize_u32(&val, &mut raw[..4]);
1277 serialize_bool(&group.bass_management, &mut raw[4..8]);
1278 val = match group.sub_channel {
1279 Some(pos) => 1 << pos,
1280 None => 0,
1281 };
1282 serialize_u32(&val, &mut raw[12..16]);
1283 serialize_cross_over_freq(&group.main_cross_over_freq, &mut raw[16..20])?;
1284 serialize_i32(&group.main_level_to_sub, &mut raw[20..24]);
1285 serialize_i32(&group.sub_level_to_sub, &mut raw[24..28]);
1286 serialize_high_pass_freq(&group.main_filter_for_main, &mut raw[28..32])?;
1287 serialize_low_pass_freq(&group.main_filter_for_sub, &mut raw[32..])?;
1288
1289 Ok(())
1290}
1291
1292fn deserialize_out_group(group: &mut OutGroup, raw: &[u8]) -> Result<(), String> {
1293 assert!(raw.len() >= OutGroup::SIZE);
1294
1295 let mut val = 0u32;
1296 deserialize_u32(&mut val, &raw[..4]);
1297 group
1298 .assigned_phys_outs
1299 .iter_mut()
1300 .enumerate()
1301 .for_each(|(i, a)| *a = val & (1 << i) > 0);
1302 deserialize_bool(&mut group.bass_management, &raw[4..8]);
1303 deserialize_u32(&mut val, &raw[12..16]);
1304 group.sub_channel = (0..group.assigned_phys_outs.len())
1305 .position(|i| val & (1 << i) > 0)
1306 .map(|pos| pos as usize);
1307 deserialize_cross_over_freq(&mut group.main_cross_over_freq, &raw[16..20])?;
1308 deserialize_i32(&mut group.main_level_to_sub, &raw[20..24]);
1309 deserialize_i32(&mut group.sub_level_to_sub, &raw[24..28]);
1310 deserialize_high_pass_freq(&mut group.main_filter_for_main, &raw[28..32])?;
1311 deserialize_low_pass_freq(&mut group.main_filter_for_sub, &raw[32..])?;
1312
1313 Ok(())
1314}
1315
1316pub const STUDIO_PHYS_OUT_PAIR_COUNT: usize = 11;
1318
1319pub const STUDIO_OUTPUT_GROUP_COUNT: usize = 3;
1321
1322#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1324pub struct StudioPhysOut {
1325 pub master_out: OutPair,
1327 pub selected_out_grp: usize,
1329 pub out_pair_srcs: [PhysOutPairSrc; STUDIO_PHYS_OUT_PAIR_COUNT],
1337 pub out_assign_to_grp: [bool; STUDIO_PHYS_OUT_PAIR_COUNT * 2],
1339 pub out_mutes: [bool; STUDIO_PHYS_OUT_PAIR_COUNT * 2],
1341 pub out_grps: [OutGroup; STUDIO_OUTPUT_GROUP_COUNT],
1343}
1344
1345impl TcKonnektSegmentSerdes<StudioPhysOut> for Studiok48Protocol {
1346 const NAME: &'static str = "physical-output";
1347 const OFFSET: usize = 0x03dc;
1348 const SIZE: usize = 440;
1349
1350 fn serialize(params: &StudioPhysOut, raw: &mut [u8]) -> Result<(), String> {
1351 serialize_out_pair(¶ms.master_out, &mut raw[..12])?;
1352 params
1353 .out_pair_srcs
1354 .iter()
1355 .enumerate()
1356 .try_for_each(|(i, p)| {
1357 let pos = 16 + i * PhysOutPairSrc::SIZE;
1358 serialize_phys_out_pair_src(p, &mut raw[pos..(pos + PhysOutPairSrc::SIZE)])
1359 })?;
1360 serialize_usize(¶ms.selected_out_grp, &mut raw[12..16]);
1361 let mut val = 0u32;
1362 params
1363 .out_assign_to_grp
1364 .iter()
1365 .enumerate()
1366 .filter(|(_, &m)| m)
1367 .for_each(|(i, _)| {
1368 val |= 1 << i;
1369 });
1370 serialize_u32(&val, &mut raw[324..328]);
1371 let mut val = 0u32;
1372 params
1373 .out_mutes
1374 .iter()
1375 .enumerate()
1376 .filter(|(_, &d)| d)
1377 .for_each(|(i, _)| {
1378 val |= 1 << i;
1379 });
1380 serialize_u32(&val, &mut raw[328..332]);
1381 params.out_grps.iter().enumerate().try_for_each(|(i, s)| {
1382 let pos = 332 + OutGroup::SIZE * i;
1383 serialize_out_group(s, &mut raw[pos..(pos + OutGroup::SIZE)])
1384 })?;
1385 Ok(())
1386 }
1387
1388 fn deserialize(params: &mut StudioPhysOut, raw: &[u8]) -> Result<(), String> {
1389 deserialize_out_pair(&mut params.master_out, &raw[..12])?;
1390 params
1391 .out_pair_srcs
1392 .iter_mut()
1393 .enumerate()
1394 .try_for_each(|(i, p)| {
1395 let pos = 16 + i * PhysOutPairSrc::SIZE;
1396 deserialize_phys_out_pair_src(p, &raw[pos..(pos + PhysOutPairSrc::SIZE)])
1397 })?;
1398 let mut val = 0u32;
1399 deserialize_u32(&mut val, &raw[12..16]);
1400 deserialize_usize(&mut params.selected_out_grp, &raw[324..328]);
1401 params
1402 .out_assign_to_grp
1403 .iter_mut()
1404 .enumerate()
1405 .for_each(|(i, m)| {
1406 *m = val & (1 << i) > 0;
1407 });
1408 let mut val = 0u32;
1409 deserialize_u32(&mut val, &raw[328..332]);
1410 params.out_mutes.iter_mut().enumerate().for_each(|(i, d)| {
1411 *d = val & (1 << i) > 0;
1412 });
1413 params
1414 .out_grps
1415 .iter_mut()
1416 .enumerate()
1417 .try_for_each(|(i, s)| {
1418 let pos = 332 + OutGroup::SIZE * i;
1419 deserialize_out_group(s, &raw[pos..(pos + OutGroup::SIZE)])
1420 })?;
1421 Ok(())
1422 }
1423}
1424
1425impl TcKonnektMutableSegmentOperation<StudioPhysOut> for Studiok48Protocol {}
1426
1427impl TcKonnektNotifiedSegmentOperation<StudioPhysOut> for Studiok48Protocol {
1428 const NOTIFY_FLAG: u32 = STUDIO_PHYS_OUT_NOTIFY_FLAG;
1429}
1430
1431const STUDIO_CH_STRIP_COUNT: usize = 4;
1432
1433#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1435pub struct StudioReverbState(pub ReverbState);
1436
1437impl TcKonnektSegmentSerdes<StudioReverbState> for Studiok48Protocol {
1438 const NAME: &'static str = "reverb-state";
1439 const OFFSET: usize = 0x0594;
1440 const SIZE: usize = ReverbState::SIZE;
1441
1442 fn serialize(params: &StudioReverbState, raw: &mut [u8]) -> Result<(), String> {
1443 serialize_reverb_state(¶ms.0, raw)
1444 }
1445
1446 fn deserialize(params: &mut StudioReverbState, raw: &[u8]) -> Result<(), String> {
1447 deserialize_reverb_state(&mut params.0, raw)
1448 }
1449}
1450
1451impl TcKonnektMutableSegmentOperation<StudioReverbState> for Studiok48Protocol {}
1452
1453impl TcKonnektNotifiedSegmentOperation<StudioReverbState> for Studiok48Protocol {
1454 const NOTIFY_FLAG: u32 = STUDIO_REVERB_NOTIFY_CHANGE;
1455}
1456
1457impl AsRef<ReverbState> for StudioReverbState {
1458 fn as_ref(&self) -> &ReverbState {
1459 &self.0
1460 }
1461}
1462
1463impl AsMut<ReverbState> for StudioReverbState {
1464 fn as_mut(&mut self) -> &mut ReverbState {
1465 &mut self.0
1466 }
1467}
1468
1469#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1471pub struct StudioChStripStates(pub [ChStripState; STUDIO_CH_STRIP_COUNT]);
1472
1473impl TcKonnektSegmentSerdes<StudioChStripStates> for Studiok48Protocol {
1474 const NAME: &'static str = "channel-strip-state";
1475 const OFFSET: usize = 0x05dc;
1476 const SIZE: usize = ChStripState::SIZE * STUDIO_CH_STRIP_COUNT + 8;
1477
1478 fn serialize(params: &StudioChStripStates, raw: &mut [u8]) -> Result<(), String> {
1479 serialize_ch_strip_states(¶ms.0, raw)
1480 }
1481
1482 fn deserialize(params: &mut StudioChStripStates, raw: &[u8]) -> Result<(), String> {
1483 deserialize_ch_strip_states(&mut params.0, raw)
1484 }
1485}
1486
1487impl TcKonnektMutableSegmentOperation<StudioChStripStates> for Studiok48Protocol {}
1488
1489impl TcKonnektNotifiedSegmentOperation<StudioChStripStates> for Studiok48Protocol {
1490 const NOTIFY_FLAG: u32 = STUDIO_CH_STRIP_NOTIFY_01_CHANGE | STUDIO_CH_STRIP_NOTIFY_23_CHANGE;
1491}
1492
1493impl AsRef<[ChStripState]> for StudioChStripStates {
1494 fn as_ref(&self) -> &[ChStripState] {
1495 &self.0
1496 }
1497}
1498
1499impl AsMut<[ChStripState]> for StudioChStripStates {
1500 fn as_mut(&mut self) -> &mut [ChStripState] {
1501 &mut self.0
1502 }
1503}
1504
1505#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1506pub enum StudioAnalogJackState {
1508 FrontSelected,
1510 FrontInserted,
1512 RearSelected,
1514 RearInserted,
1516}
1517
1518impl Default for StudioAnalogJackState {
1519 fn default() -> Self {
1520 Self::FrontSelected
1521 }
1522}
1523
1524fn serialize_analog_jack_state(
1525 state: &StudioAnalogJackState,
1526 raw: &mut [u8],
1527) -> Result<(), String> {
1528 assert!(raw.len() >= 4);
1529
1530 let val = match state {
1531 StudioAnalogJackState::FrontSelected => 5,
1532 StudioAnalogJackState::FrontInserted => 6,
1533 StudioAnalogJackState::RearSelected => 7,
1534 StudioAnalogJackState::RearInserted => 8,
1535 };
1536
1537 serialize_u32(&val, raw);
1538
1539 Ok(())
1540}
1541
1542fn deserialize_analog_jack_state(
1543 state: &mut StudioAnalogJackState,
1544 raw: &[u8],
1545) -> Result<(), String> {
1546 assert!(raw.len() >= 4);
1547
1548 let mut val = 0u32;
1549 deserialize_u32(&mut val, raw);
1550
1551 *state = match val {
1552 8 => StudioAnalogJackState::RearInserted,
1553 7 => StudioAnalogJackState::RearSelected,
1554 6 => StudioAnalogJackState::FrontInserted,
1555 _ => StudioAnalogJackState::FrontSelected,
1556 };
1557
1558 Ok(())
1559}
1560
1561pub const STUDIO_ANALOG_JACK_STATE_COUNT: usize = 12;
1563
1564#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1566pub struct StudioHwState {
1567 pub analog_jack_states: [StudioAnalogJackState; STUDIO_ANALOG_JACK_STATE_COUNT],
1569 pub hp_state: [bool; 2],
1571 pub firewire_led: FireWireLedState,
1573 pub valid_master_level: bool,
1576}
1577
1578impl TcKonnektSegmentSerdes<StudioHwState> for Studiok48Protocol {
1579 const NAME: &'static str = "hardware-state";
1580 const OFFSET: usize = 0x2008;
1581 const SIZE: usize = 68;
1582
1583 fn serialize(params: &StudioHwState, raw: &mut [u8]) -> Result<(), String> {
1584 params
1585 .analog_jack_states
1586 .iter()
1587 .enumerate()
1588 .try_for_each(|(i, state)| {
1589 let pos = 4 * i;
1590 serialize_analog_jack_state(state, &mut raw[pos..(pos + 4)])
1591 })?;
1592 serialize_bool(¶ms.hp_state[0], &mut raw[48..56]);
1593 serialize_bool(¶ms.hp_state[1], &mut raw[48..56]);
1594 serialize_fw_led_state(¶ms.firewire_led, &mut raw[56..60])?;
1595 serialize_bool(¶ms.valid_master_level, &mut raw[60..64]);
1596 Ok(())
1597 }
1598
1599 fn deserialize(params: &mut StudioHwState, raw: &[u8]) -> Result<(), String> {
1600 params
1601 .analog_jack_states
1602 .iter_mut()
1603 .enumerate()
1604 .try_for_each(|(i, state)| {
1605 let pos = 4 * i;
1606 deserialize_analog_jack_state(state, &raw[pos..(pos + 4)])
1607 })?;
1608 deserialize_bool(&mut params.hp_state[0], &raw[48..52]);
1609 deserialize_bool(&mut params.hp_state[1], &raw[52..56]);
1610 deserialize_fw_led_state(&mut params.firewire_led, &raw[56..60])?;
1611 deserialize_bool(&mut params.valid_master_level, &raw[60..64]);
1612 Ok(())
1613 }
1614}
1615
1616impl TcKonnektMutableSegmentOperation<StudioHwState> for Studiok48Protocol {}
1617
1618impl TcKonnektNotifiedSegmentOperation<StudioHwState> for Studiok48Protocol {
1619 const NOTIFY_FLAG: u32 = STUDIO_HW_STATE_NOTIFY_FLAG;
1620}
1621
1622impl AsRef<FireWireLedState> for StudioHwState {
1623 fn as_ref(&self) -> &FireWireLedState {
1624 &self.firewire_led
1625 }
1626}
1627
1628impl AsMut<FireWireLedState> for StudioHwState {
1629 fn as_mut(&mut self) -> &mut FireWireLedState {
1630 &mut self.firewire_led
1631 }
1632}
1633
1634#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1636pub struct StudioMixerMeter {
1637 pub src_inputs: [i32; 24],
1639 pub mixer_outputs: [i32; 2],
1641 pub aux_outputs: [i32; 4],
1643}
1644
1645impl TcKonnektSegmentSerdes<StudioMixerMeter> for Studiok48Protocol {
1646 const NAME: &'static str = "mixer-meter";
1647 const OFFSET: usize = 0x20b8;
1648 const SIZE: usize = 128;
1649
1650 fn serialize(params: &StudioMixerMeter, raw: &mut [u8]) -> Result<(), String> {
1651 params
1652 .src_inputs
1653 .iter()
1654 .chain(¶ms.mixer_outputs)
1655 .chain(¶ms.aux_outputs)
1656 .enumerate()
1657 .for_each(|(i, level)| {
1658 let pos = i * 4;
1659 serialize_i32(level, &mut raw[pos..(pos + 4)])
1660 });
1661
1662 Ok(())
1663 }
1664
1665 fn deserialize(params: &mut StudioMixerMeter, raw: &[u8]) -> Result<(), String> {
1666 params
1667 .src_inputs
1668 .iter_mut()
1669 .chain(&mut params.mixer_outputs)
1670 .chain(&mut params.aux_outputs)
1671 .enumerate()
1672 .for_each(|(i, level)| {
1673 let pos = i * 4;
1674 deserialize_i32(level, &raw[pos..(pos + 4)])
1675 });
1676
1677 Ok(())
1678 }
1679}
1680
1681#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1683pub struct StudioReverbMeter(pub ReverbMeter);
1684
1685impl TcKonnektSegmentSerdes<StudioReverbMeter> for Studiok48Protocol {
1686 const NAME: &'static str = "reverb-meter";
1687 const OFFSET: usize = 0x2164;
1688 const SIZE: usize = ReverbMeter::SIZE;
1689
1690 fn serialize(params: &StudioReverbMeter, raw: &mut [u8]) -> Result<(), String> {
1691 serialize_reverb_meter(¶ms.0, raw)
1692 }
1693
1694 fn deserialize(params: &mut StudioReverbMeter, raw: &[u8]) -> Result<(), String> {
1695 deserialize_reverb_meter(&mut params.0, raw)
1696 }
1697}
1698
1699impl AsRef<ReverbMeter> for StudioReverbMeter {
1700 fn as_ref(&self) -> &ReverbMeter {
1701 &self.0
1702 }
1703}
1704
1705impl AsMut<ReverbMeter> for StudioReverbMeter {
1706 fn as_mut(&mut self) -> &mut ReverbMeter {
1707 &mut self.0
1708 }
1709}
1710
1711#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1713pub struct StudioChStripMeters(pub [ChStripMeter; STUDIO_CH_STRIP_COUNT]);
1714
1715impl TcKonnektSegmentSerdes<StudioChStripMeters> for Studiok48Protocol {
1716 const NAME: &'static str = "channel-strip-meter";
1717 const OFFSET: usize = 0x217c;
1718 const SIZE: usize = ChStripMeter::SIZE * STUDIO_CH_STRIP_COUNT + 8;
1719
1720 fn serialize(params: &StudioChStripMeters, raw: &mut [u8]) -> Result<(), String> {
1721 serialize_ch_strip_meters(¶ms.0, raw)
1722 }
1723
1724 fn deserialize(params: &mut StudioChStripMeters, raw: &[u8]) -> Result<(), String> {
1725 deserialize_ch_strip_meters(&mut params.0, raw)
1726 }
1727}
1728
1729impl AsRef<[ChStripMeter]> for StudioChStripMeters {
1730 fn as_ref(&self) -> &[ChStripMeter] {
1731 &self.0
1732 }
1733}
1734
1735impl AsMut<[ChStripMeter]> for StudioChStripMeters {
1736 fn as_mut(&mut self) -> &mut [ChStripMeter] {
1737 &mut self.0
1738 }
1739}