use super::_raw;
use crate::{AlsaError, AlsaPcmHandle, AudioDevice, AudioDeviceDir, AudioStreamDir};
#[cfg(ffi_alsa··)]
use crate::{AlsaHintList, AlsaHintValue};
#[cfg(all(ffi_alsa··, feature = "alloc"))]
use crate::{AudioDeviceCow, Cow, ToString, Vec};
use crate::{CStr, Ptr};
#[doc = crate::_tags!(audio linux namespace)]
#[doc = crate::_doc_meta!{location("sys/device/audio")}]
#[derive(Debug)]
pub struct Alsa;
impl Alsa {
pub const fn is_available() -> bool {
cfg!(ffi_alsa··)
}
}
#[cfg(ffi_alsa··)]
impl Alsa {
pub fn open_pcm(id: &CStr, dir: AudioStreamDir) -> Result<AlsaPcmHandle, AlsaError> {
unsafe {
let mut handle = Ptr::null_mut();
AlsaError::result(_raw::snd_pcm_open(&mut handle, id.as_ptr(), dir.to_alsa() as _, 0))?;
Ok(AlsaPcmHandle::from_raw(handle))
}
}
pub fn open_default_playback() -> Result<AlsaPcmHandle, AlsaError> {
Self::open_pcm(c"default", AudioStreamDir::Playback)
}
pub fn open_default_capture() -> Result<AlsaPcmHandle, AlsaError> {
Self::open_pcm(c"default", AudioStreamDir::Capture)
}
#[cfg(feature = "alloc")]
pub fn pcm_devices() -> Result<Vec<AudioDeviceCow<'static>>, AlsaError> {
let mut out = Vec::new();
Self::for_each_pcm_device(|dev| {
out.push(AudioDeviceCow {
id: Cow::Owned(dev.id.to_string()),
name: dev.name.map(|s| Cow::Owned(s.to_string())),
desc: dev.desc.map(|s| Cow::Owned(s.to_string())),
dir: dev.dir,
});
Ok(())
})?;
Ok(out)
}
pub fn for_each_pcm_device(
mut f: impl FnMut(AudioDevice<'_>) -> Result<(), AlsaError>,
) -> Result<(), AlsaError> {
unsafe {
let mut hints = Ptr::null_mut();
AlsaError::result(_raw::snd_device_name_hint(-1, c"pcm".as_ptr(), &mut hints))?;
let hints = AlsaHintList { raw: hints };
let mut p = hints.raw;
while !p.is_null() && !(*p).is_null() {
let hint = *p;
let name = AlsaHintValue::get(hint, c"NAME");
let desc = AlsaHintValue::get(hint, c"DESC");
let ioid = AlsaHintValue::get(hint, c"IOID");
if let Some(id) = name.as_str() {
f(AudioDevice {
id,
name: None,
desc: desc.as_str(),
dir: AudioDeviceDir::from_alsa_ioid(ioid.as_cstr()),
})?;
}
p = p.add(1);
}
Ok(())
}
}
}