use jack_sys as j;
use std::mem;
use std::sync::atomic::{AtomicBool, Ordering};
pub struct RingBuffer(*mut j::jack_ringbuffer_t);
impl RingBuffer {
pub fn new(size: usize) -> Result<Self, crate::Error> {
let insize = size as libc::size_t;
let handle = unsafe { j::jack_ringbuffer_create(insize) };
if handle.is_null() {
return Err(crate::Error::RingbufferCreateFailed);
}
Ok(RingBuffer(handle))
}
pub fn mlock(&mut self) {
unsafe { j::jack_ringbuffer_mlock(self.0) };
}
pub fn reset(&mut self) {
unsafe { j::jack_ringbuffer_reset(self.0) };
}
pub fn into_reader_writer(self) -> (RingBufferReader, RingBufferWriter) {
let out = unsafe { (RingBufferReader::new(self.0), RingBufferWriter::new(self.0)) };
mem::forget(self);
out
}
pub fn from_reader_writer(r: RingBufferReader, w: RingBufferWriter) -> Self {
if r.ringbuffer_handle != w.ringbuffer_handle {
panic!("mismatching read and write handles!")
}
let handle = RingBuffer(r.ringbuffer_handle);
mem::forget(r);
mem::forget(w);
handle
}
}
impl Drop for RingBuffer {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { j::jack_ringbuffer_free(self.0) };
}
self.0 = std::ptr::null_mut();
}
}
unsafe impl Send for RingBuffer {}
unsafe impl Sync for RingBuffer {}
pub struct RingBufferReader {
ringbuffer_handle: *mut j::jack_ringbuffer_t,
both_live: AtomicBool,
}
unsafe impl Send for RingBufferReader {}
unsafe impl Sync for RingBufferReader {}
pub struct RingBufferWriter {
ringbuffer_handle: *mut j::jack_ringbuffer_t,
both_live: AtomicBool,
}
unsafe impl Send for RingBufferWriter {}
unsafe impl Sync for RingBufferWriter {}
impl RingBufferReader {
unsafe fn new(raw: *mut j::jack_ringbuffer_t) -> Self {
RingBufferReader {
ringbuffer_handle: raw,
both_live: AtomicBool::new(true),
}
}
pub fn get_vector(&self) -> (&[u8], &[u8]) {
let mut vec = [
j::jack_ringbuffer_data_t::default(),
j::jack_ringbuffer_data_t::default(),
];
let vecstart = &mut vec[0] as *mut j::jack_ringbuffer_data_t;
unsafe { j::jack_ringbuffer_get_read_vector(self.ringbuffer_handle, vecstart) };
let view1 = vec[0];
let view2 = vec[1];
let buf1 = view1.buf as *mut u8;
let len1 = view1.len;
let mut buf2 = view2.buf as *mut u8;
let len2 = view2.len;
if len2 == 0 {
buf2 = buf1;
}
let view1 = unsafe { std::slice::from_raw_parts(buf1, len1) };
let view2 = unsafe { std::slice::from_raw_parts(buf2, len2) };
(view1, view2)
}
pub fn read_buffer(&mut self, buf: &mut [u8]) -> usize {
if buf.is_empty() {
return 0;
}
let insize: libc::size_t = buf.len() as libc::size_t;
let bufstart = &mut buf[0] as *mut _ as *mut libc::c_char;
unsafe { j::jack_ringbuffer_read(self.ringbuffer_handle, bufstart, insize) }
}
pub fn read_slice<'a>(&mut self, buf: &'a mut [u8]) -> &'a [u8] {
let len = self.read_buffer(buf);
&buf[0..len]
}
pub fn peek(&self, buf: &mut [u8]) -> usize {
if buf.is_empty() {
return 0;
}
let insize: libc::size_t = buf.len() as libc::size_t;
let bufstart = &mut buf[0] as *mut _ as *mut libc::c_char;
unsafe { j::jack_ringbuffer_peek(self.ringbuffer_handle, bufstart, insize) }
}
pub fn advance(&mut self, cnt: usize) {
let incnt = cnt as libc::size_t;
unsafe { j::jack_ringbuffer_read_advance(self.ringbuffer_handle, incnt) };
}
pub fn space(&self) -> usize {
unsafe { j::jack_ringbuffer_read_space(self.ringbuffer_handle) }
}
pub fn peek_iter(
&'_ self,
) -> std::iter::Chain<std::slice::Iter<'_, u8>, std::slice::Iter<'_, u8>> {
let (view1, view2) = self.get_vector();
view1.iter().chain(view2.iter())
}
}
impl std::io::Read for RingBufferReader {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
Ok(self.read_buffer(buf))
}
}
impl Drop for RingBufferReader {
fn drop(&mut self) {
match self
.both_live
.compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
{
Ok(false) | Err(false) => {
drop(RingBuffer(self.ringbuffer_handle));
}
_ => (),
}
}
}
impl RingBufferWriter {
unsafe fn new(raw: *mut j::jack_ringbuffer_t) -> Self {
RingBufferWriter {
ringbuffer_handle: raw,
both_live: AtomicBool::new(true),
}
}
pub fn write_buffer(&mut self, buf: &[u8]) -> usize {
if buf.is_empty() {
return 0;
}
let insize: libc::size_t = buf.len() as libc::size_t;
let bufstart = &buf[0] as *const _ as *const libc::c_char;
unsafe { j::jack_ringbuffer_write(self.ringbuffer_handle, bufstart, insize) }
}
pub fn advance(&mut self, cnt: usize) {
let incnt = cnt as libc::size_t;
unsafe { j::jack_ringbuffer_write_advance(self.ringbuffer_handle, incnt) };
}
pub fn space(&mut self) -> usize {
unsafe { j::jack_ringbuffer_write_space(self.ringbuffer_handle) }
}
pub fn get_vector(&mut self) -> (&mut [u8], &mut [u8]) {
let mut vec = [
j::jack_ringbuffer_data_t::default(),
j::jack_ringbuffer_data_t::default(),
];
let vecstart = &mut vec[0] as *mut j::jack_ringbuffer_data_t;
unsafe { j::jack_ringbuffer_get_write_vector(self.ringbuffer_handle, vecstart) };
let view1 = vec[0];
let view2 = vec[1];
let buf1 = view1.buf as *mut u8;
let len1 = view1.len;
let mut buf2 = view2.buf as *mut u8;
let len2 = view2.len;
if len2 == 0 {
buf2 = buf1;
}
let view1 = unsafe { std::slice::from_raw_parts_mut(buf1, len1) };
let view2 = unsafe { std::slice::from_raw_parts_mut(buf2, len2) };
(view1, view2)
}
pub fn peek_iter(
&'_ mut self,
) -> std::iter::Chain<std::slice::IterMut<'_, u8>, std::slice::IterMut<'_, u8>> {
let (view1, view2) = self.get_vector();
view1.iter_mut().chain(view2.iter_mut())
}
}
impl std::io::Write for RingBufferWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(self.write_buffer(buf))
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl Drop for RingBufferWriter {
fn drop(&mut self) {
match self
.both_live
.compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
{
Ok(false) | Err(false) => {
drop(RingBuffer(self.ringbuffer_handle));
}
_ => (),
}
}
}