diff options
Diffstat (limited to 'cros_alsa/src/elem.rs')
-rw-r--r-- | cros_alsa/src/elem.rs | 204 |
1 files changed, 0 insertions, 204 deletions
diff --git a/cros_alsa/src/elem.rs b/cros_alsa/src/elem.rs deleted file mode 100644 index 08fe8b62..00000000 --- a/cros_alsa/src/elem.rs +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! This module provides different implementations of `Elem` that use the alsa-lib control interface -//! API to read and write alsa control elements. -//! -//! The `Elem::type()` returns the type of value that a control element can interact with, -//! and it is one of integer, integer64, boolean, enumerators, bytes or IEC958 structure. -//! The `Elem::size()` returns the number of values it reads from or writes to the hardware -//! at a time. -//! The `Elem::load(..)` and `Elem::save(..)` are used by `ControlOps` trait to read and write -//! the underlying mixer control. -//! -//! Users should use the provided implementations of `Elem` to define the associated type in -//! their owner encapsulation of `Control`. - -use std::default::Default; -use std::error; -use std::fmt; - -use libc::{c_long, c_uint}; -use remain::sorted; - -use crate::control_primitive::{self, snd_strerror, Ctl, ElemId, ElemType, ElemValue}; - -/// The Result type of cros-alsa::elem. -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug)] -/// Possible errors that can occur in cros-alsa::elem. -pub enum Error { - /// Failed to call AlsaControlAPI. - AlsaControlAPI(control_primitive::Error), - /// Failed to call `snd_ctl_elem_read()`. - ElemReadFailed(i32), - /// Failed to call `snd_ctl_elem_write()`. - ElemWriteFailed(i32), -} - -impl error::Error for Error {} - -impl From<control_primitive::Error> for Error { - fn from(err: control_primitive::Error) -> Error { - Error::AlsaControlAPI(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaControlAPI(e) => write!(f, "{}", e), - ElemReadFailed(e) => write!(f, "snd_ctl_elem_read failed: {}", snd_strerror(*e)?), - ElemWriteFailed(e) => write!(f, "snd_ctl_elem_write failed: {}", snd_strerror(*e)?), - } - } -} - -// Uses a recursive macro to generate implementation for [bool; n] and [i32; n], n = 1 to 128. -// The `$t:ident $($ts:ident)*` part matches and removes one token at a time. It's used for -// counting recursive steps. -macro_rules! impl_for_array { - {$n:expr, $type:ty, $t:ident $($ts:ident)*} => { - impl Elem for [$type; $n] { - type T = Self; - /// Reads [$type; $n] data from the mixer control. - /// - /// # Errors - /// - /// * If it fails to call `snd_ctl_elem_read()`. - fn load(handle: &mut Ctl, id: &ElemId) -> Result<Self::T> - { - let mut elem = ElemValue::new(id)?; - // Safe because self.handle.as_mut_ptr() is a valid *mut snd_ctl_t and - // elem.as_mut_ptr() is also a valid *mut snd_ctl_elem_value_t. - let rc = unsafe { alsa_sys::snd_ctl_elem_read(handle.as_mut_ptr(), elem.as_mut_ptr()) }; - if rc < 0 { - return Err(Error::ElemReadFailed(rc)); - } - let mut ret = [Default::default(); $n]; - for i in 0..$n { - // Safe because elem.as_ptr() is a valid snd_ctl_elem_value_t* and i is guaranteed to be - // within a valid range. - ret[i] = unsafe { <$type>::elem_value_get(&elem, i) }; - } - Ok(ret) - } - - /// Updates [$type; $n] data to the mixer control. - /// - /// # Results - /// - /// * `changed` - false on success. - /// - true on success when value was changed. - /// - /// # Errors - /// - /// * If it fails to call `snd_ctl_elem_write()`. - fn save(handle: &mut Ctl, id: &ElemId, val: Self::T) -> Result<bool> { - let mut elem = ElemValue::new(id)?; - for i in 0..$n { - // Safe because elem.as_mut_ptr() is a valid snd_ctl_elem_value_t* and i is guaranteed to be - // within a valid range. - unsafe { <$type>::elem_value_set(&mut elem, i, val[i]) }; - } - // Safe because self.handle.as_mut_ptr() is a valid *mut snd_ctl_t and - // elem.as_mut_ptr() is also a valid *mut snd_ctl_elem_value_t. - let rc = unsafe { alsa_sys::snd_ctl_elem_write(handle.as_mut_ptr(), elem.as_mut_ptr()) }; - if rc < 0 { - return Err(Error::ElemWriteFailed(rc)); - } - Ok(rc > 0) - } - - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType { - <$type>::elem_type() - } - - /// Gets the number of value entries itself can read and write. - fn size() -> usize { - $n - } - } - impl_for_array!{($n - 1), $type, $($ts)*} - }; - {$n:expr, $type:ty,} => {}; -} - -// Implements `Elem` for [i32; n] where n = 1 to 128. -impl_for_array! {128, i32, -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -} - -// Implements `Elem` for [bool; n] where n = 1 to 128. -impl_for_array! {128, bool, -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -} - -impl CtlElemValue for bool { - type T = bool; - /// Gets a bool from the ElemValue. - unsafe fn elem_value_get(elem: &ElemValue, idx: usize) -> bool { - alsa_sys::snd_ctl_elem_value_get_boolean(elem.as_ptr(), idx as c_uint) != 0 - } - /// Sets a bool to the ElemValue. - unsafe fn elem_value_set(elem: &mut ElemValue, idx: usize, val: bool) { - alsa_sys::snd_ctl_elem_value_set_boolean(elem.as_mut_ptr(), idx as c_uint, val as c_long); - } - /// Returns ElemType::Boolean. - fn elem_type() -> ElemType { - ElemType::Boolean - } -} - -impl CtlElemValue for i32 { - type T = i32; - /// Gets an i32 from the ElemValue. - unsafe fn elem_value_get(elem: &ElemValue, idx: usize) -> i32 { - alsa_sys::snd_ctl_elem_value_get_integer(elem.as_ptr(), idx as c_uint) as i32 - } - /// Sets an i32 to the ElemValue. - unsafe fn elem_value_set(elem: &mut ElemValue, idx: usize, val: i32) { - alsa_sys::snd_ctl_elem_value_set_integer(elem.as_mut_ptr(), idx as c_uint, val as c_long); - } - /// Returns ElemType::Integer. - fn elem_type() -> ElemType { - ElemType::Integer - } -} - -/// All primitive types of a control element should implement `CtlElemValue` trait. -trait CtlElemValue { - /// The primitive type of a control element. - type T; - /// Gets the value from the ElemValue. - unsafe fn elem_value_get(value: &ElemValue, idx: usize) -> Self::T; - /// Sets the value to the ElemValue. - unsafe fn elem_value_set(value: &mut ElemValue, id: usize, val: Self::T); - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType; -} - -/// Use `Elem` trait to access the underlying control element through the given `Ctl` and `ElemId`. -pub trait Elem: Sized { - /// The data type of a control element. - type T; - /// Reads the value from the mixer control. - fn load(handle: &mut Ctl, id: &ElemId) -> Result<Self::T>; - /// Saves the value to the mixer control. - fn save(handle: &mut Ctl, id: &ElemId, val: Self::T) -> Result<bool>; - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType; - /// Gets the number of value entries itself can read and write. - fn size() -> usize; -} |