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