• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! `control` module is meant to provide easier to use and more type safe abstractions
6 //! for various alsa mixer controls.
7 //!
8 //! Each mixer control should implement the `Control` trait to allow itself to be created by `Card`.
9 //! Each mixer control could hold `Ctl` as handle and `ElemID` as id and use `#[derive(ControlOps)]` macro
10 //! to generate default load / save implementations of the `ControlOps` trait which allows itself to read and
11 //! write the underlying hardware.
12 //!
13 //! # Examples
14 //! This is an example of how to define a `SwitchControl`.
15 //!
16 //! ```
17 //! use std::error::Error;
18 //!
19 //! use cros_alsa::{Ctl, ElemId, Control, ControlError, ControlOps};
20 //! use cros_alsa::elem::Elem;
21 //!
22 //! type Result<T> = std::result::Result<T, ControlError>;
23 //!
24 //! #[derive(ControlOps)]
25 //! pub struct SwitchControl<'a> {
26 //!     // Must hold `Ctl` as handle and `ElemID` as id to use `#[derive(ControlOps)]`.
27 //!     handle: &'a mut Ctl,
28 //!     id: ElemId,
29 //! }
30 //!
31 //! impl<'a> Control<'a> for SwitchControl <'a> {
32 //!     type Item = [bool; 1];
33 //!
34 //!     fn new(handle: &'a mut Ctl, id: ElemId) -> Self {
35 //!         Self {
36 //!             handle,
37 //!             id,
38 //!         }
39 //!     }
40 //! }
41 //!
42 //! impl<'a> SwitchControl<'a> {
43 //!     /// Reads the state of a switch type mix control.
44 //!     pub fn state(&mut self) -> Result<bool> {
45 //!         // Uses ControlOps::load() to read the mixer control.
46 //!         let v = self.load()?;
47 //!         Ok(v[0])
48 //!     }
49 //!
50 //!     /// Updates the control state to true.
51 //!     pub fn on(&mut self) -> Result<()> {
52 //!         // Uses ControlOps::save() to write the mixer control.
53 //!         self.save([true])?;
54 //!         Ok(())
55 //!     }
56 //! }
57 //!
58 //! ```
59 
60 use std::error;
61 use std::fmt;
62 
63 use cros_alsa_derive::ControlOps;
64 use remain::sorted;
65 
66 use crate::control_primitive::{self, Ctl, ElemId, ElemInfo, ElemType};
67 use crate::elem::{self, Elem};
68 
69 /// The Result type of cros-alsa::control.
70 pub type Result<T> = std::result::Result<T, Error>;
71 
72 #[sorted]
73 #[derive(Debug)]
74 /// Possible errors that can occur in cros-alsa::control.
75 pub enum Error {
76     /// Failed to call AlsaControlAPI.
77     AlsaControlAPI(control_primitive::Error),
78     /// Error occurs in Elem.
79     Elem(elem::Error),
80     /// Elem::size() does not match the element count of the mixer control.
81     MismatchElemCount(String, usize, usize),
82     /// Elem::elem_type() does not match the data type of the mixer control.
83     MismatchElemType(String, ElemType, ElemType),
84 }
85 
86 impl error::Error for Error {}
87 
88 impl From<control_primitive::Error> for Error {
from(err: control_primitive::Error) -> Error89     fn from(err: control_primitive::Error) -> Error {
90         Error::AlsaControlAPI(err)
91     }
92 }
93 
94 impl From<elem::Error> for Error {
from(err: elem::Error) -> Error95     fn from(err: elem::Error) -> Error {
96         Error::Elem(err)
97     }
98 }
99 
100 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result101     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102         use Error::*;
103         match self {
104             AlsaControlAPI(e) => write!(f, "{}", e),
105             Elem(e) => write!(f, "{}", e),
106             MismatchElemCount(name, count, elem_count) => write!(
107                 f,
108                 "invalid `Control::size()` of {}: expect: {}, get: {}",
109                 name, count, elem_count
110             ),
111             MismatchElemType(name, t, elem_type) => write!(
112                 f,
113                 "invalid `Control::elem_type()` of {}: expect: {}, get: {}",
114                 name, t, elem_type
115             ),
116         }
117     }
118 }
119 
120 /// Each mixer control should implement the `Control` trait to allow itself to be created by `Card`.
121 pub trait Control<'a>: Sized + 'a {
122     /// The data type of the mixer control.
123     /// Use `ElemType::load()` and `ElemType::save()` to read or write the mixer control.
124     type Item: Elem;
125 
126     /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to create a `Control`.
new(handle: &'a mut Ctl, id: ElemId) -> Self127     fn new(handle: &'a mut Ctl, id: ElemId) -> Self;
128     /// Called by `Card` to create a `Control`.
from(handle: &'a mut Ctl, id: ElemId) -> Result<Self>129     fn from(handle: &'a mut Ctl, id: ElemId) -> Result<Self> {
130         let info = ElemInfo::new(handle, &id)?;
131         if info.elem_type()? != Self::elem_type() {
132             return Err(Error::MismatchElemType(
133                 id.name()?.to_owned(),
134                 info.elem_type()?,
135                 Self::elem_type(),
136             ));
137         }
138 
139         if info.count() != Self::size() {
140             return Err(Error::MismatchElemCount(
141                 id.name()?.to_owned(),
142                 info.count(),
143                 Self::size(),
144             ));
145         }
146 
147         Ok(Self::new(handle, id))
148     }
149     /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to validate the data type of a
150     /// `Control`.
elem_type() -> ElemType151     fn elem_type() -> ElemType {
152         Self::Item::elem_type()
153     }
154     /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to validate the number of value
155     /// entries of a `Control`.
size() -> usize156     fn size() -> usize {
157         Self::Item::size()
158     }
159 }
160 
161 /// Each mixer control could implement the `ControlOps` trait to allow itself to read and
162 /// write the underlying hardware`. Users could hold `Ctl` and `ElemID` as `handle` and `id`
163 /// in their control structure and use `#[derive(ControlOps)]` macro to generate default
164 /// load / save implementations.
165 pub trait ControlOps<'a>: Control<'a> {
166     /// Reads the values of the mixer control.
load(&mut self) -> Result<<Self as Control<'a>>::Item>167     fn load(&mut self) -> Result<<Self as Control<'a>>::Item>;
168     /// Saves the values to the mixer control.
save(&mut self, val: <Self as Control<'a>>::Item) -> Result<bool>169     fn save(&mut self, val: <Self as Control<'a>>::Item) -> Result<bool>;
170 }
171 
172 /// `Control` that reads and writes a single integer value entry.
173 /// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa`
174 /// path to `crate` in derive macros by `cros_alsa` attribute.
175 #[derive(ControlOps)]
176 #[cros_alsa(path = "crate")]
177 pub struct IntControl<'a> {
178     handle: &'a mut Ctl,
179     id: ElemId,
180 }
181 
182 impl<'a> IntControl<'a> {
183     /// Gets an i32 value from the mixer control.
184     ///
185     /// # Errors
186     ///
187     /// * If it fails to read from the control.
get(&mut self) -> Result<i32>188     pub fn get(&mut self) -> Result<i32> {
189         let val = self.load()?;
190         Ok(val[0])
191     }
192 
193     /// Updates an i32 value to the mixer control.
194     ///
195     /// # Errors
196     ///
197     /// * If it fails to write to the control.
set(&mut self, val: i32) -> Result<()>198     pub fn set(&mut self, val: i32) -> Result<()> {
199         self.save([val])?;
200         Ok(())
201     }
202 }
203 
204 impl<'a> Control<'a> for IntControl<'a> {
205     type Item = [i32; 1];
new(handle: &'a mut Ctl, id: ElemId) -> Self206     fn new(handle: &'a mut Ctl, id: ElemId) -> Self {
207         Self { handle, id }
208     }
209 }
210 
211 /// Stereo Volume Mixer Control
212 /// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa`
213 /// path to `crate` in derive macros by `cros_alsa` attribute.
214 #[derive(ControlOps)]
215 #[cros_alsa(path = "crate")]
216 pub struct StereoVolumeControl<'a> {
217     handle: &'a mut Ctl,
218     id: ElemId,
219 }
220 
221 impl<'a> StereoVolumeControl<'a> {
222     /// Reads the left and right volume.
223     ///
224     /// # Errors
225     ///
226     /// * If it fails to read from the control.
volume(&mut self) -> Result<(i32, i32)>227     pub fn volume(&mut self) -> Result<(i32, i32)> {
228         let val = self.load()?;
229         Ok((val[0], val[1]))
230     }
231 
232     /// Updates the left and right volume.
233     ///
234     /// # Errors
235     ///
236     /// * If it fails to write to the control.
set_volume(&mut self, left: i32, right: i32) -> Result<()>237     pub fn set_volume(&mut self, left: i32, right: i32) -> Result<()> {
238         self.save([left, right])?;
239         Ok(())
240     }
241 }
242 
243 impl<'a> Control<'a> for StereoVolumeControl<'a> {
244     type Item = [i32; 2];
new(handle: &'a mut Ctl, id: ElemId) -> Self245     fn new(handle: &'a mut Ctl, id: ElemId) -> Self {
246         Self { handle, id }
247     }
248 }
249 
250 /// `Control` that reads and writes a single boolean value entry.
251 /// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa`
252 /// path to `crate` in derive macros by `cros_alsa` attribute.
253 #[derive(ControlOps)]
254 #[cros_alsa(path = "crate")]
255 pub struct SwitchControl<'a> {
256     handle: &'a mut Ctl,
257     id: ElemId,
258 }
259 
260 impl<'a> SwitchControl<'a> {
261     /// Reads the state of a switch type mix control.
262     ///
263     /// # Errors
264     ///
265     /// * If it fails to read from the control.
state(&mut self) -> Result<bool>266     pub fn state(&mut self) -> Result<bool> {
267         let v = self.load()?;
268         Ok(v[0])
269     }
270 
271     /// Updates the control state to true.
272     ///
273     /// # Errors
274     ///
275     /// * If it fails to write to the control.
on(&mut self) -> Result<()>276     pub fn on(&mut self) -> Result<()> {
277         self.save([true])?;
278         Ok(())
279     }
280 
281     /// Updates the control state to false.
282     ///
283     /// # Errors
284     ///
285     /// * If it fails to write to the control.
off(&mut self) -> Result<()>286     pub fn off(&mut self) -> Result<()> {
287         self.save([false])?;
288         Ok(())
289     }
290 }
291 
292 impl<'a> Control<'a> for SwitchControl<'a> {
293     type Item = [bool; 1];
new(handle: &'a mut Ctl, id: ElemId) -> Self294     fn new(handle: &'a mut Ctl, id: ElemId) -> Self {
295         Self { handle, id }
296     }
297 }
298