firewire_fireworks_protocols/
lib.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4#![doc = include_str!("../README.md")]
5
6pub mod flash;
7pub mod hw_ctl;
8pub mod hw_info;
9pub mod monitor;
10pub mod phys_input;
11pub mod phys_output;
12pub mod playback;
13pub mod port_conf;
14pub mod robot_guitar;
15pub mod transaction;
16pub mod transport;
17
18pub mod audiofire;
19pub mod onyx_f;
20
21pub mod rip;
22
23use {
24    glib::{Error, FileError},
25    hitaki::{prelude::EfwProtocolExtManual, EfwProtocolError},
26    hw_info::HwMeter,
27    monitor::{EfwMonitorParameters, EfwMonitorSourceParameters},
28    phys_output::EfwOutputParameters,
29    playback::{EfwPlaybackParameters, EfwPlaybackSoloSpecification},
30};
31
32/// The specification of hardware.
33pub trait EfwHardwareSpecification {
34    /// The list of supported sampling transfer frequencies.
35    const SUPPORTED_SAMPLING_RATES: &'static [u32];
36    /// The list of supported sources of sampling clock.
37    const SUPPORTED_SAMPLING_CLOCKS: &'static [ClkSrc];
38    /// The list of hardware capabilities.
39    const CAPABILITIES: &'static [HwCap];
40    /// The number of audio channels in received isochronous stream at each rate mode.
41    const RX_CHANNEL_COUNTS: [usize; 3];
42    /// The number of audio channels in transmitted isochronous stream at each rate mode.
43    const TX_CHANNEL_COUNTS: [usize; 3];
44    /// The total number of monitor inputs.
45    const MONITOR_SOURCE_COUNT: usize;
46    /// The total number of monitor outputs.
47    const MONITOR_DESTINATION_COUNT: usize;
48    /// The number of MIDI input port.
49    const MIDI_INPUT_COUNT: usize;
50    /// The number of MIDI output port.
51    const MIDI_OUTPUT_COUNT: usize;
52
53    const PHYS_INPUT_GROUPS: &'static [(PhysGroupType, usize)];
54
55    const PHYS_OUTPUT_GROUPS: &'static [(PhysGroupType, usize)];
56
57    /// The total number of physical audio inputs.
58    fn phys_input_count() -> usize {
59        Self::PHYS_INPUT_GROUPS
60            .iter()
61            .fold(0, |count, entry| count + entry.1)
62    }
63
64    /// The total number of physical audio outputs.
65    fn phys_output_count() -> usize {
66        Self::PHYS_OUTPUT_GROUPS
67            .iter()
68            .fold(0, |count, entry| count + entry.1)
69    }
70
71    fn create_hardware_meter() -> HwMeter {
72        HwMeter {
73            detected_clk_srcs: Self::SUPPORTED_SAMPLING_CLOCKS
74                .iter()
75                .map(|&src| (src, Default::default()))
76                .collect(),
77            detected_midi_inputs: Default::default(),
78            detected_midi_outputs: Default::default(),
79            guitar_charging: Default::default(),
80            guitar_stereo_connect: Default::default(),
81            guitar_hex_signal: Default::default(),
82            phys_output_meters: vec![Default::default(); Self::phys_output_count()],
83            phys_input_meters: vec![Default::default(); Self::phys_input_count()],
84        }
85    }
86
87    fn create_monitor_parameters() -> EfwMonitorParameters {
88        EfwMonitorParameters(vec![
89            EfwMonitorSourceParameters {
90                gains: vec![Default::default(); Self::MONITOR_SOURCE_COUNT],
91                mutes: vec![Default::default(); Self::MONITOR_SOURCE_COUNT],
92                solos: vec![Default::default(); Self::MONITOR_SOURCE_COUNT],
93                pans: vec![Default::default(); Self::MONITOR_SOURCE_COUNT],
94            };
95            Self::MONITOR_DESTINATION_COUNT
96        ])
97    }
98
99    fn create_output_parameters() -> EfwOutputParameters {
100        EfwOutputParameters {
101            volumes: vec![Default::default(); Self::phys_output_count()],
102            mutes: vec![Default::default(); Self::phys_output_count()],
103        }
104    }
105
106    fn create_playback_parameters() -> EfwPlaybackParameters {
107        EfwPlaybackParameters {
108            volumes: vec![Default::default(); Self::RX_CHANNEL_COUNTS[0]],
109            mutes: vec![Default::default(); Self::RX_CHANNEL_COUNTS[0]],
110        }
111    }
112}
113
114/// Cache whole parameters.
115pub trait EfwWhollyCachableParamsOperation<P, T>
116where
117    P: EfwProtocolExtManual,
118{
119    fn cache_wholly(proto: &mut P, states: &mut T, timeout_ms: u32) -> Result<(), Error>;
120}
121
122/// Update the part of parameters.
123pub trait EfwPartiallyUpdatableParamsOperation<P, T>
124where
125    P: EfwProtocolExtManual,
126{
127    fn update_partially(
128        proto: &mut P,
129        params: &mut T,
130        update: T,
131        timeout_ms: u32,
132    ) -> Result<(), Error>;
133}
134
135/// Update whole parameters.
136pub trait EfwWhollyUpdatableParamsOperation<P, T>
137where
138    P: EfwProtocolExtManual,
139{
140    fn update_wholly(proto: &mut P, states: &T, timeout_ms: u32) -> Result<(), Error>;
141}
142
143/// Signal source of sampling clock.
144#[derive(Debug, Copy, Clone, PartialEq, Eq)]
145pub enum ClkSrc {
146    Internal,
147    WordClock,
148    Spdif,
149    Adat,
150    Adat2,
151    Continuous,
152    Reserved(u32),
153}
154
155impl Default for ClkSrc {
156    fn default() -> Self {
157        Self::Reserved(u32::MAX)
158    }
159}
160
161fn serialize_clock_source(src: &ClkSrc) -> u32 {
162    match src {
163        ClkSrc::Internal => 0,
164        // blank.
165        ClkSrc::WordClock => 2,
166        ClkSrc::Spdif => 3,
167        ClkSrc::Adat => 4,
168        ClkSrc::Adat2 => 5,
169        ClkSrc::Continuous => 6,
170        ClkSrc::Reserved(val) => *val,
171    }
172}
173
174fn deserialize_clock_source(src: &mut ClkSrc, val: u32) {
175    *src = match val {
176        0 => ClkSrc::Internal,
177        // blank.
178        2 => ClkSrc::WordClock,
179        3 => ClkSrc::Spdif,
180        4 => ClkSrc::Adat,
181        5 => ClkSrc::Adat2,
182        6 => ClkSrc::Continuous,
183        _ => ClkSrc::Reserved(val),
184    };
185}
186
187/// Hardware capability.
188#[derive(Debug, Copy, Clone, PartialEq, Eq)]
189pub enum HwCap {
190    /// The address to which response of transaction is transmitted is configurable.
191    ChangeableRespAddr,
192    /// Has control room for output mirror.
193    ControlRoom,
194    /// S/PDIF signal is available for coaxial interface as option.
195    OptionalSpdifCoax,
196    /// S/PDIF signal is available for AES/EBU XLR interface as option.
197    OptionalAesebuXlr,
198    /// Has DSP (Texas Instrument TMS320C67).
199    Dsp,
200    /// Has FPGA (Xilinx Spartan XC35250E).
201    Fpga,
202    /// Support phantom powering for any mic input.
203    PhantomPowering,
204    /// Support mapping between playback stream and physical output.
205    OutputMapping,
206    /// The gain of physical input is adjustable.
207    InputGain,
208    /// S/PDIF signal is available for optical interface as option.
209    OptionalSpdifOpt,
210    /// ADAT signal is available for optical interface as option.
211    OptionalAdatOpt,
212    /// The nominal level of input audio signal is selectable.
213    NominalInput,
214    /// The nominal level of output audio signal is selectable.
215    NominalOutput,
216    /// Has software clipping for input audio signal.
217    SoftClip,
218    /// Is robot guitar.
219    RobotGuitar,
220    /// Support chaging for guitar.
221    GuitarCharging,
222    Reserved(usize),
223}
224
225impl Default for HwCap {
226    fn default() -> Self {
227        Self::Reserved(usize::MAX)
228    }
229}
230
231#[cfg(test)]
232fn serialize_hw_cap(cap: &HwCap) -> usize {
233    match cap {
234        HwCap::ChangeableRespAddr => 0,
235        HwCap::ControlRoom => 1,
236        HwCap::OptionalSpdifCoax => 2,
237        HwCap::OptionalAesebuXlr => 3,
238        HwCap::Dsp => 4,
239        HwCap::Fpga => 5,
240        HwCap::PhantomPowering => 6,
241        HwCap::OutputMapping => 7,
242        HwCap::InputGain => 8,
243        HwCap::OptionalSpdifOpt => 9,
244        HwCap::OptionalAdatOpt => 10,
245        HwCap::NominalInput => 11,
246        HwCap::NominalOutput => 12,
247        HwCap::SoftClip => 13,
248        HwCap::RobotGuitar => 14,
249        HwCap::GuitarCharging => 15,
250        HwCap::Reserved(pos) => *pos,
251    }
252}
253
254fn deserialize_hw_cap(cap: &mut HwCap, pos: usize) {
255    *cap = match pos {
256        0 => HwCap::ChangeableRespAddr,
257        1 => HwCap::ControlRoom,
258        2 => HwCap::OptionalSpdifCoax,
259        3 => HwCap::OptionalAesebuXlr,
260        4 => HwCap::Dsp,
261        5 => HwCap::Fpga,
262        6 => HwCap::PhantomPowering,
263        7 => HwCap::OutputMapping,
264        8 => HwCap::InputGain,
265        9 => HwCap::OptionalSpdifOpt,
266        10 => HwCap::OptionalAdatOpt,
267        11 => HwCap::NominalInput,
268        12 => HwCap::NominalOutput,
269        13 => HwCap::SoftClip,
270        14 => HwCap::RobotGuitar,
271        15 => HwCap::GuitarCharging,
272        _ => HwCap::Reserved(pos),
273    };
274}
275
276/// Nominal level of audio signal.
277#[derive(Debug, Copy, Clone, PartialEq, Eq)]
278pub enum NominalSignalLevel {
279    /// +4 dBu.
280    Professional,
281    Medium,
282    /// -10 dBV.
283    Consumer,
284}
285
286impl Default for NominalSignalLevel {
287    fn default() -> Self {
288        Self::Professional
289    }
290}
291
292fn serialize_nominal_signal_level(level: &NominalSignalLevel) -> u32 {
293    match level {
294        NominalSignalLevel::Consumer => 2,
295        NominalSignalLevel::Medium => 1,
296        NominalSignalLevel::Professional => 0,
297    }
298}
299
300fn deserialize_nominal_signal_level(level: &mut NominalSignalLevel, val: u32) {
301    *level = match val {
302        2 => NominalSignalLevel::Consumer,
303        1 => NominalSignalLevel::Medium,
304        _ => NominalSignalLevel::Professional,
305    };
306}
307
308/// Type of physical group.
309#[derive(Debug, Copy, Clone, PartialEq, Eq)]
310pub enum PhysGroupType {
311    Analog,
312    Spdif,
313    Adat,
314    SpdifOrAdat,
315    AnalogMirror,
316    Headphones,
317    I2s,
318    Guitar,
319    PiezoGuitar,
320    GuitarString,
321    Unknown(u8),
322}
323
324#[cfg(test)]
325fn serialize_phys_group_type(group_type: &PhysGroupType) -> u8 {
326    match group_type {
327        PhysGroupType::Analog => 0,
328        PhysGroupType::Spdif => 1,
329        PhysGroupType::Adat => 2,
330        PhysGroupType::SpdifOrAdat => 3,
331        PhysGroupType::AnalogMirror => 4,
332        PhysGroupType::Headphones => 5,
333        PhysGroupType::I2s => 6,
334        PhysGroupType::Guitar => 7,
335        PhysGroupType::PiezoGuitar => 8,
336        PhysGroupType::GuitarString => 9,
337        PhysGroupType::Unknown(val) => *val,
338    }
339}
340
341fn deserialize_phys_group_type(group_type: &mut PhysGroupType, val: u8) {
342    *group_type = match val {
343        0 => PhysGroupType::Analog,
344        1 => PhysGroupType::Spdif,
345        2 => PhysGroupType::Adat,
346        3 => PhysGroupType::SpdifOrAdat,
347        4 => PhysGroupType::AnalogMirror,
348        5 => PhysGroupType::Headphones,
349        6 => PhysGroupType::I2s,
350        7 => PhysGroupType::Guitar,
351        8 => PhysGroupType::PiezoGuitar,
352        9 => PhysGroupType::GuitarString,
353        _ => PhysGroupType::Unknown(val),
354    };
355}
356
357impl Default for PhysGroupType {
358    fn default() -> Self {
359        Self::Unknown(u8::MAX)
360    }
361}
362
363/// Entry of physical group.
364#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
365pub struct PhysGroupEntry {
366    pub group_type: PhysGroupType,
367    pub group_count: usize,
368}
369
370#[cfg(test)]
371mod test {
372    use super::*;
373
374    #[test]
375    fn clock_source_serdes() {
376        [
377            ClkSrc::Internal,
378            ClkSrc::WordClock,
379            ClkSrc::Spdif,
380            ClkSrc::Adat,
381            ClkSrc::Adat2,
382            ClkSrc::Continuous,
383            ClkSrc::default(),
384        ]
385        .iter()
386        .for_each(|src| {
387            let val = serialize_clock_source(&src);
388            let mut s = ClkSrc::default();
389            deserialize_clock_source(&mut s, val);
390            assert_eq!(*src, s);
391        });
392    }
393
394    #[test]
395    fn nominal_signal_level_serdes() {
396        [
397            NominalSignalLevel::Professional,
398            NominalSignalLevel::Medium,
399            NominalSignalLevel::Consumer,
400        ]
401        .iter()
402        .for_each(|level| {
403            let val = serialize_nominal_signal_level(&level);
404            let mut l = NominalSignalLevel::default();
405            deserialize_nominal_signal_level(&mut l, val);
406            assert_eq!(*level, l);
407        });
408    }
409
410    #[test]
411    fn phys_group_type_serdes() {
412        [
413            PhysGroupType::Analog,
414            PhysGroupType::Spdif,
415            PhysGroupType::Adat,
416            PhysGroupType::SpdifOrAdat,
417            PhysGroupType::AnalogMirror,
418            PhysGroupType::Headphones,
419            PhysGroupType::I2s,
420            PhysGroupType::Guitar,
421            PhysGroupType::PiezoGuitar,
422            PhysGroupType::GuitarString,
423            PhysGroupType::default(),
424        ]
425        .iter()
426        .for_each(|group_type| {
427            let val = serialize_phys_group_type(&group_type);
428            let mut t = PhysGroupType::default();
429            deserialize_phys_group_type(&mut t, val);
430            assert_eq!(*group_type, t);
431        });
432    }
433
434    #[test]
435    fn hw_cap_serdes() {
436        [
437            HwCap::ChangeableRespAddr,
438            HwCap::ControlRoom,
439            HwCap::OptionalSpdifCoax,
440            HwCap::OptionalAesebuXlr,
441            HwCap::Dsp,
442            HwCap::Fpga,
443            HwCap::PhantomPowering,
444            HwCap::OutputMapping,
445            HwCap::InputGain,
446            HwCap::OptionalSpdifOpt,
447            HwCap::OptionalAdatOpt,
448            HwCap::NominalInput,
449            HwCap::NominalOutput,
450            HwCap::SoftClip,
451            HwCap::RobotGuitar,
452            HwCap::GuitarCharging,
453            HwCap::default(),
454        ]
455        .iter()
456        .for_each(|cap| {
457            let val = serialize_hw_cap(&cap);
458            let mut c = HwCap::default();
459            deserialize_hw_cap(&mut c, val);
460            assert_eq!(*cap, c);
461        });
462    }
463}