move ffprobe stuff to its own module
This commit is contained in:
parent
84e79f6cc6
commit
bb4f776538
|
@ -40,7 +40,6 @@ taglib = { path = "./modules/taglib", optional = true }
|
|||
html-escape = "0.2"
|
||||
urlencoding = "2"
|
||||
|
||||
|
||||
# error handling
|
||||
thiserror = "1"
|
||||
string-error = "0.1"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
version = "latest";
|
||||
|
||||
src = ./.;
|
||||
cargoLock = {lockFile = ./Cargo.lock;};
|
||||
cargoLock.lockFile = ./Cargo.lock;
|
||||
|
||||
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||
|
||||
|
|
35
src/utils/ffprobe/errors.rs
Normal file
35
src/utils/ffprobe/errors.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use std::{fmt, io, process};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AnalyzeError {
|
||||
FFProbeError(FFProbeError),
|
||||
IOError(io::Error),
|
||||
ParseError(serde_json::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for AnalyzeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AnalyzeError::FFProbeError(err) => write!(f, "{}", err),
|
||||
AnalyzeError::IOError(err) => write!(f, "{}", err),
|
||||
AnalyzeError::ParseError(err) => write!(f, "{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FFProbeError {
|
||||
pub exit_status: process::ExitStatus,
|
||||
pub stderr: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for FFProbeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ffprobe exited with error code {}, stderr: {}",
|
||||
self.exit_status.code().unwrap(),
|
||||
self.stderr
|
||||
)
|
||||
}
|
||||
}
|
35
src/utils/ffprobe/ffprobe_output.rs
Normal file
35
src/utils/ffprobe/ffprobe_output.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct FFProbeOutput {
|
||||
pub format: FFProbeOutputFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct FFProbeOutputFormat {
|
||||
pub tags: FFProbeOutputTags,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct FFProbeOutputTags {
|
||||
#[serde(alias = "TITLE")]
|
||||
pub title: String,
|
||||
#[serde(default, alias = "ARTIST")]
|
||||
pub artist: String,
|
||||
|
||||
#[serde(default, alias = "REPLAYGAIN_TRACK_PEAK")]
|
||||
pub replaygain_track_peak: Option<String>,
|
||||
#[serde(default, alias = "REPLAYGAIN_TRACK_GAIN")]
|
||||
pub replaygain_track_gain: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for FFProbeOutputTags {
|
||||
fn default() -> Self {
|
||||
FFProbeOutputTags {
|
||||
title: "".to_string(),
|
||||
artist: "".to_string(),
|
||||
replaygain_track_peak: None,
|
||||
replaygain_track_gain: None,
|
||||
}
|
||||
}
|
||||
}
|
47
src/utils/ffprobe/mod.rs
Normal file
47
src/utils/ffprobe/mod.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
mod ffprobe_output;
|
||||
pub mod errors;
|
||||
pub mod types;
|
||||
|
||||
use std::{
|
||||
convert::Into,
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use self::errors::{AnalyzeError, FFProbeError};
|
||||
|
||||
pub fn analyze(path: &PathBuf) -> Result<types::FFProbeData, AnalyzeError> {
|
||||
let output = Command::new(crate::meta::FFPROBE)
|
||||
.args([
|
||||
"-v",
|
||||
"quiet",
|
||||
"-print_format",
|
||||
"json",
|
||||
"-show_format",
|
||||
path.to_str().unwrap(),
|
||||
])
|
||||
.output();
|
||||
|
||||
if let Err(err) = output {
|
||||
return Err(AnalyzeError::IOError(err));
|
||||
}
|
||||
|
||||
let output = output.unwrap();
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(AnalyzeError::FFProbeError(FFProbeError {
|
||||
exit_status: output.status,
|
||||
stderr: String::from_utf8(output.stderr).unwrap(),
|
||||
}));
|
||||
}
|
||||
|
||||
let output = String::from_utf8(output.stdout).unwrap();
|
||||
let ffprobe_out: serde_json::Result<ffprobe_output::FFProbeOutput> =
|
||||
serde_json::from_str(output.as_str());
|
||||
|
||||
let ffprobe_out = ffprobe_out.unwrap();
|
||||
|
||||
return Ok(types::FFProbeData {
|
||||
tags: ffprobe_out.format.tags.into(),
|
||||
});
|
||||
}
|
27
src/utils/ffprobe/types.rs
Normal file
27
src/utils/ffprobe/types.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use super::ffprobe_output;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct FFProbeTags {
|
||||
pub title: String,
|
||||
pub artist: String,
|
||||
pub replaygain_track_peak: Option<String>,
|
||||
pub replaygain_track_gain: Option<String>,
|
||||
}
|
||||
|
||||
impl Into<FFProbeTags> for ffprobe_output::FFProbeOutputTags {
|
||||
fn into(self) -> FFProbeTags {
|
||||
FFProbeTags {
|
||||
title: self.title,
|
||||
artist: self.artist,
|
||||
replaygain_track_peak: self.replaygain_track_peak,
|
||||
replaygain_track_gain: self.replaygain_track_gain,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct FFProbeData {
|
||||
pub tags: FFProbeTags,
|
||||
}
|
|
@ -3,12 +3,11 @@ use std::{
|
|||
process::Command,
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
use string_error::static_err;
|
||||
use string_error::into_err;
|
||||
|
||||
use crate::{
|
||||
types::{AudioFileInfo, ReplayGainData, ReplayGainRawData, Tags},
|
||||
utils::format_detection::FileFormat,
|
||||
utils::{format_detection::FileFormat, ffprobe},
|
||||
};
|
||||
|
||||
use super::{AudioContainerFormat, AudioFormatError, BoxedError};
|
||||
|
@ -26,40 +25,6 @@ struct ExtractedData {
|
|||
replaygain_data: Option<ReplayGainData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct FFProbeOutput {
|
||||
pub format: FFProbeFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct FFProbeFormat {
|
||||
pub tags: FFProbeTags,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct FFProbeTags {
|
||||
#[serde(alias = "TITLE")]
|
||||
pub title: String,
|
||||
#[serde(default, alias = "ARTIST")]
|
||||
pub artist: String,
|
||||
|
||||
#[serde(default, alias = "REPLAYGAIN_TRACK_PEAK")]
|
||||
pub replaygain_track_peak: Option<String>,
|
||||
#[serde(default, alias = "REPLAYGAIN_TRACK_GAIN")]
|
||||
pub replaygain_track_gain: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for FFProbeTags {
|
||||
fn default() -> Self {
|
||||
FFProbeTags {
|
||||
title: "".to_string(),
|
||||
artist: "".to_string(),
|
||||
replaygain_track_peak: None,
|
||||
replaygain_track_gain: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GenericFFMpegAudioFormat {
|
||||
format_type: FileFormat,
|
||||
path: Box<PathBuf>,
|
||||
|
@ -70,36 +35,23 @@ pub struct GenericFFMpegAudioFormat {
|
|||
|
||||
impl GenericFFMpegAudioFormat {
|
||||
fn analyze(&mut self) -> Result<(), BoxedError> {
|
||||
let output = Command::new(crate::meta::FFPROBE)
|
||||
.args([
|
||||
"-v",
|
||||
"quiet",
|
||||
"-print_format",
|
||||
"json",
|
||||
"-show_format",
|
||||
&self.path.to_string_lossy(),
|
||||
])
|
||||
.output()?;
|
||||
let output = ffprobe::analyze(&self.path);
|
||||
|
||||
if !output.status.success() {
|
||||
print!("{:?}", String::from_utf8(output.stderr).unwrap());
|
||||
return Err(static_err("FFprobe Crashed"));
|
||||
if let Err(err) = output {
|
||||
return Err(into_err(format!("{}", err)));
|
||||
}
|
||||
|
||||
let output_str = String::from_utf8(output.stdout).unwrap();
|
||||
let ffprobe_out: FFProbeOutput = serde_json::from_str(output_str.as_str())?;
|
||||
|
||||
let tags = ffprobe_out.format.tags;
|
||||
let output = output.unwrap();
|
||||
|
||||
self.extracted_data.tags = Tags {
|
||||
title: tags.title,
|
||||
artist: tags.artist,
|
||||
title: output.tags.title,
|
||||
artist: output.tags.artist,
|
||||
};
|
||||
|
||||
if tags.replaygain_track_gain.is_some() && 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 {
|
||||
track_gain: tags.replaygain_track_gain.unwrap(),
|
||||
track_peak: tags.replaygain_track_peak.unwrap(),
|
||||
track_gain: output.tags.replaygain_track_gain.unwrap(),
|
||||
track_peak: output.tags.replaygain_track_peak.unwrap(),
|
||||
});
|
||||
} else {
|
||||
self.extracted_data.replaygain_data = None;
|
||||
|
@ -234,6 +186,7 @@ pub fn new_generic_ffmpeg_format_handler(
|
|||
extracted_data: ExtractedData::default(),
|
||||
changes: Changes::default(),
|
||||
};
|
||||
|
||||
handler.analyze()?;
|
||||
|
||||
Ok(handler)
|
||||
|
|
|
@ -2,6 +2,7 @@ pub mod ascii_reduce;
|
|||
pub mod format_detection;
|
||||
pub mod replaygain;
|
||||
pub mod transcoder;
|
||||
pub mod ffprobe;
|
||||
|
||||
pub mod formats;
|
||||
pub(self) mod music_scanner;
|
||||
|
|
Loading…
Reference in a new issue