move relative file handing code into its own module, seperate from new AudioFile
This commit is contained in:
parent
abe16ae53b
commit
4603fc33e3
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -683,6 +683,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"metaflac",
|
||||
"notify",
|
||||
"relative_file",
|
||||
"replaygain",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -877,6 +878,10 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "relative_file"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "replaygain"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -5,13 +5,19 @@ edition = "2021"
|
|||
|
||||
[workspace]
|
||||
members = [
|
||||
"modules/taglib",
|
||||
"modules/ascii_reduce",
|
||||
"modules/ffprobe",
|
||||
"modules/relative_file",
|
||||
"modules/replaygain",
|
||||
"modules/taglib"
|
||||
]
|
||||
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
relative_file = { path = "./modules/relative_file" }
|
||||
|
||||
# for decode/encoding yaml/json for transcode config & ffprobe output
|
||||
serde = { version = "1.0.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
|
|
4
modules/relative_file/Cargo.toml
Normal file
4
modules/relative_file/Cargo.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[package]
|
||||
name = "relative_file"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
141
modules/relative_file/src/lib.rs
Normal file
141
modules/relative_file/src/lib.rs
Normal file
|
@ -0,0 +1,141 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
pub mod traits {
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub trait RelativeFileTrait {
|
||||
fn filename(&self) -> String;
|
||||
fn change_filename(&mut self, filename: String);
|
||||
|
||||
fn extension(&self) -> Option<String>;
|
||||
fn path_to(&self) -> PathBuf;
|
||||
fn path_from_source(&self) -> PathBuf;
|
||||
|
||||
fn join_filename(&self) -> String;
|
||||
fn join_path_to(&self) -> PathBuf;
|
||||
fn join_path_from_source(&self) -> PathBuf;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RelativeFile {
|
||||
filename: String,
|
||||
extension: Option<String>,
|
||||
|
||||
// relative path to file's folder
|
||||
path_to: PathBuf,
|
||||
// path to folder from source
|
||||
path_from_source: PathBuf,
|
||||
}
|
||||
|
||||
impl RelativeFile {
|
||||
pub fn from_path(source_dir: String, full_path: PathBuf) -> crate::RelativeFile {
|
||||
let full_file_path = PathBuf::from(&source_dir).join(full_path);
|
||||
|
||||
let filename_without_extension = full_file_path
|
||||
.file_stem()
|
||||
.expect("filename is invalid")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
let extension = full_file_path.extension();
|
||||
|
||||
let extension = if let Some(extension) = extension {
|
||||
Some(extension.to_string_lossy().to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let path_from_src = full_file_path
|
||||
.strip_prefix(&source_dir)
|
||||
.expect("couldn't get path relative to source");
|
||||
|
||||
let mut folder_path_from_src = path_from_src.to_path_buf();
|
||||
folder_path_from_src.pop();
|
||||
|
||||
let path_to = PathBuf::from(&source_dir).join(&folder_path_from_src);
|
||||
|
||||
RelativeFile {
|
||||
filename: filename_without_extension,
|
||||
extension,
|
||||
path_from_source: folder_path_from_src,
|
||||
path_to,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl traits::RelativeFileTrait for RelativeFile {
|
||||
fn join_filename(&self) -> String {
|
||||
return match &self.extension {
|
||||
Some(extension) => format!("{}.{}", self.filename, extension),
|
||||
None => self.filename.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
fn join_path_to(&self) -> PathBuf {
|
||||
PathBuf::from(&self.path_to).join(self.join_filename())
|
||||
}
|
||||
fn join_path_from_source(&self) -> PathBuf {
|
||||
PathBuf::from(&self.path_from_source).join(self.join_filename())
|
||||
}
|
||||
|
||||
fn path_to(&self) -> PathBuf {
|
||||
self.path_to.clone()
|
||||
}
|
||||
|
||||
fn path_from_source(&self) -> PathBuf {
|
||||
self.path_from_source.clone()
|
||||
}
|
||||
|
||||
fn filename(&self) -> String {
|
||||
self.filename.clone()
|
||||
}
|
||||
|
||||
fn extension(&self) -> Option<String> {
|
||||
self.extension.clone()
|
||||
}
|
||||
|
||||
fn change_filename(&mut self, filename: String) {
|
||||
self.filename = filename
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::traits::RelativeFileTrait;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
fn filename() {
|
||||
let file =
|
||||
crate::RelativeFile::from_path("source/".to_string(), PathBuf::from("path/file.txt"));
|
||||
assert_eq!(file.join_filename(), "file.txt")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn change_filename() {
|
||||
let mut file =
|
||||
crate::RelativeFile::from_path("source/".to_string(), PathBuf::from("path/file.txt"));
|
||||
file.change_filename("new_file".to_string());
|
||||
assert_eq!(file.join_filename(), "new_file.txt")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_extension() {
|
||||
let file =
|
||||
crate::RelativeFile::from_path("source/".to_string(), PathBuf::from("path/file"));
|
||||
assert_eq!(file.join_filename(), "file");
|
||||
assert_eq!(file.extension(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paths() {
|
||||
let file = crate::RelativeFile::from_path(
|
||||
"source/".to_string(),
|
||||
PathBuf::from("path/to/file.txt"),
|
||||
);
|
||||
assert_eq!(file.path_to(), PathBuf::from("source/path/to"));
|
||||
assert_eq!(file.path_from_source(), PathBuf::from("path/to"));
|
||||
assert_eq!(file.extension(), Some("txt".to_string()));
|
||||
}
|
||||
}
|
|
@ -8,9 +8,11 @@ use std::{
|
|||
thread::scope,
|
||||
};
|
||||
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
|
||||
use crate::{
|
||||
args::CLIArgs,
|
||||
types::File,
|
||||
types::AudioFile,
|
||||
utils::{
|
||||
formats::get_format_handler,
|
||||
scan_for_music,
|
||||
|
@ -90,7 +92,7 @@ pub fn copy_command(
|
|||
|
||||
let mut directories: Vec<String> = Vec::new();
|
||||
for file in files.iter() {
|
||||
let file_directory = file.path_from_source.to_string_lossy().to_string();
|
||||
let file_directory = file.path_from_source().to_string_lossy().to_string();
|
||||
|
||||
if !directories.contains(&file_directory) {
|
||||
directories.push(file_directory.clone());
|
||||
|
@ -121,14 +123,14 @@ pub fn copy_command(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_file(file: &File, copy_args: &CopyCommandArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn copy_file(file: &relative_file::RelativeFile, copy_args: &CopyCommandArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let from_path = file.join_path_to();
|
||||
|
||||
let to_path_dest = PathBuf::from_str(copy_args.dest.as_str()).expect("invalid destination");
|
||||
let to_path = match copy_args.single_directory {
|
||||
true => to_path_dest.join(file.join_filename()),
|
||||
false => to_path_dest
|
||||
.join(file.path_from_source.clone())
|
||||
.join(file.path_from_source())
|
||||
.join(file.join_filename()),
|
||||
};
|
||||
|
||||
|
@ -147,11 +149,11 @@ fn copy_file(file: &File, copy_args: &CopyCommandArgs) -> Result<(), Box<dyn std
|
|||
}
|
||||
|
||||
fn copy_files(
|
||||
files: &[File],
|
||||
files: &[AudioFile],
|
||||
copy_args: &CopyCommandArgs,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
for file in files.iter() {
|
||||
copy_file(file, copy_args)?;
|
||||
copy_file(file.as_relative_file(), copy_args)?;
|
||||
|
||||
if !file.extra_files.is_empty() {
|
||||
for extra_file in file.extra_files.iter() {
|
||||
|
@ -164,13 +166,13 @@ fn copy_files(
|
|||
}
|
||||
|
||||
fn transcode_file(
|
||||
file: &File,
|
||||
file: &AudioFile,
|
||||
copy_args: &CopyCommandArgs,
|
||||
config: &TranscodeConfig,
|
||||
is_threaded: bool,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let new_filename_full: String = match config.file_extension.clone() {
|
||||
Some(ext) => format!("{}.{}", file.filename, ext),
|
||||
Some(ext) => format!("{}.{}", file.filename(), ext),
|
||||
None => {
|
||||
panic!("file_extension is required in custom transcode configs");
|
||||
}
|
||||
|
@ -180,7 +182,7 @@ fn transcode_file(
|
|||
let to_path = match copy_args.single_directory {
|
||||
true => to_path_dest.join(new_filename_full),
|
||||
false => to_path_dest
|
||||
.join(file.path_from_source.clone())
|
||||
.join(file.path_from_source())
|
||||
.join(new_filename_full),
|
||||
};
|
||||
|
||||
|
@ -213,7 +215,7 @@ fn transcode_file(
|
|||
}
|
||||
|
||||
fn transcode_files(
|
||||
files: &[File],
|
||||
files: &[AudioFile],
|
||||
copy_args: &CopyCommandArgs,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let transcode_config = transcode_preset_or_config(
|
||||
|
@ -227,7 +229,7 @@ fn transcode_files(
|
|||
if threads > 1 {
|
||||
let files_copy = files.to_vec();
|
||||
|
||||
let jobs: Arc<Mutex<Vec<File>>> = Arc::new(Mutex::new(files_copy));
|
||||
let jobs: Arc<Mutex<Vec<AudioFile>>> = Arc::new(Mutex::new(files_copy));
|
||||
|
||||
let copy_args = Arc::new(copy_args);
|
||||
let transcode_config = Arc::new(transcode_config);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::args::CLIArgs;
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use crate::utils::formats::get_format_handler;
|
||||
use crate::utils::scan_for_music;
|
||||
use std::cmp::Ordering;
|
||||
|
@ -7,6 +7,7 @@ use std::ffi::OsStr;
|
|||
use std::io::Write;
|
||||
|
||||
use html_escape::encode_text;
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
use urlencoding::encode as url_encode;
|
||||
|
||||
#[derive(Debug, Clone, clap::Args)]
|
||||
|
@ -21,7 +22,7 @@ pub struct GenHTMLCommandArgs {
|
|||
pub link_base: Option<String>,
|
||||
}
|
||||
|
||||
fn table_for_files(files: Vec<File>, includes_path: bool, link_base: &Option<String>) -> String {
|
||||
fn table_for_files(files: Vec<AudioFile>, includes_path: bool, link_base: &Option<String>) -> String {
|
||||
let mut html_content = String::new();
|
||||
|
||||
let mut path_head = String::new();
|
||||
|
@ -74,7 +75,7 @@ fn table_for_files(files: Vec<File>, includes_path: bool, link_base: &Option<Str
|
|||
|
||||
let mut path_data = String::new();
|
||||
if includes_path {
|
||||
let file_directory = file.path_from_source.to_string_lossy().to_string();
|
||||
let file_directory = file.path_from_source().to_string_lossy().to_string();
|
||||
|
||||
path_data.push_str(format!("<td>{}</td>", encode_text(&file_directory)).as_str());
|
||||
}
|
||||
|
@ -154,8 +155,8 @@ pub fn genhtml_command(
|
|||
}
|
||||
|
||||
files.sort_by(|a, b| -> Ordering {
|
||||
if a.path_from_source != b.path_from_source {
|
||||
return a.path_from_source.cmp(&b.path_from_source);
|
||||
if a.path_from_source() != b.path_from_source() {
|
||||
return a.path_from_source().cmp(&b.path_from_source());
|
||||
}
|
||||
|
||||
let a_tags = &a.info.tags;
|
||||
|
|
|
@ -4,11 +4,13 @@ use std::thread::scope;
|
|||
|
||||
use crate::args::CLIArgs;
|
||||
use crate::types::AudioFileInfo;
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use crate::utils::formats::get_format_handler;
|
||||
use crate::utils::scan_for_music;
|
||||
|
||||
use ascii_reduce::reduce;
|
||||
use relative_file::RelativeFile;
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
#[cfg(feature = "replaygain")]
|
||||
use replaygain::analyze_replaygain_track;
|
||||
|
||||
|
@ -30,7 +32,7 @@ pub struct ProcessCommandArgs {
|
|||
pub analyze_threads: Option<u32>,
|
||||
}
|
||||
|
||||
fn rename_file(process_args: &ProcessCommandArgs, file: &mut File) {
|
||||
fn rename_file(process_args: &ProcessCommandArgs, file: &mut AudioFile) {
|
||||
let title = &file.info.tags.title;
|
||||
let artist = &file.info.tags.artist;
|
||||
|
||||
|
@ -65,20 +67,20 @@ fn rename_file(process_args: &ProcessCommandArgs, file: &mut File) {
|
|||
}
|
||||
};
|
||||
|
||||
if filename == file.filename {
|
||||
if filename == file.filename() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 5: Make new File with filename set
|
||||
let mut new_file = file.clone();
|
||||
new_file.filename = filename.clone();
|
||||
new_file.change_filename(filename.clone());
|
||||
|
||||
let extension = &file.extension;
|
||||
let extension = &file.extension().unwrap();
|
||||
|
||||
// Step 6: Rename File
|
||||
println!(
|
||||
"Renaming File from {}.{extension} to {}.{extension}",
|
||||
file.filename, filename
|
||||
file.filename(), filename
|
||||
);
|
||||
if !process_args.dry_run {
|
||||
if std::path::Path::new(&new_file.join_path_to()).exists() {
|
||||
|
@ -96,17 +98,18 @@ fn rename_file(process_args: &ProcessCommandArgs, file: &mut File) {
|
|||
}
|
||||
|
||||
if !file.extra_files.is_empty() {
|
||||
let mut new_extra_files: Vec<File> = Vec::new();
|
||||
let mut new_extra_files: Vec<RelativeFile> = Vec::new();
|
||||
|
||||
for extra_file in file.extra_files.iter() {
|
||||
let mut new_extra_file = extra_file.clone();
|
||||
new_extra_file.filename = filename.clone();
|
||||
|
||||
let extra_extension = &extra_file.extension;
|
||||
new_extra_file.change_filename(filename.clone());
|
||||
|
||||
let extra_extension = &extra_file.extension().unwrap();
|
||||
|
||||
println!(
|
||||
"Renaming Extra File from {}.{extra_extension} to {}.{extra_extension}",
|
||||
file.filename, filename
|
||||
file.filename(), filename
|
||||
);
|
||||
|
||||
if !process_args.dry_run {
|
||||
|
@ -125,12 +128,12 @@ fn rename_file(process_args: &ProcessCommandArgs, file: &mut File) {
|
|||
}
|
||||
|
||||
if !process_args.dry_run {
|
||||
file.filename = filename;
|
||||
file.change_filename(filename);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "replaygain")]
|
||||
pub fn add_replaygain_tags(file: &File, force: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
pub fn add_replaygain_tags(file: &AudioFile, force: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if !file.info.supports_replaygain {
|
||||
println!(
|
||||
"Skipping replaygain for {:?}, not supported",
|
||||
|
@ -169,7 +172,7 @@ pub fn add_replaygain_tags(file: &File, force: bool) -> Result<(), Box<dyn std::
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn analyze_file(file: &File) -> Result<AudioFileInfo, Box<dyn std::error::Error>> {
|
||||
fn analyze_file(file: &AudioFile) -> Result<AudioFileInfo, Box<dyn std::error::Error>> {
|
||||
println!("Analysing: {:?}", file.join_path_from_source());
|
||||
let mut handler = get_format_handler(file)?;
|
||||
|
||||
|
@ -192,8 +195,8 @@ pub fn process_command(
|
|||
file.info = info;
|
||||
}
|
||||
} else {
|
||||
let jobs: Arc<Mutex<Vec<File>>> = Arc::new(Mutex::new(files.clone()));
|
||||
let new_files: Arc<Mutex<Vec<File>>> = Arc::new(Mutex::new(Vec::new()));
|
||||
let jobs: Arc<Mutex<Vec<AudioFile>>> = Arc::new(Mutex::new(files.clone()));
|
||||
let new_files: Arc<Mutex<Vec<AudioFile>>> = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
scope(|s| {
|
||||
for _ in 0..threads {
|
||||
|
@ -243,7 +246,7 @@ pub fn process_command(
|
|||
|
||||
return Ok(());
|
||||
} else {
|
||||
let jobs: Arc<Mutex<Vec<File>>> = Arc::new(Mutex::new(files));
|
||||
let jobs: Arc<Mutex<Vec<AudioFile>>> = Arc::new(Mutex::new(files));
|
||||
|
||||
scope(|s| {
|
||||
for _ in 0..threads {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::args::CLIArgs;
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use crate::utils::formats::get_format_handler;
|
||||
|
||||
#[derive(Debug, Clone, clap::Args)]
|
||||
|
@ -33,10 +34,10 @@ pub fn get_tags_command(
|
|||
_args: CLIArgs,
|
||||
get_tags_args: &GetTagsCommandArgs,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut files: Vec<File> = Vec::new();
|
||||
let mut files: Vec<AudioFile> = Vec::new();
|
||||
|
||||
for file in get_tags_args.files.iter() {
|
||||
files.push(File::from_path("".to_string(), PathBuf::from(file)));
|
||||
files.push(AudioFile::from_path("".to_string(), PathBuf::from(file)));
|
||||
}
|
||||
|
||||
for file in files.iter_mut() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::args::CLIArgs;
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use crate::utils::formats::get_format_handler;
|
||||
|
||||
#[derive(Debug, Clone, clap::Args)]
|
||||
|
@ -17,10 +17,10 @@ pub fn set_tags_command(
|
|||
_args: CLIArgs,
|
||||
add_tags_args: &SetTagsCommandArgs,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut files: Vec<File> = Vec::new();
|
||||
let mut files: Vec<AudioFile> = Vec::new();
|
||||
|
||||
for file in add_tags_args.files.iter() {
|
||||
files.push(File::from_path("".to_string(), PathBuf::from(file)));
|
||||
files.push(AudioFile::from_path("".to_string(), PathBuf::from(file)));
|
||||
}
|
||||
|
||||
for file in files.iter() {
|
||||
|
|
|
@ -4,8 +4,10 @@ use std::sync::mpsc;
|
|||
use std::thread;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
|
||||
use crate::args::CLIArgs;
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use crate::utils::transcoder::presets::print_presets;
|
||||
use crate::utils::transcoder::presets::transcode_preset_or_config;
|
||||
use crate::utils::transcoder::transcode;
|
||||
|
@ -43,12 +45,12 @@ pub fn transcode_command(
|
|||
|
||||
println!("Transcoding");
|
||||
|
||||
let input_file = File::from_path("".to_string(), PathBuf::from(&transcode_args.source));
|
||||
let output_file = File::from_path("".to_string(), PathBuf::from(&transcode_args.dest));
|
||||
let input_file = AudioFile::from_path("".to_string(), PathBuf::from(&transcode_args.source));
|
||||
let output_file = AudioFile::from_path("".to_string(), PathBuf::from(&transcode_args.dest));
|
||||
|
||||
if !transcode_args.ignore_extension {
|
||||
if let Some(ref file_extension) = transcode_config.file_extension {
|
||||
if file_extension != &output_file.extension {
|
||||
if Some(file_extension) != output_file.extension().as_ref() {
|
||||
panic!(
|
||||
concat!(
|
||||
"{} is not the recommended ",
|
||||
|
@ -56,7 +58,7 @@ pub fn transcode_command(
|
|||
"please change it to {} ",
|
||||
"or run with --ignore-extension"
|
||||
),
|
||||
output_file.extension, file_extension
|
||||
output_file.extension().unwrap(), file_extension
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
89
src/types.rs
89
src/types.rs
|
@ -1,5 +1,6 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use relative_file::RelativeFile;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::utils::format_detection::FileFormat;
|
||||
|
@ -32,68 +33,64 @@ pub struct AudioFileInfo {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct File {
|
||||
pub filename: String,
|
||||
pub extension: String,
|
||||
pub struct AudioFile {
|
||||
file_base: RelativeFile,
|
||||
|
||||
// relative path to file's folder
|
||||
pub path_to: PathBuf,
|
||||
// path to folder from source
|
||||
pub path_from_source: PathBuf,
|
||||
|
||||
pub extra_files: Vec<File>,
|
||||
pub extra_files: Vec<RelativeFile>,
|
||||
|
||||
pub info: AudioFileInfo,
|
||||
|
||||
pub folder_meta: FolderMeta,
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn from_path(source_dir: String, full_path: PathBuf) -> File {
|
||||
let full_file_path = PathBuf::from(&source_dir).join(full_path);
|
||||
impl AudioFile {
|
||||
pub fn from_path(source_dir: String, full_path: PathBuf) -> AudioFile {
|
||||
let file_base = RelativeFile::from_path(source_dir, full_path);
|
||||
|
||||
let filename_without_extension = full_file_path
|
||||
.file_stem()
|
||||
.expect("filename invalid")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
let extension = full_file_path.extension();
|
||||
|
||||
let extension = if let Some(extension) = extension {
|
||||
extension.to_string_lossy().to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let path_from_src = full_file_path
|
||||
.strip_prefix(&source_dir)
|
||||
.expect("couldn't get path relative to source");
|
||||
|
||||
let mut folder_path_from_src = path_from_src.to_path_buf();
|
||||
folder_path_from_src.pop();
|
||||
|
||||
let path_to = PathBuf::from(&source_dir).join(&folder_path_from_src);
|
||||
|
||||
File {
|
||||
filename: filename_without_extension,
|
||||
extension,
|
||||
path_from_source: folder_path_from_src,
|
||||
path_to,
|
||||
AudioFile {
|
||||
file_base,
|
||||
extra_files: Vec::new(),
|
||||
info: AudioFileInfo::default(),
|
||||
folder_meta: FolderMeta::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join_filename(&self) -> String {
|
||||
format!("{}.{}", self.filename, self.extension)
|
||||
pub fn as_relative_file(&self) -> &RelativeFile {
|
||||
&self.file_base
|
||||
}
|
||||
pub fn join_path_to(&self) -> PathBuf {
|
||||
PathBuf::from(&self.path_to).join(self.join_filename())
|
||||
}
|
||||
|
||||
impl relative_file::traits::RelativeFileTrait for AudioFile {
|
||||
fn filename(&self) -> String {
|
||||
self.file_base.filename()
|
||||
}
|
||||
pub fn join_path_from_source(&self) -> PathBuf {
|
||||
PathBuf::from(&self.path_from_source).join(self.join_filename())
|
||||
|
||||
fn extension(&self) -> Option<String> {
|
||||
self.file_base.extension()
|
||||
}
|
||||
|
||||
fn path_to(&self) -> PathBuf {
|
||||
self.file_base.path_to()
|
||||
}
|
||||
|
||||
fn path_from_source(&self) -> PathBuf {
|
||||
self.file_base.path_from_source()
|
||||
}
|
||||
|
||||
fn join_filename(&self) -> String {
|
||||
self.file_base.join_filename()
|
||||
}
|
||||
|
||||
fn join_path_to(&self) -> PathBuf {
|
||||
self.file_base.join_path_to()
|
||||
}
|
||||
|
||||
fn join_path_from_source(&self) -> PathBuf {
|
||||
self.file_base.join_path_from_source()
|
||||
}
|
||||
|
||||
fn change_filename(&mut self, filename: String) {
|
||||
self.file_base.change_filename(filename)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@ mod handlers;
|
|||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::format_detection::detect_format;
|
||||
use crate::types::{AudioFileInfo, File, Tags};
|
||||
use crate::types::{AudioFileInfo, AudioFile, Tags};
|
||||
|
||||
#[cfg(feature = "replaygain")]
|
||||
use replaygain::ReplayGainRawData;
|
||||
|
@ -41,12 +42,12 @@ pub enum AudioFormatError {
|
|||
MissingArtist,
|
||||
}
|
||||
|
||||
pub fn get_format_handler(file: &File) -> Result<Box<dyn FormatHandler>, BoxedError> {
|
||||
pub fn get_format_handler(file: &AudioFile) -> Result<Box<dyn FormatHandler>, BoxedError> {
|
||||
let format = detect_format(&file.join_path_to())?;
|
||||
let path = file.join_path_to();
|
||||
|
||||
for handler in handlers::HANDLERS.iter() {
|
||||
if !handler.supported_extensions.contains(&file.extension) {
|
||||
if !handler.supported_extensions.contains(&file.extension().unwrap()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
use std::{fs, path::PathBuf};
|
||||
|
||||
use crate::types::{File, FolderMeta};
|
||||
use crate::types::{AudioFile, FolderMeta};
|
||||
use relative_file::{traits::RelativeFileTrait, RelativeFile};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use super::is_supported_file;
|
||||
|
||||
pub fn find_extra_files(
|
||||
src_dir: String,
|
||||
file: &File,
|
||||
) -> Result<Vec<File>, Box<dyn std::error::Error>> {
|
||||
let mut extra_files: Vec<File> = Vec::new();
|
||||
file: &AudioFile,
|
||||
) -> Result<Vec<RelativeFile>, Box<dyn std::error::Error>> {
|
||||
let mut extra_files: Vec<RelativeFile> = Vec::new();
|
||||
|
||||
for entry in fs::read_dir(&file.path_to)? {
|
||||
for entry in fs::read_dir(&file.path_to())? {
|
||||
let entry = entry?;
|
||||
if !entry.metadata()?.is_file() {
|
||||
continue;
|
||||
|
@ -23,18 +24,18 @@ pub fn find_extra_files(
|
|||
continue;
|
||||
}
|
||||
|
||||
if entry_path.file_stem().unwrap().to_string_lossy() == file.filename
|
||||
&& extension.unwrap().to_string_lossy() != file.extension
|
||||
if entry_path.file_stem().unwrap().to_string_lossy() == file.filename()
|
||||
&& extension.map(|x| x.to_string_lossy().to_string()) != file.extension()
|
||||
{
|
||||
extra_files.push(File::from_path(src_dir.clone(), entry_path.clone()));
|
||||
extra_files.push(RelativeFile::from_path(src_dir.clone(), entry_path.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(extra_files)
|
||||
}
|
||||
|
||||
pub fn scan_for_music(src_dir: &String) -> Result<Vec<File>, Box<dyn std::error::Error>> {
|
||||
let mut files: Vec<File> = Vec::new();
|
||||
pub fn scan_for_music(src_dir: &String) -> Result<Vec<AudioFile>, Box<dyn std::error::Error>> {
|
||||
let mut files: Vec<AudioFile> = Vec::new();
|
||||
|
||||
for entry in WalkDir::new(src_dir) {
|
||||
let entry = entry.unwrap();
|
||||
|
@ -45,7 +46,7 @@ pub fn scan_for_music(src_dir: &String) -> Result<Vec<File>, Box<dyn std::error:
|
|||
}
|
||||
|
||||
if is_supported_file(&entry_path) {
|
||||
let mut file = File::from_path(src_dir.clone(), entry_path.clone());
|
||||
let mut file = AudioFile::from_path(src_dir.clone(), entry_path.clone());
|
||||
|
||||
let mut folder_meta_path = PathBuf::from(entry_path.parent().unwrap().clone());
|
||||
folder_meta_path.push("folder.meta");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod presets;
|
||||
pub mod types;
|
||||
mod progress_monitor;
|
||||
#[allow(clippy::module_inception)]
|
||||
mod transcoder;
|
||||
|
||||
pub use self::progress_monitor::progress_monitor;
|
||||
|
|
|
@ -83,7 +83,7 @@ pub fn transcode_preset_or_config(
|
|||
} else if let Some(config_path) = config_path {
|
||||
return match TranscodeConfig::load(config_path.to_string()) {
|
||||
Ok(config) => Ok(config),
|
||||
Err(e) => Err(PresetError::LoadError(Box::from(e))),
|
||||
Err(e) => Err(PresetError::LoadError(e)),
|
||||
};
|
||||
} else {
|
||||
Err(PresetError::NoneSpecified)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use std::{fs, process::Command, sync::mpsc::Sender, thread::JoinHandle};
|
||||
|
||||
use crate::types::File;
|
||||
use crate::types::AudioFile;
|
||||
use relative_file::traits::RelativeFileTrait;
|
||||
use string_error::static_err;
|
||||
|
||||
use super::{progress_monitor, types::TranscodeConfig};
|
||||
|
||||
pub fn transcode(
|
||||
file: File,
|
||||
file: AudioFile,
|
||||
dest: String,
|
||||
config: &TranscodeConfig,
|
||||
progress_sender: Option<Sender<String>>,
|
||||
|
|
|
@ -39,13 +39,13 @@ impl TranscodeConfig {
|
|||
Some("json") => {
|
||||
let conf: TranscodeConfig =
|
||||
serde_json::from_reader(reader).expect("error while reading json");
|
||||
return Ok(conf);
|
||||
Ok(conf)
|
||||
}
|
||||
Some("yml") | Some("yaml") | Some(&_) | None => {
|
||||
let conf: TranscodeConfig =
|
||||
serde_json::from_reader(reader).expect("error while reading json");
|
||||
return Ok(conf);
|
||||
Ok(conf)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue