error handling

This commit is contained in:
Tom Gowan 2018-10-23 20:13:29 +11:00 committed by mitchmindtree
parent ec172bbc47
commit c24fa62028
2 changed files with 111 additions and 74 deletions

View File

@ -2,7 +2,7 @@ use std::error::Error;
use std::fmt; use std::fmt;
#[derive(Debug)] #[derive(Debug)]
pub enum AsioError { pub enum AsioDriverError {
NoResult(String), NoResult(String),
BufferError(String), BufferError(String),
DriverLoadError, DriverLoadError,
@ -10,7 +10,19 @@ pub enum AsioError {
} }
#[derive(Debug)] #[derive(Debug)]
enum AsioErrorWrapper { pub enum AsioError {
NoDrivers,
HardwareMalfunction,
InvalidInput,
BadMode,
HardwareStuck,
NoRate,
ASE_NoMemory,
UnknownError,
}
#[derive(Debug)]
pub enum AsioErrorWrapper {
ASE_OK = 0, // This value will be returned whenever the call succeeded ASE_OK = 0, // This value will be returned whenever the call succeeded
ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
ASE_NotPresent = -1000, // hardware input or output is not present or available ASE_NotPresent = -1000, // hardware input or output is not present or available
@ -23,13 +35,31 @@ enum AsioErrorWrapper {
Invalid, Invalid,
} }
impl fmt::Display for AsioDriverError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AsioDriverError::NoResult(ref e) => write!(f, "Driver {} not found", e),
AsioDriverError::BufferError(ref e) => write!(f, "Buffer Error: {}", e),
AsioDriverError::DriverLoadError => write!(f, "Couldn't load the driver"),
AsioDriverError::TypeError => write!(f, "Couldn't convert sample type"),
}
}
}
impl Error for AsioDriverError {
fn description(&self) -> &str {
match *self {
AsioDriverError::NoResult(_) => "Couln't find driver",
AsioDriverError::BufferError(_) => "Error creating the buffer",
AsioDriverError::DriverLoadError => "Error loading the driver",
AsioDriverError::TypeError => "Error getting sample type",
}
}
}
impl fmt::Display for AsioError { impl fmt::Display for AsioError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
ASIOError::NoResult(ref e) => write!(f, "Driver {} not found", e),
ASIOError::BufferError(ref e) => write!(f, "Buffer Error: {}", e),
ASIOError::DriverLoadError => write!(f, "Couldn't load the driver"),
ASIOError::TypeError => write!(f, "Couldn't convert sample type"),
AsioError::NoDrivers => { AsioError::NoDrivers => {
write!(f, "hardware input or output is not present or available") write!(f, "hardware input or output is not present or available")
}, },
@ -53,13 +83,9 @@ impl fmt::Display for AsioError {
} }
} }
impl Error for ASIOError { impl Error for AsioError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
ASIOError::NoResult(_) => "Couln't find driver",
ASIOError::BufferError(_) => "Error creating the buffer",
ASIOError::DriverLoadError => "Error loading the driver",
ASIOError::TypeError => "Error getting sample type",
AsioError::NoDrivers => "hardware input or output is not present or available", AsioError::NoDrivers => "hardware input or output is not present or available",
AsioError::HardwareMalfunction => { AsioError::HardwareMalfunction => {
"hardware is malfunctioning (can be returned by any ASIO function)" "hardware is malfunctioning (can be returned by any ASIO function)"
@ -73,7 +99,6 @@ impl Error for ASIOError {
} }
} }
} }
macro_rules! asio_error_helper { macro_rules! asio_error_helper {
($x:expr, $ae:ident{ $($v:ident),+ }, $inval:ident) => { ($x:expr, $ae:ident{ $($v:ident),+ }, $inval:ident) => {
match $x { match $x {
@ -85,7 +110,7 @@ macro_rules! asio_error_helper {
macro_rules! asio_result { macro_rules! asio_result {
($result:expr) => { ($result:expr) => {
match asio_error!( match asio_error_helper!(
$result, $result,
AsioErrorWrapper { AsioErrorWrapper {
ASE_OK, ASE_OK,
@ -100,16 +125,16 @@ macro_rules! asio_result {
}, },
Invalid Invalid
) { ) {
ASE_OK => Ok(()), AsioErrorWrapper::ASE_OK => Ok(()),
ASE_SUCCESS => Ok(()), AsioErrorWrapper::ASE_SUCCESS => Ok(()),
ASE_NotPresent => Err(AsioError::NoDrivers), AsioErrorWrapper::ASE_NotPresent => Err(AsioError::NoDrivers),
ASE_HWMalfunction => Err(AsioError::HardwareMalfunction), AsioErrorWrapper::ASE_HWMalfunction => Err(AsioError::HardwareMalfunction),
ASE_InvalidParameter => Err(AsioError::InvalidInput), AsioErrorWrapper::ASE_InvalidParameter => Err(AsioError::InvalidInput),
ASE_InvalidMode => Err(AsioError::BadMode), AsioErrorWrapper::ASE_InvalidMode => Err(AsioError::BadMode),
ASE_SPNotAdvancing => Err(AsioError::HardwareStuck), AsioErrorWrapper::ASE_SPNotAdvancing => Err(AsioError::HardwareStuck),
ASE_NoClock => Err(AsioError::NoRate), AsioErrorWrapper::ASE_NoClock => Err(AsioError::NoRate),
ASE_NoMemory => Err(AsioError::ASE_NoMemory), AsioErrorWrapper::ASE_NoMemory => Err(AsioError::ASE_NoMemory),
Invalid => Err(AsioError::UnknownError), AsioErrorWrapper::Invalid => Err(AsioError::UnknownError),
} }
}; };
} }

View File

@ -8,9 +8,10 @@ extern crate num;
extern crate num_derive; extern crate num_derive;
mod asio_import; mod asio_import;
#[macro_use]
pub mod errors; pub mod errors;
use errors::ASIOError; 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;
@ -150,7 +151,7 @@ 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, AsioDriverError> {
let mut drivers = ASIO_DRIVERS.lock().unwrap(); let mut drivers = ASIO_DRIVERS.lock().unwrap();
match *drivers { match *drivers {
Some(_) => { Some(_) => {
@ -168,10 +169,10 @@ impl Drivers {
unsafe { unsafe {
let mut asio_drivers = ai::AsioDrivers::new(); let mut asio_drivers = ai::AsioDrivers::new();
let load_result = asio_drivers.loadDriver(raw); let load_result = asio_drivers.loadDriver(raw);
asio_init(&mut driver_info)?; let init_result = 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 { if load_result && init_result.is_ok() {
println!("Creating drivers"); println!("Creating drivers");
*drivers = Some(DriverWrapper { *drivers = Some(DriverWrapper {
drivers: asio_drivers, drivers: asio_drivers,
@ -179,7 +180,7 @@ impl Drivers {
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst); STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
Ok(Drivers {}) Ok(Drivers {})
} else { } else {
Err(ASIOError::DriverLoadError) Err(AsioDriverError::DriverLoadError)
} }
} }
}, },
@ -200,7 +201,7 @@ impl Drivers {
let mut ins: c_long = 0; let mut ins: c_long = 0;
let mut outs: c_long = 0; let mut outs: c_long = 0;
unsafe { unsafe {
asio_get_channels(&mut ins, &mut outs)?; asio_get_channels(&mut ins, &mut outs).expect("failed to get channels");
channel = Channel { channel = Channel {
ins: ins as i64, ins: ins as i64,
outs: outs as i64, outs: outs as i64,
@ -217,16 +218,14 @@ impl Drivers {
let mut rate: c_double = 0.0f64; let mut rate: c_double = 0.0f64;
unsafe { unsafe {
asio_get_sample_rate(&mut rate)?; asio_get_sample_rate(&mut rate).expect("failed to get sample rate");
sample_rate = SampleRate { rate: rate as u32 }; sample_rate = SampleRate { rate: rate as u32 };
} }
sample_rate sample_rate
} }
pub fn get_data_type(&self) -> Result<AsioSampleType, ASIOError> { pub fn get_data_type(&self) -> Result<AsioSampleType, AsioDriverError> {
let data_type: Result<AsioSampleType, ASIOError>;
// Initialize memory for calls // Initialize memory for calls
let mut channel_info = ai::ASIOChannelInfo { let mut channel_info = ai::ASIOChannelInfo {
channel: 0, channel: 0,
@ -237,15 +236,20 @@ impl Drivers {
name: [0 as c_char; 32], name: [0 as c_char; 32],
}; };
unsafe { unsafe {
asio_get_channel_info(&mut channel_info)?; match asio_get_channel_info(&mut channel_info) {
data_type = num::FromPrimitive::from_i32(channel_info.type_) Ok(_) => {
.map_or(Err(ASIOError::TypeError), |t| Ok(t)); num::FromPrimitive::from_i32(channel_info.type_)
.map_or(Err(AsioDriverError::TypeError), |t| Ok(t))
},
Err(e) => {
println!("Error getting data type {}", e);
Err(AsioDriverError::DriverLoadError)
},
}
} }
data_type
} }
pub fn prepare_input_stream(&self, num_channels: usize) -> Result<AsioStream, ASIOError> { pub fn prepare_input_stream(&self, num_channels: usize) -> Result<AsioStream, AsioDriverError> {
let mut buffer_infos = vec![ let mut buffer_infos = vec![
AsioBufferInfo { AsioBufferInfo {
is_input: 1, is_input: 1,
@ -267,7 +271,7 @@ impl Drivers {
let mut pref_b_size: c_long = 0; let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0; let mut grans: c_long = 0;
let mut result = Err(ASIOError::NoResult("not implimented".to_owned())); let mut result = Err(AsioDriverError::NoResult("not implimented".to_owned()));
unsafe { unsafe {
asio_get_buffer_size( asio_get_buffer_size(
@ -275,7 +279,7 @@ impl Drivers {
&mut max_b_size, &mut max_b_size,
&mut pref_b_size, &mut pref_b_size,
&mut grans, &mut grans,
)?; ).expect("Failed getting buffers");
result = if pref_b_size > 0 { result = if pref_b_size > 0 {
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos
.into_iter() .into_iter()
@ -289,7 +293,7 @@ impl Drivers {
pref_b_size, pref_b_size,
&mut callbacks_convert, &mut callbacks_convert,
); );
if buffer_result == 0 { if buffer_result.is_ok() {
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert let mut 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))
@ -305,14 +309,14 @@ impl Drivers {
buffer_size: pref_b_size, buffer_size: pref_b_size,
}); });
} }
Err(ASIOError::BufferError(format!( Err(AsioDriverError::BufferError(format!(
"failed to create buffers, "failed to create buffers,
error \ error \
code: {}", code: {:?}",
buffer_result buffer_result
))) )))
} else { } else {
Err(ASIOError::BufferError( Err(AsioDriverError::BufferError(
"Failed to get buffer size".to_owned(), "Failed to get buffer size".to_owned(),
)) ))
}; };
@ -321,7 +325,7 @@ impl Drivers {
} }
/// Creates the output stream /// Creates the output stream
pub fn prepare_output_stream(&self, num_channels: usize) -> Result<AsioStream, ASIOError> { pub fn prepare_output_stream(&self, num_channels: usize) -> Result<AsioStream, AsioDriverError> {
// Initialize data for FFI // Initialize data for FFI
let mut buffer_infos = vec![ let mut buffer_infos = vec![
AsioBufferInfo { AsioBufferInfo {
@ -344,7 +348,7 @@ impl Drivers {
let mut pref_b_size: c_long = 0; let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0; let mut grans: c_long = 0;
let mut result = Err(ASIOError::NoResult("not implimented".to_owned())); let mut result = Err(AsioDriverError::NoResult("not implimented".to_owned()));
unsafe { unsafe {
// Get the buffer sizes // Get the buffer sizes
@ -357,7 +361,7 @@ impl Drivers {
&mut max_b_size, &mut max_b_size,
&mut pref_b_size, &mut pref_b_size,
&mut grans, &mut grans,
)?; ).expect("Failed getting buffers");
result = if pref_b_size > 0 { result = if pref_b_size > 0 {
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos
.into_iter() .into_iter()
@ -371,7 +375,7 @@ impl Drivers {
pref_b_size, pref_b_size,
&mut callbacks_convert, &mut callbacks_convert,
); );
if buffer_result == 0 { if buffer_result.is_ok() {
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert let mut 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))
@ -387,12 +391,12 @@ impl Drivers {
buffer_size: pref_b_size, buffer_size: pref_b_size,
}); });
} }
Err(ASIOError::BufferError(format!( Err(AsioDriverError::BufferError(format!(
"failed to create buffers, error code: {}", "failed to create buffers, error code: {:?}",
buffer_result buffer_result
))) )))
} else { } else {
Err(ASIOError::BufferError( Err(AsioDriverError::BufferError(
"Failed to get buffer size".to_owned(), "Failed to get buffer size".to_owned(),
)) ))
}; };
@ -490,8 +494,8 @@ pub fn get_driver_list() -> Vec<String> {
pub fn destroy_stream(stream: AsioStream) { pub fn destroy_stream(stream: AsioStream) {
unsafe { unsafe {
asio_dispose_buffers()?; asio_dispose_buffers().expect("Failed to dispose buffers");
asio_exit()?; asio_exit().expect("Failed to exit asio");
} }
} }
@ -509,49 +513,57 @@ pub fn stop() {
} }
} }
fn asio_init(di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> { unsafe fn asio_init(di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> {
asio_result!(ASIOInit(di)); let result = ai::ASIOInit(di);
asio_result!(result)
} }
fn asio_get_channels(ins: &mut c_long, outs: &mut outs) -> Result<(), AsioError> { unsafe fn asio_get_channels(ins: &mut c_long, outs: &mut c_long) -> Result<(), AsioError> {
asio_result!(ai::ASIOGetChannels(ins, outs)) let result = ai::ASIOGetChannels(ins, outs);
asio_result!(result)
} }
fn asio_get_sample_rate(rate: &mut c_double) -> Result<(), AsioError> { unsafe fn asio_get_sample_rate(rate: &mut c_double) -> Result<(), AsioError> {
asio_result!(ai::get_sample_rate(rate)) let result = ai::get_sample_rate(rate);
asio_result!(result)
} }
fn asio_get_channel_info(ci: &mut ai::ASIOChannelInfo) -> Result<(), AsioError> { unsafe fn asio_get_channel_info(ci: &mut ai::ASIOChannelInfo) -> Result<(), AsioError> {
asio_result!(ai::ASIOGetChannelInfo(ci)) let result = ai::ASIOGetChannelInfo(ci);
asio_result!(result)
} }
fn asio_get_buffer_size( unsafe fn asio_get_buffer_size(
min_b_size: &mut c_long, max_b_size: &mut c_long, pref_b_size: &mut c_long, grans: &mut c_long, min_b_size: &mut c_long, max_b_size: &mut c_long, pref_b_size: &mut c_long, grans: &mut c_long,
) -> Result<(), AsioError> { ) -> Result<(), AsioError> {
asio_result!(ai::ASIOGetBufferSize( let result = ai::ASIOGetBufferSize(
min_b_size, min_b_size,
max_b_size, max_b_size,
pref_b_size, pref_b_size,
grans, grans,
)) );
asio_result!(result)
} }
fn asio_create_buffers( unsafe fn asio_create_buffers(
buffer_info_convert: &mut ai::ASIOBufferInfo, num_channels: i32, pref_b_size: c_long, buffer_info_convert: *mut ai::ASIOBufferInfo, num_channels: i32, pref_b_size: c_long,
callbacks_convert: &mut ai::ASIOCallbacks, callbacks_convert: &mut ai::ASIOCallbacks,
) -> Result<(), AsioError> { ) -> Result<(), AsioError> {
asio_result!(ai::ASIOCreateBuffers( let result = ai::ASIOCreateBuffers(
buffer_info_convert, buffer_info_convert,
num_channels, num_channels,
pref_b_size, pref_b_size,
callbacks_convert, callbacks_convert,
)) );
asio_result!(result)
} }
fn asio_dispose_buffers() -> Result<(), AsioError> { unsafe fn asio_dispose_buffers() -> Result<(), AsioError> {
asio_result!(ai::ASIODisposeBuffers()) let result = ai::ASIODisposeBuffers();
asio_result!(result)
} }
fn asio_exit() -> Result<(), AsioError> { unsafe fn asio_exit() -> Result<(), AsioError> {
asio_result!(ai::ASIOExit()) let result = ai::ASIOExit();
} asio_result!(result)
}