firewire_fireworks_protocols/
phys_output.rs1use super::*;
10
11const CATEGORY_PHYS_OUTPUT: u32 = 4;
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_NOMINAL: u32 = 8;
18const CMD_GET_NOMINAL: u32 = 9;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct EfwOutputParameters {
23 pub volumes: Vec<i32>,
26 pub mutes: Vec<bool>,
28}
29
30impl<O, P> EfwWhollyCachableParamsOperation<P, EfwOutputParameters> for O
31where
32 O: EfwHardwareSpecification,
33 P: EfwProtocolExtManual,
34{
35 fn cache_wholly(
36 proto: &mut P,
37 states: &mut EfwOutputParameters,
38 timeout_ms: u32,
39 ) -> Result<(), Error> {
40 assert_eq!(states.volumes.len(), Self::phys_output_count());
41 assert_eq!(states.mutes.len(), Self::phys_output_count());
42
43 states
44 .volumes
45 .iter_mut()
46 .enumerate()
47 .try_for_each(|(ch, volume)| {
48 let args = [ch as u32, 0];
49 let mut params = vec![0; 2];
50 proto
51 .transaction(
52 CATEGORY_PHYS_OUTPUT,
53 CMD_GET_VOL,
54 &args,
55 &mut params,
56 timeout_ms,
57 )
58 .map(|_| *volume = params[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 params = vec![0; 2];
68 proto
69 .transaction(
70 CATEGORY_PHYS_OUTPUT,
71 CMD_GET_MUTE,
72 &args,
73 &mut params,
74 timeout_ms,
75 )
76 .map(|_| *mute = params[1] > 0)
77 })
78 }
79}
80
81impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwOutputParameters> for O
82where
83 O: EfwHardwareSpecification,
84 P: EfwProtocolExtManual,
85{
86 fn update_partially(
87 proto: &mut P,
88 states: &mut EfwOutputParameters,
89 updates: EfwOutputParameters,
90 timeout_ms: u32,
91 ) -> Result<(), Error> {
92 assert_eq!(states.volumes.len(), Self::phys_output_count());
93 assert_eq!(states.mutes.len(), Self::phys_output_count());
94
95 states
96 .volumes
97 .iter_mut()
98 .zip(updates.volumes.iter())
99 .enumerate()
100 .filter(|(_, (o, n))| !o.eq(n))
101 .try_for_each(|(ch, (curr, &vol))| {
102 let args = [ch as u32, vol as u32];
103 let mut params = vec![0; 2];
104 proto
105 .transaction(
106 CATEGORY_PHYS_OUTPUT,
107 CMD_SET_VOL,
108 &args,
109 &mut params,
110 timeout_ms,
111 )
112 .map(|_| *curr = vol)
113 })?;
114
115 states
116 .mutes
117 .iter_mut()
118 .zip(updates.mutes.iter())
119 .enumerate()
120 .filter(|(_, (o, n))| !o.eq(n))
121 .try_for_each(|(ch, (curr, &mute))| {
122 let args = [ch as u32, mute as u32];
123 let mut params = vec![0; 2];
124 proto
125 .transaction(
126 CATEGORY_PHYS_OUTPUT,
127 CMD_SET_MUTE,
128 &args,
129 &mut params,
130 timeout_ms,
131 )
132 .map(|_| *curr = mute)
133 })
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct EfwPhysOutputParameters {
140 pub nominals: Vec<NominalSignalLevel>,
142}
143
144pub trait EfwPhysOutputSpecification: EfwHardwareSpecification {
146 fn phys_analog_output_count() -> usize {
147 Self::PHYS_INPUT_GROUPS
148 .iter()
149 .filter(|(group_type, _)| PhysGroupType::Analog.eq(group_type))
150 .fold(0, |total, (_, count)| total + count)
151 }
152
153 fn create_phys_output_parameters() -> EfwPhysOutputParameters {
154 EfwPhysOutputParameters {
155 nominals: vec![Default::default(); Self::phys_analog_output_count()],
156 }
157 }
158}
159
160impl<O, P> EfwWhollyCachableParamsOperation<P, EfwPhysOutputParameters> for O
161where
162 O: EfwPhysOutputSpecification,
163 P: EfwProtocolExtManual,
164{
165 fn cache_wholly(
166 proto: &mut P,
167 states: &mut EfwPhysOutputParameters,
168 timeout_ms: u32,
169 ) -> Result<(), Error> {
170 assert_eq!(states.nominals.len(), Self::phys_analog_output_count());
171
172 states
173 .nominals
174 .iter_mut()
175 .enumerate()
176 .try_for_each(|(ch, level)| {
177 let args = [ch as u32, 0];
178 let mut params = vec![0; 2];
179 proto
180 .transaction(
181 CATEGORY_PHYS_OUTPUT,
182 CMD_GET_NOMINAL,
183 &args,
184 &mut params,
185 timeout_ms,
186 )
187 .map(|_| deserialize_nominal_signal_level(level, params[1]))
188 })
189 }
190}
191
192impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwPhysOutputParameters> for O
193where
194 O: EfwPhysOutputSpecification,
195 P: EfwProtocolExtManual,
196{
197 fn update_partially(
198 proto: &mut P,
199 states: &mut EfwPhysOutputParameters,
200 updates: EfwPhysOutputParameters,
201 timeout_ms: u32,
202 ) -> Result<(), Error> {
203 assert_eq!(states.nominals.len(), Self::phys_analog_output_count());
204 assert_eq!(updates.nominals.len(), Self::phys_analog_output_count());
205
206 states
207 .nominals
208 .iter_mut()
209 .zip(updates.nominals.iter())
210 .enumerate()
211 .filter(|(_, (o, n))| !o.eq(n))
212 .try_for_each(|(ch, (curr, &level))| {
213 let args = [ch as u32, serialize_nominal_signal_level(&level)];
214 let mut params = vec![0; 2];
215 proto
216 .transaction(
217 CATEGORY_PHYS_OUTPUT,
218 CMD_SET_NOMINAL,
219 &args,
220 &mut params,
221 timeout_ms,
222 )
223 .map(|_| *curr = level)
224 })
225 }
226}