From 8193bc9f790777b8e316de640b1190869088a062 Mon Sep 17 00:00:00 2001 From: Tom Gowan Date: Mon, 29 Oct 2018 22:57:42 +1100 Subject: [PATCH] sharing asio streams --- asio-sys/src/lib.rs | 198 +++++------ src/platform/windows/asio/stream.rs | 510 +++++++++++++++------------- 2 files changed, 363 insertions(+), 345 deletions(-) diff --git a/asio-sys/src/lib.rs b/asio-sys/src/lib.rs index b2655c2..7d77ef6 100644 --- a/asio-sys/src/lib.rs +++ b/asio-sys/src/lib.rs @@ -34,7 +34,7 @@ pub struct CbArgs { struct BufferCallback(Box); lazy_static! { - static ref buffer_callback: Mutex<[Option; 2]> = Mutex::new([None, None]); + static ref buffer_callback: Mutex>> = Mutex::new(Vec::new()); } lazy_static! { @@ -62,6 +62,11 @@ struct DriverWrapper { pub drivers: ai::AsioDrivers, } +pub struct AsioStreams { + pub input: Option, + pub output: Option, +} + pub struct AsioStream { pub buffer_infos: Vec, 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 { + pub fn prepare_input_stream(&self, output: Option, mut num_channels: usize) -> Result { 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 = buffer_infos - .into_iter() - .map(|bi| mem::transmute::(bi)) - .collect(); - let mut callbacks_convert = - mem::transmute::(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 = buffer_info_convert - .into_iter() - .map(|bi| mem::transmute::(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 { + pub fn prepare_output_stream(&self, input: Option, num_channels: usize) -> Result { // 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 { + 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) + -> Result<(Vec, 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 = buffer_infos .into_iter() .map(|bi| mem::transmute::(bi)) .collect(); let mut callbacks_convert = mem::transmute::(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 = buffer_info_convert .into_iter() .map(|bi| mem::transmute::(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(input: bool, mut callback: F) -> () +pub fn set_callback(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 diff --git a/src/platform/windows/asio/stream.rs b/src/platform/windows/asio/stream.rs index 3407d75..c76c07f 100644 --- a/src/platform/windows/asio/stream.rs +++ b/src/platform/windows/asio/stream.rs @@ -16,7 +16,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use SampleFormat; pub struct EventLoop { - asio_streams: Arc>>>, + asio_streams: Arc>, stream_count: AtomicUsize, callbacks: Arc>>, } @@ -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 { + 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 { + 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 { - 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 { + 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(&self, mut callback: F) -> ! where