allow disabling use of certain format handlers

This commit is contained in:
chaos 2023-10-18 15:55:44 +01:00
parent 13bca72e47
commit 482dc39fce
No known key found for this signature in database
11 changed files with 133 additions and 72 deletions

View file

@ -32,8 +32,8 @@ infer = "0.15"
bytes = "1"
# tag reading
id3 = "1"
metaflac = "0.2"
id3 = { version = "1", optional = true }
metaflac = { version = "0.2", optional = true }
taglib = { path = "./modules/taglib", optional = true }
# for genhtml command
@ -51,5 +51,10 @@ tempfile = "3"
notify = "6"
[features]
default = ["taglib"]
default = ["taglib", "flac", "mp3", "ffmpeg_fallback"]
# Formats
taglib = ["dep:taglib"]
flac = ["dep:metaflac"]
mp3 = ["dep:id3"]
ffmpeg_fallback = [] # If to allow using ffmpeg as a fallback tag extractor

View file

@ -4,13 +4,13 @@ pub mod types;
use std::{
convert::Into,
path::PathBuf,
path::Path,
process::Command,
};
use self::errors::{AnalyzeError, FFProbeError};
pub fn analyze(path: &PathBuf) -> Result<types::FFProbeData, AnalyzeError> {
pub fn analyze(path: &Path) -> Result<types::FFProbeData, AnalyzeError> {
let output = Command::new(crate::meta::FFPROBE)
.args([
"-v",
@ -41,7 +41,7 @@ pub fn analyze(path: &PathBuf) -> Result<types::FFProbeData, AnalyzeError> {
let ffprobe_out = ffprobe_out.unwrap();
return Ok(types::FFProbeData {
Ok(types::FFProbeData {
tags: ffprobe_out.format.tags.into(),
});
})
}

View file

@ -10,13 +10,13 @@ pub struct FFProbeTags {
pub replaygain_track_gain: Option<String>,
}
impl Into<FFProbeTags> for ffprobe_output::FFProbeOutputTags {
fn into(self) -> FFProbeTags {
impl From<ffprobe_output::FFProbeOutputTags> for FFProbeTags {
fn from(val: ffprobe_output::FFProbeOutputTags) -> Self {
FFProbeTags {
title: self.title,
artist: self.artist,
replaygain_track_peak: self.replaygain_track_peak,
replaygain_track_gain: self.replaygain_track_gain,
title: val.title,
artist: val.artist,
replaygain_track_peak: val.replaygain_track_peak,
replaygain_track_gain: val.replaygain_track_gain,
}
}
}

View file

@ -3,9 +3,9 @@ use std::path::PathBuf;
use crate::{
types::{AudioFileInfo, ReplayGainRawData, Tags},
utils::format_detection::FileFormat,
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError}
};
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
pub struct FLACAudioFormat {
flac_tags: metaflac::Tag,

View file

@ -8,10 +8,9 @@ use string_error::into_err;
use crate::{
types::{AudioFileInfo, ReplayGainData, ReplayGainRawData, Tags},
utils::{format_detection::FileFormat, ffprobe},
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError},
};
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
#[derive(Default)]
struct Changes {
title: Option<String>,

View file

@ -9,9 +9,9 @@ use taglib::{
use crate::{
types::{AudioFileInfo, ReplayGainRawData, Tags},
utils::format_detection::FileFormat,
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError}
};
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
pub struct TaglibAudioFormat {
file: taglib::TagLibFile,

View file

@ -5,10 +5,9 @@ use id3::TagLike;
use crate::{
types::{AudioFileInfo, ReplayGainRawData, Tags},
utils::format_detection::FileFormat,
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError},
};
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
pub struct ID3AudioFormat {
id3_tags: id3::Tag,
path: Box<PathBuf>,

View file

@ -0,0 +1,8 @@
#[cfg(feature = "ffmpeg_fallback")]
pub mod generic_ffmpeg;
#[cfg(feature = "flac")]
pub mod flac;
#[cfg(feature = "taglib")]
pub mod generic_taglib;
#[cfg(feature = "mp3")]
pub mod id3;

View file

@ -1,9 +1,4 @@
pub mod flac;
pub mod generic_ffmpeg;
pub mod id3;
#[cfg(feature = "taglib")]
pub mod generic_taglib;
mod handlers;
use std::error::Error;
use std::path::Path;
@ -12,11 +7,14 @@ use thiserror::Error;
use crate::types::{AudioFileInfo, File, ReplayGainRawData, Tags};
use self::flac::new_flac_format_handler;
use self::id3::new_id3_format_handler;
#[cfg(feature = "flac")]
use self::handlers::flac::new_flac_format_handler;
#[cfg(feature = "taglib")]
use self::generic_taglib::new_taglib_format_handler;
use self::handlers::generic_taglib::new_taglib_format_handler;
#[cfg(feature = "mp3")]
use self::handlers::id3::new_id3_format_handler;
#[cfg(feature = "ffmpeg_fallback")]
use self::handlers::generic_ffmpeg::new_generic_ffmpeg_format_handler;
use super::format_detection::{detect_format, FileFormat};
@ -67,22 +65,65 @@ pub fn get_format_handler(file: &File) -> Result<Box<dyn AudioContainerFormat>,
}
}
match format {
FileFormat::FLAC => {
// Native FLAC support
return Ok(Box::new(new_flac_format_handler(&path)?));
}
FileFormat::MP3 => {
// Native MP3 support
return Ok(Box::new(new_id3_format_handler(&path)?));
}
_ => {}
#[cfg(feature = "mp3")]
if format == FileFormat::MP3 {
// Native MP3 support
return Ok(Box::new(new_id3_format_handler(&path)?));
}
#[cfg(feature = "flac")]
if format == FileFormat::FLAC {
// Native FLAC support
return Ok(Box::new(new_flac_format_handler(&path)?));
}
#[cfg(feature = "ffmpeg_fallback")]
match format {
FileFormat::MP3
| FileFormat::FLAC
| FileFormat::OggVorbis
| FileFormat::OggOpus
| FileFormat::OggFLAC
| FileFormat::OggSpeex
| FileFormat::OggTheora
| FileFormat::Wav
| FileFormat::WavPack
| FileFormat::AIFF => {
return Ok(Box::new(new_generic_ffmpeg_format_handler(&path, format)?));
}
#[allow(unreachable_patterns)]
_ => {},
}
panic!("no supported handler found");
}
fn is_supported_extension(file_path: &Path) -> bool {
fn is_supported_extension(ext: &str) -> bool {
#[cfg(feature = "taglib")]
if matches!(ext, "ogg" | "opus" | "wav" | "wv" | "aiff") {
return true;
}
#[cfg(feature = "mp3")]
if ext == "mp3" {
return true;
}
#[cfg(feature = "flac")]
if ext == "flac" {
return true;
}
// FFMpeg Fallback
#[cfg(feature = "ffmpeg_fallback")]
if matches!(ext, "mp3" | "flac" | "ogg" | "opus" | "wav" | "wv" | "aiff") {
return true;
}
false
}
pub fn is_supported_file(file_path: &Path) -> bool {
let ext = file_path.extension();
if ext.is_none() {
@ -91,18 +132,7 @@ fn is_supported_extension(file_path: &Path) -> bool {
let ext = ext.unwrap().to_str().unwrap();
#[cfg(feature = "taglib")]
{
if matches!(ext, "ogg" | "opus" | "wav" | "wv" | "aiff") {
return true;
}
}
matches!(ext, "mp3" | "flac")
}
pub fn is_supported_file(file_path: &Path) -> bool {
if !is_supported_extension(file_path) {
if !is_supported_extension(ext) {
return false;
}
@ -114,26 +144,46 @@ pub fn is_supported_file(file_path: &Path) -> bool {
let format = format.unwrap();
#[cfg(feature = "taglib")]
{
match format {
FileFormat::OggVorbis
| FileFormat::OggOpus
| FileFormat::OggFLAC
| FileFormat::OggSpeex
| FileFormat::Wav
| FileFormat::WavPack
| FileFormat::AIFF => {
return true;
}
_ => {}
match format {
FileFormat::OggVorbis
| FileFormat::OggOpus
| FileFormat::OggFLAC
| FileFormat::OggSpeex
| FileFormat::Wav
| FileFormat::WavPack
| FileFormat::AIFF => {
return true;
}
_ => {}
}
match format {
// Not supported yet
FileFormat::OggTheora => false,
FileFormat::FLAC | FileFormat::MP3 => true,
// Rest not supported
_ => false,
#[cfg(feature = "mp3")]
if format == FileFormat::MP3 {
return true;
}
#[cfg(feature = "flac")]
if format == FileFormat::FLAC {
return true;
}
#[cfg(feature = "ffmpeg_fallback")]
match format {
FileFormat::MP3
| FileFormat::FLAC
| FileFormat::OggVorbis
| FileFormat::OggOpus
| FileFormat::OggFLAC
| FileFormat::OggSpeex
| FileFormat::OggTheora
| FileFormat::Wav
| FileFormat::WavPack
| FileFormat::AIFF => {
return true;
}
#[allow(unreachable_patterns)]
_ => {}
}
false
}

View file

@ -5,7 +5,7 @@ pub mod transcoder;
pub mod ffprobe;
pub mod formats;
pub(self) mod music_scanner;
mod music_scanner;
pub use formats::is_supported_file;
pub use music_scanner::scan_for_music;

View file

@ -3,5 +3,5 @@ pub mod progress_monitor;
#[allow(clippy::all)]
mod transcoder;
pub mod types;
pub(self) use self::progress_monitor::progress_monitor;
use self::progress_monitor::progress_monitor;
pub use self::transcoder::transcode;