1
0
Fork 0
mirror of https://github.com/alemidev/scope-tui.git synced 2024-11-12 17:59:19 +01:00

chore: modularized source backend code

This commit is contained in:
əlemi 2023-09-17 03:50:19 +02:00
parent c4960cf571
commit ba0174961a
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 64 additions and 45 deletions

View file

@ -12,49 +12,21 @@ use libpulse_simple_binding::Simple;
use libpulse_binding::{stream::Direction, def::BufferAttr};
use libpulse_binding::sample::{Spec, Format};
use crate::Args;
use crate::{Args, source::{PulseAudioSimple, DataSource}};
use crate::config::{ChartNames, ChartBounds, ChartReferences, AppConfig, Dimension};
use crate::parser::{SampleParser, Signed16PCM};
pub fn run_app<T : Backend>(args: Args, terminal: &mut Terminal<T>) -> Result<(), io::Error> {
// prepare globals
let mut buffer : Vec<u8> = vec![0; args.buffer as usize];
let mut app = App::from(&args);
let fmt = Signed16PCM{}; // TODO some way to choose this?
// setup audio capture
let spec = Spec {
format: Format::S16NE,
channels: args.channels,
rate: args.sample_rate,
};
assert!(spec.is_valid());
let dev = match &args.device {
Some(d) => Some(d.as_str()),
None => None,
};
let s = match Simple::new(
None, // Use the default server
"scope-tui", // Our applications name
Direction::Record, // We want a record stream
dev, // Use requested device, or default
"data", // Description of our stream
&spec, // Our sample format
None, // Use default channel map
Some(&BufferAttr {
maxlength: args.server_buffer * args.buffer,
fragsize: args.buffer,
..Default::default()
}),
) {
Ok(s) => s,
Err(e) => {
println!("[!] Could not connect to pulseaudio : {:?}", e);
return Err(io::Error::new(ErrorKind::Other, "could not connect to pulseaudio"));
},
};
let mut source = PulseAudioSimple::new(
args.device.as_deref(),
args.channels,
args.sample_rate,
args.buffer,
args.server_buffer
).unwrap();
let mut fps = 0;
let mut framerate = 0;
@ -62,17 +34,10 @@ pub fn run_app<T : Backend>(args: Args, terminal: &mut Terminal<T>) -> Result<()
let mut channels = vec![];
loop {
match s.read(&mut buffer) {
Ok(()) => {},
Err(e) => {
println!("[!] Could not read data from pulseaudio : {:?}", e);
return Err(io::Error::new(ErrorKind::Other, "could not read from pulseaudio"));
},
}
let data = source.recv().unwrap();
if !app.cfg.pause {
channels = fmt.oscilloscope(&mut buffer, args.channels);
channels = fmt.oscilloscope(data, args.channels);
}
let mut trigger_offset = 0;

View file

@ -2,6 +2,7 @@ mod parser;
mod app;
mod config;
mod music;
mod source;
use tui::{
backend::CrosstermBackend,

53
src/source.rs Normal file
View file

@ -0,0 +1,53 @@
use libpulse_binding::{stream::Direction, sample::{Spec, Format}, def::BufferAttr, error::{PAErr, Code}};
use libpulse_simple_binding::Simple;
pub trait DataSource {
fn recv(&mut self) -> Option<&[u8]>; // TODO convert in Result and make generic error
}
pub struct PulseAudioSimple {
simple: Simple,
buffer: Vec<u8>,
}
impl PulseAudioSimple {
pub fn new(
device: Option<&str>, channels: u8, rate: u32, buffer: u32, server_buffer: u32
) -> Result<Self, PAErr> {
let spec = Spec {
format: Format::S16NE, // TODO allow more formats?
channels, rate,
};
if !spec.is_valid() {
return Err(PAErr(0)); // TODO what error number should we throw?
}
let attrs = BufferAttr {
maxlength: server_buffer * buffer,
fragsize: buffer,
..Default::default()
};
let simple = Simple::new(
None, // Use the default server
"scope-tui", // Our applications name
Direction::Record, // We want a record stream
device, // Use requested device, or default
"data", // Description of our stream
&spec, // Our sample format
None, // Use default channel map
Some(&attrs), // Our hints on how to handle client/server buffers
)?;
Ok(Self { simple, buffer: vec![0; buffer as usize] })
}
}
impl DataSource for PulseAudioSimple {
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
}
}
}
}