1 //! # How to use cpal
2 //!
3 //! Here are some concepts cpal exposes:
4 //!
5 //! - A `Device` is an audio device that may have any number of input and output streams.
6 //! - A stream is an open audio channel. Input streams allow you to receive audio data, output
7 //!   streams allow you to play audio data. You must choose which `Device` runs your stream before
8 //!   you create one.
9 //! - An `EventLoop` is a collection of streams being run by one or more `Device`. Each stream must
10 //!   belong to an `EventLoop`, and all the streams that belong to an `EventLoop` are managed
11 //!   together.
12 //!
13 //! The first step is to create an `EventLoop`:
14 //!
15 //! ```
16 //! use cpal::EventLoop;
17 //! let event_loop = EventLoop::new();
18 //! ```
19 //!
20 //! Then choose a `Device`. The easiest way is to use the default input or output `Device` via the
21 //! `default_input_device()` or `default_output_device()` functions. Alternatively you can
22 //! enumerate all the available devices with the `devices()` function. Beware that the
23 //! `default_*_device()` functions return an `Option` in case no device is available for that
24 //! stream type on the system.
25 //!
26 //! ```
27 //! let device = cpal::default_output_device().expect("no output device available");
28 //! ```
29 //!
30 //! Before we can create a stream, we must decide what the format of the audio samples is going to
31 //! be. You can query all the supported formats with the `supported_input_formats()` and
32 //! `supported_output_formats()` methods. These produce a list of `SupportedFormat` structs which
33 //! can later be turned into actual `Format` structs. If you don't want to query the list of
34 //! formats, you can also build your own `Format` manually, but doing so could lead to an error
35 //! when building the stream if the format is not supported by the device.
36 //!
37 //! > **Note**: the `supported_formats()` method could return an error for example if the device
38 //! > has been disconnected.
39 //!
40 //! ```no_run
41 //! # let device = cpal::default_output_device().unwrap();
42 //! let mut supported_formats_range = device.supported_output_formats()
43 //!     .expect("error while querying formats");
44 //! let format = supported_formats_range.next()
45 //!     .expect("no supported format?!")
46 //!     .with_max_sample_rate();
47 //! ```
48 //!
49 //! Now that we have everything, we can create a stream from our event loop:
50 //!
51 //! ```no_run
52 //! # let device = cpal::default_output_device().unwrap();
53 //! # let format = device.supported_output_formats().unwrap().next().unwrap().with_max_sample_rate();
54 //! # let event_loop = cpal::EventLoop::new();
55 //! let stream_id = event_loop.build_output_stream(&device, &format).unwrap();
56 //! ```
57 //!
58 //! The value returned by `build_output_stream()` is of type `StreamId` and is an identifier that
59 //! will allow you to control the stream.
60 //!
61 //! Now we must start the stream. This is done with the `play_stream()` method on the event loop.
62 //!
63 //! ```
64 //! # let event_loop: cpal::EventLoop = return;
65 //! # let stream_id: cpal::StreamId = return;
66 //! event_loop.play_stream(stream_id);
67 //! ```
68 //!
69 //! Once everything is ready! Now we call `run()` on the `event_loop` to begin processing.
70 //!
71 //! ```no_run
72 //! # let event_loop = cpal::EventLoop::new();
73 //! event_loop.run(move |_stream_id, _stream_data| {
74 //!     // read or write stream data here
75 //! });
76 //! ```
77 //!
78 //! > **Note**: Calling `run()` will block the thread forever, so it's usually best done in a
79 //! > separate thread.
80 //!
81 //! While `run()` is running, the audio device of the user will from time to time call the callback
82 //! that you passed to this function. The callback gets passed the stream ID an instance of type
83 //! `StreamData` that represents the data that must be read from or written to. The inner
84 //! `UnknownTypeOutputBuffer` can be one of `I16`, `U16` or `F32` depending on the format that was
85 //! passed to `build_output_stream`.
86 //!
87 //! In this example, we simply simply fill the given output buffer with zeroes.
88 //!
89 //! ```no_run
90 //! use cpal::{StreamData, UnknownTypeOutputBuffer};
91 //!
92 //! # let event_loop = cpal::EventLoop::new();
93 //! event_loop.run(move |_stream_id, mut stream_data| {
94 //!     match stream_data {
95 //!         StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => {
96 //!             for elem in buffer.iter_mut() {
97 //!                 *elem = u16::max_value() / 2;
98 //!             }
99 //!         },
100 //!         StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => {
101 //!             for elem in buffer.iter_mut() {
102 //!                 *elem = 0;
103 //!             }
104 //!         },
105 //!         StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => {
106 //!             for elem in buffer.iter_mut() {
107 //!                 *elem = 0.0;
108 //!             }
109 //!         },
110 //!         _ => (),
111 //!     }
112 //! });
113 //! ```
114 
115 #![recursion_limit = "512"]
116 
117 #[cfg(target_os = "windows")]
118 #[macro_use]
119 extern crate lazy_static;
120 
121 // Extern crate declarations with `#[macro_use]` must unfortunately be at crate root.
122 #[cfg(target_os = "emscripten")]
123 #[macro_use]
124 extern crate stdweb;
125 
126 pub use samples_formats::{Sample, SampleFormat};
127 
128 #[cfg(not(any(windows, target_os = "linux", target_os = "freebsd",
129               target_os = "macos", target_os = "ios", target_os = "emscripten")))]
130 use null as cpal_impl;
131 
132 use std::error::Error;
133 use std::fmt;
134 use std::iter;
135 use std::ops::{Deref, DerefMut};
136 
137 mod null;
138 mod samples_formats;
139 
140 #[cfg(any(target_os = "linux", target_os = "freebsd"))]
141 #[path = "alsa/mod.rs"]
142 mod cpal_impl;
143 
144 #[cfg(windows)]
145 #[path = "wasapi/mod.rs"]
146 mod cpal_impl;
147 
148 #[cfg(any(target_os = "macos", target_os = "ios"))]
149 #[path = "coreaudio/mod.rs"]
150 mod cpal_impl;
151 
152 #[cfg(target_os = "emscripten")]
153 #[path = "emscripten/mod.rs"]
154 mod cpal_impl;
155 
156 /// An opaque type that identifies a device that is capable of either audio input or output.
157 ///
158 /// Please note that `Device`s may become invalid if they get disconnected. Therefore all the
159 /// methods that involve a device return a `Result`.
160 #[derive(Clone, PartialEq, Eq)]
161 pub struct Device(cpal_impl::Device);
162 
163 /// Collection of voices managed together.
164 ///
165 /// Created with the [`new`](struct.EventLoop.html#method.new) method.
166 pub struct EventLoop(cpal_impl::EventLoop);
167 
168 /// Identifier of a stream within the `EventLoop`.
169 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
170 pub struct StreamId(cpal_impl::StreamId);
171 
172 /// Number of channels.
173 pub type ChannelCount = u16;
174 
175 /// The number of samples processed per second for a single channel of audio.
176 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
177 pub struct SampleRate(pub u32);
178 
179 /// The format of an input or output audio stream.
180 #[derive(Debug, Clone, PartialEq, Eq)]
181 pub struct Format {
182     pub channels: ChannelCount,
183     pub sample_rate: SampleRate,
184     pub data_type: SampleFormat,
185 }
186 
187 /// Describes a range of supported stream formats.
188 #[derive(Debug, Clone, PartialEq, Eq)]
189 pub struct SupportedFormat {
190     pub channels: ChannelCount,
191     /// Minimum value for the samples rate of the supported formats.
192     pub min_sample_rate: SampleRate,
193     /// Maximum value for the samples rate of the supported formats.
194     pub max_sample_rate: SampleRate,
195     /// Type of data expected by the device.
196     pub data_type: SampleFormat,
197 }
198 
199 /// Stream data passed to the `EventLoop::run` callback.
200 pub enum StreamData<'a> {
201     Input {
202         buffer: UnknownTypeInputBuffer<'a>,
203     },
204     Output {
205         buffer: UnknownTypeOutputBuffer<'a>,
206     },
207 }
208 
209 /// Represents a buffer containing audio data that may be read.
210 ///
211 /// This struct implements the `Deref` trait targeting `[T]`. Therefore this buffer can be read the
212 /// same way as reading from a `Vec` or any other kind of Rust array.
213 // TODO: explain audio stuff in general
214 pub struct InputBuffer<'a, T: 'a>
215 where
216     T: Sample,
217 {
218     // Always contains something, taken by `Drop`
219     // TODO: change that
220     buffer: Option<cpal_impl::InputBuffer<'a, T>>,
221 }
222 
223 /// Represents a buffer that must be filled with audio data.
224 ///
225 /// You should destroy this object as soon as possible. Data is only sent to the audio device when
226 /// this object is destroyed.
227 ///
228 /// This struct implements the `Deref` and `DerefMut` traits to `[T]`. Therefore writing to this
229 /// buffer is done in the same way as writing to a `Vec` or any other kind of Rust array.
230 // TODO: explain audio stuff in general
231 #[must_use]
232 pub struct OutputBuffer<'a, T: 'a>
233 where
234     T: Sample,
235 {
236     // Always contains something, taken by `Drop`
237     // TODO: change that
238     target: Option<cpal_impl::OutputBuffer<'a, T>>,
239 }
240 
241 /// This is the struct that is provided to you by cpal when you want to read samples from a buffer.
242 ///
243 /// Since the type of data is only known at runtime, you have to read the right buffer.
244 pub enum UnknownTypeInputBuffer<'a> {
245     /// Samples whose format is `u16`.
246     U16(InputBuffer<'a, u16>),
247     /// Samples whose format is `i16`.
248     I16(InputBuffer<'a, i16>),
249     /// Samples whose format is `f32`.
250     F32(InputBuffer<'a, f32>),
251 }
252 
253 /// This is the struct that is provided to you by cpal when you want to write samples to a buffer.
254 ///
255 /// Since the type of data is only known at runtime, you have to fill the right buffer.
256 pub enum UnknownTypeOutputBuffer<'a> {
257     /// Samples whose format is `u16`.
258     U16(OutputBuffer<'a, u16>),
259     /// Samples whose format is `i16`.
260     I16(OutputBuffer<'a, i16>),
261     /// Samples whose format is `f32`.
262     F32(OutputBuffer<'a, f32>),
263 }
264 
265 /// An iterator yielding all `Device`s currently available to the system.
266 ///
267 /// See [`devices()`](fn.devices.html).
268 pub struct Devices(cpal_impl::Devices);
269 
270 /// A `Devices` yielding only *input* devices.
271 pub type InputDevices = iter::Filter<Devices, fn(&Device) -> bool>;
272 
273 /// A `Devices` yielding only *output* devices.
274 pub type OutputDevices = iter::Filter<Devices, fn(&Device) -> bool>;
275 
276 /// An iterator that produces a list of input stream formats supported by the device.
277 ///
278 /// See [`Device::supported_input_formats()`](struct.Device.html#method.supported_input_formats).
279 pub struct SupportedInputFormats(cpal_impl::SupportedInputFormats);
280 
281 /// An iterator that produces a list of output stream formats supported by the device.
282 ///
283 /// See [`Device::supported_output_formats()`](struct.Device.html#method.supported_output_formats).
284 pub struct SupportedOutputFormats(cpal_impl::SupportedOutputFormats);
285 
286 /// Error that can happen when enumerating the list of supported formats.
287 #[derive(Debug)]
288 pub enum FormatsEnumerationError {
289     /// The device no longer exists. This can happen if the device is disconnected while the
290     /// program is running.
291     DeviceNotAvailable,
292 }
293 
294 /// May occur when attempting to request the default input or output stream format from a `Device`.
295 #[derive(Debug)]
296 pub enum DefaultFormatError {
297     /// The device no longer exists. This can happen if the device is disconnected while the
298     /// program is running.
299     DeviceNotAvailable,
300     /// Returned if e.g. the default input format was requested on an output-only audio device.
301     StreamTypeNotSupported,
302 }
303 
304 /// Error that can happen when creating a `Voice`.
305 #[derive(Debug)]
306 pub enum CreationError {
307     /// The device no longer exists. This can happen if the device is disconnected while the
308     /// program is running.
309     DeviceNotAvailable,
310     /// The required format is not supported.
311     FormatNotSupported,
312 }
313 
314 /// An iterator yielding all `Device`s currently available to the system.
315 ///
316 /// Can be empty if the system does not support audio in general.
317 #[inline]
devices() -> Devices318 pub fn devices() -> Devices {
319     Devices(Default::default())
320 }
321 
322 /// An iterator yielding all `Device`s currently available to the system that support one or more
323 /// input stream formats.
324 ///
325 /// Can be empty if the system does not support audio input.
input_devices() -> InputDevices326 pub fn input_devices() -> InputDevices {
327     fn supports_input(device: &Device) -> bool {
328         device.supported_input_formats()
329             .map(|mut iter| iter.next().is_some())
330             .unwrap_or(false)
331     }
332     devices().filter(supports_input)
333 }
334 
335 /// An iterator yielding all `Device`s currently available to the system that support one or more
336 /// output stream formats.
337 ///
338 /// Can be empty if the system does not support audio output.
output_devices() -> OutputDevices339 pub fn output_devices() -> OutputDevices {
340     fn supports_output(device: &Device) -> bool {
341         device.supported_output_formats()
342             .map(|mut iter| iter.next().is_some())
343             .unwrap_or(false)
344     }
345     devices().filter(supports_output)
346 }
347 
348 /// The default input audio device on the system.
349 ///
350 /// Returns `None` if no input device is available.
default_input_device() -> Option<Device>351 pub fn default_input_device() -> Option<Device> {
352     cpal_impl::default_input_device().map(Device)
353 }
354 
355 /// The default output audio device on the system.
356 ///
357 /// Returns `None` if no output device is available.
default_output_device() -> Option<Device>358 pub fn default_output_device() -> Option<Device> {
359     cpal_impl::default_output_device().map(Device)
360 }
361 
362 impl Device {
363     /// The human-readable name of the device.
364     #[inline]
name(&self) -> String365     pub fn name(&self) -> String {
366         self.0.name()
367     }
368 
369     /// An iterator yielding formats that are supported by the backend.
370     ///
371     /// Can return an error if the device is no longer valid (eg. it has been disconnected).
372     #[inline]
supported_input_formats(&self) -> Result<SupportedInputFormats, FormatsEnumerationError>373     pub fn supported_input_formats(&self) -> Result<SupportedInputFormats, FormatsEnumerationError> {
374         Ok(SupportedInputFormats(self.0.supported_input_formats()?))
375     }
376 
377     /// An iterator yielding output stream formats that are supported by the device.
378     ///
379     /// Can return an error if the device is no longer valid (eg. it has been disconnected).
380     #[inline]
supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError>381     pub fn supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError> {
382         Ok(SupportedOutputFormats(self.0.supported_output_formats()?))
383     }
384 
385     /// The default input stream format for the device.
386     #[inline]
default_input_format(&self) -> Result<Format, DefaultFormatError>387     pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
388         self.0.default_input_format()
389     }
390 
391     /// The default output stream format for the device.
392     #[inline]
default_output_format(&self) -> Result<Format, DefaultFormatError>393     pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
394         self.0.default_output_format()
395     }
396 }
397 
398 impl EventLoop {
399     /// Initializes a new events loop.
400     #[inline]
new() -> EventLoop401     pub fn new() -> EventLoop {
402         EventLoop(cpal_impl::EventLoop::new())
403     }
404 
405     /// Creates a new input stream that will run from the given device and with the given format.
406     ///
407     /// On success, returns an identifier for the stream.
408     ///
409     /// Can return an error if the device is no longer valid, or if the input stream format is not
410     /// supported by the device.
411     #[inline]
build_input_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>412     pub fn build_input_stream(
413         &self,
414         device: &Device,
415         format: &Format,
416     ) -> Result<StreamId, CreationError>
417     {
418         self.0.build_input_stream(&device.0, format).map(StreamId)
419     }
420 
421     /// Creates a new output stream that will play on the given device and with the given format.
422     ///
423     /// On success, returns an identifier for the stream.
424     ///
425     /// Can return an error if the device is no longer valid, or if the output stream format is not
426     /// supported by the device.
427     #[inline]
build_output_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>428     pub fn build_output_stream(
429         &self,
430         device: &Device,
431         format: &Format,
432     ) -> Result<StreamId, CreationError>
433     {
434         self.0.build_output_stream(&device.0, format).map(StreamId)
435     }
436 
437     /// Instructs the audio device that it should start playing the stream with the given ID.
438     ///
439     /// Has no effect is the stream was already playing.
440     ///
441     /// Only call this after you have submitted some data, otherwise you may hear some glitches.
442     ///
443     /// # Panic
444     ///
445     /// If the stream does not exist, this function can either panic or be a no-op.
446     ///
447     #[inline]
play_stream(&self, stream: StreamId)448     pub fn play_stream(&self, stream: StreamId) {
449         self.0.play_stream(stream.0)
450     }
451 
452     /// Instructs the audio device that it should stop playing the stream with the given ID.
453     ///
454     /// Has no effect is the stream was already paused.
455     ///
456     /// If you call `play` afterwards, the playback will resume where it was.
457     ///
458     /// # Panic
459     ///
460     /// If the stream does not exist, this function can either panic or be a no-op.
461     ///
462     #[inline]
pause_stream(&self, stream: StreamId)463     pub fn pause_stream(&self, stream: StreamId) {
464         self.0.pause_stream(stream.0)
465     }
466 
467     /// Destroys an existing stream.
468     ///
469     /// # Panic
470     ///
471     /// If the stream does not exist, this function can either panic or be a no-op.
472     ///
473     #[inline]
destroy_stream(&self, stream_id: StreamId)474     pub fn destroy_stream(&self, stream_id: StreamId) {
475         self.0.destroy_stream(stream_id.0)
476     }
477 
478     /// Takes control of the current thread and begins the stream processing.
479     ///
480     /// > **Note**: Since it takes control of the thread, this method is best called on a separate
481     /// > thread.
482     ///
483     /// Whenever a stream needs to be fed some data, the closure passed as parameter is called.
484     /// You can call the other methods of `EventLoop` without getting a deadlock.
485     #[inline]
run<F>(&self, mut callback: F) -> ! where F: FnMut(StreamId, StreamData) + Send486     pub fn run<F>(&self, mut callback: F) -> !
487         where F: FnMut(StreamId, StreamData) + Send
488     {
489         self.0.run(move |id, data| callback(StreamId(id), data))
490     }
491 }
492 
493 impl SupportedFormat {
494     /// Turns this `SupportedFormat` into a `Format` corresponding to the maximum samples rate.
495     #[inline]
with_max_sample_rate(self) -> Format496     pub fn with_max_sample_rate(self) -> Format {
497         Format {
498             channels: self.channels,
499             sample_rate: self.max_sample_rate,
500             data_type: self.data_type,
501         }
502     }
503 
504     /// A comparison function which compares two `SupportedFormat`s in terms of their priority of
505     /// use as a default stream format.
506     ///
507     /// Some backends do not provide a default stream format for their audio devices. In these
508     /// cases, CPAL attempts to decide on a reasonable default format for the user. To do this we
509     /// use the "greatest" of all supported stream formats when compared with this method.
510     ///
511     /// Formats are prioritised by the following heuristics:
512     ///
513     /// **Channels**:
514     ///
515     /// - Stereo
516     /// - Mono
517     /// - Max available channels
518     ///
519     /// **Sample format**:
520     /// - f32
521     /// - i16
522     /// - u16
523     ///
524     /// **Sample rate**:
525     ///
526     /// - 44100 (cd quality)
527     /// - Max sample rate
cmp_default_heuristics(&self, other: &Self) -> std::cmp::Ordering528     pub fn cmp_default_heuristics(&self, other: &Self) -> std::cmp::Ordering {
529         use std::cmp::Ordering::Equal;
530         use SampleFormat::{F32, I16, U16};
531 
532         let cmp_stereo = (self.channels == 2).cmp(&(other.channels == 2));
533         if cmp_stereo != Equal {
534             return cmp_stereo;
535         }
536 
537         let cmp_mono = (self.channels == 1).cmp(&(other.channels == 1));
538         if cmp_mono != Equal {
539             return cmp_mono;
540         }
541 
542         let cmp_channels = self.channels.cmp(&other.channels);
543         if cmp_channels != Equal {
544             return cmp_channels;
545         }
546 
547         let cmp_f32 = (self.data_type == F32).cmp(&(other.data_type == F32));
548         if cmp_f32 != Equal {
549             return cmp_f32;
550         }
551 
552         let cmp_i16 = (self.data_type == I16).cmp(&(other.data_type == I16));
553         if cmp_i16 != Equal {
554             return cmp_i16;
555         }
556 
557         let cmp_u16 = (self.data_type == U16).cmp(&(other.data_type == U16));
558         if cmp_u16 != Equal {
559             return cmp_u16;
560         }
561 
562         const HZ_44100: SampleRate = SampleRate(44_100);
563         let r44100_in_self = self.min_sample_rate <= HZ_44100
564             && HZ_44100 <= self.max_sample_rate;
565         let r44100_in_other = other.min_sample_rate <= HZ_44100
566             && HZ_44100 <= other.max_sample_rate;
567         let cmp_r44100 = r44100_in_self.cmp(&r44100_in_other);
568         if cmp_r44100 != Equal {
569             return cmp_r44100;
570         }
571 
572         self.max_sample_rate.cmp(&other.max_sample_rate)
573     }
574 }
575 
576 impl<'a, T> Deref for InputBuffer<'a, T>
577     where T: Sample
578 {
579     type Target = [T];
580 
581     #[inline]
deref(&self) -> &[T]582     fn deref(&self) -> &[T] {
583         self.buffer.as_ref().unwrap().buffer()
584     }
585 }
586 
587 impl<'a, T> Drop for InputBuffer<'a, T>
588     where T: Sample
589 {
590     #[inline]
drop(&mut self)591     fn drop(&mut self) {
592         self.buffer.take().unwrap().finish();
593     }
594 }
595 
596 impl<'a, T> Deref for OutputBuffer<'a, T>
597     where T: Sample
598 {
599     type Target = [T];
600 
601     #[inline]
deref(&self) -> &[T]602     fn deref(&self) -> &[T] {
603         panic!("It is forbidden to read from the audio buffer");
604     }
605 }
606 
607 impl<'a, T> DerefMut for OutputBuffer<'a, T>
608     where T: Sample
609 {
610     #[inline]
deref_mut(&mut self) -> &mut [T]611     fn deref_mut(&mut self) -> &mut [T] {
612         self.target.as_mut().unwrap().buffer()
613     }
614 }
615 
616 impl<'a, T> Drop for OutputBuffer<'a, T>
617     where T: Sample
618 {
619     #[inline]
drop(&mut self)620     fn drop(&mut self) {
621         self.target.take().unwrap().finish();
622     }
623 }
624 
625 impl<'a> UnknownTypeInputBuffer<'a> {
626     /// Returns the length of the buffer in number of samples.
627     #[inline]
len(&self) -> usize628     pub fn len(&self) -> usize {
629         match self {
630             &UnknownTypeInputBuffer::U16(ref buf) => buf.len(),
631             &UnknownTypeInputBuffer::I16(ref buf) => buf.len(),
632             &UnknownTypeInputBuffer::F32(ref buf) => buf.len(),
633         }
634     }
635 }
636 
637 impl<'a> UnknownTypeOutputBuffer<'a> {
638     /// Returns the length of the buffer in number of samples.
639     #[inline]
len(&self) -> usize640     pub fn len(&self) -> usize {
641         match self {
642             &UnknownTypeOutputBuffer::U16(ref buf) => buf.target.as_ref().unwrap().len(),
643             &UnknownTypeOutputBuffer::I16(ref buf) => buf.target.as_ref().unwrap().len(),
644             &UnknownTypeOutputBuffer::F32(ref buf) => buf.target.as_ref().unwrap().len(),
645         }
646     }
647 }
648 
649 impl From<Format> for SupportedFormat {
650     #[inline]
from(format: Format) -> SupportedFormat651     fn from(format: Format) -> SupportedFormat {
652         SupportedFormat {
653             channels: format.channels,
654             min_sample_rate: format.sample_rate,
655             max_sample_rate: format.sample_rate,
656             data_type: format.data_type,
657         }
658     }
659 }
660 
661 impl Iterator for Devices {
662     type Item = Device;
663 
664     #[inline]
next(&mut self) -> Option<Self::Item>665     fn next(&mut self) -> Option<Self::Item> {
666         self.0.next().map(Device)
667     }
668 
669     #[inline]
size_hint(&self) -> (usize, Option<usize>)670     fn size_hint(&self) -> (usize, Option<usize>) {
671         self.0.size_hint()
672     }
673 }
674 
675 impl Iterator for SupportedInputFormats {
676     type Item = SupportedFormat;
677 
678     #[inline]
next(&mut self) -> Option<SupportedFormat>679     fn next(&mut self) -> Option<SupportedFormat> {
680         self.0.next()
681     }
682 
683     #[inline]
size_hint(&self) -> (usize, Option<usize>)684     fn size_hint(&self) -> (usize, Option<usize>) {
685         self.0.size_hint()
686     }
687 }
688 
689 impl Iterator for SupportedOutputFormats {
690     type Item = SupportedFormat;
691 
692     #[inline]
next(&mut self) -> Option<SupportedFormat>693     fn next(&mut self) -> Option<SupportedFormat> {
694         self.0.next()
695     }
696 
697     #[inline]
size_hint(&self) -> (usize, Option<usize>)698     fn size_hint(&self) -> (usize, Option<usize>) {
699         self.0.size_hint()
700     }
701 }
702 
703 impl fmt::Display for FormatsEnumerationError {
704     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>705     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
706         write!(fmt, "{}", self.description())
707     }
708 }
709 
710 impl Error for FormatsEnumerationError {
711     #[inline]
description(&self) -> &str712     fn description(&self) -> &str {
713         match self {
714             &FormatsEnumerationError::DeviceNotAvailable => {
715                 "The requested device is no longer available (for example, it has been unplugged)."
716             },
717         }
718     }
719 }
720 
721 impl fmt::Display for CreationError {
722     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>723     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
724         write!(fmt, "{}", self.description())
725     }
726 }
727 
728 impl Error for CreationError {
729     #[inline]
description(&self) -> &str730     fn description(&self) -> &str {
731         match self {
732             &CreationError::DeviceNotAvailable => {
733                 "The requested device is no longer available (for example, it has been unplugged)."
734             },
735 
736             &CreationError::FormatNotSupported => {
737                 "The requested samples format is not supported by the device."
738             },
739         }
740     }
741 }
742 
743 impl fmt::Display for DefaultFormatError {
744     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>745     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
746         write!(fmt, "{}", self.description())
747     }
748 }
749 
750 impl Error for DefaultFormatError {
751     #[inline]
description(&self) -> &str752     fn description(&self) -> &str {
753         match self {
754             &DefaultFormatError::DeviceNotAvailable => {
755                 CreationError::DeviceNotAvailable.description()
756             },
757 
758             &DefaultFormatError::StreamTypeNotSupported => {
759                 "The requested stream type is not supported by the device."
760             },
761         }
762     }
763 }
764 
765 // If a backend does not provide an API for retrieving supported formats, we query it with a bunch
766 // of commonly used rates. This is always the case for wasapi and is sometimes the case for alsa.
767 //
768 // If a rate you desire is missing from this list, feel free to add it!
769 #[cfg(target_os = "windows")]
770 const COMMON_SAMPLE_RATES: &'static [SampleRate] = &[
771     SampleRate(5512),
772     SampleRate(8000),
773     SampleRate(11025),
774     SampleRate(16000),
775     SampleRate(22050),
776     SampleRate(32000),
777     SampleRate(44100),
778     SampleRate(48000),
779     SampleRate(64000),
780     SampleRate(88200),
781     SampleRate(96000),
782     SampleRate(176400),
783     SampleRate(192000),
784 ];
785