use std::{thread, mem};
use std::vec::Vec;
use std::sync::mpsc::{channel, Sender, Receiver};
use record_context::RecordContext;
use record_context;
use openal::ffi;
use sndfile::{SndInfo, SndFile};
use sndfile::OpenMode::Write;
use sndfile::FormatType::{FormatWav, FormatPcm16};
use std::intrinsics::transmute;
pub struct Recorder {
ctxt: RecordContext,
stop_sender: Option<Sender<bool>>,
data_receiver: Option<Receiver<Vec<i16>>>,
samples: Vec<i16>
}
impl Recorder {
pub fn new(record_context: RecordContext) -> Recorder {
Recorder {
ctxt: record_context,
stop_sender: None,
data_receiver: None,
samples: Vec::new()
}
}
pub fn start(&mut self) {
let (stop_sender, stop_receiver) = channel();
let (data_sender, data_receiver) = channel();
let r_c = self.ctxt.clone();
self.stop_sender = Some(stop_sender);
self.data_receiver = Some(data_receiver);
thread::spawn(move || {
let mut terminate = false;
let ctxt = record_context::get(r_c);
unsafe { ffi::alcCaptureStart(ctxt); }
let mut available_samples = 0;
let mut samples: Vec<i16> = Vec::new();
while !terminate {
unsafe {
ffi::alcGetIntegerv(ctxt,
ffi::ALC_CAPTURE_SAMPLES,
1,
&mut available_samples)
};
if available_samples != 0 {
let tmp_buf = vec![0i16; available_samples as usize];
unsafe {
ffi::alcCaptureSamples(ctxt,
transmute(&tmp_buf[0]),
available_samples);
}
samples.extend(tmp_buf.into_iter());
}
match stop_receiver.try_recv() {
Ok(_) => {
unsafe { ffi::alcCaptureStop(ctxt); }
terminate = true;
},
_ => {}
}
}
data_sender.send(samples);
});
}
pub fn stop(&mut self) -> bool {
match self.stop_sender {
Some(ref s_c) => {
s_c.send(true);
match self.data_receiver {
Some(ref d_p) => {
self.samples = d_p.recv().ok().unwrap();
true
},
None => false
}
},
None => false
}
}
pub fn save_to_file(&mut self, filename: &str) -> bool {
if self.samples.len() == 0 {
false
} else {
let infos = Box::new(SndInfo {
frames : self.samples.len() as i64,
samplerate : 44100,
channels : 1,
format : (FormatPcm16 | FormatWav) as i32,
sections : 0,
seekable : 0
});
let mut file_ext = String::new();
file_ext.push_str(filename);
file_ext.push_str(".wav");
match SndFile::new_with_info(file_ext.as_ref(), Write, infos) {
Ok(mut f) => {
let len = self.samples.len() as i64;
f.write_i16(&mut self.samples[..], len);
f.close();
true
},
Err(e) => { println!("{}", e); false }
}
}
}
}