summaryrefslogtreecommitdiff
path: root/cros_alsa/src/card.rs
blob: 42beef2cfd4111d553f94eb02d80e613a9c3ee4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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)?)
    }
}