firewire_dice_protocols/tcelectronic/shell/
klive.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2020 Takashi Sakamoto
3
4//! Protocol defined by TC Electronic for Konnekt Live.
5//!
6//! The module includes structure, enumeration, and trait and its implementation for protocol
7//! defined by TC Electronic for Konnekt Live.
8//!
9//! ## Diagram of internal signal flow
10//!
11//! ```text
12//!
13//! XLR input 1 ----------------or----+--------------------------> analog-input-1/2
14//! Phone input 1 --------------+     |
15//!                                   |
16//! XLR input 2 ----------------or----+
17//! Phone input 2 --------------+
18//!
19//! Phone input 3/4  --------------------------------------------> analog-input-3/4
20//!                               ++=========++
21//! Coaxial input --------------> || digital ||
22//!                               || input   || -----------------> digital-input-1..8
23//! Optical input --------------> || select  ||
24//!                               ++=========++
25//!
26//! analog-input-1/2 --------------------------------------------> stream-output-1/2
27//! analog-input-3/4 --------------------------------------------> stream-output-3/4
28//! channel-strip-effects-output-1/2 ----------------------------> stream-output-5/6
29//! reverb-effect-output-1/2 ------------------------------------> stream-output-7/8
30//! digital-input-1..8 ------------------------------------------> stream-output-9..16
31//!
32//!                                           ++============++
33//! analog-input-1/2 ---+                     ||            ||
34//! analog-input-3/4 ---+                     ||  channel   ||
35//! digital-input-1/2 --+-- (one of them) --> ||   strip    || --> channel-strip-effect-output-1/2
36//! digital-input-3/4 --+  (internal mode)    ||  effects   ||
37//! digital-input-5/6 --+                     ||    1/2     ||
38//! digital-input-7/8 --+                     ||            ||
39//! stream-input-5/6  ----- (plugin mode) --> ++============++
40//!
41//!                                           ++============++
42//! analog-input-1/2 --- (internal mode) ---> ||            ||
43//! analog-input-3/4 --- (internal mode) ---> ||   reverb   ||
44//! digital-input-1/2 -- (internal mode) ---> ||            ||
45//! digital-input-3/4 -- (internal mode) ---> ||   effect   || --> reverb-effect-output-1/2
46//! digital-input-5/6 -- (internal mode) ---> ||            ||
47//! digital-input-7/8 -- (internal mode) ---> ||   12 x 2   ||
48//! stream-input-7/8 --- (plugin mode) -----> ||            ||
49//!                                           ++============++
50//!
51//!
52//! stream-input-1/2 --------------(one of them) ----------------> stream-source-input-1/2
53//! stream-input-3/4 ------------------+
54//! stream-input-5/6 ------------------+
55//! stream-input-7/8 ------------------+
56//! stream-input-9/10 -----------------+
57//! stream-input-11/12 ----------------+
58//! stream-input-13/14 ----------------+
59//! stream-input-15/16 ----------------+
60//!                                      ++==========++
61//! analog-input-1/2 -----------or-----> ||          ||
62//! channel-effect-output-1/2 --+        ||          ||
63//!                                      ||          ||
64//! analog-input-3/4 -----------or-----> ||          ||
65//! channel-effect-output-1/2 --+        ||          ||
66//!                                      ||          ||
67//! digital-input-1/2 ----------or-----> ||          ||
68//! channel-effect-output-1/2 --+        ||  16 x 2  ||
69//!                                      ||          ||
70//! digital-input-3/4 ----------or-----> ||          || ---------> mixer-output-1/2
71//! channel-effect-output-1/2 --+        ||  mixer   ||
72//!                                      ||          ||
73//! digital-input-5/6 ----------or-----> ||          ||
74//! channel-effect-output-1/2 --+        ||          ||
75//!                                      ||          ||
76//! digital-input-7/8 ----------or-----> ||          ||
77//! channel-effect-output-1/2 --+        ||          ||
78//!                                      ||          ||
79//! reverb-effect-output-1/2 ----------> ||          ||
80//! stream-source-input-1/2 -----------> ||          ||
81//!                                      ++==========++
82//!
83//!
84//! stream-input-1/2 -------------(one of them) -----------------> analog-output-1/2
85//! analog-input-1/2 ------------------+
86//! mixer-output-1/2 ------------------+
87//! reverb-source-1/2 -----------------+
88//!
89//! stream-input-1/2 -------------(one of them) -----------------> analog-output-3/4
90//! analog-input-1/2 ------------------+
91//! mixer-output-1/2 ------------------+
92//! reverb-source-1/2 -----------------+
93//!
94//! stream-input-15/16 -----------(one of them) -----------------> coaxial-output-1/2
95//! analog-input-1/2 ------------------+
96//! mixer-output-1/2 ------------------+
97//! reverb-source-1/2 -----------------+
98//!
99//! stream-input-9..16 -----------(one of them) -----------------> optical-output-9..16
100//! analog-input-1/2 ------------------+
101//! mixer-output-1/2 ------------------+
102//! reverb-source-1/2 -----------------+
103//!
104//! ```
105
106use super::*;
107
108/// Protocol implementation of Konnekt Live.
109#[derive(Default, Debug)]
110pub struct KliveProtocol;
111
112impl TcatOperation for KliveProtocol {}
113
114impl TcatGlobalSectionSpecification for KliveProtocol {}
115
116/// Segment for knob. 0x0000..0x0027 (36 quads).
117pub type KliveKnobSegment = TcKonnektSegment<KliveKnob>;
118
119/// Segment for configuration. 0x0028..0x00ab (33 quads).
120pub type KliveConfigSegment = TcKonnektSegment<KliveConfig>;
121
122/// Segment for state of mixer. 0x00ac..0x0217 (91 quads).
123pub type KliveMixerStateSegment = TcKonnektSegment<KliveMixerState>;
124
125/// Segment for state of reverb effect. 0x0218..0x025b. (17 quads)
126pub type KliveReverbStateSegment = TcKonnektSegment<KliveReverbState>;
127
128/// Segment for states of channel strip effect. 0x0260..0x037f (72 quads).
129pub type KliveChStripStatesSegment = TcKonnektSegment<KliveChStripStates>;
130
131// NOTE: Segment for tuner. 0x0384..0x039c (8 quads).
132
133/// Segment for mixer meter. 0x1068..0x10c3 (23 quads).
134pub type KliveMixerMeterSegment = TcKonnektSegment<KliveMixerMeter>;
135
136/// Segment for state of hardware. 0x1008..0x1023 (7 quads).
137pub type KliveHwStateSegment = TcKonnektSegment<KliveHwState>;
138
139/// Segment for meter of reverb effect. 0x10c4..0x010db (6 quads).
140pub type KliveReverbMeterSegment = TcKonnektSegment<KliveReverbMeter>;
141
142/// Segment for meters of channel strip effect. 0x10dc..0x1117 (15 quads).
143pub type KliveChStripMetersSegment = TcKonnektSegment<KliveChStripMeters>;
144
145macro_rules! segment_default {
146    ($p:ty, $t:ty) => {
147        impl Default for TcKonnektSegment<$t> {
148            fn default() -> Self {
149                Self {
150                    data: <$t>::default(),
151                    raw: vec![0; <$p as TcKonnektSegmentSerdes<$t>>::SIZE],
152                }
153            }
154        }
155    };
156}
157
158segment_default!(KliveProtocol, KliveKnob);
159segment_default!(KliveProtocol, KliveConfig);
160segment_default!(KliveProtocol, KliveMixerState);
161segment_default!(KliveProtocol, KliveReverbState);
162segment_default!(KliveProtocol, KliveChStripStates);
163segment_default!(KliveProtocol, KliveMixerMeter);
164segment_default!(KliveProtocol, KliveHwState);
165segment_default!(KliveProtocol, KliveReverbMeter);
166segment_default!(KliveProtocol, KliveChStripMeters);
167
168/// State of knob.
169#[derive(Debug, Copy, Clone, PartialEq, Eq)]
170pub struct KliveKnob {
171    /// Target of 1st knob.
172    pub knob0_target: ShellKnob0Target,
173    /// Target of 2nd knob.
174    pub knob1_target: ShellKnob1Target,
175    /// Loaded program number.
176    pub prog: TcKonnektLoadedProgram,
177    /// Impedance of outputs.
178    pub out_impedance: [OutputImpedance; 2],
179}
180
181impl Default for KliveKnob {
182    fn default() -> Self {
183        Self {
184            knob0_target: KliveProtocol::KNOB0_TARGETS[0],
185            knob1_target: KliveProtocol::KNOB1_TARGETS[0],
186            prog: Default::default(),
187            out_impedance: Default::default(),
188        }
189    }
190}
191
192impl ShellKnob0TargetSpecification for KliveProtocol {
193    const KNOB0_TARGETS: &'static [ShellKnob0Target] = &[
194        ShellKnob0Target::Analog0,
195        ShellKnob0Target::Analog1,
196        ShellKnob0Target::Analog2_3,
197        ShellKnob0Target::Configurable,
198    ];
199}
200
201impl ShellKnob1TargetSpecification for KliveProtocol {
202    const KNOB1_TARGETS: &'static [ShellKnob1Target] = &[
203        ShellKnob1Target::Digital0_1,
204        ShellKnob1Target::Digital2_3,
205        ShellKnob1Target::Digital4_5,
206        ShellKnob1Target::Digital6_7,
207        ShellKnob1Target::Stream,
208        ShellKnob1Target::Reverb,
209        ShellKnob1Target::Mixer,
210        ShellKnob1Target::TunerPitchTone,
211        ShellKnob1Target::MidiSend,
212    ];
213}
214
215impl TcKonnektSegmentSerdes<KliveKnob> for KliveProtocol {
216    const NAME: &'static str = "knob";
217    const OFFSET: usize = 0x0004;
218    const SIZE: usize = SHELL_KNOB_SEGMENT_SIZE;
219
220    fn serialize(params: &KliveKnob, raw: &mut [u8]) -> Result<(), String> {
221        serialize_knob0_target::<KliveProtocol>(&params.knob0_target, &mut raw[..4])?;
222        serialize_knob1_target::<KliveProtocol>(&params.knob1_target, &mut raw[4..8])?;
223        serialize_loaded_program(&params.prog, &mut raw[8..12])?;
224        serialize_output_impedance(&params.out_impedance[0], &mut raw[12..16])?;
225        serialize_output_impedance(&params.out_impedance[1], &mut raw[16..20])?;
226        Ok(())
227    }
228
229    fn deserialize(params: &mut KliveKnob, raw: &[u8]) -> Result<(), String> {
230        deserialize_knob0_target::<KliveProtocol>(&mut params.knob0_target, &raw[..4])?;
231        deserialize_knob1_target::<KliveProtocol>(&mut params.knob1_target, &raw[4..8])?;
232        deserialize_loaded_program(&mut params.prog, &raw[8..12])?;
233        deserialize_output_impedance(&mut params.out_impedance[0], &raw[12..16])?;
234        deserialize_output_impedance(&mut params.out_impedance[1], &raw[16..20])?;
235        Ok(())
236    }
237}
238
239impl TcKonnektMutableSegmentOperation<KliveKnob> for KliveProtocol {}
240
241impl TcKonnektNotifiedSegmentOperation<KliveKnob> for KliveProtocol {
242    const NOTIFY_FLAG: u32 = SHELL_KNOB_NOTIFY_FLAG;
243}
244
245impl AsRef<ShellKnob0Target> for KliveKnob {
246    fn as_ref(&self) -> &ShellKnob0Target {
247        &self.knob0_target
248    }
249}
250
251impl AsMut<ShellKnob0Target> for KliveKnob {
252    fn as_mut(&mut self) -> &mut ShellKnob0Target {
253        &mut self.knob0_target
254    }
255}
256
257impl AsRef<ShellKnob1Target> for KliveKnob {
258    fn as_ref(&self) -> &ShellKnob1Target {
259        &self.knob1_target
260    }
261}
262
263impl AsMut<ShellKnob1Target> for KliveKnob {
264    fn as_mut(&mut self) -> &mut ShellKnob1Target {
265        &mut self.knob1_target
266    }
267}
268
269impl AsRef<TcKonnektLoadedProgram> for KliveKnob {
270    fn as_ref(&self) -> &TcKonnektLoadedProgram {
271        &self.prog
272    }
273}
274
275impl AsMut<TcKonnektLoadedProgram> for KliveKnob {
276    fn as_mut(&mut self) -> &mut TcKonnektLoadedProgram {
277        &mut self.prog
278    }
279}
280
281/// Configuration.
282#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
283pub struct KliveConfig {
284    /// Configuration for optical interface.
285    pub opt: ShellOptIfaceConfig,
286    /// Source of coaxial output.
287    pub coax_out_src: ShellCoaxOutPairSrc,
288    /// Source of analog output 1/2.
289    pub out_01_src: ShellPhysOutSrc,
290    /// Source of analog output 3/4.
291    pub out_23_src: ShellPhysOutSrc,
292    /// Source of stream input pair as mixer source.
293    pub mixer_stream_src_pair: ShellMixerStreamSourcePair,
294    /// Source of sampling clock at standalone mode.
295    pub standalone_src: ShellStandaloneClockSource,
296    /// Rate of sampling clock at standalone mode.
297    pub standalone_rate: TcKonnektStandaloneClockRate,
298    /// Configuration for midi event generator.
299    pub midi_sender: TcKonnektMidiSender,
300}
301
302impl ShellMixerStreamSourcePairSpecification for KliveProtocol {
303    const MIXER_STREAM_SOURCE_PAIRS: &'static [ShellMixerStreamSourcePair] = &[
304        ShellMixerStreamSourcePair::Stream0_1,
305        ShellMixerStreamSourcePair::Stream2_3,
306        ShellMixerStreamSourcePair::Stream4_5,
307        ShellMixerStreamSourcePair::Stream6_7,
308        ShellMixerStreamSourcePair::Stream8_9,
309        ShellMixerStreamSourcePair::Stream10_11,
310    ];
311}
312
313impl ShellStandaloneClockSpecification for KliveProtocol {
314    const STANDALONE_CLOCK_SOURCES: &'static [ShellStandaloneClockSource] = &[
315        ShellStandaloneClockSource::Optical,
316        ShellStandaloneClockSource::Coaxial,
317        ShellStandaloneClockSource::Internal,
318    ];
319}
320
321impl TcKonnektSegmentSerdes<KliveConfig> for KliveProtocol {
322    const NAME: &'static str = "configuration";
323    const OFFSET: usize = 0x0028;
324    const SIZE: usize = 132;
325
326    fn serialize(params: &KliveConfig, raw: &mut [u8]) -> Result<(), String> {
327        serialize_opt_iface_config(&params.opt, &mut raw[..12])?;
328        serialize_coax_out_pair_source(&params.coax_out_src, &mut raw[12..16])?;
329        serialize_phys_out_src(&params.out_01_src, &mut raw[16..20])?;
330        serialize_phys_out_src(&params.out_23_src, &mut raw[20..24])?;
331        serialize_mixer_stream_source_pair::<KliveProtocol>(
332            &params.mixer_stream_src_pair,
333            &mut raw[24..28],
334        )?;
335        serialize_standalone_clock_source::<KliveProtocol>(
336            &params.standalone_src,
337            &mut raw[28..32],
338        )?;
339        serialize_standalone_clock_rate(&params.standalone_rate, &mut raw[32..36])?;
340        serialize_midi_sender(&params.midi_sender, &mut raw[84..120])?;
341        Ok(())
342    }
343
344    fn deserialize(params: &mut KliveConfig, raw: &[u8]) -> Result<(), String> {
345        deserialize_opt_iface_config(&mut params.opt, &raw[..12])?;
346        deserialize_coax_out_pair_source(&mut params.coax_out_src, &raw[12..16])?;
347        deserialize_phys_out_src(&mut params.out_01_src, &raw[16..20])?;
348        deserialize_phys_out_src(&mut params.out_23_src, &raw[20..24])?;
349        deserialize_mixer_stream_source_pair::<KliveProtocol>(
350            &mut params.mixer_stream_src_pair,
351            &raw[24..28],
352        )?;
353        deserialize_standalone_clock_source::<KliveProtocol>(
354            &mut params.standalone_src,
355            &raw[28..32],
356        )?;
357        deserialize_standalone_clock_rate(&mut params.standalone_rate, &raw[32..36])?;
358        deserialize_midi_sender(&mut params.midi_sender, &raw[84..120])?;
359        Ok(())
360    }
361}
362
363impl TcKonnektMutableSegmentOperation<KliveConfig> for KliveProtocol {}
364
365impl TcKonnektNotifiedSegmentOperation<KliveConfig> for KliveProtocol {
366    const NOTIFY_FLAG: u32 = SHELL_CONFIG_NOTIFY_FLAG;
367}
368
369impl AsRef<ShellOptIfaceConfig> for KliveConfig {
370    fn as_ref(&self) -> &ShellOptIfaceConfig {
371        &self.opt
372    }
373}
374
375impl AsMut<ShellOptIfaceConfig> for KliveConfig {
376    fn as_mut(&mut self) -> &mut ShellOptIfaceConfig {
377        &mut self.opt
378    }
379}
380
381impl AsRef<ShellCoaxOutPairSrc> for KliveConfig {
382    fn as_ref(&self) -> &ShellCoaxOutPairSrc {
383        &self.coax_out_src
384    }
385}
386
387impl AsMut<ShellCoaxOutPairSrc> for KliveConfig {
388    fn as_mut(&mut self) -> &mut ShellCoaxOutPairSrc {
389        &mut self.coax_out_src
390    }
391}
392
393impl AsRef<ShellStandaloneClockSource> for KliveConfig {
394    fn as_ref(&self) -> &ShellStandaloneClockSource {
395        &self.standalone_src
396    }
397}
398
399impl AsMut<ShellStandaloneClockSource> for KliveConfig {
400    fn as_mut(&mut self) -> &mut ShellStandaloneClockSource {
401        &mut self.standalone_src
402    }
403}
404
405impl AsRef<TcKonnektStandaloneClockRate> for KliveConfig {
406    fn as_ref(&self) -> &TcKonnektStandaloneClockRate {
407        &self.standalone_rate
408    }
409}
410
411impl AsMut<TcKonnektStandaloneClockRate> for KliveConfig {
412    fn as_mut(&mut self) -> &mut TcKonnektStandaloneClockRate {
413        &mut self.standalone_rate
414    }
415}
416
417impl AsRef<TcKonnektMidiSender> for KliveConfig {
418    fn as_ref(&self) -> &TcKonnektMidiSender {
419        &self.midi_sender
420    }
421}
422
423impl AsMut<TcKonnektMidiSender> for KliveConfig {
424    fn as_mut(&mut self) -> &mut TcKonnektMidiSender {
425        &mut self.midi_sender
426    }
427}
428
429impl AsRef<ShellMixerStreamSourcePair> for KliveConfig {
430    fn as_ref(&self) -> &ShellMixerStreamSourcePair {
431        &self.mixer_stream_src_pair
432    }
433}
434
435impl AsMut<ShellMixerStreamSourcePair> for KliveConfig {
436    fn as_mut(&mut self) -> &mut ShellMixerStreamSourcePair {
437        &mut self.mixer_stream_src_pair
438    }
439}
440
441/// The source of channel strip effect.
442#[derive(Debug, Copy, Clone, PartialEq, Eq)]
443pub enum ChStripSrc {
444    /// Stream input 1/2.
445    Stream01,
446    /// Analog input 1/2.
447    Analog01,
448    /// Analog input 3/4.
449    Analog23,
450    /// Digital input 1/2.
451    Digital01,
452    /// Digital input 3/4.
453    Digital23,
454    /// Digital input 5/6.
455    Digital45,
456    /// Digital input 7/8.
457    Digital67,
458    /// Mixer output 1/2.
459    MixerOutput,
460    /// Nothing.
461    None,
462}
463
464impl Default for ChStripSrc {
465    fn default() -> Self {
466        ChStripSrc::None
467    }
468}
469
470fn serialize_ch_strip_src(src: &ChStripSrc, raw: &mut [u8]) -> Result<(), String> {
471    assert!(raw.len() >= 4);
472
473    let val = match src {
474        ChStripSrc::Stream01 => 0,
475        ChStripSrc::Analog01 => 4,
476        ChStripSrc::Analog23 => 5,
477        ChStripSrc::Digital01 => 6,
478        ChStripSrc::Digital23 => 7,
479        ChStripSrc::Digital45 => 8,
480        ChStripSrc::Digital67 => 9,
481        ChStripSrc::MixerOutput => 10,
482        ChStripSrc::None => 11,
483    };
484
485    serialize_u32(&val, raw);
486
487    Ok(())
488}
489
490fn deserialize_ch_strip_src(src: &mut ChStripSrc, raw: &[u8]) -> Result<(), String> {
491    assert!(raw.len() >= 4);
492
493    let mut val = 0u32;
494    deserialize_u32(&mut val, raw);
495
496    *src = match val {
497        0 => ChStripSrc::Stream01,
498        4 => ChStripSrc::Analog01,
499        5 => ChStripSrc::Analog23,
500        6 => ChStripSrc::Digital01,
501        7 => ChStripSrc::Digital23,
502        8 => ChStripSrc::Digital45,
503        9 => ChStripSrc::Digital67,
504        10 => ChStripSrc::MixerOutput,
505        _ => ChStripSrc::None,
506    };
507
508    Ok(())
509}
510
511/// The type of channel strip effect.
512#[derive(Debug, Copy, Clone, PartialEq, Eq)]
513pub enum ChStripMode {
514    /// Fablik C.
515    FabrikC,
516    /// RIAA 1964.
517    RIAA1964,
518    /// RIAA 1987.
519    RIAA1987,
520}
521
522impl Default for ChStripMode {
523    fn default() -> Self {
524        ChStripMode::FabrikC
525    }
526}
527
528const CH_STRIP_MODES: &[ChStripMode] = &[
529    ChStripMode::FabrikC,
530    ChStripMode::RIAA1964,
531    ChStripMode::RIAA1987,
532];
533
534const CH_STRIP_MODE_LABEL: &str = "channel strip mode";
535
536fn serialize_ch_strip_mode(mode: &ChStripMode, raw: &mut [u8]) -> Result<(), String> {
537    serialize_position(CH_STRIP_MODES, mode, raw, CH_STRIP_MODE_LABEL)
538}
539
540fn deserialize_ch_strip_mode(mode: &mut ChStripMode, raw: &[u8]) -> Result<(), String> {
541    deserialize_position(CH_STRIP_MODES, mode, raw, CH_STRIP_MODE_LABEL)
542}
543
544/// State of mixer.
545#[derive(Debug, Clone, PartialEq, Eq)]
546pub struct KliveMixerState {
547    /// The common structure for state of mixer.
548    pub mixer: ShellMixerState,
549    /// The parameter of return from reverb effect.
550    pub reverb_return: ShellReverbReturn,
551    /// Whether to use channel strip effect as plugin. It results in output of channel strip effect
552    /// on tx stream.
553    pub use_ch_strip_as_plugin: bool,
554    /// The source of channel strip effect.
555    pub ch_strip_src: ChStripSrc,
556    /// The type of channel effect. Fabrik-C, RIAA-1964, and RIAA-1987.
557    pub ch_strip_mode: ChStripMode,
558    /// Whether to use channel strip effect at middle sampling rate (88.2/96.0 kHz).
559    pub use_reverb_at_mid_rate: bool,
560    /// Whether to use mixer function.
561    pub enabled: bool,
562}
563
564impl Default for KliveMixerState {
565    fn default() -> Self {
566        KliveMixerState {
567            mixer: KliveProtocol::create_mixer_state(),
568            reverb_return: Default::default(),
569            use_ch_strip_as_plugin: Default::default(),
570            ch_strip_src: Default::default(),
571            ch_strip_mode: Default::default(),
572            use_reverb_at_mid_rate: Default::default(),
573            enabled: Default::default(),
574        }
575    }
576}
577
578impl ShellMixerStateSpecification for KliveProtocol {
579    const MONITOR_SRC_MAP: [Option<ShellMixerMonitorSrcType>; SHELL_MIXER_MONITOR_SRC_COUNT] = [
580        Some(ShellMixerMonitorSrcType::Stream),
581        None,
582        None,
583        Some(ShellMixerMonitorSrcType::Spdif),
584        Some(ShellMixerMonitorSrcType::Analog),
585        Some(ShellMixerMonitorSrcType::Analog),
586        Some(ShellMixerMonitorSrcType::AdatSpdif),
587        Some(ShellMixerMonitorSrcType::Adat),
588        Some(ShellMixerMonitorSrcType::Adat),
589        Some(ShellMixerMonitorSrcType::Adat),
590    ];
591}
592
593impl TcKonnektSegmentSerdes<KliveMixerState> for KliveProtocol {
594    const NAME: &'static str = "mixer-state";
595    const OFFSET: usize = 0x0004;
596    const SIZE: usize = ShellMixerState::SIZE + 48;
597
598    fn serialize(params: &KliveMixerState, raw: &mut [u8]) -> Result<(), String> {
599        serialize_mixer_state::<KliveProtocol>(&params.mixer, raw)?;
600        serialize_reverb_return(&params.reverb_return, &mut raw[316..328])?;
601        serialize_bool(&params.use_ch_strip_as_plugin, &mut raw[328..332]);
602        serialize_ch_strip_src(&params.ch_strip_src, &mut raw[332..336])?;
603        serialize_ch_strip_mode(&params.ch_strip_mode, &mut raw[336..340])?;
604        serialize_bool(&params.use_reverb_at_mid_rate, &mut raw[340..344]);
605        serialize_bool(&params.enabled, &mut raw[344..348]);
606        Ok(())
607    }
608
609    fn deserialize(params: &mut KliveMixerState, raw: &[u8]) -> Result<(), String> {
610        deserialize_mixer_state::<KliveProtocol>(&mut params.mixer, raw)?;
611        deserialize_reverb_return(&mut params.reverb_return, &raw[316..328])?;
612        deserialize_bool(&mut params.use_ch_strip_as_plugin, &raw[328..332]);
613        deserialize_ch_strip_src(&mut params.ch_strip_src, &raw[332..336])?;
614        deserialize_ch_strip_mode(&mut params.ch_strip_mode, &raw[336..340])?;
615        deserialize_bool(&mut params.use_reverb_at_mid_rate, &raw[340..344]);
616        deserialize_bool(&mut params.enabled, &raw[344..348]);
617        Ok(())
618    }
619}
620
621impl TcKonnektMutableSegmentOperation<KliveMixerState> for KliveProtocol {}
622
623impl TcKonnektNotifiedSegmentOperation<KliveMixerState> for KliveProtocol {
624    const NOTIFY_FLAG: u32 = SHELL_MIXER_NOTIFY_FLAG;
625}
626
627impl AsRef<ShellMixerState> for KliveMixerState {
628    fn as_ref(&self) -> &ShellMixerState {
629        &self.mixer
630    }
631}
632
633impl AsMut<ShellMixerState> for KliveMixerState {
634    fn as_mut(&mut self) -> &mut ShellMixerState {
635        &mut self.mixer
636    }
637}
638
639impl AsRef<ShellReverbReturn> for KliveMixerState {
640    fn as_ref(&self) -> &ShellReverbReturn {
641        &self.reverb_return
642    }
643}
644
645impl AsMut<ShellReverbReturn> for KliveMixerState {
646    fn as_mut(&mut self) -> &mut ShellReverbReturn {
647        &mut self.reverb_return
648    }
649}
650
651/// Configuration for reverb effect.
652#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
653pub struct KliveReverbState(pub ReverbState);
654
655impl TcKonnektSegmentSerdes<KliveReverbState> for KliveProtocol {
656    const NAME: &'static str = "reverb-state";
657    const OFFSET: usize = 0x0218;
658    const SIZE: usize = ReverbState::SIZE;
659
660    fn serialize(params: &KliveReverbState, raw: &mut [u8]) -> Result<(), String> {
661        serialize_reverb_state(&params.0, raw)
662    }
663
664    fn deserialize(params: &mut KliveReverbState, raw: &[u8]) -> Result<(), String> {
665        deserialize_reverb_state(&mut params.0, raw)
666    }
667}
668
669impl TcKonnektMutableSegmentOperation<KliveReverbState> for KliveProtocol {}
670
671impl TcKonnektNotifiedSegmentOperation<KliveReverbState> for KliveProtocol {
672    const NOTIFY_FLAG: u32 = SHELL_REVERB_NOTIFY_FLAG;
673}
674
675impl AsRef<ReverbState> for KliveReverbState {
676    fn as_ref(&self) -> &ReverbState {
677        &self.0
678    }
679}
680
681impl AsMut<ReverbState> for KliveReverbState {
682    fn as_mut(&mut self) -> &mut ReverbState {
683        &mut self.0
684    }
685}
686
687/// Configuration for channel strip effect.
688#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
689pub struct KliveChStripStates(pub [ChStripState; SHELL_CH_STRIP_COUNT]);
690
691impl TcKonnektSegmentSerdes<KliveChStripStates> for KliveProtocol {
692    const NAME: &'static str = "channel-strip-state";
693    const OFFSET: usize = 0x0260;
694    const SIZE: usize = ChStripState::SIZE * SHELL_CH_STRIP_COUNT + 4;
695
696    fn serialize(params: &KliveChStripStates, raw: &mut [u8]) -> Result<(), String> {
697        serialize_ch_strip_states(&params.0, raw)
698    }
699
700    fn deserialize(params: &mut KliveChStripStates, raw: &[u8]) -> Result<(), String> {
701        deserialize_ch_strip_states(&mut params.0, raw)
702    }
703}
704
705impl TcKonnektMutableSegmentOperation<KliveChStripStates> for KliveProtocol {}
706
707impl TcKonnektNotifiedSegmentOperation<KliveChStripStates> for KliveProtocol {
708    const NOTIFY_FLAG: u32 = SHELL_CH_STRIP_NOTIFY_FLAG;
709}
710
711impl AsRef<[ChStripState]> for KliveChStripStates {
712    fn as_ref(&self) -> &[ChStripState] {
713        &self.0
714    }
715}
716
717impl AsMut<[ChStripState]> for KliveChStripStates {
718    fn as_mut(&mut self) -> &mut [ChStripState] {
719        &mut self.0
720    }
721}
722
723/// Hardware state.
724#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
725pub struct KliveHwState(pub ShellHwState);
726
727impl TcKonnektSegmentSerdes<KliveHwState> for KliveProtocol {
728    const NAME: &'static str = "hardware-state";
729    const OFFSET: usize = 0x1008;
730    const SIZE: usize = ShellHwState::SIZE;
731
732    fn serialize(params: &KliveHwState, raw: &mut [u8]) -> Result<(), String> {
733        serialize_hw_state(&params.0, raw)
734    }
735
736    fn deserialize(params: &mut KliveHwState, raw: &[u8]) -> Result<(), String> {
737        deserialize_hw_state(&mut params.0, raw)
738    }
739}
740
741impl TcKonnektMutableSegmentOperation<KliveHwState> for KliveProtocol {}
742
743impl TcKonnektNotifiedSegmentOperation<KliveHwState> for KliveProtocol {
744    const NOTIFY_FLAG: u32 = SHELL_HW_STATE_NOTIFY_FLAG;
745}
746
747impl AsRef<ShellHwState> for KliveHwState {
748    fn as_ref(&self) -> &ShellHwState {
749        &self.0
750    }
751}
752
753impl AsMut<ShellHwState> for KliveHwState {
754    fn as_mut(&mut self) -> &mut ShellHwState {
755        &mut self.0
756    }
757}
758
759impl AsRef<FireWireLedState> for KliveHwState {
760    fn as_ref(&self) -> &FireWireLedState {
761        &self.0.firewire_led
762    }
763}
764
765impl AsMut<FireWireLedState> for KliveHwState {
766    fn as_mut(&mut self) -> &mut FireWireLedState {
767        &mut self.0.firewire_led
768    }
769}
770
771const KLIVE_METER_ANALOG_INPUT_COUNT: usize = 4;
772const KLIVE_METER_DIGITAL_INPUT_COUNT: usize = 8;
773
774/// Hardware metering for mixer function.
775#[derive(Debug, Clone, PartialEq, Eq)]
776pub struct KliveMixerMeter(pub ShellMixerMeter);
777
778impl Default for KliveMixerMeter {
779    fn default() -> Self {
780        KliveMixerMeter(KliveProtocol::create_meter_state())
781    }
782}
783
784impl ShellMixerMeterSpecification for KliveProtocol {
785    const ANALOG_INPUT_COUNT: usize = KLIVE_METER_ANALOG_INPUT_COUNT;
786    const DIGITAL_INPUT_COUNT: usize = KLIVE_METER_DIGITAL_INPUT_COUNT;
787}
788
789impl TcKonnektSegmentSerdes<KliveMixerMeter> for KliveProtocol {
790    const NAME: &'static str = "mixer-meter";
791    const OFFSET: usize = 0x1068;
792    const SIZE: usize = ShellMixerMeter::SIZE;
793
794    fn serialize(params: &KliveMixerMeter, raw: &mut [u8]) -> Result<(), String> {
795        serialize_mixer_meter::<KliveProtocol>(&params.0, raw)
796    }
797
798    fn deserialize(params: &mut KliveMixerMeter, raw: &[u8]) -> Result<(), String> {
799        deserialize_mixer_meter::<KliveProtocol>(&mut params.0, raw)
800    }
801}
802
803impl AsRef<ShellMixerMeter> for KliveMixerMeter {
804    fn as_ref(&self) -> &ShellMixerMeter {
805        &self.0
806    }
807}
808
809impl AsMut<ShellMixerMeter> for KliveMixerMeter {
810    fn as_mut(&mut self) -> &mut ShellMixerMeter {
811        &mut self.0
812    }
813}
814
815/// Hardware metering for reverb effect.
816#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
817pub struct KliveReverbMeter(pub ReverbMeter);
818
819impl TcKonnektSegmentSerdes<KliveReverbMeter> for KliveProtocol {
820    const NAME: &'static str = "reverb-meter";
821    const OFFSET: usize = 0x10c4;
822    const SIZE: usize = ReverbMeter::SIZE;
823
824    fn serialize(params: &KliveReverbMeter, raw: &mut [u8]) -> Result<(), String> {
825        serialize_reverb_meter(&params.0, raw)
826    }
827
828    fn deserialize(params: &mut KliveReverbMeter, raw: &[u8]) -> Result<(), String> {
829        deserialize_reverb_meter(&mut params.0, raw)
830    }
831}
832
833impl AsRef<ReverbMeter> for KliveReverbMeter {
834    fn as_ref(&self) -> &ReverbMeter {
835        &self.0
836    }
837}
838
839impl AsMut<ReverbMeter> for KliveReverbMeter {
840    fn as_mut(&mut self) -> &mut ReverbMeter {
841        &mut self.0
842    }
843}
844
845/// Hardware metering for channel strip effect.
846#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
847pub struct KliveChStripMeters(pub [ChStripMeter; SHELL_CH_STRIP_COUNT]);
848
849impl TcKonnektSegmentSerdes<KliveChStripMeters> for KliveProtocol {
850    const NAME: &'static str = "channel-strip-meter";
851    const OFFSET: usize = 0x10dc;
852    const SIZE: usize = ChStripMeter::SIZE * SHELL_CH_STRIP_COUNT + 4;
853
854    fn serialize(params: &KliveChStripMeters, raw: &mut [u8]) -> Result<(), String> {
855        serialize_ch_strip_meters(&params.0, raw)
856    }
857
858    fn deserialize(params: &mut KliveChStripMeters, raw: &[u8]) -> Result<(), String> {
859        deserialize_ch_strip_meters(&mut params.0, raw)
860    }
861}
862
863impl AsRef<[ChStripMeter]> for KliveChStripMeters {
864    fn as_ref(&self) -> &[ChStripMeter] {
865        &self.0
866    }
867}
868
869impl AsMut<[ChStripMeter]> for KliveChStripMeters {
870    fn as_mut(&mut self) -> &mut [ChStripMeter] {
871        &mut self.0
872    }
873}
874
875/// Impedance of output.
876#[derive(Debug, Copy, Clone, PartialEq, Eq)]
877pub enum OutputImpedance {
878    /// Unbalance.
879    Unbalance,
880    /// Balance.
881    Balance,
882}
883
884impl Default for OutputImpedance {
885    fn default() -> Self {
886        Self::Unbalance
887    }
888}
889
890const OUTPUT_IMPEDANCES: &[OutputImpedance] =
891    &[OutputImpedance::Unbalance, OutputImpedance::Balance];
892
893const OUTPUT_IMPEDANCE_LABEL: &str = "output impedance";
894
895fn serialize_output_impedance(impedance: &OutputImpedance, raw: &mut [u8]) -> Result<(), String> {
896    serialize_position(OUTPUT_IMPEDANCES, impedance, raw, OUTPUT_IMPEDANCE_LABEL)
897}
898
899fn deserialize_output_impedance(impedance: &mut OutputImpedance, raw: &[u8]) -> Result<(), String> {
900    deserialize_position(OUTPUT_IMPEDANCES, impedance, raw, OUTPUT_IMPEDANCE_LABEL)
901}