From 9a328a9ba2c4cf0dad23a473243805046bf4728f Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sun, 10 Sep 2017 16:31:32 +0200 Subject: [PATCH] Initial commit. Reacording and grabbing samples for vu meter works --- .gitignore | 2 + Cargo.lock | 101 ++++++++++++++++++++++++++++++++++ Cargo.toml | 11 ++++ rascam.toml | 7 +++ src/main.rs | 138 +++++++++++++++++++++++++++++++++++++++++++++++ testpipeline.txt | 1 + 6 files changed, 260 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 rascam.toml create mode 100644 src/main.rs create mode 100644 testpipeline.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..324c57f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..99ed221 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,101 @@ +[root] +name = "rascam" +version = "0.1.0" +dependencies = [ + "gstreamer 0.7.2 (git+https://github.com/arturoc/gstreamer1.0-rs.git)", + "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gstreamer" +version = "0.7.2" +source = "git+https://github.com/arturoc/gstreamer1.0-rs.git#1b7eaf024130520922c4f98f4ada135f58cfc315" + +[[package]] +name = "itertools" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" +"checksum gstreamer 0.7.2 (git+https://github.com/arturoc/gstreamer1.0-rs.git)" = "" +"checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7f61b753dd58ec5d4c735f794dbddde1f28b977f652afbcde89d75bc77902216" +"checksum serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2a169fa5384d751ada1da9f3992b81830151a03c875e40dcb37c9fb31aafc68f" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..94d3d56 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rascam" +version = "0.1.0" +authors = ["LongHairedHacker "] + +[dependencies] +itertools = "*" +serde = "*" +serde_derive = "*" +toml = "*" +gstreamer = { git = "https://github.com/arturoc/gstreamer1.0-rs.git" } diff --git a/rascam.toml b/rascam.toml new file mode 100644 index 0000000..b3feaf8 --- /dev/null +++ b/rascam.toml @@ -0,0 +1,7 @@ +[audio] +alsa_device = "hw:1,0" +rate = 96000 + +[output] +prefix = "test" +directory = "./output/" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d242f42 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,138 @@ +extern crate toml; +#[macro_use] +extern crate serde_derive; +extern crate gst; +extern crate itertools; + + +use std::fs::File; +use std::io::prelude::*; +use std::thread; +use std::time::Duration; + +use itertools::Itertools; + + + +#[derive(Debug, Deserialize)] +struct Config { + audio: AudioConfig, + output: OutputConfig, +} + +#[derive(Debug, Deserialize)] +struct AudioConfig { + alsa_device: String, + rate: u32, +} + +#[derive(Debug, Deserialize)] +struct OutputConfig { + directory: String, + prefix: String, +} + + + +fn read_config(path: &str) -> Config { + + let mut config_toml = String::new(); + + let mut file = match File::open(path) { + Ok(file) => file, + Err(_) => panic!("Could not find config file!"), + }; + + file.read_to_string(&mut config_toml) + .unwrap_or_else(|err| panic!("Error while reading config: [{}]", err)); + + let config: Config = + toml::from_str(&config_toml).unwrap_or_else(|err| { + panic!("Error while parsing config: [{}]", + err) + }); + + return config; +} + + + +fn main() { + gst::init(); + + let config = read_config("rascam.toml"); + + + let pipeline_str = format!("alsasrc device={} ! audio/x-raw,rate={},channels=2 ! queue ! tee name=apptee ! audioconvert ! flacenc ! filesink location={}/{}.flac apptee. ! queue ! audioconvert ! appsink name=appsink0 caps=\"audio/x-raw,format=F32LE,channels=2\"", + config.audio.alsa_device, + config.audio.rate, + config.output.directory, + config.output.prefix); + + let mut pipeline = gst::Pipeline::new_from_str(&pipeline_str).unwrap(); + let mut mainloop = gst::MainLoop::new(); + let mut bus = pipeline.bus().expect("Couldn't get bus from pipeline"); + let bus_receiver = bus.receiver(); + let appsink = pipeline + .get_by_name("appsink0") + .expect("Couldn't get appsink from pipeline"); + let appsink = gst::AppSink::new_from_element(appsink); + + mainloop.spawn(); + pipeline.play(); + + + loop { + let mut exit = false; + while let Ok(msg) = bus_receiver.try_recv() { + match msg.parse() { + gst::Message::StateChangedParsed { ref old, ref new, .. } => { + println!("element `{}` changed from {:?} to {:?}", + msg.src_name(), + old, + new); + } + gst::Message::ErrorParsed {ref error, ref debug, .. } => { + println!("error msg from element `{}`: {}, {}. Quitting", + msg.src_name(), + error.message(), + debug); + exit = true; + break; + } + _ => { + println!("msg of type `{}` from element `{}`", + msg.type_name(), + msg.src_name()); + } + } + } + if exit { + break; + } + + match appsink.recv(){ + Ok(gst::appsink::Message::NewSample(sample)) | Ok(gst::appsink::Message::NewPreroll(sample)) => { + if let Some(buffer) = sample.buffer() { + let (max0, max1) = buffer.map_read(|mapping| { + mapping.iter::().tuples().fold((0.0f32, 0.0f32), |(acc0, acc1), (sample0, sample1)| { + (acc0.max(sample0.abs()), acc1.max(sample1.abs())) + }) + }).unwrap(); + println!("{} | {}", max0, max1); + } + } + Ok(gst::appsink::Message::Eos) => { + println!("Got no sample when polling. EOS"); + break; + } + Err(_) => { + println!("Error, exiting"); + break; + } + } + } + + + mainloop.quit(); +} diff --git a/testpipeline.txt b/testpipeline.txt new file mode 100644 index 0000000..5282e2e --- /dev/null +++ b/testpipeline.txt @@ -0,0 +1 @@ +gst-launch-1.0 -v alsasrc device=hw:1,0 ! queue ! audio/x-raw,rate=96000 ! audioconvert ! flacenc ! filesink location=test.flac