use clap::{Arg, ArgAction, Command};
use songrec::{Config, OutputFormat, RecognitionOutput, SongRec};
use std::process;
fn main() {
let matches = Command::new("SongRec CLI")
.version("0.4.3")
.about("An open-source Shazam client library and CLI")
.subcommand(
Command::new("recognize")
.about("Recognize a song from an audio file")
.arg(
Arg::new("input")
.required(true)
.help("Input audio file path")
.index(1),
)
.arg(
Arg::new("format")
.short('f')
.long("format")
.value_name("FORMAT")
.help("Output format: simple, json, csv")
.default_value("simple"),
)
.arg(
Arg::new("quiet")
.short('q')
.long("quiet")
.action(ArgAction::SetTrue)
.help("Suppress verbose debug output (default)"),
)
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::SetTrue)
.help("Enable verbose debug output"),
),
)
.subcommand(
Command::new("listen")
.about("Listen continuously for songs")
.arg(
Arg::new("device")
.short('d')
.long("device")
.value_name("DEVICE")
.help("Audio input device name"),
)
.arg(
Arg::new("format")
.short('f')
.long("format")
.value_name("FORMAT")
.help("Output format: simple, json, csv")
.default_value("simple"),
)
.arg(
Arg::new("quiet")
.short('q')
.long("quiet")
.action(ArgAction::SetTrue)
.help("Suppress verbose debug output (default)"),
)
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::SetTrue)
.help("Enable verbose debug output"),
)
.arg(
Arg::new("no-dedupe")
.long("no-dedupe")
.action(ArgAction::SetTrue)
.help("Disable request deduplication"),
),
)
.subcommand(Command::new("devices").about("List available audio input devices"))
.get_matches();
match matches.subcommand() {
Some(("recognize", sub_matches)) => {
let input_file = sub_matches.get_one::<String>("input").unwrap();
let format_str = sub_matches.get_one::<String>("format").unwrap();
let verbose = sub_matches.get_flag("verbose");
let format = match format_str.as_str() {
"json" => OutputFormat::Json,
"csv" => OutputFormat::Csv,
_ => OutputFormat::Simple,
};
let config = Config::default().with_quiet_mode(!verbose);
let songrec = SongRec::new(config);
match songrec.recognize_from_file(input_file) {
Ok(result) => {
let output = RecognitionOutput::format_result(&result, format);
println!("{}", output);
}
Err(e) => {
eprintln!("Error: {}", e);
process::exit(1);
}
}
}
Some(("listen", sub_matches)) => {
let device = sub_matches.get_one::<String>("device").cloned();
let format_str = sub_matches.get_one::<String>("format").unwrap();
let verbose = sub_matches.get_flag("verbose");
let no_dedupe = sub_matches.get_flag("no-dedupe");
let format = match format_str.as_str() {
"json" => OutputFormat::Json,
"csv" => OutputFormat::Csv,
_ => OutputFormat::Simple,
};
let config = Config::default()
.with_quiet_mode(!verbose)
.with_deduplication(!no_dedupe);
let songrec = SongRec::new(config);
if verbose {
println!("Starting continuous recognition...");
}
if format == OutputFormat::Csv {
println!("{}", RecognitionOutput::csv_header());
}
match songrec.start_continuous_recognition_with_device(device) {
Ok(stream) => {
for result in stream {
match result {
Ok(recognition) => {
let output = RecognitionOutput::format_result(&recognition, format);
println!("{}", output);
}
Err(e) => {
if verbose {
eprintln!("Recognition error: {}", e);
}
}
}
}
}
Err(e) => {
if verbose {
eprintln!("Error starting recognition: {}", e);
}
process::exit(1);
}
}
}
Some(("devices", _)) => {
match songrec::audio::AudioRecorder::list_input_devices() {
Ok(devices) => {
println!("Available audio input devices:");
for (i, device) in devices.iter().enumerate() {
println!(" {}: {}", i, device);
}
}
Err(e) => {
eprintln!("Error listing devices: {}", e);
process::exit(1);
}
}
}
_ => {}
}
}