use anyhow::Result;
use colored::*;
use mp3rgain::{aac, id3v2, mp4meta, undo_gain};
use std::fmt::Write as _;
use std::path::Path;
use crate::cli::options::{Options, OutputFormat};
use crate::json_output::{FileStatus, JsonFileResult};
use crate::util::get_filename;
use super::utils::{restore_timestamp, save_original_mtime};
pub fn process_undo(file: &Path, opts: &Options) -> Result<(JsonFileResult, String)> {
let mut out = String::new();
let result = process_undo_into(file, opts, &mut out)?;
Ok((result, out))
}
fn process_undo_into(file: &Path, opts: &Options, out: &mut String) -> Result<JsonFileResult> {
let filename = get_filename(file);
let dry_run_prefix = opts.dry_run_prefix();
let original_mtime = save_original_mtime(file, opts);
if opts.dry_run {
if opts.output_format == OutputFormat::Text && !opts.quiet {
writeln!(out, " {} [DRY RUN] {} (would undo)", "~".cyan(), filename)?;
}
return Ok(JsonFileResult {
file: file.display().to_string(),
status: Some(FileStatus::DryRun),
dry_run: Some(true),
..Default::default()
});
}
let is_aac = mp4meta::is_aac_file(file);
let undo_result = if is_aac {
aac::undo_aac_gain(file)
} else if opts.use_id3v2 {
id3v2::undo_gain_id3v2(file)
} else {
undo_gain(file)
};
match undo_result {
Ok(frames) => {
if frames == 0 {
if opts.output_format == OutputFormat::Text && !opts.quiet {
writeln!(
out,
" {} {}{} (no changes to undo)",
".".cyan(),
dry_run_prefix,
filename
)?;
}
Ok(JsonFileResult {
file: file.display().to_string(),
status: Some(FileStatus::Skipped),
frames: Some(0),
..Default::default()
})
} else {
if let Some(mtime) = original_mtime {
restore_timestamp(file, mtime);
}
if opts.output_format == OutputFormat::Text && !opts.quiet {
writeln!(
out,
" {} {} ({} frames restored)",
"v".green(),
filename,
frames
)?;
}
Ok(JsonFileResult {
file: file.display().to_string(),
status: Some(FileStatus::Success),
frames: Some(frames),
..Default::default()
})
}
}
Err(e) => {
if opts.output_format == OutputFormat::Text && !opts.quiet {
eprintln!(" {} {} - {}", "x".red(), filename, e);
}
Ok(JsonFileResult {
file: file.display().to_string(),
status: Some(FileStatus::Error),
error: Some(e.to_string()),
..Default::default()
})
}
}
}