Add matching host platform, max seconds recording, template Makefile
This commit is contained in:
parent
aba5279be9
commit
36dea6c9e2
17
Makefile
Normal file
17
Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
configure:
|
||||||
|
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
|
||||||
|
run-audio-recorder:
|
||||||
|
|
||||||
|
|
||||||
|
run-gps-recorder:
|
||||||
|
|
||||||
|
|
||||||
|
run-depth-recorder:
|
||||||
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
|||||||
all:
|
all:
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
test:
|
test: all
|
||||||
cargo build --release
|
|
||||||
mkdir -p recordings
|
mkdir -p recordings
|
||||||
bash run_test.sh
|
bash run_test.sh
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ use clap::{Parser, ValueEnum, Subcommand};
|
|||||||
pub enum Hosts {
|
pub enum Hosts {
|
||||||
Alsa,
|
Alsa,
|
||||||
Jack,
|
Jack,
|
||||||
|
CoreAudio,
|
||||||
|
Asio,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
@ -52,6 +54,10 @@ pub struct Rec {
|
|||||||
#[clap(short, long, value_name = "SECONDS")]
|
#[clap(short, long, value_name = "SECONDS")]
|
||||||
pub batch_recording: Option<u64>,
|
pub batch_recording: Option<u64>,
|
||||||
|
|
||||||
|
/// (optional) Will record for a total of [SECONDS]
|
||||||
|
#[clap(short, long, value_name = "MAX_SECONDS")]
|
||||||
|
pub max_seconds: Option<u64>,
|
||||||
|
|
||||||
/// Host API to use
|
/// Host API to use
|
||||||
#[clap(value_enum)]
|
#[clap(value_enum)]
|
||||||
pub host: Hosts,
|
pub host: Hosts,
|
||||||
|
@ -97,7 +97,7 @@ pub fn get_wav_spec(default_config: &SupportedStreamConfig, user_config: &Stream
|
|||||||
pub fn get_date_time_string() -> String {
|
pub fn get_date_time_string() -> String {
|
||||||
let now: DateTime<Local> = Local::now();
|
let now: DateTime<Local> = Local::now();
|
||||||
format!(
|
format!(
|
||||||
"{}-{}-{}_{}:{}:{}",
|
"{}-{}-{}_{}:{}:{:02}",
|
||||||
now.year(), now.month(), now.day(),
|
now.year(), now.month(), now.day(),
|
||||||
now.hour(), now.minute(), now.second(),
|
now.hour(), now.minute(), now.second(),
|
||||||
)
|
)
|
||||||
|
@ -19,10 +19,11 @@ type BatchInterrupt= Arc<AtomicBool>;
|
|||||||
pub struct InterruptHandles {
|
pub struct InterruptHandles {
|
||||||
batch_interrupt: BatchInterrupt,
|
batch_interrupt: BatchInterrupt,
|
||||||
stream_interrupt: StreamInterrupt,
|
stream_interrupt: StreamInterrupt,
|
||||||
|
max_seconds: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterruptHandles {
|
impl InterruptHandles {
|
||||||
pub fn new() -> Result<Self, anyhow::Error> {
|
pub fn new(max_seconds: Option<u64>) -> Result<Self, anyhow::Error> {
|
||||||
let stream_interrupt = Arc::new((Mutex::new(false), Condvar::new()));
|
let stream_interrupt = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
let stream_interrupt_cloned = stream_interrupt.clone();
|
let stream_interrupt_cloned = stream_interrupt.clone();
|
||||||
|
|
||||||
@ -42,13 +43,23 @@ impl InterruptHandles {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
batch_interrupt,
|
batch_interrupt,
|
||||||
stream_interrupt,
|
stream_interrupt,
|
||||||
|
max_seconds,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stream_wait(&self) {
|
pub fn stream_wait(&self) {
|
||||||
let &(ref lock, ref cvar) = &*self.stream_interrupt;
|
let &(ref lock, ref cvar) = &*self.stream_interrupt;
|
||||||
let mut started = lock.lock().unwrap();
|
let mut started = lock.lock().unwrap();
|
||||||
|
let now = std::time::Instant::now();
|
||||||
while !*started {
|
while !*started {
|
||||||
|
match self.max_seconds {
|
||||||
|
Some(secs) => {
|
||||||
|
if now.elapsed().as_secs() >= secs {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
started = cvar.wait(started).unwrap();
|
started = cvar.wait(started).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ use constants::*;
|
|||||||
use getters::*;
|
use getters::*;
|
||||||
use input_handling::*;
|
use input_handling::*;
|
||||||
use play::*;
|
use play::*;
|
||||||
|
use anyhow::{Error, Result, anyhow};
|
||||||
|
|
||||||
use anyhow::{Result, Error};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
|
@ -27,6 +27,7 @@ pub struct Recorder {
|
|||||||
name: String,
|
name: String,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
current_file: String,
|
current_file: String,
|
||||||
|
max_seconds: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Recorder
|
/// # Recorder
|
||||||
@ -50,10 +51,11 @@ impl Recorder {
|
|||||||
sample_rate: u32,
|
sample_rate: u32,
|
||||||
channels: u16,
|
channels: u16,
|
||||||
buffer_size: u32,
|
buffer_size: u32,
|
||||||
|
max_seconds: Option<u64>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
|
||||||
// Create interrupt handles to be used by the stream or batch loop.
|
// Create interrupt handles to be used by the stream or batch loop.
|
||||||
let interrupt_handles = InterruptHandles::new()?;
|
let interrupt_handles = InterruptHandles::new(max_seconds)?;
|
||||||
|
|
||||||
// Select requested host.
|
// Select requested host.
|
||||||
let host = get_host(host)?;
|
let host = get_host(host)?;
|
||||||
@ -80,13 +82,14 @@ impl Recorder {
|
|||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
current_file: "".to_string(),
|
current_file: "".to_string(),
|
||||||
|
max_seconds,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_writer(&mut self) -> Result<(), Error> {
|
fn init_writer(&mut self) -> Result<(), Error> {
|
||||||
let filename = get_filename(&self.name, &self.path);
|
let filename = get_filename(&self.name, &self.path);
|
||||||
self.current_file = filename.clone();
|
self.current_file = filename.clone();
|
||||||
*self.writer.lock().unwrap() = Some(hound::WavWriter::create(filename, self.spec)?);
|
self.writer = Arc::new(Mutex::new(Some(hound::WavWriter::create(filename, self.spec)?)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,15 +144,19 @@ impl Recorder {
|
|||||||
stream.play()?;
|
stream.play()?;
|
||||||
println!("REC: {}", self.current_file);
|
println!("REC: {}", self.current_file);
|
||||||
let now = std::time::Instant::now();
|
let now = std::time::Instant::now();
|
||||||
loop {
|
while self.interrupt_handles.batch_is_running() {
|
||||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
std::thread::sleep(std::time::Duration::from_millis(1));
|
||||||
if now.elapsed().as_secs() >= secs {
|
if now.elapsed().as_secs() >= secs {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(stream);
|
drop(stream);
|
||||||
self.writer.lock().unwrap().take().unwrap().finalize()?;
|
let writer = self.writer.clone();
|
||||||
println!("STOP: {}", self.current_file);
|
let current_file = self.current_file.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
writer.lock().unwrap().take().unwrap().finalize().unwrap();
|
||||||
|
println!("STOP: {}", current_file);
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +177,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn batch_recording(rec: &mut Recorder, secs: u64) -> Result<(), Error> {
|
fn batch_recording(rec: &mut Recorder, secs: u64) -> Result<(), Error> {
|
||||||
|
let now = std::time::Instant::now();
|
||||||
while rec.interrupt_handles.batch_is_running() {
|
while rec.interrupt_handles.batch_is_running() {
|
||||||
|
match rec.max_seconds {
|
||||||
|
Some(max_secs) => {
|
||||||
|
if now.elapsed().as_secs() >= max_secs {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
rec.record_secs(secs)?;
|
rec.record_secs(secs)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -181,6 +197,31 @@ fn continuous_recording(rec: &mut Recorder) -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn match_host_platform(host: Hosts) -> Result<cpal::HostId, Error> {
|
||||||
|
match host {
|
||||||
|
Hosts::Alsa => Ok(cpal::HostId::Alsa),
|
||||||
|
Hosts::Jack => Ok(cpal::HostId::Jack),
|
||||||
|
_ => Err(anyhow!("Host not supported on Linux.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn match_host_platform(host: Hosts) -> Result<cpal::HostId, Error> {
|
||||||
|
match host {
|
||||||
|
Hosts::CoreAudio => Ok(cpal::HostId::CoreAudio),
|
||||||
|
_ => Err(anyhow!("Host not supported on macOS.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn match_host_platform(host: Hosts) -> Result<cpal::HostId, Error> {
|
||||||
|
match host {
|
||||||
|
Hosts::Asio => Ok(cpal::HostId::Asio),
|
||||||
|
_ => Err(anyhow!("Host not supported on Windows.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn record(args: &Rec) -> Result<(), Error> {
|
pub fn record(args: &Rec) -> Result<(), Error> {
|
||||||
let mut recorder = Recorder::init(
|
let mut recorder = Recorder::init(
|
||||||
args.name.clone(),
|
args.name.clone(),
|
||||||
@ -188,13 +229,11 @@ pub fn record(args: &Rec) -> Result<(), Error> {
|
|||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => Path::new("./").to_path_buf(),
|
None => Path::new("./").to_path_buf(),
|
||||||
},
|
},
|
||||||
match args.host {
|
match_host_platform(args.host)?,
|
||||||
Hosts::Alsa => cpal::HostId::Alsa,
|
|
||||||
Hosts::Jack => cpal::HostId::Jack,
|
|
||||||
},
|
|
||||||
args.sample_rate.unwrap_or(DEFAULT_SAMPLE_RATE),
|
args.sample_rate.unwrap_or(DEFAULT_SAMPLE_RATE),
|
||||||
args.channels.unwrap_or(DEFAULT_CHANNEL_COUNT),
|
args.channels.unwrap_or(DEFAULT_CHANNEL_COUNT),
|
||||||
args.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE),
|
args.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE),
|
||||||
|
args.max_seconds,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
match args.batch_recording {
|
match args.batch_recording {
|
||||||
|
@ -6,4 +6,9 @@ https://www.circuito.io/app?components=9443,200000,267055
|
|||||||
|
|
||||||
# Setting up Jack on Raspberry Pi
|
# Setting up Jack on Raspberry Pi
|
||||||
|
|
||||||
https://wiki.linuxaudio.org/wiki/raspberrypi
|
https://wiki.linuxaudio.org/wiki/raspberrypi
|
||||||
|
https://github.com/supercollider/supercollider/blob/develop/README_RASPBERRY_PI.md
|
||||||
|
https://madskjeldgaard.dk/posts/raspi4-notes/
|
||||||
|
|
||||||
|
# Setting up GPS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user