commit
4e6ecb7f25
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -218,7 +229,6 @@ impl Voice {
|
||||||
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();
|
||||||
|
|
||||||
Ok(Voice {
|
Ok(Voice {
|
||||||
|
|
Loading…
Reference in New Issue