virittaa

Log | Files | Refs | README | LICENSE

commit 48dfccd5d56b01f40f86c515b5feb6c54358d7c0
parent b44df3563bdf09df96415f324d6d11bf7d9c4c8e
Author: mtmn <miro@haravara.org>
Date:   Thu, 14 May 2026 01:08:56 +0200

feat!: deprecate csv report; default db path

Diffstat:
MREADME.md | 21+++++++--------------
Msrc/db.rs | 6+++---
Msrc/main.rs | 50+++++++++++++++++++++++++-------------------------
3 files changed, 35 insertions(+), 42 deletions(-)

diff --git a/README.md b/README.md @@ -6,7 +6,6 @@ A command-line tool that analyzes audio files to detect `BPM` and `Key` tags. * Detect BPM and Key of audio files * Write detected BPM and Key to metadata tags -* Generate CSV reports of analyzed tracks * Save track metadata to a database ## Building @@ -32,11 +31,10 @@ cargo build --release * `-w`, `--write`: Write detected BPM and Key to audio file metadata. * `-f`, `--force`: Re-analyze files even if they already have BPM/Key tags. * `-j`, `--jobs <JOBS>`: Number of threads to use (0 = all cores). -* `-r`, `--report`: Generate a CSV report with timestamped filename. * `-S`, `--save`: Save track reports (artist, track, BPM, key) to the database. * `-l`, `--list`: List all track reports stored in the database. -* `--query <PATH>`: Look up a track report by file path. -* `--db-path <PATH>`: Path to the database directory (default: `~/.local/share/virittaa.db`). +* `--query <KEY>`: Look up a track report by artist - track key. +* `--db-path <PATH>`: Path to the database directory (default: `~/.local/share/virittaa`). * `-h`, `--help`: Print help information. * `-V`, `--version`: Print version information. @@ -55,24 +53,19 @@ cargo build --release # Limit to 4 threads ./target/release/virittaa -j 4 /path/to/music/ -# Generate a CSV report -./target/release/virittaa --report /path/to/music/ - # Analyze and save reports to database ./target/release/virittaa --save /path/to/music/ # Write tags and save to database with custom path -./target/release/virittaa -w --save --db-path ~/my_library.db /path/to/music/ - -# Generate CSV report and save to database -./target/release/virittaa -r --save /path/to/music/ +./target/release/virittaa -w --save --db-path ~/my_library /path/to/music/ # List all tracks in the database ./target/release/virittaa --list -# Look up a specific track by file path -./target/release/virittaa --query /path/to/track.flac +# Look up a specific track +./target/release/virittaa --query "Aphex Twin - Xtal" # Query using a custom database path -./target/release/virittaa --list --db-path ~/my_library.db +./target/release/virittaa --list --db-path ~/my_library ``` + diff --git a/src/db.rs b/src/db.rs @@ -11,17 +11,17 @@ pub struct TrackReport { pub key: Option<String>, } -pub struct ReportDb { +pub struct LibraryDb { db: Db, } -impl ReportDb { +impl LibraryDb { /// # Errors /// /// Returns an error if the database cannot be opened or created. pub fn open(path: &Path) -> Result<Self> { let db = sled::open(path) - .with_context(|| format!("Failed to open sled database at {}", path.display()))?; + .with_context(|| format!("Failed to open database at {}", path.display()))?; Ok(Self { db }) } diff --git a/src/main.rs b/src/main.rs @@ -10,8 +10,8 @@ use rayon::prelude::*; use std::path::PathBuf; use walkdir::WalkDir; -use crate::db::ReportDb; -use crate::file_io::{process_file, write_report}; +use crate::db::LibraryDb; +use crate::file_io::process_file; use crate::types::TrackError; use crate::constants::SUPPORTED_EXTENSIONS; @@ -30,9 +30,11 @@ fn main() -> Result<()> { let matches = Command::new("virittaa") .version(clap::crate_version!()) .about("Analyze audio files to detect BPM and Key") - .arg(Arg::new("path").num_args(1..).help( - "One or more files or directories to analyze (not required with --list or --query)", - )) + .arg( + Arg::new("path") + .num_args(1..) + .help("One or more files or directories to analyze (not required with --list or --query)"), + ) .arg( Arg::new("write") .short('w') @@ -56,18 +58,11 @@ fn main() -> Result<()> { .value_parser(clap::value_parser!(usize)), ) .arg( - Arg::new("report") - .short('r') - .long("report") - .action(clap::ArgAction::SetTrue) - .help("Generate a CSV report file in the current directory"), - ) - .arg( Arg::new("save") .short('S') .long("save") .action(clap::ArgAction::SetTrue) - .help("Save track metadata to a database"), + .help("Save track reports (artist, track, BPM, key) to a database"), ) .arg( Arg::new("list") @@ -79,19 +74,18 @@ fn main() -> Result<()> { .arg( Arg::new("query") .long("query") - .help("Look up a track report by file path"), + .help("Look up a track report by artist - track key"), ) .arg( Arg::new("db-path") .long("db-path") - .help("Path to the database directory for saved reports (default: ~/.local/share/virittaa.db)"), + .help("Path to the database directory for saved reports (default: ~/.local/share/virittaa)"), ) .get_matches(); let write_tags = matches.get_flag("write"); let force = matches.get_flag("force"); let jobs = *matches.get_one::<usize>("jobs").unwrap(); - let generate_report = matches.get_flag("report"); let save_to_db = matches.get_flag("save"); let list_db = matches.get_flag("list"); let query_path = matches.get_one::<String>("query").map(String::as_str); @@ -99,17 +93,17 @@ fn main() -> Result<()> { p.clone() } else { let mut dir = dirs::data_local_dir().unwrap_or_else(|| std::path::PathBuf::from(".")); - dir.push("virittaa.db"); + dir.push("virittaa"); dir.to_string_lossy().to_string() }; // Read-only DB operations that don't need file paths if list_db || query_path.is_some() { - let db = ReportDb::open(std::path::Path::new(&db_path))?; + let db = LibraryDb::open(std::path::Path::new(&db_path))?; if let Some(path) = query_path { match db.get(path)? { - Some(report) => println!("{path}: {}", db::format_report(&report)), + Some(report) => println!("{}", db::format_report(&report)), None => eprintln!("No report found for: {path}"), } } else { @@ -142,7 +136,7 @@ fn main() -> Result<()> { } let report_db = if save_to_db { - Some(ReportDb::open(std::path::Path::new(&db_path))?) + Some(LibraryDb::open(std::path::Path::new(&db_path))?) } else { None }; @@ -179,9 +173,19 @@ fn main() -> Result<()> { let results: Vec<_> = results.into_iter().map(|r| r.unwrap()).collect(); let errors: Vec<_> = errors.into_iter().map(|r| r.unwrap_err()).collect(); + if !errors.is_empty() { + for err in &errors { + eprintln!("Error: {} - {}", err.path.display(), err.reason); + } + } + if let Some(db) = &report_db { for track in &results { - let key = track.path.to_string_lossy(); + let key = format!( + "{} - {}", + track.artist.as_deref().unwrap_or("Unknown"), + track.track.as_deref().unwrap_or("Unknown") + ); let report = db::TrackReport { artist: track.artist.clone(), track: track.track.clone(), @@ -196,9 +200,5 @@ fn main() -> Result<()> { } } - if generate_report { - write_report(&results, &errors)?; - } - Ok(()) }