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" bytes = "1"
# tag reading # tag reading
id3 = "1" id3 = { version = "1", optional = true }
metaflac = "0.2" metaflac = { version = "0.2", optional = true }
taglib = { path = "./modules/taglib", optional = true } taglib = { path = "./modules/taglib", optional = true }
# for genhtml command # for genhtml command
@ -51,5 +51,10 @@ tempfile = "3"
notify = "6" notify = "6"
[features] [features]
default = ["taglib"] default = ["taglib", "flac", "mp3", "ffmpeg_fallback"]
# Formats
taglib = ["dep:taglib"] 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::{ use std::{
convert::Into, convert::Into,
path::PathBuf, path::Path,
process::Command, process::Command,
}; };
use self::errors::{AnalyzeError, FFProbeError}; 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) let output = Command::new(crate::meta::FFPROBE)
.args([ .args([
"-v", "-v",
@ -41,7 +41,7 @@ pub fn analyze(path: &PathBuf) -> Result<types::FFProbeData, AnalyzeError> {
let ffprobe_out = ffprobe_out.unwrap(); let ffprobe_out = ffprobe_out.unwrap();
return Ok(types::FFProbeData { Ok(types::FFProbeData {
tags: ffprobe_out.format.tags.into(), tags: ffprobe_out.format.tags.into(),
}); })
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -5,10 +5,9 @@ use id3::TagLike;
use crate::{ use crate::{
types::{AudioFileInfo, ReplayGainRawData, Tags}, types::{AudioFileInfo, ReplayGainRawData, Tags},
utils::format_detection::FileFormat, utils::format_detection::FileFormat,
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError},
}; };
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
pub struct ID3AudioFormat { pub struct ID3AudioFormat {
id3_tags: id3::Tag, id3_tags: id3::Tag,
path: Box<PathBuf>, 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; mod handlers;
pub mod generic_ffmpeg;
pub mod id3;
#[cfg(feature = "taglib")]
pub mod generic_taglib;
use std::error::Error; use std::error::Error;
use std::path::Path; use std::path::Path;
@ -12,11 +7,14 @@ use thiserror::Error;
use crate::types::{AudioFileInfo, File, ReplayGainRawData, Tags}; use crate::types::{AudioFileInfo, File, ReplayGainRawData, Tags};
use self::flac::new_flac_format_handler; #[cfg(feature = "flac")]
use self::id3::new_id3_format_handler; use self::handlers::flac::new_flac_format_handler;
#[cfg(feature = "taglib")] #[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}; use super::format_detection::{detect_format, FileFormat};
@ -67,22 +65,65 @@ pub fn get_format_handler(file: &File) -> Result<Box<dyn AudioContainerFormat>,
} }
} }
match format { #[cfg(feature = "mp3")]
FileFormat::FLAC => { if format == FileFormat::MP3 {
// Native FLAC support // Native MP3 support
return Ok(Box::new(new_flac_format_handler(&path)?)); return Ok(Box::new(new_id3_format_handler(&path)?));
}
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"); 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(); let ext = file_path.extension();
if ext.is_none() { if ext.is_none() {
@ -91,18 +132,7 @@ fn is_supported_extension(file_path: &Path) -> bool {
let ext = ext.unwrap().to_str().unwrap(); let ext = ext.unwrap().to_str().unwrap();
#[cfg(feature = "taglib")] if !is_supported_extension(ext) {
{
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) {
return false; return false;
} }
@ -114,26 +144,46 @@ pub fn is_supported_file(file_path: &Path) -> bool {
let format = format.unwrap(); let format = format.unwrap();
#[cfg(feature = "taglib")] #[cfg(feature = "taglib")]
{ match format {
match format { FileFormat::OggVorbis
FileFormat::OggVorbis | FileFormat::OggOpus
| FileFormat::OggOpus | FileFormat::OggFLAC
| FileFormat::OggFLAC | FileFormat::OggSpeex
| FileFormat::OggSpeex | FileFormat::Wav
| FileFormat::Wav | FileFormat::WavPack
| FileFormat::WavPack | FileFormat::AIFF => {
| FileFormat::AIFF => { return true;
return true;
}
_ => {}
} }
_ => {}
} }
match format { #[cfg(feature = "mp3")]
// Not supported yet if format == FileFormat::MP3 {
FileFormat::OggTheora => false, return true;
FileFormat::FLAC | FileFormat::MP3 => true,
// Rest not supported
_ => false,
} }
#[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 ffprobe;
pub mod formats; pub mod formats;
pub(self) mod music_scanner; mod music_scanner;
pub use formats::is_supported_file; pub use formats::is_supported_file;
pub use music_scanner::scan_for_music; pub use music_scanner::scan_for_music;

View file

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