diff --git a/src/app.rs b/src/app.rs index c0bf0c8..8e9d891 100644 --- a/src/app.rs +++ b/src/app.rs @@ -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(args: Args, terminal: &mut Terminal) -> Result<(), io::Error> { // prepare globals - let mut buffer : Vec = 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 application’s 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(args: Args, terminal: &mut Terminal) -> 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; diff --git a/src/main.rs b/src/main.rs index 8d5d436..3973272 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod parser; mod app; mod config; mod music; +mod source; use tui::{ backend::CrosstermBackend, diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 0000000..190b6bd --- /dev/null +++ b/src/source.rs @@ -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, +} + +impl PulseAudioSimple { + pub fn new( + device: Option<&str>, channels: u8, rate: u32, buffer: u32, server_buffer: u32 + ) -> Result { + 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 application’s 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 + } + } + } +}