From 5fa41538a67c64f257e4b9d8079ed0a97aa2023d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 Sep 2015 15:46:56 +0200 Subject: [PATCH] Various ALSA fixes --- examples/enumerate.rs | 6 +++++- src/alsa/enumerate.rs | 14 +++++++++++++- src/alsa/mod.rs | 30 ++++++++++++++++++++---------- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/examples/enumerate.rs b/examples/enumerate.rs index 03a0244..570d380 100644 --- a/examples/enumerate.rs +++ b/examples/enumerate.rs @@ -9,7 +9,11 @@ fn main() { for (endpoint_index, endpoint) in endpoints.enumerate() { println!("{}. Endpoint \"{}\" Audio formats: ", endpoint_index + 1, endpoint.get_name()); - let formats = endpoint.get_supported_formats_list().unwrap(); + let formats = match endpoint.get_supported_formats_list() { + Ok(f) => f, + Err(e) => { println!("Error: {:?}", e); continue; } + }; + for (format_index, format) in formats.enumerate() { println!("{}.{}. {:?}", endpoint_index + 1, format_index + 1, format); } diff --git a/src/alsa/enumerate.rs b/src/alsa/enumerate.rs index 5ceaba6..18d64c4 100644 --- a/src/alsa/enumerate.rs +++ b/src/alsa/enumerate.rs @@ -3,6 +3,7 @@ use super::check_errors; use super::Endpoint; use std::ffi::CStr; +use std::ffi::CString; use std::mem; use libc; @@ -91,6 +92,18 @@ impl Iterator for EndpointsIterator { } if let Some(name) = name { + // trying to open the PCM device to see if it can be opened + let name_zeroed = CString::new(name.clone()).unwrap(); + let mut playback_handle = mem::uninitialized(); + if alsa::snd_pcm_open(&mut playback_handle, name_zeroed.as_ptr() as *const _, + alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK) == 0 + { + alsa::snd_pcm_close(playback_handle); + } else { + continue; + } + + // ignoring the `null` device if name != "null" { return Some(Endpoint(name)); } @@ -102,6 +115,5 @@ impl Iterator for EndpointsIterator { #[inline] pub fn get_default_endpoint() -> Option { - // TODO: do in a different way? Some(Endpoint("default".to_owned())) } diff --git a/src/alsa/mod.rs b/src/alsa/mod.rs index 5e72add..361a6de 100644 --- a/src/alsa/mod.rs +++ b/src/alsa/mod.rs @@ -10,7 +10,7 @@ use FormatsEnumerationError; use SampleFormat; use SamplesRate; -use std::{ffi, iter, mem, ptr}; +use std::{ffi, cmp, iter, mem, ptr}; use std::vec::IntoIter as VecIntoIter; use std::sync::Mutex; @@ -28,12 +28,19 @@ impl Endpoint { unsafe { let mut playback_handle = mem::uninitialized(); let device_name = ffi::CString::new(self.0.clone()).unwrap(); - check_errors(alsa::snd_pcm_open(&mut playback_handle, device_name.as_ptr() as *const _, - alsa::SND_PCM_STREAM_PLAYBACK, - alsa::SND_PCM_NONBLOCK)).unwrap(); + + match alsa::snd_pcm_open(&mut playback_handle, device_name.as_ptr() as *const _, + alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK) + { + -16 /* determined empirically */ => return Err(FormatsEnumerationError::DeviceNotAvailable), + e => check_errors(e).unwrap() + } let hw_params = HwParams::alloc(); - check_errors(alsa::snd_pcm_hw_params_any(playback_handle, hw_params.0)).unwrap(); + match check_errors(alsa::snd_pcm_hw_params_any(playback_handle, hw_params.0)) { + Err(_) => return Ok(Vec::new().into_iter()), + Ok(_) => () + }; // TODO: check endianess const FORMATS: [(SampleFormat, alsa::snd_pcm_format_t); 3] = [ @@ -128,6 +135,7 @@ impl Endpoint { check_errors(alsa::snd_pcm_hw_params_get_channels_min(hw_params.0, &mut min_channels)).unwrap(); let mut max_channels = mem::uninitialized(); check_errors(alsa::snd_pcm_hw_params_get_channels_max(hw_params.0, &mut max_channels)).unwrap(); + let max_channels = cmp::min(max_channels, 32); // TODO: limiting to 32 channels or too much stuff is returned let supported_channels = (min_channels .. max_channels + 1).filter_map(|num| { if alsa::snd_pcm_hw_params_test_channels(playback_handle, hw_params.0, num) == 0 { Some(iter::repeat(ChannelPosition::FrontLeft).take(num as usize).collect::>()) // FIXME: @@ -158,7 +166,7 @@ impl Endpoint { #[inline] pub fn get_name(&self) -> String { - "unknown".to_owned() // TODO: + self.0.clone() } } @@ -199,9 +207,12 @@ impl Voice { let name = ffi::CString::new(endpoint.0.clone()).unwrap(); let mut playback_handle = mem::uninitialized(); - check_errors(alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(), - alsa::SND_PCM_STREAM_PLAYBACK, - alsa::SND_PCM_NONBLOCK)).unwrap(); + match alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(), + alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK) + { + -16 /* determined empirically */ => return Err(CreationError::DeviceNotAvailable), + e => check_errors(e).unwrap() + } // TODO: check endianess let data_type = match format.data_type { @@ -217,7 +228,6 @@ impl Voice { check_errors(alsa::snd_pcm_hw_params_set_rate(playback_handle, hw_params.0, format.samples_rate.0 as libc::c_uint, 0)).unwrap(); check_errors(alsa::snd_pcm_hw_params_set_channels(playback_handle, hw_params.0, format.channels.len() as libc::c_uint)).unwrap(); check_errors(alsa::snd_pcm_hw_params(playback_handle, hw_params.0)).unwrap(); - check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap();