use std::collections::BTreeMap;
use crate::naming::CharacterSet;
use crate::vocab::{AudioFormat, StemFormat, VideoCoverRetention, WebpEncodeSettings};
use super::shape::{AreasConfig, Settings};
#[derive(Debug, Default)]
pub struct FlagOverrides {
pub token: Option<String>,
pub settings: Settings,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EffectiveSettings {
pub token: Option<String>,
pub stored_token: Option<String>,
pub token_command: Option<String>,
pub account_id: Option<String>,
pub format: AudioFormat,
pub concurrency: u32,
pub retries: u32,
pub min_newest: u32,
pub animated_covers: bool,
pub raw_animated_cover: bool,
pub video_cover_retention: VideoCoverRetention,
pub animated_cover_webp: WebpEncodeSettings,
pub details_sidecar: bool,
pub lyrics_sidecar: bool,
pub lrc_sidecar: bool,
pub video_mp4: bool,
pub download_stems: bool,
pub stem_format: StemFormat,
pub naming_template: String,
pub character_set: CharacterSet,
pub areas: Option<AreasConfig>,
pub album_overrides: BTreeMap<String, String>,
pub lead_tracks: Vec<String>,
pub number_singletons: bool,
}
impl EffectiveSettings {
pub fn requires_ffmpeg(&self) -> bool {
matches!(self.format, AudioFormat::Flac | AudioFormat::Alac) || self.animated_covers
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::Config;
use crate::config::fixtures::{no_env, no_flags};
#[test]
fn audio_format_display_roundtrip() {
for fmt in [
AudioFormat::Mp3,
AudioFormat::Flac,
AudioFormat::Wav,
AudioFormat::Alac,
] {
let s = fmt.to_string();
assert_eq!(s.parse::<AudioFormat>().unwrap(), fmt);
}
}
#[test]
fn audio_format_ext() {
assert_eq!(AudioFormat::Mp3.ext(), "mp3");
assert_eq!(AudioFormat::Flac.ext(), "flac");
assert_eq!(AudioFormat::Wav.ext(), "wav");
assert_eq!(AudioFormat::Alac.ext(), "m4a");
}
fn base_settings(format: AudioFormat) -> EffectiveSettings {
let toml = "[accounts.a]\n";
let cfg = Config::from_toml(toml).unwrap();
let mut eff = cfg.resolve("a", None, &no_env(), &no_flags()).unwrap();
eff.format = format;
eff
}
#[test]
fn requires_ffmpeg_flac_always_needs_it() {
let mut eff = base_settings(AudioFormat::Flac);
eff.animated_covers = false;
assert!(eff.requires_ffmpeg());
eff.animated_covers = true;
assert!(eff.requires_ffmpeg());
}
#[test]
fn requires_ffmpeg_alac_always_needs_it() {
let mut eff = base_settings(AudioFormat::Alac);
eff.animated_covers = false;
assert!(eff.requires_ffmpeg(), "alac transcodes, so needs ffmpeg");
}
#[test]
fn requires_ffmpeg_mp3_needs_it_only_for_animated_webp() {
let mut eff = base_settings(AudioFormat::Mp3);
assert!(!eff.requires_ffmpeg(), "mp3 + no covers = no ffmpeg");
eff.animated_covers = true;
assert!(eff.requires_ffmpeg(), "mp3 + animated webp = needs ffmpeg");
eff.raw_animated_cover = true;
assert!(
eff.requires_ffmpeg(),
"mp3 + both (webp + raw mp4) = needs ffmpeg"
);
eff.animated_covers = false;
assert!(!eff.requires_ffmpeg(), "mp3 + raw mp4 only = no ffmpeg");
}
}