cpal/host/alsa/
enumerate.rs1use super::alsa;
2use super::{Device, DeviceHandles};
3use crate::{BackendSpecificError, DevicesError};
4use std::sync::{Arc, Mutex};
5
6pub struct Devices {
8 builtin_pos: usize,
9 card_iter: alsa::card::Iter,
10}
11
12impl Devices {
13 pub fn new() -> Result<Self, DevicesError> {
14 Ok(Devices {
15 builtin_pos: 0,
16 card_iter: alsa::card::Iter::new(),
17 })
18 }
19}
20
21unsafe impl Send for Devices {}
22unsafe impl Sync for Devices {}
23
24const BUILTINS: [&str; 5] = ["default", "pipewire", "pulse", "jack", "oss"];
25
26impl Iterator for Devices {
27 type Item = Device;
28
29 fn next(&mut self) -> Option<Device> {
30 while self.builtin_pos < BUILTINS.len() {
31 let pos = self.builtin_pos;
32 self.builtin_pos += 1;
33 let name = BUILTINS[pos];
34
35 if let Ok(handles) = DeviceHandles::open(name) {
36 return Some(Device {
37 name: name.to_string(),
38 pcm_id: name.to_string(),
39 handles: Arc::new(Mutex::new(handles)),
40 });
41 }
42 }
43
44 loop {
45 let res = self.card_iter.next()?;
46 let Ok(card) = res else { continue };
47
48 let ctl_id = format!("hw:{}", card.get_index());
49 let Ok(ctl) = alsa::Ctl::new(&ctl_id, false) else {
50 continue;
51 };
52 let Ok(cardinfo) = ctl.card_info() else {
53 continue;
54 };
55 let Ok(card_name) = cardinfo.get_name() else {
56 continue;
57 };
58
59 const USE_PLUGHW: bool = true;
68 let pcm_id = if USE_PLUGHW {
69 format!("plughw:{}", card.get_index())
70 } else {
71 ctl_id
72 };
73 if let Ok(handles) = DeviceHandles::open(&pcm_id) {
74 return Some(Device {
75 name: card_name.to_string(),
76 pcm_id: pcm_id.to_string(),
77 handles: Arc::new(Mutex::new(handles)),
78 });
79 }
80 }
81 }
82}
83
84#[inline]
85pub fn default_input_device() -> Option<Device> {
86 Some(Device {
87 name: "default".to_owned(),
88 pcm_id: "default".to_owned(),
89 handles: Arc::new(Mutex::new(Default::default())),
90 })
91}
92
93#[inline]
94pub fn default_output_device() -> Option<Device> {
95 Some(Device {
96 name: "default".to_owned(),
97 pcm_id: "default".to_owned(),
98 handles: Arc::new(Mutex::new(Default::default())),
99 })
100}
101
102impl From<alsa::Error> for DevicesError {
103 fn from(err: alsa::Error) -> Self {
104 let err: BackendSpecificError = err.into();
105 err.into()
106 }
107}