pub trait DataSource {
fn recv(&mut self) -> Option<&[u8]>; }
pub mod file {
use std::{fs::File, io::Read};
pub struct FileSource {
file: File,
buffer: Vec<u8>,
}
impl FileSource {
#[allow(clippy::new_ret_no_self)]
pub fn new(path: &str, buffer: u32) -> Result<Box<dyn super::DataSource>, std::io::Error> {
Ok(Box::new(
FileSource {
file: File::open(path)?,
buffer: vec![0u8; buffer as usize],
}
))
}
}
impl super::DataSource for FileSource {
fn recv(&mut self) -> Option<&[u8]> {
match self.file.read_exact(&mut self.buffer) {
Ok(()) => Some(self.buffer.as_slice()),
Err(_e) => None, }
}
}
}
#[cfg(feature = "pulseaudio")]
pub mod pulseaudio {
use libpulse_binding::{sample::{Spec, Format}, def::BufferAttr, error::PAErr, stream::Direction};
use libpulse_simple_binding::Simple;
pub struct PulseAudioSimpleDataSource {
simple: Simple,
buffer: Vec<u8>,
}
impl PulseAudioSimpleDataSource {
#[allow(clippy::new_ret_no_self)]
pub fn new(
device: Option<&str>, channels: u8, rate: u32, buffer: u32, server_buffer: u32
) -> Result<Box<dyn super::DataSource>, PAErr> {
let spec = Spec {
format: Format::S16NE, channels, rate,
};
if !spec.is_valid() {
return Err(PAErr(0)); }
let attrs = BufferAttr {
maxlength: server_buffer * buffer,
fragsize: buffer,
..Default::default()
};
let simple = Simple::new(
None, "scope-tui", Direction::Record, device, "data", &spec, None, Some(&attrs), )?;
Ok(Box::new(Self { simple, buffer: vec![0; buffer as usize] }))
}
}
impl super::DataSource for PulseAudioSimpleDataSource {
fn recv(&mut self) -> Option<&[u8]> {
match self.simple.read(&mut self.buffer) {
Ok(()) => Some(&self.buffer),
Err(e) => {
eprintln!("[!] could not receive from pulseaudio: {}", e);
None
}
}
}
}
}