parent
056630cca3
commit
ae7a03d788
|
@ -16,7 +16,7 @@ use std::os::raw::c_void;
|
||||||
use std::os::raw::c_double;
|
use std::os::raw::c_double;
|
||||||
use errors::ASIOError;
|
use errors::ASIOError;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Mutex;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use asio_import as ai;
|
use asio_import as ai;
|
||||||
|
|
||||||
|
@ -44,9 +44,19 @@ pub struct SampleRate {
|
||||||
pub rate: u32,
|
pub rate: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Drivers {
|
||||||
|
drivers: Arc<Mutex<DriverWrapper>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DriverWrapper {
|
||||||
|
pub drivers: ai::AsioDrivers,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AsioStream {
|
pub struct AsioStream {
|
||||||
pub buffer_infos: [AsioBufferInfo; 2],
|
pub buffer_infos: [AsioBufferInfo; 2],
|
||||||
driver: ai::AsioDrivers,
|
//driver: Driver,
|
||||||
pub buffer_size: i32,
|
pub buffer_size: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +148,271 @@ extern "C" fn buffer_switch_time_info(
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsioStream {
|
|
||||||
fn pop_driver(self) -> ai::AsioDrivers {
|
impl Drivers {
|
||||||
self.driver
|
pub fn load(driver_name: &str) -> Result<Self, ASIOError> {
|
||||||
|
// Make owned CString to send to load driver
|
||||||
|
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
||||||
|
let raw = my_driver_name.into_raw();
|
||||||
|
unsafe {
|
||||||
|
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 {
|
||||||
|
Ok(Drivers{ drivers: Arc::new(Mutex::new(DriverWrapper{drivers: asio_drivers})) })
|
||||||
|
} else {
|
||||||
|
Err(ASIOError::DriverLoadError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the channels for the driver it's passed
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `driver name` - Name of the driver
|
||||||
|
/// # Usage
|
||||||
|
/// Use the get_driver_list() to get the list of names
|
||||||
|
/// Then pass the one you want to get_channels
|
||||||
|
pub fn get_channels(&self) -> Channel {
|
||||||
|
let channel: Channel;
|
||||||
|
|
||||||
|
// Initialize memory for calls
|
||||||
|
let mut ins: c_long = 0;
|
||||||
|
let mut outs: c_long = 0;
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
|
ai::ASIOGetChannels(&mut ins, &mut outs);
|
||||||
|
channel = Channel {
|
||||||
|
ins: ins as i64,
|
||||||
|
outs: outs as i64,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sample_rate(&self) -> SampleRate {
|
||||||
|
let sample_rate: SampleRate;
|
||||||
|
|
||||||
|
// Initialize memory for calls
|
||||||
|
let mut rate: c_double = 0.0f64;
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
|
ai::get_sample_rate(&mut 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>;
|
||||||
|
|
||||||
|
// Initialize memory for calls
|
||||||
|
let mut channel_info = ai::ASIOChannelInfo {
|
||||||
|
channel: 0,
|
||||||
|
isInput: 0,
|
||||||
|
isActive: 0,
|
||||||
|
channelGroup: 0,
|
||||||
|
type_: 0,
|
||||||
|
name: [0 as c_char; 32],
|
||||||
|
};
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
|
ai::ASIOGetChannelInfo(&mut channel_info);
|
||||||
|
data_type = num::FromPrimitive::from_i32(channel_info.type_)
|
||||||
|
.map_or(Err(ASIOError::TypeError), |t| Ok(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
data_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepare_input_stream(&self) -> Result<AsioStream, ASIOError> {
|
||||||
|
let mut buffer_infos = [
|
||||||
|
AsioBufferInfo {
|
||||||
|
is_input: 1,
|
||||||
|
channel_num: 0,
|
||||||
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
|
},
|
||||||
|
AsioBufferInfo {
|
||||||
|
is_input: 1,
|
||||||
|
channel_num: 1,
|
||||||
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let num_channels = 2;
|
||||||
|
|
||||||
|
let mut callbacks = AsioCallbacks {
|
||||||
|
buffer_switch: buffer_switch,
|
||||||
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
|
asio_message: asio_message,
|
||||||
|
buffer_switch_time_info: buffer_switch_time_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut min_b_size: c_long = 0;
|
||||||
|
let mut max_b_size: c_long = 0;
|
||||||
|
let mut pref_b_size: c_long = 0;
|
||||||
|
let mut grans: c_long = 0;
|
||||||
|
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
|
ai::ASIOGetBufferSize(
|
||||||
|
&mut min_b_size,
|
||||||
|
&mut max_b_size,
|
||||||
|
&mut pref_b_size,
|
||||||
|
&mut grans,
|
||||||
|
);
|
||||||
|
result = if pref_b_size > 0 {
|
||||||
|
let mut buffer_info_convert = [
|
||||||
|
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
||||||
|
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
||||||
|
];
|
||||||
|
let mut callbacks_convert =
|
||||||
|
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
||||||
|
let buffer_result = ai::ASIOCreateBuffers(
|
||||||
|
buffer_info_convert.as_mut_ptr(),
|
||||||
|
num_channels,
|
||||||
|
pref_b_size,
|
||||||
|
&mut callbacks_convert,
|
||||||
|
);
|
||||||
|
if buffer_result == 0 {
|
||||||
|
let buffer_infos = [
|
||||||
|
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
||||||
|
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
||||||
|
];
|
||||||
|
for d in &buffer_infos {
|
||||||
|
println!("after {:?}", d);
|
||||||
|
}
|
||||||
|
println!("channels: {:?}", num_channels);
|
||||||
|
|
||||||
|
return Ok(AsioStream {
|
||||||
|
buffer_infos: buffer_infos,
|
||||||
|
buffer_size: pref_b_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(ASIOError::BufferError(format!(
|
||||||
|
"failed to create buffers,
|
||||||
|
error code: {}",
|
||||||
|
buffer_result
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Err(ASIOError::BufferError(
|
||||||
|
"Failed to get buffer size".to_owned(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepare_output_stream(&self) -> Result<AsioStream, ASIOError> {
|
||||||
|
let mut buffer_infos = [
|
||||||
|
AsioBufferInfo {
|
||||||
|
is_input: 0,
|
||||||
|
channel_num: 0,
|
||||||
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
|
},
|
||||||
|
AsioBufferInfo {
|
||||||
|
is_input: 0,
|
||||||
|
channel_num: 0,
|
||||||
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let num_channels = 2;
|
||||||
|
let mut callbacks = AsioCallbacks {
|
||||||
|
buffer_switch: buffer_switch,
|
||||||
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
|
asio_message: asio_message,
|
||||||
|
buffer_switch_time_info: buffer_switch_time_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut min_b_size: c_long = 0;
|
||||||
|
let mut max_b_size: c_long = 0;
|
||||||
|
let mut pref_b_size: c_long = 0;
|
||||||
|
let mut grans: c_long = 0;
|
||||||
|
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
|
ai::ASIOGetBufferSize(
|
||||||
|
&mut min_b_size,
|
||||||
|
&mut max_b_size,
|
||||||
|
&mut pref_b_size,
|
||||||
|
&mut grans,
|
||||||
|
);
|
||||||
|
result = if pref_b_size > 0 {
|
||||||
|
let mut buffer_info_convert = [
|
||||||
|
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
||||||
|
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
||||||
|
];
|
||||||
|
let mut callbacks_convert =
|
||||||
|
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
||||||
|
let buffer_result = ai::ASIOCreateBuffers(
|
||||||
|
buffer_info_convert.as_mut_ptr(),
|
||||||
|
num_channels,
|
||||||
|
pref_b_size,
|
||||||
|
&mut callbacks_convert,
|
||||||
|
);
|
||||||
|
if buffer_result == 0 {
|
||||||
|
let buffer_infos = [
|
||||||
|
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
||||||
|
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
||||||
|
];
|
||||||
|
for d in &buffer_infos {
|
||||||
|
println!("after {:?}", d);
|
||||||
|
}
|
||||||
|
println!("channels: {:?}", num_channels);
|
||||||
|
|
||||||
|
return Ok(AsioStream {
|
||||||
|
buffer_infos: buffer_infos,
|
||||||
|
buffer_size: pref_b_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(ASIOError::BufferError(format!(
|
||||||
|
"failed to create buffers,
|
||||||
|
error code: {}",
|
||||||
|
buffer_result
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Err(ASIOError::BufferError(
|
||||||
|
"Failed to get buffer size".to_owned(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DriverWrapper {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe{
|
||||||
|
ai::destruct_AsioDrivers(&mut self.drivers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,52 +432,9 @@ where
|
||||||
let mut bc = buffer_callback.lock().unwrap();
|
let mut bc = buffer_callback.lock().unwrap();
|
||||||
*bc = Some(BufferCallback(Box::new(callback)));
|
*bc = Some(BufferCallback(Box::new(callback)));
|
||||||
}
|
}
|
||||||
/// Returns the channels for the driver it's passed
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
/// * `driver name` - Name of the driver
|
|
||||||
/// # Usage
|
|
||||||
/// Use the get_driver_list() to get the list of names
|
|
||||||
/// Then pass the one you want to get_channels
|
|
||||||
pub fn get_channels(driver_name: &str) -> Result<Channel, ASIOError> {
|
|
||||||
let channel: Result<Channel, ASIOError>;
|
|
||||||
// Make owned CString to send to load driver
|
|
||||||
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
|
||||||
let raw = my_driver_name.into_raw();
|
|
||||||
|
|
||||||
// Initialize memory for calls
|
|
||||||
let mut ins: c_long = 0;
|
|
||||||
let mut outs: c_long = 0;
|
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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 {
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::ASIOGetChannels(&mut ins, &mut outs);
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
channel = Ok(Channel {
|
|
||||||
ins: ins as i64,
|
|
||||||
outs: outs as i64,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
channel = Err(ASIOError::NoResult(driver_name.to_owned()));
|
|
||||||
}
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
|
|
||||||
channel
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
||||||
pub fn get_driver_list() -> Vec<String> {
|
pub fn get_driver_list() -> Vec<String> {
|
||||||
let mut driver_list: Vec<String> = Vec::new();
|
let mut driver_list: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
@ -242,296 +471,11 @@ pub fn get_driver_list() -> Vec<String> {
|
||||||
driver_list
|
driver_list
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sample_rate(driver_name: &str) -> Result<SampleRate, ASIOError> {
|
|
||||||
let sample_rate: Result<SampleRate, ASIOError>;
|
|
||||||
// Make owned CString to send to load driver
|
|
||||||
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
|
||||||
let raw = my_driver_name.into_raw();
|
|
||||||
|
|
||||||
// Initialize memory for calls
|
|
||||||
let mut rate: c_double = 0.0f64;
|
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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 {
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::get_sample_rate(&mut rate);
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
sample_rate = Ok(SampleRate { rate: rate as u32 });
|
|
||||||
} else {
|
|
||||||
sample_rate = Err(ASIOError::NoResult(driver_name.to_owned()));
|
|
||||||
}
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_rate
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_data_type(driver_name: &str) -> Result<AsioSampleType, ASIOError> {
|
|
||||||
let data_type: Result<AsioSampleType, ASIOError>;
|
|
||||||
// Make owned CString to send to load driver
|
|
||||||
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
|
||||||
let raw = my_driver_name.into_raw();
|
|
||||||
|
|
||||||
// Initialize memory for calls
|
|
||||||
let mut channel_info = ai::ASIOChannelInfo {
|
|
||||||
channel: 0,
|
|
||||||
isInput: 0,
|
|
||||||
isActive: 0,
|
|
||||||
channelGroup: 0,
|
|
||||||
type_: 0,
|
|
||||||
name: [0 as c_char; 32],
|
|
||||||
};
|
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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 {
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::ASIOGetChannelInfo(&mut channel_info);
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
data_type = num::FromPrimitive::from_i32(channel_info.type_)
|
|
||||||
.map_or(Err(ASIOError::TypeError), |t| Ok(t));
|
|
||||||
} else {
|
|
||||||
data_type = Err(ASIOError::NoResult(driver_name.to_owned()));
|
|
||||||
}
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
|
|
||||||
data_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepare_input_stream(driver_name: &str) -> Result<AsioStream, ASIOError> {
|
|
||||||
let mut buffer_infos = [
|
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 1,
|
|
||||||
channel_num: 0,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 1,
|
|
||||||
channel_num: 1,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
let num_channels = 2;
|
|
||||||
|
|
||||||
let mut callbacks = AsioCallbacks {
|
|
||||||
buffer_switch: buffer_switch,
|
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
|
||||||
asio_message: asio_message,
|
|
||||||
buffer_switch_time_info: buffer_switch_time_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut min_b_size: c_long = 0;
|
|
||||||
let mut max_b_size: c_long = 0;
|
|
||||||
let mut pref_b_size: c_long = 0;
|
|
||||||
let mut grans: c_long = 0;
|
|
||||||
|
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make owned CString to send to load driver
|
|
||||||
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
|
||||||
let raw = my_driver_name.into_raw();
|
|
||||||
|
|
||||||
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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 {
|
|
||||||
return Err(ASIOError::DriverLoadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
for d in &buffer_infos {
|
|
||||||
println!("before {:?}", d);
|
|
||||||
}
|
|
||||||
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::ASIOGetBufferSize(
|
|
||||||
&mut min_b_size,
|
|
||||||
&mut max_b_size,
|
|
||||||
&mut pref_b_size,
|
|
||||||
&mut grans,
|
|
||||||
);
|
|
||||||
result = if pref_b_size > 0 {
|
|
||||||
let mut buffer_info_convert = [
|
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
|
||||||
];
|
|
||||||
let mut callbacks_convert =
|
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
|
||||||
let buffer_result = ai::ASIOCreateBuffers(
|
|
||||||
buffer_info_convert.as_mut_ptr(),
|
|
||||||
num_channels,
|
|
||||||
pref_b_size,
|
|
||||||
&mut callbacks_convert,
|
|
||||||
);
|
|
||||||
if buffer_result == 0 {
|
|
||||||
let buffer_infos = [
|
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
|
||||||
];
|
|
||||||
for d in &buffer_infos {
|
|
||||||
println!("after {:?}", d);
|
|
||||||
}
|
|
||||||
println!("channels: {:?}", num_channels);
|
|
||||||
|
|
||||||
return Ok(AsioStream {
|
|
||||||
buffer_infos: buffer_infos,
|
|
||||||
driver: asio_drivers,
|
|
||||||
buffer_size: pref_b_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(ASIOError::BufferError(format!(
|
|
||||||
"failed to create buffers,
|
|
||||||
error code: {}",
|
|
||||||
buffer_result
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Err(ASIOError::BufferError(
|
|
||||||
"Failed to get buffer size".to_owned(),
|
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepare_stream(driver_name: &str) -> Result<AsioStream, ASIOError> {
|
|
||||||
//let mut buffer_info = ai::ASIOBufferInfo{_bindgen_opaque_blob: [0u32; 6]};
|
|
||||||
let mut buffer_infos = [
|
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 0,
|
|
||||||
channel_num: 0,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 0,
|
|
||||||
channel_num: 0,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let num_channels = 2;
|
|
||||||
//let mut callbacks = ai::ASIOCallbacks{_bindgen_opaque_blob: [0u32; 8]};
|
|
||||||
let mut callbacks = AsioCallbacks {
|
|
||||||
buffer_switch: buffer_switch,
|
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
|
||||||
asio_message: asio_message,
|
|
||||||
buffer_switch_time_info: buffer_switch_time_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut min_b_size: c_long = 0;
|
|
||||||
let mut max_b_size: c_long = 0;
|
|
||||||
let mut pref_b_size: c_long = 0;
|
|
||||||
let mut grans: c_long = 0;
|
|
||||||
|
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make owned CString to send to load driver
|
|
||||||
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
|
||||||
let raw = my_driver_name.into_raw();
|
|
||||||
|
|
||||||
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
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 {
|
|
||||||
return Err(ASIOError::DriverLoadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
for d in &buffer_infos {
|
|
||||||
println!("before {:?}", d);
|
|
||||||
}
|
|
||||||
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::ASIOGetBufferSize(
|
|
||||||
&mut min_b_size,
|
|
||||||
&mut max_b_size,
|
|
||||||
&mut pref_b_size,
|
|
||||||
&mut grans,
|
|
||||||
);
|
|
||||||
result = if pref_b_size > 0 {
|
|
||||||
let mut buffer_info_convert = [
|
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
|
||||||
];
|
|
||||||
let mut callbacks_convert =
|
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
|
||||||
let buffer_result = ai::ASIOCreateBuffers(
|
|
||||||
buffer_info_convert.as_mut_ptr(),
|
|
||||||
num_channels,
|
|
||||||
pref_b_size,
|
|
||||||
&mut callbacks_convert,
|
|
||||||
);
|
|
||||||
if buffer_result == 0 {
|
|
||||||
let buffer_infos = [
|
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
|
||||||
];
|
|
||||||
for d in &buffer_infos {
|
|
||||||
println!("after {:?}", d);
|
|
||||||
}
|
|
||||||
println!("channels: {:?}", num_channels);
|
|
||||||
|
|
||||||
return Ok(AsioStream {
|
|
||||||
buffer_infos: buffer_infos,
|
|
||||||
driver: asio_drivers,
|
|
||||||
buffer_size: pref_b_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(ASIOError::BufferError(format!(
|
|
||||||
"failed to create buffers,
|
|
||||||
error code: {}",
|
|
||||||
buffer_result
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Err(ASIOError::BufferError(
|
|
||||||
"Failed to get buffer size".to_owned(),
|
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn destroy_stream(stream: AsioStream) {
|
pub fn destroy_stream(stream: AsioStream) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ai::ASIODisposeBuffers();
|
ai::ASIODisposeBuffers();
|
||||||
let mut asio_drivers = stream.pop_driver();
|
|
||||||
asio_drivers.removeCurrentDriver();
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,22 +9,35 @@ use DefaultFormatError;
|
||||||
use SupportedFormat;
|
use SupportedFormat;
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use SampleRate;
|
use SampleRate;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Device{
|
pub struct Device{
|
||||||
// Calls to get a driver in memory
|
pub drivers: sys::Drivers,
|
||||||
// require a name so I will store the
|
pub name: String,
|
||||||
// name here as a handle to the driver
|
|
||||||
pub driver_name: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Devices{
|
pub struct Devices{
|
||||||
drivers: std::vec::IntoIter<String>,
|
drivers: std::vec::IntoIter<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Device {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.name == other.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Device {}
|
||||||
|
|
||||||
|
impl Hash for Device {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.name.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
self.driver_name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just supporting default for now
|
// Just supporting default for now
|
||||||
|
@ -44,70 +57,10 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Pass errors along
|
|
||||||
pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
|
pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
|
||||||
let format = Format{channels: 0, sample_rate: SampleRate(0),
|
let channels = self.drivers.get_channels().ins as u16;
|
||||||
// TODO Not sure about how to set the data type
|
let sample_rate = SampleRate(self.drivers.get_sample_rate().rate);
|
||||||
data_type: SampleFormat::F32};
|
match self.drivers.get_data_type() {
|
||||||
|
|
||||||
let format = match sys::get_channels(&self.driver_name) {
|
|
||||||
Ok(channels) => {
|
|
||||||
Format{channels: channels.ins as u16,
|
|
||||||
sample_rate: format.sample_rate,
|
|
||||||
data_type: format.data_type}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error retrieving channels: {}", e);
|
|
||||||
format
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let format = match sys::get_sample_rate(&self.driver_name) {
|
|
||||||
Ok(sample_rate) => {
|
|
||||||
Format{channels: format.channels,
|
|
||||||
sample_rate: SampleRate(sample_rate.rate),
|
|
||||||
data_type: format.data_type}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error retrieving sample rate: {}", e);
|
|
||||||
format
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let format = match sys::get_data_type(&self.driver_name) {
|
|
||||||
Ok(data_type) => {
|
|
||||||
println!("Audio Type: {:?}", data_type);
|
|
||||||
let data_type = match data_type{
|
|
||||||
sys::AsioSampleType::ASIOSTInt16MSB => SampleFormat::I16,
|
|
||||||
sys::AsioSampleType::ASIOSTFloat32MSB => SampleFormat::F32,
|
|
||||||
sys::AsioSampleType::ASIOSTInt16LSB => SampleFormat::I16,
|
|
||||||
// TODO This should not be set to 16bit but is for testing
|
|
||||||
sys::AsioSampleType::ASIOSTInt32LSB => SampleFormat::I16,
|
|
||||||
sys::AsioSampleType::ASIOSTFloat32LSB => SampleFormat::F32,
|
|
||||||
_ => panic!("Unsupported Audio Type: {:?}", data_type),
|
|
||||||
};
|
|
||||||
Format{channels: format.channels,
|
|
||||||
sample_rate: format.sample_rate,
|
|
||||||
data_type: data_type}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error retrieving sample rate: {}", e);
|
|
||||||
format
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(format)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
|
||||||
let num_channels = sys::get_channels(&self.driver_name)
|
|
||||||
.map(|c| c.outs as u16);
|
|
||||||
let sample_rate = sys::get_sample_rate(&self.driver_name)
|
|
||||||
.map(|s| SampleRate(s.rate));
|
|
||||||
let data_type = sys::get_data_type(&self.driver_name);
|
|
||||||
let data_type = match data_type{
|
|
||||||
Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16),
|
Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16),
|
||||||
Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32),
|
Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32),
|
||||||
Ok(sys::AsioSampleType::ASIOSTInt16LSB) => Ok(SampleFormat::I16),
|
Ok(sys::AsioSampleType::ASIOSTInt16LSB) => Ok(SampleFormat::I16),
|
||||||
|
@ -115,17 +68,29 @@ impl Device {
|
||||||
Ok(sys::AsioSampleType::ASIOSTInt32LSB) => Ok(SampleFormat::I16),
|
Ok(sys::AsioSampleType::ASIOSTInt32LSB) => Ok(SampleFormat::I16),
|
||||||
Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32),
|
Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32),
|
||||||
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
||||||
};
|
}.map(|dt| {
|
||||||
let format = match (num_channels, sample_rate, data_type){
|
Format{channels,
|
||||||
(Ok(num_channels), Ok(sample_rate), Ok(data_type)) =>{
|
sample_rate,
|
||||||
Ok(Format{channels: num_channels,
|
data_type: dt }
|
||||||
sample_rate: sample_rate,
|
})
|
||||||
data_type: data_type})
|
|
||||||
}
|
}
|
||||||
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
|
||||||
};
|
|
||||||
|
|
||||||
format
|
pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
||||||
|
let channels = self.drivers.get_channels().outs as u16;
|
||||||
|
let sample_rate = SampleRate(self.drivers.get_sample_rate().rate);
|
||||||
|
match self.drivers.get_data_type() {
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16),
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32),
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTInt16LSB) => Ok(SampleFormat::I16),
|
||||||
|
// TODO This should not be set to 16bit but is for testing
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTInt32LSB) => Ok(SampleFormat::I16),
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32),
|
||||||
|
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
||||||
|
}.map(|dt|{
|
||||||
|
Format{channels,
|
||||||
|
sample_rate,
|
||||||
|
data_type: dt }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +106,15 @@ impl Iterator for Devices {
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Device> {
|
fn next(&mut self) -> Option<Device> {
|
||||||
match self.drivers.next() {
|
match self.drivers.next() {
|
||||||
Some(dn) => Some(Device{driver_name: dn}),
|
Some(name) => {
|
||||||
|
sys::Drivers::load(&name)
|
||||||
|
.or_else(|e| {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
Err(e)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(|drivers| Device{drivers, name} )
|
||||||
|
},
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,31 +128,32 @@ impl Iterator for Devices {
|
||||||
// so returning first in list as default
|
// so returning first in list as default
|
||||||
pub fn default_input_device() -> Option<Device> {
|
pub fn default_input_device() -> Option<Device> {
|
||||||
let mut driver_list = sys::get_driver_list();
|
let mut driver_list = sys::get_driver_list();
|
||||||
for dn in &driver_list{
|
|
||||||
if dn == "ASIO4ALL v2"{
|
|
||||||
println!("Defaulted to ASIO4ALL **remove from production**");
|
|
||||||
return Some(Device{ driver_name: dn.clone() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match driver_list.pop() {
|
match driver_list.pop() {
|
||||||
Some(dn) => Some(Device{ driver_name: dn }),
|
Some(name) => {
|
||||||
|
sys::Drivers::load(&name)
|
||||||
|
.or_else(|e| {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
Err(e)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(|drivers| Device{drivers, name} )
|
||||||
|
},
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_output_device() -> Option<Device> {
|
pub fn default_output_device() -> Option<Device> {
|
||||||
let mut driver_list = sys::get_driver_list();
|
let mut driver_list = sys::get_driver_list();
|
||||||
// TODO For build test only,
|
|
||||||
// remove if inproduction
|
|
||||||
for dn in &driver_list{
|
|
||||||
if dn == "ASIO4ALL v2"{
|
|
||||||
println!("Defaulted to ASIO4ALL **remove from production**");
|
|
||||||
return Some(Device{ driver_name: dn.clone() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end remove
|
|
||||||
match driver_list.pop() {
|
match driver_list.pop() {
|
||||||
Some(dn) => Some(Device{ driver_name: dn }),
|
Some(name) => {
|
||||||
|
sys::Drivers::load(&name)
|
||||||
|
.or_else(|e| {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
Err(e)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(|drivers| Device{drivers, name} )
|
||||||
|
},
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,12 @@ impl EventLoop {
|
||||||
device: &Device,
|
device: &Device,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, CreationError> {
|
||||||
let stream_type = sys::get_data_type(&device.driver_name).expect("Couldn't load data type");
|
let Device {
|
||||||
match sys::prepare_input_stream(&device.driver_name) {
|
drivers,
|
||||||
|
..
|
||||||
|
} = device;
|
||||||
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
match drivers.prepare_input_stream() {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
let cpal_num_samples =
|
let cpal_num_samples =
|
||||||
|
@ -229,8 +233,12 @@ pub fn build_output_stream(
|
||||||
device: &Device,
|
device: &Device,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, CreationError> {
|
||||||
let stream_type = sys::get_data_type(&device.driver_name).expect("Couldn't load data type");
|
let Device {
|
||||||
match sys::prepare_stream(&device.driver_name) {
|
drivers,
|
||||||
|
..
|
||||||
|
} = device;
|
||||||
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
match drivers.prepare_output_stream() {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue