73 lines
1.8 KiB
Rust
73 lines
1.8 KiB
Rust
use circular_buffer::CircularBuffer;
|
|
use songbird::input::core::io::MediaSource;
|
|
use std::io::SeekFrom;
|
|
use std::{
|
|
io::{Read, Seek, Write},
|
|
sync::{Arc, Condvar, Mutex},
|
|
};
|
|
|
|
const BUFFER_SIZE: usize = 64 * 1024;
|
|
|
|
#[derive(Clone, Default)]
|
|
pub struct CircularBufferSource {
|
|
condvar: Arc<Condvar>,
|
|
circular_buffer: Arc<Mutex<CircularBuffer<BUFFER_SIZE, u8>>>,
|
|
}
|
|
|
|
impl Read for CircularBufferSource {
|
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
|
let mut circ_buffer = self.circular_buffer.lock().expect("Mutex was poisoned");
|
|
|
|
if circ_buffer.is_empty() {
|
|
buf.fill(0);
|
|
self.condvar.notify_all();
|
|
return Ok(buf.len());
|
|
}
|
|
|
|
let bytes_to_read = usize::min(buf.len(), circ_buffer.len());
|
|
|
|
for (ndx, value) in circ_buffer.drain(0..bytes_to_read).enumerate() {
|
|
buf[ndx] = value;
|
|
}
|
|
|
|
self.condvar.notify_all();
|
|
|
|
Ok(bytes_to_read)
|
|
}
|
|
}
|
|
|
|
impl Write for CircularBufferSource {
|
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
|
let mut circ_buffer = self.circular_buffer.lock().expect("Mutex was poisoned");
|
|
|
|
while circ_buffer.len() + buf.len() > BUFFER_SIZE {
|
|
circ_buffer = self.condvar.wait(circ_buffer).expect("Mutex was poisoned");
|
|
}
|
|
|
|
circ_buffer.extend_from_slice(buf);
|
|
self.condvar.notify_all();
|
|
|
|
Ok(buf.len())
|
|
}
|
|
|
|
fn flush(&mut self) -> std::io::Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Seek for CircularBufferSource {
|
|
fn seek(&mut self, _pos: SeekFrom) -> std::io::Result<u64> {
|
|
Err(std::io::ErrorKind::Unsupported.into())
|
|
}
|
|
}
|
|
|
|
impl MediaSource for CircularBufferSource {
|
|
fn is_seekable(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
fn byte_len(&self) -> Option<u64> {
|
|
None
|
|
}
|
|
}
|