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