Make ALSA compile again
This commit is contained in:
parent
078769dbbd
commit
3db17889a4
|
@ -0,0 +1,78 @@
|
||||||
|
use super::alsa;
|
||||||
|
use super::check_errors;
|
||||||
|
use super::Endpoint;
|
||||||
|
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
/// ALSA implementation for `EndpointsIterator`.
|
||||||
|
pub struct EndpointsIterator {
|
||||||
|
// we keep the original list so that we can pass it to the free function
|
||||||
|
global_list: *const *const u8,
|
||||||
|
|
||||||
|
// pointer to the next string ; contained within `global_list`
|
||||||
|
next_str: *const *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for EndpointsIterator {}
|
||||||
|
unsafe impl Sync for EndpointsIterator {}
|
||||||
|
|
||||||
|
impl Drop for EndpointsIterator {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
alsa::snd_device_name_free_hint(self.global_list as *mut _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EndpointsIterator {
|
||||||
|
fn default() -> EndpointsIterator {
|
||||||
|
unsafe {
|
||||||
|
let mut hints = mem::uninitialized();
|
||||||
|
// TODO: check in which situation this can fail
|
||||||
|
check_errors(alsa::snd_device_name_hint(-1, b"pcm\0".as_ptr() as *const _,
|
||||||
|
&mut hints)).unwrap();
|
||||||
|
|
||||||
|
let hints = hints as *const *const u8;
|
||||||
|
|
||||||
|
EndpointsIterator {
|
||||||
|
global_list: hints,
|
||||||
|
next_str: hints,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for EndpointsIterator {
|
||||||
|
type Item = Endpoint;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Endpoint> {
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
if (*self.next_str).is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = alsa::snd_device_name_get_hint(*self.next_str as *const _,
|
||||||
|
b"NAME".as_ptr() as *const _);
|
||||||
|
self.next_str = self.next_str.offset(1);
|
||||||
|
|
||||||
|
if name.is_null() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = CStr::from_ptr(name).to_bytes().to_vec();
|
||||||
|
let name = String::from_utf8(name).unwrap();
|
||||||
|
|
||||||
|
if name != "null" {
|
||||||
|
return Some(Endpoint(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_default_endpoint() -> Option<Endpoint> {
|
||||||
|
// TODO: do in a different way?
|
||||||
|
Some(Endpoint("default".to_owned()))
|
||||||
|
}
|
|
@ -1,9 +1,39 @@
|
||||||
extern crate alsa_sys as alsa;
|
extern crate alsa_sys as alsa;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
|
pub use self::enumerate::{EndpointsIterator, get_default_endpoint};
|
||||||
|
|
||||||
|
use CreationError;
|
||||||
|
use Format;
|
||||||
|
use FormatsEnumerationError;
|
||||||
|
use SampleFormat;
|
||||||
|
use SamplesRate;
|
||||||
|
|
||||||
use std::{ffi, iter, mem};
|
use std::{ffi, iter, mem};
|
||||||
|
use std::option::IntoIter as OptionIntoIter;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
pub type SupportedFormatsIterator = OptionIntoIter<Format>;
|
||||||
|
|
||||||
|
mod enumerate;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Endpoint(String);
|
||||||
|
|
||||||
|
impl Endpoint {
|
||||||
|
pub fn get_supported_formats_list(&self)
|
||||||
|
-> Result<SupportedFormatsIterator, FormatsEnumerationError>
|
||||||
|
{
|
||||||
|
let format = Format {
|
||||||
|
channels: 2,
|
||||||
|
samples_rate: SamplesRate(44100),
|
||||||
|
data_type: SampleFormat::I16,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(format).into_iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Voice {
|
pub struct Voice {
|
||||||
channel: Mutex<*mut alsa::snd_pcm_t>,
|
channel: Mutex<*mut alsa::snd_pcm_t>,
|
||||||
num_channels: u16,
|
num_channels: u16,
|
||||||
|
@ -15,9 +45,9 @@ pub struct Buffer<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Voice {
|
impl Voice {
|
||||||
pub fn new() -> Voice {
|
pub fn new(endpoint: &Endpoint, _format: &Format) -> Result<Voice, CreationError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = ffi::CString::new(b"default".to_vec()).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(), alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK)).unwrap();
|
check_errors(alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(), alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK)).unwrap();
|
||||||
|
@ -34,10 +64,10 @@ impl Voice {
|
||||||
|
|
||||||
check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap();
|
check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap();
|
||||||
|
|
||||||
Voice {
|
Ok(Voice {
|
||||||
channel: Mutex::new(playback_handle),
|
channel: Mutex::new(playback_handle),
|
||||||
num_channels: 2,
|
num_channels: 2,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue