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;
#[derive(Debug)]
pub enum AsioError {
pub enum AsioDriverError {
NoResult(String),
BufferError(String),
DriverLoadError,
@ -10,7 +10,19 @@ pub enum AsioError {
}
#[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_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
ASE_NotPresent = -1000, // hardware input or output is not present or available
@ -23,13 +35,31 @@ enum AsioErrorWrapper {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 => {
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 {
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::HardwareMalfunction => {
"hardware is malfunctioning (can be returned by any ASIO function)"
@ -73,7 +99,6 @@ impl Error for ASIOError {
}
}
}
macro_rules! asio_error_helper {
($x:expr, $ae:ident{ $($v:ident),+ }, $inval:ident) => {
match $x {
@ -85,7 +110,7 @@ macro_rules! asio_error_helper {
macro_rules! asio_result {
($result:expr) => {
match asio_error!(
match asio_error_helper!(
$result,
AsioErrorWrapper {
ASE_OK,
@ -100,16 +125,16 @@ macro_rules! asio_result {
},
Invalid
) {
ASE_OK => Ok(()),
ASE_SUCCESS => Ok(()),
ASE_NotPresent => Err(AsioError::NoDrivers),
ASE_HWMalfunction => Err(AsioError::HardwareMalfunction),
ASE_InvalidParameter => Err(AsioError::InvalidInput),
ASE_InvalidMode => Err(AsioError::BadMode),
ASE_SPNotAdvancing => Err(AsioError::HardwareStuck),
ASE_NoClock => Err(AsioError::NoRate),
ASE_NoMemory => Err(AsioError::ASE_NoMemory),
Invalid => Err(AsioError::UnknownError),
AsioErrorWrapper::ASE_OK => Ok(()),
AsioErrorWrapper::ASE_SUCCESS => Ok(()),
AsioErrorWrapper::ASE_NotPresent => Err(AsioError::NoDrivers),
AsioErrorWrapper::ASE_HWMalfunction => Err(AsioError::HardwareMalfunction),
AsioErrorWrapper::ASE_InvalidParameter => Err(AsioError::InvalidInput),
AsioErrorWrapper::ASE_InvalidMode => Err(AsioError::BadMode),
AsioErrorWrapper::ASE_SPNotAdvancing => Err(AsioError::HardwareStuck),
AsioErrorWrapper::ASE_NoClock => Err(AsioError::NoRate),
AsioErrorWrapper::ASE_NoMemory => Err(AsioError::ASE_NoMemory),
AsioErrorWrapper::Invalid => Err(AsioError::UnknownError),
}
};
}

View File

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