extern crate easyjack as jack;
extern crate nix;
use nix::sys::signal;
use std::sync::atomic;
use std::sync::mpsc::{SyncSender, Receiver};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
const N: usize = 200;
static RUNNING: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
struct AudioHandler {
samples: [jack::DefaultAudioSample; N],
right_phase: usize,
left_phase: usize,
right_output: jack::OutputPortHandle<jack::DefaultAudioSample>,
left_output: jack::OutputPortHandle<jack::DefaultAudioSample>,
incoming: Receiver<[jack::DefaultAudioSample; N]>,
}
impl AudioHandler {
fn new(
init_samples: [jack::DefaultAudioSample; N],
right: jack::OutputPortHandle<jack::DefaultAudioSample>,
left: jack::OutputPortHandle<jack::DefaultAudioSample>,
incoming: Receiver<[jack::DefaultAudioSample; N]>) -> Self
{
AudioHandler {
samples: init_samples,
right_phase: 0,
left_phase: 0,
right_output: right,
left_output: left,
incoming: incoming
}
}
}
impl jack::ProcessHandler for AudioHandler {
fn process(&mut self, ctx: &jack::CallbackContext, nframes: jack::NumFrames) -> i32 {
let right = self.right_output.get_write_buffer(nframes, ctx);
let left = self.left_output.get_write_buffer(nframes, ctx);
for i in 0..(nframes as usize) {
right[i] = self.samples[self.right_phase];
left[i] = self.samples[self.left_phase];
self.right_phase = self.right_phase + 1;
self.left_phase = self.left_phase + 3;
if self.right_phase >= self.samples.len() {
self.right_phase = 0
}
if self.left_phase >= self.samples.len() {
self.left_phase = 0
}
}
match self.incoming.try_recv() {
Ok(samples) => self.samples = samples,
Err(_) => (),
};
0
}
}
struct SimpleClient<'a> {
client: jack::Client<'a>,
sender: SyncSender<[jack::DefaultAudioSample; N]>,
}
impl<'a> SimpleClient<'a> {
fn new() -> Result<Self, jack::status::Status> {
let client = jack::Client::open("simple", jack::options::NO_START_SERVER);
let mut client = match client {
Ok((client, _)) => client,
Err(code) => return Err(code),
};
let right = client.register_output_audio_port("output1").unwrap();
let left = client.register_output_audio_port("output2").unwrap();
let (tx, rx) = mpsc::sync_channel(1);
let handler = AudioHandler::new(SimpleClient::compute_sine(0.2), right, left, rx);
client.set_process_handler(handler).unwrap();
Ok(SimpleClient {
client: client,
sender: tx,
})
}
fn activate(&mut self) -> Result<(), jack::status::Status> {
self.client.activate()
}
fn run(mut self) {
let mut i = 0;
while RUNNING.load(atomic::Ordering::SeqCst) {
let newsine = SimpleClient::compute_sine(i as f32 / 10.0);
match self.sender.send(newsine) {
Ok(_) => (),
Err(_) => (),
};
i += 1;
if i > 10 {
i = 0
}
thread::sleep(Duration::from_millis(1000));
}
println!("tearing down");
self.client.close().unwrap();
}
fn compute_sine(constant: f32) -> [jack::DefaultAudioSample; N] {
let mut sine = [0.0; N];
for i in 0..N {
let inner = ((i as f32) / (N as f32)) * 3.14159265 * 2.0;
sine[i] = constant * inner.sin();
}
sine
}
}
extern "C" fn handle_sigint(_: i32) {
RUNNING.store(false, atomic::Ordering::SeqCst);
}
fn main() {
let action = signal::SigAction::new(
signal::SigHandler::Handler(handle_sigint),
signal::SaFlags::empty(),
signal::SigSet::empty());
unsafe { signal::sigaction(signal::Signal::SIGINT, &action) }.unwrap();
RUNNING.store(true, atomic::Ordering::SeqCst);
let mut c = SimpleClient::new().unwrap();
c.activate().unwrap();
c.run()
}