firewire_dice_protocols/
alesis.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2020 Takashi Sakamoto
3
4//! Protocol specific to Alesis iO FireWire series.
5//!
6//! The module includes structure, enumeration, and trait and its implementation for protocol
7//! defined by Alesis for iO FireWire series.
8//!
9//! ## Diagram of internal signal flow for iO 14 FireWire.
10//!
11//! ```text
12//!
13//! analog-input-1/2 ----------------------> stream-output-A-1/2
14//! analog-input-3/4 ----------------------> stream-output-A-3/4
15//! spdif-input-1/2 -----------------------> stream-output-A-5/6
16//! adat-input-1/2 ------------------------> stream-output-B-1/2
17//! adat-input-3/4 ------------------------> stream-output-B-3/4
18//! adat-input-5/6 ------------------------> stream-output-B-5/6
19//! adat-input-7/8 ------------------------> stream-output-B-7/8
20//!
21//!                        ++=========++
22//! analog-input-1/2 ----> ||         ||
23//! analog-input-3/4 ----> || 14 x 8  || --> monitor-output-1/2
24//! adat-input-1/2 ------> ||         || --> monitor-output-3/4
25//! adat-input-3/4 ------> || monitor || --> monitor-output-5/6
26//! adat-input-5/6 ------> ||         || --> monitor-output-7/8
27//! adat-input-7/8 ------> ||  mixer  ||
28//! spdif-input-1/2 -----> ||         ||
29//!                        ++=========++
30//!
31//!                        ++=========++
32//! monitor-output-1/2 --> ||  4 x 2  || --> mixer-output-1/2
33//! stream-input-1/2 ----> ||  mixer  ||
34//!                        ++=========++
35//!
36//!                        ++=========++
37//! monitor-output-3/4 --> ||  4 x 2  || --> mixer-output-3/4
38//! stream-input-3/4 ----> ||  mixer  ||
39//!                        ++=========++
40//!
41//!                        ++=========++
42//! monitor-output-5/6 --> ||  4 x 2  || --> mixer-output-5/6
43//! stream-input-5/6 ----> ||  mixer  ||
44//!                        ++=========++
45//!
46//!                        ++=========++
47//! monitor-output-7/8 --> ||  4 x 2  || --> mixer-output-7/8
48//! stream-input-7/8 ----> ||  mixer  ||
49//!                        ++=========++
50//!
51//! mixer-output-1/2 -----------+----------> analog-output-1/2
52//!                             +----------> headphone-output-1/2
53//! mixer-output-3/4 ----------------------> analog-output-3/4
54//! mixer-output-5/6 ----------------------> analog-output-5/6
55//! mixer-output-7/8 ----------------------> analog-output-7/8
56//!
57//! mixer-output-1/2 -------(one of)------> headphone-output-3/4
58//! mixer-output-3/4 -----------+
59//! mixer-output-5/6 -----------+
60//! mixer-output-7/8 -----------+
61//!
62//! mixer-output-1/2 -------(one of)-------> spdif-output-1/2
63//! mixer-output-3/4 -----------+
64//! mixer-output-5/6 -----------+
65//! mixer-output-7/8 -----------+
66//! ```
67//!
68//! ## Diagram of internal signal flow for iO 26 FireWire.
69//!
70//! ```text
71//!
72//! analog-input-1/2 ----------------------> stream-output-A-1/2
73//! analog-input-3/4 ----------------------> stream-output-A-3/4
74//! analog-input-5/6 ----------------------> stream-output-A-5/6
75//! analog-input-7/8 ----------------------> stream-output-A-7/8
76//! spdif-input-1/2 -----------------------> stream-output-A-9/10
77//! adat-input-1/2 ------------------------> stream-output-B-1/2
78//! adat-input-3/4 ------------------------> stream-output-B-3/4
79//! adat-input-5/6 ------------------------> stream-output-B-5/6
80//! adat-input-7/8 ------------------------> stream-output-B-7/8
81//! adat-input-9/10 -----------------------> stream-output-B-9/10
82//! adat-input-11/12 ----------------------> stream-output-B-11/12
83//! adat-input-13/14 ----------------------> stream-output-B-13/14
84//! adat-input-15/16 ----------------------> stream-output-B-15/16
85//!
86//!                        ++=========++
87//! analog-input-1/2 ----> ||         ||
88//! analog-input-3/4 ----> ||         ||
89//! analog-input-5/6 ----> ||         ||
90//! analog-input-7/8 ----> || 24 x 8  ||
91//! adat-input-1/2 ------> ||         || --> monitor-output-1/2
92//! adat-input-3/4 ------> || monitor || --> monitor-output-3/4
93//! adat-input-5/6 ------> ||         || --> monitor-output-5/6
94//! adat-input-7/8 ------> ||  mixer  || --> monitor-output-7/8
95//! adat-input-9/10 -----> ||         ||
96//! adat-input-11/12 ----> ||         ||
97//! adat-input-13/14 ----> ||         ||
98//! adat-input-15/16 -or-> ||         ||
99//! spdif-input-1/2 --+    ||         ||
100//!                        ++=========++
101//!
102//!                        ++=========++
103//! monitor-output-1/2 --> ||  4 x 2  || --> mixer-output-1/2
104//! stream-input-1/2 ----> ||  mixer  ||
105//!                        ++=========++
106//!
107//!                        ++=========++
108//! monitor-output-3/4 --> ||  4 x 2  || --> mixer-output-3/4
109//! stream-input-3/4 ----> ||  mixer  ||
110//!                        ++=========++
111//!
112//!                        ++=========++
113//! monitor-output-5/6 --> ||  4 x 2  || --> mixer-output-5/6
114//! stream-input-5/6 ----> ||  mixer  ||
115//!                        ++=========++
116//!
117//!                        ++=========++
118//! monitor-output-7/8 --> ||  4 x 2  || --> mixer-output-7/8
119//! stream-input-7/8 ----> ||  mixer  ||
120//!                        ++=========++
121//!
122//! mixer-output-1/2 -----------+----------> analog-output-1/2
123//!                             +----------> headphone-output-1/2
124//! mixer-output-3/4 ----------------------> analog-output-3/4
125//! mixer-output-5/6 ----------------------> analog-output-5/6
126//! mixer-output-7/8 ----------------------> analog-output-7/8
127//!
128//! mixer-output-1/2 -------(one of)------> headphone-output-3/4
129//! mixer-output-3/4 -----------+
130//! mixer-output-5/6 -----------+
131//! mixer-output-7/8 -----------+
132//!
133//! mixer-output-1/2 -------(one of)-------> spdif-output-1/2
134//! mixer-output-3/4 -----------+
135//! mixer-output-5/6 -----------+
136//! mixer-output-7/8 -----------+
137//! ```
138
139use {
140    super::{tcat::*, *},
141    std::ops::Range,
142};
143
144/// Protocol implementation specific to iO 14 FireWire.
145#[derive(Default, Debug)]
146pub struct Io14fwProtocol;
147
148impl TcatOperation for Io14fwProtocol {}
149
150impl TcatGlobalSectionSpecification for Io14fwProtocol {}
151
152impl AlesisOperation for Io14fwProtocol {}
153
154impl IofwMeterSpecification for Io14fwProtocol {
155    const ANALOG_INPUT_COUNT: usize = 4;
156    const DIGITAL_B_INPUT_COUNT: usize = 2;
157}
158
159impl IofwOutputSpecification for Io14fwProtocol {
160    const ANALOG_OUTPUT_COUNT: usize = 4;
161    const HAS_OPT_IFACE_B: bool = false;
162}
163
164impl IofwMixerSpecification for Io14fwProtocol {
165    const ANALOG_INPUT_PAIR_COUNT: usize = 2;
166    const DIGITAL_B_INPUT_PAIR_COUNT: usize = 1;
167}
168
169/// Protocol implementation specific to iO 26 FireWire.
170#[derive(Default, Debug)]
171pub struct Io26fwProtocol;
172
173impl TcatOperation for Io26fwProtocol {}
174
175impl TcatGlobalSectionSpecification for Io26fwProtocol {}
176
177impl AlesisOperation for Io26fwProtocol {}
178
179impl IofwMeterSpecification for Io26fwProtocol {
180    const ANALOG_INPUT_COUNT: usize = 8;
181    const DIGITAL_B_INPUT_COUNT: usize = 8;
182}
183
184impl IofwOutputSpecification for Io26fwProtocol {
185    const ANALOG_OUTPUT_COUNT: usize = 8;
186    const HAS_OPT_IFACE_B: bool = true;
187}
188
189impl IofwMixerSpecification for Io26fwProtocol {
190    const ANALOG_INPUT_PAIR_COUNT: usize = 4;
191    const DIGITAL_B_INPUT_PAIR_COUNT: usize = 4;
192}
193
194const BASE_OFFSET: usize = 0x00200000;
195
196const MIXER_PARAMS_OFFSET: usize = 0x0038;
197// const MIXER_PAIR_SOURCE_GAIN_OFFSET: usize = 0x0038;
198const MIXER_OUTPUT_VOLUME_OFFSET: usize = 0x0438;
199// const MIXER_PAIR_SOURCE_MUTE_OFFSET: usize = 0x0458;
200// const MIXER_OUTPUT_MUTE_OFFSET: usize = 0x0468;
201// const MIXER_PAIR_SOURCE_SOLO_OFFSET: usize = 0x046c;
202// const MIXER_PAIR_SOURCE_LINK_OFFSET: usize = 0x047c;
203
204const METER_OFFSET: usize = 0x04c0;
205// NOTE: 0: mixer 0/1, 1: mixer 2/3, 2: mixer 4/5, 3: mixer 6/7, 4: meter.
206// const UI_SELECT_OFFSET: usize = 0x0560;
207const OUT_LEVEL_OFFSET: usize = 0x0564;
208// const MIXER_DIGITAL_B_67_SRC_OFFSET: usize = 0x0568;
209// const SPDIF_OUT_SRC_OFFSET: usize = 0x056c;
210// const HP34_SRC_OFFSET: usize = 0x0570;
211
212const KNOB_PARAMS_OFFSET: usize = 0x0574;
213// const MIXER_BLEND_KNOB_OFFSET: usize = 0x0574;
214// const MIXER_MASTER_KNOB_OFFSET: usize = 0x0578;
215
216const METER_SIZE: usize = 160;
217
218const MIXER_PARAMS_SIZE: usize = 0x454;
219// const MIXER_PAIR_SOURCE_GAIN_SIZE: usize = 4 * 4 * (8 + 8 + 8 + 8);
220// const MIXER_OUTPUT_VOLUME_SIZE: usize = 4 * 8;
221// const MIXER_PAIR_SOURCE_MUTE_SIZE: usize = 4 * 4;
222// const MIXER_OUTPUT_MUTE_SIZE: usize = 4;
223// const MIXER_PAIR_SOURCE_SOLO_SIZE: usize = 4 * 4;
224// const MIXER_PAIR_SOURCE_LINK_SIZE: usize = 4 * 4;
225const KNOB_PARAMS_SIZE: usize = 8;
226// const MIXER_BLEND_KNOB_SIZE: usize = 4;
227// const MIXER_MASTER_KNOB_SIZE: usize = 4;
228
229/// Serialize and deserialize for parameters of iO FireWire series.
230pub trait AlesisParametersSerdes<T> {
231    /// The name of parameters
232    const NAME: &'static str;
233
234    /// The range of offset for parameters.
235    const OFFSET_RANGES: &'static [Range<usize>];
236
237    /// Serialize parameters to raw layout of data.
238    fn serialize_params(params: &T, raw: &mut [u8]) -> Result<(), String>;
239
240    /// Deserialize parameters from raw layout of data.
241    fn deserialize_params(params: &mut T, raw: &[u8]) -> Result<(), String>;
242}
243
244/// Specification for hardware meter.
245pub trait IofwMeterSpecification {
246    /// The number of analog inputs.
247    const ANALOG_INPUT_COUNT: usize;
248
249    /// The number of digital B inputs.
250    const DIGITAL_B_INPUT_COUNT: usize;
251
252    /// The number of stream inputs.
253    const STREAM_INPUT_COUNT: usize = 8;
254
255    /// The number of digital A inputs.
256    const DIGITAL_A_INPUT_COUNT: usize = 8;
257
258    /// The number of mixer outputs.
259    const MIXER_OUTPUT_COUNT: usize = 8;
260
261    /// The minimum value of detected signal level.
262    const LEVEL_MIN: i32 = 0;
263
264    /// The maximum value of detected signal level.
265    const LEVEL_MAX: i32 = i16::MAX as i32;
266
267    /// Instantiate state of meters.
268    fn create_meter_params() -> IofwMeterParams {
269        IofwMeterParams {
270            analog_inputs: vec![0; Self::ANALOG_INPUT_COUNT],
271            stream_inputs: [0; 8],
272            digital_a_inputs: [0; 8],
273            digital_b_inputs: vec![0; Self::DIGITAL_B_INPUT_COUNT],
274            mixer_outputs: [0; 8],
275        }
276    }
277}
278
279/// Specification of outputs.
280pub trait IofwOutputSpecification {
281    /// The number of analog outputs.
282    const ANALOG_OUTPUT_COUNT: usize;
283
284    /// Whether optical interface B is available or not.
285    const HAS_OPT_IFACE_B: bool;
286
287    /// Instantiate output parameters.
288    fn create_output_params() -> IofwOutputParams {
289        IofwOutputParams {
290            nominal_levels: vec![Default::default(); Self::ANALOG_OUTPUT_COUNT],
291            digital_67_src: Default::default(),
292            spdif_out_src: Default::default(),
293            headphone2_3_out_src: Default::default(),
294        }
295    }
296}
297
298impl<O> AlesisMutableParametersOperation<IofwOutputParams> for O where
299    O: AlesisOperation + IofwOutputSpecification + AlesisParametersSerdes<IofwOutputParams>
300{
301}
302
303/// Specification of mixers.
304pub trait IofwMixerSpecification {
305    /// The number of analog input pairs.
306    const ANALOG_INPUT_PAIR_COUNT: usize;
307
308    /// The number of digital input B pairs.
309    const DIGITAL_B_INPUT_PAIR_COUNT: usize;
310
311    /// The number of stream input pairs.
312    const STREAM_INPUT_PAIR_COUNT: usize = 4;
313
314    /// The number of digital input A pairs.
315    const DIGITAL_A_INPUT_PAIR_COUNT: usize = 4;
316
317    /// The number of mixer output pairs.
318    const MIXER_OUTPUT_PAIR_COUNT: usize = 4;
319
320    /// The minimum value of gain.
321    const GAIN_MIN: i32 = 0;
322
323    /// The maximum value of gain.
324    const GAIN_MAX: i32 = 0x007fffff;
325
326    /// The minimum value of volume, as well as minimum value of knob.
327    const VOLUME_MIN: u32 = 0;
328
329    /// The maximum value of volume, as well as maximum value of knob.
330    const VOLUME_MAX: u32 = 0x100;
331
332    /// Instantiate mixer parameters.
333    fn create_mixer_params() -> IofwMixerParams {
334        IofwMixerParams {
335            mixer_pairs: [
336                IofwMixerPair {
337                    monitor_pair: IofwMonitorPair {
338                        analog_input_pairs: vec![Default::default(); Self::ANALOG_INPUT_PAIR_COUNT],
339                        digital_a_input_pairs: [Default::default(); 4],
340                        digital_b_input_pairs: vec![
341                            Default::default();
342                            Self::DIGITAL_B_INPUT_PAIR_COUNT
343                        ],
344                        output_volumes: [Default::default(); 2],
345                        output_mutes: [Default::default(); 2],
346                    },
347                    stream_inputs_to_left: [Default::default(); 8],
348                    stream_inputs_to_right: [Default::default(); 8],
349                },
350                IofwMixerPair {
351                    monitor_pair: IofwMonitorPair {
352                        analog_input_pairs: vec![Default::default(); Self::ANALOG_INPUT_PAIR_COUNT],
353                        digital_a_input_pairs: [Default::default(); 4],
354                        digital_b_input_pairs: vec![
355                            Default::default();
356                            Self::DIGITAL_B_INPUT_PAIR_COUNT
357                        ],
358                        output_volumes: [Default::default(); 2],
359                        output_mutes: [Default::default(); 2],
360                    },
361                    stream_inputs_to_left: [Default::default(); 8],
362                    stream_inputs_to_right: [Default::default(); 8],
363                },
364                IofwMixerPair {
365                    monitor_pair: IofwMonitorPair {
366                        analog_input_pairs: vec![Default::default(); Self::ANALOG_INPUT_PAIR_COUNT],
367                        digital_a_input_pairs: [Default::default(); 4],
368                        digital_b_input_pairs: vec![
369                            Default::default();
370                            Self::DIGITAL_B_INPUT_PAIR_COUNT
371                        ],
372                        output_volumes: [Default::default(); 2],
373                        output_mutes: [Default::default(); 2],
374                    },
375                    stream_inputs_to_left: [Default::default(); 8],
376                    stream_inputs_to_right: [Default::default(); 8],
377                },
378                IofwMixerPair {
379                    monitor_pair: IofwMonitorPair {
380                        analog_input_pairs: vec![Default::default(); Self::ANALOG_INPUT_PAIR_COUNT],
381                        digital_a_input_pairs: [Default::default(); 4],
382                        digital_b_input_pairs: vec![
383                            Default::default();
384                            Self::DIGITAL_B_INPUT_PAIR_COUNT
385                        ],
386                        output_volumes: [Default::default(); 2],
387                        output_mutes: [Default::default(); 2],
388                    },
389                    stream_inputs_to_left: [Default::default(); 8],
390                    stream_inputs_to_right: [Default::default(); 8],
391                },
392            ],
393            master_knob: Default::default(),
394            blend_knob: Default::default(),
395        }
396    }
397}
398
399impl<O> AlesisMutableParametersOperation<IofwMixerParams> for O where
400    O: AlesisOperation + IofwMixerSpecification + AlesisParametersSerdes<IofwMixerParams>
401{
402}
403
404fn compute_params_size(ranges: &[Range<usize>]) -> usize {
405    ranges
406        .iter()
407        .fold(0usize, |size, range| size + range.end - range.start)
408}
409
410fn generate_err(name: &str, cause: &str, raw: &[u8]) -> Error {
411    let msg = format!("params: {}, cause: {}, raw: {:02x?}", name, cause, raw);
412    Error::new(GeneralProtocolError::VendorDependent, &msg)
413}
414
415/// Operation for Alesis iO FireWire series.
416pub trait AlesisOperation: TcatOperation {
417    /// Read from specific range of address.
418    fn read_params(
419        req: &FwReq,
420        node: &FwNode,
421        offset: usize,
422        raw: &mut [u8],
423        timeout_ms: u32,
424    ) -> Result<(), Error> {
425        Self::read(req, node, BASE_OFFSET + offset, raw, timeout_ms)
426    }
427
428    /// Write to specific range of address.
429    fn write_params(
430        req: &FwReq,
431        node: &FwNode,
432        offset: usize,
433        raw: &mut [u8],
434        timeout_ms: u32,
435    ) -> Result<(), Error> {
436        Self::write(req, node, BASE_OFFSET + offset, raw, timeout_ms)
437    }
438}
439
440/// Operation for parameters to cache state of hardware.
441pub trait AlesisParametersOperation<T>: AlesisOperation + AlesisParametersSerdes<T> {
442    /// Cache whole segment and deserialize for parameters.
443    fn cache_whole_params(
444        req: &FwReq,
445        node: &FwNode,
446        params: &mut T,
447        timeout_ms: u32,
448    ) -> Result<(), Error> {
449        let size = compute_params_size(Self::OFFSET_RANGES);
450        let mut raw = vec![0u8; size];
451
452        let mut pos = 0;
453
454        Self::OFFSET_RANGES.iter().try_for_each(|range| {
455            let size = range.end - range.start;
456            Self::read_params(
457                req,
458                node,
459                range.start,
460                &mut raw[pos..(pos + size)],
461                timeout_ms,
462            )
463            .map(|_| pos += size)
464        })?;
465
466        Self::deserialize_params(params, &raw)
467            .map_err(|cause| generate_err(Self::NAME, &cause, &raw))
468    }
469}
470
471impl<O: AlesisOperation + AlesisParametersSerdes<T>, T> AlesisParametersOperation<T> for O {}
472
473/// Operation for parameters to update state of hardware.
474pub trait AlesisMutableParametersOperation<T>: AlesisOperation + AlesisParametersSerdes<T> {
475    /// Update the hardware partially for any change of parameter.
476    fn update_partial_params(
477        req: &FwReq,
478        node: &FwNode,
479        params: &T,
480        prev: &mut T,
481        timeout_ms: u32,
482    ) -> Result<(), Error> {
483        let size = compute_params_size(Self::OFFSET_RANGES);
484
485        let mut new = vec![0u8; size];
486        let mut old = vec![0u8; size];
487        Self::serialize_params(params, &mut new)
488            .map_err(|cause| generate_err(Self::NAME, &cause, &new))?;
489        Self::serialize_params(prev, &mut old)
490            .map_err(|cause| generate_err(Self::NAME, &cause, &old))?;
491
492        let mut pos = 0;
493
494        Self::OFFSET_RANGES.iter().try_for_each(|range| {
495            let size = range.end - range.start;
496
497            if new[pos..(pos + size)] != old[pos..(pos + size)] {
498                (0..size).step_by(4).try_for_each(|offset| {
499                    let p = pos + offset;
500                    if new[p..(p + 4)] != old[p..(p + 4)] {
501                        Self::write_params(
502                            req,
503                            node,
504                            range.start + offset,
505                            &mut new[p..(p + 4)],
506                            timeout_ms,
507                        )
508                    } else {
509                        Ok(())
510                    }
511                })
512            } else {
513                Ok(())
514            }
515            .map(|_| pos += size)
516        })?;
517
518        Self::deserialize_params(prev, &new).map_err(|cause| generate_err(Self::NAME, &cause, &new))
519    }
520}
521
522/// Operation for parameters to include fluctuated values.
523pub trait AlesisFluctuatedParametersOperation<T>:
524    AlesisOperation + AlesisParametersSerdes<T>
525{
526    /// The set of address offsets in which any value is changed apart from software operation.
527    const FLUCTUATED_OFFSET_RANGES: &'static [Range<usize>];
528
529    /// Cache part of offset ranges for fluctuated values, then deserialize for parameters.
530    fn cache_partial_params(
531        req: &FwReq,
532        node: &FwNode,
533        params: &mut T,
534        timeout_ms: u32,
535    ) -> Result<(), Error> {
536        let size = compute_params_size(Self::OFFSET_RANGES);
537
538        let mut raw = vec![0u8; size];
539        Self::serialize_params(params, &mut raw)
540            .map_err(|cause| generate_err(Self::NAME, &cause, &raw))?;
541
542        Self::FLUCTUATED_OFFSET_RANGES
543            .iter()
544            .try_for_each(|range| {
545                let mut pos = 0;
546                for r in Self::OFFSET_RANGES {
547                    if !r.contains(&range.start) {
548                        pos += r.end - r.start;
549                    } else {
550                        pos += range.start - r.start;
551                        break;
552                    }
553                }
554                assert!(
555                    pos < size,
556                    "Programming error. The offset range should be found."
557                );
558
559                let end = pos + range.end - range.start;
560                Self::read_params(req, node, range.start, &mut raw[pos..end], timeout_ms)
561            })
562            .and_then(|_| {
563                Self::deserialize_params(params, &raw)
564                    .map_err(|cause| generate_err(Self::NAME, &cause, &raw))
565            })
566    }
567}
568
569/// For hardware meters, between 0..0x7fff (-90.0..0.0 dB).
570#[derive(Default, Debug, Clone, PartialEq, Eq)]
571pub struct IofwMeterParams {
572    /// Detected levels for analog inputs.
573    pub analog_inputs: Vec<i16>,
574    /// Detected levels for stream inputs.
575    pub stream_inputs: [i16; 8],
576    /// Detected levels for digital A inputs.
577    pub digital_a_inputs: [i16; 8],
578    /// Detected levels for digital B inputs.
579    pub digital_b_inputs: Vec<i16>,
580    /// Detected levels for mixer outputs.
581    pub mixer_outputs: [i16; 8],
582}
583
584impl<O: IofwMeterSpecification> AlesisParametersSerdes<IofwMeterParams> for O {
585    const NAME: &'static str = "meter";
586
587    const OFFSET_RANGES: &'static [Range<usize>] = &[Range {
588        start: METER_OFFSET,
589        end: METER_OFFSET + METER_SIZE,
590    }];
591
592    fn serialize_params(params: &IofwMeterParams, raw: &mut [u8]) -> Result<(), String> {
593        [
594            (&params.analog_inputs[..], 0),
595            (&params.stream_inputs[..], 32),
596            (&params.digital_a_inputs[..], 64),
597            (&params.mixer_outputs[..], 128),
598        ]
599        .iter()
600        .for_each(|(levels, offset)| {
601            levels.iter().enumerate().for_each(|(i, &level)| {
602                let pos = *offset + i * 4;
603                let val = (level as i32) << 8;
604                raw[pos..(pos + 4)].copy_from_slice(&val.to_be_bytes());
605            });
606        });
607
608        params
609            .digital_b_inputs
610            .iter()
611            .rev()
612            .enumerate()
613            .for_each(|(i, &level)| {
614                let pos = 96 + (7 - i) * 4;
615                let val = (level as i32) << 8;
616                raw[pos..(pos + 4)].copy_from_slice(&val.to_be_bytes());
617            });
618
619        Ok(())
620    }
621
622    fn deserialize_params(params: &mut IofwMeterParams, raw: &[u8]) -> Result<(), String> {
623        [
624            (&mut params.analog_inputs[..], 0),
625            (&mut params.stream_inputs[..], 32),
626            (&mut params.digital_a_inputs[..], 64),
627            (&mut params.mixer_outputs[..], 128),
628        ]
629        .iter_mut()
630        .for_each(|(levels, offset)| {
631            levels.iter_mut().enumerate().for_each(|(i, level)| {
632                let pos = *offset + i * 4;
633                let mut val = 0i32;
634                deserialize_i32(&mut val, &raw[pos..(pos + 4)]);
635                *level = ((val & 0x00ffff00) >> 8) as i16;
636            });
637        });
638
639        params
640            .digital_b_inputs
641            .iter_mut()
642            .rev()
643            .enumerate()
644            .for_each(|(i, level)| {
645                let pos = 96 + (7 - i) * 4;
646                let mut val = 0i32;
647                deserialize_i32(&mut val, &raw[pos..(pos + 4)]);
648                *level = ((val & 0x00ffff00) >> 8) as i16;
649            });
650
651        Ok(())
652    }
653}
654
655/// Parameters of output.
656#[derive(Default, Debug, Clone, PartialEq, Eq)]
657pub struct IofwOutputParams {
658    /// Nominal signal level of outputs.
659    pub nominal_levels: Vec<NominalSignalLevel>,
660    /// Source of digital output 7/8.
661    pub digital_67_src: DigitalB67Src,
662    /// Source of S/PDIF output 1/2.
663    pub spdif_out_src: MixerOutPair,
664    /// Source of headphone output 3/4.
665    pub headphone2_3_out_src: MixerOutPair,
666}
667
668/// Nominal level of signal.
669#[derive(Debug, Copy, Clone, PartialEq, Eq)]
670pub enum NominalSignalLevel {
671    /// -10dBV.
672    Consumer,
673    /// +4dBu.
674    Professional,
675}
676
677impl Default for NominalSignalLevel {
678    fn default() -> Self {
679        NominalSignalLevel::Consumer
680    }
681}
682
683fn serialize_nominal_signal_levels(
684    levels: &[NominalSignalLevel],
685    raw: &mut [u8],
686) -> Result<(), String> {
687    assert!(raw.len() >= 4);
688
689    let val = levels
690        .iter()
691        .enumerate()
692        .filter(|(_, &level)| level == NominalSignalLevel::Professional)
693        .fold(0u32, |val, (i, _)| val | (1 << i));
694
695    serialize_u32(&val, raw);
696
697    Ok(())
698}
699
700fn deserialize_nominal_signal_levels(
701    levels: &mut [NominalSignalLevel],
702    raw: &[u8],
703) -> Result<(), String> {
704    assert!(raw.len() >= 4);
705
706    let mut val = 0u32;
707    deserialize_u32(&mut val, raw);
708
709    levels.iter_mut().enumerate().for_each(|(i, level)| {
710        *level = if val & (1 << i) > 0 {
711            NominalSignalLevel::Professional
712        } else {
713            NominalSignalLevel::Consumer
714        };
715    });
716
717    Ok(())
718}
719
720/// Source of 6/7 channels of digital B input.
721#[derive(Debug, Copy, Clone, PartialEq, Eq)]
722pub enum DigitalB67Src {
723    /// S/PDIF input 1/2.
724    Spdif12,
725    /// ADAT input B 7/8.
726    Adat67,
727}
728
729impl Default for DigitalB67Src {
730    fn default() -> Self {
731        Self::Spdif12
732    }
733}
734
735fn serialize_digital_b67_src(src: &DigitalB67Src, raw: &mut [u8]) -> Result<(), String> {
736    assert!(raw.len() >= 4);
737
738    let val = match src {
739        DigitalB67Src::Spdif12 => 0,
740        DigitalB67Src::Adat67 => 1,
741    };
742    serialize_u32(&val, raw);
743
744    Ok(())
745}
746
747fn deserialize_digital_b67_src(src: &mut DigitalB67Src, raw: &[u8]) -> Result<(), String> {
748    assert!(raw.len() >= 4);
749
750    let mut val = 0u32;
751    deserialize_u32(&mut val, raw);
752
753    *src = match val {
754        0 => DigitalB67Src::Spdif12,
755        1 => DigitalB67Src::Adat67,
756        _ => Err(format!("Digital B 7/8 source not found for value: {}", val))?,
757    };
758
759    Ok(())
760}
761
762/// Pair of mixer output.
763#[derive(Debug, Copy, Clone, PartialEq, Eq)]
764pub enum MixerOutPair {
765    /// Mixer output 1/2.
766    Mixer01,
767    /// Mixer output 3/4.
768    Mixer23,
769    /// Mixer output 5/6.
770    Mixer45,
771    /// Mixer output 7/8.
772    Mixer67,
773}
774
775impl Default for MixerOutPair {
776    fn default() -> Self {
777        Self::Mixer01
778    }
779}
780
781fn serialize_mixer_out_pair(pair: &MixerOutPair, raw: &mut [u8]) -> Result<(), String> {
782    assert!(raw.len() >= 4);
783
784    let val = match pair {
785        MixerOutPair::Mixer01 => 0,
786        MixerOutPair::Mixer23 => 1,
787        MixerOutPair::Mixer45 => 2,
788        MixerOutPair::Mixer67 => 3,
789    };
790    serialize_u32(&val, raw);
791
792    Ok(())
793}
794
795fn deserialize_mixer_out_pair(pair: &mut MixerOutPair, raw: &[u8]) -> Result<(), String> {
796    assert!(raw.len() >= 4);
797
798    let mut val = 0u32;
799    deserialize_u32(&mut val, raw);
800
801    *pair = match val {
802        0 => MixerOutPair::Mixer01,
803        1 => MixerOutPair::Mixer23,
804        2 => MixerOutPair::Mixer45,
805        3 => MixerOutPair::Mixer67,
806        _ => Err(format!("Mixer output pair not found for value: {}", val))?,
807    };
808
809    Ok(())
810}
811
812impl<O: IofwOutputSpecification> AlesisParametersSerdes<IofwOutputParams> for O {
813    const NAME: &'static str = "output-params";
814
815    const OFFSET_RANGES: &'static [Range<usize>] = &[Range {
816        start: OUT_LEVEL_OFFSET,
817        end: OUT_LEVEL_OFFSET + 16,
818    }];
819
820    fn serialize_params(params: &IofwOutputParams, raw: &mut [u8]) -> Result<(), String> {
821        serialize_nominal_signal_levels(&params.nominal_levels, &mut raw[..4])?;
822        serialize_digital_b67_src(&params.digital_67_src, &mut raw[4..8])?;
823        serialize_mixer_out_pair(&params.spdif_out_src, &mut raw[8..12])?;
824        serialize_mixer_out_pair(&params.headphone2_3_out_src, &mut raw[12..16])?;
825        Ok(())
826    }
827
828    fn deserialize_params(params: &mut IofwOutputParams, raw: &[u8]) -> Result<(), String> {
829        deserialize_nominal_signal_levels(&mut params.nominal_levels, &raw[..4])?;
830        deserialize_digital_b67_src(&mut params.digital_67_src, &raw[4..8])?;
831        deserialize_mixer_out_pair(&mut params.spdif_out_src, &raw[8..12])?;
832        deserialize_mixer_out_pair(&mut params.headphone2_3_out_src, &raw[12..16])?;
833        Ok(())
834    }
835}
836
837/// Parameters for pair of sources of paired mixer.
838#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
839pub struct IofwMonitorPairSourcePair {
840    /// Gain from left and right channels to left channel of monitor, between 0x7fffff and 0 (-60
841    /// and 0 dB).
842    pub gain_to_left: [i32; 2],
843    /// Gain from left and right channels to right channel of monitor, between 0x7fffff and 0 (-60
844    /// and 0 dB).
845    pub gain_to_right: [i32; 2],
846    /// Whether to mute left and right channels.
847    pub mutes: [bool; 2],
848    /// Whether to mute the other channels.
849    pub solos: [bool; 2],
850    /// Whether to link left and right channels.
851    pub link: bool,
852}
853
854/// Parameters of source pairs for monitor. The function to control volume of monitor outputs
855/// seems not to be available in all of models with the latest firmware, while vendor's GUI
856/// application still operates them.
857#[derive(Debug, Clone, PartialEq, Eq)]
858pub struct IofwMonitorPair {
859    /// Source pairs of analog inputs.
860    pub analog_input_pairs: Vec<IofwMonitorPairSourcePair>,
861    /// Source pairs of digital A inputs.
862    pub digital_a_input_pairs: [IofwMonitorPairSourcePair; 4],
863    /// Source pairs of digital B inputs.
864    pub digital_b_input_pairs: Vec<IofwMonitorPairSourcePair>,
865    /// Volume of left and right outputs, between 0 and 0x100 (-60 and 0 dB).
866    pub output_volumes: [u32; 2],
867    /// Mute of left and right outputs.
868    pub output_mutes: [bool; 2],
869}
870
871/// Parameters of source pairs for mixer. The function to control gain of stream inputs seems not
872/// to be available in iO 26 FireWire with the latest version of firmware.
873#[derive(Debug, Clone, PartialEq, Eq)]
874pub struct IofwMixerPair {
875    /// Source pairs for monitor.
876    pub monitor_pair: IofwMonitorPair,
877    /// Stream inputs to left channel of mixer.
878    pub stream_inputs_to_left: [i32; 8],
879    /// Stream inputs to right channel of mixer.
880    pub stream_inputs_to_right: [i32; 8],
881}
882
883/// Parametes of source pairs for mixer.
884#[derive(Debug, Clone, PartialEq, Eq)]
885pub struct IofwMixerParams {
886    /// The setting of each mixer.
887    pub mixer_pairs: [IofwMixerPair; 4],
888    /// The value of master knob, between 0 and 0x100.
889    pub blend_knob: u32,
890    /// The value of master knob, between 0 and 0x100.
891    pub master_knob: u32,
892}
893
894impl<O: IofwMixerSpecification> AlesisParametersSerdes<IofwMixerParams> for O {
895    const NAME: &'static str = "mixer";
896
897    const OFFSET_RANGES: &'static [Range<usize>] = &[
898        Range {
899            start: MIXER_PARAMS_OFFSET,
900            end: MIXER_PARAMS_OFFSET + MIXER_PARAMS_SIZE,
901        },
902        Range {
903            start: KNOB_PARAMS_OFFSET,
904            end: KNOB_PARAMS_OFFSET + KNOB_PARAMS_SIZE,
905        },
906    ];
907
908    fn serialize_params(params: &IofwMixerParams, raw: &mut [u8]) -> Result<(), String> {
909        params.mixer_pairs.iter().enumerate().for_each(|(i, srcs)| {
910            let mut mutes_val = 0u32;
911            let mut solos_val = 0u32;
912            let mut links_val = 0u32;
913
914            let digital_b_pos = 2 * (4 - Self::DIGITAL_B_INPUT_PAIR_COUNT);
915            [
916                (&srcs.monitor_pair.analog_input_pairs[..], 0),
917                (&srcs.monitor_pair.digital_a_input_pairs[..], 16),
918                (
919                    &srcs.monitor_pair.digital_b_input_pairs[..],
920                    24 + digital_b_pos,
921                ),
922            ]
923            .iter()
924            .for_each(|(pairs, offset)| {
925                pairs
926                    .iter()
927                    .flat_map(|pair| pair.gain_to_left.iter())
928                    .enumerate()
929                    .for_each(|(j, gain)| {
930                        let mixer_index = i * 2;
931                        let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + *offset + j);
932                        serialize_i32(gain, &mut raw[pos..(pos + 4)]);
933                    });
934
935                pairs
936                    .iter()
937                    .flat_map(|pair| pair.gain_to_right.iter())
938                    .enumerate()
939                    .for_each(|(j, gain)| {
940                        let mixer_index = i * 2 + 1;
941                        let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + *offset + j);
942                        serialize_i32(gain, &mut raw[pos..(pos + 4)]);
943                    });
944
945                pairs
946                    .iter()
947                    .flat_map(|pair| pair.mutes.iter())
948                    .enumerate()
949                    .filter(|(_, &mute)| mute)
950                    .for_each(|(j, _)| mutes_val |= 1 << (*offset + j));
951
952                pairs
953                    .iter()
954                    .flat_map(|pair| pair.solos.iter())
955                    .enumerate()
956                    .filter(|(_, &solo)| solo)
957                    .for_each(|(j, _)| solos_val |= 1 << (*offset + j));
958
959                pairs
960                    .iter()
961                    .enumerate()
962                    .filter(|(_, &pair)| pair.link)
963                    .for_each(|(j, _)| links_val |= 1 << (*offset / 2 + j));
964            });
965
966            let pos = 0x0420 + 4 * i;
967            serialize_u32(&mutes_val, &mut raw[pos..(pos + 4)]);
968
969            let pos = 0x0434 + 4 * i;
970            serialize_u32(&solos_val, &mut raw[pos..(pos + 4)]);
971
972            let pos = 0x0444 + 4 * i;
973            serialize_u32(&links_val, &mut raw[pos..(pos + 4)]);
974
975            [
976                &srcs.stream_inputs_to_left[..],
977                &srcs.stream_inputs_to_right[..],
978            ]
979            .iter()
980            .enumerate()
981            .for_each(|(j, gains)| {
982                gains.iter().enumerate().for_each(|(k, gain)| {
983                    let mixer_index = i * 2 + j;
984                    let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + 8 + k);
985                    serialize_i32(gain, &mut raw[pos..(pos + 4)]);
986                });
987            });
988        });
989
990        params
991            .mixer_pairs
992            .iter()
993            .flat_map(|srcs| srcs.monitor_pair.output_volumes.iter())
994            .enumerate()
995            .for_each(|(i, vol)| {
996                let pos = 0x400 + 4 * i;
997                serialize_u32(vol, &mut raw[pos..(pos + 4)]);
998            });
999
1000        let mut val = 0u32;
1001        params
1002            .mixer_pairs
1003            .iter()
1004            .flat_map(|srcs| srcs.monitor_pair.output_mutes.iter())
1005            .enumerate()
1006            .filter(|(_, &mute)| mute)
1007            .for_each(|(i, _)| val |= 1 << i);
1008        serialize_u32(&val, &mut raw[0x430..0x434]);
1009
1010        serialize_u32(&params.blend_knob, &mut raw[0x454..0x458]);
1011        serialize_u32(&params.master_knob, &mut raw[0x458..0x45c]);
1012
1013        Ok(())
1014    }
1015
1016    fn deserialize_params(params: &mut IofwMixerParams, raw: &[u8]) -> Result<(), String> {
1017        params
1018            .mixer_pairs
1019            .iter_mut()
1020            .enumerate()
1021            .for_each(|(i, srcs)| {
1022                let digital_b_pos = 2 * (4 - Self::DIGITAL_B_INPUT_PAIR_COUNT);
1023
1024                let pos = 0x0420 + 4 * i;
1025                let mut mutes_val = 0u32;
1026                deserialize_u32(&mut mutes_val, &raw[pos..(pos + 4)]);
1027
1028                let pos = 0x0434 + 4 * i;
1029                let mut solos_val = 0u32;
1030                deserialize_u32(&mut solos_val, &raw[pos..(pos + 4)]);
1031
1032                let pos = 0x0444 + 4 * i;
1033                let mut links_val = 0u32;
1034                deserialize_u32(&mut links_val, &raw[pos..(pos + 4)]);
1035
1036                [
1037                    (&mut srcs.monitor_pair.analog_input_pairs[..], 0),
1038                    (&mut srcs.monitor_pair.digital_a_input_pairs[..], 16),
1039                    (
1040                        &mut srcs.monitor_pair.digital_b_input_pairs[..],
1041                        24 + digital_b_pos,
1042                    ),
1043                ]
1044                .iter_mut()
1045                .for_each(|(pairs, offset)| {
1046                    pairs
1047                        .iter_mut()
1048                        .flat_map(|pair| pair.gain_to_left.iter_mut())
1049                        .enumerate()
1050                        .for_each(|(j, gain)| {
1051                            let mixer_index = i * 2;
1052                            let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + *offset + j);
1053                            deserialize_i32(gain, &raw[pos..(pos + 4)]);
1054                        });
1055
1056                    pairs
1057                        .iter_mut()
1058                        .flat_map(|pair| pair.gain_to_right.iter_mut())
1059                        .enumerate()
1060                        .for_each(|(j, gain)| {
1061                            let mixer_index = i * 2 + 1;
1062                            let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + *offset + j);
1063                            deserialize_i32(gain, &raw[pos..(pos + 4)]);
1064                        });
1065
1066                    pairs
1067                        .iter_mut()
1068                        .flat_map(|pair| pair.mutes.iter_mut())
1069                        .enumerate()
1070                        .for_each(|(j, mute)| *mute = mutes_val & (1 << (*offset + j)) > 0);
1071
1072                    pairs
1073                        .iter_mut()
1074                        .flat_map(|pair| pair.solos.iter_mut())
1075                        .enumerate()
1076                        .for_each(|(j, solo)| *solo = solos_val & (1 << (*offset + j)) > 0);
1077
1078                    pairs
1079                        .iter_mut()
1080                        .enumerate()
1081                        .for_each(|(j, pair)| pair.link = links_val & (1 << (*offset / 2 + j)) > 0);
1082                });
1083
1084                [
1085                    &mut srcs.stream_inputs_to_left[..],
1086                    &mut srcs.stream_inputs_to_right[..],
1087                ]
1088                .iter_mut()
1089                .enumerate()
1090                .for_each(|(j, gains)| {
1091                    gains.iter_mut().enumerate().for_each(|(k, gain)| {
1092                        let mixer_index = i * 2 + j;
1093                        let pos = 4 * (mixer_index * (8 + 8 + 8 + 8) + 8 + k);
1094                        deserialize_i32(gain, &raw[pos..(pos + 4)]);
1095                    });
1096                });
1097            });
1098
1099        params
1100            .mixer_pairs
1101            .iter_mut()
1102            .flat_map(|srcs| srcs.monitor_pair.output_volumes.iter_mut())
1103            .enumerate()
1104            .for_each(|(i, vol)| {
1105                let pos = 0x400 + 4 * i;
1106                deserialize_u32(vol, &raw[pos..(pos + 4)]);
1107            });
1108
1109        let mut val = 0u32;
1110        deserialize_u32(&mut val, &raw[0x430..0x434]);
1111        params
1112            .mixer_pairs
1113            .iter_mut()
1114            .flat_map(|srcs| srcs.monitor_pair.output_mutes.iter_mut())
1115            .enumerate()
1116            .for_each(|(i, mute)| *mute = val & (1 << i) > 0);
1117
1118        deserialize_u32(&mut params.blend_knob, &raw[0x454..0x458]);
1119        deserialize_u32(&mut params.master_knob, &raw[0x458..0x45c]);
1120
1121        Ok(())
1122    }
1123}
1124
1125impl<O: AlesisOperation + AlesisParametersSerdes<IofwMixerParams>>
1126    AlesisFluctuatedParametersOperation<IofwMixerParams> for O
1127{
1128    const FLUCTUATED_OFFSET_RANGES: &'static [Range<usize>] = &[
1129        // NOTE: Mix blend knob operates output volume of mixer 1/2.
1130        Range {
1131            start: MIXER_OUTPUT_VOLUME_OFFSET,
1132            end: MIXER_OUTPUT_VOLUME_OFFSET + 8,
1133        },
1134        Range {
1135            start: KNOB_PARAMS_OFFSET,
1136            end: KNOB_PARAMS_OFFSET + KNOB_PARAMS_SIZE,
1137        },
1138    ];
1139}
1140
1141#[cfg(test)]
1142mod test {
1143    use super::*;
1144
1145    #[test]
1146    fn io14_meter_params_serdes() {
1147        let mut params = <Io14fwProtocol as IofwMeterSpecification>::create_meter_params();
1148        params
1149            .analog_inputs
1150            .iter_mut()
1151            .chain(params.stream_inputs.iter_mut())
1152            .chain(params.digital_a_inputs.iter_mut())
1153            .chain(params.digital_b_inputs.iter_mut())
1154            .chain(params.mixer_outputs.iter_mut())
1155            .enumerate()
1156            .for_each(|(i, level)| *level = i as i16);
1157
1158        let size = compute_params_size(
1159            <Io14fwProtocol as AlesisParametersSerdes<IofwMeterParams>>::OFFSET_RANGES,
1160        );
1161        let mut raw = vec![0u8; size];
1162        Io14fwProtocol::serialize_params(&params, &mut raw).unwrap();
1163
1164        let mut target = <Io14fwProtocol as IofwMeterSpecification>::create_meter_params();
1165        Io14fwProtocol::deserialize_params(&mut target, &raw).unwrap();
1166
1167        assert_eq!(params, target);
1168    }
1169
1170    #[test]
1171    fn io26_meter_params_serdes() {
1172        let mut params = <Io26fwProtocol as IofwMeterSpecification>::create_meter_params();
1173        params
1174            .analog_inputs
1175            .iter_mut()
1176            .chain(params.stream_inputs.iter_mut())
1177            .chain(params.digital_a_inputs.iter_mut())
1178            .chain(params.digital_b_inputs.iter_mut())
1179            .chain(params.mixer_outputs.iter_mut())
1180            .enumerate()
1181            .for_each(|(i, level)| *level = i as i16);
1182
1183        let size = compute_params_size(
1184            <Io14fwProtocol as AlesisParametersSerdes<IofwMeterParams>>::OFFSET_RANGES,
1185        );
1186        let mut raw = vec![0u8; size];
1187        Io26fwProtocol::serialize_params(&params, &mut raw).unwrap();
1188
1189        let mut target = <Io26fwProtocol as IofwMeterSpecification>::create_meter_params();
1190        Io26fwProtocol::deserialize_params(&mut target, &raw).unwrap();
1191
1192        assert_eq!(params, target);
1193    }
1194
1195    #[test]
1196    fn io14_output_params_serdes() {
1197        let mut params = <Io14fwProtocol as IofwOutputSpecification>::create_output_params();
1198        params
1199            .nominal_levels
1200            .iter_mut()
1201            .enumerate()
1202            .filter(|(i, _)| i % 2 > 0)
1203            .for_each(|(_, level)| *level = NominalSignalLevel::Professional);
1204        params.digital_67_src = DigitalB67Src::Spdif12;
1205        params.spdif_out_src = MixerOutPair::Mixer45;
1206        params.headphone2_3_out_src = MixerOutPair::Mixer67;
1207
1208        let size = compute_params_size(
1209            <Io14fwProtocol as AlesisParametersSerdes<IofwOutputParams>>::OFFSET_RANGES,
1210        );
1211        let mut raw = vec![0u8; size];
1212        Io14fwProtocol::serialize_params(&params, &mut raw).unwrap();
1213
1214        let mut target = <Io14fwProtocol as IofwOutputSpecification>::create_output_params();
1215        Io14fwProtocol::deserialize_params(&mut target, &raw).unwrap();
1216
1217        assert_eq!(params, target);
1218    }
1219
1220    #[test]
1221    fn io26_output_params_serdes() {
1222        let mut params = <Io26fwProtocol as IofwOutputSpecification>::create_output_params();
1223        params
1224            .nominal_levels
1225            .iter_mut()
1226            .enumerate()
1227            .filter(|(i, _)| i % 2 > 0)
1228            .for_each(|(_, level)| *level = NominalSignalLevel::Professional);
1229        params.digital_67_src = DigitalB67Src::Adat67;
1230        params.spdif_out_src = MixerOutPair::Mixer01;
1231        params.headphone2_3_out_src = MixerOutPair::Mixer23;
1232
1233        let size = compute_params_size(
1234            <Io14fwProtocol as AlesisParametersSerdes<IofwOutputParams>>::OFFSET_RANGES,
1235        );
1236        let mut raw = vec![0u8; size];
1237        Io26fwProtocol::serialize_params(&params, &mut raw).unwrap();
1238
1239        let mut target = <Io26fwProtocol as IofwOutputSpecification>::create_output_params();
1240        Io26fwProtocol::deserialize_params(&mut target, &raw).unwrap();
1241
1242        assert_eq!(params, target);
1243    }
1244
1245    #[test]
1246    fn io14fw_mixer_params_serdes() {
1247        let mut params = Io14fwProtocol::create_mixer_params();
1248        params.mixer_pairs.iter_mut().for_each(|mixer_pair| {
1249            mixer_pair
1250                .monitor_pair
1251                .analog_input_pairs
1252                .iter_mut()
1253                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1254                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1255                .flat_map(|pair| pair.gain_to_left.iter_mut())
1256                .enumerate()
1257                .for_each(|(i, gain)| *gain = 2 * i as i32);
1258            mixer_pair
1259                .monitor_pair
1260                .analog_input_pairs
1261                .iter_mut()
1262                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1263                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1264                .flat_map(|pair| pair.gain_to_right.iter_mut())
1265                .enumerate()
1266                .for_each(|(i, gain)| *gain = 1 + 2 * i as i32);
1267            [
1268                &mut mixer_pair.stream_inputs_to_left[..],
1269                &mut mixer_pair.stream_inputs_to_right[..],
1270            ]
1271            .iter_mut()
1272            .enumerate()
1273            .for_each(|(i, gains)| {
1274                gains
1275                    .iter_mut()
1276                    .enumerate()
1277                    .for_each(|(j, gain)| *gain = (i * 8 + j) as i32);
1278            });
1279            mixer_pair
1280                .monitor_pair
1281                .analog_input_pairs
1282                .iter_mut()
1283                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1284                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1285                .flat_map(|pair| pair.mutes.iter_mut())
1286                .enumerate()
1287                .for_each(|(i, mute)| *mute = i % 2 > 0);
1288            mixer_pair
1289                .monitor_pair
1290                .analog_input_pairs
1291                .iter_mut()
1292                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1293                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1294                .flat_map(|pair| pair.solos.iter_mut())
1295                .enumerate()
1296                .for_each(|(i, solo)| *solo = i % 2 > 0);
1297            mixer_pair
1298                .monitor_pair
1299                .analog_input_pairs
1300                .iter_mut()
1301                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1302                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1303                .enumerate()
1304                .for_each(|(i, pair)| pair.link = i % 2 > 0);
1305        });
1306        params
1307            .mixer_pairs
1308            .iter_mut()
1309            .flat_map(|pair| pair.monitor_pair.output_volumes.iter_mut())
1310            .enumerate()
1311            .for_each(|(i, vol)| *vol = 3 * i as u32);
1312        params
1313            .mixer_pairs
1314            .iter_mut()
1315            .flat_map(|pair| pair.monitor_pair.output_mutes.iter_mut())
1316            .enumerate()
1317            .for_each(|(i, mute)| *mute = i % 2 > 0);
1318        params.master_knob = 111;
1319        params.blend_knob = 111;
1320
1321        let size = compute_params_size(
1322            <Io14fwProtocol as AlesisParametersSerdes<IofwMixerParams>>::OFFSET_RANGES,
1323        );
1324        let mut raw = vec![0u8; size];
1325        Io14fwProtocol::serialize_params(&params, &mut raw).unwrap();
1326
1327        let mut p = Io14fwProtocol::create_mixer_params();
1328        Io14fwProtocol::deserialize_params(&mut p, &raw).unwrap();
1329
1330        assert_eq!(params, p);
1331    }
1332
1333    #[test]
1334    fn io26fw_mixer_params_serdes() {
1335        let mut params = Io26fwProtocol::create_mixer_params();
1336        params.mixer_pairs.iter_mut().for_each(|mixer_pair| {
1337            mixer_pair
1338                .monitor_pair
1339                .analog_input_pairs
1340                .iter_mut()
1341                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1342                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1343                .flat_map(|pair| pair.gain_to_left.iter_mut())
1344                .enumerate()
1345                .for_each(|(i, gain)| *gain = 2 * i as i32);
1346            mixer_pair
1347                .monitor_pair
1348                .analog_input_pairs
1349                .iter_mut()
1350                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1351                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1352                .flat_map(|pair| pair.gain_to_right.iter_mut())
1353                .enumerate()
1354                .for_each(|(i, gain)| *gain = 1 + 2 * i as i32);
1355            [
1356                &mut mixer_pair.stream_inputs_to_left[..],
1357                &mut mixer_pair.stream_inputs_to_right[..],
1358            ]
1359            .iter_mut()
1360            .enumerate()
1361            .for_each(|(i, gains)| {
1362                gains
1363                    .iter_mut()
1364                    .enumerate()
1365                    .for_each(|(j, gain)| *gain = (i * 8 + j) as i32);
1366            });
1367            mixer_pair
1368                .monitor_pair
1369                .analog_input_pairs
1370                .iter_mut()
1371                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1372                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1373                .flat_map(|pair| pair.mutes.iter_mut())
1374                .enumerate()
1375                .for_each(|(i, mute)| *mute = i % 2 > 0);
1376            mixer_pair
1377                .monitor_pair
1378                .analog_input_pairs
1379                .iter_mut()
1380                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1381                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1382                .flat_map(|pair| pair.solos.iter_mut())
1383                .enumerate()
1384                .for_each(|(i, solo)| *solo = i % 2 > 0);
1385            mixer_pair
1386                .monitor_pair
1387                .analog_input_pairs
1388                .iter_mut()
1389                .chain(mixer_pair.monitor_pair.digital_a_input_pairs.iter_mut())
1390                .chain(mixer_pair.monitor_pair.digital_b_input_pairs.iter_mut())
1391                .enumerate()
1392                .for_each(|(i, pair)| pair.link = i % 2 > 0);
1393        });
1394        params
1395            .mixer_pairs
1396            .iter_mut()
1397            .flat_map(|pair| pair.monitor_pair.output_volumes.iter_mut())
1398            .enumerate()
1399            .for_each(|(i, vol)| *vol = 3 * i as u32);
1400        params
1401            .mixer_pairs
1402            .iter_mut()
1403            .flat_map(|pair| pair.monitor_pair.output_mutes.iter_mut())
1404            .enumerate()
1405            .for_each(|(i, mute)| *mute = i % 2 > 0);
1406        params.master_knob = 111;
1407        params.blend_knob = 111;
1408        let size = compute_params_size(
1409            <Io26fwProtocol as AlesisParametersSerdes<IofwMixerParams>>::OFFSET_RANGES,
1410        );
1411        let mut raw = vec![0u8; size];
1412        Io26fwProtocol::serialize_params(&params, &mut raw).unwrap();
1413
1414        let mut p = Io26fwProtocol::create_mixer_params();
1415        Io26fwProtocol::deserialize_params(&mut p, &raw).unwrap();
1416
1417        assert_eq!(params, p);
1418    }
1419}