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 ;
2016-08-02 20:28:37 +00:00
use UnknownTypeBuffer ;
2015-09-01 15:15:49 +00:00
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 ;
2016-08-02 20:28:37 +00:00
use std ::sync ::{ Arc , Mutex } ;
2016-10-02 11:18:27 +00:00
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2016-08-02 20:28:37 +00:00
use futures ::Poll ;
2016-09-30 16:18:28 +00:00
use futures ::task ::Task ;
use futures ::task ;
2016-08-02 20:28:37 +00:00
use futures ::stream ::Stream ;
2016-09-30 16:18:28 +00:00
use futures ::Async ;
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 ;
2017-07-13 11:58:01 +00:00
struct Trigger {
// [read fd, write fd]
fds : [ libc ::c_int ; 2 ] ,
}
impl Trigger {
fn new ( ) -> Self {
let mut fds = [ 0 , 0 ] ;
match unsafe { libc ::pipe ( fds . as_mut_ptr ( ) ) } {
0 = > Trigger { fds : fds } ,
_ = > panic! ( " Could not create pipe " )
}
}
fn read_fd ( & self ) -> libc ::c_int {
self . fds [ 0 ]
}
fn write_fd ( & self ) -> libc ::c_int {
self . fds [ 1 ]
}
fn wakeup ( & self ) {
let buf = 1 u64 ;
let ret = unsafe { libc ::write ( self . write_fd ( ) , & buf as * const u64 as * const _ , 8 ) } ;
assert! ( ret = = 8 ) ;
}
fn clear_pipe ( & self ) {
let mut out = 0 u64 ;
let ret = unsafe { libc ::read ( self . read_fd ( ) , & mut out as * mut u64 as * mut _ , 8 ) } ;
assert_eq! ( ret , 8 ) ;
}
}
impl Drop for Trigger {
fn drop ( & mut self ) {
unsafe {
libc ::close ( self . fds [ 0 ] ) ;
libc ::close ( self . fds [ 1 ] ) ;
}
}
}
2015-09-01 15:15:49 +00:00
#[ 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
}
2016-08-02 20:28:37 +00:00
pub struct EventLoop {
inner : Arc < EventLoopInner > ,
}
struct EventLoopInner {
// Descriptors that we are currently waiting upon. This member is always locked while `run()`
// is executed, ie. most of the time.
//
// Note that for `current_wait`, the first element of `descriptors` is always
// `pending_wait_signal`. Therefore the length of `descriptors` is always one more than
// `voices`.
current_wait : Mutex < PollDescriptors > ,
// Since we can't add elements to `current_wait` (as it's locked), we add them to
// `pending_wait`. Once that's done, we signal `pending_wait_signal` so that the `run()`
// function can pause and add the content of `pending_wait` to `current_wait`.
pending_wait : Mutex < PollDescriptors > ,
2017-07-13 11:58:01 +00:00
// A trigger that uses a `pipe` as backend. Always the first element
2016-08-02 20:28:37 +00:00
// of `current_wait.descriptors`. Should be notified when an element is added
// to `pending_wait` so that the current wait can stop and take the pending wait into
// account.
2017-07-13 11:58:01 +00:00
pending_trigger : Trigger ,
2016-08-02 20:28:37 +00:00
}
struct PollDescriptors {
// Descriptors to wait for.
descriptors : Vec < libc ::pollfd > ,
// List of voices that are written in `descriptors`.
voices : Vec < Arc < VoiceInner > > ,
}
unsafe impl Send for EventLoopInner { }
unsafe impl Sync for EventLoopInner { }
impl EventLoop {
#[ inline ]
pub fn new ( ) -> EventLoop {
2017-07-13 11:58:01 +00:00
let pending_trigger = Trigger ::new ( ) ;
2016-08-02 20:28:37 +00:00
EventLoop {
inner : Arc ::new ( EventLoopInner {
current_wait : Mutex ::new ( PollDescriptors {
descriptors : vec ! [ libc ::pollfd {
2017-07-13 11:58:01 +00:00
fd : pending_trigger . read_fd ( ) ,
2016-08-02 20:28:37 +00:00
events : libc ::POLLIN ,
revents : 0 ,
} ] ,
voices : Vec ::new ( ) ,
} ) ,
pending_wait : Mutex ::new ( PollDescriptors {
descriptors : Vec ::new ( ) ,
voices : Vec ::new ( ) ,
} ) ,
2017-07-13 11:58:01 +00:00
pending_trigger : pending_trigger ,
2016-08-02 20:28:37 +00:00
} )
}
}
#[ inline ]
pub fn run ( & self ) {
unsafe {
let mut current_wait = self . inner . current_wait . lock ( ) . unwrap ( ) ;
loop {
let ret = libc ::poll ( current_wait . descriptors . as_mut_ptr ( ) ,
current_wait . descriptors . len ( ) as libc ::nfds_t ,
- 1 /* infinite */ ) ;
assert! ( ret > = 0 , " poll() failed " ) ;
if ret = = 0 {
continue ;
}
// If the `pending_wait_signal` was signaled, add the pending waits to
// the current waits.
if current_wait . descriptors [ 0 ] . revents ! = 0 {
current_wait . descriptors [ 0 ] . revents = 0 ;
let mut pending = self . inner . pending_wait . lock ( ) . unwrap ( ) ;
current_wait . descriptors . append ( & mut pending . descriptors ) ;
current_wait . voices . append ( & mut pending . voices ) ;
// Emptying the signal.
2017-07-13 11:58:01 +00:00
self . inner . pending_trigger . clear_pipe ( ) ;
2016-08-02 20:28:37 +00:00
}
// Check each individual descriptor for events.
let mut i_voice = 0 ;
let mut i_descriptor = 1 ;
while i_voice < current_wait . voices . len ( ) {
2016-10-02 11:18:27 +00:00
let kind = {
let scheduled = current_wait . voices [ i_voice ] . scheduled . lock ( ) . unwrap ( ) ;
match * scheduled {
Some ( ref scheduled ) = > scheduled . kind ,
None = > panic! ( " current wait unscheduled task " ) ,
2016-08-02 20:28:37 +00:00
}
2016-10-02 11:18:27 +00:00
} ;
// Depending on the kind of scheduling the number of descriptors corresponding
// to the voice and the events associated are different
match kind {
ScheduledKind ::WaitPCM = > {
let mut revent = mem ::uninitialized ( ) ;
{
let channel = * current_wait . voices [ i_voice ] . channel . lock ( ) . unwrap ( ) ;
let num_descriptors = current_wait . voices [ i_voice ] . num_descriptors as libc ::c_uint ;
check_errors ( alsa ::snd_pcm_poll_descriptors_revents ( channel , current_wait . descriptors
. as_mut_ptr ( ) . offset ( i_descriptor ) ,
num_descriptors , & mut revent ) ) . unwrap ( ) ;
}
if ( revent as libc ::c_short & libc ::POLLOUT ) ! = 0 {
let scheduled = current_wait . voices [ i_voice ] . scheduled . lock ( ) . unwrap ( ) . take ( ) ;
scheduled . unwrap ( ) . task . unpark ( ) ;
for _ in 0 .. current_wait . voices [ i_voice ] . num_descriptors {
current_wait . descriptors . remove ( i_descriptor as usize ) ;
}
current_wait . voices . remove ( i_voice ) ;
} else {
i_descriptor + = current_wait . voices [ i_voice ] . num_descriptors as isize ;
i_voice + = 1 ;
}
} ,
ScheduledKind ::WaitResume = > {
if current_wait . descriptors [ i_descriptor as usize ] . revents ! = 0 {
// Unpark the task
let scheduled = current_wait . voices [ i_voice ] . scheduled . lock ( ) . unwrap ( ) . take ( ) ;
scheduled . unwrap ( ) . task . unpark ( ) ;
// Emptying the signal.
let mut out = 0 u64 ;
let ret = libc ::read ( current_wait . descriptors [ i_descriptor as usize ] . fd ,
& mut out as * mut u64 as * mut _ , 8 ) ;
assert_eq! ( ret , 8 ) ;
// Remove from current waiting poll descriptors
current_wait . descriptors . remove ( i_descriptor as usize ) ;
current_wait . voices . remove ( i_voice ) ;
} else {
i_descriptor + = 1 ;
i_voice + = 1 ;
}
2016-08-02 20:28:37 +00:00
}
}
}
}
}
}
}
2016-10-02 11:18:27 +00:00
pub struct Voice {
inner : Arc < VoiceInner > ,
}
2016-08-02 20:28:37 +00:00
pub struct Buffer < T > {
inner : Arc < VoiceInner > ,
buffer : Vec < T > ,
}
pub struct SamplesStream {
inner : Arc < VoiceInner > ,
}
2016-10-02 11:18:27 +00:00
pub struct Scheduled {
task : Task ,
kind : ScheduledKind ,
}
#[ derive(Clone,Copy) ]
pub enum ScheduledKind {
WaitResume ,
WaitPCM ,
}
2016-08-02 20:28:37 +00:00
struct VoiceInner {
// The event loop used to create the voice.
event_loop : Arc < EventLoopInner > ,
// The ALSA channel.
2015-06-24 13:17:52 +00:00
channel : Mutex < * mut alsa ::snd_pcm_t > ,
2016-08-02 20:28:37 +00:00
// When converting between file descriptors and `snd_pcm_t`, this is the number of
// file descriptors that this `snd_pcm_t` uses.
num_descriptors : usize ,
// Format of the samples.
sample_format : SampleFormat ,
// Number of channels, ie. number of samples per frame.
2014-12-16 15:45:45 +00:00
num_channels : u16 ,
2016-08-02 20:28:37 +00:00
// Number of samples that can fit in the buffer.
2016-09-30 16:18:28 +00:00
buffer_len : usize ,
2016-08-02 20:28:37 +00:00
// Minimum number of samples to put in the buffer.
period_len : usize ,
// If `Some`, something previously called `schedule` on the stream.
2016-10-02 11:18:27 +00:00
scheduled : Mutex < Option < Scheduled > > ,
// Wherease the sample stream is paused
2016-10-02 12:24:30 +00:00
is_paused : AtomicBool ,
2016-10-02 11:18:27 +00:00
// A file descriptor opened with `eventfd`.
// It is used to wait for resume signal.
2017-07-13 11:58:01 +00:00
resume_trigger : Trigger ,
2014-12-16 15:45:45 +00:00
}
2016-08-02 20:28:37 +00:00
unsafe impl Send for VoiceInner { }
unsafe impl Sync for VoiceInner { }
2016-09-30 16:18:28 +00:00
impl SamplesStream {
#[ inline ]
2016-10-02 11:18:27 +00:00
fn schedule ( & mut self , kind : ScheduledKind ) {
2016-09-30 16:18:28 +00:00
unsafe {
let channel = self . inner . channel . lock ( ) . unwrap ( ) ;
// We start by filling `scheduled`.
2016-10-02 11:18:27 +00:00
* self . inner . scheduled . lock ( ) . unwrap ( ) = Some ( Scheduled {
task : task ::park ( ) ,
kind : kind ,
} ) ;
2016-09-30 16:18:28 +00:00
let mut pending_wait = self . inner . event_loop . pending_wait . lock ( ) . unwrap ( ) ;
2016-10-02 11:18:27 +00:00
match kind {
ScheduledKind ::WaitPCM = > {
// In this function we turn the `snd_pcm_t` into a collection of file descriptors.
// And we add these descriptors to `event_loop.pending_wait.descriptors`.
pending_wait . descriptors . reserve ( self . inner . num_descriptors ) ;
let len = pending_wait . descriptors . len ( ) ;
let filled = alsa ::snd_pcm_poll_descriptors ( * channel ,
pending_wait . descriptors . as_mut_ptr ( )
. offset ( len as isize ) ,
self . inner . num_descriptors as libc ::c_uint ) ;
debug_assert_eq! ( filled , self . inner . num_descriptors as libc ::c_int ) ;
pending_wait . descriptors . set_len ( len + self . inner . num_descriptors ) ;
} ,
ScheduledKind ::WaitResume = > {
// And we add the descriptor corresponding to the resume signal
// to `event_loop.pending_wait.descriptors`.
pending_wait . descriptors . push ( libc ::pollfd {
2017-07-13 11:58:01 +00:00
fd : self . inner . resume_trigger . read_fd ( ) ,
2016-10-02 11:18:27 +00:00
events : libc ::POLLIN ,
revents : 0 ,
} ) ;
}
}
2016-09-30 16:18:28 +00:00
// We also fill `voices`.
pending_wait . voices . push ( self . inner . clone ( ) ) ;
// Now that `pending_wait` received additional descriptors, we signal the event
// so that our event loops can pick it up.
drop ( pending_wait ) ;
2017-07-13 11:58:01 +00:00
self . inner . event_loop . pending_trigger . wakeup ( ) ;
2016-09-30 16:18:28 +00:00
}
}
}
2016-08-02 20:28:37 +00:00
impl Stream for SamplesStream {
type Item = UnknownTypeBuffer ;
type Error = ( ) ;
2016-09-30 16:18:28 +00:00
fn poll ( & mut self ) -> Poll < Option < Self ::Item > , Self ::Error > {
2016-10-02 11:18:27 +00:00
// If paused then we schedule the task and return `NotReady`
if self . inner . is_paused . load ( Ordering ::Relaxed ) {
self . schedule ( ScheduledKind ::WaitResume ) ;
return Ok ( Async ::NotReady ) ;
}
2016-08-02 20:28:37 +00:00
// Determine the number of samples that are available to write.
let available = {
let channel = self . inner . channel . lock ( ) . expect ( " could not lock channel " ) ;
let available = unsafe { alsa ::snd_pcm_avail ( * channel ) } ; // TODO: what about snd_pcm_avail_update?
if available = = - 32 {
// buffer underrun
self . inner . buffer_len
} else if available < 0 {
check_errors ( available as libc ::c_int ) . expect ( " buffer is not available " ) ;
unreachable! ( )
} else {
( available * self . inner . num_channels as alsa ::snd_pcm_sframes_t ) as usize
}
} ;
2016-10-02 11:18:27 +00:00
// If we don't have one period ready, schedule the task and return `NotReady`.
2016-08-02 20:28:37 +00:00
if available < self . inner . period_len {
2016-10-02 11:18:27 +00:00
self . schedule ( ScheduledKind ::WaitPCM ) ;
2016-09-30 16:18:28 +00:00
return Ok ( Async ::NotReady ) ;
2016-08-02 20:28:37 +00:00
}
// We now sure that we're ready to write data.
match self . inner . sample_format {
SampleFormat ::I16 = > {
let buffer = Buffer {
buffer : iter ::repeat ( unsafe { mem ::uninitialized ( ) } ) . take ( available ) . collect ( ) ,
inner : self . inner . clone ( ) ,
} ;
2016-09-30 16:18:28 +00:00
Ok ( Async ::Ready ( ( Some ( UnknownTypeBuffer ::I16 ( ::Buffer { target : Some ( buffer ) } ) ) ) ) )
2016-08-02 20:28:37 +00:00
} ,
SampleFormat ::U16 = > {
let buffer = Buffer {
buffer : iter ::repeat ( unsafe { mem ::uninitialized ( ) } ) . take ( available ) . collect ( ) ,
inner : self . inner . clone ( ) ,
} ;
2016-09-30 16:18:28 +00:00
Ok ( Async ::Ready ( ( Some ( UnknownTypeBuffer ::U16 ( ::Buffer { target : Some ( buffer ) } ) ) ) ) )
2016-08-02 20:28:37 +00:00
} ,
SampleFormat ::F32 = > {
let buffer = Buffer {
buffer : iter ::repeat ( unsafe { mem ::uninitialized ( ) } ) . take ( available ) . collect ( ) ,
inner : self . inner . clone ( ) ,
} ;
2016-09-30 16:18:28 +00:00
Ok ( Async ::Ready ( ( Some ( UnknownTypeBuffer ::F32 ( ::Buffer { target : Some ( buffer ) } ) ) ) ) )
2016-08-02 20:28:37 +00:00
} ,
}
}
2014-12-16 15:45:45 +00:00
}
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 {
2016-08-02 20:28:37 +00:00
pub fn new ( endpoint : & Endpoint , format : & Format , event_loop : & EventLoop )
-> Result < ( Voice , SamplesStream ) , 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 ( ) ,
2016-08-02 20:28:37 +00:00
alsa ::SND_PCM_STREAM_PLAYBACK , 0 )
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 " ) ;
2016-08-03 08:31:02 +00:00
let mut max_buffer_size = format . samples_rate . 0 as alsa ::snd_pcm_uframes_t / format . channels . len ( ) as alsa ::snd_pcm_uframes_t / 5 ; // 200ms of buffer
check_errors ( alsa ::snd_pcm_hw_params_set_buffer_size_max ( playback_handle , hw_params . 0 , & mut max_buffer_size ) ) . unwrap ( ) ;
2016-01-15 20:16:34 +00:00
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-08-02 20:28:37 +00:00
let mut sw_params = mem ::uninitialized ( ) ; // TODO: RAII
check_errors ( alsa ::snd_pcm_sw_params_malloc ( & mut sw_params ) ) . unwrap ( ) ;
check_errors ( alsa ::snd_pcm_sw_params_current ( playback_handle , sw_params ) ) . unwrap ( ) ;
check_errors ( alsa ::snd_pcm_sw_params_set_start_threshold ( playback_handle , sw_params , 0 ) ) . unwrap ( ) ;
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 ) ;
2017-01-25 08:07:23 +00:00
check_errors ( alsa ::snd_pcm_sw_params_set_avail_min ( playback_handle , sw_params , period ) ) . unwrap ( ) ;
2015-09-27 11:00:17 +00:00
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
} ;
2017-01-24 00:10:44 +00:00
check_errors ( alsa ::snd_pcm_sw_params ( playback_handle , sw_params ) ) . unwrap ( ) ;
check_errors ( alsa ::snd_pcm_prepare ( playback_handle ) ) . expect ( " could not get playback handle " ) ;
2016-08-02 20:28:37 +00:00
let num_descriptors = {
let num_descriptors = alsa ::snd_pcm_poll_descriptors_count ( playback_handle ) ;
debug_assert! ( num_descriptors > = 1 ) ;
num_descriptors as usize
} ;
let samples_stream_inner = Arc ::new ( VoiceInner {
event_loop : event_loop . inner . clone ( ) ,
2015-06-24 13:17:52 +00:00
channel : Mutex ::new ( playback_handle ) ,
2016-08-02 20:28:37 +00:00
sample_format : format . data_type ,
num_descriptors : num_descriptors ,
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 ,
2016-08-02 20:28:37 +00:00
scheduled : Mutex ::new ( None ) ,
2016-10-02 12:24:30 +00:00
is_paused : AtomicBool ::new ( true ) ,
2017-07-13 11:58:01 +00:00
resume_trigger : Trigger ::new ( ) ,
2016-08-02 20:28:37 +00:00
} ) ;
2015-09-22 18:20:17 +00:00
2016-10-02 11:18:27 +00:00
Ok ( ( Voice {
inner : samples_stream_inner . clone ( )
} , SamplesStream {
2016-08-02 20:28:37 +00:00
inner : samples_stream_inner
} ) )
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 ) {
2016-10-02 11:18:27 +00:00
// If it was paused then we resume and signal
// FIXME: the signal is send even if the event loop wasn't waiting for resume, is that an issue ?
2016-10-02 12:19:58 +00:00
if self . inner . is_paused . swap ( false , Ordering ::Relaxed ) {
2017-07-13 11:58:01 +00:00
self . inner . resume_trigger . wakeup ( ) ;
2016-10-02 11:18:27 +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 pause ( & mut self ) {
2016-10-02 12:19:58 +00:00
self . inner . is_paused . store ( true , Ordering ::Relaxed ) ;
2014-12-22 13:16:47 +00:00
}
2014-12-16 15:45:45 +00:00
}
2016-08-02 20:28:37 +00:00
impl Drop for VoiceInner {
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
}
}
}
2016-08-02 20:28:37 +00:00
impl < T > Buffer < T > {
2015-09-11 08:55:29 +00:00
#[ inline ]
2016-08-02 20:28:37 +00:00
pub fn get_buffer ( & mut self ) -> & 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 ) {
2016-08-02 20:28:37 +00:00
let to_write = ( self . buffer . len ( ) / self . inner . num_channels as usize )
2015-09-22 19:01:26 +00:00
as alsa ::snd_pcm_uframes_t ;
2016-08-02 20:28:37 +00:00
let channel = self . inner . 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 ,
2016-04-25 11:33:12 +00:00
self . buffer . as_ptr ( ) as * const _ ,
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 ( ( ) )
}