Update asio backend for stream format renaming
This commit is contained in:
parent
3a692f8bca
commit
f292391190
|
@ -1,20 +1,20 @@
|
||||||
use std;
|
use std;
|
||||||
pub type SupportedInputFormats = std::vec::IntoIter<SupportedFormat>;
|
pub type SupportedInputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
|
||||||
pub type SupportedOutputFormats = std::vec::IntoIter<SupportedFormat>;
|
pub type SupportedOutputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
|
||||||
|
|
||||||
use super::parking_lot::Mutex;
|
use super::parking_lot::Mutex;
|
||||||
use super::sys;
|
use super::sys;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use BackendSpecificError;
|
use BackendSpecificError;
|
||||||
use DefaultFormatError;
|
use DefaultStreamConfigError;
|
||||||
use DeviceNameError;
|
use DeviceNameError;
|
||||||
use DevicesError;
|
use DevicesError;
|
||||||
use Format;
|
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use SampleRate;
|
use SampleRate;
|
||||||
use SupportedFormat;
|
use SupportedStreamConfig;
|
||||||
use SupportedFormatsError;
|
use SupportedStreamConfigRange;
|
||||||
|
use SupportedStreamConfigsError;
|
||||||
|
|
||||||
/// A ASIO Device
|
/// A ASIO Device
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
|
@ -52,52 +52,21 @@ impl Device {
|
||||||
Ok(self.driver.name().to_string())
|
Ok(self.driver.name().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the supported input formats.
|
/// Gets the supported input configs.
|
||||||
/// TODO currently only supports the default.
|
/// TODO currently only supports the default.
|
||||||
/// Need to find all possible formats.
|
/// Need to find all possible configs.
|
||||||
pub fn supported_input_formats(&self) -> Result<SupportedInputFormats, SupportedFormatsError> {
|
pub fn supported_input_configs(
|
||||||
// Retrieve the default format for the total supported channels and supported sample
|
|
||||||
// format.
|
|
||||||
let mut f = match self.default_input_format() {
|
|
||||||
Err(_) => return Err(SupportedFormatsError::DeviceNotAvailable),
|
|
||||||
Ok(f) => f,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Collect a format for every combination of supported sample rate and number of channels.
|
|
||||||
let mut supported_formats = vec![];
|
|
||||||
for &rate in ::COMMON_SAMPLE_RATES {
|
|
||||||
if !self
|
|
||||||
.driver
|
|
||||||
.can_sample_rate(rate.0.into())
|
|
||||||
.ok()
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for channels in 1..f.channels + 1 {
|
|
||||||
f.channels = channels;
|
|
||||||
f.sample_rate = rate;
|
|
||||||
supported_formats.push(SupportedFormat::from(f.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(supported_formats.into_iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the supported output formats.
|
|
||||||
/// TODO currently only supports the default.
|
|
||||||
/// Need to find all possible formats.
|
|
||||||
pub fn supported_output_formats(
|
|
||||||
&self,
|
&self,
|
||||||
) -> Result<SupportedOutputFormats, SupportedFormatsError> {
|
) -> Result<SupportedInputConfigs, SupportedStreamConfigsError> {
|
||||||
// Retrieve the default format for the total supported channels and supported sample
|
// Retrieve the default config for the total supported channels and supported sample
|
||||||
// format.
|
// format.
|
||||||
let mut f = match self.default_output_format() {
|
let mut f = match self.default_input_config() {
|
||||||
Err(_) => return Err(SupportedFormatsError::DeviceNotAvailable),
|
Err(_) => return Err(SupportedStreamConfigsError::DeviceNotAvailable),
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collect a format for every combination of supported sample rate and number of channels.
|
// Collect a config for every combination of supported sample rate and number of channels.
|
||||||
let mut supported_formats = vec![];
|
let mut supported_configs = vec![];
|
||||||
for &rate in ::COMMON_SAMPLE_RATES {
|
for &rate in ::COMMON_SAMPLE_RATES {
|
||||||
if !self
|
if !self
|
||||||
.driver
|
.driver
|
||||||
|
@ -110,38 +79,71 @@ impl Device {
|
||||||
for channels in 1..f.channels + 1 {
|
for channels in 1..f.channels + 1 {
|
||||||
f.channels = channels;
|
f.channels = channels;
|
||||||
f.sample_rate = rate;
|
f.sample_rate = rate;
|
||||||
supported_formats.push(SupportedFormat::from(f.clone()));
|
supported_configs.push(SupportedStreamConfigRange::from(f.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(supported_formats.into_iter())
|
Ok(supported_configs.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default input format
|
/// Gets the supported output configs.
|
||||||
pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
|
/// TODO currently only supports the default.
|
||||||
let channels = self.driver.channels().map_err(default_format_err)?.ins as u16;
|
/// Need to find all possible configs.
|
||||||
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_format_err)? as _);
|
pub fn supported_output_configs(
|
||||||
|
&self,
|
||||||
|
) -> Result<SupportedOutputConfigs, SupportedStreamConfigsError> {
|
||||||
|
// Retrieve the default config for the total supported channels and supported sample
|
||||||
|
// format.
|
||||||
|
let mut f = match self.default_output_config() {
|
||||||
|
Err(_) => return Err(SupportedStreamConfigsError::DeviceNotAvailable),
|
||||||
|
Ok(f) => f,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collect a config for every combination of supported sample rate and number of channels.
|
||||||
|
let mut supported_configs = vec![];
|
||||||
|
for &rate in ::COMMON_SAMPLE_RATES {
|
||||||
|
if !self
|
||||||
|
.driver
|
||||||
|
.can_sample_rate(rate.0.into())
|
||||||
|
.ok()
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for channels in 1..f.channels + 1 {
|
||||||
|
f.channels = channels;
|
||||||
|
f.sample_rate = rate;
|
||||||
|
supported_configs.push(SupportedStreamConfigRange::from(f.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(supported_configs.into_iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the default input config
|
||||||
|
pub fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
|
||||||
|
let channels = self.driver.channels().map_err(default_config_err)?.ins as u16;
|
||||||
|
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _);
|
||||||
// Map th ASIO sample type to a CPAL sample type
|
// Map th ASIO sample type to a CPAL sample type
|
||||||
let data_type = self.driver.input_data_type().map_err(default_format_err)?;
|
let data_type = self.driver.input_data_type().map_err(default_config_err)?;
|
||||||
let data_type =
|
let sample_format = convert_data_type(&data_type)
|
||||||
convert_data_type(&data_type).ok_or(DefaultFormatError::StreamTypeNotSupported)?;
|
.ok_or(DefaultStreamConfigError::StreamTypeNotSupported)?;
|
||||||
Ok(Format {
|
Ok(SupportedStreamConfig {
|
||||||
channels,
|
channels,
|
||||||
sample_rate,
|
sample_rate,
|
||||||
data_type,
|
sample_format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default output format
|
/// Returns the default output config
|
||||||
pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
pub fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
|
||||||
let channels = self.driver.channels().map_err(default_format_err)?.outs as u16;
|
let channels = self.driver.channels().map_err(default_config_err)?.outs as u16;
|
||||||
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_format_err)? as _);
|
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _);
|
||||||
let data_type = self.driver.output_data_type().map_err(default_format_err)?;
|
let data_type = self.driver.output_data_type().map_err(default_config_err)?;
|
||||||
let data_type =
|
let sample_format = convert_data_type(&data_type)
|
||||||
convert_data_type(&data_type).ok_or(DefaultFormatError::StreamTypeNotSupported)?;
|
.ok_or(DefaultStreamConfigError::StreamTypeNotSupported)?;
|
||||||
Ok(Format {
|
Ok(SupportedStreamConfig {
|
||||||
channels,
|
channels,
|
||||||
sample_rate,
|
sample_rate,
|
||||||
data_type,
|
sample_format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,12 +204,12 @@ pub(crate) fn convert_data_type(ty: &sys::AsioSampleType) -> Option<SampleFormat
|
||||||
Some(fmt)
|
Some(fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_format_err(e: sys::AsioError) -> DefaultFormatError {
|
fn default_config_err(e: sys::AsioError) -> DefaultStreamConfigError {
|
||||||
match e {
|
match e {
|
||||||
sys::AsioError::NoDrivers | sys::AsioError::HardwareMalfunction => {
|
sys::AsioError::NoDrivers | sys::AsioError::HardwareMalfunction => {
|
||||||
DefaultFormatError::DeviceNotAvailable
|
DefaultStreamConfigError::DeviceNotAvailable
|
||||||
}
|
}
|
||||||
sys::AsioError::NoRate => DefaultFormatError::StreamTypeNotSupported,
|
sys::AsioError::NoRate => DefaultStreamConfigError::StreamTypeNotSupported,
|
||||||
err => {
|
err => {
|
||||||
let description = format!("{}", err);
|
let description = format!("{}", err);
|
||||||
BackendSpecificError { description }.into()
|
BackendSpecificError { description }.into()
|
||||||
|
|
|
@ -2,12 +2,13 @@ extern crate asio_sys as sys;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BuildStreamError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
|
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
PauseStreamError, PlayStreamError, StreamError, SupportedFormatsError,
|
PauseStreamError, PlayStreamError, StreamError, SupportedStreamConfig,
|
||||||
|
SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
|
|
||||||
pub use self::device::{Device, Devices, SupportedInputFormats, SupportedOutputFormats};
|
pub use self::device::{Device, Devices, SupportedInputConfigs, SupportedOutputConfigs};
|
||||||
pub use self::stream::Stream;
|
pub use self::stream::Stream;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -53,37 +54,37 @@ impl HostTrait for Host {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceTrait for Device {
|
impl DeviceTrait for Device {
|
||||||
type SupportedInputFormats = SupportedInputFormats;
|
type SupportedInputConfigs = SupportedInputConfigs;
|
||||||
type SupportedOutputFormats = SupportedOutputFormats;
|
type SupportedOutputConfigs = SupportedOutputConfigs;
|
||||||
type Stream = Stream;
|
type Stream = Stream;
|
||||||
|
|
||||||
fn name(&self) -> Result<String, DeviceNameError> {
|
fn name(&self) -> Result<String, DeviceNameError> {
|
||||||
Device::name(self)
|
Device::name(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supported_input_formats(
|
fn supported_input_configs(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
|
) -> Result<Self::SupportedInputConfigs, SupportedStreamConfigsError> {
|
||||||
Device::supported_input_formats(self)
|
Device::supported_input_configs(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supported_output_formats(
|
fn supported_output_configs(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
|
) -> Result<Self::SupportedOutputConfigs, SupportedStreamConfigsError> {
|
||||||
Device::supported_output_formats(self)
|
Device::supported_output_configs(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
|
fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
|
||||||
Device::default_input_format(self)
|
Device::default_input_config(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
|
||||||
Device::default_output_format(self)
|
Device::default_output_config(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_input_stream_raw<D, E>(
|
fn build_input_stream_raw<D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
config: &SupportedStreamConfig,
|
||||||
data_callback: D,
|
data_callback: D,
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
|
@ -91,12 +92,12 @@ 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, format, data_callback, error_callback)
|
Device::build_input_stream_raw(self, config, data_callback, error_callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_output_stream_raw<D, E>(
|
fn build_output_stream_raw<D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
config: &SupportedStreamConfig,
|
||||||
data_callback: D,
|
data_callback: D,
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
|
@ -104,7 +105,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, format, data_callback, error_callback)
|
Device::build_output_stream_raw(self, config, data_callback, error_callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ use std::sync::Arc;
|
||||||
use BackendSpecificError;
|
use BackendSpecificError;
|
||||||
use BuildStreamError;
|
use BuildStreamError;
|
||||||
use Data;
|
use Data;
|
||||||
use Format;
|
|
||||||
use PauseStreamError;
|
use PauseStreamError;
|
||||||
use PlayStreamError;
|
use PlayStreamError;
|
||||||
use Sample;
|
use Sample;
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use StreamError;
|
use StreamError;
|
||||||
|
use SupportedStreamConfig;
|
||||||
|
|
||||||
/// Sample types whose constant silent value is known.
|
/// Sample types whose constant silent value is known.
|
||||||
trait Silence {
|
trait Silence {
|
||||||
|
@ -59,7 +59,7 @@ impl Stream {
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn build_input_stream_raw<D, E>(
|
pub fn build_input_stream_raw<D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
config: &SupportedStreamConfig,
|
||||||
mut data_callback: D,
|
mut data_callback: D,
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
|
@ -70,18 +70,18 @@ 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 data_type = super::device::convert_data_type(&stream_type)
|
let sample_format = super::device::convert_data_type(&stream_type)
|
||||||
.ok_or(BuildStreamError::FormatNotSupported)?;
|
.ok_or(BuildStreamError::FormatNotSupported)?;
|
||||||
if format.data_type != data_type {
|
if config.sample_format != sample_format {
|
||||||
return Err(BuildStreamError::FormatNotSupported);
|
return Err(BuildStreamError::FormatNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = config.channels.clone();
|
||||||
let buffer_size = self.get_or_create_input_stream(format)?;
|
let buffer_size = self.get_or_create_input_stream(config)?;
|
||||||
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.
|
||||||
let len_bytes = cpal_num_samples * data_type.sample_size();
|
let len_bytes = cpal_num_samples * sample_format.sample_size();
|
||||||
let mut interleaved = vec![0u8; len_bytes];
|
let mut interleaved = vec![0u8; len_bytes];
|
||||||
|
|
||||||
let stream_playing = Arc::new(AtomicBool::new(false));
|
let stream_playing = Arc::new(AtomicBool::new(false));
|
||||||
|
@ -134,7 +134,7 @@ impl Device {
|
||||||
callback(&data);
|
callback(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
match (&stream_type, data_type) {
|
match (&stream_type, sample_format) {
|
||||||
(&sys::AsioSampleType::ASIOSTInt16LSB, SampleFormat::I16) => {
|
(&sys::AsioSampleType::ASIOSTInt16LSB, SampleFormat::I16) => {
|
||||||
process_input_callback::<i16, i16, _, _>(
|
process_input_callback::<i16, i16, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
|
@ -225,7 +225,7 @@ impl Device {
|
||||||
|
|
||||||
pub fn build_output_stream_raw<D, E>(
|
pub fn build_output_stream_raw<D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
config: &SupportedStreamConfig,
|
||||||
mut data_callback: D,
|
mut data_callback: D,
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
|
@ -236,18 +236,18 @@ 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 data_type = super::device::convert_data_type(&stream_type)
|
let sample_format = super::device::convert_data_type(&stream_type)
|
||||||
.ok_or(BuildStreamError::FormatNotSupported)?;
|
.ok_or(BuildStreamError::FormatNotSupported)?;
|
||||||
if format.data_type != data_type {
|
if config.sample_format != sample_format {
|
||||||
return Err(BuildStreamError::FormatNotSupported);
|
return Err(BuildStreamError::FormatNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = config.channels.clone();
|
||||||
let buffer_size = self.get_or_create_output_stream(format)?;
|
let buffer_size = self.get_or_create_output_stream(config)?;
|
||||||
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.
|
||||||
let len_bytes = cpal_num_samples * data_type.sample_size();
|
let len_bytes = cpal_num_samples * sample_format.sample_size();
|
||||||
let mut interleaved = vec![0u8; len_bytes];
|
let mut interleaved = vec![0u8; len_bytes];
|
||||||
let mut silence_asio_buffer = SilenceAsioBuffer::default();
|
let mut silence_asio_buffer = SilenceAsioBuffer::default();
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (data_type, &stream_type) {
|
match (sample_format, &stream_type) {
|
||||||
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16LSB) => {
|
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16LSB) => {
|
||||||
process_output_callback::<i16, i16, _, _>(
|
process_output_callback::<i16, i16, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
|
@ -436,15 +436,18 @@ impl Device {
|
||||||
/// If there is no existing ASIO Input Stream it will be created.
|
/// If there is no existing ASIO Input Stream it will be created.
|
||||||
///
|
///
|
||||||
/// 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(&self, format: &Format) -> Result<usize, BuildStreamError> {
|
fn get_or_create_input_stream(
|
||||||
match self.default_input_format() {
|
&self,
|
||||||
|
config: &SupportedStreamConfig,
|
||||||
|
) -> Result<usize, BuildStreamError> {
|
||||||
|
match self.default_input_config() {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
let num_asio_channels = f.channels;
|
let num_asio_channels = f.channels;
|
||||||
check_format(&self.driver, format, num_asio_channels)
|
check_config(&self.driver, config, num_asio_channels)
|
||||||
}
|
}
|
||||||
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
||||||
}?;
|
}?;
|
||||||
let num_channels = format.channels as usize;
|
let num_channels = config.channels as usize;
|
||||||
let ref mut streams = *self.asio_streams.lock();
|
let ref mut streams = *self.asio_streams.lock();
|
||||||
// Either create a stream if thers none or had back the
|
// Either create a stream if thers none or had back the
|
||||||
// size of the current one.
|
// size of the current one.
|
||||||
|
@ -473,15 +476,18 @@ impl Device {
|
||||||
/// Create a new CPAL Output Stream.
|
/// Create a new CPAL Output Stream.
|
||||||
///
|
///
|
||||||
/// 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(&self, format: &Format) -> Result<usize, BuildStreamError> {
|
fn get_or_create_output_stream(
|
||||||
match self.default_output_format() {
|
&self,
|
||||||
|
config: &SupportedStreamConfig,
|
||||||
|
) -> Result<usize, BuildStreamError> {
|
||||||
|
match self.default_output_config() {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
let num_asio_channels = f.channels;
|
let num_asio_channels = f.channels;
|
||||||
check_format(&self.driver, format, num_asio_channels)
|
check_config(&self.driver, config, num_asio_channels)
|
||||||
}
|
}
|
||||||
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
||||||
}?;
|
}?;
|
||||||
let num_channels = format.channels as usize;
|
let num_channels = config.channels as usize;
|
||||||
let ref mut streams = *self.asio_streams.lock();
|
let ref mut streams = *self.asio_streams.lock();
|
||||||
// Either create a stream if thers none or had back the
|
// Either create a stream if thers none or had back the
|
||||||
// size of the current one.
|
// size of the current one.
|
||||||
|
@ -570,19 +576,19 @@ impl AsioSample for f64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether or not the desired format is supported by the stream.
|
/// Check whether or not the desired config is supported by the stream.
|
||||||
///
|
///
|
||||||
/// 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_format(
|
fn check_config(
|
||||||
driver: &sys::Driver,
|
driver: &sys::Driver,
|
||||||
format: &Format,
|
config: &SupportedStreamConfig,
|
||||||
num_asio_channels: u16,
|
num_asio_channels: u16,
|
||||||
) -> Result<(), BuildStreamError> {
|
) -> Result<(), BuildStreamError> {
|
||||||
let Format {
|
let SupportedStreamConfig {
|
||||||
channels,
|
channels,
|
||||||
sample_rate,
|
sample_rate,
|
||||||
data_type,
|
sample_format,
|
||||||
} = format;
|
} = 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();
|
||||||
if sample_rate != driver.sample_rate().map_err(build_stream_err)? {
|
if sample_rate != driver.sample_rate().map_err(build_stream_err)? {
|
||||||
|
@ -598,7 +604,7 @@ fn check_format(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// unsigned formats are not supported by asio
|
// unsigned formats are not supported by asio
|
||||||
match data_type {
|
match sample_format {
|
||||||
SampleFormat::I16 | SampleFormat::F32 => (),
|
SampleFormat::I16 | SampleFormat::F32 => (),
|
||||||
SampleFormat::U16 => return Err(BuildStreamError::FormatNotSupported),
|
SampleFormat::U16 => return Err(BuildStreamError::FormatNotSupported),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue