blob: 42beef2cfd4111d553f94eb02d80e613a9c3ee4a [file] [log] [blame]
// 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.
use std::error;
use std::fmt;
use remain::sorted;
use crate::control::{self, Control};
use crate::control_primitive;
use crate::control_primitive::{Ctl, ElemId, ElemIface};
use crate::control_tlv::{self, ControlTLV};
pub type Result<T> = std::result::Result<T, Error>;
#[sorted]
#[derive(Debug)]
/// Possible errors that can occur in cros-alsa::card.
pub enum Error {
/// Failed to call AlsaControlAPI.
AlsaControlAPI(control_primitive::Error),
/// Error occurs in Control.
Control(control::Error),
/// Error occurs in ControlTLV.
ControlTLV(control_tlv::Error),
}
impl error::Error for Error {}
impl From<control::Error> for Error {
fn from(err: control::Error) -> Error {
Error::Control(err)
}
}
impl From<control_tlv::Error> for Error {
fn from(err: control_tlv::Error) -> Error {
Error::ControlTLV(err)
}
}
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),
Control(e) => write!(f, "{}", e),
ControlTLV(e) => write!(f, "{}", e),
}
}
}
/// `Card` represents a sound card.
#[derive(Debug)]
pub struct Card {
handle: Ctl,
name: String,
}
impl Card {
/// Creates a `Card`.
///
/// # Arguments
///
/// * `card_name` - The sound card name, ex: sofcmlmax98390d.
///
/// # Errors
///
/// * If card_name is an invalid CString.
/// * If snd_ctl_open() fails.
pub fn new(card_name: &str) -> Result<Self> {
let handle = Ctl::new(&format!("hw:{}", card_name))?;
Ok(Card {
name: card_name.to_owned(),
handle,
})
}
/// Gets sound card name.
pub fn name(&self) -> &str {
&self.name
}
/// Creates a `Control` from control name.
///
/// # Errors
///
/// * If control name is an invalid CString.
/// * If control does not exist.
/// * If `Control` elem_type() mismatches the type of underlying mixer control.
/// * If `Control` size() mismatches the number of value entries of underlying mixer control.
pub fn control_by_name<'a, T: 'a>(&'a mut self, control_name: &str) -> Result<T>
where
T: Control<'a>,
{
let id = ElemId::new(ElemIface::Mixer, control_name)?;
Ok(T::from(&mut self.handle, id)?)
}
/// Creates a `ControlTLV` from control name.
///
/// # Errors
///
/// * If control name is an invalid CString.
/// * If control does not exist.
pub fn control_tlv_by_name<'a>(&'a mut self, control_name: &str) -> Result<ControlTLV<'a>> {
let id = ElemId::new(ElemIface::Mixer, control_name)?;
Ok(ControlTLV::new(&mut self.handle, id)?)
}
}