1use super::*;
188
189#[derive(Default, Debug)]
191pub struct Fw410ClkProtocol;
192
193impl MediaClockFrequencyOperation for Fw410ClkProtocol {
194 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000, 176400, 192000];
195}
196
197impl SamplingClockSourceOperation for Fw410ClkProtocol {
198 const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
199 subunit: MUSIC_SUBUNIT_0,
200 plug_id: 0x01,
201 });
202
203 const SRC_LIST: &'static [SignalAddr] = &[
204 SignalAddr::Subunit(SignalSubunitAddr {
206 subunit: MUSIC_SUBUNIT_0,
207 plug_id: 0x01,
208 }),
209 SignalAddr::Unit(SignalUnitAddr::Ext(0x02)),
211 ];
212}
213
214#[derive(Default, Debug)]
216pub struct Fw410MeterProtocol;
217
218impl MaudioNormalMeterProtocol for Fw410MeterProtocol {
219 const PHYS_INPUT_COUNT: usize = 4;
220 const STREAM_INPUT_COUNT: usize = 0;
221 const PHYS_OUTPUT_COUNT: usize = 10;
222 const ROTARY_COUNT: usize = 1;
223 const HAS_SWITCH: bool = false;
224 const HAS_SYNC_STATUS: bool = true;
225}
226
227#[derive(Default, Debug)]
229pub struct Fw410PhysInputProtocol;
230
231impl AvcAudioFeatureSpecification for Fw410PhysInputProtocol {
232 const ENTRIES: &'static [(u8, AudioCh)] = &[
233 (0x03, AudioCh::Each(0)), (0x03, AudioCh::Each(1)), (0x04, AudioCh::Each(0)), (0x04, AudioCh::Each(1)), ];
238}
239
240impl AvcLevelOperation for Fw410PhysInputProtocol {}
241
242impl AvcLrBalanceOperation for Fw410PhysInputProtocol {}
243
244#[derive(Default, Debug)]
246pub struct Fw410PhysOutputProtocol;
247
248impl AvcAudioFeatureSpecification for Fw410PhysOutputProtocol {
249 const ENTRIES: &'static [(u8, AudioCh)] = &[
250 (0x0a, AudioCh::Each(0)), (0x0a, AudioCh::Each(1)), (0x0b, AudioCh::Each(0)), (0x0b, AudioCh::Each(1)), (0x0c, AudioCh::Each(0)), (0x0c, AudioCh::Each(1)), (0x0d, AudioCh::Each(0)), (0x0d, AudioCh::Each(1)), (0x0e, AudioCh::Each(0)), (0x0e, AudioCh::Each(1)), ];
261}
262
263impl AvcLevelOperation for Fw410PhysOutputProtocol {}
264
265impl AvcSelectorOperation for Fw410PhysOutputProtocol {
266 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x02, 0x03, 0x04, 0x05, 0x06];
269 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01];
271}
272
273#[derive(Default, Debug)]
275pub struct Fw410AuxSourceProtocol;
276
277impl AvcAudioFeatureSpecification for Fw410AuxSourceProtocol {
278 const ENTRIES: &'static [(u8, AudioCh)] = &[
279 (0x07, AudioCh::Each(0)), (0x07, AudioCh::Each(1)), (0x08, AudioCh::Each(0)), (0x08, AudioCh::Each(1)), (0x06, AudioCh::Each(0)), (0x06, AudioCh::Each(1)), (0x05, AudioCh::Each(0)), (0x05, AudioCh::Each(1)), (0x05, AudioCh::Each(2)), (0x05, AudioCh::Each(3)), (0x05, AudioCh::Each(4)), (0x05, AudioCh::Each(5)), (0x05, AudioCh::Each(6)), (0x05, AudioCh::Each(7)), ];
294}
295
296impl AvcLevelOperation for Fw410AuxSourceProtocol {}
297
298#[derive(Default, Debug)]
300pub struct Fw410AuxOutputProtocol;
301
302impl AvcAudioFeatureSpecification for Fw410AuxOutputProtocol {
303 const ENTRIES: &'static [(u8, AudioCh)] = &[
304 (0x09, AudioCh::Each(0)), (0x09, AudioCh::Each(1)), ];
307}
308
309impl AvcLevelOperation for Fw410AuxOutputProtocol {}
310
311#[derive(Default, Debug)]
313pub struct Fw410HeadphoneProtocol;
314
315impl AvcAudioFeatureSpecification for Fw410HeadphoneProtocol {
316 const ENTRIES: &'static [(u8, AudioCh)] = &[
317 (0x0f, AudioCh::Each(0)), (0x0f, AudioCh::Each(1)), ];
320}
321
322impl AvcLevelOperation for Fw410HeadphoneProtocol {}
323
324impl AvcSelectorOperation for Fw410HeadphoneProtocol {
325 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x07];
326 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01];
328}
329
330#[derive(Default, Debug)]
332pub struct Fw410SpdifOutputProtocol;
333
334impl AvcSelectorOperation for Fw410SpdifOutputProtocol {
335 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x01];
336 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01];
338}
339
340#[derive(Default, Debug)]
342pub struct Fw410MixerProtocol;
343
344impl MaudioNormalMixerOperation for Fw410MixerProtocol {
345 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
346 (0x01, AudioCh::Each(0)), (0x01, AudioCh::Each(2)), (0x01, AudioCh::Each(4)), (0x01, AudioCh::Each(6)), (0x01, AudioCh::Each(8)), ];
352 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
353 (0x02, AudioCh::Each(0)), (0x03, AudioCh::Each(0)), (0x01, AudioCh::Each(0)), (0x00, AudioCh::Each(0)), (0x00, AudioCh::Each(2)), (0x00, AudioCh::Each(4)), (0x00, AudioCh::Each(6)), ];
361}
362
363impl MaudioNormalMixerOperation for Fw410HeadphoneProtocol {
364 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[(0x07, AudioCh::Each(0))];
365 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
366 (0x00, AudioCh::Each(0)), (0x00, AudioCh::Each(2)), (0x00, AudioCh::Each(4)), (0x00, AudioCh::Each(6)), (0x00, AudioCh::Each(8)), ];
372}
373
374#[derive(Default, Debug)]
376pub struct SoloClkProtocol;
377
378impl MediaClockFrequencyOperation for SoloClkProtocol {
379 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000];
380}
381
382impl SamplingClockSourceOperation for SoloClkProtocol {
383 const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
384 subunit: MUSIC_SUBUNIT_0,
385 plug_id: 0x01,
386 });
387
388 const SRC_LIST: &'static [SignalAddr] = &[
389 SignalAddr::Subunit(SignalSubunitAddr {
391 subunit: MUSIC_SUBUNIT_0,
392 plug_id: 0x01,
393 }),
394 SignalAddr::Unit(SignalUnitAddr::Ext(0x01)),
396 ];
397}
398
399#[derive(Default, Debug)]
401pub struct SoloMeterProtocol;
402
403impl MaudioNormalMeterProtocol for SoloMeterProtocol {
404 const PHYS_INPUT_COUNT: usize = 4;
405 const STREAM_INPUT_COUNT: usize = 4;
406 const PHYS_OUTPUT_COUNT: usize = 4;
407 const ROTARY_COUNT: usize = 0;
408 const HAS_SWITCH: bool = false;
409 const HAS_SYNC_STATUS: bool = true;
410}
411
412#[derive(Default, Debug)]
414pub struct SoloPhysInputProtocol;
415
416impl AvcAudioFeatureSpecification for SoloPhysInputProtocol {
417 const ENTRIES: &'static [(u8, AudioCh)] = &[
418 (0x03, AudioCh::Each(0)), (0x03, AudioCh::Each(1)), (0x04, AudioCh::Each(0)), (0x04, AudioCh::Each(1)), ];
423}
424
425impl AvcLevelOperation for SoloPhysInputProtocol {}
426
427impl AvcLrBalanceOperation for SoloPhysInputProtocol {}
428
429#[derive(Default, Debug)]
431pub struct SoloStreamInputProtocol;
432
433impl AvcAudioFeatureSpecification for SoloStreamInputProtocol {
434 const ENTRIES: &'static [(u8, AudioCh)] = &[
435 (0x01, AudioCh::Each(0)), (0x01, AudioCh::Each(1)), (0x02, AudioCh::Each(0)), (0x02, AudioCh::Each(1)), ];
440}
441
442impl AvcLevelOperation for SoloStreamInputProtocol {}
443
444#[derive(Default, Debug)]
448pub struct SoloSpdifOutputProtocol;
449
450impl AvcSelectorOperation for SoloSpdifOutputProtocol {
451 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x01];
452 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01];
454}
455
456#[derive(Default, Debug)]
458pub struct SoloMixerProtocol;
459
460impl MaudioNormalMixerOperation for SoloMixerProtocol {
461 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
462 (0x01, AudioCh::Each(0)),
464 (0x01, AudioCh::Each(2)), ];
466 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
467 (0x00, AudioCh::Each(0)), (0x01, AudioCh::Each(0)), (0x02, AudioCh::Each(0)), (0x03, AudioCh::Each(0)), ];
472}
473
474#[derive(Default, Debug)]
476pub struct AudiophileClkProtocol;
477
478impl MediaClockFrequencyOperation for AudiophileClkProtocol {
479 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000];
480}
481
482impl SamplingClockSourceOperation for AudiophileClkProtocol {
483 const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
484 subunit: MUSIC_SUBUNIT_0,
485 plug_id: 0x01,
486 });
487
488 const SRC_LIST: &'static [SignalAddr] = &[
489 SignalAddr::Subunit(SignalSubunitAddr {
491 subunit: MUSIC_SUBUNIT_0,
492 plug_id: 0x01,
493 }),
494 SignalAddr::Unit(SignalUnitAddr::Ext(0x02)),
496 ];
497}
498
499#[derive(Default, Debug)]
501pub struct AudiophileMeterProtocol;
502
503impl MaudioNormalMeterProtocol for AudiophileMeterProtocol {
504 const PHYS_INPUT_COUNT: usize = 4;
505 const STREAM_INPUT_COUNT: usize = 0;
506 const PHYS_OUTPUT_COUNT: usize = 6;
507 const ROTARY_COUNT: usize = 2;
508 const HAS_SWITCH: bool = true;
509 const HAS_SYNC_STATUS: bool = true;
510}
511
512#[derive(Default, Debug)]
514pub struct AudiophilePhysInputProtocol;
515
516impl AvcAudioFeatureSpecification for AudiophilePhysInputProtocol {
517 const ENTRIES: &'static [(u8, AudioCh)] = &[
518 (0x04, AudioCh::Each(0)), (0x04, AudioCh::Each(1)), (0x05, AudioCh::Each(0)), (0x05, AudioCh::Each(1)), ];
523}
524
525impl AvcLevelOperation for AudiophilePhysInputProtocol {}
526
527impl AvcLrBalanceOperation for AudiophilePhysInputProtocol {}
528
529#[derive(Default, Debug)]
531pub struct AudiophilePhysOutputProtocol;
532
533impl AvcAudioFeatureSpecification for AudiophilePhysOutputProtocol {
534 const ENTRIES: &'static [(u8, AudioCh)] = &[
535 (0x0c, AudioCh::Each(0)), (0x0c, AudioCh::Each(1)), (0x0d, AudioCh::Each(0)), (0x0d, AudioCh::Each(1)), (0x0e, AudioCh::Each(0)), (0x0e, AudioCh::Each(1)), ];
542}
543
544impl AvcLevelOperation for AudiophilePhysOutputProtocol {}
545
546impl AvcSelectorOperation for AudiophilePhysOutputProtocol {
547 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x01, 0x02, 0x03];
549 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01];
551}
552
553#[derive(Default, Debug)]
555pub struct AudiophileAuxSourceProtocol;
556
557impl AvcAudioFeatureSpecification for AudiophileAuxSourceProtocol {
558 const ENTRIES: &'static [(u8, AudioCh)] = &[
559 (0x09, AudioCh::Each(0)), (0x09, AudioCh::Each(1)), (0x0a, AudioCh::Each(0)), (0x0a, AudioCh::Each(1)), (0x06, AudioCh::Each(0)), (0x06, AudioCh::Each(1)), (0x07, AudioCh::Each(0)), (0x07, AudioCh::Each(1)), (0x08, AudioCh::Each(0)), (0x08, AudioCh::Each(1)), ];
570}
571
572impl AvcLevelOperation for AudiophileAuxSourceProtocol {}
573
574#[derive(Default, Debug)]
576pub struct AudiophileAuxOutputProtocol;
577
578impl AvcAudioFeatureSpecification for AudiophileAuxOutputProtocol {
579 const ENTRIES: &'static [(u8, AudioCh)] = &[
580 (0x0b, AudioCh::Each(0)), (0x0b, AudioCh::Each(1)), ];
583}
584
585impl AvcLevelOperation for AudiophileAuxOutputProtocol {}
586
587#[derive(Default, Debug)]
589pub struct AudiophileHeadphoneProtocol;
590
591impl AvcAudioFeatureSpecification for AudiophileHeadphoneProtocol {
592 const ENTRIES: &'static [(u8, AudioCh)] = &[
593 (0x0f, AudioCh::Each(0)), (0x0f, AudioCh::Each(1)), ];
596}
597
598impl AvcLevelOperation for AudiophileHeadphoneProtocol {}
599
600impl AvcSelectorOperation for AudiophileHeadphoneProtocol {
601 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x04];
602 const INPUT_PLUG_ID_LIST: &'static [u8] = &[0x00, 0x01, 0x02, 0x03];
604}
605
606#[derive(Default, Debug)]
608pub struct AudiophileMixerProtocol;
609
610impl MaudioNormalMixerOperation for AudiophileMixerProtocol {
611 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
612 (0x01, AudioCh::Each(0)), (0x02, AudioCh::Each(0)), (0x03, AudioCh::Each(0)), ];
616 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
617 (0x03, AudioCh::Each(0)), (0x04, AudioCh::Each(0)), (0x00, AudioCh::Each(0)), (0x01, AudioCh::Each(0)), (0x02, AudioCh::Each(0)), ];
623}
624
625#[derive(Default, Debug)]
627pub struct OzonicClkProtocol;
628
629impl MediaClockFrequencyOperation for OzonicClkProtocol {
630 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000];
631}
632
633impl SamplingClockSourceOperation for OzonicClkProtocol {
634 const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
635 subunit: MUSIC_SUBUNIT_0,
636 plug_id: 0x05,
637 });
638
639 const SRC_LIST: &'static [SignalAddr] = &[
640 SignalAddr::Subunit(SignalSubunitAddr {
642 subunit: MUSIC_SUBUNIT_0,
643 plug_id: 0x05,
644 }),
645 ];
646}
647
648#[derive(Default, Debug)]
650pub struct OzonicMeterProtocol;
651
652impl MaudioNormalMeterProtocol for OzonicMeterProtocol {
653 const PHYS_INPUT_COUNT: usize = 4;
654 const STREAM_INPUT_COUNT: usize = 4;
655 const PHYS_OUTPUT_COUNT: usize = 4;
656 const ROTARY_COUNT: usize = 0;
657 const HAS_SWITCH: bool = false;
658 const HAS_SYNC_STATUS: bool = false;
659}
660
661#[derive(Default, Debug)]
663pub struct OzonicPhysInputProtocol;
664
665impl AvcAudioFeatureSpecification for OzonicPhysInputProtocol {
666 const ENTRIES: &'static [(u8, AudioCh)] = &[
667 (0x03, AudioCh::Each(0)), (0x03, AudioCh::Each(1)), (0x04, AudioCh::Each(0)), (0x04, AudioCh::Each(1)), ];
672}
673
674impl AvcLevelOperation for OzonicPhysInputProtocol {}
675
676impl AvcLrBalanceOperation for OzonicPhysInputProtocol {}
677
678#[derive(Default, Debug)]
680pub struct OzonicStreamInputProtocol;
681
682impl AvcAudioFeatureSpecification for OzonicStreamInputProtocol {
683 const ENTRIES: &'static [(u8, AudioCh)] = &[
684 (0x01, AudioCh::Each(0)), (0x01, AudioCh::Each(1)), (0x02, AudioCh::Each(0)), (0x02, AudioCh::Each(1)), ];
689}
690
691impl AvcLevelOperation for OzonicStreamInputProtocol {}
692
693#[derive(Debug, Clone, Copy, Eq, PartialEq)]
697pub enum AudiophileSwitchState {
698 Off,
699 A,
700 B,
701}
702
703impl Default for AudiophileSwitchState {
704 fn default() -> Self {
705 Self::Off
706 }
707}
708
709impl AudiophileSwitchState {
710 const VALUE_OFF: u8 = 0x00;
711 const VALUE_A: u8 = 0x01;
712 const VALUE_B: u8 = 0x02;
713
714 fn to_val(&self) -> u8 {
715 match self {
716 Self::Off => Self::VALUE_OFF,
717 Self::A => Self::VALUE_A,
718 Self::B => Self::VALUE_B,
719 }
720 }
721
722 #[allow(dead_code)]
723 fn from_val(val: u8) -> Self {
724 match val {
725 Self::VALUE_A => Self::A,
726 Self::VALUE_B => Self::B,
727 _ => Self::Off,
728 }
729 }
730}
731
732pub struct AudiophileLedSwitch {
735 state: AudiophileSwitchState,
736 op: VendorDependent,
737}
738
739impl AudiophileLedSwitch {
740 pub fn new(switch_state: AudiophileSwitchState) -> Self {
741 let mut instance = Self::default();
742 instance.state = switch_state;
743 instance
744 }
745}
746
747impl Default for AudiophileLedSwitch {
748 fn default() -> Self {
749 Self {
750 state: Default::default(),
751 op: VendorDependent {
752 company_id: MAUDIO_OUI,
753 data: vec![0x02, 0x00, 0x01, 0xff, 0xff, 0xff],
754 },
755 }
756 }
757}
758
759impl AvcOp for AudiophileLedSwitch {
760 const OPCODE: u8 = VendorDependent::OPCODE;
761}
762
763impl AvcControl for AudiophileLedSwitch {
764 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
765 self.op.data[3] = self.state.to_val();
766 AvcControl::build_operands(&mut self.op, addr)
767 }
768
769 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
770 AvcControl::parse_operands(&mut self.op, addr, operands)
771 }
772}
773
774#[derive(Debug, Clone, PartialEq, Eq)]
777pub struct MaudioNormalMeter {
778 pub phys_inputs: Vec<i32>,
779 pub stream_inputs: Option<Vec<i32>>,
780 pub phys_outputs: Vec<i32>,
781 pub headphone: Option<[i32; 2]>,
782 pub aux_output: Option<[i32; 2]>,
783 pub rotaries: Option<[i32; 2]>,
784 pub switch: Option<AudiophileSwitchState>,
785 pub sync_status: Option<bool>,
786
787 cache: Vec<u8>,
788}
789
790pub trait MaudioNormalMeterProtocol {
792 const PHYS_INPUT_COUNT: usize;
793 const STREAM_INPUT_COUNT: usize;
794 const PHYS_OUTPUT_COUNT: usize;
795 const ROTARY_COUNT: usize;
796 const HAS_SWITCH: bool;
797 const HAS_SYNC_STATUS: bool;
798
799 const LEVEL_MIN: i32 = 0;
800 const LEVEL_MAX: i32 = i32::MAX;
801 const LEVEL_STEP: i32 = 0x100;
802
803 const ROTARY_MIN: i32 = 0;
804 const ROTARY_MAX: i32 = i16::MAX as i32;
805 const ROTARY_STEP: i32 = 0x200;
806
807 fn create_meter() -> MaudioNormalMeter {
808 let mut meter = MaudioNormalMeter {
809 phys_inputs: vec![0; Self::PHYS_INPUT_COUNT],
810 stream_inputs: Default::default(),
811 phys_outputs: vec![0; Self::PHYS_OUTPUT_COUNT],
812 headphone: Default::default(),
813 aux_output: Default::default(),
814 rotaries: Default::default(),
815 switch: Default::default(),
816 sync_status: Default::default(),
817 cache: vec![0; Self::calculate_meter_frame_size()],
818 };
819
820 if Self::STREAM_INPUT_COUNT > 0 {
821 meter.stream_inputs = Some(vec![0; Self::STREAM_INPUT_COUNT]);
822 } else {
823 meter.headphone = Some(Default::default());
824 meter.aux_output = Some(Default::default());
825 }
826
827 if Self::ROTARY_COUNT > 0 {
828 meter.rotaries = Some(Default::default());
829 }
830
831 if Self::HAS_SWITCH {
832 meter.switch = Some(Default::default());
833 }
834
835 if Self::HAS_SYNC_STATUS {
836 meter.sync_status = Some(Default::default());
837 }
838
839 meter
840 }
841
842 fn calculate_meter_frame_size() -> usize {
843 let mut size = Self::PHYS_INPUT_COUNT + Self::PHYS_OUTPUT_COUNT;
844
845 if Self::STREAM_INPUT_COUNT > 0 {
846 size += Self::STREAM_INPUT_COUNT;
847 } else {
848 size += 4;
850 }
851
852 if Self::ROTARY_COUNT > 0 || Self::HAS_SWITCH || Self::HAS_SYNC_STATUS {
853 size += 1;
854 }
855
856 size * 4
857 }
858
859 fn read_meter(
860 req: &FwReq,
861 node: &FwNode,
862 meter: &mut MaudioNormalMeter,
863 timeout_ms: u32,
864 ) -> Result<(), Error> {
865 let frame = &mut meter.cache;
866
867 let mut bitmap = [0; 4];
869 let pos = frame.len() - 4;
870 bitmap.copy_from_slice(&frame[pos..]);
871
872 req.transaction_sync(
873 node,
874 FwTcode::ReadBlockRequest,
875 DM_APPL_METER_OFFSET,
876 frame.len(),
877 frame,
878 timeout_ms,
879 )?;
880
881 let mut quadlet = [0; 4];
882
883 meter.phys_inputs.iter_mut().enumerate().for_each(|(i, m)| {
884 let pos = i * 4;
885 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
886 *m = i32::from_be_bytes(quadlet);
887 });
888
889 if let Some(stream_inputs) = &mut meter.stream_inputs {
890 stream_inputs.iter_mut().enumerate().for_each(|(i, m)| {
891 let pos = (Self::PHYS_INPUT_COUNT + i) * 4;
892 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
893 *m = i32::from_be_bytes(quadlet);
894 });
895 }
896
897 meter
898 .phys_outputs
899 .iter_mut()
900 .enumerate()
901 .for_each(|(i, m)| {
902 let pos = (Self::PHYS_INPUT_COUNT + Self::STREAM_INPUT_COUNT + i) * 4;
903 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
904 *m = i32::from_be_bytes(quadlet);
905 });
906
907 if let Some(headphone) = &mut meter.headphone {
908 headphone.iter_mut().enumerate().for_each(|(i, m)| {
909 let pos = (Self::PHYS_INPUT_COUNT + Self::PHYS_OUTPUT_COUNT + i) * 4;
910 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
911 *m = i32::from_be_bytes(quadlet);
912 });
913 }
914
915 if let Some(aux_output) = &mut meter.aux_output {
916 aux_output.iter_mut().enumerate().for_each(|(i, m)| {
917 let pos = (Self::PHYS_INPUT_COUNT + Self::PHYS_OUTPUT_COUNT + 2 + i) * 4;
918 quadlet.copy_from_slice(&frame[pos..(pos + 4)]);
919 *m = i32::from_be_bytes(quadlet);
920 });
921 }
922
923 if let Some(rotaries) = &mut meter.rotaries {
924 rotaries.iter_mut().enumerate().for_each(|(i, r)| {
925 let shift = i * 4;
926 if (bitmap[1] ^ frame[frame.len() - 3]) & (0x0f << shift) > 0 {
927 let flag = (frame[frame.len() - 3] >> shift) & 0x0f;
928 if flag == 0x01 {
929 if *r <= Self::ROTARY_MAX - Self::ROTARY_STEP {
930 *r += Self::ROTARY_STEP;
931 }
932 } else if flag == 0x02 {
933 if *r >= Self::ROTARY_MIN + Self::ROTARY_STEP {
934 *r -= Self::ROTARY_STEP;
935 }
936 }
937 }
938 });
939 }
940
941 if let Some(switch) = &mut meter.switch {
942 if bitmap[0] ^ frame[frame.len() - 4] & 0xf0 > 0 {
943 if bitmap[0] & 0xf0 > 0 {
944 *switch = match *switch {
945 AudiophileSwitchState::Off => AudiophileSwitchState::A,
946 AudiophileSwitchState::A => AudiophileSwitchState::B,
947 AudiophileSwitchState::B => AudiophileSwitchState::Off,
948 };
949 }
950 }
951 }
952
953 if let Some(sync_status) = &mut meter.sync_status {
954 *sync_status = frame[frame.len() - 1] > 0;
955 }
956
957 Ok(())
958 }
959}
960
961#[derive(Default, Debug)]
963pub struct OzonicMixerProtocol;
964
965impl MaudioNormalMixerOperation for OzonicMixerProtocol {
966 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
967 (0x01, AudioCh::Each(0)), (0x02, AudioCh::Each(0)), ];
970 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)] = &[
971 (0x02, AudioCh::Each(0)), (0x03, AudioCh::Each(0)), (0x00, AudioCh::Each(0)), (0x01, AudioCh::Each(0)), ];
976}
977
978#[derive(Debug, Clone, PartialEq, Eq)]
981pub struct MaudioNormalMixerParameters(pub Vec<Vec<bool>>);
982
983pub trait MaudioNormalMixerOperation {
985 const DST_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)];
986 const SRC_FUNC_BLOCK_ID_LIST: &'static [(u8, AudioCh)];
987
988 const SRC_OFF: i16 = 0x8000u16 as i16;
989 const SRC_ON: i16 = 0;
990
991 fn create_mixer_parameters() -> MaudioNormalMixerParameters {
992 MaudioNormalMixerParameters(vec![
993 vec![
994 Default::default();
995 Self::SRC_FUNC_BLOCK_ID_LIST.len()
996 ];
997 Self::DST_FUNC_BLOCK_ID_LIST.len()
998 ])
999 }
1000
1001 fn cache(
1004 avc: &BebobAvc,
1005 params: &mut MaudioNormalMixerParameters,
1006 timeout_ms: u32,
1007 ) -> Result<(), Error> {
1008 assert_eq!(params.0.len(), Self::DST_FUNC_BLOCK_ID_LIST.len());
1009 assert_eq!(params.0[0].len(), Self::SRC_FUNC_BLOCK_ID_LIST.len());
1010
1011 params
1012 .0
1013 .iter_mut()
1014 .zip(Self::DST_FUNC_BLOCK_ID_LIST)
1015 .try_for_each(|(srcs, &(dst_func_block_id, dst_audio_ch))| {
1016 srcs.iter_mut()
1017 .zip(Self::SRC_FUNC_BLOCK_ID_LIST)
1018 .try_for_each(|(src, &(src_func_block_id, src_audio_ch))| {
1019 let mut op = AudioProcessing::new(
1020 dst_func_block_id,
1021 CtlAttr::Current,
1022 src_func_block_id,
1023 src_audio_ch,
1024 dst_audio_ch,
1025 ProcessingCtl::Mixer(vec![-1]),
1026 );
1027 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)
1028 .map(|_| {
1029 if let ProcessingCtl::Mixer(data) = op.ctl {
1030 *src = data[0] == Self::SRC_ON
1031 }
1032 })
1033 })
1034 })
1035 }
1036
1037 fn update(
1038 avc: &BebobAvc,
1039 params: &MaudioNormalMixerParameters,
1040 old: &mut MaudioNormalMixerParameters,
1041 timeout_ms: u32,
1042 ) -> Result<(), Error> {
1043 old.0
1044 .iter_mut()
1045 .zip(params.0.iter())
1046 .zip(Self::DST_FUNC_BLOCK_ID_LIST)
1047 .try_for_each(
1048 |((old_srcs, new_srcs), &(dst_func_block_id, dst_audio_ch))| {
1049 old_srcs
1050 .iter_mut()
1051 .zip(new_srcs.iter())
1052 .zip(Self::SRC_FUNC_BLOCK_ID_LIST)
1053 .filter(|((o, n), _)| !n.eq(o))
1054 .try_for_each(|((old, &new), &(src_func_block_id, src_audio_ch))| {
1055 let val = if new { Self::SRC_ON } else { Self::SRC_OFF };
1056 let mut op = AudioProcessing::new(
1057 dst_func_block_id,
1058 CtlAttr::Current,
1059 src_func_block_id,
1060 src_audio_ch,
1061 dst_audio_ch,
1062 ProcessingCtl::Mixer(vec![val]),
1063 );
1064 avc.control(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)
1065 .map(|_| *old = new)
1066 })
1067 },
1068 )
1069 }
1070}