Fixed driver bug
This commit is contained in:
parent
6a71f0a801
commit
5ec6da3aad
|
@ -1,9 +1,20 @@
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
extern "C" void destruct_AsioDrivers(AsioDrivers * a){
|
|
||||||
a->~AsioDrivers();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" ASIOError get_sample_rate(double * rate){
|
extern "C" ASIOError get_sample_rate(double * rate){
|
||||||
return ASIOGetSampleRate(reinterpret_cast<ASIOSampleRate *>(rate));
|
return ASIOGetSampleRate(reinterpret_cast<ASIOSampleRate *>(rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern AsioDrivers* asioDrivers;
|
||||||
|
bool loadAsioDriver(char *name);
|
||||||
|
|
||||||
|
extern "C" bool load_asio_driver(char * name){
|
||||||
|
return loadAsioDriver(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void remove_current_driver() {
|
||||||
|
asioDrivers->removeCurrentDriver();
|
||||||
|
}
|
||||||
|
extern "C" long get_driver_names(char **names, long maxDrivers) {
|
||||||
|
AsioDrivers ad;
|
||||||
|
return ad.getDriverNames(names, maxDrivers);
|
||||||
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
#include "asiodrivers.h"
|
#include "asiodrivers.h"
|
||||||
#include "asio.h"
|
#include "asio.h"
|
||||||
|
|
||||||
// Helper function to call destructors from within library
|
|
||||||
extern "C" void destruct_AsioDrivers(AsioDrivers * a);
|
|
||||||
|
|
||||||
// Helper function to wrap confusing preprocessor
|
// Helper function to wrap confusing preprocessor
|
||||||
extern "C" ASIOError get_sample_rate(double * rate);
|
extern "C" ASIOError get_sample_rate(double * rate);
|
||||||
|
|
||||||
|
extern "C" bool load_asio_driver(char * name);
|
||||||
|
extern "C" void remove_current_driver();
|
||||||
|
extern "C" long get_driver_names(char **names, long maxDrivers);
|
|
@ -163,7 +163,6 @@ fn create_bindings(cpal_asio_dir: &PathBuf) {
|
||||||
.whitelist_type("ASIOCallbacks")
|
.whitelist_type("ASIOCallbacks")
|
||||||
.whitelist_type("ASIOSampleType")
|
.whitelist_type("ASIOSampleType")
|
||||||
.whitelist_type("ASIOChannelInfo")
|
.whitelist_type("ASIOChannelInfo")
|
||||||
.whitelist_function("destruct_AsioDrivers")
|
|
||||||
.whitelist_function("ASIOGetChannels")
|
.whitelist_function("ASIOGetChannels")
|
||||||
.whitelist_function("ASIOGetChannelInfo")
|
.whitelist_function("ASIOGetChannelInfo")
|
||||||
.whitelist_function("ASIOGetBufferSize")
|
.whitelist_function("ASIOGetBufferSize")
|
||||||
|
@ -174,6 +173,9 @@ fn create_bindings(cpal_asio_dir: &PathBuf) {
|
||||||
.whitelist_function("ASIOStop")
|
.whitelist_function("ASIOStop")
|
||||||
.whitelist_function("ASIODisposeBuffers")
|
.whitelist_function("ASIODisposeBuffers")
|
||||||
.whitelist_function("ASIOExit")
|
.whitelist_function("ASIOExit")
|
||||||
|
.whitelist_function("load_asio_driver")
|
||||||
|
.whitelist_function("remove_current_driver")
|
||||||
|
.whitelist_function("get_driver_names")
|
||||||
// Finish the builder and generate the bindings.
|
// Finish the builder and generate the bindings.
|
||||||
.generate()
|
.generate()
|
||||||
// Unwrap the Result and panic on failure.
|
// Unwrap the Result and panic on failure.
|
||||||
|
|
|
@ -15,17 +15,12 @@ use errors::{AsioError, AsioDriverError, AsioErrorWrapper};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::{c_char, c_double, c_long, c_void};
|
||||||
use std::os::raw::c_double;
|
|
||||||
use std::os::raw::c_long;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Mutex, MutexGuard};
|
||||||
use std::sync::MutexGuard;
|
|
||||||
|
|
||||||
use asio_import as ai;
|
use asio_import as ai;
|
||||||
|
|
||||||
const MAX_DRIVER: usize = 32;
|
|
||||||
|
|
||||||
pub struct CbArgs<S, D> {
|
pub struct CbArgs<S, D> {
|
||||||
pub stream_id: S,
|
pub stream_id: S,
|
||||||
|
@ -39,8 +34,7 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ASIO_DRIVERS: Mutex<DriverWrapper> = Mutex::new(DriverWrapper{
|
static ref ASIO_DRIVERS: Mutex<AsioWrapper> = Mutex::new(AsioWrapper{
|
||||||
drivers: None,
|
|
||||||
state: AsioState::Offline,
|
state: AsioState::Offline,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,8 +58,7 @@ pub struct SampleRate {
|
||||||
pub struct Drivers;
|
pub struct Drivers;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DriverWrapper {
|
struct AsioWrapper {
|
||||||
drivers: Option<ai::AsioDrivers>,
|
|
||||||
state: AsioState,
|
state: AsioState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +71,7 @@ enum AsioState {
|
||||||
Running,
|
Running,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct AsioStreams {
|
pub struct AsioStreams {
|
||||||
pub input: Option<AsioStream>,
|
pub input: Option<AsioStream>,
|
||||||
pub output: Option<AsioStream>,
|
pub output: Option<AsioStream>,
|
||||||
|
@ -132,7 +126,7 @@ pub enum AsioSampleType {
|
||||||
pub struct AsioBufferInfo {
|
pub struct AsioBufferInfo {
|
||||||
pub is_input: c_long,
|
pub is_input: c_long,
|
||||||
pub channel_num: c_long,
|
pub channel_num: c_long,
|
||||||
pub buffers: [*mut std::os::raw::c_void; 2],
|
pub buffers: [*mut c_void; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -148,7 +142,7 @@ struct AsioCallbacks {
|
||||||
direct_process: c_long,
|
direct_process: c_long,
|
||||||
) -> *mut ai::ASIOTime,
|
) -> *mut ai::ASIOTime,
|
||||||
}
|
}
|
||||||
extern "C" fn buffer_switch(double_buffer_index: c_long, direct_process: c_long) -> () {
|
extern "C" fn buffer_switch(double_buffer_index: c_long, _direct_process: c_long) -> () {
|
||||||
let mut bcs = buffer_callback.lock().unwrap();
|
let mut bcs = buffer_callback.lock().unwrap();
|
||||||
|
|
||||||
for mut bc in bcs.iter_mut() {
|
for mut bc in bcs.iter_mut() {
|
||||||
|
@ -158,29 +152,28 @@ extern "C" fn buffer_switch(double_buffer_index: c_long, direct_process: c_long)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn sample_rate_did_change(s_rate: c_double) -> () {}
|
extern "C" fn sample_rate_did_change(_s_rate: c_double) -> () {}
|
||||||
|
|
||||||
extern "C" fn asio_message(
|
extern "C" fn asio_message(
|
||||||
selector: c_long, value: c_long, message: *mut (), opt: *mut c_double,
|
_selector: c_long, _value: c_long, _message: *mut (), _opt: *mut c_double,
|
||||||
) -> c_long {
|
) -> c_long {
|
||||||
4 as c_long
|
4 as c_long
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn buffer_switch_time_info(
|
extern "C" fn buffer_switch_time_info(
|
||||||
params: *mut ai::ASIOTime, double_buffer_index: c_long, direct_process: c_long,
|
params: *mut ai::ASIOTime, _double_buffer_index: c_long, _direct_process: c_long,
|
||||||
) -> *mut ai::ASIOTime {
|
) -> *mut ai::ASIOTime {
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_drivers() -> MutexGuard<'static, DriverWrapper> {
|
fn get_drivers() -> MutexGuard<'static, AsioWrapper> {
|
||||||
ASIO_DRIVERS.lock().unwrap()
|
ASIO_DRIVERS.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drivers {
|
impl Drivers {
|
||||||
|
#[allow(unused_assignments)]
|
||||||
pub fn load(driver_name: &str) -> Result<Self, AsioDriverError> {
|
pub fn load(driver_name: &str) -> Result<Self, AsioDriverError> {
|
||||||
let mut drivers = get_drivers();
|
let mut drivers = get_drivers();
|
||||||
match drivers.state {
|
|
||||||
AsioState::Offline => {
|
|
||||||
// Make owned CString to send to load driver
|
// Make owned CString to send to load driver
|
||||||
let mut my_driver_name =
|
let mut my_driver_name =
|
||||||
CString::new(driver_name).expect("Can't go from str to CString");
|
CString::new(driver_name).expect("Can't go from str to CString");
|
||||||
|
@ -189,27 +182,23 @@ impl Drivers {
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut asio_drivers = ai::AsioDrivers::new();
|
let load_result = drivers.load(raw);
|
||||||
let load_result = asio_drivers.loadDriver(raw);
|
|
||||||
if load_result { drivers.state = AsioState::Loaded; }
|
|
||||||
let init_result = drivers.asio_init(&mut driver_info);
|
|
||||||
// Take back ownership
|
// Take back ownership
|
||||||
my_driver_name = CString::from_raw(raw);
|
my_driver_name = CString::from_raw(raw);
|
||||||
if load_result && init_result.is_ok() {
|
if load_result {
|
||||||
println!("Creating drivers");
|
match drivers.asio_init(&mut driver_info) {
|
||||||
drivers.drivers = Some(asio_drivers);
|
Ok(_) => {
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
Ok(Drivers)
|
Ok(Drivers)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
Err(AsioDriverError::DriverLoadError)
|
||||||
|
},
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(AsioDriverError::DriverLoadError)
|
Err(AsioDriverError::DriverLoadError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
|
||||||
Ok(Drivers)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the channels for the driver it's passed
|
/// Returns the channels for the driver it's passed
|
||||||
|
@ -274,8 +263,8 @@ impl Drivers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_input_stream(&self, output: Option<AsioStream>, mut num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
|
pub fn prepare_input_stream(&self, output: Option<AsioStream>, num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
|
||||||
let mut buffer_infos = vec![
|
let buffer_infos = vec![
|
||||||
AsioBufferInfo {
|
AsioBufferInfo {
|
||||||
is_input: 1,
|
is_input: 1,
|
||||||
channel_num: 0,
|
channel_num: 0,
|
||||||
|
@ -291,7 +280,7 @@ impl Drivers {
|
||||||
/// Creates the output stream
|
/// Creates the output stream
|
||||||
pub fn prepare_output_stream(&self, input: Option<AsioStream>, num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
|
pub fn prepare_output_stream(&self, input: Option<AsioStream>, num_channels: usize) -> Result<AsioStreams, AsioDriverError> {
|
||||||
// Initialize data for FFI
|
// Initialize data for FFI
|
||||||
let mut buffer_infos = vec![
|
let buffer_infos = vec![
|
||||||
AsioBufferInfo {
|
AsioBufferInfo {
|
||||||
is_input: 0,
|
is_input: 0,
|
||||||
channel_num: 0,
|
channel_num: 0,
|
||||||
|
@ -363,7 +352,7 @@ impl Drivers {
|
||||||
fn create_buffers(&self, buffer_infos: Vec<AsioBufferInfo>)
|
fn create_buffers(&self, buffer_infos: Vec<AsioBufferInfo>)
|
||||||
-> Result<(Vec<AsioBufferInfo>, c_long), AsioDriverError>{
|
-> Result<(Vec<AsioBufferInfo>, c_long), AsioDriverError>{
|
||||||
let num_channels = buffer_infos.len();
|
let num_channels = buffer_infos.len();
|
||||||
let mut callbacks = AsioCallbacks {
|
let callbacks = AsioCallbacks {
|
||||||
buffer_switch: buffer_switch,
|
buffer_switch: buffer_switch,
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
asio_message: asio_message,
|
asio_message: asio_message,
|
||||||
|
@ -402,7 +391,7 @@ impl Drivers {
|
||||||
pref_b_size,
|
pref_b_size,
|
||||||
&mut callbacks_convert,
|
&mut callbacks_convert,
|
||||||
).map(|_|{
|
).map(|_|{
|
||||||
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert
|
let buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
|
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -427,27 +416,25 @@ impl Drivers {
|
||||||
|
|
||||||
impl Drop for Drivers {
|
impl Drop for Drivers {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
println!("dropping drivers");
|
|
||||||
let count = STREAM_DRIVER_COUNT.fetch_sub(1, Ordering::SeqCst);
|
let count = STREAM_DRIVER_COUNT.fetch_sub(1, Ordering::SeqCst);
|
||||||
if count == 1 {
|
if count == 1 {
|
||||||
println!("Destroying driver");
|
|
||||||
clean_up();
|
clean_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for DriverWrapper {}
|
unsafe impl Send for AsioWrapper {}
|
||||||
|
|
||||||
impl BufferCallback {
|
impl BufferCallback {
|
||||||
fn run(&mut self, index: i32) {
|
fn run(&mut self, index: i32) {
|
||||||
let mut cb = &mut self.0;
|
let cb = &mut self.0;
|
||||||
cb(index);
|
cb(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for AsioStream {}
|
unsafe impl Send for AsioStream {}
|
||||||
|
|
||||||
pub fn set_callback<F: 'static>(mut callback: F) -> ()
|
pub fn set_callback<F: 'static>(callback: F) -> ()
|
||||||
where
|
where
|
||||||
F: FnMut(i32) + Send,
|
F: FnMut(i32) + Send,
|
||||||
{
|
{
|
||||||
|
@ -456,82 +443,36 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of all the ASIO drivers
|
/// Returns a list of all the ASIO drivers
|
||||||
//TODO this needs to not create and remove drivers
|
#[allow(unused_assignments)]
|
||||||
pub fn get_driver_list() -> Vec<String> {
|
pub fn get_driver_list() -> Vec<String> {
|
||||||
let mut driver_list: Vec<String> = Vec::new();
|
const MAX_DRIVERS: usize = 100;
|
||||||
|
const CHAR_LEN: usize = 32;
|
||||||
|
|
||||||
let mut driver_names: [[c_char; MAX_DRIVER]; MAX_DRIVER] = [[0; MAX_DRIVER]; MAX_DRIVER];
|
let mut driver_names: [[c_char; CHAR_LEN]; MAX_DRIVERS] = [[0; CHAR_LEN]; MAX_DRIVERS];
|
||||||
let mut p_driver_name: [*mut i8; MAX_DRIVER] = [0 as *mut i8; MAX_DRIVER];
|
let mut p_driver_name: [*mut i8; MAX_DRIVERS] = [0 as *mut i8; MAX_DRIVERS];
|
||||||
|
|
||||||
for i in 0 .. MAX_DRIVER {
|
for i in 0 .. MAX_DRIVERS {
|
||||||
p_driver_name[i] = driver_names[i].as_mut_ptr();
|
p_driver_name[i] = driver_names[i].as_mut_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut asio_drivers = ai::AsioDrivers::new();
|
let num_drivers = ai::get_driver_names(p_driver_name.as_mut_ptr(), MAX_DRIVERS as i32);
|
||||||
|
|
||||||
let num_drivers =
|
(0..num_drivers)
|
||||||
asio_drivers.getDriverNames(p_driver_name.as_mut_ptr(), MAX_DRIVER as i32);
|
.map(|i|{
|
||||||
|
|
||||||
if num_drivers > 0 {
|
|
||||||
for i in 0 .. num_drivers {
|
|
||||||
let mut my_driver_name = CString::new("").unwrap();
|
let mut my_driver_name = CString::new("").unwrap();
|
||||||
let name = CStr::from_ptr(p_driver_name[i as usize]);
|
let name = CStr::from_ptr(p_driver_name[i as usize]);
|
||||||
my_driver_name = name.to_owned();
|
my_driver_name = name.to_owned();
|
||||||
match my_driver_name.into_string() {
|
my_driver_name.into_string().expect("Failed to convert driver name")
|
||||||
Ok(s) => driver_list.push(s),
|
})
|
||||||
Err(_) => println!("Failed converting from CString"),
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
println!("No ASIO drivers found");
|
|
||||||
}
|
|
||||||
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
|
|
||||||
driver_list
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clean_up() {
|
pub fn clean_up() {
|
||||||
let mut drivers = get_drivers();
|
let mut drivers = get_drivers();
|
||||||
match drivers.state {
|
drivers.clean_up();
|
||||||
AsioState::Offline => (),
|
|
||||||
AsioState::Loaded => {
|
|
||||||
unsafe {
|
|
||||||
let mut old_drivers = drivers.drivers.take().unwrap();
|
|
||||||
ai::destruct_AsioDrivers(&mut old_drivers);
|
|
||||||
}
|
|
||||||
drivers.state = AsioState::Offline;
|
|
||||||
},
|
|
||||||
AsioState::Initialized => {
|
|
||||||
unsafe {
|
|
||||||
drivers.asio_exit().expect("Failed to exit asio");
|
|
||||||
let mut old_drivers = drivers.drivers.take().unwrap();
|
|
||||||
ai::destruct_AsioDrivers(&mut old_drivers);
|
|
||||||
}
|
|
||||||
drivers.state = AsioState::Offline;
|
|
||||||
},
|
|
||||||
AsioState::Prepared => {
|
|
||||||
unsafe {
|
|
||||||
drivers.asio_dispose_buffers().expect("Failed to dispose buffers");
|
|
||||||
drivers.asio_exit().expect("Failed to exit asio");
|
|
||||||
let mut old_drivers = drivers.drivers.take().unwrap();
|
|
||||||
ai::destruct_AsioDrivers(&mut old_drivers);
|
|
||||||
}
|
|
||||||
drivers.state = AsioState::Offline;
|
|
||||||
},
|
|
||||||
AsioState::Running => {
|
|
||||||
unsafe {
|
|
||||||
drivers.asio_stop();
|
|
||||||
drivers.asio_dispose_buffers().expect("Failed to dispose buffers");
|
|
||||||
drivers.asio_exit().expect("Failed to exit asio");
|
|
||||||
let mut old_drivers = drivers.drivers.take().unwrap();
|
|
||||||
ai::destruct_AsioDrivers(&mut old_drivers);
|
|
||||||
}
|
|
||||||
drivers.state = AsioState::Offline;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn play() {
|
pub fn play() {
|
||||||
|
@ -548,12 +489,32 @@ pub fn stop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DriverWrapper {
|
impl AsioWrapper {
|
||||||
|
|
||||||
|
unsafe fn load(&mut self, raw: *mut i8) -> bool {
|
||||||
|
use AsioState::*;
|
||||||
|
self.clean_up();
|
||||||
|
if ai::load_asio_driver(raw) {
|
||||||
|
self.state = Loaded;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn unload(&mut self) {
|
||||||
|
ai::remove_current_driver();
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn asio_init(&mut self, di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> {
|
unsafe fn asio_init(&mut self, di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> {
|
||||||
if let AsioState::Loaded = self.state {
|
if let AsioState::Loaded = self.state {
|
||||||
let result = ai::ASIOInit(di);
|
let result = ai::ASIOInit(di);
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
.map(|_| self.state = AsioState::Initialized)
|
.map(|_| self.state = AsioState::Initialized)
|
||||||
|
.map_err(|e| {
|
||||||
|
self.state = AsioState::Offline;
|
||||||
|
e
|
||||||
|
})
|
||||||
}else{
|
}else{
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -612,7 +573,7 @@ unsafe fn asio_create_buffers(
|
||||||
match self.state {
|
match self.state {
|
||||||
Offline | Loaded => return Err(AsioError::NoDrivers),
|
Offline | Loaded => return Err(AsioError::NoDrivers),
|
||||||
Running => {
|
Running => {
|
||||||
self.asio_stop();
|
self.asio_stop().expect("Asio failed to stop");
|
||||||
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
||||||
self.state = Initialized;
|
self.state = Initialized;
|
||||||
},
|
},
|
||||||
|
@ -652,7 +613,7 @@ unsafe fn asio_exit(&mut self) -> Result<(), AsioError> {
|
||||||
}
|
}
|
||||||
let result = ai::ASIOExit();
|
let result = ai::ASIOExit();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
.map(|_| self.state = AsioState::Loaded)
|
.map(|_| self.state = AsioState::Offline)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_start(&mut self) -> Result<(), AsioError> {
|
unsafe fn asio_start(&mut self) -> Result<(), AsioError> {
|
||||||
|
@ -678,4 +639,41 @@ unsafe fn asio_stop(&mut self) -> Result<(), AsioError> {
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
.map(|_| self.state = AsioState::Prepared)
|
.map(|_| self.state = AsioState::Prepared)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_up(&mut self) {
|
||||||
|
match self.state {
|
||||||
|
AsioState::Offline => (),
|
||||||
|
AsioState::Loaded => {
|
||||||
|
unsafe {
|
||||||
|
self.asio_exit().expect("Failed to exit asio");
|
||||||
|
self.unload();
|
||||||
|
}
|
||||||
|
self.state = AsioState::Offline;
|
||||||
|
},
|
||||||
|
AsioState::Initialized => {
|
||||||
|
unsafe {
|
||||||
|
self.asio_exit().expect("Failed to exit asio");
|
||||||
|
self.unload();
|
||||||
|
}
|
||||||
|
self.state = AsioState::Offline;
|
||||||
|
},
|
||||||
|
AsioState::Prepared => {
|
||||||
|
unsafe {
|
||||||
|
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
||||||
|
self.asio_exit().expect("Failed to exit asio");
|
||||||
|
self.unload();
|
||||||
|
}
|
||||||
|
self.state = AsioState::Offline;
|
||||||
|
},
|
||||||
|
AsioState::Running => {
|
||||||
|
unsafe {
|
||||||
|
self.asio_stop().expect("Asio failed to stop");
|
||||||
|
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
||||||
|
self.asio_exit().expect("Failed to exit asio");
|
||||||
|
self.unload();
|
||||||
|
}
|
||||||
|
self.state = AsioState::Offline;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -96,7 +96,12 @@ impl Device {
|
||||||
|
|
||||||
impl Default for Devices {
|
impl Default for Devices {
|
||||||
fn default() -> Devices {
|
fn default() -> Devices {
|
||||||
Devices{ drivers: sys::get_driver_list().into_iter() }
|
// Remove offline drivers
|
||||||
|
let driver_names: Vec<String> = sys::get_driver_list()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|name| sys::Drivers::load(&name).is_ok())
|
||||||
|
.collect();
|
||||||
|
Devices{ drivers: driver_names.into_iter() }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue