Update wasapi and emscripten backends for SupportedStreamConfig private fields

This commit is contained in:
mitchmindtree 2020-02-02 19:22:27 +01:00
parent 009b796b7c
commit 9bf5664f7d
3 changed files with 47 additions and 35 deletions

View File

@ -3,8 +3,8 @@ extern crate parking_lot;
use crate::{ use crate::{
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
PauseStreamError, PlayStreamError, StreamError, SupportedStreamConfig, PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
SupportedStreamConfigsError, SupportedStreamConfig, SupportedStreamConfigsError,
}; };
use traits::{DeviceTrait, HostTrait, StreamTrait}; use traits::{DeviceTrait, HostTrait, StreamTrait};
@ -84,7 +84,8 @@ impl DeviceTrait for Device {
fn build_input_stream_raw<D, E>( fn build_input_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
@ -92,12 +93,13 @@ impl DeviceTrait for Device {
D: FnMut(&Data) + Send + 'static, D: FnMut(&Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
Device::build_input_stream_raw(self, config, data_callback, error_callback) Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
} }
fn build_output_stream_raw<D, E>( fn build_output_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
@ -105,7 +107,7 @@ impl DeviceTrait for Device {
D: FnMut(&mut Data) + Send + 'static, D: FnMut(&mut Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
Device::build_output_stream_raw(self, config, data_callback, error_callback) Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
} }
} }

View File

@ -14,6 +14,7 @@ use PauseStreamError;
use PlayStreamError; use PlayStreamError;
use Sample; use Sample;
use SampleFormat; use SampleFormat;
use StreamConfig;
use StreamError; use StreamError;
use SupportedStreamConfig; use SupportedStreamConfig;
@ -59,7 +60,8 @@ impl Stream {
impl Device { impl Device {
pub fn build_input_stream_raw<D, E>( pub fn build_input_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
mut data_callback: D, mut data_callback: D,
_error_callback: E, _error_callback: E,
) -> Result<Stream, BuildStreamError> ) -> Result<Stream, BuildStreamError>
@ -70,14 +72,14 @@ impl Device {
let stream_type = self.driver.input_data_type().map_err(build_stream_err)?; let stream_type = self.driver.input_data_type().map_err(build_stream_err)?;
// Ensure that the desired sample type is supported. // Ensure that the desired sample type is supported.
let sample_format = super::device::convert_data_type(&stream_type) let expected_sample_format = super::device::convert_data_type(&stream_type)
.ok_or(BuildStreamError::StreamConfigNotSupported)?; .ok_or(BuildStreamError::StreamConfigNotSupported)?;
if config.sample_format != sample_format { if sample_format != expected_sample_format {
return Err(BuildStreamError::StreamConfigNotSupported); return Err(BuildStreamError::StreamConfigNotSupported);
} }
let num_channels = config.channels.clone(); let num_channels = config.channels.clone();
let buffer_size = self.get_or_create_input_stream(config)?; let buffer_size = self.get_or_create_input_stream(config, sample_format)?;
let cpal_num_samples = buffer_size * num_channels as usize; let cpal_num_samples = buffer_size * num_channels as usize;
// Create the buffer depending on the size of the data type. // Create the buffer depending on the size of the data type.
@ -225,7 +227,8 @@ impl Device {
pub fn build_output_stream_raw<D, E>( pub fn build_output_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
mut data_callback: D, mut data_callback: D,
_error_callback: E, _error_callback: E,
) -> Result<Stream, BuildStreamError> ) -> Result<Stream, BuildStreamError>
@ -236,14 +239,14 @@ impl Device {
let stream_type = self.driver.output_data_type().map_err(build_stream_err)?; let stream_type = self.driver.output_data_type().map_err(build_stream_err)?;
// Ensure that the desired sample type is supported. // Ensure that the desired sample type is supported.
let sample_format = super::device::convert_data_type(&stream_type) let expected_sample_format = super::device::convert_data_type(&stream_type)
.ok_or(BuildStreamError::StreamConfigNotSupported)?; .ok_or(BuildStreamError::StreamConfigNotSupported)?;
if config.sample_format != sample_format { if sample_format != expected_sample_format {
return Err(BuildStreamError::StreamConfigNotSupported); return Err(BuildStreamError::StreamConfigNotSupported);
} }
let num_channels = config.channels.clone(); let num_channels = config.channels.clone();
let buffer_size = self.get_or_create_output_stream(config)?; let buffer_size = self.get_or_create_output_stream(config, sample_format)?;
let cpal_num_samples = buffer_size * num_channels as usize; let cpal_num_samples = buffer_size * num_channels as usize;
// Create buffers depending on data type. // Create buffers depending on data type.
@ -438,12 +441,13 @@ impl Device {
/// On success, the buffer size of the stream is returned. /// On success, the buffer size of the stream is returned.
fn get_or_create_input_stream( fn get_or_create_input_stream(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
) -> Result<usize, BuildStreamError> { ) -> Result<usize, BuildStreamError> {
match self.default_input_config() { match self.default_input_config() {
Ok(f) => { Ok(f) => {
let num_asio_channels = f.channels; let num_asio_channels = f.channels;
check_config(&self.driver, config, num_asio_channels) check_config(&self.driver, config, sample_format, num_asio_channels)
} }
Err(_) => Err(BuildStreamError::StreamConfigNotSupported), Err(_) => Err(BuildStreamError::StreamConfigNotSupported),
}?; }?;
@ -478,12 +482,13 @@ impl Device {
/// If there is no existing ASIO Output Stream it will be created. /// If there is no existing ASIO Output Stream it will be created.
fn get_or_create_output_stream( fn get_or_create_output_stream(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
) -> Result<usize, BuildStreamError> { ) -> Result<usize, BuildStreamError> {
match self.default_output_config() { match self.default_output_config() {
Ok(f) => { Ok(f) => {
let num_asio_channels = f.channels; let num_asio_channels = f.channels;
check_config(&self.driver, config, num_asio_channels) check_config(&self.driver, config, sample_format, num_asio_channels)
} }
Err(_) => Err(BuildStreamError::StreamConfigNotSupported), Err(_) => Err(BuildStreamError::StreamConfigNotSupported),
}?; }?;
@ -581,13 +586,13 @@ impl AsioSample for f64 {
/// Checks sample rate, data type and then finally the number of channels. /// Checks sample rate, data type and then finally the number of channels.
fn check_config( fn check_config(
driver: &sys::Driver, driver: &sys::Driver,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
num_asio_channels: u16, num_asio_channels: u16,
) -> Result<(), BuildStreamError> { ) -> Result<(), BuildStreamError> {
let SupportedStreamConfig { let StreamConfig {
channels, channels,
sample_rate, sample_rate,
sample_format,
} = config; } = config;
// Try and set the sample rate to what the user selected. // Try and set the sample rate to what the user selected.
let sample_rate = sample_rate.0.into(); let sample_rate = sample_rate.0.into();

View File

@ -22,7 +22,8 @@ use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
use crate::{ use crate::{
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError, BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate, DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate,
StreamError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
SupportedStreamConfigsError,
}; };
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::CStr; use std::ffi::CStr;
@ -104,7 +105,8 @@ impl DeviceTrait for Device {
fn build_input_stream_raw<D, E>( fn build_input_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
@ -112,12 +114,13 @@ impl DeviceTrait for Device {
D: FnMut(&Data) + Send + 'static, D: FnMut(&Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
Device::build_input_stream_raw(self, config, data_callback, error_callback) Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
} }
fn build_output_stream_raw<D, E>( fn build_output_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
@ -125,7 +128,7 @@ impl DeviceTrait for Device {
D: FnMut(&mut Data) + Send + 'static, D: FnMut(&mut Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
Device::build_output_stream_raw(self, config, data_callback, error_callback) Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
} }
} }
@ -402,15 +405,17 @@ impl From<coreaudio::Error> for BuildStreamError {
} }
// Create a coreaudio AudioStreamBasicDescription from a CPAL Format. // Create a coreaudio AudioStreamBasicDescription from a CPAL Format.
fn asbd_from_config(config: &SupportedStreamConfig) -> AudioStreamBasicDescription { fn asbd_from_config(
config: &StreamConfig,
sample_format: SampleFormat,
) -> AudioStreamBasicDescription {
let n_channels = config.channels as usize; let n_channels = config.channels as usize;
let sample_rate = config.sample_rate.0; let sample_rate = config.sample_rate.0;
let bytes_per_channel = config.sample_format.sample_size(); let bytes_per_channel = sample_format.sample_size();
let bits_per_channel = bytes_per_channel * 8; let bits_per_channel = bytes_per_channel * 8;
let bytes_per_frame = n_channels * bytes_per_channel; let bytes_per_frame = n_channels * bytes_per_channel;
let frames_per_packet = 1; let frames_per_packet = 1;
let bytes_per_packet = frames_per_packet * bytes_per_frame; let bytes_per_packet = frames_per_packet * bytes_per_frame;
let sample_format = config.sample_format;
let format_flags = match sample_format { let format_flags = match sample_format {
SampleFormat::F32 => (kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked) as u32, SampleFormat::F32 => (kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked) as u32,
_ => kAudioFormatFlagIsPacked as u32, _ => kAudioFormatFlagIsPacked as u32,
@ -475,7 +480,8 @@ fn audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, cor
impl Device { impl Device {
fn build_input_stream_raw<D, E>( fn build_input_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
mut data_callback: D, mut data_callback: D,
_error_callback: E, _error_callback: E,
) -> Result<Stream, BuildStreamError> ) -> Result<Stream, BuildStreamError>
@ -625,12 +631,11 @@ impl Device {
let mut audio_unit = audio_unit_from_device(self, true)?; let mut audio_unit = audio_unit_from_device(self, true)?;
// Set the stream in interleaved mode. // Set the stream in interleaved mode.
let asbd = asbd_from_config(config); let asbd = asbd_from_config(config, sample_format);
audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?; audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
// Register the callback that is being called by coreaudio whenever it needs data to be // Register the callback that is being called by coreaudio whenever it needs data to be
// fed to the audio buffer. // fed to the audio buffer.
let sample_format = config.sample_format;
let bytes_per_channel = sample_format.sample_size(); let bytes_per_channel = sample_format.sample_size();
type Args = render_callback::Args<data::Raw>; type Args = render_callback::Args<data::Raw>;
audio_unit.set_input_callback(move |args: Args| unsafe { audio_unit.set_input_callback(move |args: Args| unsafe {
@ -663,7 +668,8 @@ impl Device {
fn build_output_stream_raw<D, E>( fn build_output_stream_raw<D, E>(
&self, &self,
config: &SupportedStreamConfig, config: &StreamConfig,
sample_format: SampleFormat,
mut data_callback: D, mut data_callback: D,
_error_callback: E, _error_callback: E,
) -> Result<Stream, BuildStreamError> ) -> Result<Stream, BuildStreamError>
@ -678,12 +684,11 @@ impl Device {
let element = Element::Output; let element = Element::Output;
// Set the stream in interleaved mode. // Set the stream in interleaved mode.
let asbd = asbd_from_config(config); let asbd = asbd_from_config(config, sample_format);
audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?; audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
// Register the callback that is being called by coreaudio whenever it needs data to be // Register the callback that is being called by coreaudio whenever it needs data to be
// fed to the audio buffer. // fed to the audio buffer.
let sample_format = config.sample_format;
let bytes_per_channel = sample_format.sample_size(); let bytes_per_channel = sample_format.sample_size();
type Args = render_callback::Args<data::Raw>; type Args = render_callback::Args<data::Raw>;
audio_unit.set_render_callback(move |args: Args| unsafe { audio_unit.set_render_callback(move |args: Args| unsafe {