Skip to content

feat: Tauri GUI #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-binaries-and-update-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
target: ${{ matrix.target }}

- name: Build project
run: cargo build --release --target ${{ matrix.target }}
run: cargo build --bin ffzap --release --target ${{ matrix.target }}

- name: Prepare archive
run: |
Expand Down
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
[package]
name = "ffzap"
[workspace]
members = [
"cli",
"shared",
"ui"
]
resolver = "2"

[workspace.package]
version = "1.1.2"
edition = "2021"
description = "⚡ A multithreaded CLI for digital media processing using ffmpeg. If ffmpeg can do it, ffzap can do it - as many files in parallel as your system can handle."
Expand All @@ -9,7 +16,7 @@ repository = "https://github.com/CodeF0x/ffzap"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
[workspace.dependencies]
chrono = "0.4.39"
clap = { version = "4.5.20", features = ["derive"] }
dirs = "6.0.0"
Expand Down
12 changes: 12 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "ffzap"
version.workspace = true
edition.workspace = true
description.workspace = true
license-file.workspace = true
keywords.workspace = true
repository.workspace = true

[dependencies]
ffzap-shared = { path = "../shared" }
clap.workspace = true
86 changes: 86 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use clap::Parser;
use ffzap_shared::{CmdArgs, Logger, Processor, Progress};
use std::fs;
use std::io::ErrorKind;
use std::process::exit;
use std::sync::Arc;

fn main() {
let cmd_args = CmdArgs::parse();

if cmd_args.eta {
println!("Warning: ETA is a highly experimental feature and prone to absurd estimations. If your encoding process has long pauses in-between each processed file, you WILL experience incredibly inaccurate estimations!");
println!("This is due to unwanted behaviour in one of ffzap's dependencies and cannot be fixed by ffzap.");
}

let paths = load_paths(&cmd_args);
let progress = Arc::new(Progress::new(paths.len(), cmd_args.eta));
let logger = Arc::new(Logger::new(Arc::clone(&progress)));
let processor = Processor::new(Arc::clone(&logger), Arc::clone(&progress));

processor.process_files(
paths,
cmd_args.thread_count,
cmd_args.ffmpeg_options,
cmd_args.output,
cmd_args.overwrite,
cmd_args.verbose,
cmd_args.delete,
);

let final_output = format!(
"{} out of {} files have been successful. A detailed log has been written to {}",
progress.value(),
progress.len(),
logger.get_log_path()
);
println!("{final_output}");

let failed_paths = processor.get_failed_paths();
logger.append_failed_paths_to_log(&std::sync::Mutex::new(failed_paths.clone()).lock().unwrap());

if cmd_args.verbose && !failed_paths.is_empty() {
println!("\nThe following files were not processed due to the errors above:");
for path in failed_paths.iter() {
println!("{path}");
}
}
}

fn load_paths(cmd_args: &CmdArgs) -> Vec<String> {
if let Some(input_file_path) = &cmd_args.file_list {
match fs::read_to_string(input_file_path) {
Ok(contents) => contents
.trim()
.split('\n')
.map(|s| s.trim().to_string())
.collect(),
Err(err) => {
match err.kind() {
ErrorKind::NotFound => {
eprintln!("No file found at {input_file_path}.");
exit(1);
}
ErrorKind::PermissionDenied => {
eprintln!("Permission denied when reading file {input_file_path}.");
exit(1);
}
ErrorKind::InvalidData => {
eprintln!("The contents of {input_file_path} contain invalid data. Please make sure it is encoded as UTF-8.");
exit(1);
}
ErrorKind::IsADirectory => {
eprintln!("The path {input_file_path} is a directory.");
exit(1);
}
_ => {
eprintln!("An error has occurred reading the file at path {input_file_path}: {:?}.", err);
exit(1);
}
}
}
}
} else {
cmd_args.input.clone().unwrap()
}
}
14 changes: 14 additions & 0 deletions shared/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "ffzap-shared"
version.workspace = true
edition.workspace = true
description.workspace = true
license-file.workspace = true
keywords.workspace = true
repository.workspace = true

[dependencies]
chrono.workspace = true
dirs.workspace = true
indicatif.workspace = true
clap.workspace = true
51 changes: 51 additions & 0 deletions shared/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use clap::Parser;

#[derive(Parser, Debug, Clone)]
#[command(version, about)]
pub struct CmdArgs {
/// The amount of threads you want to utilize. most systems can handle 2. Go higher if you have a powerful computer. Default is 2. Can't be lower than 1
#[arg(short, long, default_value_t = 2, value_parser = clap::value_parser!(u16).range(1..))]
pub thread_count: u16,

/// Options you want to pass to ffmpeg. For the output file name, use --output
#[arg(short, long, allow_hyphen_values = true)]
pub ffmpeg_options: Option<String>,

/// The files you want to process.
#[arg(short, long, num_args = 1.., required_unless_present = "file_list", conflicts_with = "file_list")]
pub input: Option<Vec<String>>,

/// Path to a file containing paths to process. One path per line
#[arg(long, required_unless_present = "input", conflicts_with = "input")]
pub file_list: Option<String>,

/// If ffmpeg should overwrite files if they already exist. Default is false
#[arg(long, default_value_t = false)]
pub overwrite: bool,

/// If verbose logs should be shown while ffzap is running
#[arg(long, default_value_t = false)]
pub verbose: bool,

/// Delete the source file after it was successfully processed. If the process fails, the file is kept.
#[arg(long, default_value_t = false)]
pub delete: bool,

/// Displays the current eta in the progressbar
#[arg(long, default_value_t = false)]
pub eta: bool,

/// Specify the output file pattern. Use placeholders to customize file paths:
///
/// {{dir}} - Entire specified file path, e.g. ./path/to/file.txt -> ?./path/to/
///
/// {{name}} - Original file's name (without extension)
///
/// {{ext}} - Original file's extension
///
/// Example: /destination/{{dir}}/{{name}}_transcoded.{{ext}}
///
/// Outputs the file in /destination, mirroring the original structure and keeping both the file extension and name, while adding _transcoded to the name.
#[arg(short, long)]
pub output: String,
}
9 changes: 9 additions & 0 deletions shared/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod logger;
pub mod progress;
pub mod processor;
pub mod args;

pub use logger::Logger;
pub use progress::Progress;
pub use processor::Processor;
pub use args::CmdArgs;
14 changes: 7 additions & 7 deletions src/logger.rs → shared/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use std::io::Write;
use std::path::{Display, PathBuf};
use std::sync::{Arc, Mutex, MutexGuard};

pub(crate) struct Logger {
pub struct Logger {
progress: Arc<Progress>,
log_file: Arc<Mutex<File>>,
log_path: PathBuf,
}

impl Logger {
pub(crate) fn new(progress: Arc<Progress>) -> Self {
pub fn new(progress: Arc<Progress>) -> Self {
let path_file_tuple = Self::setup_log_dir_and_create_log_file();

let log_path = path_file_tuple.0;
Expand All @@ -25,7 +25,7 @@ impl Logger {
}
}

pub(crate) fn log_info(&self, line: String, thread: u16, print: bool) {
pub fn log_info(&self, line: String, thread: u16, print: bool) {
let line = format!("[INFO in THREAD {thread}] -- {line}\n");

self.write_to_log(&line);
Expand All @@ -35,7 +35,7 @@ impl Logger {
}
}

pub(crate) fn log_error(&self, line: String, thread: u16, print: bool) {
pub fn log_error(&self, line: String, thread: u16, print: bool) {
let line = format!("[ERROR in THREAD {thread} -- {line}\n");

self.write_to_log(&line);
Expand All @@ -45,7 +45,7 @@ impl Logger {
}
}

pub(crate) fn append_failed_paths_to_log(&self, paths: &MutexGuard<Vec<String>>) {
pub fn append_failed_paths_to_log(&self, paths: &MutexGuard<Vec<String>>) {
if paths.len() == 0 {
return;
}
Expand All @@ -59,7 +59,7 @@ impl Logger {
self.write_to_log(&to_write);
}

pub(crate) fn get_log_path(&self) -> Display {
pub fn get_log_path(&self) -> Display {
self.log_path.display()
}

Expand Down Expand Up @@ -122,4 +122,4 @@ impl Logger {
fn print(&self, line: String) {
self.progress.println(line);
}
}
}
Loading