caesura 0.11.2

An all-in-one command line tool to **transcode FLAC** audio files and **upload to gazelle** based indexers/trackers.
Documentation
use std::fs::create_dir_all;
use std::path::PathBuf;
use std::process::Stdio;

use audiotags::{AudioTagWrite, Id3v2Tag};
use colored::Colorize;
use log::*;
use tokio::io::AsyncWriteExt;

use crate::errors::{AppError, OutputHandler};
use crate::transcode::CommandFactory;

pub struct TranscodeJob {
    pub id: String,
    pub output_path: PathBuf,
    pub commands: Vec<CommandFactory>,
    pub tags: Option<Id3v2Tag>,
}

impl TranscodeJob {
    pub async fn execute(self) -> Result<(), AppError> {
        let output_dir = self
            .output_path
            .parent()
            .expect("output path should have a parent");
        create_dir_all(output_dir)
            .or_else(|e| AppError::io(e, "create transcode output directory"))?;
        let mut buffer = vec![];
        for factory in self.commands {
            let program = factory.program.clone();
            let command = format!(
                "{} \"{}\"",
                factory.program.clone(),
                factory.args.clone().join("\" \"")
            );
            trace!("{} {}", "Executing".bold(), command);
            let mut child = factory
                .create()
                .stdin(Stdio::piped())
                .stdout(Stdio::piped())
                .stderr(Stdio::piped())
                .spawn()
                .or_else(|e| AppError::command(e, "execute transcode job", program.as_str()))?;
            if !buffer.is_empty() {
                let mut stdin = child.stdin.take().expect("stdin should be available");
                stdin
                    .write_all(&buffer)
                    .await
                    .expect("Should be able to write to std in");
                drop(stdin);
            }
            let output = child
                .wait_with_output()
                .await
                .expect("Child should produce an output");
            let output = OutputHandler::execute(output, "transcode", "transcode")?;
            buffer = output.stdout;
        }
        if let Some(tags) = self.tags {
            let mut tags = tags;
            tags.write_to_path(self.output_path.to_string_lossy().as_ref())
                .or_else(|e| AppError::tag(e, "write tags to file"))?;
        }
        Ok(())
    }
}