refactor format handlers to make it easier to tell what extensions and formats are allowed by each
This commit is contained in:
parent
8b70b2b851
commit
1dc74c2cb0
|
@ -51,10 +51,10 @@ tempfile = "3"
|
||||||
notify = "6"
|
notify = "6"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["taglib_extractor", "flac_extractor", "mp3_extractor", "ffmpeg_extractor"]
|
default = ["taglib_extractor", "flac_extractor", "mp3_extractor", "ffprobe_extractor"]
|
||||||
|
|
||||||
# Formats
|
# Formats
|
||||||
taglib_extractor = ["dep:taglib"]
|
taglib_extractor = ["dep:taglib"]
|
||||||
flac_extractor = ["dep:metaflac"]
|
flac_extractor = ["dep:metaflac"]
|
||||||
mp3_extractor = ["dep:id3"]
|
mp3_extractor = ["dep:id3"]
|
||||||
ffmpeg_extractor = [] # If to allow using ffmpeg as a fallback tag extractor
|
ffprobe_extractor = [] # If to allow using ffmpeg/ffprobe as a fallback tag extractor
|
|
@ -7,15 +7,17 @@ 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::formats::{AudioFormatError, BoxedError, FormatHandler},
|
||||||
utils::formats::{AudioContainerFormat, AudioFormatError, BoxedError},
|
utils::{
|
||||||
|
ffprobe,
|
||||||
|
format_detection::{detect_format, FileFormat},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Changes {
|
struct Changes {
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
artist: Option<String>,
|
artist: Option<String>,
|
||||||
replaygain_data: Option<ReplayGainRawData>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -25,7 +27,7 @@ struct ExtractedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GenericFFMpegAudioFormat {
|
pub struct GenericFFMpegAudioFormat {
|
||||||
format_type: FileFormat,
|
file_format: FileFormat,
|
||||||
path: Box<PathBuf>,
|
path: Box<PathBuf>,
|
||||||
|
|
||||||
extracted_data: ExtractedData,
|
extracted_data: ExtractedData,
|
||||||
|
@ -47,7 +49,9 @@ impl GenericFFMpegAudioFormat {
|
||||||
artist: output.tags.artist,
|
artist: output.tags.artist,
|
||||||
};
|
};
|
||||||
|
|
||||||
if output.tags.replaygain_track_gain.is_some() && output.tags.replaygain_track_peak.is_some() {
|
if output.tags.replaygain_track_gain.is_some()
|
||||||
|
&& output.tags.replaygain_track_peak.is_some()
|
||||||
|
{
|
||||||
self.extracted_data.replaygain_data = Some(ReplayGainData {
|
self.extracted_data.replaygain_data = Some(ReplayGainData {
|
||||||
track_gain: output.tags.replaygain_track_gain.unwrap(),
|
track_gain: output.tags.replaygain_track_gain.unwrap(),
|
||||||
track_peak: output.tags.replaygain_track_peak.unwrap(),
|
track_peak: output.tags.replaygain_track_peak.unwrap(),
|
||||||
|
@ -60,7 +64,7 @@ impl GenericFFMpegAudioFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioContainerFormat for GenericFFMpegAudioFormat {
|
impl FormatHandler for GenericFFMpegAudioFormat {
|
||||||
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
||||||
let mut tags = self.extracted_data.tags.clone();
|
let mut tags = self.extracted_data.tags.clone();
|
||||||
|
|
||||||
|
@ -85,14 +89,6 @@ impl AudioContainerFormat for GenericFFMpegAudioFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_replaygain_tags(&self) -> bool {
|
fn contains_replaygain_tags(&self) -> bool {
|
||||||
if self.changes.replaygain_data.is_some() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.extracted_data.replaygain_data.is_some() {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,16 +106,12 @@ impl AudioContainerFormat for GenericFFMpegAudioFormat {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_replaygain_data(&mut self, data: ReplayGainRawData) -> Result<(), BoxedError> {
|
fn set_replaygain_data(&mut self, _data: ReplayGainRawData) -> Result<(), BoxedError> {
|
||||||
self.changes.replaygain_data = Some(data);
|
panic!("ffprobe doesn't support setting replaygain data, check supports_replaygain() f")
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_changes(&mut self) -> Result<(), BoxedError> {
|
fn save_changes(&mut self) -> Result<(), BoxedError> {
|
||||||
if self.changes.title.is_none()
|
if self.changes.title.is_none() && self.changes.artist.is_none() {
|
||||||
&& self.changes.artist.is_none()
|
|
||||||
&& self.changes.replaygain_data.is_none()
|
|
||||||
{
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,17 +162,22 @@ impl AudioContainerFormat for GenericFFMpegAudioFormat {
|
||||||
tags: self.get_tags(allow_missing_tags)?,
|
tags: self.get_tags(allow_missing_tags)?,
|
||||||
contains_replaygain: self.contains_replaygain_tags(),
|
contains_replaygain: self.contains_replaygain_tags(),
|
||||||
supports_replaygain: self.supports_replaygain(),
|
supports_replaygain: self.supports_replaygain(),
|
||||||
format: Some(self.format_type),
|
format: Some(self.file_format),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_generic_ffmpeg_format_handler(
|
pub fn new_handler(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
format_type: FileFormat,
|
file_format: Option<FileFormat>,
|
||||||
) -> Result<GenericFFMpegAudioFormat, BoxedError> {
|
) -> Result<GenericFFMpegAudioFormat, BoxedError> {
|
||||||
|
let mut file_format = file_format;
|
||||||
|
if file_format.is_none() {
|
||||||
|
file_format = Some(detect_format(path)?);
|
||||||
|
}
|
||||||
|
|
||||||
let mut handler = GenericFFMpegAudioFormat {
|
let mut handler = GenericFFMpegAudioFormat {
|
||||||
format_type,
|
file_format: file_format.unwrap(),
|
||||||
path: Box::new(path.to_path_buf()),
|
path: Box::new(path.to_path_buf()),
|
||||||
extracted_data: ExtractedData::default(),
|
extracted_data: ExtractedData::default(),
|
||||||
changes: Changes::default(),
|
changes: Changes::default(),
|
|
@ -3,7 +3,7 @@ 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}
|
utils::formats::{FormatHandler, AudioFormatError, BoxedError}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ fn flac_get_first(tag: &metaflac::Tag, key: &str) -> Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioContainerFormat for FLACAudioFormat {
|
impl FormatHandler for FLACAudioFormat {
|
||||||
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
||||||
let title = flac_get_first(&self.flac_tags, "TITLE");
|
let title = flac_get_first(&self.flac_tags, "TITLE");
|
||||||
let artist = flac_get_first(&self.flac_tags, "ARTIST");
|
let artist = flac_get_first(&self.flac_tags, "ARTIST");
|
||||||
|
@ -107,7 +107,7 @@ impl AudioContainerFormat for FLACAudioFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_flac_format_handler(path: &PathBuf) -> Result<FLACAudioFormat, BoxedError> {
|
pub fn new_handler(path: &PathBuf) -> Result<FLACAudioFormat, BoxedError> {
|
||||||
Ok(FLACAudioFormat {
|
Ok(FLACAudioFormat {
|
||||||
flac_tags: metaflac::Tag::read_from_path(path)?,
|
flac_tags: metaflac::Tag::read_from_path(path)?,
|
||||||
path: Box::new(path.clone()),
|
path: Box::new(path.clone()),
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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},
|
utils::formats::{FormatHandler, AudioFormatError, BoxedError},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ID3AudioFormat {
|
pub struct ID3AudioFormat {
|
||||||
|
@ -13,7 +13,7 @@ pub struct ID3AudioFormat {
|
||||||
path: Box<PathBuf>,
|
path: Box<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioContainerFormat for ID3AudioFormat {
|
impl FormatHandler for ID3AudioFormat {
|
||||||
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
||||||
let title = self.id3_tags.title();
|
let title = self.id3_tags.title();
|
||||||
let artist = self.id3_tags.artist();
|
let artist = self.id3_tags.artist();
|
||||||
|
@ -123,7 +123,7 @@ impl AudioContainerFormat for ID3AudioFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_id3_format_handler(path: &PathBuf) -> Result<ID3AudioFormat, BoxedError> {
|
pub fn new_handler(path: &PathBuf) -> Result<ID3AudioFormat, BoxedError> {
|
||||||
let id3_tags = id3::Tag::read_from_path(path)?;
|
let id3_tags = id3::Tag::read_from_path(path)?;
|
||||||
|
|
||||||
Ok(ID3AudioFormat {
|
Ok(ID3AudioFormat {
|
||||||
|
|
|
@ -1,8 +1,141 @@
|
||||||
#[cfg(feature = "ffmpeg_extractor")]
|
use std::path::PathBuf;
|
||||||
pub mod generic_ffmpeg;
|
|
||||||
|
use crate::utils::format_detection::FileFormat;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use super::{BoxedError, FormatHandler};
|
||||||
|
|
||||||
#[cfg(feature = "flac_extractor")]
|
#[cfg(feature = "flac_extractor")]
|
||||||
pub mod flac;
|
mod flac;
|
||||||
|
#[cfg(feature = "ffprobe_extractor")]
|
||||||
|
mod ffprobe;
|
||||||
#[cfg(feature = "taglib_extractor")]
|
#[cfg(feature = "taglib_extractor")]
|
||||||
pub mod generic_taglib;
|
mod taglib;
|
||||||
#[cfg(feature = "mp3_extractor")]
|
#[cfg(feature = "mp3_extractor")]
|
||||||
pub mod id3;
|
mod id3;
|
||||||
|
|
||||||
|
type NewHandlerFuncReturn = Result<Box<dyn FormatHandler>, BoxedError>;
|
||||||
|
type NewHandlerFunc = fn(path: &PathBuf, file_format: Option<FileFormat>) -> NewHandlerFuncReturn;
|
||||||
|
|
||||||
|
pub struct Handler {
|
||||||
|
pub supported_extensions: Vec<String>,
|
||||||
|
pub supported_formats: Vec<FileFormat>,
|
||||||
|
pub new: NewHandlerFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref SUPPORTED_EXTENSIONS: Vec<String> = {
|
||||||
|
let mut extensions: Vec<String> = Vec::new();
|
||||||
|
for handler in HANDLERS.iter() {
|
||||||
|
for extension in handler.supported_extensions.iter() {
|
||||||
|
if !extensions.contains(extension) {
|
||||||
|
extensions.push(extension.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ref SUPPORTED_FORMATS: Vec<FileFormat> = {
|
||||||
|
let mut formats: Vec<FileFormat> = Vec::new();
|
||||||
|
for handler in HANDLERS.iter() {
|
||||||
|
for format in handler.supported_formats.iter() {
|
||||||
|
if !formats.contains(format) {
|
||||||
|
formats.push(*format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
formats
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ref HANDLERS: Vec<Handler> = {
|
||||||
|
let mut handlers: Vec<Handler> = Vec::new();
|
||||||
|
|
||||||
|
#[cfg(feature = "mp3_extractor")]
|
||||||
|
handlers.push(Handler {
|
||||||
|
supported_extensions: vec!["mp3".to_string()],
|
||||||
|
supported_formats: vec![FileFormat::MP3],
|
||||||
|
new: |path, _file_format| -> NewHandlerFuncReturn {
|
||||||
|
let handler = id3::new_handler(path)?;
|
||||||
|
|
||||||
|
Ok(Box::from(handler))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "flac_extractor")]
|
||||||
|
handlers.push(Handler {
|
||||||
|
supported_extensions: vec!["flac".to_string()],
|
||||||
|
supported_formats: vec![FileFormat::FLAC],
|
||||||
|
new: |path, _file_format| -> NewHandlerFuncReturn {
|
||||||
|
let handler = flac::new_handler(path)?;
|
||||||
|
|
||||||
|
Ok(Box::from(handler))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "taglib_extractor")]
|
||||||
|
handlers.push(Handler {
|
||||||
|
supported_extensions: vec![
|
||||||
|
"mp3".to_string(),
|
||||||
|
"flac".to_string(),
|
||||||
|
"ogg".to_string(),
|
||||||
|
"opus".to_string(),
|
||||||
|
"wav".to_string(),
|
||||||
|
"wv".to_string(),
|
||||||
|
"aiff".to_string(),
|
||||||
|
],
|
||||||
|
supported_formats: vec![
|
||||||
|
FileFormat::MP3,
|
||||||
|
FileFormat::FLAC,
|
||||||
|
FileFormat::OggVorbis,
|
||||||
|
FileFormat::OggOpus,
|
||||||
|
FileFormat::OggFLAC,
|
||||||
|
FileFormat::OggSpeex,
|
||||||
|
FileFormat::OggTheora,
|
||||||
|
FileFormat::Wav,
|
||||||
|
FileFormat::WavPack,
|
||||||
|
FileFormat::AIFF,
|
||||||
|
],
|
||||||
|
new: |path, file_format| -> NewHandlerFuncReturn {
|
||||||
|
let handler = taglib::new_handler(path, file_format)?;
|
||||||
|
|
||||||
|
Ok(Box::from(handler))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "ffprobe_extractor")]
|
||||||
|
handlers.push(Handler {
|
||||||
|
supported_extensions: vec![
|
||||||
|
"mp3".to_string(),
|
||||||
|
"flac".to_string(),
|
||||||
|
"ogg".to_string(),
|
||||||
|
"opus".to_string(),
|
||||||
|
"wav".to_string(),
|
||||||
|
"wv".to_string(),
|
||||||
|
"aiff".to_string(),
|
||||||
|
],
|
||||||
|
supported_formats: vec![
|
||||||
|
FileFormat::MP3,
|
||||||
|
FileFormat::FLAC,
|
||||||
|
FileFormat::OggVorbis,
|
||||||
|
FileFormat::OggOpus,
|
||||||
|
FileFormat::OggFLAC,
|
||||||
|
FileFormat::OggSpeex,
|
||||||
|
FileFormat::OggTheora,
|
||||||
|
FileFormat::Wav,
|
||||||
|
FileFormat::WavPack,
|
||||||
|
FileFormat::AIFF,
|
||||||
|
],
|
||||||
|
new: |path, file_format| -> NewHandlerFuncReturn {
|
||||||
|
let handler = ffprobe::new_handler(path, file_format)?;
|
||||||
|
|
||||||
|
Ok(Box::from(handler))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
handlers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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}
|
utils::formats::{FormatHandler, AudioFormatError, BoxedError}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ pub struct TaglibAudioFormat {
|
||||||
file_format: Option<FileFormat>,
|
file_format: Option<FileFormat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioContainerFormat for TaglibAudioFormat {
|
impl FormatHandler for TaglibAudioFormat {
|
||||||
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError> {
|
||||||
let tags = self.file.tag()?;
|
let tags = self.file.tag()?;
|
||||||
|
|
||||||
|
@ -75,10 +75,10 @@ impl AudioContainerFormat for TaglibAudioFormat {
|
||||||
FileFormat::OggVorbis
|
FileFormat::OggVorbis
|
||||||
| FileFormat::OggOpus
|
| FileFormat::OggOpus
|
||||||
| FileFormat::OggFLAC
|
| FileFormat::OggFLAC
|
||||||
| FileFormat::OggSpeex // Both "support" ReplayGain but not implemented yet
|
| FileFormat::OggSpeex
|
||||||
|
// Both "support" ReplayGain but not implemented yet
|
||||||
// FileFormat::Wav |
|
// FileFormat::Wav |
|
||||||
// FileFormat::WavPack
|
// FileFormat::WavPack
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ impl AudioContainerFormat for TaglibAudioFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_taglib_format_handler(
|
pub fn new_handler(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
file_format: Option<FileFormat>,
|
file_format: Option<FileFormat>,
|
||||||
) -> Result<TaglibAudioFormat, BoxedError> {
|
) -> Result<TaglibAudioFormat, BoxedError> {
|
||||||
|
@ -154,7 +154,6 @@ pub fn new_taglib_format_handler(
|
||||||
FileFormat::OggOpus => Some(TagLibFileType::OggOpus),
|
FileFormat::OggOpus => Some(TagLibFileType::OggOpus),
|
||||||
FileFormat::OggFLAC => Some(TagLibFileType::OggFLAC),
|
FileFormat::OggFLAC => Some(TagLibFileType::OggFLAC),
|
||||||
FileFormat::OggSpeex => Some(TagLibFileType::OggSpeex),
|
FileFormat::OggSpeex => Some(TagLibFileType::OggSpeex),
|
||||||
FileFormat::OggTheora => panic!("Ogg Theora is not supported by taglib"),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,20 +7,12 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::types::{AudioFileInfo, File, ReplayGainRawData, Tags};
|
use crate::types::{AudioFileInfo, File, ReplayGainRawData, Tags};
|
||||||
|
|
||||||
#[cfg(feature = "flac_extractor")]
|
|
||||||
use self::handlers::flac::new_flac_format_handler;
|
|
||||||
#[cfg(feature = "taglib_extractor")]
|
|
||||||
use self::handlers::generic_taglib::new_taglib_format_handler;
|
|
||||||
#[cfg(feature = "mp3_extractor")]
|
|
||||||
use self::handlers::id3::new_id3_format_handler;
|
|
||||||
#[cfg(feature = "ffmpeg_extractor")]
|
|
||||||
use self::handlers::generic_ffmpeg::new_generic_ffmpeg_format_handler;
|
|
||||||
|
|
||||||
use super::format_detection::{detect_format, FileFormat};
|
use super::format_detection::detect_format;
|
||||||
|
|
||||||
type BoxedError = Box<dyn Error>;
|
type BoxedError = Box<dyn Error>;
|
||||||
|
|
||||||
pub trait AudioContainerFormat {
|
pub trait FormatHandler {
|
||||||
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError>;
|
fn get_tags(&self, allow_missing: bool) -> Result<Tags, BoxedError>;
|
||||||
fn contains_replaygain_tags(&self) -> bool;
|
fn contains_replaygain_tags(&self) -> bool;
|
||||||
fn supports_replaygain(&self) -> bool;
|
fn supports_replaygain(&self) -> bool;
|
||||||
|
@ -45,82 +37,29 @@ pub enum AudioFormatError {
|
||||||
MissingArtist,
|
MissingArtist,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_format_handler(file: &File) -> Result<Box<dyn AudioContainerFormat>, BoxedError> {
|
pub fn get_format_handler(file: &File) -> Result<Box<dyn FormatHandler>, BoxedError> {
|
||||||
let format = detect_format(&file.join_path_to())?;
|
let format = detect_format(&file.join_path_to())?;
|
||||||
let path = file.join_path_to();
|
let path = file.join_path_to();
|
||||||
|
|
||||||
#[cfg(feature = "taglib_extractor")]
|
for handler in handlers::HANDLERS.iter() {
|
||||||
{
|
if !handler.supported_extensions.contains(&file.extension) {
|
||||||
match format {
|
continue
|
||||||
FileFormat::OggFLAC
|
|
||||||
| FileFormat::OggSpeex
|
|
||||||
| FileFormat::OggVorbis
|
|
||||||
| FileFormat::OggOpus
|
|
||||||
| FileFormat::Wav
|
|
||||||
| FileFormat::WavPack
|
|
||||||
| FileFormat::AIFF => {
|
|
||||||
return Ok(Box::new(new_taglib_format_handler(&path, Some(format))?));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "mp3_extractor")]
|
if !handler.supported_formats.contains(&format) {
|
||||||
if format == FileFormat::MP3 {
|
continue
|
||||||
// Native MP3 support
|
|
||||||
return Ok(Box::new(new_id3_format_handler(&path)?));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "flac_extractor")]
|
|
||||||
if format == FileFormat::FLAC {
|
|
||||||
// Native FLAC support
|
|
||||||
return Ok(Box::new(new_flac_format_handler(&path)?));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg_extractor")]
|
|
||||||
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)]
|
|
||||||
_ => {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new = handler.new;
|
||||||
|
|
||||||
|
return new(&path, Some(format));
|
||||||
|
}
|
||||||
|
|
||||||
panic!("no supported handler found");
|
panic!("no supported handler found");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_supported_extension(ext: &str) -> bool {
|
fn is_supported_extension(ext: &str) -> bool {
|
||||||
#[cfg(feature = "taglib_extractor")]
|
handlers::SUPPORTED_EXTENSIONS.contains(&ext.to_string())
|
||||||
if matches!(ext, "ogg" | "opus" | "wav" | "wv" | "aiff") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "mp3_extractor")]
|
|
||||||
if ext == "mp3" {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "flac_extractor")]
|
|
||||||
if ext == "flac" {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FFMpeg Fallback
|
|
||||||
#[cfg(feature = "ffmpeg_extractor")]
|
|
||||||
if matches!(ext, "mp3" | "flac" | "ogg" | "opus" | "wav" | "wv" | "aiff") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_supported_file(file_path: &Path) -> bool {
|
pub fn is_supported_file(file_path: &Path) -> bool {
|
||||||
|
@ -143,47 +82,5 @@ pub fn is_supported_file(file_path: &Path) -> bool {
|
||||||
|
|
||||||
let format = format.unwrap();
|
let format = format.unwrap();
|
||||||
|
|
||||||
#[cfg(feature = "taglib_extractor")]
|
handlers::SUPPORTED_FORMATS.contains(&format)
|
||||||
match format {
|
|
||||||
FileFormat::OggVorbis
|
|
||||||
| FileFormat::OggOpus
|
|
||||||
| FileFormat::OggFLAC
|
|
||||||
| FileFormat::OggSpeex
|
|
||||||
| FileFormat::Wav
|
|
||||||
| FileFormat::WavPack
|
|
||||||
| FileFormat::AIFF => {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "mp3_extractor")]
|
|
||||||
if format == FileFormat::MP3 {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "flac_extractor")]
|
|
||||||
if format == FileFormat::FLAC {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg_extractor")]
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue