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