Refactor asio-sys to use less global state and more RAII

The asio-sys examples have been tested and still work nicely. The CPAL
asio host has not yet been updated for these changes.
This commit is contained in:
mitchmindtree 2019-06-28 03:00:52 +10:00
parent 05f8b7dc43
commit efe683133c
4 changed files with 486 additions and 706 deletions

View File

@ -34,19 +34,20 @@ pub struct Format {
}
fn main() {
for name in sys::get_driver_list() {
let asio = sys::Asio::new();
for name in asio.driver_names() {
println!("Driver: {:?}", name);
let driver = sys::Drivers::load(&name).expect("failed to load driver");
let channels = driver.get_channels();
let sample_rate = driver.get_sample_rate();
let driver = asio.load_driver(&name).expect("failed to load driver");
let channels = driver.channels().expect("failed to retrieve channel counts");
let sample_rate = driver.sample_rate().expect("failed to retrieve sample rate");
let in_fmt = Format {
channels: channels.ins as _,
sample_rate: SampleRate(sample_rate.rate as _),
sample_rate: SampleRate(sample_rate as _),
data_type: SampleFormat::F32,
};
let out_fmt = Format {
channels: channels.outs as _,
sample_rate: SampleRate(sample_rate.rate as _),
sample_rate: SampleRate(sample_rate as _),
data_type: SampleFormat::F32,
};
println!(" Input {:?}", in_fmt);

View File

@ -1,13 +1,11 @@
extern crate asio_sys as sys;
fn main() {
let driver_list = sys::get_driver_list();
for driver in &driver_list {
let asio = sys::Asio::new();
for driver in asio.driver_names() {
println!("Driver: {}", driver);
let driver = sys::Drivers::load(driver).expect("failed to load drivers");
println!(" Channels: {:?}", driver.get_channels());
println!(" Sample rate: {:?}", driver.get_sample_rate());
let driver = asio.load_driver(&driver).expect("failed to load drivers");
println!(" Channels: {:?}", driver.channels().expect("failed to get channels"));
println!(" Sample rate: {:?}", driver.sample_rate().expect("failed to get sample rate"));
}
}

View File

@ -1,14 +1,15 @@
use std::error::Error;
use std::fmt;
/// Errors that might occur during `Asio::load_driver`.
#[derive(Debug)]
pub enum AsioDriverError {
NoResult(String),
BufferError(String),
DriverLoadError,
TypeError,
pub enum LoadDriverError {
LoadDriverFailed,
DriverAlreadyExists,
InitializationFailed(AsioError),
}
/// General errors returned by ASIO.
#[derive(Debug)]
pub enum AsioError {
NoDrivers,
@ -35,25 +36,9 @@ pub enum AsioErrorWrapper {
Invalid,
}
impl fmt::Display for AsioDriverError {
impl fmt::Display for LoadDriverError {
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",
}
write!(f, "{}", self.description())
}
}
@ -83,6 +68,20 @@ impl fmt::Display for AsioError {
}
}
impl Error for LoadDriverError {
fn description(&self) -> &str {
match *self {
LoadDriverError::LoadDriverFailed => {
"ASIO `loadDriver` function returned `false` indicating failure"
}
LoadDriverError::InitializationFailed(ref err) => err.description(),
LoadDriverError::DriverAlreadyExists => {
"ASIO only supports loading one driver at a time"
}
}
}
}
impl Error for AsioError {
fn description(&self) -> &str {
match *self {
@ -99,42 +98,27 @@ impl Error for AsioError {
}
}
}
macro_rules! asio_error_helper {
($x:expr, $ae:ident{ $($v:ident),+ }, $inval:ident) => {
match $x {
$(_ if $x == $ae::$v as i32 => $ae::$v,)+
_ => $ae::$inval,
}
};
impl From<AsioError> for LoadDriverError {
fn from(err: AsioError) -> Self {
LoadDriverError::InitializationFailed(err)
}
}
macro_rules! asio_result {
($result:expr) => {
match asio_error_helper!(
$result,
AsioErrorWrapper {
ASE_OK,
ASE_SUCCESS,
ASE_NotPresent,
ASE_HWMalfunction,
ASE_InvalidParameter,
ASE_InvalidMode,
ASE_SPNotAdvancing,
ASE_NoClock,
ASE_NoMemory
},
Invalid
) {
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),
($e:expr) => {{
let res = { $e };
match res {
r if r == AsioErrorWrapper::ASE_OK as i32 => Ok(()),
r if r == AsioErrorWrapper::ASE_SUCCESS as i32 => Ok(()),
r if r == AsioErrorWrapper::ASE_NotPresent as i32 => Err(AsioError::NoDrivers),
r if r == AsioErrorWrapper::ASE_HWMalfunction as i32 => Err(AsioError::HardwareMalfunction),
r if r == AsioErrorWrapper::ASE_InvalidParameter as i32 => Err(AsioError::InvalidInput),
r if r == AsioErrorWrapper::ASE_InvalidMode as i32 => Err(AsioError::BadMode),
r if r == AsioErrorWrapper::ASE_SPNotAdvancing as i32 => Err(AsioError::HardwareStuck),
r if r == AsioErrorWrapper::ASE_NoClock as i32 => Err(AsioError::NoRate),
r if r == AsioErrorWrapper::ASE_NoMemory as i32 => Err(AsioError::ASE_NoMemory),
_ => Err(AsioError::UnknownError),
}
};
}};
}

File diff suppressed because it is too large Load Diff