use std::marker::PhantomData;
use std::os::raw::c_void;
use std::ptr;
use crate::{
error::{check_status, Error, Result},
stream::StreamCommand,
usrp::Usrp,
utils::check_equal_buffer_lengths,
ReceiveMetadata,
};
#[derive(Debug)]
pub struct ReceiveStreamer<'usrp, I> {
handle: uhd_sys::uhd_rx_streamer_handle,
buffer_pointers: Vec<*mut c_void>,
usrp: PhantomData<&'usrp Usrp>,
item_phantom: PhantomData<I>,
}
impl<I> ReceiveStreamer<'_, I> {
pub(crate) fn new() -> Self {
ReceiveStreamer {
handle: ptr::null_mut(),
buffer_pointers: Vec::new(),
usrp: PhantomData,
item_phantom: PhantomData,
}
}
pub(crate) fn handle_mut(&mut self) -> &mut uhd_sys::uhd_rx_streamer_handle {
&mut self.handle
}
pub(crate) fn handle(&mut self) -> uhd_sys::uhd_rx_streamer_handle {
self.handle
}
pub fn send_command(&mut self, command: &StreamCommand) -> Result<(), Error> {
let command_c = command.as_c_command();
check_status(unsafe { uhd_sys::uhd_rx_streamer_issue_stream_cmd(self.handle, &command_c) })
}
pub fn num_channels(&self) -> usize {
let mut num_channels = 0usize;
check_status(unsafe {
uhd_sys::uhd_rx_streamer_num_channels(
self.handle,
&mut num_channels as *mut usize as *mut _,
)
})
.unwrap();
num_channels
}
pub fn receive(
&mut self,
buffers: &mut [&mut [I]],
timeout: f64,
one_packet: bool,
) -> Result<ReceiveMetadata, Error> {
let mut metadata = ReceiveMetadata::default();
let mut samples_received = 0usize;
if self.buffer_pointers.is_empty() {
self.buffer_pointers
.resize(self.num_channels(), ptr::null_mut());
}
assert_eq!(
buffers.len(),
self.buffer_pointers.len(),
"Number of buffers is not equal to this streamer's number of channels"
);
let buffer_length = check_equal_buffer_lengths(buffers);
for (entry, buffer) in self.buffer_pointers.iter_mut().zip(buffers.iter_mut()) {
*entry = buffer.as_mut_ptr() as *mut c_void;
}
check_status(unsafe {
uhd_sys::uhd_rx_streamer_recv(
self.handle,
self.buffer_pointers.as_mut_ptr(),
buffer_length as _,
metadata.handle_mut(),
timeout,
one_packet,
&mut samples_received as *mut usize as *mut _,
)
})?;
metadata.set_samples(samples_received);
Ok(metadata)
}
pub fn receive_simple(&mut self, buffer: &mut [I]) -> Result<ReceiveMetadata> {
self.receive(&mut [buffer], 0.1, false)
}
}
impl<I> Drop for ReceiveStreamer<'_, I> {
fn drop(&mut self) {
let _ = unsafe { uhd_sys::uhd_rx_streamer_free(&mut self.handle) };
}
}
unsafe impl<I> Send for ReceiveStreamer<'_, I> {}
unsafe impl<I> Sync for ReceiveStreamer<'_, I> {}