fuchsia_audio/
sigproc.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use {fidl_fuchsia_hardware_audio_signalprocessing as fhaudio_sigproc, zx_types};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Topology {
9    pub id: fhaudio_sigproc::TopologyId,
10    pub edge_pairs: Vec<fhaudio_sigproc::EdgePair>,
11}
12
13impl TryFrom<fhaudio_sigproc::Topology> for Topology {
14    type Error = String;
15
16    fn try_from(value: fhaudio_sigproc::Topology) -> Result<Self, Self::Error> {
17        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
18        let edge_pairs = value
19            .processing_elements_edge_pairs
20            .ok_or_else(|| "missing 'processing_elements_edge_pairs'".to_string())?;
21        Ok(Self { id, edge_pairs })
22    }
23}
24
25impl From<Topology> for fhaudio_sigproc::Topology {
26    fn from(value: Topology) -> Self {
27        Self {
28            id: Some(value.id),
29            processing_elements_edge_pairs: Some(value.edge_pairs),
30            ..Default::default()
31        }
32    }
33}
34
35#[derive(Debug, Clone, PartialEq)]
36pub struct Element {
37    pub id: fhaudio_sigproc::ElementId,
38    pub type_: fhaudio_sigproc::ElementType,
39    pub type_specific: Option<TypeSpecificElement>,
40    pub description: Option<String>,
41    pub can_stop: Option<bool>,
42    pub can_bypass: Option<bool>,
43}
44
45impl TryFrom<fhaudio_sigproc::Element> for Element {
46    type Error = String;
47
48    fn try_from(value: fhaudio_sigproc::Element) -> Result<Self, Self::Error> {
49        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
50        let type_ = value.type_.ok_or_else(|| "missing 'type'".to_string())?;
51        let type_specific: Option<TypeSpecificElement> =
52            value.type_specific.map(TryInto::try_into).transpose()?;
53        Ok(Self {
54            id,
55            type_,
56            type_specific,
57            description: value.description,
58            can_stop: value.can_stop,
59            can_bypass: value.can_bypass,
60        })
61    }
62}
63
64impl From<Element> for fhaudio_sigproc::Element {
65    fn from(value: Element) -> Self {
66        Self {
67            id: Some(value.id),
68            type_: Some(value.type_.into()),
69            type_specific: value.type_specific.map(Into::into),
70            description: value.description,
71            can_stop: value.can_stop,
72            can_bypass: value.can_bypass,
73            ..Default::default()
74        }
75    }
76}
77
78#[derive(Debug, Clone, PartialEq)]
79pub enum TypeSpecificElement {
80    VendorSpecific(VendorSpecific),
81    Gain(Gain),
82    Equalizer(Equalizer),
83    Dynamics(Dynamics),
84    DaiInterconnect(DaiInterconnect),
85}
86
87impl TryFrom<fhaudio_sigproc::TypeSpecificElement> for TypeSpecificElement {
88    type Error = String;
89
90    fn try_from(value: fhaudio_sigproc::TypeSpecificElement) -> Result<Self, Self::Error> {
91        match value {
92            fhaudio_sigproc::TypeSpecificElement::VendorSpecific(vendor_specific) => {
93                Ok(Self::VendorSpecific(vendor_specific.try_into()?))
94            }
95            fhaudio_sigproc::TypeSpecificElement::Gain(gain) => Ok(Self::Gain(gain.try_into()?)),
96            fhaudio_sigproc::TypeSpecificElement::Equalizer(equalizer) => {
97                Ok(Self::Equalizer(equalizer.try_into()?))
98            }
99            fhaudio_sigproc::TypeSpecificElement::Dynamics(dynamics) => {
100                Ok(Self::Dynamics(dynamics.try_into()?))
101            }
102            fhaudio_sigproc::TypeSpecificElement::DaiInterconnect(dai_interconnect) => {
103                Ok(Self::DaiInterconnect(dai_interconnect.try_into()?))
104            }
105            _ => Err("unknown TypeSpecificElement variant".to_string()),
106        }
107    }
108}
109
110impl From<TypeSpecificElement> for fhaudio_sigproc::TypeSpecificElement {
111    fn from(value: TypeSpecificElement) -> Self {
112        match value {
113            TypeSpecificElement::VendorSpecific(vendor_specific) => {
114                Self::VendorSpecific(vendor_specific.into())
115            }
116            TypeSpecificElement::Gain(gain) => Self::Gain(gain.into()),
117            TypeSpecificElement::Equalizer(equalizer) => Self::Equalizer(equalizer.into()),
118            TypeSpecificElement::Dynamics(dynamics) => Self::Dynamics(dynamics.into()),
119            TypeSpecificElement::DaiInterconnect(dai_interconnect) => {
120                Self::DaiInterconnect(dai_interconnect.into())
121            }
122        }
123    }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub struct VendorSpecific {}
128
129impl TryFrom<fhaudio_sigproc::VendorSpecific> for VendorSpecific {
130    type Error = String;
131
132    fn try_from(_value: fhaudio_sigproc::VendorSpecific) -> Result<Self, Self::Error> {
133        Ok(Self {})
134    }
135}
136
137impl From<VendorSpecific> for fhaudio_sigproc::VendorSpecific {
138    fn from(_value: VendorSpecific) -> Self {
139        Default::default()
140    }
141}
142
143#[derive(Debug, Clone, Copy, PartialEq)]
144pub struct Gain {
145    pub type_: fhaudio_sigproc::GainType,
146    pub domain: Option<fhaudio_sigproc::GainDomain>,
147    pub range: GainRange,
148}
149
150impl TryFrom<fhaudio_sigproc::Gain> for Gain {
151    type Error = String;
152
153    fn try_from(value: fhaudio_sigproc::Gain) -> Result<Self, Self::Error> {
154        let type_ = value.type_.ok_or_else(|| "missing 'type'".to_string())?;
155        let min_gain = value.min_gain.ok_or_else(|| "missing 'min_gain'".to_string())?;
156        let max_gain = value.max_gain.ok_or_else(|| "missing 'max_gain'".to_string())?;
157        let min_gain_step =
158            value.min_gain_step.ok_or_else(|| "missing 'min_gain_step'".to_string())?;
159        let range = GainRange { min: min_gain, max: max_gain, min_step: min_gain_step };
160        Ok(Self { type_, domain: value.domain, range })
161    }
162}
163
164impl From<Gain> for fhaudio_sigproc::Gain {
165    fn from(value: Gain) -> Self {
166        Self {
167            type_: Some(value.type_),
168            domain: value.domain,
169            min_gain: Some(value.range.min),
170            max_gain: Some(value.range.max),
171            min_gain_step: Some(value.range.min_step),
172            ..Default::default()
173        }
174    }
175}
176
177#[derive(Debug, Clone, Copy, PartialEq)]
178pub struct GainRange {
179    pub min: f32,
180    pub max: f32,
181    pub min_step: f32,
182}
183
184#[derive(Debug, Clone, PartialEq)]
185pub struct Equalizer {
186    pub bands: Vec<EqualizerBand>,
187    pub supported_controls: Option<fhaudio_sigproc::EqualizerSupportedControls>,
188    pub can_disable_bands: Option<bool>,
189    pub min_frequency: u32,
190    pub max_frequency: u32,
191    pub max_q: Option<f32>,
192    pub min_gain_db: Option<f32>,
193    pub max_gain_db: Option<f32>,
194}
195
196impl TryFrom<fhaudio_sigproc::Equalizer> for Equalizer {
197    type Error = String;
198
199    fn try_from(value: fhaudio_sigproc::Equalizer) -> Result<Self, Self::Error> {
200        let bands: Vec<EqualizerBand> = value
201            .bands
202            .ok_or_else(|| "missing 'bands'".to_string())?
203            .into_iter()
204            .map(TryInto::try_into)
205            .collect::<Result<Vec<_>, _>>()?;
206        let min_frequency =
207            value.min_frequency.ok_or_else(|| "missing 'min_frequency'".to_string())?;
208        let max_frequency =
209            value.max_frequency.ok_or_else(|| "missing 'max_frequency'".to_string())?;
210        Ok(Self {
211            bands,
212            supported_controls: value.supported_controls,
213            can_disable_bands: value.can_disable_bands,
214            min_frequency,
215            max_frequency,
216            max_q: value.max_q,
217            min_gain_db: value.min_gain_db,
218            max_gain_db: value.max_gain_db,
219        })
220    }
221}
222
223impl From<Equalizer> for fhaudio_sigproc::Equalizer {
224    fn from(value: Equalizer) -> Self {
225        let bands: Vec<fhaudio_sigproc::EqualizerBand> =
226            value.bands.into_iter().map(Into::into).collect();
227        Self {
228            bands: Some(bands),
229            supported_controls: value.supported_controls,
230            can_disable_bands: value.can_disable_bands,
231            min_frequency: Some(value.min_frequency),
232            max_frequency: Some(value.max_frequency),
233            max_q: value.max_q,
234            min_gain_db: value.min_gain_db,
235            max_gain_db: value.max_gain_db,
236            ..Default::default()
237        }
238    }
239}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub struct EqualizerBand {
243    pub id: u64,
244}
245
246impl TryFrom<fhaudio_sigproc::EqualizerBand> for EqualizerBand {
247    type Error = String;
248
249    fn try_from(value: fhaudio_sigproc::EqualizerBand) -> Result<Self, Self::Error> {
250        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
251        Ok(Self { id })
252    }
253}
254
255impl From<EqualizerBand> for fhaudio_sigproc::EqualizerBand {
256    fn from(value: EqualizerBand) -> Self {
257        Self { id: Some(value.id), ..Default::default() }
258    }
259}
260
261#[derive(Debug, Clone, PartialEq)]
262pub struct Dynamics {
263    pub bands: Vec<DynamicsBand>,
264    pub supported_controls: Option<fhaudio_sigproc::DynamicsSupportedControls>,
265}
266
267impl TryFrom<fhaudio_sigproc::Dynamics> for Dynamics {
268    type Error = String;
269
270    fn try_from(value: fhaudio_sigproc::Dynamics) -> Result<Self, Self::Error> {
271        let bands: Vec<DynamicsBand> = value
272            .bands
273            .ok_or_else(|| "missing 'bands'".to_string())?
274            .into_iter()
275            .map(TryInto::try_into)
276            .collect::<Result<Vec<_>, _>>()?;
277        Ok(Self { bands, supported_controls: value.supported_controls })
278    }
279}
280
281impl From<Dynamics> for fhaudio_sigproc::Dynamics {
282    fn from(value: Dynamics) -> Self {
283        let bands: Vec<fhaudio_sigproc::DynamicsBand> =
284            value.bands.into_iter().map(Into::into).collect();
285        Self {
286            bands: Some(bands),
287            supported_controls: value.supported_controls,
288            ..Default::default()
289        }
290    }
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294pub struct DynamicsBand {
295    pub id: u64,
296}
297
298impl TryFrom<fhaudio_sigproc::DynamicsBand> for DynamicsBand {
299    type Error = String;
300
301    fn try_from(value: fhaudio_sigproc::DynamicsBand) -> Result<Self, Self::Error> {
302        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
303        Ok(Self { id })
304    }
305}
306
307impl From<DynamicsBand> for fhaudio_sigproc::DynamicsBand {
308    fn from(value: DynamicsBand) -> Self {
309        Self { id: Some(value.id), ..Default::default() }
310    }
311}
312
313#[derive(Debug, Clone, Copy, PartialEq)]
314pub struct DaiInterconnect {
315    pub plug_detect_capabilities: fhaudio_sigproc::PlugDetectCapabilities,
316}
317
318impl TryFrom<fhaudio_sigproc::DaiInterconnect> for DaiInterconnect {
319    type Error = String;
320
321    fn try_from(value: fhaudio_sigproc::DaiInterconnect) -> Result<Self, Self::Error> {
322        let plug_detect_capabilities = value
323            .plug_detect_capabilities
324            .ok_or_else(|| "missing 'plug_detect_capabilities'".to_string())?;
325        Ok(Self { plug_detect_capabilities })
326    }
327}
328
329impl From<DaiInterconnect> for fhaudio_sigproc::DaiInterconnect {
330    fn from(value: DaiInterconnect) -> Self {
331        Self {
332            plug_detect_capabilities: Some(value.plug_detect_capabilities),
333            ..Default::default()
334        }
335    }
336}
337
338#[derive(Debug, Clone, PartialEq)]
339pub struct ElementState {
340    pub type_specific: Option<TypeSpecificElementState>,
341    pub vendor_specific_data: Option<Vec<u8>>,
342    pub started: bool,
343    pub bypassed: Option<bool>,
344    pub turn_on_delay_ns: Option<zx_types::zx_duration_t>,
345    pub turn_off_delay_ns: Option<zx_types::zx_duration_t>,
346    pub processing_delay_ns: Option<zx_types::zx_duration_t>,
347}
348
349impl TryFrom<fhaudio_sigproc::ElementState> for ElementState {
350    type Error = String;
351
352    fn try_from(value: fhaudio_sigproc::ElementState) -> Result<Self, Self::Error> {
353        let type_specific = value.type_specific.map(TryInto::try_into).transpose()?;
354        let started = value.started.ok_or_else(|| "missing 'started'".to_string())?;
355        Ok(Self {
356            type_specific,
357            vendor_specific_data: value.vendor_specific_data,
358            started,
359            bypassed: value.bypassed,
360            turn_on_delay_ns: value.turn_on_delay,
361            turn_off_delay_ns: value.turn_off_delay,
362            processing_delay_ns: value.processing_delay,
363        })
364    }
365}
366
367impl From<ElementState> for fhaudio_sigproc::ElementState {
368    fn from(value: ElementState) -> Self {
369        Self {
370            type_specific: value.type_specific.map(Into::into),
371            enabled: None,
372            vendor_specific_data: value.vendor_specific_data,
373            started: Some(value.started),
374            bypassed: value.bypassed,
375            turn_on_delay: value.turn_on_delay_ns,
376            turn_off_delay: value.turn_off_delay_ns,
377            processing_delay: value.processing_delay_ns,
378            ..Default::default()
379        }
380    }
381}
382
383#[derive(Debug, Clone, PartialEq)]
384pub enum TypeSpecificElementState {
385    VendorSpecific(VendorSpecificElementState),
386    Gain(GainElementState),
387    Equalizer(EqualizerElementState),
388    Dynamics(DynamicsElementState),
389    DaiInterconnect(DaiInterconnectElementState),
390}
391
392impl TryFrom<fhaudio_sigproc::TypeSpecificElementState> for TypeSpecificElementState {
393    type Error = String;
394
395    fn try_from(value: fhaudio_sigproc::TypeSpecificElementState) -> Result<Self, Self::Error> {
396        match value {
397            fhaudio_sigproc::TypeSpecificElementState::VendorSpecific(vendor_specific_state) => {
398                Ok(Self::VendorSpecific(vendor_specific_state.try_into()?))
399            }
400            fhaudio_sigproc::TypeSpecificElementState::Gain(gain_state) => {
401                Ok(Self::Gain(gain_state.try_into()?))
402            }
403            fhaudio_sigproc::TypeSpecificElementState::Equalizer(equalizer_state) => {
404                Ok(Self::Equalizer(equalizer_state.try_into()?))
405            }
406            fhaudio_sigproc::TypeSpecificElementState::Dynamics(dynamics_state) => {
407                Ok(Self::Dynamics(dynamics_state.try_into()?))
408            }
409            fhaudio_sigproc::TypeSpecificElementState::DaiInterconnect(dai_interconnect_state) => {
410                Ok(Self::DaiInterconnect(dai_interconnect_state.try_into()?))
411            }
412            _ => Err("unknown TypeSpecificElementStateState variant".to_string()),
413        }
414    }
415}
416
417impl From<TypeSpecificElementState> for fhaudio_sigproc::TypeSpecificElementState {
418    fn from(value: TypeSpecificElementState) -> Self {
419        match value {
420            TypeSpecificElementState::VendorSpecific(vendor_specific_state) => {
421                Self::VendorSpecific(vendor_specific_state.into())
422            }
423            TypeSpecificElementState::Gain(gain_state) => Self::Gain(gain_state.into()),
424            TypeSpecificElementState::Equalizer(equalizer_state) => {
425                Self::Equalizer(equalizer_state.into())
426            }
427            TypeSpecificElementState::Dynamics(dynamics_state) => {
428                Self::Dynamics(dynamics_state.into())
429            }
430            TypeSpecificElementState::DaiInterconnect(dai_interconnect_state) => {
431                Self::DaiInterconnect(dai_interconnect_state.into())
432            }
433        }
434    }
435}
436
437#[derive(Debug, Clone, Copy, PartialEq, Eq)]
438pub struct VendorSpecificElementState {}
439
440impl TryFrom<fhaudio_sigproc::VendorSpecificState> for VendorSpecificElementState {
441    type Error = String;
442
443    fn try_from(_value: fhaudio_sigproc::VendorSpecificState) -> Result<Self, Self::Error> {
444        Ok(Self {})
445    }
446}
447
448impl From<VendorSpecificElementState> for fhaudio_sigproc::VendorSpecificState {
449    fn from(_value: VendorSpecificElementState) -> Self {
450        Default::default()
451    }
452}
453
454#[derive(Debug, Clone, Copy, PartialEq)]
455pub struct GainElementState {
456    pub gain: f32,
457}
458
459impl TryFrom<fhaudio_sigproc::GainElementState> for GainElementState {
460    type Error = String;
461
462    fn try_from(value: fhaudio_sigproc::GainElementState) -> Result<Self, Self::Error> {
463        let gain = value.gain.ok_or_else(|| "missing 'gain'".to_string())?;
464        Ok(Self { gain })
465    }
466}
467
468impl From<GainElementState> for fhaudio_sigproc::GainElementState {
469    fn from(value: GainElementState) -> Self {
470        Self { gain: Some(value.gain), ..Default::default() }
471    }
472}
473
474#[derive(Debug, Clone, PartialEq)]
475pub struct EqualizerElementState {
476    pub band_states: Vec<EqualizerBandState>,
477}
478
479impl TryFrom<fhaudio_sigproc::EqualizerElementState> for EqualizerElementState {
480    type Error = String;
481
482    fn try_from(value: fhaudio_sigproc::EqualizerElementState) -> Result<Self, Self::Error> {
483        let band_states = value
484            .band_states
485            .ok_or_else(|| "missing 'band_states'".to_string())?
486            .into_iter()
487            .map(TryInto::try_into)
488            .collect::<Result<Vec<_>, _>>()?;
489        Ok(Self { band_states })
490    }
491}
492
493impl From<EqualizerElementState> for fhaudio_sigproc::EqualizerElementState {
494    fn from(value: EqualizerElementState) -> Self {
495        let band_states: Vec<fhaudio_sigproc::EqualizerBandState> =
496            value.band_states.into_iter().map(Into::into).collect();
497        Self { band_states: Some(band_states), ..Default::default() }
498    }
499}
500
501#[derive(Debug, Clone, PartialEq)]
502pub struct EqualizerBandState {
503    pub id: u64,
504    pub type_: Option<fhaudio_sigproc::EqualizerBandType>,
505    pub frequency: Option<u32>,
506    pub q: Option<f32>,
507    pub gain_db: Option<f32>,
508    pub enabled: Option<bool>,
509}
510
511impl TryFrom<fhaudio_sigproc::EqualizerBandState> for EqualizerBandState {
512    type Error = String;
513
514    fn try_from(value: fhaudio_sigproc::EqualizerBandState) -> Result<Self, Self::Error> {
515        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
516        Ok(Self {
517            id,
518            type_: value.type_,
519            frequency: value.frequency,
520            q: value.q,
521            gain_db: value.gain_db,
522            enabled: value.enabled,
523        })
524    }
525}
526
527impl From<EqualizerBandState> for fhaudio_sigproc::EqualizerBandState {
528    fn from(value: EqualizerBandState) -> Self {
529        Self {
530            id: Some(value.id),
531            type_: value.type_,
532            frequency: value.frequency,
533            q: value.q,
534            gain_db: value.gain_db,
535            enabled: value.enabled,
536            ..Default::default()
537        }
538    }
539}
540
541#[derive(Debug, Clone, PartialEq)]
542pub struct DynamicsElementState {
543    pub band_states: Vec<DynamicsBandState>,
544}
545
546impl TryFrom<fhaudio_sigproc::DynamicsElementState> for DynamicsElementState {
547    type Error = String;
548
549    fn try_from(value: fhaudio_sigproc::DynamicsElementState) -> Result<Self, Self::Error> {
550        let band_states = value
551            .band_states
552            .ok_or_else(|| "missing 'band_states'".to_string())?
553            .into_iter()
554            .map(TryInto::try_into)
555            .collect::<Result<Vec<_>, _>>()?;
556        Ok(Self { band_states })
557    }
558}
559
560impl From<DynamicsElementState> for fhaudio_sigproc::DynamicsElementState {
561    fn from(value: DynamicsElementState) -> Self {
562        let band_states: Vec<fhaudio_sigproc::DynamicsBandState> =
563            value.band_states.into_iter().map(Into::into).collect();
564        Self { band_states: Some(band_states), ..Default::default() }
565    }
566}
567
568#[derive(Debug, Clone, PartialEq)]
569pub struct DynamicsBandState {
570    pub id: u64,
571    pub min_frequency: u32,
572    pub max_frequency: u32,
573    pub threshold_db: f32,
574    pub threshold_type: fhaudio_sigproc::ThresholdType,
575    pub ratio: f32,
576    pub knee_width_db: Option<f32>,
577    pub attack: Option<zx_types::zx_duration_t>,
578    pub release: Option<zx_types::zx_duration_t>,
579    pub output_gain_db: Option<f32>,
580    pub input_gain_db: Option<f32>,
581    pub level_type: Option<fhaudio_sigproc::LevelType>,
582    pub lookahead: Option<zx_types::zx_duration_t>,
583    pub linked_channels: Option<bool>,
584}
585
586impl TryFrom<fhaudio_sigproc::DynamicsBandState> for DynamicsBandState {
587    type Error = String;
588
589    fn try_from(value: fhaudio_sigproc::DynamicsBandState) -> Result<Self, Self::Error> {
590        let id = value.id.ok_or_else(|| "missing 'id'".to_string())?;
591        let min_frequency =
592            value.min_frequency.ok_or_else(|| "missing 'min_frequency'".to_string())?;
593        let max_frequency =
594            value.max_frequency.ok_or_else(|| "missing 'max_frequency'".to_string())?;
595        let threshold_db =
596            value.threshold_db.ok_or_else(|| "missing 'threshold_db'".to_string())?;
597        let threshold_type =
598            value.threshold_type.ok_or_else(|| "missing 'threshold_type'".to_string())?;
599        let ratio = value.ratio.ok_or_else(|| "missing 'ratio'".to_string())?;
600        Ok(Self {
601            id,
602            min_frequency,
603            max_frequency,
604            threshold_db,
605            threshold_type,
606            ratio,
607            knee_width_db: value.knee_width_db,
608            attack: value.attack,
609            release: value.release,
610            output_gain_db: value.output_gain_db,
611            input_gain_db: value.input_gain_db,
612            level_type: value.level_type,
613            lookahead: value.lookahead,
614            linked_channels: value.linked_channels,
615        })
616    }
617}
618
619impl From<DynamicsBandState> for fhaudio_sigproc::DynamicsBandState {
620    fn from(value: DynamicsBandState) -> Self {
621        Self {
622            id: Some(value.id),
623            min_frequency: Some(value.min_frequency),
624            max_frequency: Some(value.max_frequency),
625            threshold_db: Some(value.threshold_db),
626            threshold_type: Some(value.threshold_type),
627            ratio: Some(value.ratio),
628            knee_width_db: value.knee_width_db,
629            attack: value.attack,
630            release: value.release,
631            output_gain_db: value.output_gain_db,
632            input_gain_db: value.input_gain_db,
633            level_type: value.level_type,
634            lookahead: value.lookahead,
635            linked_channels: value.linked_channels,
636            ..Default::default()
637        }
638    }
639}
640
641#[derive(Debug, Clone, Copy, PartialEq, Eq)]
642pub struct PlugState {
643    pub plugged: bool,
644    pub plug_state_time: zx_types::zx_time_t,
645}
646
647impl TryFrom<fhaudio_sigproc::PlugState> for PlugState {
648    type Error = String;
649
650    fn try_from(value: fhaudio_sigproc::PlugState) -> Result<Self, Self::Error> {
651        let plugged = value.plugged.ok_or_else(|| "missing 'plugged'".to_string())?;
652        let plug_state_time =
653            value.plug_state_time.ok_or_else(|| "missing 'plug_state_time'".to_string())?;
654        Ok(Self { plugged, plug_state_time })
655    }
656}
657
658impl From<PlugState> for fhaudio_sigproc::PlugState {
659    fn from(value: PlugState) -> Self {
660        Self {
661            plugged: Some(value.plugged),
662            plug_state_time: Some(value.plug_state_time),
663            ..Default::default()
664        }
665    }
666}
667
668#[derive(Debug, Clone, PartialEq)]
669pub struct DaiInterconnectElementState {
670    pub plug_state: PlugState,
671    pub external_delay_ns: Option<zx_types::zx_duration_t>,
672}
673
674impl TryFrom<fhaudio_sigproc::DaiInterconnectElementState> for DaiInterconnectElementState {
675    type Error = String;
676
677    fn try_from(value: fhaudio_sigproc::DaiInterconnectElementState) -> Result<Self, Self::Error> {
678        let plug_state: PlugState =
679            value.plug_state.ok_or_else(|| "missing 'plug_state'".to_string())?.try_into()?;
680        Ok(Self { plug_state, external_delay_ns: value.external_delay })
681    }
682}
683
684impl From<DaiInterconnectElementState> for fhaudio_sigproc::DaiInterconnectElementState {
685    fn from(value: DaiInterconnectElementState) -> Self {
686        Self {
687            plug_state: Some(value.plug_state.into()),
688            external_delay: value.external_delay_ns,
689            ..Default::default()
690        }
691    }
692}