Update docs for removal of the `EventLoop`

This commit is contained in:
mitchmindtree 2019-12-14 17:30:25 +01:00
parent 27245444a7
commit f34a062fac
2 changed files with 93 additions and 79 deletions

View File

@ -7,25 +7,21 @@
//! least one [**DefaultHost**](./struct.Host.html) that is guaranteed to be available. //! least one [**DefaultHost**](./struct.Host.html) that is guaranteed to be available.
//! - A [**Device**](./struct.Device.html) is an audio device that may have any number of input and //! - A [**Device**](./struct.Device.html) is an audio device that may have any number of input and
//! output streams. //! output streams.
//! - A stream is an open flow of audio data. Input streams allow you to receive audio data, output //! - A [**Stream**](./trait.Stream.html) is an open flow of audio data. Input streams allow you to
//! streams allow you to play audio data. You must choose which **Device** will run your stream //! receive audio data, output streams allow you to play audio data. You must choose which
//! before you can create one. Often, a default device can be retrieved via the **Host**. //! **Device** will run your stream before you can create one. Often, a default device can be
//! - An [**EventLoop**](./struct.EventLoop.html) is a collection of streams being run by one or //! retrieved via the **Host**.
//! more **Device**s under a single **Host**. Each stream must belong to an **EventLoop**, and
//! all the streams that belong to an **EventLoop** are managed together.
//! //!
//! The first step is to initialise the `Host` (for accessing audio devices) and create an //! The first step is to initialise the `Host`:
//! `EventLoop`:
//! //!
//! ``` //! ```
//! use cpal::traits::HostTrait; //! use cpal::traits::HostTrait;
//! let host = cpal::default_host(); //! let host = cpal::default_host();
//! let event_loop = host.event_loop();
//! ``` //! ```
//! //!
//! Then choose a `Device`. The easiest way is to use the default input or output `Device` via the //! Then choose an available `Device`. The easiest way is to use the default input or output
//! `default_input_device()` or `default_output_device()` functions. Alternatively you can //! `Device` via the `default_input_device()` or `default_output_device()` functions. Alternatively
//! enumerate all the available devices with the `devices()` function. Beware that the //! you can enumerate all the available devices with the `devices()` function. Beware that the
//! `default_*_device()` functions return an `Option` in case no device is available for that //! `default_*_device()` functions return an `Option` in case no device is available for that
//! stream type on the system. //! stream type on the system.
//! //!
@ -56,87 +52,96 @@
//! .with_max_sample_rate(); //! .with_max_sample_rate();
//! ``` //! ```
//! //!
//! Now that we have everything for the stream, we can create it from our event loop: //! Now that we have everything for the stream, we are ready to create it from our selected device:
//! //!
//! ```no_run //! ```no_run
//! use cpal::traits::{DeviceTrait, EventLoopTrait, HostTrait}; //! use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host(); //! # let host = cpal::default_host();
//! # let event_loop = host.event_loop();
//! # let device = host.default_output_device().unwrap(); //! # let device = host.default_output_device().unwrap();
//! # let format = device.supported_output_formats().unwrap().next().unwrap().with_max_sample_rate(); //! # let format = device.default_output_format().unwrap();
//! let stream_id = event_loop.build_output_stream(&device, &format).unwrap(); //! let stream = device.build_output_stream(
//! &format,
//! move |data| {
//! // react to stream events and read or write stream data here.
//! },
//! move |err| {
//! // react to errors here.
//! },
//! );
//! ``` //! ```
//! //!
//! The value returned by `build_output_stream()` is of type `StreamId` and is an identifier that //! While the stream is running, the selected audio device will periodically call the data callback
//! will allow you to control the stream. //! that was passed to the function. The callback is passed an instance of type `StreamData` that
//! represents the data that must be read from or written to. The inner `UnknownTypeOutputBuffer`
//! can be one of `I16`, `U16` or `F32` depending on the format that was passed to
//! `build_output_stream`.
//! //!
//! Now we must start the stream. This is done with the `play_stream()` method on the event loop. //! > **Note**: Creating and running a stream will *not* block the thread. On modern platforms, the
//! //! > given callback is called by a dedicated, high-priority thread responsible for delivering
//! ```no_run //! > audio data to the system's audio device in a timely manner. On older platforms that only
//! # use cpal::traits::{EventLoopTrait, HostTrait}; //! > provide a blocking API (e.g. ALSA), CPAL will create a thread in order to consistently
//! # let host = cpal::default_host(); //! > provide non-blocking behaviour. *If this is an issue for your platform or design, please
//! # let event_loop = host.event_loop(); //! > share your issue and use-case with the CPAL team on the github issue tracker for
//! # let stream_id = unimplemented!(); //! > consideration.*
//! event_loop.play_stream(stream_id).expect("failed to play_stream");
//! ```
//!
//! Now everything is ready! We call `run()` on the `event_loop` to begin processing.
//!
//! ```no_run
//! # use cpal::traits::{EventLoopTrait, HostTrait};
//! # let host = cpal::default_host();
//! # let event_loop = host.event_loop();
//! event_loop.run(move |_stream_id, _stream_result| {
//! // react to stream events and read or write stream data here
//! });
//! ```
//!
//! > **Note**: Calling `run()` will block the thread forever, so it's usually best done in a
//! > separate thread.
//!
//! While `run()` is running, the audio device of the user will from time to time call the callback
//! that you passed to this function. The callback gets passed the stream ID and an instance of type
//! `StreamData` that represents the data that must be read from or written to. The inner
//! `UnknownTypeOutputBuffer` can be one of `I16`, `U16` or `F32` depending on the format that was
//! passed to `build_output_stream`.
//! //!
//! In this example, we simply fill the given output buffer with zeroes. //! In this example, we simply fill the given output buffer with zeroes.
//! //!
//! ```no_run //! ```no_run
//! use cpal::{StreamData, UnknownTypeOutputBuffer}; //! use cpal::{StreamData, UnknownTypeOutputBuffer};
//! use cpal::traits::{EventLoopTrait, HostTrait}; //! use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host(); //! # let host = cpal::default_host();
//! # let event_loop = host.event_loop(); //! # let device = host.default_output_device().unwrap();
//! event_loop.run(move |stream_id, stream_result| { //! # let format = device.default_output_format().unwrap();
//! let stream_data = match stream_result { //! let stream = device.build_output_stream(
//! Ok(data) => data, //! &format,
//! Err(err) => { //! move |data| {
//! eprintln!("an error occurred on stream {:?}: {}", stream_id, err); //! match data {
//! return; //! StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => {
//! for elem in buffer.iter_mut() {
//! *elem = u16::max_value() / 2;
//! }
//! },
//! StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => {
//! for elem in buffer.iter_mut() {
//! *elem = 0;
//! }
//! },
//! StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => {
//! for elem in buffer.iter_mut() {
//! *elem = 0.0;
//! }
//! },
//! _ => (),
//! } //! }
//! _ => return, //! },
//! }; //! move |err| {
//! //! eprintln!("an error occurred on the output audio stream: {}", err);
//! match stream_data { //! },
//! StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => { //! );
//! for elem in buffer.iter_mut() {
//! *elem = u16::max_value() / 2;
//! }
//! },
//! StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => {
//! for elem in buffer.iter_mut() {
//! *elem = 0;
//! }
//! },
//! StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => {
//! for elem in buffer.iter_mut() {
//! *elem = 0.0;
//! }
//! },
//! _ => (),
//! }
//! });
//! ``` //! ```
//!
//! Not all platforms automatically run the stream upon creation. To ensure the stream has started,
//! we can use `Stream::play`.
//!
//! ```no_run
//! # use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host();
//! # let device = host.default_output_device().unwrap();
//! # let format = device.default_output_format().unwrap();
//! # let stream = device.build_output_stream(&format, move |_data| {}, move |_err| {}).unwrap();
//! stream.play().unwrap();
//! ```
//!
//! Some devices support pausing the audio stream. This can be useful for saving energy in moments
//! of silence.
//!
//! ```no_run
//! # use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host();
//! # let device = host.default_output_device().unwrap();
//! # let format = device.default_output_format().unwrap();
//! # let stream = device.build_output_stream(&format, move |_data| {}, move |_err| {}).unwrap();
//! stream.pause().unwrap();
#![recursion_limit = "512"] #![recursion_limit = "512"]

View File

@ -128,7 +128,16 @@ pub trait DeviceTrait {
/// A stream created from `Device`, with methods to control playback. /// A stream created from `Device`, with methods to control playback.
pub trait StreamTrait { pub trait StreamTrait {
/// Run the stream.
///
/// Note: Not all platforms automatically run the stream upon creation, so it is important to
/// call `play` after creation if it is expected that the stream should run immediately.
fn play(&self) -> Result<(), PlayStreamError>; fn play(&self) -> Result<(), PlayStreamError>;
/// Some devices support pausing the audio stream. This can be useful for saving energy in
/// moments of silence.
///
/// Note: Not all devices support suspending the stream at the hardware level. This method may
/// fail in these cases.
fn pause(&self) -> Result<(), PauseStreamError>; fn pause(&self) -> Result<(), PauseStreamError>;
} }