clean up
This commit is contained in:
parent
93f75940d6
commit
ff7fd62a2d
|
@ -21,6 +21,7 @@ use std::os::raw::c_long;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::sync::MutexGuard;
|
||||||
|
|
||||||
use asio_import as ai;
|
use asio_import as ai;
|
||||||
|
|
||||||
|
@ -38,7 +39,10 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ASIO_DRIVERS: Mutex<Option<DriverWrapper>> = Mutex::new(None);
|
static ref ASIO_DRIVERS: Mutex<DriverWrapper> = Mutex::new(DriverWrapper{
|
||||||
|
drivers: None,
|
||||||
|
state: AsioState::Offline,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
@ -59,7 +63,17 @@ pub struct Drivers;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DriverWrapper {
|
struct DriverWrapper {
|
||||||
pub drivers: ai::AsioDrivers,
|
drivers: Option<ai::AsioDrivers>,
|
||||||
|
state: AsioState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum AsioState {
|
||||||
|
Offline,
|
||||||
|
Loaded,
|
||||||
|
Initialized,
|
||||||
|
Prepared,
|
||||||
|
Running,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsioStreams {
|
pub struct AsioStreams {
|
||||||
|
@ -156,15 +170,15 @@ extern "C" fn buffer_switch_time_info(
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_drivers() -> MutexGuard<'static, DriverWrapper> {
|
||||||
|
ASIO_DRIVERS.lock().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
impl Drivers {
|
impl Drivers {
|
||||||
pub fn load(driver_name: &str) -> Result<Self, AsioDriverError> {
|
pub fn load(driver_name: &str) -> Result<Self, AsioDriverError> {
|
||||||
let mut drivers = ASIO_DRIVERS.lock().unwrap();
|
let mut drivers = get_drivers();
|
||||||
match *drivers {
|
match drivers.state {
|
||||||
Some(_) => {
|
AsioState::Offline => {
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
|
||||||
Ok(Drivers {})
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
// 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");
|
||||||
|
@ -175,21 +189,24 @@ 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);
|
||||||
let init_result = asio_init(&mut driver_info);
|
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 && init_result.is_ok() {
|
||||||
println!("Creating drivers");
|
println!("Creating drivers");
|
||||||
*drivers = Some(DriverWrapper {
|
drivers.drivers = Some(asio_drivers);
|
||||||
drivers: asio_drivers,
|
|
||||||
});
|
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
Ok(Drivers {})
|
Ok(Drivers)
|
||||||
} else {
|
} else {
|
||||||
Err(AsioDriverError::DriverLoadError)
|
Err(AsioDriverError::DriverLoadError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_ => {
|
||||||
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
|
Ok(Drivers)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +224,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).expect("failed to get channels");
|
get_drivers().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,
|
||||||
|
@ -224,7 +241,7 @@ impl Drivers {
|
||||||
let mut rate: c_double = 0.0f64;
|
let mut rate: c_double = 0.0f64;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
asio_get_sample_rate(&mut rate).expect("failed to get sample rate");
|
get_drivers().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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +259,7 @@ impl Drivers {
|
||||||
name: [0 as c_char; 32],
|
name: [0 as c_char; 32],
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
match asio_get_channel_info(&mut channel_info) {
|
match get_drivers().asio_get_channel_info(&mut channel_info) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
num::FromPrimitive::from_i32(channel_info.type_)
|
num::FromPrimitive::from_i32(channel_info.type_)
|
||||||
.map_or(Err(AsioDriverError::TypeError), |t| Ok(t))
|
.map_or(Err(AsioDriverError::TypeError), |t| Ok(t))
|
||||||
|
@ -312,22 +329,28 @@ impl Drivers {
|
||||||
},
|
},
|
||||||
(Some(input), None) => {
|
(Some(input), None) => {
|
||||||
self.create_buffers(input.buffer_infos)
|
self.create_buffers(input.buffer_infos)
|
||||||
.map(|(buffer_infos, buffer_size)| AsioStreams{
|
.map(|(buffer_infos, buffer_size)| {
|
||||||
input: Some(AsioStream{
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
buffer_infos,
|
AsioStreams{
|
||||||
buffer_size,
|
input: Some(AsioStream{
|
||||||
}),
|
buffer_infos,
|
||||||
output: None,
|
buffer_size,
|
||||||
|
}),
|
||||||
|
output: None,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(None, Some(output)) => {
|
(None, Some(output)) => {
|
||||||
self.create_buffers(output.buffer_infos)
|
self.create_buffers(output.buffer_infos)
|
||||||
.map(|(buffer_infos, buffer_size)| AsioStreams{
|
.map(|(buffer_infos, buffer_size)| {
|
||||||
output: Some(AsioStream{
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
buffer_infos,
|
AsioStreams{
|
||||||
buffer_size,
|
output: Some(AsioStream{
|
||||||
}),
|
buffer_infos,
|
||||||
input: None,
|
buffer_size,
|
||||||
|
}),
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(None, None) => panic!("Trying to create streams without preparing"),
|
(None, None) => panic!("Trying to create streams without preparing"),
|
||||||
|
@ -350,7 +373,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(AsioDriverError::NoResult("not implimented".to_owned()));
|
let mut drivers = get_drivers();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Get the buffer sizes
|
// Get the buffer sizes
|
||||||
|
@ -358,7 +381,7 @@ impl Drivers {
|
||||||
// max possible size
|
// max possible size
|
||||||
// preferred size
|
// preferred size
|
||||||
// granularity
|
// granularity
|
||||||
asio_get_buffer_size(
|
drivers.asio_get_buffer_size(
|
||||||
&mut min_b_size,
|
&mut min_b_size,
|
||||||
&mut max_b_size,
|
&mut max_b_size,
|
||||||
&mut pref_b_size,
|
&mut pref_b_size,
|
||||||
|
@ -371,7 +394,7 @@ impl Drivers {
|
||||||
.collect();
|
.collect();
|
||||||
let mut callbacks_convert =
|
let mut callbacks_convert =
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
||||||
asio_create_buffers(
|
drivers.asio_create_buffers(
|
||||||
buffer_info_convert.as_mut_ptr(),
|
buffer_info_convert.as_mut_ptr(),
|
||||||
num_channels as i32,
|
num_channels as i32,
|
||||||
pref_b_size,
|
pref_b_size,
|
||||||
|
@ -386,7 +409,6 @@ impl Drivers {
|
||||||
}
|
}
|
||||||
println!("channels: {:?}", num_channels);
|
println!("channels: {:?}", num_channels);
|
||||||
|
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
|
||||||
(buffer_infos, pref_b_size)
|
(buffer_infos, pref_b_size)
|
||||||
}).map_err(|e|{
|
}).map_err(|e|{
|
||||||
AsioDriverError::BufferError(format!(
|
AsioDriverError::BufferError(format!(
|
||||||
|
@ -407,30 +429,10 @@ impl Drop for 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");
|
println!("Destroying driver");
|
||||||
unsafe {
|
clean_up();
|
||||||
if let Some(mut asio_drivers) = (*ASIO_DRIVERS.lock().unwrap()).take() {
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers.drivers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO this should be tied to cpal streams and not AsioStreams
|
|
||||||
impl Drop for AsioStream {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
println!("dropping stream");
|
|
||||||
let count = STREAM_DRIVER_COUNT.fetch_sub(1, Ordering::SeqCst);
|
|
||||||
if count == 1 {
|
|
||||||
println!("Destroying driver");
|
|
||||||
unsafe {
|
|
||||||
if let Some(mut asio_drivers) = (*ASIO_DRIVERS.lock().unwrap()).take() {
|
|
||||||
ai::destruct_AsioDrivers(&mut asio_drivers.drivers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsafe impl Send for DriverWrapper {}
|
unsafe impl Send for DriverWrapper {}
|
||||||
|
|
||||||
|
@ -489,63 +491,135 @@ pub fn get_driver_list() -> Vec<String> {
|
||||||
driver_list
|
driver_list
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy_stream(stream: AsioStream) {
|
pub fn clean_up() {
|
||||||
unsafe {
|
let mut drivers = get_drivers();
|
||||||
asio_dispose_buffers().expect("Failed to dispose buffers");
|
match drivers.state {
|
||||||
asio_exit().expect("Failed to exit asio");
|
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() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = asio_start();
|
let result = get_drivers().asio_start();
|
||||||
println!("start result: {:?}", result);
|
println!("start result: {:?}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop() {
|
pub fn stop() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = asio_stop();
|
let result = get_drivers().asio_stop();
|
||||||
println!("stop result: {:?}", result);
|
println!("stop result: {:?}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_init(di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> {
|
impl DriverWrapper {
|
||||||
let result = ai::ASIOInit(di);
|
unsafe fn asio_init(&mut self, di: &mut ai::ASIODriverInfo) -> Result<(), AsioError> {
|
||||||
asio_result!(result)
|
if let AsioState::Loaded = self.state {
|
||||||
|
let result = ai::ASIOInit(di);
|
||||||
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Initialized)
|
||||||
|
}else{
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_get_channels(ins: &mut c_long, outs: &mut c_long) -> Result<(), AsioError> {
|
unsafe fn asio_get_channels(&mut self, ins: &mut c_long, outs: &mut c_long) -> Result<(), AsioError> {
|
||||||
let result = ai::ASIOGetChannels(ins, outs);
|
if let AsioState::Offline = self.state {
|
||||||
asio_result!(result)
|
Err(AsioError::NoDrivers)
|
||||||
|
} else {
|
||||||
|
let result = ai::ASIOGetChannels(ins, outs);
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_get_sample_rate(rate: &mut c_double) -> Result<(), AsioError> {
|
unsafe fn asio_get_sample_rate(&mut self, rate: &mut c_double) -> Result<(), AsioError> {
|
||||||
let result = ai::get_sample_rate(rate);
|
if let AsioState::Offline = self.state {
|
||||||
asio_result!(result)
|
Err(AsioError::NoDrivers)
|
||||||
|
} else {
|
||||||
|
let result = ai::get_sample_rate(rate);
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_get_channel_info(ci: &mut ai::ASIOChannelInfo) -> Result<(), AsioError> {
|
unsafe fn asio_get_channel_info(&mut self, ci: &mut ai::ASIOChannelInfo) -> Result<(), AsioError> {
|
||||||
let result = ai::ASIOGetChannelInfo(ci);
|
if let AsioState::Offline = self.state {
|
||||||
asio_result!(result)
|
Err(AsioError::NoDrivers)
|
||||||
|
} else {
|
||||||
|
let result = ai::ASIOGetChannelInfo(ci);
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_get_buffer_size(
|
unsafe fn asio_get_buffer_size(
|
||||||
|
&mut self,
|
||||||
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> {
|
||||||
let result = ai::ASIOGetBufferSize(
|
if let AsioState::Offline = self.state {
|
||||||
min_b_size,
|
Err(AsioError::NoDrivers)
|
||||||
max_b_size,
|
} else {
|
||||||
pref_b_size,
|
let result = ai::ASIOGetBufferSize(
|
||||||
grans,
|
min_b_size,
|
||||||
);
|
max_b_size,
|
||||||
asio_result!(result)
|
pref_b_size,
|
||||||
|
grans,
|
||||||
|
);
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_create_buffers(
|
unsafe fn asio_create_buffers(
|
||||||
|
&mut self,
|
||||||
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> {
|
||||||
|
use AsioState::*;
|
||||||
|
match self.state {
|
||||||
|
Offline | Loaded => return Err(AsioError::NoDrivers),
|
||||||
|
Running => {
|
||||||
|
self.asio_stop();
|
||||||
|
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
||||||
|
self.state = Initialized;
|
||||||
|
},
|
||||||
|
Prepared => {
|
||||||
|
self.asio_dispose_buffers().expect("Failed to dispose buffers");
|
||||||
|
self.state = Initialized;
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
let result = ai::ASIOCreateBuffers(
|
let result = ai::ASIOCreateBuffers(
|
||||||
buffer_info_convert,
|
buffer_info_convert,
|
||||||
num_channels,
|
num_channels,
|
||||||
|
@ -553,24 +627,53 @@ unsafe fn asio_create_buffers(
|
||||||
callbacks_convert,
|
callbacks_convert,
|
||||||
);
|
);
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Prepared)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_dispose_buffers() -> Result<(), AsioError> {
|
unsafe fn asio_dispose_buffers(&mut self) -> Result<(), AsioError> {
|
||||||
|
use AsioState::*;
|
||||||
|
match self.state {
|
||||||
|
Offline | Loaded => return Err(AsioError::NoDrivers),
|
||||||
|
Running | Prepared => (),
|
||||||
|
Initialized => return Ok(()),
|
||||||
|
}
|
||||||
let result = ai::ASIODisposeBuffers();
|
let result = ai::ASIODisposeBuffers();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Initialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_exit() -> Result<(), AsioError> {
|
unsafe fn asio_exit(&mut self) -> Result<(), AsioError> {
|
||||||
|
use AsioState::*;
|
||||||
|
match self.state {
|
||||||
|
Offline | Loaded => return Err(AsioError::NoDrivers),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
let result = ai::ASIOExit();
|
let result = ai::ASIOExit();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Loaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_start() -> Result<(), AsioError> {
|
unsafe fn asio_start(&mut self) -> Result<(), AsioError> {
|
||||||
|
use AsioState::*;
|
||||||
|
match self.state {
|
||||||
|
Offline | Loaded | Initialized => return Err(AsioError::NoDrivers),
|
||||||
|
Running => return Ok(()),
|
||||||
|
Prepared => (),
|
||||||
|
}
|
||||||
let result = ai::ASIOStart();
|
let result = ai::ASIOStart();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Running)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn asio_stop() -> Result<(), AsioError> {
|
unsafe fn asio_stop(&mut self) -> Result<(), AsioError> {
|
||||||
|
use AsioState::*;
|
||||||
|
match self.state {
|
||||||
|
Offline | Loaded => return Err(AsioError::NoDrivers),
|
||||||
|
Running => (),
|
||||||
|
Initialized | Prepared => return Ok(()),
|
||||||
|
}
|
||||||
let result = ai::ASIOStop();
|
let result = ai::ASIOStop();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
|
.map(|_| self.state = AsioState::Prepared)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ use SampleFormat;
|
||||||
|
|
||||||
pub struct EventLoop {
|
pub struct EventLoop {
|
||||||
asio_streams: Arc<Mutex<sys::AsioStreams>>,
|
asio_streams: Arc<Mutex<sys::AsioStreams>>,
|
||||||
|
cpal_streams: Arc<Mutex<Vec<Option<Stream>>>>,
|
||||||
stream_count: AtomicUsize,
|
stream_count: AtomicUsize,
|
||||||
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
||||||
}
|
}
|
||||||
|
@ -31,6 +32,11 @@ pub struct OutputBuffer<'a, T: 'a> {
|
||||||
buffer: &'a mut [T],
|
buffer: &'a mut [T],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Stream{
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct I16Buffer{
|
struct I16Buffer{
|
||||||
cpal: Vec<i16>,
|
cpal: Vec<i16>,
|
||||||
|
@ -56,6 +62,7 @@ impl EventLoop {
|
||||||
pub fn new() -> EventLoop {
|
pub fn new() -> EventLoop {
|
||||||
EventLoop {
|
EventLoop {
|
||||||
asio_streams: Arc::new(Mutex::new(sys::AsioStreams{input: None, output: None})),
|
asio_streams: Arc::new(Mutex::new(sys::AsioStreams{input: None, output: None})),
|
||||||
|
cpal_streams: Arc::new(Mutex::new(Vec::new())),
|
||||||
stream_count: AtomicUsize::new(0),
|
stream_count: AtomicUsize::new(0),
|
||||||
callbacks: Arc::new(Mutex::new(Vec::new())),
|
callbacks: Arc::new(Mutex::new(Vec::new())),
|
||||||
}
|
}
|
||||||
|
@ -259,6 +266,7 @@ impl EventLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.cpal_streams.lock().unwrap().push(Some(Stream::Input));
|
||||||
StreamId(count)
|
StreamId(count)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -414,10 +422,12 @@ pub fn build_output_stream(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.cpal_streams.lock().unwrap().push(Some(Stream::Output));
|
||||||
StreamId(count)
|
StreamId(count)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn play_stream(&self, stream: StreamId) {
|
pub fn play_stream(&self, stream: StreamId) {
|
||||||
sys::play();
|
sys::play();
|
||||||
}
|
}
|
||||||
|
@ -426,20 +436,17 @@ pub fn pause_stream(&self, stream: StreamId) {
|
||||||
sys::stop();
|
sys::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO the logic for this is wrong
|
|
||||||
// We are not destroying AsioStreams but CPAL streams
|
|
||||||
// Asio Streams should only be destroyed if there are no
|
|
||||||
// CPAL streams left
|
|
||||||
pub fn destroy_stream(&self, stream_id: StreamId) {
|
pub fn destroy_stream(&self, stream_id: StreamId) {
|
||||||
/*
|
let mut streams = self.cpal_streams.lock().unwrap();
|
||||||
let mut asio_streams_lock = self.asio_streams.lock().unwrap();
|
streams.get_mut(stream_id.0 - 1).take();
|
||||||
let old_stream = mem::replace(asio_streams_lock.get_mut(stream_id.0 - 1).expect("stream count out of bounds"), None);
|
let count = self.stream_count.load(Ordering::SeqCst);
|
||||||
if let Some(old_stream) = old_stream {
|
self.stream_count.store(count - 1, Ordering::SeqCst);
|
||||||
sys::destroy_stream(old_stream);
|
if count == 1 {
|
||||||
|
*self.asio_streams.lock().unwrap() = sys::AsioStreams{ output: None, input: None };
|
||||||
|
sys::clean_up();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<F>(&self, mut callback: F) -> !
|
pub fn run<F>(&self, mut callback: F) -> !
|
||||||
where
|
where
|
||||||
F: FnMut(StreamId, StreamData) + Send,
|
F: FnMut(StreamId, StreamData) + Send,
|
||||||
|
@ -456,6 +463,12 @@ F: FnMut(StreamId, StreamData) + Send,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for EventLoop {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
sys::clean_up();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T> InputBuffer<'a, T> {
|
impl<'a, T> InputBuffer<'a, T> {
|
||||||
pub fn buffer(&self) -> &[T] {
|
pub fn buffer(&self) -> &[T] {
|
||||||
&self.buffer
|
&self.buffer
|
||||||
|
|
Loading…
Reference in New Issue