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.
//! - A [**Device**](./struct.Device.html) is an audio device that may have any number of input and
//! output streams.
//! - A stream is an open flow of audio data. Input streams allow you to receive audio data, output
//! streams allow you to play audio data. You must choose which **Device** will run your stream
//! before you can create one. Often, a default device can be retrieved via the **Host**.
//! - An [**EventLoop**](./struct.EventLoop.html) is a collection of streams being run by one or
//! 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.
//! - A [**Stream**](./trait.Stream.html) is an open flow of audio data. Input streams allow you to
//! receive audio data, output streams allow you to play audio data. You must choose which
//! **Device** will run your stream before you can create one. Often, a default device can be
//! retrieved via the **Host**.
//!
//! The first step is to initialise the `Host` (for accessing audio devices) and create an
//! `EventLoop`:
//! The first step is to initialise the `Host`:
//!
//! ```
//! use cpal::traits::HostTrait;
//! 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
//! `default_input_device()` or `default_output_device()` functions. Alternatively you can
//! enumerate all the available devices with the `devices()` function. Beware that the
//! Then choose an available `Device`. The easiest way is to use the default input or output
//! `Device` via the `default_input_device()` or `default_output_device()` functions. Alternatively
//! 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
//! stream type on the system.
//!
@ -56,87 +52,96 @@
//! .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
//! use cpal::traits::{DeviceTrait, EventLoopTrait, HostTrait};
//! use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host();
//! # let event_loop = host.event_loop();
//! # let device = host.default_output_device().unwrap();
//! # let format = device.supported_output_formats().unwrap().next().unwrap().with_max_sample_rate();
//! let stream_id = event_loop.build_output_stream(&device, &format).unwrap();
//! # let format = device.default_output_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
//! will allow you to control the stream.
//! While the stream is running, the selected audio device will periodically call the data callback
//! 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.
//!
//! ```no_run
//! # use cpal::traits::{EventLoopTrait, HostTrait};
//! # let host = cpal::default_host();
//! # let event_loop = host.event_loop();
//! # let stream_id = unimplemented!();
//! 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`.
//! > **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
//! > audio data to the system's audio device in a timely manner. On older platforms that only
//! > provide a blocking API (e.g. ALSA), CPAL will create a thread in order to consistently
//! > provide non-blocking behaviour. *If this is an issue for your platform or design, please
//! > share your issue and use-case with the CPAL team on the github issue tracker for
//! > consideration.*
//!
//! In this example, we simply fill the given output buffer with zeroes.
//!
//! ```no_run
//! use cpal::{StreamData, UnknownTypeOutputBuffer};
//! use cpal::traits::{EventLoopTrait, HostTrait};
//! use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
//! # let host = cpal::default_host();
//! # let event_loop = host.event_loop();
//! event_loop.run(move |stream_id, stream_result| {
//! let stream_data = match stream_result {
//! Ok(data) => data,
//! Err(err) => {
//! eprintln!("an error occurred on stream {:?}: {}", stream_id, err);
//! return;
//! # let device = host.default_output_device().unwrap();
//! # let format = device.default_output_format().unwrap();
//! let stream = device.build_output_stream(
//! &format,
//! move |data| {
//! match 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;
//! }
//! },
//! _ => (),
//! }
//! _ => return,
//! };
//!
//! 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;
//! }
//! },
//! _ => (),
//! }
//! });
//! },
//! move |err| {
//! eprintln!("an error occurred on the output audio stream: {}", err);
//! },
//! );
//! ```
//!
//! 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"]

View File

@ -128,7 +128,16 @@ pub trait DeviceTrait {
/// A stream created from `Device`, with methods to control playback.
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>;
/// 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>;
}
}