use anyhow::Result;
use clap::Parser;
use log::warn;
use rustradio::Repeat;
use rustradio::blockchain;
use rustradio::blocks::*;
use rustradio::graph::GraphRunner;
use rustradio::mtgraph::MTGraph;
#[derive(clap::Parser, Debug)]
#[command(version, about)]
struct Opt {
#[arg(long, default_value_t = 0)]
verbose: usize,
#[arg(long)]
driver: String,
#[arg(long)]
input: std::path::PathBuf,
#[arg(long, default_value_t = 0.1)]
ogain: f32,
#[arg(long, default_value_t = 436.2)]
freq: f32,
#[arg(long, default_value_t = 48000)]
audio_rate: usize,
#[arg(long, default_value_t = 480000)]
sample_rate: usize,
#[arg(long)]
list_devices: bool,
#[arg(long, default_value_t = 5000)]
deviation: usize,
}
fn main() -> Result<()> {
let opt = Opt::parse();
stderrlog::new()
.module(module_path!())
.module("rustradio")
.quiet(false)
.verbosity(opt.verbose)
.timestamp(stderrlog::Timestamp::Second)
.init()?;
soapysdr::configure_logging();
if opt.list_devices {
for dev in soapysdr::enumerate("").unwrap() {
println!("{dev}");
}
return Ok(());
}
let mut g = MTGraph::new();
let dev = soapysdr::Device::new(&*opt.driver)?;
let prev = blockchain![
g,
prev,
FileSource::builder(&opt.input)
.repeat(Repeat::infinite())
.build()?,
AuDecode::new(prev, opt.audio_rate as u32),
RationalResampler::builder()
.deci(opt.audio_rate)
.interp(opt.sample_rate)
.build(prev)?,
Vco::new(
prev,
2.0 * std::f64::consts::PI * opt.deviation as f64 / opt.sample_rate as f64
),
];
g.add(Box::new(
SoapySdrSink::builder(
&dev,
(1_000_000.0 * opt.freq).into(),
opt.sample_rate as f64,
)
.ogain(opt.ogain.into())
.build(prev)?,
));
let cancel = g.cancel_token();
ctrlc::set_handler(move || {
warn!("Got Ctrl-C");
eprintln!("\n");
cancel.cancel();
})
.expect("failed to set Ctrl-C handler");
eprintln!("Running loop");
g.run()?;
eprintln!("{}", g.generate_stats().unwrap());
Ok(())
}