sharing asio streams

This commit is contained in:
Tom Gowan 2018-10-29 22:57:42 +11:00 committed by mitchmindtree
parent 76eb07a274
commit 8193bc9f79
2 changed files with 363 additions and 345 deletions

View File

@ -34,7 +34,7 @@ pub struct CbArgs<S, D> {
struct BufferCallback(Box<FnMut(i32) + Send>);
lazy_static! {
static ref buffer_callback: Mutex<[Option<BufferCallback>; 2]> = Mutex::new([None, None]);
static ref buffer_callback: Mutex<Vec<Option<BufferCallback>>> = Mutex::new(Vec::new());
}
lazy_static! {
@ -62,6 +62,11 @@ struct DriverWrapper {
pub drivers: ai::AsioDrivers,
}
pub struct AsioStreams {
pub input: Option<AsioStream>,
pub output: Option<AsioStream>,
}
pub struct AsioStream {
pub buffer_infos: Vec<AsioBufferInfo>,
pub buffer_size: i32,
@ -127,21 +132,13 @@ struct AsioCallbacks {
direct_process: c_long,
) -> *mut ai::ASIOTime,
}
extern "C" fn buffer_switch_output(double_buffer_index: c_long, direct_process: c_long) -> () {
let mut bc = buffer_callback.lock().unwrap();
println!("output");
extern "C" fn buffer_switch(double_buffer_index: c_long, direct_process: c_long) -> () {
let mut bcs = buffer_callback.lock().unwrap();
if let Some(ref mut bc) = bc[0] {
bc.run(double_buffer_index);
}
}
extern "C" fn buffer_switch_input(double_buffer_index: c_long, direct_process: c_long) -> () {
let mut bc = buffer_callback.lock().unwrap();
println!("input");
if let Some(ref mut bc) = bc[1] {
bc.run(double_buffer_index);
for mut bc in bcs.iter_mut() {
if let Some(ref mut bc) = bc {
bc.run(double_buffer_index);
}
}
}
@ -258,7 +255,7 @@ impl Drivers {
}
}
pub fn prepare_input_stream(&self, num_channels: usize) -> Result<AsioStream, AsioDriverError> {
pub fn prepare_input_stream(&self, output: Option<AsioStream>, mut num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
let mut buffer_infos = vec![
AsioBufferInfo {
is_input: 1,
@ -267,74 +264,13 @@ impl Drivers {
};
num_channels
];
let mut callbacks = AsioCallbacks {
buffer_switch: buffer_switch_input,
sample_rate_did_change: sample_rate_did_change,
asio_message: asio_message,
buffer_switch_time_info: buffer_switch_time_info,
};
let mut min_b_size: c_long = 0;
let mut max_b_size: c_long = 0;
let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0;
let mut result = Err(AsioDriverError::NoResult("not implimented".to_owned()));
unsafe {
asio_get_buffer_size(
&mut min_b_size,
&mut max_b_size,
&mut pref_b_size,
&mut grans,
).expect("Failed getting buffers");
result = if pref_b_size > 0 {
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos
.into_iter()
.map(|bi| mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(bi))
.collect();
let mut callbacks_convert =
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
let buffer_result = asio_create_buffers(
buffer_info_convert.as_mut_ptr(),
num_channels as i32,
pref_b_size,
&mut callbacks_convert,
);
if buffer_result.is_ok() {
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert
.into_iter()
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
.collect();
for d in &buffer_infos {
println!("after {:?}", d);
}
println!("channels: {:?}", num_channels);
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
return Ok(AsioStream {
buffer_infos: buffer_infos,
buffer_size: pref_b_size,
});
}
Err(AsioDriverError::BufferError(format!(
"failed to create buffers,
error \
code: {:?}",
buffer_result
)))
} else {
Err(AsioDriverError::BufferError(
"Failed to get buffer size".to_owned(),
))
};
}
result
let streams = AsioStreams{input: Some(AsioStream{buffer_infos, buffer_size: 0}), output};
self.create_streams(streams)
}
/// Creates the output stream
pub fn prepare_output_stream(&self, num_channels: usize) -> Result<AsioStream, AsioDriverError> {
pub fn prepare_output_stream(&self, input: Option<AsioStream>, num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
// Initialize data for FFI
let mut buffer_infos = vec![
AsioBufferInfo {
@ -344,9 +280,66 @@ impl Drivers {
};
num_channels
];
let streams = AsioStreams{output: Some(AsioStream{buffer_infos, buffer_size: 0}), input};
self.create_streams(streams)
}
/// Creates the output stream
fn create_streams(&self, streams: AsioStreams) -> Result<AsioStreams, AsioDriverError> {
let AsioStreams {
input,
output,
} = streams;
match (input, output) {
(Some(input), Some(mut output)) => {
let split_point = input.buffer_infos.len();
let mut bi = input.buffer_infos;
bi.append(&mut output.buffer_infos);
self.create_buffers(bi)
.map(|(mut bi, buffer_size)|{
let out_bi = bi.split_off(split_point);
let in_bi = bi;
let output = Some(AsioStream{
buffer_infos: out_bi,
buffer_size,
});
let input = Some(AsioStream{
buffer_infos: in_bi,
buffer_size,
});
AsioStreams{output, input}
})
},
(Some(input), None) => {
self.create_buffers(input.buffer_infos)
.map(|(buffer_infos, buffer_size)| AsioStreams{
input: Some(AsioStream{
buffer_infos,
buffer_size,
}),
output: None,
})
},
(None, Some(output)) => {
self.create_buffers(output.buffer_infos)
.map(|(buffer_infos, buffer_size)| AsioStreams{
output: Some(AsioStream{
buffer_infos,
buffer_size,
}),
input: None,
})
},
(None, None) => panic!("Trying to create streams without preparing"),
}
}
fn create_buffers(&self, buffer_infos: Vec<AsioBufferInfo>)
-> Result<(Vec<AsioBufferInfo>, c_long), AsioDriverError>{
let num_channels = buffer_infos.len();
let mut callbacks = AsioCallbacks {
buffer_switch: buffer_switch_output,
buffer_switch: buffer_switch,
sample_rate_did_change: sample_rate_did_change,
asio_message: asio_message,
buffer_switch_time_info: buffer_switch_time_info,
@ -357,7 +350,7 @@ impl Drivers {
let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0;
let mut result = Err(AsioDriverError::NoResult("not implimented".to_owned()));
//let mut result = Err(AsioDriverError::NoResult("not implimented".to_owned()));
unsafe {
// Get the buffer sizes
@ -371,20 +364,19 @@ impl Drivers {
&mut pref_b_size,
&mut grans,
).expect("Failed getting buffers");
result = if pref_b_size > 0 {
if pref_b_size > 0 {
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos
.into_iter()
.map(|bi| mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(bi))
.collect();
let mut callbacks_convert =
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
let buffer_result = asio_create_buffers(
asio_create_buffers(
buffer_info_convert.as_mut_ptr(),
num_channels as i32,
pref_b_size,
&mut callbacks_convert,
);
if buffer_result.is_ok() {
).map(|_|{
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert
.into_iter()
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
@ -395,22 +387,17 @@ impl Drivers {
println!("channels: {:?}", num_channels);
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
return Ok(AsioStream {
buffer_infos: buffer_infos,
buffer_size: pref_b_size,
});
}
Err(AsioDriverError::BufferError(format!(
"failed to create buffers, error code: {:?}",
buffer_result
)))
(buffer_infos, pref_b_size)
}).map_err(|e|{
AsioDriverError::BufferError(format!(
"failed to create buffers, error code: {:?}", e))
})
} else {
Err(AsioDriverError::BufferError(
"Failed to get buffer size".to_owned(),
"bad buffer size".to_owned(),
))
};
}
}
result
}
}
@ -428,7 +415,7 @@ impl Drop for Drivers {
}
}
}
/* TODO this should be tied to cpal streams and not AsioStreams
impl Drop for AsioStream {
fn drop(&mut self) {
println!("dropping stream");
@ -443,6 +430,7 @@ impl Drop for AsioStream {
}
}
}
*/
unsafe impl Send for DriverWrapper {}
@ -455,18 +443,12 @@ impl BufferCallback {
unsafe impl Send for AsioStream {}
pub fn set_callback<F: 'static>(input: bool, mut callback: F) -> ()
pub fn set_callback<F: 'static>(mut callback: F) -> ()
where
F: FnMut(i32) + Send,
{
let mut bc = buffer_callback.lock().unwrap();
if input {
println!("Set input callback");
bc[1] = Some(BufferCallback(Box::new(callback)));
}else{
println!("Set output callback");
bc[0] = Some(BufferCallback(Box::new(callback)));
}
bc.push(Some(BufferCallback(Box::new(callback))));
}
/// Returns a list of all the ASIO drivers

View File

@ -16,7 +16,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use SampleFormat;
pub struct EventLoop {
asio_streams: Arc<Mutex<Vec<Option<sys::AsioStream>>>>,
asio_streams: Arc<Mutex<sys::AsioStreams>>,
stream_count: AtomicUsize,
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
}
@ -55,12 +55,58 @@ struct Buffers {
impl EventLoop {
pub fn new() -> EventLoop {
EventLoop {
asio_streams: Arc::new(Mutex::new(Vec::new())),
asio_streams: Arc::new(Mutex::new(sys::AsioStreams{input: None, output: None})),
stream_count: AtomicUsize::new(0),
callbacks: Arc::new(Mutex::new(Vec::new())),
}
}
fn get_input_stream(&self, drivers: &sys::Drivers, num_channels: usize) -> Result<usize, CreationError> {
let ref mut streams = *self.asio_streams.lock().unwrap();
match streams.input {
Some(ref input) => Ok(input.buffer_size as usize),
None => {
let output = streams.output.take();
drivers.prepare_input_stream(output, num_channels)
.map(|new_streams| {
let bs = match new_streams.input {
Some(ref inp) => inp.buffer_size as usize,
None => unreachable!(),
};
*streams = new_streams;
bs
})
.map_err(|ref e| {
println!("Error preparing stream: {}", e);
CreationError::DeviceNotAvailable
})
}
}
}
fn get_output_stream(&self, drivers: &sys::Drivers, num_channels: usize) -> Result<usize, CreationError> {
let ref mut streams = *self.asio_streams.lock().unwrap();
match streams.output {
Some(ref output) => Ok(output.buffer_size as usize),
None => {
let input = streams.input.take();
drivers.prepare_output_stream(input, num_channels)
.map(|new_streams| {
let bs = match new_streams.output {
Some(ref out) => out.buffer_size as usize,
None => unreachable!(),
};
*streams = new_streams;
bs
})
.map_err(|ref e| {
println!("Error preparing stream: {}", e);
CreationError::DeviceNotAvailable
})
},
}
}
pub fn build_input_stream(
&self,
device: &Device,
@ -72,190 +118,20 @@ impl EventLoop {
} = device;
let num_channels = format.channels.clone();
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
match drivers.prepare_input_stream(num_channels as usize) {
Ok(stream) => {
let cpal_num_samples =
(stream.buffer_size as usize) * num_channels as usize;
{
self.asio_streams.lock().unwrap().push(Some(stream));
}
let count = self.stream_count.load(Ordering::SeqCst);
self.stream_count.store(count + 1, Ordering::SeqCst);
let asio_streams = self.asio_streams.clone();
let callbacks = self.callbacks.clone();
let bytes_per_channel = format.data_type.sample_size();
// Create buffers
let channel_len = cpal_num_samples
/ num_channels as usize;
let mut buffers = match format.data_type{
SampleFormat::I16 => {
Buffers{
i16_buff: I16Buffer{
cpal: vec![0 as i16; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
u16_buff: U16Buffer::default(),
f32_buff: F32Buffer::default(),
}
}
SampleFormat::U16 => {
Buffers{
i16_buff: I16Buffer::default(),
u16_buff: U16Buffer{
cpal: vec![0 as u16; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
f32_buff: F32Buffer::default(),
}
}
SampleFormat::F32 => {
Buffers{
i16_buff: I16Buffer::default(),
u16_buff: U16Buffer::default(),
f32_buff: F32Buffer{
cpal: vec![0 as f32; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
}
}
};
sys::set_callback(true, move |index| unsafe {
if let Some(ref asio_stream) = asio_streams.lock().unwrap()[count - 1] {
// Number of samples needed total
let mut callbacks = callbacks.lock().unwrap();
// Assuming only one callback, probably needs to change
match callbacks.first_mut() {
Some(callback) => {
macro_rules! try_callback {
($SampleFormat:ident,
$SampleType:ty,
$SampleTypeIdent:ident,
$AsioType:ty,
$AsioTypeIdent:ident,
$Buffers:expr,
$BuffersType:ty,
$BuffersTypeIdent:ident
) => {
// For each channel write the cpal data to
// the asio buffer
// Also need to check for Endian
for (i, channel) in $Buffers.channel.iter_mut().enumerate(){
let buff_ptr = asio_stream
.buffer_infos[i]
.buffers[index as usize] as *mut $AsioType;
let asio_buffer: &'static [$AsioType] =
std::slice::from_raw_parts(
buff_ptr,
asio_stream.buffer_size as usize);
for asio_s in asio_buffer.iter(){
channel.push( (*asio_s as i64 *
::std::$SampleTypeIdent::MAX as i64 /
::std::$AsioTypeIdent::MAX as i64) as $SampleType);
}
}
// interleave all the channels
{
let $BuffersTypeIdent {
cpal: ref mut c_buffer,
channel: ref mut channels,
} = $Buffers;
au::interleave(&channels, c_buffer);
for c in channels.iter_mut() {
c.clear();
}
}
let buff = InputBuffer{
buffer: &mut $Buffers.cpal,
};
callback(
StreamId(count),
StreamData::Input{
buffer: UnknownTypeInputBuffer::$SampleFormat(
::InputBuffer{
buffer: Some(super::super::InputBuffer::Asio(buff))
})
}
);
}
};
// Generic over types
// TODO check for endianess
match stream_type {
sys::AsioSampleType::ASIOSTInt32LSB => {
try_callback!(I16, i16, i16, i32, i32,
buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTInt16LSB => {
try_callback!(I16, i16, i16, i16, i16,
buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTFloat32LSB => {
try_callback!(F32, f32, f32, f32, f32,
buffers.f32_buff, F32Buffer, F32Buffer);
}
sys::AsioSampleType::ASIOSTFloat64LSB => {
try_callback!(F32, f32, f32, f64, f64,
buffers.f32_buff, F32Buffer, F32Buffer);
}
_ => println!("unsupported format {:?}", stream_type),
}
}
None => return (),
}
}
});
Ok(StreamId(count))
}
Err(ref e) => {
println!("Error preparing stream: {}", e);
Err(CreationError::DeviceNotAvailable)
}
}
}
pub fn build_output_stream(
&self,
device: &Device,
format: &Format,
) -> Result<StreamId, CreationError> {
let Device {
drivers,
..
} = device;
let num_channels = format.channels.clone();
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
match drivers.prepare_output_stream(num_channels as usize) {
Ok(stream) => {
let cpal_num_samples =
(stream.buffer_size as usize) * num_channels as usize;
{
self.asio_streams.lock().unwrap().push(Some(stream));
}
self.get_input_stream(&drivers, num_channels as usize).map(|stream_buffer_size| {
let cpal_num_samples = stream_buffer_size * num_channels as usize;
let count = self.stream_count.load(Ordering::SeqCst);
self.stream_count.store(count + 1, Ordering::SeqCst);
let asio_streams = self.asio_streams.clone();
let callbacks = self.callbacks.clone();
let bytes_per_channel = format.data_type.sample_size();
// Create buffers
let channel_len = cpal_num_samples
/ num_channels as usize;
let mut re_buffers = match format.data_type{
let mut buffers = match format.data_type{
SampleFormat::I16 => {
Buffers{
i16_buff: I16Buffer{
@ -291,8 +167,8 @@ pub fn build_output_stream(
}
};
sys::set_callback(false, move |index| unsafe {
if let Some(ref asio_stream) = asio_streams.lock().unwrap()[count - 1] {
sys::set_callback(move |index| unsafe {
if let Some(ref asio_stream) = asio_streams.lock().unwrap().input {
// Number of samples needed total
let mut callbacks = callbacks.lock().unwrap();
@ -301,81 +177,80 @@ pub fn build_output_stream(
Some(callback) => {
macro_rules! try_callback {
($SampleFormat:ident,
$SampleType:ty,
$SampleTypeIdent:ident,
$AsioType:ty,
$AsioTypeIdent:ident,
$Buffers:expr,
$BuffersType:ty,
$BuffersTypeIdent:ident
) => {
let mut my_buffers = $Buffers;
// Buffer that is filled by cpal.
//let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples];
// Call in block because of mut borrow
{
let buff = OutputBuffer{
buffer: &mut my_buffers.cpal
};
callback(
StreamId(count),
StreamData::Output{
buffer: UnknownTypeOutputBuffer::$SampleFormat(
::OutputBuffer{
target: Some(super::super::OutputBuffer::Asio(buff))
})
}
);
}
// Deinter all the channels
{
let $BuffersTypeIdent {
cpal: ref mut c_buffer,
channel: ref mut channels,
} = my_buffers;
au::deinterleave(&c_buffer[..], channels);
}
$SampleType:ty,
$SampleTypeIdent:ident,
$AsioType:ty,
$AsioTypeIdent:ident,
$Buffers:expr,
$BuffersType:ty,
$BuffersTypeIdent:ident
) => {
// For each channel write the cpal data to
// the asio buffer
// Also need to check for Endian
for (i, channel) in my_buffers.channel.iter().enumerate(){
let buff_ptr = (asio_stream
for (i, channel) in $Buffers.channel.iter_mut().enumerate(){
let buff_ptr = asio_stream
.buffer_infos[i]
.buffers[index as usize] as *mut $AsioType)
.offset(asio_stream.buffer_size as isize * i as isize);
let asio_buffer: &'static mut [$AsioType] =
std::slice::from_raw_parts_mut(
.buffers[index as usize] as *mut $AsioType;
let asio_buffer: &'static [$AsioType] =
std::slice::from_raw_parts(
buff_ptr,
asio_stream.buffer_size as usize);
for (asio_s, cpal_s) in asio_buffer.iter_mut()
.zip(channel){
*asio_s = (*cpal_s as i64 *
::std::$AsioTypeIdent::MAX as i64 /
::std::$SampleTypeIdent::MAX as i64) as $AsioType;
}
for asio_s in asio_buffer.iter(){
channel.push( (*asio_s as i64 *
::std::$SampleTypeIdent::MAX as i64 /
::std::$AsioTypeIdent::MAX as i64) as $SampleType);
}
}
};
}
// interleave all the channels
{
let $BuffersTypeIdent {
cpal: ref mut c_buffer,
channel: ref mut channels,
} = $Buffers;
au::interleave(&channels, c_buffer);
for c in channels.iter_mut() {
c.clear();
}
}
let buff = InputBuffer{
buffer: &mut $Buffers.cpal,
};
callback(
StreamId(count),
StreamData::Input{
buffer: UnknownTypeInputBuffer::$SampleFormat(
::InputBuffer{
buffer: Some(super::super::InputBuffer::Asio(buff))
})
}
);
}
};
// Generic over types
// TODO check for endianess
match stream_type {
sys::AsioSampleType::ASIOSTInt32LSB => {
try_callback!(I16, i16, i16, i32, i32,
&mut re_buffers.i16_buff, I16Buffer, I16Buffer);
buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTInt16LSB => {
try_callback!(I16, i16, i16, i16, i16,
&mut re_buffers.i16_buff, I16Buffer, I16Buffer);
buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTFloat32LSB => {
try_callback!(F32, f32, f32, f32, f32,
&mut re_buffers.f32_buff, F32Buffer, F32Buffer);
buffers.f32_buff, F32Buffer, F32Buffer);
}
sys::AsioSampleType::ASIOSTFloat64LSB => {
try_callback!(F32, f32, f32, f64, f64,
&mut re_buffers.f32_buff, F32Buffer, F32Buffer);
buffers.f32_buff, F32Buffer, F32Buffer);
}
_ => println!("unsupported format {:?}", stream_type),
}
@ -384,13 +259,166 @@ pub fn build_output_stream(
}
}
});
Ok(StreamId(count))
}
Err(ref e) => {
println!("Error preparing stream: {}", e);
Err(CreationError::DeviceNotAvailable)
}
StreamId(count)
})
}
pub fn build_output_stream(
&self,
device: &Device,
format: &Format,
) -> Result<StreamId, CreationError> {
let Device {
drivers,
..
} = device;
let num_channels = format.channels.clone();
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
self.get_output_stream(&drivers, num_channels as usize).map(|stream_buffer_size| {
let cpal_num_samples = stream_buffer_size * num_channels as usize;
let count = self.stream_count.load(Ordering::SeqCst);
self.stream_count.store(count + 1, Ordering::SeqCst);
let asio_streams = self.asio_streams.clone();
let callbacks = self.callbacks.clone();
let bytes_per_channel = format.data_type.sample_size();
// Create buffers
let channel_len = cpal_num_samples
/ num_channels as usize;
let mut re_buffers = match format.data_type{
SampleFormat::I16 => {
Buffers{
i16_buff: I16Buffer{
cpal: vec![0 as i16; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
u16_buff: U16Buffer::default(),
f32_buff: F32Buffer::default(),
}
}
SampleFormat::U16 => {
Buffers{
i16_buff: I16Buffer::default(),
u16_buff: U16Buffer{
cpal: vec![0 as u16; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
f32_buff: F32Buffer::default(),
}
}
SampleFormat::F32 => {
Buffers{
i16_buff: I16Buffer::default(),
u16_buff: U16Buffer::default(),
f32_buff: F32Buffer{
cpal: vec![0 as f32; cpal_num_samples],
channel: (0..num_channels)
.map(|_| Vec::with_capacity(channel_len))
.collect()},
}
}
};
sys::set_callback(move |index| unsafe {
if let Some(ref asio_stream) = asio_streams.lock().unwrap().output {
// Number of samples needed total
let mut callbacks = callbacks.lock().unwrap();
// Assuming only one callback, probably needs to change
match callbacks.first_mut() {
Some(callback) => {
macro_rules! try_callback {
($SampleFormat:ident,
$SampleType:ty,
$SampleTypeIdent:ident,
$AsioType:ty,
$AsioTypeIdent:ident,
$Buffers:expr,
$BuffersType:ty,
$BuffersTypeIdent:ident
) => {
let mut my_buffers = $Buffers;
// Buffer that is filled by cpal.
//let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples];
// Call in block because of mut borrow
{
let buff = OutputBuffer{
buffer: &mut my_buffers.cpal
};
callback(
StreamId(count),
StreamData::Output{
buffer: UnknownTypeOutputBuffer::$SampleFormat(
::OutputBuffer{
target: Some(super::super::OutputBuffer::Asio(buff))
})
}
);
}
// Deinter all the channels
{
let $BuffersTypeIdent {
cpal: ref mut c_buffer,
channel: ref mut channels,
} = my_buffers;
au::deinterleave(&c_buffer[..], channels);
}
// For each channel write the cpal data to
// the asio buffer
// TODO need to check for Endian
for (i, channel) in my_buffers.channel.iter().enumerate(){
let buff_ptr = (asio_stream
.buffer_infos[i]
.buffers[index as usize] as *mut $AsioType)
// I'm not sure if this is needed anymore
// Why should we offset the pointer?
.offset(asio_stream.buffer_size as isize * i as isize);
let asio_buffer: &'static mut [$AsioType] =
std::slice::from_raw_parts_mut(
buff_ptr,
asio_stream.buffer_size as usize);
for (asio_s, cpal_s) in asio_buffer.iter_mut()
.zip(channel){
*asio_s = (*cpal_s as i64 *
::std::$AsioTypeIdent::MAX as i64 /
::std::$SampleTypeIdent::MAX as i64) as $AsioType;
}
}
};
}
// Generic over types
// TODO check for endianess
match stream_type {
sys::AsioSampleType::ASIOSTInt32LSB => {
try_callback!(I16, i16, i16, i32, i32,
&mut re_buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTInt16LSB => {
try_callback!(I16, i16, i16, i16, i16,
&mut re_buffers.i16_buff, I16Buffer, I16Buffer);
}
sys::AsioSampleType::ASIOSTFloat32LSB => {
try_callback!(F32, f32, f32, f32, f32,
&mut re_buffers.f32_buff, F32Buffer, F32Buffer);
}
sys::AsioSampleType::ASIOSTFloat64LSB => {
try_callback!(F32, f32, f32, f64, f64,
&mut re_buffers.f32_buff, F32Buffer, F32Buffer);
}
_ => println!("unsupported format {:?}", stream_type),
}
}
None => return (),
}
}
});
StreamId(count)
})
}
pub fn play_stream(&self, stream: StreamId) {
@ -400,12 +428,20 @@ pub fn play_stream(&self, stream: StreamId) {
pub fn pause_stream(&self, stream: StreamId) {
sys::stop();
}
// TODO the logic for this is wrong
// We are not destroying AsioStreams but CPAL streams
// Asio Streams should only be destroyed if there are no
// CPAL streams left
pub fn destroy_stream(&self, stream_id: StreamId) {
/*
let mut asio_streams_lock = self.asio_streams.lock().unwrap();
let old_stream = mem::replace(asio_streams_lock.get_mut(stream_id.0 - 1).expect("stream count out of bounds"), None);
if let Some(old_stream) = old_stream {
sys::destroy_stream(old_stream);
}
*/
unimplemented!()
}
pub fn run<F>(&self, mut callback: F) -> !
where