interflow/
lib.rs

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