1 //! The suite of traits allowing CPAL to abstract over hosts, devices, event loops and stream IDs. 2 3 use { 4 BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, 5 InputCallbackInfo, InputDevices, OutputCallbackInfo, OutputDevices, PauseStreamError, 6 PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError, SupportedStreamConfig, 7 SupportedStreamConfigRange, SupportedStreamConfigsError, 8 }; 9 10 /// A **Host** provides access to the available audio devices on the system. 11 /// 12 /// Each platform may have a number of available hosts depending on the system, each with their own 13 /// pros and cons. 14 /// 15 /// For example, WASAPI is the standard audio host API that ships with the Windows operating 16 /// system. However, due to historical limitations with respect to performance and flexibility, 17 /// Steinberg created the ASIO API providing better audio device support for pro audio and 18 /// low-latency applications. As a result, it is common for some devices and device capabilities to 19 /// only be available via ASIO, while others are only available via WASAPI. 20 /// 21 /// Another great example is the Linux platform. While the ALSA host API is the lowest-level API 22 /// available to almost all distributions of Linux, its flexibility is limited as it requires that 23 /// each process have exclusive access to the devices with which they establish streams. PulseAudio 24 /// is another popular host API that aims to solve this issue by providing user-space mixing, 25 /// however it has its own limitations w.r.t. low-latency and high-performance audio applications. 26 /// JACK is yet another host API that is more suitable to pro-audio applications, however it is 27 /// less readily available by default in many Linux distributions and is known to be tricky to 28 /// set up. 29 pub trait HostTrait { 30 /// The type used for enumerating available devices by the host. 31 type Devices: Iterator<Item = Self::Device>; 32 /// The `Device` type yielded by the host. 33 type Device: DeviceTrait; 34 35 /// Whether or not the host is available on the system. is_available() -> bool36 fn is_available() -> bool; 37 38 /// An iterator yielding all `Device`s currently available to the host on the system. 39 /// 40 /// Can be empty if the system does not support audio in general. devices(&self) -> Result<Self::Devices, DevicesError>41 fn devices(&self) -> Result<Self::Devices, DevicesError>; 42 43 /// The default input audio device on the system. 44 /// 45 /// Returns `None` if no input device is available. default_input_device(&self) -> Option<Self::Device>46 fn default_input_device(&self) -> Option<Self::Device>; 47 48 /// The default output audio device on the system. 49 /// 50 /// Returns `None` if no output device is available. default_output_device(&self) -> Option<Self::Device>51 fn default_output_device(&self) -> Option<Self::Device>; 52 53 /// An iterator yielding all `Device`s currently available to the system that support one or more 54 /// input stream formats. 55 /// 56 /// Can be empty if the system does not support audio input. input_devices(&self) -> Result<InputDevices<Self::Devices>, DevicesError>57 fn input_devices(&self) -> Result<InputDevices<Self::Devices>, DevicesError> { 58 fn supports_input<D: DeviceTrait>(device: &D) -> bool { 59 device 60 .supported_input_configs() 61 .map(|mut iter| iter.next().is_some()) 62 .unwrap_or(false) 63 } 64 Ok(self.devices()?.filter(supports_input::<Self::Device>)) 65 } 66 67 /// An iterator yielding all `Device`s currently available to the system that support one or more 68 /// output stream formats. 69 /// 70 /// Can be empty if the system does not support audio output. output_devices(&self) -> Result<OutputDevices<Self::Devices>, DevicesError>71 fn output_devices(&self) -> Result<OutputDevices<Self::Devices>, DevicesError> { 72 fn supports_output<D: DeviceTrait>(device: &D) -> bool { 73 device 74 .supported_output_configs() 75 .map(|mut iter| iter.next().is_some()) 76 .unwrap_or(false) 77 } 78 Ok(self.devices()?.filter(supports_output::<Self::Device>)) 79 } 80 } 81 82 /// A device that is capable of audio input and/or output. 83 /// 84 /// Please note that `Device`s may become invalid if they get disconnected. Therefore, all the 85 /// methods that involve a device return a `Result` allowing the user to handle this case. 86 pub trait DeviceTrait { 87 /// The iterator type yielding supported input stream formats. 88 type SupportedInputConfigs: Iterator<Item = SupportedStreamConfigRange>; 89 /// The iterator type yielding supported output stream formats. 90 type SupportedOutputConfigs: Iterator<Item = SupportedStreamConfigRange>; 91 /// The stream type created by `build_input_stream_raw` and `build_output_stream_raw`. 92 type Stream: StreamTrait; 93 94 /// The human-readable name of the device. name(&self) -> Result<String, DeviceNameError>95 fn name(&self) -> Result<String, DeviceNameError>; 96 97 /// An iterator yielding formats that are supported by the backend. 98 /// 99 /// Can return an error if the device is no longer valid (e.g. it has been disconnected). supported_input_configs( &self, ) -> Result<Self::SupportedInputConfigs, SupportedStreamConfigsError>100 fn supported_input_configs( 101 &self, 102 ) -> Result<Self::SupportedInputConfigs, SupportedStreamConfigsError>; 103 104 /// An iterator yielding output stream formats that are supported by the device. 105 /// 106 /// Can return an error if the device is no longer valid (e.g. it has been disconnected). supported_output_configs( &self, ) -> Result<Self::SupportedOutputConfigs, SupportedStreamConfigsError>107 fn supported_output_configs( 108 &self, 109 ) -> Result<Self::SupportedOutputConfigs, SupportedStreamConfigsError>; 110 111 /// The default input stream format for the device. default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>112 fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>; 113 114 /// The default output stream format for the device. default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>115 fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>; 116 117 /// Create an input stream. build_input_stream<T, D, E>( &self, config: &StreamConfig, mut data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where T: Sample, D: FnMut(&[T], &InputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static,118 fn build_input_stream<T, D, E>( 119 &self, 120 config: &StreamConfig, 121 mut data_callback: D, 122 error_callback: E, 123 ) -> Result<Self::Stream, BuildStreamError> 124 where 125 T: Sample, 126 D: FnMut(&[T], &InputCallbackInfo) + Send + 'static, 127 E: FnMut(StreamError) + Send + 'static, 128 { 129 self.build_input_stream_raw( 130 config, 131 T::FORMAT, 132 move |data, info| { 133 data_callback( 134 data.as_slice() 135 .expect("host supplied incorrect sample type"), 136 info, 137 ) 138 }, 139 error_callback, 140 ) 141 } 142 143 /// Create an output stream. build_output_stream<T, D, E>( &self, config: &StreamConfig, mut data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where T: Sample, D: FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static,144 fn build_output_stream<T, D, E>( 145 &self, 146 config: &StreamConfig, 147 mut data_callback: D, 148 error_callback: E, 149 ) -> Result<Self::Stream, BuildStreamError> 150 where 151 T: Sample, 152 D: FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static, 153 E: FnMut(StreamError) + Send + 'static, 154 { 155 self.build_output_stream_raw( 156 config, 157 T::FORMAT, 158 move |data, info| { 159 data_callback( 160 data.as_slice_mut() 161 .expect("host supplied incorrect sample type"), 162 info, 163 ) 164 }, 165 error_callback, 166 ) 167 } 168 169 /// Create a dynamically typed input stream. build_input_stream_raw<D, E>( &self, config: &StreamConfig, sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where D: FnMut(&Data, &InputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static170 fn build_input_stream_raw<D, E>( 171 &self, 172 config: &StreamConfig, 173 sample_format: SampleFormat, 174 data_callback: D, 175 error_callback: E, 176 ) -> Result<Self::Stream, BuildStreamError> 177 where 178 D: FnMut(&Data, &InputCallbackInfo) + Send + 'static, 179 E: FnMut(StreamError) + Send + 'static; 180 181 /// Create a dynamically typed output stream. build_output_stream_raw<D, E>( &self, config: &StreamConfig, sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static182 fn build_output_stream_raw<D, E>( 183 &self, 184 config: &StreamConfig, 185 sample_format: SampleFormat, 186 data_callback: D, 187 error_callback: E, 188 ) -> Result<Self::Stream, BuildStreamError> 189 where 190 D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static, 191 E: FnMut(StreamError) + Send + 'static; 192 } 193 194 /// A stream created from `Device`, with methods to control playback. 195 pub trait StreamTrait { 196 /// Run the stream. 197 /// 198 /// Note: Not all platforms automatically run the stream upon creation, so it is important to 199 /// call `play` after creation if it is expected that the stream should run immediately. play(&self) -> Result<(), PlayStreamError>200 fn play(&self) -> Result<(), PlayStreamError>; 201 202 /// Some devices support pausing the audio stream. This can be useful for saving energy in 203 /// moments of silence. 204 /// 205 /// Note: Not all devices support suspending the stream at the hardware level. This method may 206 /// fail in these cases. pause(&self) -> Result<(), PauseStreamError>207 fn pause(&self) -> Result<(), PauseStreamError>; 208 } 209