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 use std::error; 6 use std::fmt; 7 8 use remain::sorted; 9 10 use crate::control::{self, Control}; 11 use crate::control_primitive; 12 use crate::control_primitive::{Ctl, ElemId, ElemIface}; 13 use crate::control_tlv::{self, ControlTLV}; 14 15 pub type Result<T> = std::result::Result<T, Error>; 16 17 #[sorted] 18 #[derive(Debug)] 19 /// Possible errors that can occur in cros-alsa::card. 20 pub enum Error { 21 /// Failed to call AlsaControlAPI. 22 AlsaControlAPI(control_primitive::Error), 23 /// Error occurs in Control. 24 Control(control::Error), 25 /// Error occurs in ControlTLV. 26 ControlTLV(control_tlv::Error), 27 } 28 29 impl error::Error for Error {} 30 31 impl From<control::Error> for Error { from(err: control::Error) -> Error32 fn from(err: control::Error) -> Error { 33 Error::Control(err) 34 } 35 } 36 37 impl From<control_tlv::Error> for Error { from(err: control_tlv::Error) -> Error38 fn from(err: control_tlv::Error) -> Error { 39 Error::ControlTLV(err) 40 } 41 } 42 43 impl From<control_primitive::Error> for Error { from(err: control_primitive::Error) -> Error44 fn from(err: control_primitive::Error) -> Error { 45 Error::AlsaControlAPI(err) 46 } 47 } 48 49 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 51 use Error::*; 52 match self { 53 AlsaControlAPI(e) => write!(f, "{}", e), 54 Control(e) => write!(f, "{}", e), 55 ControlTLV(e) => write!(f, "{}", e), 56 } 57 } 58 } 59 60 /// `Card` represents a sound card. 61 #[derive(Debug)] 62 pub struct Card { 63 handle: Ctl, 64 name: String, 65 } 66 67 impl Card { 68 /// Creates a `Card`. 69 /// 70 /// # Arguments 71 /// 72 /// * `card_name` - The sound card name, ex: sofcmlmax98390d. 73 /// 74 /// # Errors 75 /// 76 /// * If card_name is an invalid CString. 77 /// * If snd_ctl_open() fails. new(card_name: &str) -> Result<Self>78 pub fn new(card_name: &str) -> Result<Self> { 79 let handle = Ctl::new(&format!("hw:{}", card_name))?; 80 Ok(Card { 81 name: card_name.to_owned(), 82 handle, 83 }) 84 } 85 86 /// Gets sound card name. name(&self) -> &str87 pub fn name(&self) -> &str { 88 &self.name 89 } 90 91 /// Creates a `Control` from control name. 92 /// 93 /// # Errors 94 /// 95 /// * If control name is an invalid CString. 96 /// * If control does not exist. 97 /// * If `Control` elem_type() mismatches the type of underlying mixer control. 98 /// * If `Control` size() mismatches the number of value entries of underlying mixer control. control_by_name<'a, T: 'a>(&'a mut self, control_name: &str) -> Result<T> where T: Control<'a>,99 pub fn control_by_name<'a, T: 'a>(&'a mut self, control_name: &str) -> Result<T> 100 where 101 T: Control<'a>, 102 { 103 let id = ElemId::new(ElemIface::Mixer, control_name)?; 104 Ok(T::from(&mut self.handle, id)?) 105 } 106 107 /// Creates a `ControlTLV` from control name. 108 /// 109 /// # Errors 110 /// 111 /// * If control name is an invalid CString. 112 /// * If control does not exist. control_tlv_by_name<'a>(&'a mut self, control_name: &str) -> Result<ControlTLV<'a>>113 pub fn control_tlv_by_name<'a>(&'a mut self, control_name: &str) -> Result<ControlTLV<'a>> { 114 let id = ElemId::new(ElemIface::Mixer, control_name)?; 115 Ok(ControlTLV::new(&mut self.handle, id)?) 116 } 117 } 118