2015-03-26 09:03:13 +00:00
extern crate alsa_sys as alsa ;
2014-12-16 15:45:45 +00:00
extern crate libc ;
2015-09-01 15:15:49 +00:00
pub use self ::enumerate ::{ EndpointsIterator , get_default_endpoint } ;
2015-09-10 10:43:37 +00:00
use ChannelPosition ;
2015-09-01 15:15:49 +00:00
use CreationError ;
use Format ;
use FormatsEnumerationError ;
use SampleFormat ;
use SamplesRate ;
2015-09-22 13:46:56 +00:00
use std ::{ ffi , cmp , iter , mem , ptr } ;
2015-09-10 17:48:39 +00:00
use std ::vec ::IntoIter as VecIntoIter ;
2015-06-24 13:17:52 +00:00
use std ::sync ::Mutex ;
2014-12-16 15:45:45 +00:00
2015-09-10 17:48:39 +00:00
pub type SupportedFormatsIterator = VecIntoIter < Format > ;
2015-09-01 15:15:49 +00:00
mod enumerate ;
#[ derive(Clone, Debug, PartialEq, Eq) ]
pub struct Endpoint ( String ) ;
impl Endpoint {
pub fn get_supported_formats_list ( & self )
-> Result < SupportedFormatsIterator , FormatsEnumerationError >
{
2015-09-10 17:48:39 +00:00
unsafe {
let mut playback_handle = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
let device_name = ffi ::CString ::new ( self . 0. clone ( ) ) . expect ( " Unable to get device name " ) ;
2015-09-22 13:46:56 +00:00
match alsa ::snd_pcm_open ( & mut playback_handle , device_name . as_ptr ( ) as * const _ ,
alsa ::SND_PCM_STREAM_PLAYBACK , alsa ::SND_PCM_NONBLOCK )
2016-01-28 20:27:09 +00:00
{
2015-10-13 10:22:07 +00:00
- 2 |
2015-09-22 13:46:56 +00:00
- 16 /* determined empirically */ = > return Err ( FormatsEnumerationError ::DeviceNotAvailable ) ,
2016-01-15 20:16:34 +00:00
e = > check_errors ( e ) . expect ( " device not available " )
2015-09-22 13:46:56 +00:00
}
2015-09-10 17:48:39 +00:00
let hw_params = HwParams ::alloc ( ) ;
2015-09-22 13:46:56 +00:00
match check_errors ( alsa ::snd_pcm_hw_params_any ( playback_handle , hw_params . 0 ) ) {
Err ( _ ) = > return Ok ( Vec ::new ( ) . into_iter ( ) ) ,
Ok ( _ ) = > ( )
} ;
2015-09-10 17:48:39 +00:00
2015-09-22 13:20:11 +00:00
// TODO: check endianess
2015-09-10 17:48:39 +00:00
const FORMATS : [ ( SampleFormat , alsa ::snd_pcm_format_t ) ; 3 ] = [
//SND_PCM_FORMAT_S8,
//SND_PCM_FORMAT_U8,
( SampleFormat ::I16 , alsa ::SND_PCM_FORMAT_S16_LE ) ,
//SND_PCM_FORMAT_S16_BE,
( SampleFormat ::U16 , alsa ::SND_PCM_FORMAT_U16_LE ) ,
//SND_PCM_FORMAT_U16_BE,
/* SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE ,
SND_PCM_FORMAT_U24_LE ,
SND_PCM_FORMAT_U24_BE ,
SND_PCM_FORMAT_S32_LE ,
SND_PCM_FORMAT_S32_BE ,
SND_PCM_FORMAT_U32_LE ,
SND_PCM_FORMAT_U32_BE , * /
( SampleFormat ::F32 , alsa ::SND_PCM_FORMAT_FLOAT_LE ) ,
/* SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_FLOAT64_LE ,
SND_PCM_FORMAT_FLOAT64_BE ,
SND_PCM_FORMAT_IEC958_SUBFRAME_LE ,
SND_PCM_FORMAT_IEC958_SUBFRAME_BE ,
SND_PCM_FORMAT_MU_LAW ,
SND_PCM_FORMAT_A_LAW ,
SND_PCM_FORMAT_IMA_ADPCM ,
SND_PCM_FORMAT_MPEG ,
SND_PCM_FORMAT_GSM ,
SND_PCM_FORMAT_SPECIAL ,
SND_PCM_FORMAT_S24_3LE ,
SND_PCM_FORMAT_S24_3BE ,
SND_PCM_FORMAT_U24_3LE ,
SND_PCM_FORMAT_U24_3BE ,
SND_PCM_FORMAT_S20_3LE ,
SND_PCM_FORMAT_S20_3BE ,
SND_PCM_FORMAT_U20_3LE ,
SND_PCM_FORMAT_U20_3BE ,
SND_PCM_FORMAT_S18_3LE ,
SND_PCM_FORMAT_S18_3BE ,
SND_PCM_FORMAT_U18_3LE ,
SND_PCM_FORMAT_U18_3BE , * /
] ;
let mut supported_formats = Vec ::new ( ) ;
for & ( sample_format , alsa_format ) in FORMATS . iter ( ) {
if alsa ::snd_pcm_hw_params_test_format ( playback_handle , hw_params . 0 , alsa_format ) = = 0 {
supported_formats . push ( sample_format ) ;
}
}
let mut min_rate = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_get_rate_min ( hw_params . 0 , & mut min_rate , ptr ::null_mut ( ) ) ) . expect ( " unable to get minimum supported rete " ) ;
2015-09-10 17:48:39 +00:00
let mut max_rate = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_get_rate_max ( hw_params . 0 , & mut max_rate , ptr ::null_mut ( ) ) ) . expect ( " unable to get maximum supported rate " ) ;
2015-09-10 17:48:39 +00:00
let samples_rates = if min_rate = = max_rate {
vec! [ min_rate ]
2015-09-22 13:12:41 +00:00
/* } else if alsa::snd_pcm_hw_params_test_rate(playback_handle, hw_params.0, min_rate + 1, 0) == 0 {
( min_rate .. max_rate + 1 ) . collect ( ) * / // TODO: code is correct but returns lots of stuff
2015-09-10 17:48:39 +00:00
} else {
const RATES : [ libc ::c_uint ; 13 ] = [
5512 ,
8000 ,
11025 ,
16000 ,
22050 ,
32000 ,
44100 ,
48000 ,
64000 ,
88200 ,
96000 ,
176400 ,
192000 ,
] ;
2016-01-28 20:27:09 +00:00
let mut rates = Vec ::new ( ) ;
2015-09-10 17:48:39 +00:00
for & rate in RATES . iter ( ) {
if alsa ::snd_pcm_hw_params_test_rate ( playback_handle , hw_params . 0 , rate , 0 ) = = 0 {
rates . push ( rate ) ;
}
}
2015-09-22 13:12:41 +00:00
/* if rates.len() == 0 {
2015-09-10 17:48:39 +00:00
( min_rate .. max_rate + 1 ) . collect ( )
2015-09-22 13:12:41 +00:00
} else { * /
rates // TODO: code is correct but returns lots of stuff
//}
2015-09-10 17:48:39 +00:00
} ;
let mut min_channels = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_get_channels_min ( hw_params . 0 , & mut min_channels ) ) . expect ( " unable to get minimum supported channel count " ) ;
2015-09-10 17:48:39 +00:00
let mut max_channels = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_get_channels_max ( hw_params . 0 , & mut max_channels ) ) . expect ( " unable to get maximum supported channel count " ) ;
2015-09-22 13:46:56 +00:00
let max_channels = cmp ::min ( max_channels , 32 ) ; // TODO: limiting to 32 channels or too much stuff is returned
2015-09-10 17:48:39 +00:00
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 {
2015-09-27 11:27:00 +00:00
Some ( [ ChannelPosition ::FrontLeft , ChannelPosition ::FrontRight ,
ChannelPosition ::BackLeft , ChannelPosition ::BackRight ,
ChannelPosition ::FrontCenter , ChannelPosition ::LowFrequency ]
. iter ( ) . take ( num as usize ) . cloned ( ) . collect ::< Vec < _ > > ( ) )
2015-09-10 17:48:39 +00:00
} else {
None
}
} ) . collect ::< Vec < _ > > ( ) ;
let mut output = Vec ::with_capacity ( supported_formats . len ( ) * supported_channels . len ( ) *
samples_rates . len ( ) ) ;
for & data_type in supported_formats . iter ( ) {
for channels in supported_channels . iter ( ) {
for & rate in samples_rates . iter ( ) {
output . push ( Format {
channels : channels . clone ( ) ,
samples_rate : SamplesRate ( rate as u32 ) ,
data_type : data_type ,
} ) ;
}
}
}
// TODO: RAII
alsa ::snd_pcm_close ( playback_handle ) ;
Ok ( output . into_iter ( ) )
}
2015-09-01 15:15:49 +00:00
}
2015-09-22 12:46:27 +00:00
#[ inline ]
pub fn get_name ( & self ) -> String {
2015-09-22 13:46:56 +00:00
self . 0. clone ( )
2015-09-22 12:46:27 +00:00
}
2015-09-01 15:15:49 +00:00
}
2014-12-17 08:16:26 +00:00
pub struct Voice {
2015-06-24 13:17:52 +00:00
channel : Mutex < * mut alsa ::snd_pcm_t > ,
2014-12-16 15:45:45 +00:00
num_channels : u16 ,
2015-09-22 15:52:35 +00:00
buffer_len : usize , // number of samples that can fit in the buffer
2015-09-27 11:00:17 +00:00
period_len : usize , // minimum number of samples to put in the buffer
2014-12-16 15:45:45 +00:00
}
pub struct Buffer < ' a , T > {
2014-12-17 08:16:26 +00:00
channel : & ' a mut Voice ,
2014-12-16 15:45:45 +00:00
buffer : Vec < T > ,
}
2015-09-10 17:48:39 +00:00
/// Wrapper around `hw_params`.
struct HwParams ( * mut alsa ::snd_pcm_hw_params_t ) ;
impl HwParams {
pub fn alloc ( ) -> HwParams {
unsafe {
let mut hw_params = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_malloc ( & mut hw_params ) ) . expect ( " unable to get hardware parameters " ) ;
2015-09-10 17:48:39 +00:00
HwParams ( hw_params )
}
}
}
impl Drop for HwParams {
fn drop ( & mut self ) {
unsafe {
alsa ::snd_pcm_hw_params_free ( self . 0 ) ;
}
}
}
2014-12-17 08:16:26 +00:00
impl Voice {
2015-09-22 13:20:11 +00:00
pub fn new ( endpoint : & Endpoint , format : & Format ) -> Result < Voice , CreationError > {
2014-12-16 15:45:45 +00:00
unsafe {
2016-01-15 20:16:34 +00:00
let name = ffi ::CString ::new ( endpoint . 0. clone ( ) ) . expect ( " unable to clone endpoint " ) ;
2014-12-16 15:45:45 +00:00
let mut playback_handle = mem ::uninitialized ( ) ;
2015-09-22 13:46:56 +00:00
match alsa ::snd_pcm_open ( & mut playback_handle , name . as_ptr ( ) ,
alsa ::SND_PCM_STREAM_PLAYBACK , alsa ::SND_PCM_NONBLOCK )
2016-01-28 20:27:09 +00:00
{
2015-09-22 13:46:56 +00:00
- 16 /* determined empirically */ = > return Err ( CreationError ::DeviceNotAvailable ) ,
2016-01-15 20:16:34 +00:00
e = > check_errors ( e ) . expect ( " Device unavailable " )
2015-09-22 13:46:56 +00:00
}
2015-09-10 17:48:39 +00:00
2015-09-22 13:20:11 +00:00
// TODO: check endianess
let data_type = match format . data_type {
SampleFormat ::I16 = > alsa ::SND_PCM_FORMAT_S16_LE ,
SampleFormat ::U16 = > alsa ::SND_PCM_FORMAT_U16_LE ,
SampleFormat ::F32 = > alsa ::SND_PCM_FORMAT_FLOAT_LE ,
} ;
2015-09-10 17:48:39 +00:00
let hw_params = HwParams ::alloc ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_hw_params_any ( playback_handle , hw_params . 0 ) ) . expect ( " Errors on playback handle " ) ;
check_errors ( alsa ::snd_pcm_hw_params_set_access ( playback_handle , hw_params . 0 , alsa ::SND_PCM_ACCESS_RW_INTERLEAVED ) ) . expect ( " handle not acessible " ) ;
check_errors ( alsa ::snd_pcm_hw_params_set_format ( playback_handle , hw_params . 0 , data_type ) ) . expect ( " format could not be set " ) ;
check_errors ( alsa ::snd_pcm_hw_params_set_rate ( playback_handle , hw_params . 0 , format . samples_rate . 0 as libc ::c_uint , 0 ) ) . expect ( " sample rate could not be set " ) ;
check_errors ( alsa ::snd_pcm_hw_params_set_channels ( playback_handle , hw_params . 0 , format . channels . len ( ) as libc ::c_uint ) ) . expect ( " channel count could not be set " ) ;
check_errors ( alsa ::snd_pcm_hw_params ( playback_handle , hw_params . 0 ) ) . expect ( " hardware params could not be set " ) ;
2014-12-16 15:45:45 +00:00
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_prepare ( playback_handle ) ) . expect ( " could not get playback handle " ) ;
2014-12-16 15:45:45 +00:00
2015-09-27 11:00:17 +00:00
let ( buffer_len , period_len ) = {
let mut buffer = mem ::uninitialized ( ) ;
let mut period = mem ::uninitialized ( ) ;
2016-01-15 20:16:34 +00:00
check_errors ( alsa ::snd_pcm_get_params ( playback_handle , & mut buffer , & mut period ) ) . expect ( " could not initialize buffer " ) ;
2015-09-27 11:00:17 +00:00
assert! ( buffer ! = 0 ) ;
let buffer = buffer as usize * format . channels . len ( ) ;
let period = period as usize * format . channels . len ( ) ;
( buffer , period )
2015-09-22 15:52:35 +00:00
} ;
2015-09-01 15:15:49 +00:00
Ok ( Voice {
2015-06-24 13:17:52 +00:00
channel : Mutex ::new ( playback_handle ) ,
2015-09-22 13:20:11 +00:00
num_channels : format . channels . len ( ) as u16 ,
2015-09-22 15:52:35 +00:00
buffer_len : buffer_len ,
2015-09-27 11:00:17 +00:00
period_len : period_len ,
2015-09-01 15:15:49 +00:00
} )
2014-12-16 15:45:45 +00:00
}
}
2015-01-09 20:25:51 +00:00
pub fn append_data < ' a , T > ( & ' a mut self , max_elements : usize ) -> Buffer < ' a , T > where T : Clone {
2015-06-24 13:17:52 +00:00
let available = {
2016-01-15 20:16:34 +00:00
let channel = self . channel . lock ( ) . expect ( " could not lock channel " ) ;
2015-06-24 13:17:52 +00:00
let available = unsafe { alsa ::snd_pcm_avail ( * channel ) } ;
2015-09-22 18:20:17 +00:00
if available = = - 32 {
// buffer underrun
self . buffer_len
} else if available < 0 {
2016-01-15 20:16:34 +00:00
check_errors ( available as libc ::c_int ) . expect ( " buffer is not available " ) ;
2015-09-22 18:20:17 +00:00
unreachable! ( )
} else {
( available * self . num_channels as alsa ::snd_pcm_sframes_t ) as usize
}
2015-06-24 13:17:52 +00:00
} ;
2014-12-16 15:45:45 +00:00
2015-09-22 18:20:17 +00:00
let elements = cmp ::min ( available , max_elements ) ;
2014-12-16 15:45:45 +00:00
Buffer {
channel : self ,
2015-01-08 19:34:27 +00:00
buffer : iter ::repeat ( unsafe { mem ::uninitialized ( ) } ) . take ( elements ) . collect ( ) ,
2014-12-16 15:45:45 +00:00
}
}
2014-12-22 13:16:47 +00:00
2015-09-11 08:55:29 +00:00
#[ inline ]
2014-12-22 13:16:47 +00:00
pub fn play ( & mut self ) {
// already playing
//unimplemented!()
}
2015-09-11 08:55:29 +00:00
#[ inline ]
2014-12-22 13:16:47 +00:00
pub fn pause ( & mut self ) {
unimplemented! ( )
}
2015-09-10 19:03:40 +00:00
2015-09-27 11:00:17 +00:00
#[ inline ]
pub fn get_period ( & self ) -> usize {
self . period_len
}
2015-09-22 15:52:35 +00:00
pub fn get_pending_samples ( & self ) -> usize {
let available = {
2016-01-15 20:16:34 +00:00
let channel = self . channel . lock ( ) . expect ( " could not lock channel " ) ;
2015-09-22 15:52:35 +00:00
let available = unsafe { alsa ::snd_pcm_avail ( * channel ) } ;
2016-01-28 20:27:09 +00:00
2015-09-22 18:20:17 +00:00
if available = = - 32 {
2016-01-28 20:27:09 +00:00
self . buffer_len as alsa ::snd_pcm_sframes_t // buffer underrun
2015-09-22 18:20:17 +00:00
} else if available < 0 {
2016-01-15 20:16:34 +00:00
check_errors ( available as libc ::c_int ) . expect ( " could not write to buffer " ) ;
2015-09-22 18:20:17 +00:00
unreachable! ( )
} else {
available * self . num_channels as alsa ::snd_pcm_sframes_t
}
2015-09-22 15:52:35 +00:00
} ;
self . buffer_len - available as usize
}
2015-09-10 19:03:40 +00:00
pub fn underflowed ( & self ) -> bool {
2016-01-15 20:16:34 +00:00
let channel = self . channel . lock ( ) . expect ( " channel underflow " ) ;
2015-09-22 18:20:17 +00:00
let state = unsafe { alsa ::snd_pcm_state ( * channel ) } ;
state = = alsa ::SND_PCM_STATE_XRUN
2015-09-10 19:03:40 +00:00
}
2014-12-16 15:45:45 +00:00
}
2014-12-30 07:35:13 +00:00
unsafe impl Send for Voice { }
unsafe impl Sync for Voice { }
2014-12-17 08:16:26 +00:00
impl Drop for Voice {
2015-09-11 08:55:29 +00:00
#[ inline ]
2014-12-16 15:45:45 +00:00
fn drop ( & mut self ) {
unsafe {
2016-01-15 20:16:34 +00:00
alsa ::snd_pcm_close ( * self . channel . lock ( ) . expect ( " drop for voice " ) ) ;
2014-12-16 15:45:45 +00:00
}
}
}
impl < ' a , T > Buffer < ' a , T > {
2015-09-11 08:55:29 +00:00
#[ inline ]
2014-12-16 15:45:45 +00:00
pub fn get_buffer < ' b > ( & ' b mut self ) -> & ' b mut [ T ] {
2015-03-30 09:06:46 +00:00
& mut self . buffer
2014-12-16 15:45:45 +00:00
}
2015-09-11 08:55:29 +00:00
#[ inline ]
2015-09-10 19:21:46 +00:00
pub fn len ( & self ) -> usize {
self . buffer . len ( )
}
2014-12-16 15:45:45 +00:00
pub fn finish ( self ) {
2015-09-22 19:01:26 +00:00
let to_write = ( self . buffer . len ( ) / self . channel . num_channels as usize )
as alsa ::snd_pcm_uframes_t ;
2016-01-15 20:16:34 +00:00
let channel = self . channel . channel . lock ( ) . expect ( " Buffer channel lock failed " ) ;
2014-12-16 15:45:45 +00:00
unsafe {
2015-09-22 18:20:17 +00:00
loop {
let result = alsa ::snd_pcm_writei ( * channel ,
self . buffer . as_ptr ( ) as * const libc ::c_void ,
2015-09-22 19:01:26 +00:00
to_write ) ;
2015-09-22 18:20:17 +00:00
if result = = - 32 {
// buffer underrun
alsa ::snd_pcm_prepare ( * channel ) ;
} else if result < 0 {
2016-01-15 20:16:34 +00:00
check_errors ( result as libc ::c_int ) . expect ( " could not write pcm " ) ;
2015-09-22 18:20:17 +00:00
} else {
2015-09-22 19:01:26 +00:00
assert_eq! ( result as alsa ::snd_pcm_uframes_t , to_write ) ;
2015-09-22 18:20:17 +00:00
break ;
}
2014-12-16 15:45:45 +00:00
}
}
}
}
2015-09-11 08:55:29 +00:00
#[ inline ]
2014-12-16 15:45:45 +00:00
fn check_errors ( err : libc ::c_int ) -> Result < ( ) , String > {
2015-01-08 19:34:27 +00:00
use std ::ffi ;
2014-12-16 15:45:45 +00:00
if err < 0 {
unsafe {
2015-04-04 07:06:46 +00:00
let s = ffi ::CStr ::from_ptr ( alsa ::snd_strerror ( err ) ) . to_bytes ( ) . to_vec ( ) ;
2016-01-15 20:16:34 +00:00
let s = String ::from_utf8 ( s ) . expect ( " Streaming error occured " ) ;
2015-04-04 07:06:46 +00:00
return Err ( s ) ;
2014-12-16 15:45:45 +00:00
}
}
Ok ( ( ) )
}