1#![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
32pub trait EfwHardwareSpecification {
34 const SUPPORTED_SAMPLING_RATES: &'static [u32];
36 const SUPPORTED_SAMPLING_CLOCKS: &'static [ClkSrc];
38 const CAPABILITIES: &'static [HwCap];
40 const RX_CHANNEL_COUNTS: [usize; 3];
42 const TX_CHANNEL_COUNTS: [usize; 3];
44 const MONITOR_SOURCE_COUNT: usize;
46 const MONITOR_DESTINATION_COUNT: usize;
48 const MIDI_INPUT_COUNT: usize;
50 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 fn phys_input_count() -> usize {
59 Self::PHYS_INPUT_GROUPS
60 .iter()
61 .fold(0, |count, entry| count + entry.1)
62 }
63
64 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
114pub 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
122pub 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
135pub 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#[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 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 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#[derive(Debug, Copy, Clone, PartialEq, Eq)]
189pub enum HwCap {
190 ChangeableRespAddr,
192 ControlRoom,
194 OptionalSpdifCoax,
196 OptionalAesebuXlr,
198 Dsp,
200 Fpga,
202 PhantomPowering,
204 OutputMapping,
206 InputGain,
208 OptionalSpdifOpt,
210 OptionalAdatOpt,
212 NominalInput,
214 NominalOutput,
216 SoftClip,
218 RobotGuitar,
220 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#[derive(Debug, Copy, Clone, PartialEq, Eq)]
278pub enum NominalSignalLevel {
279 Professional,
281 Medium,
282 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#[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#[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}