aboutsummaryrefslogtreecommitdiffstats
path: root/src/fl2k.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/fl2k.rs')
-rw-r--r--src/fl2k.rs78
1 files changed, 68 insertions, 10 deletions
diff --git a/src/fl2k.rs b/src/fl2k.rs
index 8bfc0ec..f2e197b 100644
--- a/src/fl2k.rs
+++ b/src/fl2k.rs
@@ -1,5 +1,5 @@
-use std::ffi::c_int;
-use fl2k_ampliphase::{fl2k_dev_t, fl2k_get_device_count, fl2k_open, fl2k_close, fl2k_stop_tx, fl2k_set_sample_rate, fl2k_get_sample_rate, fl2k_tx_cb_t, fl2k_start_tx};
+use std::{ffi::{c_int, c_void}, sync::mpsc};
+use fl2k_ampliphase::{fl2k_dev_t, fl2k_get_device_count, fl2k_open, fl2k_close, fl2k_stop_tx, fl2k_set_sample_rate, fl2k_get_sample_rate, fl2k_start_tx};
#[derive(Debug)]
pub enum FL2KError {
@@ -12,7 +12,7 @@ pub enum FL2KError {
Unknown(c_int)
}
-fn handle_return_value(val : c_int) -> Result<(), FL2KError> {
+fn handle_return_value(val: c_int) -> Result<(), FL2KError> {
if val == fl2k_ampliphase::fl2k_error_FL2K_SUCCESS { Ok(()) }
else if val == fl2k_ampliphase::fl2k_error_FL2K_TRUE { Ok(()) }
else if val == fl2k_ampliphase::fl2k_error_FL2K_ERROR_INVALID_PARAM { Err(FL2KError::InvalidParam) }
@@ -29,20 +29,71 @@ pub fn get_device_count() -> u32 {
}
pub struct FL2K {
- device : *mut fl2k_dev_t,
+ device: *mut fl2k_dev_t,
+ callback_ctx: Box<CallbackCtx>,
+ tx : mpsc::SyncSender<(Vec<i8>, Vec<i8>)>,
+}
+
+pub struct CallbackCtx {
+ // All three buffers must have same length!
+ r_buf: Vec<i8>,
+ g_buf: Vec<i8>,
+
+ rg_bufs_channel: mpsc::Receiver<(Vec<i8>, Vec<i8>)>,
+
+ underflow_count: u32,
+ buffer_underflows: u32,
+
+ abort: bool,
+}
+
+extern "C" fn tx_callback(data_info: *mut fl2k_ampliphase::fl2k_data_info_t) {
+ unsafe {
+ let ctx = (*data_info).ctx as *mut CallbackCtx;
+
+ if (*data_info).device_error != 0 {
+ (*ctx).abort = true;
+ }
+ else {
+ (*ctx).underflow_count = (*data_info).underflow_cnt;
+
+ match (*ctx).rg_bufs_channel.try_recv() {
+ Ok((r, g)) => {
+ (*data_info).sampletype_signed = 1;
+
+ (*ctx).r_buf = r;
+ (*ctx).g_buf = g;
+
+ (*data_info).r_buf = (*ctx).r_buf.as_mut_ptr();
+ (*data_info).g_buf = (*ctx).g_buf.as_mut_ptr();
+ },
+ Err(_) => {
+ (*ctx).buffer_underflows += 1;
+ },
+ }
+ }
+ }
}
impl FL2K {
- pub fn open(device_index : u32) -> Result<Self, FL2KError> {
+ pub fn open(device_index: u32) -> Result<Self, FL2KError> {
+ let (tx, rx) = mpsc::sync_channel(2);
+ let ctx = CallbackCtx {
+ r_buf: Vec::new(),
+ g_buf: Vec::new(),
+ rg_bufs_channel: rx,
+ underflow_count: 0,
+ buffer_underflows: 0,
+ abort: false,
+ };
unsafe {
- let mut fl2k = FL2K { device: std::mem::zeroed() };
+ let mut fl2k = FL2K { device: std::mem::zeroed(), callback_ctx: Box::new(ctx), tx };
handle_return_value(fl2k_open(&mut fl2k.device, device_index))?;
Ok(fl2k)
}
}
-
- pub fn set_sample_rate(&mut self, sample_rate : u32) -> Result<(), FL2KError> {
+ pub fn set_sample_rate(&mut self, sample_rate: u32) -> Result<(), FL2KError> {
handle_return_value( unsafe { fl2k_set_sample_rate(self.device, sample_rate) })
}
@@ -51,14 +102,21 @@ impl FL2K {
if sr == 0 { Err(FL2KError::Unknown(0)) } else { Ok(sr) }
}
- pub fn start_tx(&mut self, callback : fl2k_tx_cb_t, buf_num: u32) -> Result<(), FL2KError> {
- let r = unsafe { fl2k_start_tx(self.device, callback, std::ptr::null_mut(), 0) };
+ pub fn start_tx(&mut self) -> Result<(), FL2KError> {
+ let r = unsafe { fl2k_start_tx(self.device, Some(tx_callback), self.callback_ctx.as_mut() as *mut CallbackCtx as *mut c_void, 0) };
handle_return_value(r)
}
pub fn stop_tx(&self) -> Result<(), FL2KError> {
handle_return_value( unsafe { fl2k_stop_tx(self.device) } )
}
+
+ pub fn send(&self, r_buf: Vec<i8>, g_buf: Vec<i8>) -> bool {
+ if r_buf.len() != g_buf.len() {
+ panic!("r_buf and g_buf must have same length");
+ }
+ self.tx.send((r_buf, g_buf)).is_ok()
+ }
}