Keep driver alive
This commit is contained in:
parent
ae7a03d788
commit
2ef7008615
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue