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. The library will make a bast-effort attempt at
114    /// honoring this setting, and in future versions may provide additional buffering to ensure
115    /// it, but for now you should not make assumptions on buffer sizes based on this setting.
116    pub buffer_size_range: (Option<usize>, Option<usize>),
117    /// Whether the device should be exclusively held (meaning no other application can open the
118    /// same device).
119    pub exclusive: bool,
120}
121
122/// Audio channel description.
123#[derive(Debug, Clone)]
124pub struct Channel<'a> {
125    /// Index of the channel in the device
126    pub index: usize,
127    /// Display name for the channel, if available, else a generic name like "Channel 1"
128    pub name: Cow<'a, str>,
129}
130
131/// Trait for types describing audio devices. Audio devices have zero or more inputs and outputs,
132/// and depending on the driver, can be duplex devices which can provide both of them at the same
133/// time natively.
134pub trait AudioDevice {
135    /// Type of errors that can happen when using this device.
136    type Error: std::error::Error;
137
138    /// Device display name
139    fn name(&self) -> Cow<str>;
140
141    /// Device type. Either input, output, or duplex.
142    fn device_type(&self) -> DeviceType;
143
144    /// Iterator of the available channels in this device. Channel indices are used when
145    /// specifying which channels to open when creating an audio stream.
146    fn channel_map(&self) -> impl IntoIterator<Item = Channel>;
147
148    /// Not all configuration values make sense for a particular device, and this method tests a
149    /// configuration to see if it can be used in an audio stream.
150    fn is_config_supported(&self, config: &StreamConfig) -> bool;
151
152    /// Enumerate all possible configurations this device supports. If that is not provided by
153    /// the device, and not easily generated manually, this will return `None`.
154    fn enumerate_configurations(&self) -> Option<impl IntoIterator<Item = StreamConfig>>;
155}
156
157/// Marker trait for values which are [Send] everywhere but on the web (as WASM does not yet have
158/// web targets.
159///
160/// This should only be used to define the traits and should not be relied upon in external code.
161///
162/// This definition is selected on non-web platforms, and does require [`Send`].
163#[cfg(not(wasm))]
164pub trait SendEverywhereButOnWeb: 'static + Send {}
165#[cfg(not(wasm))]
166impl<T: 'static + Send> SendEverywhereButOnWeb for T {}
167
168/// Marker trait for values which are [Send] everywhere but on the web (as WASM does not yet have
169/// web targets.
170///
171/// This should only be used to define the traits and should not be relied upon in external code.
172///
173/// This definition is selected on web platforms, and does not require [`Send`].
174#[cfg(wasm)]
175pub trait SendEverywhereButOnWeb {}
176#[cfg(wasm)]
177impl<T> SendEverywhereButOnWeb for T {}
178
179/// Trait for types which can provide input streams.
180///
181/// Input devices require a [`AudioInputCallback`] which receives the audio data from the input
182/// device, and processes it.
183pub trait AudioInputDevice: AudioDevice {
184    /// Type of the resulting stream. This stream can be used to control the audio processing
185    /// externally, or stop it completely and give back ownership of the callback with
186    /// [`AudioStreamHandle::eject`].
187    type StreamHandle<Callback: AudioInputCallback>: AudioStreamHandle<Callback>;
188
189    /// Return the default configuration for this device, if there is one. The returned configuration *must* be
190    /// valid according to [`Self::is_config_supported`].
191    fn default_input_config(&self) -> Result<StreamConfig, Self::Error>;
192
193    /// Creates an input stream with the provided stream configuration. For this call to be
194    /// valid, [`AudioDevice::is_config_supported`] should have returned `true` on the provided
195    /// configuration.
196    ///
197    /// An input callback is required to process the audio, whose ownership will be transferred
198    /// to the audio stream.
199    fn create_input_stream<Callback: SendEverywhereButOnWeb + AudioInputCallback>(
200        &self,
201        stream_config: StreamConfig,
202        callback: Callback,
203    ) -> Result<Self::StreamHandle<Callback>, Self::Error>;
204
205    /// Create an input stream with the default configuration (as returned by [`Self::default_input_config`]).
206    ///
207    /// # Arguments
208    ///
209    /// - `callback`: Callback to process the audio input
210    fn default_input_stream<Callback: SendEverywhereButOnWeb + AudioInputCallback>(
211        &self,
212        callback: Callback,
213    ) -> Result<Self::StreamHandle<Callback>, Self::Error> {
214        self.create_input_stream(self.default_input_config()?, callback)
215    }
216}
217
218/// Trait for types which can provide output streams.
219///
220/// Output devices require a [`AudioOutputCallback`] which receives the audio data from the output
221/// device, and processes it.
222pub trait AudioOutputDevice: AudioDevice {
223    /// Type of the resulting stream. This stream can be used to control the audio processing
224    /// externally, or stop it completely and give back ownership of the callback with
225    /// [`AudioStreamHandle::eject`].
226    type StreamHandle<Callback: AudioOutputCallback>: AudioStreamHandle<Callback>;
227
228    /// Return the default output configuration for this device, if it exists
229    fn default_output_config(&self) -> Result<StreamConfig, Self::Error>;
230
231    /// Creates an output stream with the provided stream configuration. For this call to be
232    /// valid, [`AudioDevice::is_config_supported`] should have returned `true` on the provided
233    /// configuration.
234    ///
235    /// An output callback is required to process the audio, whose ownership will be transferred
236    /// to the audio stream.
237    fn create_output_stream<Callback: SendEverywhereButOnWeb + AudioOutputCallback>(
238        &self,
239        stream_config: StreamConfig,
240        callback: Callback,
241    ) -> Result<Self::StreamHandle<Callback>, Self::Error>;
242
243    /// Create an output stream using the default configuration as returned by [`Self::default_output_config`].
244    ///
245    /// # Arguments
246    ///
247    /// - `callback`: Output callback to generate audio data with.
248    fn default_output_stream<Callback: SendEverywhereButOnWeb + AudioOutputCallback>(
249        &self,
250        callback: Callback,
251    ) -> Result<Self::StreamHandle<Callback>, Self::Error> {
252        self.create_output_stream(self.default_output_config()?, callback)
253    }
254}
255
256/// Trait for types which handles an audio stream (input or output).
257pub trait AudioStreamHandle<Callback> {
258    /// Type of errors which have caused the stream to fail.
259    type Error: std::error::Error;
260
261    /// Eject the stream, returning ownership of the callback.
262    ///
263    /// An error can occur when an irrecoverable error has occured and ownership has been lost
264    /// already.
265    fn eject(self) -> Result<Callback, Self::Error>;
266}
267
268#[duplicate::duplicate_item(
269    name            bufty;
270    [AudioInput]    [AudioRef < 'a, T >];
271    [AudioOutput]   [AudioMut < 'a, T >];
272)]
273/// Plain-old-data object holding references to the audio buffer and the associated time-keeping
274/// [`Timestamp`]. This timestamp is associated with the stream, and in the cases where the
275/// driver provides timing information, it is used instead of relying on sample-counting.
276pub struct name<'a, T> {
277    /// Associated time stamp for this callback. The time represents the duration for which the
278    /// stream has been opened, and is either provided by the driver if available, or is kept up
279    /// manually by the library.
280    pub timestamp: Timestamp,
281    /// Audio buffer data.
282    pub buffer: bufty,
283}
284
285/// Plain-old-data object holding the passed-in stream configuration, as well as a general
286/// callback timestamp, which can be different from the input and output streams in case of
287/// cross-stream latencies; differences in timing can indicate desync.
288pub struct AudioCallbackContext {
289    /// Passed-in stream configuration. Values have been updated where necessary to correspond to
290    /// the actual stream properties.
291    pub stream_config: StreamConfig,
292    /// Callback-wide timestamp.
293    pub timestamp: Timestamp,
294}
295
296/// Trait of types which process input audio data. This is the trait that users will want to
297/// implement when processing an input device.
298pub trait AudioInputCallback {
299    /// Callback called when input data is available to be processed.
300    fn on_input_data(&mut self, context: AudioCallbackContext, input: AudioInput<f32>);
301}
302
303/// Trait of types which process output audio data. This is the trait that users will want to
304/// implement when processing an output device.
305pub trait AudioOutputCallback {
306    /// Callback called when output data is available to be processed.
307    fn on_output_data(&mut self, context: AudioCallbackContext, input: AudioOutput<f32>);
308}