Merge pull request #76 from tomaka/alsa-fixes

Various ALSA fixes
This commit is contained in:
tomaka 2015-09-22 15:51:37 +02:00
commit 4e6ecb7f25
3 changed files with 38 additions and 12 deletions

View File

@ -9,7 +9,11 @@ fn main() {
for (endpoint_index, endpoint) in endpoints.enumerate() { for (endpoint_index, endpoint) in endpoints.enumerate() {
println!("{}. Endpoint \"{}\" Audio formats: ", endpoint_index + 1, endpoint.get_name()); 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() { for (format_index, format) in formats.enumerate() {
println!("{}.{}. {:?}", endpoint_index + 1, format_index + 1, format); println!("{}.{}. {:?}", endpoint_index + 1, format_index + 1, format);
} }

View File

@ -3,6 +3,7 @@ use super::check_errors;
use super::Endpoint; use super::Endpoint;
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::CString;
use std::mem; use std::mem;
use libc; use libc;
@ -91,6 +92,18 @@ impl Iterator for EndpointsIterator {
} }
if let Some(name) = name { 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" { if name != "null" {
return Some(Endpoint(name)); return Some(Endpoint(name));
} }
@ -102,6 +115,5 @@ impl Iterator for EndpointsIterator {
#[inline] #[inline]
pub fn get_default_endpoint() -> Option<Endpoint> { pub fn get_default_endpoint() -> Option<Endpoint> {
// TODO: do in a different way?
Some(Endpoint("default".to_owned())) Some(Endpoint("default".to_owned()))
} }

View File

@ -10,7 +10,7 @@ use FormatsEnumerationError;
use SampleFormat; use SampleFormat;
use SamplesRate; use SamplesRate;
use std::{ffi, iter, mem, ptr}; use std::{ffi, cmp, iter, mem, ptr};
use std::vec::IntoIter as VecIntoIter; use std::vec::IntoIter as VecIntoIter;
use std::sync::Mutex; use std::sync::Mutex;
@ -28,12 +28,19 @@ impl Endpoint {
unsafe { unsafe {
let mut playback_handle = mem::uninitialized(); let mut playback_handle = mem::uninitialized();
let device_name = ffi::CString::new(self.0.clone()).unwrap(); 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, match alsa::snd_pcm_open(&mut playback_handle, device_name.as_ptr() as *const _,
alsa::SND_PCM_NONBLOCK)).unwrap(); 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(); 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 // TODO: check endianess
const FORMATS: [(SampleFormat, alsa::snd_pcm_format_t); 3] = [ 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(); check_errors(alsa::snd_pcm_hw_params_get_channels_min(hw_params.0, &mut min_channels)).unwrap();
let mut max_channels = mem::uninitialized(); let mut max_channels = mem::uninitialized();
check_errors(alsa::snd_pcm_hw_params_get_channels_max(hw_params.0, &mut max_channels)).unwrap(); 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| { 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 { 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::<Vec<_>>()) // FIXME: Some(iter::repeat(ChannelPosition::FrontLeft).take(num as usize).collect::<Vec<_>>()) // FIXME:
@ -158,7 +166,7 @@ impl Endpoint {
#[inline] #[inline]
pub fn get_name(&self) -> String { 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 name = ffi::CString::new(endpoint.0.clone()).unwrap();
let mut playback_handle = mem::uninitialized(); let mut playback_handle = mem::uninitialized();
check_errors(alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(), match alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(),
alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK)
alsa::SND_PCM_NONBLOCK)).unwrap(); {
-16 /* determined empirically */ => return Err(CreationError::DeviceNotAvailable),
e => check_errors(e).unwrap()
}
// TODO: check endianess // TODO: check endianess
let data_type = match format.data_type { 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_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_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_hw_params(playback_handle, hw_params.0)).unwrap();
check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap(); check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap();