interflow/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4use bitflags::bitflags;
5use std::borrow::Cow;
6use std::fmt;
7use std::fmt::Formatter;
8
9use crate::audio_buffer::{AudioMut, AudioRef};
10use crate::channel_map::ChannelMap32;
11use crate::timestamp::Timestamp;
12
13pub mod audio_buffer;
14pub mod backends;
15pub mod channel_map;
16pub mod duplex;
17pub mod prelude;
18pub mod timestamp;
19
20bitflags! {
21    /// Represents the types/capabilities of an audio device.
22    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23    pub struct DeviceType: u32 {
24        /// Device supports audio input.
25        const INPUT = 1 << 0;
26
27        /// Device supports audio output.
28        const OUTPUT = 1 << 1;
29
30        /// Physical audio device (hardware).
31        const PHYSICAL = 1 << 2;
32
33        /// Virtual/software application device.
34        const APPLICATION = 1 << 3;
35
36        /// This device is set as default
37        const DEFAULT = 1 << 4;
38
39        /// Device that supports both input and output.
40        const DUPLEX = Self::INPUT.bits() | Self::OUTPUT.bits();
41    }
42}
43
44/// Audio drivers provide access to the inputs and outputs of devices.
45/// Several drivers might provide the same accesses, some sharing it with other applications,
46/// while others work in exclusive mode.
47pub trait AudioDriver {
48    /// Type of errors that can happen when using this audio driver.
49    type Error: std::error::Error;
50    /// Type of audio devices this driver provides.
51    type Device: AudioDevice;
52
53    /// Driver display name.
54    const DISPLAY_NAME: &'static str;
55
56    /// Runtime version of the audio driver. If there is a difference between "client" and
57    /// "server" versions, then this should reflect the server version.
58    fn version(&self) -> Result<Cow<str>, Self::Error>;
59
60    /// Default device of the given type. This is most often tied to the audio settings at the
61    /// operating system level.
62    fn default_device(&self, device_type: DeviceType) -> Result<Option<Self::Device>, Self::Error>;
63
64    /// List all devices available through this audio driver.
65    fn list_devices(&self) -> Result<impl IntoIterator<Item = Self::Device>, Self::Error>;
66}
67
68impl DeviceType {
69    /// Returns true if this device type has the input capability.
70    pub fn is_input(&self) -> bool {
71        self.contains(Self::INPUT)
72    }
73
74    /// Returns true if this device type has the output capability.
75    pub fn is_output(&self) -> bool {
76        self.contains(Self::OUTPUT)
77    }
78
79    /// Returns true if this device type is a physical device.
80    pub fn is_physical(&self) -> bool {
81        self.contains(Self::PHYSICAL)
82    }
83
84    /// Returns true if this device type is an application/virtual device.
85    pub fn is_application(&self) -> bool {
86        self.contains(Self::APPLICATION)
87    }
88
89    /// Returns true if this device is set as default
90    pub fn is_default(&self) -> bool {
91        self.contains(Self::DEFAULT)
92    }
93
94    /// Returns true if this device type supports both input and output.
95    pub fn is_duplex(&self) -> bool {
96        self.contains(Self::DUPLEX)
97    }
98}
99
100/// Configuration for an audio stream.
101#[derive(Debug, Clone, Copy, PartialEq)]
102pub struct StreamConfig {
103    /// Configured sample rate of the requested stream. The opened stream can have a different
104    /// sample rate, so don't rely on this parameter being correct at runtime.
105    pub samplerate: f64,
106    /// Map of channels requested by the stream. Entries correspond in order to
107    /// [AudioDevice::channel_map].
108    ///
109    /// Some drivers allow specifying which channels are going to be opened and available through
110    /// the audio buffers. For other drivers, only the number of requested channels is used, and
111    /// order does not matter.
112    pub channels: ChannelMap32,
113    /// Range of preferential buffer sizes, in units of audio samples per channel.
114    /// The library will make a best-effort attempt at honoring this setting, and in future versions
115    /// may provide additional buffering to ensure it, but for now you should not make assumptions
116    /// on buffer sizes based on this setting.
117    pub buffer_size_range: (Option<usize>, Option<usize>),
118    /// Whether the device should be exclusively held (meaning no other application can open the
119    /// same device).
120    pub exclusive: bool,
121}
122
123/// Audio channel description.
124#[derive(Debug, Clone)]
125pub struct Channel<'a> {
126    /// Index of the channel in the device
127    pub index: usize,
128    /// Display name for the channel, if available, else a generic name like "Channel 1"
129    pub name: Cow<'a, str>,
130}
131
132/// Trait for types describing audio devices. Audio devices have zero or more inputs and outputs,
133/// and depending on the driver, can be duplex devices which can provide both of them at the same
134/// time natively.
135pub trait AudioDevice {
136    /// Type of errors that can happen when using this device.
137    type Error: std::error::Error;
138
139    /// Device display name
140    fn name(&self) -> Cow<str>;
141
142    /// Device type. Either input, output, or duplex.
143    fn device_type(&self) -> DeviceType;
144
145    /// Iterator of the available channels in this device. Channel indices are used when
146    /// specifying which channels to open when creating an audio stream.
147    fn channel_map(&self) -> impl IntoIterator<Item = Channel>;
148
149    /// Not all configuration values make sense for a particular device, and this method tests a
150    /// configuration to see if it can be used in an audio stream.
151    fn is_config_supported(&self, config: &StreamConfig) -> bool;
152
153    /// Enumerate all possible configurations this device supports. If that is not provided by
154    /// the device, and not easily generated manually, this will return `None`.
155    fn enumerate_configurations(&self) -> Option<impl IntoIterator<Item = StreamConfig>>;
156
157    /// Returns the supported I/O buffer size range for the device.
158    fn buffer_size_range(&self) -> Result<(Option<usize>, Option<usize>), Self::Error> {
159        Ok((None, None))
160    }
161}
162
163/// Marker trait for values which are [Send] everywhere but on the web (as WASM does not yet have
164/// web targets.
165///
166/// This should only be used to define the traits and should not be relied upon in external code.
167///
168/// This definition is selected on non-web platforms, and does require [`Send`].
169#[cfg(not(wasm))]
170pub trait SendEverywhereButOnWeb: 'static + Send {}
171#[cfg(not(wasm))]
172impl<T: 'static + Send> SendEverywhereButOnWeb for T {}
173
174/// Marker trait for values which are [Send] everywhere but on the web (as WASM does not yet have
175/// web targets.
176///
177/// This should only be used to define the traits and should not be relied upon in external code.
178///
179/// This definition is selected on web platforms, and does not require [`Send`].
180#[cfg(wasm)]
181pub trait SendEverywhereButOnWeb {}
182#[cfg(wasm)]
183impl<T> SendEverywhereButOnWeb for T {}
184
185/// Trait for types which can provide input streams.
186///
187/// Input devices require a [`AudioInputCallback`] which receives the audio data from the input
188/// device, and processes it.
189pub trait AudioInputDevice: AudioDevice {
190    /// Type of the resulting stream. This stream can be used to control the audio processing
191    /// externally, or stop it completely and give back ownership of the callback with
192    /// [`AudioStreamHandle::eject`].
193    type StreamHandle<Callback: AudioInputCallback>: AudioStreamHandle<Callback>;
194
195    /// Return the default configuration for this device, if there is one. The returned configuration *must* be
196    /// valid according to [`Self::is_config_supported`].
197    fn default_input_config(&self) -> Result<StreamConfig, Self::Error>;
198
199    /// Creates an input stream with the provided stream configuration. For this call to be
200    /// valid, [`AudioDevice::is_config_supported`] should have returned `true` on the provided
201    /// configuration.
202    ///
203    /// An input callback is required to process the audio, whose ownership will be transferred
204    /// to the audio stream.
205    fn create_input_stream<Callback: SendEverywhereButOnWeb + AudioInputCallback>(
206        &self,
207        stream_config: StreamConfig,
208        callback: Callback,
209    ) -> Result<Self::StreamHandle<Callback>, Self::Error>;
210
211    /// Create an input stream with the default configuration (as returned by [`Self::default_input_config`]).
212    ///
213    /// # Arguments
214    ///
215    /// - `callback`: Callback to process the audio input
216    fn default_input_stream<Callback: SendEverywhereButOnWeb + AudioInputCallback>(
217        &self,
218        callback: Callback,
219    ) -> Result<Self::StreamHandle<Callback>, Self::Error> {
220        self.create_input_stream(self.default_input_config()?, callback)
221    }
222}
223
224/// Trait for types which can provide output streams.
225///
226/// Output devices require a [`AudioOutputCallback`] which receives the audio data from the output
227/// device, and processes it.
228pub trait AudioOutputDevice: AudioDevice {
229    /// Type of the resulting stream. This stream can be used to control the audio processing
230    /// externally, or stop it completely and give back ownership of the callback with
231    /// [`AudioStreamHandle::eject`].
232    type StreamHandle<Callback: AudioOutputCallback>: AudioStreamHandle<Callback>;
233
234    /// Return the default output configuration for this device, if it exists
235    fn default_output_config(&self) -> Result<StreamConfig, Self::Error>;
236
237    /// Creates an output stream with the provided stream configuration. For this call to be
238    /// valid, [`AudioDevice::is_config_supported`] should have returned `true` on the provided
239    /// configuration.
240    ///
241    /// An output callback is required to process the audio, whose ownership will be transferred
242    /// to the audio stream.
243    fn create_output_stream<Callback: SendEverywhereButOnWeb + AudioOutputCallback>(
244        &self,
245        stream_config: StreamConfig,
246        callback: Callback,
247    ) -> Result<Self::StreamHandle<Callback>, Self::Error>;
248
249    /// Create an output stream using the default configuration as returned by [`Self::default_output_config`].
250    ///
251    /// # Arguments
252    ///
253    /// - `callback`: Output callback to generate audio data with.
254    fn default_output_stream<Callback: SendEverywhereButOnWeb + AudioOutputCallback>(
255        &self,
256        callback: Callback,
257    ) -> Result<Self::StreamHandle<Callback>, Self::Error> {
258        self.create_output_stream(self.default_output_config()?, callback)
259    }
260}
261
262/// Trait for types which handles an audio stream (input or output).
263pub trait AudioStreamHandle<Callback> {
264    /// Type of errors which have caused the stream to fail.
265    type Error: std::error::Error;
266
267    /// Eject the stream, returning ownership of the callback.
268    ///
269    /// An error can occur when an irrecoverable error has occured and ownership has been lost
270    /// already.
271    fn eject(self) -> Result<Callback, Self::Error>;
272}
273
274#[duplicate::duplicate_item(
275    name            bufty;
276    [AudioInput]    [AudioRef < 'a, T >];
277    [AudioOutput]   [AudioMut < 'a, T >];
278)]
279/// Plain-old-data object holding references to the audio buffer and the associated time-keeping
280/// [`Timestamp`]. This timestamp is associated with the stream, and in the cases where the
281/// driver provides timing information, it is used instead of relying on sample-counting.
282pub struct name<'a, T> {
283    /// Associated time stamp for this callback. The time represents the duration for which the
284    /// stream has been opened, and is either provided by the driver if available, or is kept up
285    /// manually by the library.
286    pub timestamp: Timestamp,
287    /// Audio buffer data.
288    pub buffer: bufty,
289}
290
291/// Plain-old-data object holding the passed-in stream configuration, as well as a general
292/// callback timestamp, which can be different from the input and output streams in case of
293/// cross-stream latencies; differences in timing can indicate desync.
294pub struct AudioCallbackContext {
295    /// Passed-in stream configuration. Values have been updated where necessary to correspond to
296    /// the actual stream properties.
297    pub stream_config: StreamConfig,
298    /// Callback-wide timestamp.
299    pub timestamp: Timestamp,
300}
301
302/// Trait of types which process input audio data. This is the trait that users will want to
303/// implement when processing an input device.
304pub trait AudioInputCallback {
305    /// Callback called when input data is available to be processed.
306    fn on_input_data(&mut self, context: AudioCallbackContext, input: AudioInput<f32>);
307}
308
309/// Trait of types which process output audio data. This is the trait that users will want to
310/// implement when processing an output device.
311pub trait AudioOutputCallback {
312    /// Callback called when output data is available to be processed.
313    fn on_output_data(&mut self, context: AudioCallbackContext, input: AudioOutput<f32>);
314}