firewire_fireworks_protocols/
playback.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Protocol about stream playback.
5//!
6//! The module includes protocol about stream playback defined by Echo Audio Digital Corporation for
7//! Fireworks board module.
8
9use super::*;
10
11const CATEGORY_PLAYBACK: u32 = 6;
12
13const CMD_SET_VOL: u32 = 0;
14const CMD_GET_VOL: u32 = 1;
15const CMD_SET_MUTE: u32 = 2;
16const CMD_GET_MUTE: u32 = 3;
17const CMD_SET_SOLO: u32 = 4;
18const CMD_GET_SOLO: u32 = 5;
19
20/// The parameters of playback.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct EfwPlaybackParameters {
23    /// The volume of playback. The value is unsigned fixed-point number of 8.24 format; i.e. Q24.
24    /// It is between 0x00000000..0x02000000 for -144.0..+6.0 dB.
25    pub volumes: Vec<i32>,
26    /// Whether to mute the playback.
27    pub mutes: Vec<bool>,
28}
29
30impl<O, P> EfwWhollyCachableParamsOperation<P, EfwPlaybackParameters> for O
31where
32    O: EfwHardwareSpecification,
33    P: EfwProtocolExtManual,
34{
35    fn cache_wholly(
36        proto: &mut P,
37        states: &mut EfwPlaybackParameters,
38        timeout_ms: u32,
39    ) -> Result<(), Error> {
40        assert_eq!(states.volumes.len(), Self::RX_CHANNEL_COUNTS[0]);
41        assert_eq!(states.mutes.len(), Self::RX_CHANNEL_COUNTS[0]);
42
43        states
44            .volumes
45            .iter_mut()
46            .enumerate()
47            .try_for_each(|(ch, vol)| {
48                let args = [ch as u32, 0];
49                let mut resps = vec![0; 2];
50                proto
51                    .transaction(
52                        CATEGORY_PLAYBACK,
53                        CMD_GET_VOL,
54                        &args,
55                        &mut resps,
56                        timeout_ms,
57                    )
58                    .map(|_| *vol = resps[1] as i32)
59            })?;
60
61        states
62            .mutes
63            .iter_mut()
64            .enumerate()
65            .try_for_each(|(ch, mute)| {
66                let args = [ch as u32, 0];
67                let mut resps = vec![0; 2];
68                proto
69                    .transaction(
70                        CATEGORY_PLAYBACK,
71                        CMD_GET_MUTE,
72                        &args,
73                        &mut resps,
74                        timeout_ms,
75                    )
76                    .map(|_| *mute = resps[1] > 0)
77            })?;
78
79        Ok(())
80    }
81}
82
83impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwPlaybackParameters> for O
84where
85    O: EfwHardwareSpecification,
86    P: EfwProtocolExtManual,
87{
88    fn update_partially(
89        proto: &mut P,
90        states: &mut EfwPlaybackParameters,
91        updates: EfwPlaybackParameters,
92        timeout_ms: u32,
93    ) -> Result<(), Error> {
94        assert_eq!(states.volumes.len(), Self::RX_CHANNEL_COUNTS[0]);
95        assert_eq!(states.mutes.len(), Self::RX_CHANNEL_COUNTS[0]);
96        assert_eq!(updates.volumes.len(), Self::RX_CHANNEL_COUNTS[0]);
97        assert_eq!(updates.mutes.len(), Self::RX_CHANNEL_COUNTS[0]);
98
99        states
100            .volumes
101            .iter_mut()
102            .zip(updates.volumes.iter())
103            .enumerate()
104            .filter(|(_, (o, n))| !o.eq(n))
105            .try_for_each(|(ch, (curr, &vol))| {
106                let args = [ch as u32, vol as u32];
107                let mut params = vec![0; 2];
108                proto
109                    .transaction(
110                        CATEGORY_PLAYBACK,
111                        CMD_SET_VOL,
112                        &args,
113                        &mut params,
114                        timeout_ms,
115                    )
116                    .map(|_| *curr = vol)
117            })?;
118
119        states
120            .mutes
121            .iter_mut()
122            .zip(updates.mutes.iter())
123            .enumerate()
124            .filter(|(_, (o, n))| !o.eq(n))
125            .try_for_each(|(ch, (curr, &mute))| {
126                let args = [ch as u32, mute as u32];
127                let mut params = vec![0; 2];
128                proto
129                    .transaction(
130                        CATEGORY_PLAYBACK,
131                        CMD_SET_MUTE,
132                        &args,
133                        &mut params,
134                        timeout_ms,
135                    )
136                    .map(|_| *curr = mute)
137            })?;
138
139        Ok(())
140    }
141}
142
143/// The parameters of playback.
144#[derive(Debug, Clone, PartialEq, Eq)]
145pub struct EfwPlaybackSoloParameters {
146    /// Whether to mute the other channels.
147    pub solos: Vec<bool>,
148}
149
150/// The specification for solo of playback.
151pub trait EfwPlaybackSoloSpecification: EfwHardwareSpecification {
152    fn create_playback_solo_parameters() -> EfwPlaybackSoloParameters {
153        EfwPlaybackSoloParameters {
154            solos: vec![Default::default(); Self::RX_CHANNEL_COUNTS[0]],
155        }
156    }
157}
158
159impl<O, P> EfwWhollyCachableParamsOperation<P, EfwPlaybackSoloParameters> for O
160where
161    O: EfwPlaybackSoloSpecification,
162    P: EfwProtocolExtManual,
163{
164    fn cache_wholly(
165        proto: &mut P,
166        states: &mut EfwPlaybackSoloParameters,
167        timeout_ms: u32,
168    ) -> Result<(), Error> {
169        assert_eq!(states.solos.len(), Self::RX_CHANNEL_COUNTS[0]);
170
171        states
172            .solos
173            .iter_mut()
174            .enumerate()
175            .try_for_each(|(ch, solo)| {
176                let args = [ch as u32, 0];
177                let mut resps = vec![0; 2];
178                proto
179                    .transaction(
180                        CATEGORY_PLAYBACK,
181                        CMD_GET_SOLO,
182                        &args,
183                        &mut resps,
184                        timeout_ms,
185                    )
186                    .map(|_| *solo = resps[1] > 0)
187            })?;
188
189        Ok(())
190    }
191}
192
193impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwPlaybackSoloParameters> for O
194where
195    O: EfwPlaybackSoloSpecification,
196    P: EfwProtocolExtManual,
197{
198    fn update_partially(
199        proto: &mut P,
200        states: &mut EfwPlaybackSoloParameters,
201        updates: EfwPlaybackSoloParameters,
202        timeout_ms: u32,
203    ) -> Result<(), Error> {
204        assert_eq!(states.solos.len(), Self::RX_CHANNEL_COUNTS[0]);
205        assert_eq!(updates.solos.len(), Self::RX_CHANNEL_COUNTS[0]);
206
207        states
208            .solos
209            .iter_mut()
210            .zip(updates.solos.iter())
211            .enumerate()
212            .filter(|(_, (o, n))| !o.eq(n))
213            .try_for_each(|(ch, (curr, &solo))| {
214                let args = [ch as u32, solo as u32];
215                let mut params = vec![0; 2];
216                proto
217                    .transaction(
218                        CATEGORY_PLAYBACK,
219                        CMD_SET_SOLO,
220                        &args,
221                        &mut params,
222                        timeout_ms,
223                    )
224                    .map(|_| *curr = solo)
225            })?;
226
227        Ok(())
228    }
229}