1 extern crate alsa_sys as alsa;
2 extern crate libc;
3 
4 pub use self::enumerate::{Devices, default_input_device, default_output_device};
5 
6 use ChannelCount;
7 use CreationError;
8 use DefaultFormatError;
9 use Format;
10 use FormatsEnumerationError;
11 use SampleFormat;
12 use SampleRate;
13 use StreamData;
14 use SupportedFormat;
15 use UnknownTypeInputBuffer;
16 use UnknownTypeOutputBuffer;
17 
18 use std::{cmp, ffi, iter, mem, ptr};
19 use std::sync::Mutex;
20 use std::sync::atomic::{AtomicUsize, Ordering};
21 use std::vec::IntoIter as VecIntoIter;
22 
23 pub type SupportedInputFormats = VecIntoIter<SupportedFormat>;
24 pub type SupportedOutputFormats = VecIntoIter<SupportedFormat>;
25 
26 mod enumerate;
27 
28 
29 struct Trigger {
30     // [read fd, write fd]
31     fds: [libc::c_int; 2],
32 }
33 
34 impl Trigger {
new() -> Self35     fn new() -> Self {
36         let mut fds = [0, 0];
37         match unsafe { libc::pipe(fds.as_mut_ptr()) } {
38             0 => Trigger { fds: fds },
39             _ => panic!("Could not create pipe"),
40         }
41     }
read_fd(&self) -> libc::c_int42     fn read_fd(&self) -> libc::c_int {
43         self.fds[0]
44     }
write_fd(&self) -> libc::c_int45     fn write_fd(&self) -> libc::c_int {
46         self.fds[1]
47     }
wakeup(&self)48     fn wakeup(&self) {
49         let buf = 1u64;
50         let ret = unsafe { libc::write(self.write_fd(), &buf as *const u64 as *const _, 8) };
51         assert!(ret == 8);
52     }
clear_pipe(&self)53     fn clear_pipe(&self) {
54         let mut out = 0u64;
55         let ret = unsafe { libc::read(self.read_fd(), &mut out as *mut u64 as *mut _, 8) };
56         assert_eq!(ret, 8);
57     }
58 }
59 
60 impl Drop for Trigger {
drop(&mut self)61     fn drop(&mut self) {
62         unsafe {
63             libc::close(self.fds[0]);
64             libc::close(self.fds[1]);
65         }
66     }
67 }
68 
69 
70 #[derive(Clone, Debug, PartialEq, Eq)]
71 pub struct Device(String);
72 
73 impl Device {
74     #[inline]
name(&self) -> String75     pub fn name(&self) -> String {
76         self.0.clone()
77     }
78 
supported_formats( &self, stream_t: alsa::snd_pcm_stream_t, ) -> Result<VecIntoIter<SupportedFormat>, FormatsEnumerationError>79     unsafe fn supported_formats(
80         &self,
81         stream_t: alsa::snd_pcm_stream_t,
82     ) -> Result<VecIntoIter<SupportedFormat>, FormatsEnumerationError>
83     {
84         let mut handle = mem::uninitialized();
85         let device_name = ffi::CString::new(&self.0[..]).expect("Unable to get device name");
86 
87         match alsa::snd_pcm_open(
88             &mut handle,
89             device_name.as_ptr() as *const _,
90             stream_t,
91             alsa::SND_PCM_NONBLOCK,
92         ) {
93             -2 |
94             -16 /* determined empirically */ => return Err(FormatsEnumerationError::DeviceNotAvailable),
95             e => check_errors(e).expect("device not available")
96         }
97 
98         let hw_params = HwParams::alloc();
99         match check_errors(alsa::snd_pcm_hw_params_any(handle, hw_params.0)) {
100             Err(_) => return Ok(Vec::new().into_iter()),
101             Ok(_) => (),
102         };
103 
104         // TODO: check endianess
105         const FORMATS: [(SampleFormat, alsa::snd_pcm_format_t); 3] =
106             [
107                 //SND_PCM_FORMAT_S8,
108                 //SND_PCM_FORMAT_U8,
109                 (SampleFormat::I16, alsa::SND_PCM_FORMAT_S16_LE),
110                 //SND_PCM_FORMAT_S16_BE,
111                 (SampleFormat::U16, alsa::SND_PCM_FORMAT_U16_LE),
112                 //SND_PCM_FORMAT_U16_BE,
113             /*SND_PCM_FORMAT_S24_LE,
114             SND_PCM_FORMAT_S24_BE,
115             SND_PCM_FORMAT_U24_LE,
116             SND_PCM_FORMAT_U24_BE,
117             SND_PCM_FORMAT_S32_LE,
118             SND_PCM_FORMAT_S32_BE,
119             SND_PCM_FORMAT_U32_LE,
120             SND_PCM_FORMAT_U32_BE,*/
121                 (SampleFormat::F32, alsa::SND_PCM_FORMAT_FLOAT_LE) /*SND_PCM_FORMAT_FLOAT_BE,
122             SND_PCM_FORMAT_FLOAT64_LE,
123             SND_PCM_FORMAT_FLOAT64_BE,
124             SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
125             SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
126             SND_PCM_FORMAT_MU_LAW,
127             SND_PCM_FORMAT_A_LAW,
128             SND_PCM_FORMAT_IMA_ADPCM,
129             SND_PCM_FORMAT_MPEG,
130             SND_PCM_FORMAT_GSM,
131             SND_PCM_FORMAT_SPECIAL,
132             SND_PCM_FORMAT_S24_3LE,
133             SND_PCM_FORMAT_S24_3BE,
134             SND_PCM_FORMAT_U24_3LE,
135             SND_PCM_FORMAT_U24_3BE,
136             SND_PCM_FORMAT_S20_3LE,
137             SND_PCM_FORMAT_S20_3BE,
138             SND_PCM_FORMAT_U20_3LE,
139             SND_PCM_FORMAT_U20_3BE,
140             SND_PCM_FORMAT_S18_3LE,
141             SND_PCM_FORMAT_S18_3BE,
142             SND_PCM_FORMAT_U18_3LE,
143             SND_PCM_FORMAT_U18_3BE,*/,
144             ];
145 
146         let mut supported_formats = Vec::new();
147         for &(sample_format, alsa_format) in FORMATS.iter() {
148             if alsa::snd_pcm_hw_params_test_format(handle,
149                                                    hw_params.0,
150                                                    alsa_format) == 0
151             {
152                 supported_formats.push(sample_format);
153             }
154         }
155 
156         let mut min_rate = mem::uninitialized();
157         check_errors(alsa::snd_pcm_hw_params_get_rate_min(hw_params.0,
158                                                           &mut min_rate,
159                                                           ptr::null_mut()))
160             .expect("unable to get minimum supported rete");
161         let mut max_rate = mem::uninitialized();
162         check_errors(alsa::snd_pcm_hw_params_get_rate_max(hw_params.0,
163                                                           &mut max_rate,
164                                                           ptr::null_mut()))
165             .expect("unable to get maximum supported rate");
166 
167         let sample_rates = if min_rate == max_rate {
168             vec![(min_rate, max_rate)]
169         } else if alsa::snd_pcm_hw_params_test_rate(handle,
170                                                     hw_params.0,
171                                                     min_rate + 1,
172                                                     0) == 0
173         {
174             vec![(min_rate, max_rate)]
175         } else {
176             const RATES: [libc::c_uint; 13] = [
177                 5512,
178                 8000,
179                 11025,
180                 16000,
181                 22050,
182                 32000,
183                 44100,
184                 48000,
185                 64000,
186                 88200,
187                 96000,
188                 176400,
189                 192000,
190             ];
191 
192             let mut rates = Vec::new();
193             for &rate in RATES.iter() {
194                 if alsa::snd_pcm_hw_params_test_rate(handle,
195                                                      hw_params.0,
196                                                      rate,
197                                                      0) == 0
198                 {
199                     rates.push((rate, rate));
200                 }
201             }
202 
203             if rates.len() == 0 {
204                 vec![(min_rate, max_rate)]
205             } else {
206                 rates
207             }
208         };
209 
210         let mut min_channels = mem::uninitialized();
211         check_errors(alsa::snd_pcm_hw_params_get_channels_min(hw_params.0, &mut min_channels))
212             .expect("unable to get minimum supported channel count");
213         let mut max_channels = mem::uninitialized();
214         check_errors(alsa::snd_pcm_hw_params_get_channels_max(hw_params.0, &mut max_channels))
215             .expect("unable to get maximum supported channel count");
216         let max_channels = cmp::min(max_channels, 32); // TODO: limiting to 32 channels or too much stuff is returned
217         let supported_channels = (min_channels .. max_channels + 1)
218             .filter_map(|num| if alsa::snd_pcm_hw_params_test_channels(
219                 handle,
220                 hw_params.0,
221                 num,
222             ) == 0
223             {
224                 Some(num as ChannelCount)
225             } else {
226                 None
227             })
228             .collect::<Vec<_>>();
229 
230         let mut output = Vec::with_capacity(supported_formats.len() * supported_channels.len() *
231                                                 sample_rates.len());
232         for &data_type in supported_formats.iter() {
233             for channels in supported_channels.iter() {
234                 for &(min_rate, max_rate) in sample_rates.iter() {
235                     output.push(SupportedFormat {
236                                     channels: channels.clone(),
237                                     min_sample_rate: SampleRate(min_rate as u32),
238                                     max_sample_rate: SampleRate(max_rate as u32),
239                                     data_type: data_type,
240                                 });
241                 }
242             }
243         }
244 
245         // TODO: RAII
246         alsa::snd_pcm_close(handle);
247         Ok(output.into_iter())
248     }
249 
supported_input_formats(&self) -> Result<SupportedInputFormats, FormatsEnumerationError>250     pub fn supported_input_formats(&self) -> Result<SupportedInputFormats, FormatsEnumerationError> {
251         unsafe {
252             self.supported_formats(alsa::SND_PCM_STREAM_CAPTURE)
253         }
254     }
255 
supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError>256     pub fn supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError> {
257         unsafe {
258             self.supported_formats(alsa::SND_PCM_STREAM_PLAYBACK)
259         }
260     }
261 
262     // ALSA does not offer default stream formats, so instead we compare all supported formats by
263     // the `SupportedFormat::cmp_default_heuristics` order and select the greatest.
default_format( &self, stream_t: alsa::snd_pcm_stream_t, ) -> Result<Format, DefaultFormatError>264     fn default_format(
265         &self,
266         stream_t: alsa::snd_pcm_stream_t,
267     ) -> Result<Format, DefaultFormatError>
268     {
269         let mut formats: Vec<_> = unsafe {
270             match self.supported_formats(stream_t) {
271                 Err(FormatsEnumerationError::DeviceNotAvailable) => {
272                     return Err(DefaultFormatError::DeviceNotAvailable);
273                 },
274                 Ok(fmts) => fmts.collect(),
275             }
276         };
277 
278         formats.sort_by(|a, b| a.cmp_default_heuristics(b));
279 
280         match formats.into_iter().last() {
281             Some(f) => {
282                 let min_r = f.min_sample_rate;
283                 let max_r = f.max_sample_rate;
284                 let mut format = f.with_max_sample_rate();
285                 const HZ_44100: SampleRate = SampleRate(44_100);
286                 if min_r <= HZ_44100 && HZ_44100 <= max_r {
287                     format.sample_rate = HZ_44100;
288                 }
289                 Ok(format)
290             },
291             None => Err(DefaultFormatError::StreamTypeNotSupported)
292         }
293     }
294 
default_input_format(&self) -> Result<Format, DefaultFormatError>295     pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
296         self.default_format(alsa::SND_PCM_STREAM_CAPTURE)
297     }
298 
default_output_format(&self) -> Result<Format, DefaultFormatError>299     pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
300         self.default_format(alsa::SND_PCM_STREAM_PLAYBACK)
301     }
302 }
303 
304 pub struct EventLoop {
305     // Each newly-created stream gets a new ID from this counter. The counter is then incremented.
306     next_stream_id: AtomicUsize, // TODO: use AtomicU64 when stable?
307 
308     // A trigger that uses a `pipe()` as backend. Signalled whenever a new command is ready, so
309     // that `poll()` can wake up and pick the changes.
310     pending_trigger: Trigger,
311 
312     // This field is locked by the `run()` method.
313     // The mutex also ensures that only one thread at a time has `run()` running.
314     run_context: Mutex<RunContext>,
315 
316     // Commands processed by the `run()` method that is currently running.
317     // TODO: use a lock-free container
318     commands: Mutex<Vec<Command>>,
319 }
320 
321 unsafe impl Send for EventLoop {
322 }
323 
324 unsafe impl Sync for EventLoop {
325 }
326 
327 enum Command {
328     NewStream(StreamInner),
329     PlayStream(StreamId),
330     PauseStream(StreamId),
331     DestroyStream(StreamId),
332 }
333 
334 struct RunContext {
335     // Descriptors to wait for. Always contains `pending_trigger.read_fd()` as first element.
336     descriptors: Vec<libc::pollfd>,
337     // List of streams that are written in `descriptors`.
338     streams: Vec<StreamInner>,
339 }
340 
341 struct StreamInner {
342     // The id of the stream.
343     id: StreamId,
344 
345     // The ALSA channel.
346     channel: *mut alsa::snd_pcm_t,
347 
348     // When converting between file descriptors and `snd_pcm_t`, this is the number of
349     // file descriptors that this `snd_pcm_t` uses.
350     num_descriptors: usize,
351 
352     // Format of the samples.
353     sample_format: SampleFormat,
354 
355     // Number of channels, ie. number of samples per frame.
356     num_channels: u16,
357 
358     // Number of samples that can fit in the buffer.
359     buffer_len: usize,
360 
361     // Minimum number of samples to put in the buffer.
362     period_len: usize,
363 
364     // Whether or not the hardware supports pausing the stream.
365     can_pause: bool,
366 
367     // Whether or not the sample stream is currently paused.
368     is_paused: bool,
369 
370     // A file descriptor opened with `eventfd`.
371     // It is used to wait for resume signal.
372     resume_trigger: Trigger,
373 }
374 
375 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
376 pub struct StreamId(usize);
377 
378 impl EventLoop {
379     #[inline]
new() -> EventLoop380     pub fn new() -> EventLoop {
381         let pending_trigger = Trigger::new();
382 
383         let initial_descriptors = vec![
384             libc::pollfd {
385                 fd: pending_trigger.read_fd(),
386                 events: libc::POLLIN,
387                 revents: 0,
388             },
389         ];
390 
391         let run_context = Mutex::new(RunContext {
392                                          descriptors: initial_descriptors,
393                                          streams: Vec::new(),
394                                      });
395 
396         EventLoop {
397             next_stream_id: AtomicUsize::new(0),
398             pending_trigger: pending_trigger,
399             run_context,
400             commands: Mutex::new(Vec::new()),
401         }
402     }
403 
404     #[inline]
run<F>(&self, mut callback: F) -> ! where F: FnMut(StreamId, StreamData)405     pub fn run<F>(&self, mut callback: F) -> !
406         where F: FnMut(StreamId, StreamData)
407     {
408         self.run_inner(&mut callback)
409     }
410 
run_inner(&self, callback: &mut FnMut(StreamId, StreamData)) -> !411     fn run_inner(&self, callback: &mut FnMut(StreamId, StreamData)) -> ! {
412         unsafe {
413             let mut run_context = self.run_context.lock().unwrap();
414             let run_context = &mut *run_context;
415 
416             loop {
417                 {
418                     let mut commands_lock = self.commands.lock().unwrap();
419                     if !commands_lock.is_empty() {
420                         for command in commands_lock.drain(..) {
421                             match command {
422                                 Command::DestroyStream(stream_id) => {
423                                     run_context.streams.retain(|s| s.id != stream_id);
424                                 },
425                                 Command::PlayStream(stream_id) => {
426                                     if let Some(stream) = run_context.streams.iter_mut()
427                                         .find(|stream| stream.can_pause && stream.id == stream_id)
428                                     {
429                                         alsa::snd_pcm_pause(stream.channel, 0);
430                                         stream.is_paused = false;
431                                     }
432                                 },
433                                 Command::PauseStream(stream_id) => {
434                                     if let Some(stream) = run_context.streams.iter_mut()
435                                         .find(|stream| stream.can_pause && stream.id == stream_id)
436                                     {
437                                         alsa::snd_pcm_pause(stream.channel, 1);
438                                         stream.is_paused = true;
439                                     }
440                                 },
441                                 Command::NewStream(stream_inner) => {
442                                     run_context.streams.push(stream_inner);
443                                 },
444                             }
445                         }
446 
447                         run_context.descriptors = vec![
448                             libc::pollfd {
449                                 fd: self.pending_trigger.read_fd(),
450                                 events: libc::POLLIN,
451                                 revents: 0,
452                             },
453                         ];
454                         for stream in run_context.streams.iter() {
455                             run_context.descriptors.reserve(stream.num_descriptors);
456                             let len = run_context.descriptors.len();
457                             let filled = alsa::snd_pcm_poll_descriptors(stream.channel,
458                                                                         run_context
459                                                                             .descriptors
460                                                                             .as_mut_ptr()
461                                                                             .offset(len as isize),
462                                                                         stream.num_descriptors as
463                                                                             libc::c_uint);
464                             debug_assert_eq!(filled, stream.num_descriptors as libc::c_int);
465                             run_context.descriptors.set_len(len + stream.num_descriptors);
466                         }
467                     }
468                 }
469 
470                 let ret = libc::poll(run_context.descriptors.as_mut_ptr(),
471                                      run_context.descriptors.len() as libc::nfds_t,
472                                      -1 /* infinite */);
473                 assert!(ret >= 0, "poll() failed");
474 
475                 if ret == 0 {
476                     continue;
477                 }
478 
479                 // If the `pending_trigger` was signaled, we need to process the comands.
480                 if run_context.descriptors[0].revents != 0 {
481                     run_context.descriptors[0].revents = 0;
482                     self.pending_trigger.clear_pipe();
483                 }
484 
485                 // Iterate over each individual stream/descriptor.
486                 let mut i_stream = 0;
487                 let mut i_descriptor = 1;
488                 while (i_descriptor as usize) < run_context.descriptors.len() {
489                     enum StreamType { Input, Output }
490                     let stream_type;
491                     let stream_inner = run_context.streams.get_mut(i_stream).unwrap();
492 
493                     // Check whether the event is `POLLOUT` or `POLLIN`. If neither, `continue`.
494                     {
495                         let mut revent = mem::uninitialized();
496 
497                         {
498                             let num_descriptors = stream_inner.num_descriptors as libc::c_uint;
499                             let desc_ptr =
500                                 run_context.descriptors.as_mut_ptr().offset(i_descriptor);
501                             let res = alsa::snd_pcm_poll_descriptors_revents(stream_inner.channel,
502                                                                              desc_ptr,
503                                                                              num_descriptors,
504                                                                              &mut revent);
505                             check_errors(res).unwrap();
506                         }
507 
508                         if revent as i16 == libc::POLLOUT {
509                             stream_type = StreamType::Output;
510                         } else if revent as i16 == libc::POLLIN {
511                             stream_type = StreamType::Input;
512                         } else {
513                             i_descriptor += stream_inner.num_descriptors as isize;
514                             i_stream += 1;
515                             continue;
516                         }
517                     }
518 
519                     // Determine the number of samples that are available to read/write.
520                     let available = {
521                         let available = alsa::snd_pcm_avail(stream_inner.channel); // TODO: what about snd_pcm_avail_update?
522 
523                         if available == -32 {
524                             // buffer underrun
525                             stream_inner.buffer_len
526                         } else if available < 0 {
527                             check_errors(available as libc::c_int)
528                                 .expect("buffer is not available");
529                             unreachable!()
530                         } else {
531                             (available * stream_inner.num_channels as alsa::snd_pcm_sframes_t) as
532                                 usize
533                         }
534                     };
535 
536                     if available < stream_inner.period_len {
537                         i_descriptor += stream_inner.num_descriptors as isize;
538                         i_stream += 1;
539                         continue;
540                     }
541 
542                     let stream_id = stream_inner.id.clone();
543 
544                     match stream_type {
545                         StreamType::Input => {
546                             // Simplify shared logic across the sample format branches.
547                             macro_rules! read_buffer {
548                                 ($T:ty, $Variant:ident) => {{
549                                     // The buffer to read into.
550                                     let mut buffer: Vec<$T> = iter::repeat(mem::uninitialized())
551                                         .take(available)
552                                         .collect();
553                                     let err = alsa::snd_pcm_readi(
554                                         stream_inner.channel,
555                                         buffer.as_mut_ptr() as *mut _,
556                                         available as _,
557                                     );
558                                     check_errors(err as _).expect("snd_pcm_readi error");
559                                     let input_buffer = InputBuffer {
560                                         buffer: &buffer,
561                                     };
562                                     let buffer = UnknownTypeInputBuffer::$Variant(::InputBuffer {
563                                         buffer: Some(input_buffer),
564                                     });
565                                     let stream_data = StreamData::Input { buffer: buffer };
566                                     callback(stream_id, stream_data);
567                                 }};
568                             }
569 
570                             match stream_inner.sample_format {
571                                 SampleFormat::I16 => read_buffer!(i16, I16),
572                                 SampleFormat::U16 => read_buffer!(u16, U16),
573                                 SampleFormat::F32 => read_buffer!(f32, F32),
574                             }
575                         },
576                         StreamType::Output => {
577                             // We're now sure that we're ready to write data.
578                             let buffer = match stream_inner.sample_format {
579                                 SampleFormat::I16 => {
580                                     let buffer = OutputBuffer {
581                                         stream_inner: stream_inner,
582                                         buffer: iter::repeat(mem::uninitialized())
583                                             .take(available)
584                                             .collect(),
585                                     };
586 
587                                     UnknownTypeOutputBuffer::I16(::OutputBuffer { target: Some(buffer) })
588                                 },
589                                 SampleFormat::U16 => {
590                                     let buffer = OutputBuffer {
591                                         stream_inner: stream_inner,
592                                         buffer: iter::repeat(mem::uninitialized())
593                                             .take(available)
594                                             .collect(),
595                                     };
596 
597                                     UnknownTypeOutputBuffer::U16(::OutputBuffer { target: Some(buffer) })
598                                 },
599                                 SampleFormat::F32 => {
600                                     let buffer = OutputBuffer {
601                                         stream_inner: stream_inner,
602                                         // Note that we don't use `mem::uninitialized` because of sNaN.
603                                         buffer: iter::repeat(0.0).take(available).collect(),
604                                     };
605 
606                                     UnknownTypeOutputBuffer::F32(::OutputBuffer { target: Some(buffer) })
607                                 },
608                             };
609 
610                             let stream_data = StreamData::Output { buffer: buffer };
611                             callback(stream_id, stream_data);
612                         },
613                     }
614                 }
615             }
616         }
617     }
618 
build_input_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>619     pub fn build_input_stream(
620         &self,
621         device: &Device,
622         format: &Format,
623     ) -> Result<StreamId, CreationError>
624     {
625         unsafe {
626             let name = ffi::CString::new(device.0.clone()).expect("unable to clone device");
627 
628             let mut capture_handle = mem::uninitialized();
629             match alsa::snd_pcm_open(
630                 &mut capture_handle,
631                 name.as_ptr(),
632                 alsa::SND_PCM_STREAM_CAPTURE,
633                 alsa::SND_PCM_NONBLOCK,
634             ) {
635                 -16 /* determined empirically */ => return Err(CreationError::DeviceNotAvailable),
636                 e => check_errors(e).expect("Device unavailable")
637             }
638             let hw_params = HwParams::alloc();
639 
640             set_hw_params_from_format(capture_handle, &hw_params, format);
641 
642             let can_pause = alsa::snd_pcm_hw_params_can_pause(hw_params.0) == 1;
643 
644             let (buffer_len, period_len) = set_sw_params_from_format(capture_handle, format);
645 
646             check_errors(alsa::snd_pcm_prepare(capture_handle))
647                 .expect("could not get playback handle");
648 
649             let num_descriptors = {
650                 let num_descriptors = alsa::snd_pcm_poll_descriptors_count(capture_handle);
651                 debug_assert!(num_descriptors >= 1);
652                 num_descriptors as usize
653             };
654 
655             let new_stream_id = StreamId(self.next_stream_id.fetch_add(1, Ordering::Relaxed));
656             assert_ne!(new_stream_id.0, usize::max_value()); // check for overflows
657 
658             let stream_inner = StreamInner {
659                 id: new_stream_id.clone(),
660                 channel: capture_handle,
661                 sample_format: format.data_type,
662                 num_descriptors: num_descriptors,
663                 num_channels: format.channels as u16,
664                 buffer_len: buffer_len,
665                 period_len: period_len,
666                 can_pause: can_pause,
667                 is_paused: false,
668                 resume_trigger: Trigger::new(),
669             };
670 
671             check_errors(alsa::snd_pcm_start(capture_handle))
672                 .expect("could not start capture stream");
673 
674             self.push_command(Command::NewStream(stream_inner));
675             Ok(new_stream_id)
676         }
677     }
678 
build_output_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>679     pub fn build_output_stream(
680         &self,
681         device: &Device,
682         format: &Format,
683     ) -> Result<StreamId, CreationError>
684     {
685         unsafe {
686             let name = ffi::CString::new(device.0.clone()).expect("unable to clone device");
687 
688             let mut playback_handle = mem::uninitialized();
689             match alsa::snd_pcm_open(
690                 &mut playback_handle,
691                 name.as_ptr(),
692                 alsa::SND_PCM_STREAM_PLAYBACK,
693                 alsa::SND_PCM_NONBLOCK,
694             ) {
695                 -16 /* determined empirically */ => return Err(CreationError::DeviceNotAvailable),
696                 e => check_errors(e).expect("Device unavailable")
697             }
698             let hw_params = HwParams::alloc();
699 
700             set_hw_params_from_format(playback_handle, &hw_params, format);
701 
702             let can_pause = alsa::snd_pcm_hw_params_can_pause(hw_params.0) == 1;
703 
704             let (buffer_len, period_len) = set_sw_params_from_format(playback_handle, format);
705 
706             check_errors(alsa::snd_pcm_prepare(playback_handle))
707                 .expect("could not get playback handle");
708 
709             let num_descriptors = {
710                 let num_descriptors = alsa::snd_pcm_poll_descriptors_count(playback_handle);
711                 debug_assert!(num_descriptors >= 1);
712                 num_descriptors as usize
713             };
714 
715             let new_stream_id = StreamId(self.next_stream_id.fetch_add(1, Ordering::Relaxed));
716             assert_ne!(new_stream_id.0, usize::max_value()); // check for overflows
717 
718             let stream_inner = StreamInner {
719                 id: new_stream_id.clone(),
720                 channel: playback_handle,
721                 sample_format: format.data_type,
722                 num_descriptors: num_descriptors,
723                 num_channels: format.channels as u16,
724                 buffer_len: buffer_len,
725                 period_len: period_len,
726                 can_pause: can_pause,
727                 is_paused: false,
728                 resume_trigger: Trigger::new(),
729             };
730 
731             self.push_command(Command::NewStream(stream_inner));
732             Ok(new_stream_id)
733         }
734     }
735 
736     #[inline]
push_command(&self, command: Command)737     fn push_command(&self, command: Command) {
738         self.commands.lock().unwrap().push(command);
739         self.pending_trigger.wakeup();
740     }
741 
742     #[inline]
destroy_stream(&self, stream_id: StreamId)743     pub fn destroy_stream(&self, stream_id: StreamId) {
744         self.push_command(Command::DestroyStream(stream_id));
745     }
746 
747     #[inline]
play_stream(&self, stream_id: StreamId)748     pub fn play_stream(&self, stream_id: StreamId) {
749         self.push_command(Command::PlayStream(stream_id));
750     }
751 
752     #[inline]
pause_stream(&self, stream_id: StreamId)753     pub fn pause_stream(&self, stream_id: StreamId) {
754         self.push_command(Command::PauseStream(stream_id));
755     }
756 }
757 
set_hw_params_from_format( pcm_handle: *mut alsa::snd_pcm_t, hw_params: &HwParams, format: &Format, )758 unsafe fn set_hw_params_from_format(
759     pcm_handle: *mut alsa::snd_pcm_t,
760     hw_params: &HwParams,
761     format: &Format,
762 ) {
763     check_errors(alsa::snd_pcm_hw_params_any(pcm_handle, hw_params.0))
764         .expect("Errors on pcm handle");
765     check_errors(alsa::snd_pcm_hw_params_set_access(pcm_handle,
766                                                     hw_params.0,
767                                                     alsa::SND_PCM_ACCESS_RW_INTERLEAVED))
768         .expect("handle not acessible");
769 
770     let data_type = if cfg!(target_endian = "big") {
771         match format.data_type {
772             SampleFormat::I16 => alsa::SND_PCM_FORMAT_S16_BE,
773             SampleFormat::U16 => alsa::SND_PCM_FORMAT_U16_BE,
774             SampleFormat::F32 => alsa::SND_PCM_FORMAT_FLOAT_BE,
775         }
776     } else {
777         match format.data_type {
778             SampleFormat::I16 => alsa::SND_PCM_FORMAT_S16_LE,
779             SampleFormat::U16 => alsa::SND_PCM_FORMAT_U16_LE,
780             SampleFormat::F32 => alsa::SND_PCM_FORMAT_FLOAT_LE,
781         }
782     };
783 
784     check_errors(alsa::snd_pcm_hw_params_set_format(pcm_handle,
785                                                     hw_params.0,
786                                                     data_type))
787         .expect("format could not be set");
788     check_errors(alsa::snd_pcm_hw_params_set_rate(pcm_handle,
789                                                   hw_params.0,
790                                                   format.sample_rate.0 as libc::c_uint,
791                                                   0))
792         .expect("sample rate could not be set");
793     check_errors(alsa::snd_pcm_hw_params_set_channels(pcm_handle,
794                                                       hw_params.0,
795                                                       format.channels as
796                                                           libc::c_uint))
797         .expect("channel count could not be set");
798     let mut max_buffer_size = format.sample_rate.0 as alsa::snd_pcm_uframes_t /
799         format.channels as alsa::snd_pcm_uframes_t /
800         5; // 200ms of buffer
801     check_errors(alsa::snd_pcm_hw_params_set_buffer_size_max(pcm_handle,
802                                                              hw_params.0,
803                                                              &mut max_buffer_size))
804         .unwrap();
805     check_errors(alsa::snd_pcm_hw_params(pcm_handle, hw_params.0))
806         .expect("hardware params could not be set");
807 }
808 
set_sw_params_from_format( pcm_handle: *mut alsa::snd_pcm_t, format: &Format, ) -> (usize, usize)809 unsafe fn set_sw_params_from_format(
810     pcm_handle: *mut alsa::snd_pcm_t,
811     format: &Format,
812 ) -> (usize, usize)
813 {
814     let mut sw_params = mem::uninitialized(); // TODO: RAII
815     check_errors(alsa::snd_pcm_sw_params_malloc(&mut sw_params)).unwrap();
816     check_errors(alsa::snd_pcm_sw_params_current(pcm_handle, sw_params)).unwrap();
817     check_errors(alsa::snd_pcm_sw_params_set_start_threshold(pcm_handle,
818                                                              sw_params,
819                                                              0))
820         .unwrap();
821 
822     let (buffer_len, period_len) = {
823         let mut buffer = mem::uninitialized();
824         let mut period = mem::uninitialized();
825         check_errors(alsa::snd_pcm_get_params(pcm_handle, &mut buffer, &mut period))
826             .expect("could not initialize buffer");
827         assert!(buffer != 0);
828         check_errors(alsa::snd_pcm_sw_params_set_avail_min(pcm_handle,
829                                                            sw_params,
830                                                            period))
831             .unwrap();
832         let buffer = buffer as usize * format.channels as usize;
833         let period = period as usize * format.channels as usize;
834         (buffer, period)
835     };
836 
837     check_errors(alsa::snd_pcm_sw_params(pcm_handle, sw_params)).unwrap();
838     alsa::snd_pcm_sw_params_free(sw_params);
839     (buffer_len, period_len)
840 }
841 
842 pub struct InputBuffer<'a, T: 'a> {
843     buffer: &'a [T],
844 }
845 
846 pub struct OutputBuffer<'a, T: 'a> {
847     stream_inner: &'a mut StreamInner,
848     buffer: Vec<T>,
849 }
850 
851 /// Wrapper around `hw_params`.
852 struct HwParams(*mut alsa::snd_pcm_hw_params_t);
853 
854 impl HwParams {
alloc() -> HwParams855     pub fn alloc() -> HwParams {
856         unsafe {
857             let mut hw_params = mem::uninitialized();
858             check_errors(alsa::snd_pcm_hw_params_malloc(&mut hw_params))
859                 .expect("unable to get hardware parameters");
860             HwParams(hw_params)
861         }
862     }
863 }
864 
865 impl Drop for HwParams {
drop(&mut self)866     fn drop(&mut self) {
867         unsafe {
868             alsa::snd_pcm_hw_params_free(self.0);
869         }
870     }
871 }
872 
873 impl Drop for StreamInner {
874     #[inline]
drop(&mut self)875     fn drop(&mut self) {
876         unsafe {
877             alsa::snd_pcm_close(self.channel);
878         }
879     }
880 }
881 
882 impl<'a, T> InputBuffer<'a, T> {
883     #[inline]
buffer(&self) -> &[T]884     pub fn buffer(&self) -> &[T] {
885         &self.buffer
886     }
887 
888     #[inline]
finish(self)889     pub fn finish(self) {
890         // Nothing to be done.
891     }
892 }
893 
894 impl<'a, T> OutputBuffer<'a, T> {
895     #[inline]
buffer(&mut self) -> &mut [T]896     pub fn buffer(&mut self) -> &mut [T] {
897         &mut self.buffer
898     }
899 
900     #[inline]
len(&self) -> usize901     pub fn len(&self) -> usize {
902         self.buffer.len()
903     }
904 
finish(self)905     pub fn finish(self) {
906         let to_write = (self.buffer.len() / self.stream_inner.num_channels as usize) as
907             alsa::snd_pcm_uframes_t;
908 
909         unsafe {
910             loop {
911                 let result = alsa::snd_pcm_writei(self.stream_inner.channel,
912                                                   self.buffer.as_ptr() as *const _,
913                                                   to_write);
914 
915                 if result == -32 {
916                     // buffer underrun
917                     alsa::snd_pcm_prepare(self.stream_inner.channel);
918                 } else if result < 0 {
919                     check_errors(result as libc::c_int).expect("could not write pcm");
920                 } else {
921                     assert_eq!(result as alsa::snd_pcm_uframes_t, to_write);
922                     break;
923                 }
924             }
925         }
926     }
927 }
928 
929 #[inline]
check_errors(err: libc::c_int) -> Result<(), String>930 fn check_errors(err: libc::c_int) -> Result<(), String> {
931     use std::ffi;
932 
933     if err < 0 {
934         unsafe {
935             let s = ffi::CStr::from_ptr(alsa::snd_strerror(err))
936                 .to_bytes()
937                 .to_vec();
938             let s = String::from_utf8(s).expect("Streaming error occured");
939             return Err(s);
940         }
941     }
942 
943     Ok(())
944 }
945