Keep driver alive

This commit is contained in:
Tom Gowan 2018-10-16 22:25:37 +11:00 committed by mitchmindtree
parent ae7a03d788
commit 2ef7008615
1 changed files with 71 additions and 22 deletions

View File

@ -17,6 +17,7 @@ use std::os::raw::c_double;
use errors::ASIOError; use errors::ASIOError;
use std::mem; use std::mem;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use asio_import as ai; use asio_import as ai;
@ -33,6 +34,12 @@ lazy_static!{
static ref buffer_callback: Mutex<Option<BufferCallback>> = Mutex::new(None); static ref buffer_callback: Mutex<Option<BufferCallback>> = Mutex::new(None);
} }
lazy_static!{
static ref ASIO_DRIVERS: Mutex<Option<DriverWrapper>> = Mutex::new(None);
}
static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)] #[derive(Debug)]
pub struct Channel { pub struct Channel {
pub ins: i64, pub ins: i64,
@ -45,9 +52,7 @@ pub struct SampleRate {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Drivers { pub struct Drivers;
drivers: Arc<Mutex<DriverWrapper>>,
}
#[derive(Debug)] #[derive(Debug)]
struct DriverWrapper { struct DriverWrapper {
@ -151,19 +156,30 @@ extern "C" fn buffer_switch_time_info(
impl Drivers { impl Drivers {
pub fn load(driver_name: &str) -> Result<Self, ASIOError> { pub fn load(driver_name: &str) -> Result<Self, ASIOError> {
// Make owned CString to send to load driver let mut drivers = ASIO_DRIVERS.lock().unwrap();
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString"); match *drivers {
let raw = my_driver_name.into_raw(); Some(_) => {
unsafe { STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
let mut asio_drivers = ai::AsioDrivers::new(); Ok(Drivers{})
let load_result = asio_drivers.loadDriver(raw); },
// Take back ownership None => {
my_driver_name = CString::from_raw(raw); // Make owned CString to send to load driver
if load_result { let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
Ok(Drivers{ drivers: Arc::new(Mutex::new(DriverWrapper{drivers: asio_drivers})) }) let raw = my_driver_name.into_raw();
} else { unsafe {
Err(ASIOError::DriverLoadError) let mut asio_drivers = ai::AsioDrivers::new();
} let load_result = asio_drivers.loadDriver(raw);
// Take back ownership
my_driver_name = CString::from_raw(raw);
if load_result {
*drivers = Some(DriverWrapper{drivers: asio_drivers});
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
Ok(Drivers{})
} else {
Err(ASIOError::DriverLoadError)
}
}
},
} }
} }
@ -305,6 +321,7 @@ impl Drivers {
} }
println!("channels: {:?}", num_channels); println!("channels: {:?}", num_channels);
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
return Ok(AsioStream { return Ok(AsioStream {
buffer_infos: buffer_infos, buffer_infos: buffer_infos,
buffer_size: pref_b_size, buffer_size: pref_b_size,
@ -324,7 +341,9 @@ impl Drivers {
result result
} }
/// Creates the output stream
pub fn prepare_output_stream(&self) -> Result<AsioStream, ASIOError> { pub fn prepare_output_stream(&self) -> Result<AsioStream, ASIOError> {
// Initialize data for FFI
let mut buffer_infos = [ let mut buffer_infos = [
AsioBufferInfo { AsioBufferInfo {
is_input: 0, is_input: 0,
@ -358,7 +377,13 @@ impl Drivers {
let mut result = Err(ASIOError::NoResult("not implimented".to_owned())); let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
unsafe { unsafe {
// Initialize ASIO stream
ai::ASIOInit(&mut driver_info); ai::ASIOInit(&mut driver_info);
// Get the buffer sizes
// min possilbe size
// max possible size
// preferred size
// granularity
ai::ASIOGetBufferSize( ai::ASIOGetBufferSize(
&mut min_b_size, &mut min_b_size,
&mut max_b_size, &mut max_b_size,
@ -388,15 +413,14 @@ impl Drivers {
} }
println!("channels: {:?}", num_channels); println!("channels: {:?}", num_channels);
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
return Ok(AsioStream { return Ok(AsioStream {
buffer_infos: buffer_infos, buffer_infos: buffer_infos,
buffer_size: pref_b_size, buffer_size: pref_b_size,
}); });
} }
Err(ASIOError::BufferError(format!( Err(ASIOError::BufferError(format!(
"failed to create buffers, "failed to create buffers, error code: {}", buffer_result
error code: {}",
buffer_result
))) )))
} else { } else {
Err(ASIOError::BufferError( Err(ASIOError::BufferError(
@ -408,14 +432,38 @@ impl Drivers {
} }
} }
impl Drop for DriverWrapper { impl Drop for Drivers {
fn drop(&mut self) { fn drop(&mut self) {
unsafe{ println!("dropping drivers");
ai::destruct_AsioDrivers(&mut self.drivers); let count = STREAM_DRIVER_COUNT.fetch_sub(1, Ordering::SeqCst);
if count == 1 {
println!("Destroying driver");
unsafe{
if let Some(mut asio_drivers) = (*ASIO_DRIVERS.lock().unwrap()).take() {
ai::destruct_AsioDrivers(&mut asio_drivers.drivers);
}
}
} }
} }
} }
impl Drop for AsioStream {
fn drop(&mut self) {
println!("dropping stream");
let count = STREAM_DRIVER_COUNT.fetch_sub(1, Ordering::SeqCst);
if count == 1 {
println!("Destroying driver");
unsafe{
if let Some(mut asio_drivers) = (*ASIO_DRIVERS.lock().unwrap()).take() {
ai::destruct_AsioDrivers(&mut asio_drivers.drivers);
}
}
}
}
}
unsafe impl Send for DriverWrapper {}
impl BufferCallback { impl BufferCallback {
fn run(&mut self, index: i32) { fn run(&mut self, index: i32) {
let mut cb = &mut self.0; let mut cb = &mut self.0;
@ -476,6 +524,7 @@ pub fn get_driver_list() -> Vec<String> {
pub fn destroy_stream(stream: AsioStream) { pub fn destroy_stream(stream: AsioStream) {
unsafe { unsafe {
ai::ASIODisposeBuffers(); ai::ASIODisposeBuffers();
ai::ASIOExit();
} }
} }