allow disabling use of certain format handlers
This commit is contained in:
parent
13bca72e47
commit
482dc39fce
11
Cargo.toml
11
Cargo.toml
|
@ -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
|
|
@ -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(),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
|
@ -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>,
|
|
@ -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,
|
|
@ -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>,
|
8
src/utils/formats/handlers/mod.rs
Normal file
8
src/utils/formats/handlers/mod.rs
Normal 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;
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue