Multiple streams
This commit is contained in:
parent
c24fa62028
commit
76eb07a274
|
@ -34,7 +34,7 @@ pub struct CbArgs<S, D> {
|
||||||
struct BufferCallback(Box<FnMut(i32) + Send>);
|
struct BufferCallback(Box<FnMut(i32) + Send>);
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref buffer_callback: Mutex<Option<BufferCallback>> = Mutex::new(None);
|
static ref buffer_callback: Mutex<[Option<BufferCallback>; 2]> = Mutex::new([None, None]);
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -127,11 +127,20 @@ struct AsioCallbacks {
|
||||||
direct_process: c_long,
|
direct_process: c_long,
|
||||||
) -> *mut ai::ASIOTime,
|
) -> *mut ai::ASIOTime,
|
||||||
}
|
}
|
||||||
|
extern "C" fn buffer_switch_output(double_buffer_index: c_long, direct_process: c_long) -> () {
|
||||||
extern "C" fn buffer_switch(double_buffer_index: c_long, direct_process: c_long) -> () {
|
|
||||||
let mut bc = buffer_callback.lock().unwrap();
|
let mut bc = buffer_callback.lock().unwrap();
|
||||||
|
println!("output");
|
||||||
|
|
||||||
if let Some(ref mut bc) = *bc {
|
if let Some(ref mut bc) = bc[0] {
|
||||||
|
bc.run(double_buffer_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn buffer_switch_input(double_buffer_index: c_long, direct_process: c_long) -> () {
|
||||||
|
let mut bc = buffer_callback.lock().unwrap();
|
||||||
|
println!("input");
|
||||||
|
|
||||||
|
if let Some(ref mut bc) = bc[1] {
|
||||||
bc.run(double_buffer_index);
|
bc.run(double_buffer_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +269,7 @@ impl Drivers {
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut callbacks = AsioCallbacks {
|
let mut callbacks = AsioCallbacks {
|
||||||
buffer_switch: buffer_switch,
|
buffer_switch: buffer_switch_input,
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
asio_message: asio_message,
|
asio_message: asio_message,
|
||||||
buffer_switch_time_info: buffer_switch_time_info,
|
buffer_switch_time_info: buffer_switch_time_info,
|
||||||
|
@ -337,7 +346,7 @@ impl Drivers {
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut callbacks = AsioCallbacks {
|
let mut callbacks = AsioCallbacks {
|
||||||
buffer_switch: buffer_switch,
|
buffer_switch: buffer_switch_output,
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
asio_message: asio_message,
|
asio_message: asio_message,
|
||||||
buffer_switch_time_info: buffer_switch_time_info,
|
buffer_switch_time_info: buffer_switch_time_info,
|
||||||
|
@ -446,12 +455,18 @@ impl BufferCallback {
|
||||||
|
|
||||||
unsafe impl Send for AsioStream {}
|
unsafe impl Send for AsioStream {}
|
||||||
|
|
||||||
pub fn set_callback<F: 'static>(mut callback: F) -> ()
|
pub fn set_callback<F: 'static>(input: bool, mut callback: F) -> ()
|
||||||
where
|
where
|
||||||
F: FnMut(i32) + Send,
|
F: FnMut(i32) + Send,
|
||||||
{
|
{
|
||||||
let mut bc = buffer_callback.lock().unwrap();
|
let mut bc = buffer_callback.lock().unwrap();
|
||||||
*bc = Some(BufferCallback(Box::new(callback)));
|
if input {
|
||||||
|
println!("Set input callback");
|
||||||
|
bc[1] = Some(BufferCallback(Box::new(callback)));
|
||||||
|
}else{
|
||||||
|
println!("Set output callback");
|
||||||
|
bc[0] = Some(BufferCallback(Box::new(callback)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of all the ASIO drivers
|
/// Returns a list of all the ASIO drivers
|
||||||
|
@ -501,15 +516,15 @@ pub fn destroy_stream(stream: AsioStream) {
|
||||||
|
|
||||||
pub fn play() {
|
pub fn play() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = ai::ASIOStart();
|
let result = asio_start();
|
||||||
println!("start result: {}", result);
|
println!("start result: {:?}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop() {
|
pub fn stop() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = ai::ASIOStop();
|
let result = asio_stop();
|
||||||
println!("start result: {}", result);
|
println!("stop result: {:?}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,3 +582,13 @@ unsafe fn asio_exit() -> Result<(), AsioError> {
|
||||||
let result = ai::ASIOExit();
|
let result = ai::ASIOExit();
|
||||||
asio_result!(result)
|
asio_result!(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn asio_start() -> Result<(), AsioError> {
|
||||||
|
let result = ai::ASIOStart();
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn asio_stop() -> Result<(), AsioError> {
|
||||||
|
let result = ai::ASIOStop();
|
||||||
|
asio_result!(result)
|
||||||
|
}
|
|
@ -128,7 +128,15 @@ 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();
|
||||||
match driver_list.pop() {
|
// Remove
|
||||||
|
let d_name = driver_list.into_iter()
|
||||||
|
.filter(|d| d == "ASIO4ALL v2")
|
||||||
|
//.filter(|d| d.name() == "Dante Via (x64)")
|
||||||
|
//.filter(|d| d.name() == "Dante Virtual Soundcard (x64)")
|
||||||
|
.next();
|
||||||
|
//match driver_list.pop() {
|
||||||
|
match d_name {
|
||||||
|
// end remove
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
sys::Drivers::load(&name)
|
sys::Drivers::load(&name)
|
||||||
.or_else(|e| {
|
.or_else(|e| {
|
||||||
|
@ -144,7 +152,15 @@ pub fn default_input_device() -> Option<Device> {
|
||||||
|
|
||||||
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();
|
||||||
match driver_list.pop() {
|
// Remove
|
||||||
|
let d_name = driver_list.into_iter()
|
||||||
|
.filter(|d| d == "ASIO4ALL v2")
|
||||||
|
//.filter(|d| d.name() == "Dante Via (x64)")
|
||||||
|
//.filter(|d| d.name() == "Dante Virtual Soundcard (x64)")
|
||||||
|
.next();
|
||||||
|
//match driver_list.pop() {
|
||||||
|
match d_name {
|
||||||
|
// end remove
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
sys::Drivers::load(&name)
|
sys::Drivers::load(&name)
|
||||||
.or_else(|e| {
|
.or_else(|e| {
|
||||||
|
|
|
@ -16,8 +16,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
|
|
||||||
pub struct EventLoop {
|
pub struct EventLoop {
|
||||||
asio_stream: Arc<Mutex<Option<sys::AsioStream>>>,
|
asio_streams: Arc<Mutex<Vec<Option<sys::AsioStream>>>>,
|
||||||
stream_count: Arc<AtomicUsize>,
|
stream_count: AtomicUsize,
|
||||||
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ struct Buffers {
|
||||||
impl EventLoop {
|
impl EventLoop {
|
||||||
pub fn new() -> EventLoop {
|
pub fn new() -> EventLoop {
|
||||||
EventLoop {
|
EventLoop {
|
||||||
asio_stream: Arc::new(Mutex::new(None)),
|
asio_streams: Arc::new(Mutex::new(Vec::new())),
|
||||||
stream_count: Arc::new(AtomicUsize::new(0)),
|
stream_count: AtomicUsize::new(0),
|
||||||
callbacks: Arc::new(Mutex::new(Vec::new())),
|
callbacks: Arc::new(Mutex::new(Vec::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,11 @@ impl EventLoop {
|
||||||
let cpal_num_samples =
|
let cpal_num_samples =
|
||||||
(stream.buffer_size as usize) * num_channels as usize;
|
(stream.buffer_size as usize) * num_channels as usize;
|
||||||
{
|
{
|
||||||
*self.asio_stream.lock().unwrap() = Some(stream);
|
self.asio_streams.lock().unwrap().push(Some(stream));
|
||||||
}
|
}
|
||||||
let count = self.stream_count.load(Ordering::SeqCst);
|
let count = self.stream_count.load(Ordering::SeqCst);
|
||||||
self.stream_count.store(count + 1, Ordering::SeqCst);
|
self.stream_count.store(count + 1, Ordering::SeqCst);
|
||||||
let asio_stream = self.asio_stream.clone();
|
let asio_streams = self.asio_streams.clone();
|
||||||
let callbacks = self.callbacks.clone();
|
let callbacks = self.callbacks.clone();
|
||||||
let bytes_per_channel = format.data_type.sample_size();
|
let bytes_per_channel = format.data_type.sample_size();
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ impl EventLoop {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sys::set_callback(move |index| unsafe {
|
sys::set_callback(true, move |index| unsafe {
|
||||||
if let Some(ref asio_stream) = *asio_stream.lock().unwrap() {
|
if let Some(ref asio_stream) = asio_streams.lock().unwrap()[count - 1] {
|
||||||
// Number of samples needed total
|
// Number of samples needed total
|
||||||
let mut callbacks = callbacks.lock().unwrap();
|
let mut callbacks = callbacks.lock().unwrap();
|
||||||
|
|
||||||
|
@ -153,7 +153,6 @@ impl EventLoop {
|
||||||
let buff_ptr = asio_stream
|
let buff_ptr = asio_stream
|
||||||
.buffer_infos[i]
|
.buffer_infos[i]
|
||||||
.buffers[index as usize] as *mut $AsioType;
|
.buffers[index as usize] as *mut $AsioType;
|
||||||
//.offset(asio_stream.buffer_size as isize * i as isize);
|
|
||||||
let asio_buffer: &'static [$AsioType] =
|
let asio_buffer: &'static [$AsioType] =
|
||||||
std::slice::from_raw_parts(
|
std::slice::from_raw_parts(
|
||||||
buff_ptr,
|
buff_ptr,
|
||||||
|
@ -244,11 +243,11 @@ pub fn build_output_stream(
|
||||||
let cpal_num_samples =
|
let cpal_num_samples =
|
||||||
(stream.buffer_size as usize) * num_channels as usize;
|
(stream.buffer_size as usize) * num_channels as usize;
|
||||||
{
|
{
|
||||||
*self.asio_stream.lock().unwrap() = Some(stream);
|
self.asio_streams.lock().unwrap().push(Some(stream));
|
||||||
}
|
}
|
||||||
let count = self.stream_count.load(Ordering::SeqCst);
|
let count = self.stream_count.load(Ordering::SeqCst);
|
||||||
self.stream_count.store(count + 1, Ordering::SeqCst);
|
self.stream_count.store(count + 1, Ordering::SeqCst);
|
||||||
let asio_stream = self.asio_stream.clone();
|
let asio_streams = self.asio_streams.clone();
|
||||||
let callbacks = self.callbacks.clone();
|
let callbacks = self.callbacks.clone();
|
||||||
let bytes_per_channel = format.data_type.sample_size();
|
let bytes_per_channel = format.data_type.sample_size();
|
||||||
// Create buffers
|
// Create buffers
|
||||||
|
@ -292,8 +291,8 @@ pub fn build_output_stream(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sys::set_callback(move |index| unsafe {
|
sys::set_callback(false, move |index| unsafe {
|
||||||
if let Some(ref asio_stream) = *asio_stream.lock().unwrap() {
|
if let Some(ref asio_stream) = asio_streams.lock().unwrap()[count - 1] {
|
||||||
// Number of samples needed total
|
// Number of samples needed total
|
||||||
let mut callbacks = callbacks.lock().unwrap();
|
let mut callbacks = callbacks.lock().unwrap();
|
||||||
|
|
||||||
|
@ -402,8 +401,8 @@ pub fn pause_stream(&self, stream: StreamId) {
|
||||||
sys::stop();
|
sys::stop();
|
||||||
}
|
}
|
||||||
pub fn destroy_stream(&self, stream_id: StreamId) {
|
pub fn destroy_stream(&self, stream_id: StreamId) {
|
||||||
let mut asio_stream_lock = self.asio_stream.lock().unwrap();
|
let mut asio_streams_lock = self.asio_streams.lock().unwrap();
|
||||||
let old_stream = mem::replace(&mut *asio_stream_lock, None);
|
let old_stream = mem::replace(asio_streams_lock.get_mut(stream_id.0 - 1).expect("stream count out of bounds"), None);
|
||||||
if let Some(old_stream) = old_stream {
|
if let Some(old_stream) = old_stream {
|
||||||
sys::destroy_stream(old_stream);
|
sys::destroy_stream(old_stream);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue