diff --git a/examples/beep.rs b/examples/beep.rs index 20dc5ea..60ec8aa 100644 --- a/examples/beep.rs +++ b/examples/beep.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), anyhow::Error> { .expect("failed to find a default output device"); let config = device.default_output_config()?; - match config.sample_format { + match config.sample_format() { cpal::SampleFormat::F32 => run::(&device, &config.into())?, cpal::SampleFormat::I16 => run::(&device, &config.into())?, cpal::SampleFormat::U16 => run::(&device, &config.into())?, diff --git a/examples/enumerate.rs b/examples/enumerate.rs index 08606ae..d599790 100644 --- a/examples/enumerate.rs +++ b/examples/enumerate.rs @@ -22,8 +22,8 @@ fn main() -> Result<(), anyhow::Error> { println!(" {}. \"{}\"", device_index + 1, device.name()?); // Input configs - if let Ok(fmt) = device.default_input_config() { - println!(" Default input stream config:\n {:?}", fmt); + if let Ok(conf) = device.default_input_config() { + println!(" Default input stream config:\n {:?}", conf); } let mut input_configs = match device.supported_input_configs() { Ok(f) => f.peekable(), @@ -45,8 +45,8 @@ fn main() -> Result<(), anyhow::Error> { } // Output configs - if let Ok(fmt) = device.default_output_config() { - println!(" Default output stream config:\n {:?}", fmt); + if let Ok(conf) = device.default_output_config() { + println!(" Default output stream config:\n {:?}", conf); } let mut output_configs = match device.supported_output_configs() { Ok(f) => f.peekable(), diff --git a/examples/record_wav.rs b/examples/record_wav.rs index 793b781..223a153 100644 --- a/examples/record_wav.rs +++ b/examples/record_wav.rs @@ -40,7 +40,7 @@ fn main() -> Result<(), anyhow::Error> { eprintln!("an error occurred on stream: {}", err); }; - let stream = match config.sample_format { + let stream = match config.sample_format() { cpal::SampleFormat::F32 => device.build_input_stream( &config.into(), move |data| write_input_data::(data, &writer_2), @@ -78,10 +78,10 @@ fn sample_format(format: cpal::SampleFormat) -> hound::SampleFormat { fn wav_spec_from_config(config: &cpal::SupportedStreamConfig) -> hound::WavSpec { hound::WavSpec { - channels: config.channels as _, - sample_rate: config.sample_rate.0 as _, - bits_per_sample: (config.sample_format.sample_size() * 8) as _, - sample_format: sample_format(config.sample_format), + channels: config.channels() as _, + sample_rate: config.sample_rate().0 as _, + bits_per_sample: (config.sample_format().sample_size() * 8) as _, + sample_format: sample_format(config.sample_format()), } } diff --git a/src/host/alsa/mod.rs b/src/host/alsa/mod.rs index 6050d74..42f5660 100644 --- a/src/host/alsa/mod.rs +++ b/src/host/alsa/mod.rs @@ -4,7 +4,8 @@ extern crate libc; use crate::{ BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate, - StreamError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, + StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange, + SupportedStreamConfigsError, }; use std::sync::Arc; use std::thread::{self, JoinHandle}; @@ -82,7 +83,8 @@ impl DeviceTrait for Device { fn build_input_stream_raw( &self, - conf: &SupportedStreamConfig, + conf: &StreamConfig, + sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result @@ -90,14 +92,16 @@ impl DeviceTrait for Device { D: FnMut(&Data) + Send + 'static, E: FnMut(StreamError) + Send + 'static, { - let stream_inner = self.build_stream_inner(conf, alsa::SND_PCM_STREAM_CAPTURE)?; + let stream_inner = + self.build_stream_inner(conf, sample_format, alsa::SND_PCM_STREAM_CAPTURE)?; let stream = Stream::new_input(Arc::new(stream_inner), data_callback, error_callback); Ok(stream) } fn build_output_stream_raw( &self, - conf: &SupportedStreamConfig, + conf: &StreamConfig, + sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result @@ -105,7 +109,8 @@ impl DeviceTrait for Device { D: FnMut(&mut Data) + Send + 'static, E: FnMut(StreamError) + Send + 'static, { - let stream_inner = self.build_stream_inner(conf, alsa::SND_PCM_STREAM_PLAYBACK)?; + let stream_inner = + self.build_stream_inner(conf, sample_format, alsa::SND_PCM_STREAM_PLAYBACK)?; let stream = Stream::new_output(Arc::new(stream_inner), data_callback, error_callback); Ok(stream) } @@ -161,7 +166,8 @@ pub struct Device(String); impl Device { fn build_stream_inner( &self, - conf: &SupportedStreamConfig, + conf: &StreamConfig, + sample_format: SampleFormat, stream_type: alsa::snd_pcm_stream_t, ) -> Result { let name = ffi::CString::new(self.0.clone()).expect("unable to clone device"); @@ -185,7 +191,7 @@ impl Device { }; let can_pause = unsafe { let hw_params = HwParams::alloc(); - set_hw_params_from_format(handle, &hw_params, conf) + set_hw_params_from_format(handle, &hw_params, conf, sample_format) .map_err(|description| BackendSpecificError { description })?; alsa::snd_pcm_hw_params_can_pause(hw_params.0) == 1 @@ -213,7 +219,7 @@ impl Device { let stream_inner = StreamInner { channel: handle, - sample_format: conf.sample_format, + sample_format, num_descriptors, num_channels: conf.channels as u16, buffer_len, @@ -904,7 +910,8 @@ fn get_available_samples(stream: &StreamInner) -> Result Result<(), String> { if let Err(e) = check_errors(alsa::snd_pcm_hw_params_any(pcm_handle, hw_params.0)) { return Err(format!("errors on pcm handle: {}", e)); @@ -918,13 +925,13 @@ unsafe fn set_hw_params_from_format( } let sample_format = if cfg!(target_endian = "big") { - match format.sample_format { + match sample_format { SampleFormat::I16 => alsa::SND_PCM_FORMAT_S16_BE, SampleFormat::U16 => alsa::SND_PCM_FORMAT_U16_BE, SampleFormat::F32 => alsa::SND_PCM_FORMAT_FLOAT_BE, } } else { - match format.sample_format { + match sample_format { SampleFormat::I16 => alsa::SND_PCM_FORMAT_S16_LE, SampleFormat::U16 => alsa::SND_PCM_FORMAT_U16_LE, SampleFormat::F32 => alsa::SND_PCM_FORMAT_FLOAT_LE, @@ -941,7 +948,7 @@ unsafe fn set_hw_params_from_format( if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_rate( pcm_handle, hw_params.0, - format.sample_rate.0 as libc::c_uint, + config.sample_rate.0 as libc::c_uint, 0, )) { return Err(format!("sample rate could not be set: {}", e)); @@ -949,7 +956,7 @@ unsafe fn set_hw_params_from_format( if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_channels( pcm_handle, hw_params.0, - format.channels as libc::c_uint, + config.channels as libc::c_uint, )) { return Err(format!("channel count could not be set: {}", e)); } @@ -973,7 +980,7 @@ unsafe fn set_hw_params_from_format( unsafe fn set_sw_params_from_format( pcm_handle: *mut alsa::snd_pcm_t, - format: &SupportedStreamConfig, + config: &StreamConfig, ) -> Result<(usize, usize), String> { let mut sw_params = ptr::null_mut(); // TODO: RAII if let Err(e) = check_errors(alsa::snd_pcm_sw_params_malloc(&mut sw_params)) { @@ -1009,8 +1016,8 @@ unsafe fn set_sw_params_from_format( )) { return Err(format!("snd_pcm_sw_params_set_avail_min failed: {}", e)); } - let buffer = buffer as usize * format.channels as usize; - let period = period as usize * format.channels as usize; + let buffer = buffer as usize * config.channels as usize; + let period = period as usize * config.channels as usize; (buffer, period) }; diff --git a/src/host/null/mod.rs b/src/host/null/mod.rs index 2aab365..1424ca8 100644 --- a/src/host/null/mod.rs +++ b/src/host/null/mod.rs @@ -1,7 +1,7 @@ use crate::{ BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, - PauseStreamError, PlayStreamError, StreamError, SupportedStreamConfig, - SupportedStreamConfigRange, SupportedStreamConfigsError, + PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError, + SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, }; use traits::{DeviceTrait, HostTrait, StreamTrait}; @@ -68,7 +68,8 @@ impl DeviceTrait for Device { fn build_input_stream_raw( &self, - _format: &SupportedStreamConfig, + _config: &StreamConfig, + _sample_format: SampleFormat, _data_callback: D, _error_callback: E, ) -> Result @@ -82,7 +83,8 @@ impl DeviceTrait for Device { /// Create an output stream. fn build_output_stream_raw( &self, - _format: &SupportedStreamConfig, + _config: &StreamConfig, + _sample_format: SampleFormat, _data_callback: D, _error_callback: E, ) -> Result diff --git a/src/lib.rs b/src/lib.rs index cf98a67..e97b2ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ //! # let device = host.default_output_device().unwrap(); //! # let supported_config = device.default_output_config().unwrap(); //! let err_fn = |err| eprintln!("an error occurred on the output audio stream: {}", err); -//! let sample_format = supported_config.sample_format; +//! let sample_format = supported_config.sample_format(); //! let config = supported_config.into(); //! let stream = match sample_format { //! SampleFormat::F32 => device.build_output_stream(&config, write_silence::, err_fn), @@ -117,10 +117,11 @@ //! # let host = cpal::default_host(); //! # let device = host.default_output_device().unwrap(); //! # let supported_config = device.default_output_config().unwrap(); +//! # let sample_format = supported_config.sample_format(); //! # let config = supported_config.into(); //! # let data_fn = move |_data: &mut cpal::Data| {}; //! # let err_fn = move |_err| {}; -//! # let stream = device.build_output_stream_raw(&config, data_fn, err_fn).unwrap(); +//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap(); //! stream.play().unwrap(); //! ``` //! @@ -132,10 +133,11 @@ //! # let host = cpal::default_host(); //! # let device = host.default_output_device().unwrap(); //! # let supported_config = device.default_output_config().unwrap(); +//! # let sample_format = supported_config.sample_format(); //! # let config = supported_config.into(); //! # let data_fn = move |_data: &mut cpal::Data| {}; //! # let err_fn = move |_err| {}; -//! # let stream = device.build_output_stream_raw(&config, data_fn, err_fn).unwrap(); +//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap(); //! stream.pause().unwrap(); //! ``` @@ -202,9 +204,9 @@ pub struct SupportedStreamConfigRange { /// `SupportedStreamConfigRange` instance or one of the `Device::default_input/output_config` methods. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SupportedStreamConfig { - pub channels: ChannelCount, - pub sample_rate: SampleRate, - pub sample_format: SampleFormat, + channels: ChannelCount, + sample_rate: SampleRate, + sample_format: SampleFormat, } /// A buffer of dynamically typed audio data, passed to raw stream callbacks. @@ -219,12 +221,22 @@ pub struct Data { } impl SupportedStreamConfig { - /// Construct a `SupportedStreamConfig` from an existing `StreamConfig`. - pub fn from_config(conf: &StreamConfig, fmt: SampleFormat) -> Self { - Self { - channels: conf.channels, - sample_rate: conf.sample_rate, - sample_format: fmt, + pub fn channels(&self) -> ChannelCount { + self.channels + } + + pub fn sample_rate(&self) -> SampleRate { + self.sample_rate + } + + pub fn sample_format(&self) -> SampleFormat { + self.sample_format + } + + pub fn config(&self) -> StreamConfig { + StreamConfig { + channels: self.channels, + sample_rate: self.sample_rate, } } } @@ -406,12 +418,7 @@ impl SupportedStreamConfigRange { impl From for StreamConfig { fn from(conf: SupportedStreamConfig) -> Self { - let channels = conf.channels; - let sample_rate = conf.sample_rate; - StreamConfig { - channels, - sample_rate, - } + conf.config() } } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 08fa5ed..cd5f529 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -257,7 +257,8 @@ macro_rules! impl_platform_host { fn build_input_stream_raw( &self, - format: &crate::SupportedStreamConfig, + config: &crate::StreamConfig, + sample_format: crate::SampleFormat, data_callback: D, error_callback: E, ) -> Result @@ -267,7 +268,13 @@ macro_rules! impl_platform_host { { match self.0 { $( - DeviceInner::$HostVariant(ref d) => d.build_input_stream_raw(format, data_callback, error_callback) + DeviceInner::$HostVariant(ref d) => d + .build_input_stream_raw( + config, + sample_format, + data_callback, + error_callback, + ) .map(StreamInner::$HostVariant) .map(Stream::from), )* @@ -276,7 +283,8 @@ macro_rules! impl_platform_host { fn build_output_stream_raw( &self, - format: &crate::SupportedStreamConfig, + config: &crate::StreamConfig, + sample_format: crate::SampleFormat, data_callback: D, error_callback: E, ) -> Result @@ -286,7 +294,13 @@ macro_rules! impl_platform_host { { match self.0 { $( - DeviceInner::$HostVariant(ref d) => d.build_output_stream_raw(format, data_callback, error_callback) + DeviceInner::$HostVariant(ref d) => d + .build_output_stream_raw( + config, + sample_format, + data_callback, + error_callback, + ) .map(StreamInner::$HostVariant) .map(Stream::from), )* diff --git a/src/traits.rs b/src/traits.rs index 16fa240..ef94aa7 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -2,8 +2,8 @@ use { BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, InputDevices, - OutputDevices, PauseStreamError, PlayStreamError, Sample, StreamConfig, StreamError, - SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, + OutputDevices, PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig, + StreamError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, }; /// A **Host** provides access to the available audio devices on the system. @@ -126,7 +126,8 @@ pub trait DeviceTrait { E: FnMut(StreamError) + Send + 'static, { self.build_input_stream_raw( - &SupportedStreamConfig::from_config(config, T::FORMAT), + config, + T::FORMAT, move |data| { data_callback( data.as_slice() @@ -150,7 +151,8 @@ pub trait DeviceTrait { E: FnMut(StreamError) + Send + 'static, { self.build_output_stream_raw( - &SupportedStreamConfig::from_config(config, T::FORMAT), + config, + T::FORMAT, move |data| { data_callback( data.as_slice_mut() @@ -164,7 +166,8 @@ pub trait DeviceTrait { /// Create a dynamically typed input stream. fn build_input_stream_raw( &self, - format: &SupportedStreamConfig, + config: &StreamConfig, + sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result @@ -175,7 +178,8 @@ pub trait DeviceTrait { /// Create a dynamically typed output stream. fn build_output_stream_raw( &self, - format: &SupportedStreamConfig, + config: &StreamConfig, + sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result