Update CoreAudio backend for removal of `UnknownBufferType`

This commit is contained in:
mitchmindtree 2020-01-15 17:21:11 +01:00
parent 9e832c6eb3
commit 6fbb701826
2 changed files with 86 additions and 72 deletions

View File

@ -10,7 +10,7 @@ keywords = ["audio", "sound", "asio", "steinberg"]
build = "build.rs"
[target.'cfg(any(target_os = "windows"))'.build-dependencies]
bindgen = "0.42.0"
bindgen = "0.51.0"
walkdir = "2"
cc = "1.0.25"

View File

@ -1,35 +1,26 @@
extern crate coreaudio;
extern crate core_foundation_sys;
use ChannelCount;
use BackendSpecificError;
use BuildStreamError;
use DefaultFormatError;
use DeviceNameError;
use DevicesError;
use Format;
use PauseStreamError;
use PlayStreamError;
use SupportedFormatsError;
use SampleFormat;
use SampleRate;
use StreamData;
use StreamError;
use SupportedFormat;
use UnknownTypeInputBuffer;
use UnknownTypeOutputBuffer;
use traits::{DeviceTrait, HostTrait, StreamTrait};
use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::cell::RefCell;
use std::os::raw::c_char;
use std::ptr::null;
use std::slice;
use std::thread;
use std::time::Duration;
use crate::{
ChannelCount,
BackendSpecificError,
BuildStreamError,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
InputData,
OutputData,
PauseStreamError,
PlayStreamError,
Sample,
SampleFormat,
SampleRate,
StreamError,
SupportedFormat,
SupportedFormatsError,
};
use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
use self::coreaudio::audio_unit::{AudioUnit, Scope, Element};
use self::coreaudio::audio_unit::render_callback::{self, data};
use self::coreaudio::sys::{
@ -69,6 +60,15 @@ use self::core_foundation_sys::string::{
CFStringRef,
CFStringGetCStringPtr,
};
use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::cell::RefCell;
use std::os::raw::c_char;
use std::ptr::null;
use std::slice;
use std::thread;
use std::time::Duration;
mod enumerate;
@ -131,11 +131,33 @@ impl DeviceTrait for Device {
Device::default_output_format(self)
}
fn build_input_stream<D, E>(&self, format: &Format, data_callback: D, error_callback: E) -> Result<Self::Stream, BuildStreamError> where D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static {
fn build_input_stream<T, D, E>(
&self,
format: &Format,
data_callback: D,
error_callback: E,
) -> Result<Self::Stream, BuildStreamError>
where
T: Sample,
D: FnMut(InputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static,
{
assert_eq!(T::FORMAT, format.data_type);
Device::build_input_stream(self, format, data_callback, error_callback)
}
fn build_output_stream<D, E>(&self, format: &Format, data_callback: D, error_callback: E) -> Result<Self::Stream, BuildStreamError> where D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static {
fn build_output_stream<T, D, E>(
&self,
format: &Format,
data_callback: D,
error_callback: E,
) -> Result<Self::Stream, BuildStreamError>
where
T: Sample,
D: FnMut(OutputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static,
{
assert_eq!(T::FORMAT, format.data_type);
Device::build_output_stream(self, format, data_callback, error_callback)
}
}
@ -478,7 +500,17 @@ fn audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, cor
}
impl Device {
fn build_input_stream<D, E>(&self, format: &Format, mut data_callback: D, _error_callback: E) -> Result<Stream, BuildStreamError> where D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static {
fn build_input_stream<T, D, E>(
&self,
format: &Format,
mut data_callback: D,
_error_callback: E,
) -> Result<Stream, BuildStreamError>
where
T: Sample,
D: FnMut(InputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static,
{
// The scope and element for working with a device's input stream.
let scope = Scope::Output;
let element = Element::Input;
@ -625,8 +657,7 @@ impl Device {
// Register the callback that is being called by coreaudio whenever it needs data to be
// fed to the audio buffer.
let sample_format = format.data_type;
let bytes_per_channel = format.data_type.sample_size();
let bytes_per_channel = std::mem::size_of::<T>();
type Args = render_callback::Args<data::Raw>;
audio_unit.set_input_callback(move |args: Args| unsafe {
let ptr = (*args.data.data).mBuffers.as_ptr() as *const AudioBuffer;
@ -640,23 +671,10 @@ impl Device {
mData: data
} = buffers[0];
// A small macro to simplify handling the callback for different sample types.
macro_rules! try_callback {
($SampleFormat:ident, $SampleType:ty) => {{
let data_len = (data_byte_size as usize / bytes_per_channel) as usize;
let data_slice = slice::from_raw_parts(data as *const $SampleType, data_len);
let unknown_type_buffer = UnknownTypeInputBuffer::$SampleFormat(::InputBuffer { buffer: data_slice });
let stream_data = StreamData::Input { buffer: unknown_type_buffer };
data_callback(stream_data);
}};
}
match sample_format {
SampleFormat::F32 => try_callback!(F32, f32),
SampleFormat::I16 => try_callback!(I16, i16),
SampleFormat::U16 => try_callback!(U16, u16),
}
let data_slice = slice::from_raw_parts(data as *const T, data_len);
let input_data = InputData { buffer: data_slice };
data_callback(input_data);
Ok(())
})?;
@ -669,7 +687,17 @@ impl Device {
}))
}
fn build_output_stream<D, E>(&self, format: &Format, mut data_callback: D, _error_callback: E) -> Result<Stream, BuildStreamError> where D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static {
fn build_output_stream<T, D, E>(
&self,
format: &Format,
mut data_callback: D,
_error_callback: E,
) -> Result<Stream, BuildStreamError>
where
T: Sample,
D: FnMut(OutputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static,
{
let mut audio_unit = audio_unit_from_device(self, false)?;
// The scope and element for working with a device's output stream.
@ -682,8 +710,7 @@ impl Device {
// Register the callback that is being called by coreaudio whenever it needs data to be
// fed to the audio buffer.
let sample_format = format.data_type;
let bytes_per_channel = format.data_type.sample_size();
let bytes_per_channel = std::mem::size_of::<T>();
type Args = render_callback::Args<data::Raw>;
audio_unit.set_render_callback(move |args: Args| unsafe {
// If `run()` is currently running, then a callback will be available from this list.
@ -695,23 +722,10 @@ impl Device {
mData: data
} = (*args.data.data).mBuffers[0];
// A small macro to simplify handling the callback for different sample types.
macro_rules! try_callback {
($SampleFormat:ident, $SampleType:ty, $equilibrium:expr) => {{
let data_len = (data_byte_size as usize / bytes_per_channel) as usize;
let data_slice = slice::from_raw_parts_mut(data as *mut $SampleType, data_len);
let unknown_type_buffer = UnknownTypeOutputBuffer::$SampleFormat(::OutputBuffer { buffer: data_slice });
let stream_data = StreamData::Output { buffer: unknown_type_buffer };
data_callback(stream_data);
}};
}
match sample_format {
SampleFormat::F32 => try_callback!(F32, f32, 0.0),
SampleFormat::I16 => try_callback!(I16, i16, 0),
SampleFormat::U16 => try_callback!(U16, u16, ::std::u16::MAX / 2),
}
let data_slice = slice::from_raw_parts_mut(data as *mut T, data_len);
let output_data = OutputData { buffer: data_slice };
data_callback(output_data);
Ok(())
})?;