Skip to content

Commit 5386746

Browse files
authored
Merge pull request #130 from RavuAlHemio/elem_list
Add ElemList
2 parents 06d43d7 + e3438b8 commit 5386746

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

examples/ctl_list.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Example that enumerates controls for a device.
2+
3+
use alsa::Card;
4+
use alsa::card::Iter;
5+
use alsa::ctl::Ctl;
6+
use alsa::Error;
7+
8+
fn list_controls_for_card(card: &Card) -> Result<(), Error>{
9+
// Get a Ctl for the card
10+
let ctl_id = format!("hw:{}", card.get_index());
11+
let ctl = Ctl::new(&ctl_id, false)?;
12+
13+
println!("card {}", ctl_id);
14+
15+
// Query the elements
16+
let elems = ctl.elem_list()?;
17+
for list_index in 0..elems.get_used() {
18+
let numeric_id = elems.get_numid(list_index)?;
19+
let name = elems.get_name(list_index)?;
20+
println!(" {}: {}", numeric_id, name);
21+
}
22+
23+
Ok(())
24+
}
25+
26+
fn main() {
27+
let cards = Iter::new();
28+
cards.for_each(|card| if let Ok(c) = card { list_controls_for_card(&c).unwrap_or_default() });
29+
}

src/ctl_int.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ impl Ctl {
105105
acheck!(snd_ctl_elem_unlock(self.0, elem_id_ptr(id)))
106106
}
107107

108+
pub fn elem_list(&self) -> Result<ElemList> {
109+
// populate an empty list to get the number of elements
110+
let empty_list = elem_list_new(0)?;
111+
acheck!(snd_ctl_elem_list(self.0, empty_list.0))?;
112+
let required_elements = empty_list.get_count();
113+
114+
// obtain the list of all the elements now that we know how many there are
115+
let full_list = elem_list_new(required_elements)?;
116+
acheck!(snd_ctl_elem_list(self.0, full_list.0))?;
117+
Ok(full_list)
118+
}
119+
108120
/// Note: According to alsa-lib documentation, you're also supposed to have functionality for
109121
/// returning whether or not you are subscribed. This does not work in practice, so I'm not
110122
/// including that here.
@@ -448,6 +460,57 @@ impl fmt::Debug for ElemId {
448460
}
449461
}
450462

463+
/// [snd_ctl_elem_list_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper
464+
pub struct ElemList(*mut alsa::snd_ctl_elem_list_t);
465+
466+
impl Drop for ElemList {
467+
fn drop(&mut self) {
468+
unsafe { alsa::snd_ctl_elem_list_free_space(self.0) };
469+
unsafe { alsa::snd_ctl_elem_list_free(self.0) };
470+
}
471+
}
472+
473+
pub fn elem_list_new(count: u32) -> Result<ElemList> {
474+
let mut p = ptr::null_mut();
475+
let list = acheck!(snd_ctl_elem_list_malloc(&mut p)).map(|_| ElemList(p))?;
476+
if count > 0 {
477+
acheck!(snd_ctl_elem_list_alloc_space(list.0, count))?;
478+
}
479+
Ok(list)
480+
}
481+
482+
impl ElemList {
483+
#[inline]
484+
fn ensure_valid_index(&self, index: u32) -> Result<()> {
485+
if index >= self.get_used() {
486+
Err(Error::new("snd_ctl_elem_list_*", libc::EINVAL))
487+
} else {
488+
Ok(())
489+
}
490+
}
491+
492+
pub(crate) fn get_count(&self) -> u32 { unsafe { alsa::snd_ctl_elem_list_get_count(self.0) } }
493+
pub fn get_used(&self) -> u32 { unsafe { alsa::snd_ctl_elem_list_get_used(self.0) } }
494+
pub fn get_id(&self, index: u32) -> Result<ElemId> {
495+
self.ensure_valid_index(index)?;
496+
let elem_id = elem_id_new()?;
497+
unsafe { alsa::snd_ctl_elem_list_get_id(self.0, index, elem_id_ptr(&elem_id)) };
498+
Ok(elem_id)
499+
}
500+
pub fn get_numid(&self, index: u32) -> Result<u32> { self.ensure_valid_index(index)?; Ok(unsafe { alsa::snd_ctl_elem_list_get_numid(self.0, index) }) }
501+
pub fn get_interface(&self, index: u32) -> Result<ElemIface> {
502+
self.ensure_valid_index(index)?;
503+
ElemIface::from_c_int(unsafe { alsa::snd_ctl_elem_list_get_interface(self.0, index) } as c_int, "snd_ctl_elem_list_get_interface")
504+
}
505+
pub fn get_device(&self, index: u32) -> Result<u32> { self.ensure_valid_index(index)?; Ok(unsafe { alsa::snd_ctl_elem_list_get_device(self.0, index) }) }
506+
pub fn get_subdevice(&self, index: u32) -> Result<u32> { self.ensure_valid_index(index)?; Ok(unsafe { alsa::snd_ctl_elem_list_get_subdevice(self.0, index) }) }
507+
pub fn get_name(&self, index: u32) -> Result<&str> {
508+
self.ensure_valid_index(index)?;
509+
from_const("snd_ctl_elem_list_get_name", unsafe { alsa::snd_ctl_elem_list_get_name(self.0, index) })
510+
}
511+
pub fn get_index(&self, index: u32) -> Result<u32> { self.ensure_valid_index(index)?; Ok(unsafe { alsa::snd_ctl_elem_list_get_index(self.0, index) }) }
512+
}
513+
451514
/// [snd_ctl_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper
452515
pub struct Event(*mut alsa::snd_ctl_event_t);
453516

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub use crate::card::Card as Card;
9999
mod ctl_int;
100100
pub mod ctl {
101101
//! Control device API
102-
pub use super::ctl_int::{Ctl, CardInfo, DeviceIter, ElemIface, ElemId, ElemType, ElemValue, ElemInfo};
102+
pub use super::ctl_int::{Ctl, CardInfo, DeviceIter, ElemIface, ElemId, ElemList, ElemType, ElemValue, ElemInfo};
103103
}
104104

105105
pub use crate::ctl::Ctl as Ctl;

0 commit comments

Comments
 (0)