adding outputs
This commit is contained in:
parent
ff7fd62a2d
commit
ed50bb9923
|
@ -19,7 +19,7 @@ use std::os::raw::c_char;
|
||||||
use std::os::raw::c_double;
|
use std::os::raw::c_double;
|
||||||
use std::os::raw::c_long;
|
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, AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::MutexGuard;
|
use std::sync::MutexGuard;
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
pub static SILENCE_FIRST: AtomicBool = AtomicBool::new(false);
|
||||||
|
pub static SILENCE_SECOND: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl Device {
|
||||||
FormatsEnumerationError> {
|
FormatsEnumerationError> {
|
||||||
match self.default_input_format() {
|
match self.default_input_format() {
|
||||||
Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()),
|
Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()),
|
||||||
Err(e) => Err(FormatsEnumerationError::DeviceNotAvailable),
|
Err(_) => Err(FormatsEnumerationError::DeviceNotAvailable),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ impl Device {
|
||||||
FormatsEnumerationError> {
|
FormatsEnumerationError> {
|
||||||
match self.default_output_format() {
|
match self.default_output_format() {
|
||||||
Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()),
|
Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()),
|
||||||
Err(e) => Err(FormatsEnumerationError::DeviceNotAvailable),
|
Err(_) => Err(FormatsEnumerationError::DeviceNotAvailable),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ impl Iterator for Devices {
|
||||||
// Asio doesn't have a concept of default
|
// Asio doesn't have a concept of default
|
||||||
// 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 driver_list = sys::get_driver_list();
|
||||||
// Remove
|
// Remove
|
||||||
let d_name = driver_list.into_iter()
|
let d_name = driver_list.into_iter()
|
||||||
.filter(|d| d == "ASIO4ALL v2")
|
.filter(|d| d == "ASIO4ALL v2")
|
||||||
|
@ -151,7 +151,7 @@ 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 driver_list = sys::get_driver_list();
|
||||||
// Remove
|
// Remove
|
||||||
let d_name = driver_list.into_iter()
|
let d_name = driver_list.into_iter()
|
||||||
.filter(|d| d == "ASIO4ALL v2")
|
.filter(|d| d == "ASIO4ALL v2")
|
||||||
|
|
|
@ -5,11 +5,9 @@ use std;
|
||||||
use Format;
|
use Format;
|
||||||
use CreationError;
|
use CreationError;
|
||||||
use StreamData;
|
use StreamData;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use super::Device;
|
use super::Device;
|
||||||
use std::cell::Cell;
|
|
||||||
use UnknownTypeOutputBuffer;
|
|
||||||
use UnknownTypeInputBuffer;
|
use UnknownTypeInputBuffer;
|
||||||
|
use UnknownTypeOutputBuffer;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
@ -32,9 +30,8 @@ pub struct OutputBuffer<'a, T: 'a> {
|
||||||
buffer: &'a mut [T],
|
buffer: &'a mut [T],
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Stream{
|
struct Stream{
|
||||||
Input,
|
playing: bool,
|
||||||
Output,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -68,6 +65,9 @@ impl EventLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new CPAL Input Stream
|
||||||
|
/// If there is no ASIO Input Stream
|
||||||
|
/// it will be created
|
||||||
fn get_input_stream(&self, drivers: &sys::Drivers, num_channels: usize) -> Result<usize, CreationError> {
|
fn get_input_stream(&self, drivers: &sys::Drivers, num_channels: usize) -> Result<usize, CreationError> {
|
||||||
let ref mut streams = *self.asio_streams.lock().unwrap();
|
let ref mut streams = *self.asio_streams.lock().unwrap();
|
||||||
match streams.input {
|
match streams.input {
|
||||||
|
@ -130,8 +130,8 @@ impl EventLoop {
|
||||||
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_streams = self.asio_streams.clone();
|
let asio_streams = self.asio_streams.clone();
|
||||||
|
let cpal_streams = self.cpal_streams.clone();
|
||||||
let callbacks = self.callbacks.clone();
|
let callbacks = self.callbacks.clone();
|
||||||
let bytes_per_channel = format.data_type.sample_size();
|
|
||||||
|
|
||||||
// Create buffers
|
// Create buffers
|
||||||
let channel_len = cpal_num_samples
|
let channel_len = cpal_num_samples
|
||||||
|
@ -175,11 +175,19 @@ impl EventLoop {
|
||||||
};
|
};
|
||||||
|
|
||||||
sys::set_callback(move |index| unsafe {
|
sys::set_callback(move |index| unsafe {
|
||||||
|
//if not playing return early
|
||||||
|
{
|
||||||
|
if let Some(s) = cpal_streams.lock().unwrap().get(count - 1){
|
||||||
|
if let Some(s) = s{
|
||||||
|
if !s.playing { return (); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(ref asio_stream) = asio_streams.lock().unwrap().input {
|
if let Some(ref asio_stream) = asio_streams.lock().unwrap().input {
|
||||||
// Number of samples needed total
|
// Number of samples needed total
|
||||||
let mut callbacks = callbacks.lock().unwrap();
|
let mut callbacks = callbacks.lock().unwrap();
|
||||||
|
|
||||||
// Assuming only one callback, probably needs to change
|
// Theres only a single callback because theres only one event loop
|
||||||
match callbacks.first_mut() {
|
match callbacks.first_mut() {
|
||||||
Some(callback) => {
|
Some(callback) => {
|
||||||
macro_rules! try_callback {
|
macro_rules! try_callback {
|
||||||
|
@ -266,7 +274,7 @@ impl EventLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.cpal_streams.lock().unwrap().push(Some(Stream::Input));
|
self.cpal_streams.lock().unwrap().push(Some(Stream{ playing: false }));
|
||||||
StreamId(count)
|
StreamId(count)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -287,8 +295,8 @@ pub fn build_output_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_streams = self.asio_streams.clone();
|
let asio_streams = self.asio_streams.clone();
|
||||||
|
let cpal_streams = self.cpal_streams.clone();
|
||||||
let callbacks = self.callbacks.clone();
|
let callbacks = self.callbacks.clone();
|
||||||
let bytes_per_channel = format.data_type.sample_size();
|
|
||||||
// Create buffers
|
// Create buffers
|
||||||
let channel_len = cpal_num_samples
|
let channel_len = cpal_num_samples
|
||||||
/ num_channels as usize;
|
/ num_channels as usize;
|
||||||
|
@ -331,11 +339,19 @@ pub fn build_output_stream(
|
||||||
};
|
};
|
||||||
|
|
||||||
sys::set_callback(move |index| unsafe {
|
sys::set_callback(move |index| unsafe {
|
||||||
|
//if not playing return early
|
||||||
|
{
|
||||||
|
if let Some(s) = cpal_streams.lock().unwrap().get(count - 1){
|
||||||
|
if let Some(s) = s{
|
||||||
|
if !s.playing { return (); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(ref asio_stream) = asio_streams.lock().unwrap().output {
|
if let Some(ref asio_stream) = asio_streams.lock().unwrap().output {
|
||||||
// Number of samples needed total
|
// Number of samples needed total
|
||||||
let mut callbacks = callbacks.lock().unwrap();
|
let mut callbacks = callbacks.lock().unwrap();
|
||||||
|
|
||||||
// Assuming only one callback, probably needs to change
|
// Theres only a single callback because theres only one event loop
|
||||||
match callbacks.first_mut() {
|
match callbacks.first_mut() {
|
||||||
Some(callback) => {
|
Some(callback) => {
|
||||||
macro_rules! try_callback {
|
macro_rules! try_callback {
|
||||||
|
@ -349,9 +365,6 @@ pub fn build_output_stream(
|
||||||
$BuffersTypeIdent:ident
|
$BuffersTypeIdent:ident
|
||||||
) => {
|
) => {
|
||||||
let mut my_buffers = $Buffers;
|
let mut my_buffers = $Buffers;
|
||||||
// Buffer that is filled by cpal.
|
|
||||||
//let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples];
|
|
||||||
// Call in block because of mut borrow
|
|
||||||
{
|
{
|
||||||
let buff = OutputBuffer{
|
let buff = OutputBuffer{
|
||||||
buffer: &mut my_buffers.cpal
|
buffer: &mut my_buffers.cpal
|
||||||
|
@ -375,6 +388,25 @@ pub fn build_output_stream(
|
||||||
au::deinterleave(&c_buffer[..], channels);
|
au::deinterleave(&c_buffer[..], channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let silence = match index {
|
||||||
|
0 =>{
|
||||||
|
if !sys::SILENCE_FIRST.load(Ordering::SeqCst) {
|
||||||
|
sys::SILENCE_FIRST.store(true, Ordering::SeqCst);
|
||||||
|
sys::SILENCE_SECOND.store(false, Ordering::SeqCst);
|
||||||
|
true
|
||||||
|
}else{false}
|
||||||
|
},
|
||||||
|
1 =>{
|
||||||
|
if !sys::SILENCE_SECOND.load(Ordering::SeqCst) {
|
||||||
|
sys::SILENCE_SECOND.store(true, Ordering::SeqCst);
|
||||||
|
sys::SILENCE_FIRST.store(false, Ordering::SeqCst);
|
||||||
|
true
|
||||||
|
}else{false}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// For each channel write the cpal data to
|
// For each channel write the cpal data to
|
||||||
// the asio buffer
|
// the asio buffer
|
||||||
// TODO need to check for Endian
|
// TODO need to check for Endian
|
||||||
|
@ -388,7 +420,8 @@ pub fn build_output_stream(
|
||||||
asio_stream.buffer_size as usize);
|
asio_stream.buffer_size as usize);
|
||||||
for (asio_s, cpal_s) in asio_buffer.iter_mut()
|
for (asio_s, cpal_s) in asio_buffer.iter_mut()
|
||||||
.zip(channel){
|
.zip(channel){
|
||||||
*asio_s = (*cpal_s as i64 *
|
if silence { *asio_s = 0.0 as $AsioType; }
|
||||||
|
*asio_s += (*cpal_s as i64 *
|
||||||
::std::$AsioTypeIdent::MAX as i64 /
|
::std::$AsioTypeIdent::MAX as i64 /
|
||||||
::std::$SampleTypeIdent::MAX as i64) as $AsioType;
|
::std::$SampleTypeIdent::MAX as i64) as $AsioType;
|
||||||
}
|
}
|
||||||
|
@ -422,23 +455,40 @@ pub fn build_output_stream(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.cpal_streams.lock().unwrap().push(Some(Stream::Output));
|
self.cpal_streams.lock().unwrap().push(Some(Stream{ playing: false }));
|
||||||
StreamId(count)
|
StreamId(count)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn play_stream(&self, stream: StreamId) {
|
pub fn play_stream(&self, stream_id: StreamId) {
|
||||||
|
let mut streams = self.cpal_streams.lock().unwrap();
|
||||||
|
if let Some(s) = streams.get_mut(stream_id.0).expect("Bad play stream index") {
|
||||||
|
s.playing = true;
|
||||||
|
}
|
||||||
|
// Calling play when already playing is a no-op
|
||||||
sys::play();
|
sys::play();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pause_stream(&self, stream: StreamId) {
|
pub fn pause_stream(&self, stream_id: StreamId) {
|
||||||
|
let mut streams = self.cpal_streams.lock().unwrap();
|
||||||
|
if let Some(s) = streams.get_mut(stream_id.0).expect("Bad pause stream index") {
|
||||||
|
s.playing = false;
|
||||||
|
}
|
||||||
|
let any_playing = streams
|
||||||
|
.iter()
|
||||||
|
.filter(|s| if let Some(s) = s {
|
||||||
|
s.playing
|
||||||
|
} else {false} )
|
||||||
|
.next();
|
||||||
|
if let None = any_playing {
|
||||||
sys::stop();
|
sys::stop();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 streams = self.cpal_streams.lock().unwrap();
|
||||||
streams.get_mut(stream_id.0 - 1).take();
|
streams.get_mut(stream_id.0).take();
|
||||||
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);
|
||||||
if count == 1 {
|
if count == 1 {
|
||||||
|
|
Loading…
Reference in New Issue