use rumu::{self, output::Output}; use std::env; use std::path::PathBuf; #[derive(Debug)] struct MainError { mes: &'static str, } impl std::fmt::Display for MainError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "main error: {}", self.mes) } } impl std::error::Error for MainError {} impl From<&'static str> for MainError { fn from(mes: &'static str) -> Self { Self { mes } } } fn get_root() -> std::io::Result { let path = env::current_dir()?; let path_ancestors = path.as_path().ancestors(); for p in path_ancestors { let has_cargo_p = std::fs::read_dir(p)? .into_iter() .any(|p| p.unwrap().file_name() == std::ffi::OsString::from("Cargo.toml")); if has_cargo_p { return Ok(PathBuf::from(p)); } } Err(std::io::Error::new( std::io::ErrorKind::NotFound, "Cannot find project root", )) } fn main() -> Result<(), Box> { let args: Vec<_> = env::args().skip(1).collect(); if args.iter().any(|string| string as &str == "-h") { println!( "Usage: cargo run [--features ffmpeg] -- [-h] [sheet filename] [output filename] [encoder]" ); println!(); let prefix = " ".repeat(7); println!("{prefix}-h: just print this usage and exit"); println!(); println!("{prefix}sheet filename \t the file to read the sheet from"); println!("{prefix}output filename \t the name of the output audio file"); println!("{prefix}encoder \t\t the encoder used to encode the output"); println!("{}", "-".repeat(89)); println!("{prefix}To skip a paramter, use \"-\" in its place"); return Ok(()); } let mut sheet_name = "Ievan Polkka".to_owned(); let mut output_name = "Ievan Polkka.opus".to_owned(); let mut encoder = if cfg!(feature = "ffmpeg") { "opus" } else { "plain" }; match args.len() { 0 => {} 1 => { if args[0] != "-" { sheet_name = args[0].to_owned(); output_name = format!("{sheet_name}.opus"); } } 2 => { if args[0] != "-" { sheet_name = args[0].to_owned(); } if args[1] != "-" { output_name = args[1].to_owned(); } else { output_name = format!("{sheet_name}.opus"); } } 3 => { if args[0] != "-" { sheet_name = args[0].to_owned(); } let mut output_not_specified = false; if args[1] != "-" { output_name = args[1].to_owned(); } else { output_not_specified = true; output_name = format!("{sheet_name}.{encoder}"); } if args[2] != "-" { encoder = &args[2]; if output_not_specified { output_name = format!("{sheet_name}.{encoder}"); } } } _ => { println!( "Usage: cargo run [--features ffmpeg] -- \ [-h] [sheet filename] [output filename] [encoder]" ); println!(); let prefix = " ".repeat(7); println!("{prefix}-h: just print this usage and exit"); println!(); println!("{prefix}sheet filename \t the file to read the sheet from"); println!("{prefix}output filename \t the name of the output audio file"); println!("{prefix}encoder \t\t the encoder used to encode the output"); println!("{}", "-".repeat(89)); println!("{prefix}To skip a paramter, use \"-\" in its place"); std::process::exit(1); } } let project_root = get_root()?.to_str().unwrap().to_owned(); output_name = format!("{project_root}/audio files/{output_name}"); let source = std::fs::read_to_string(format!("{project_root}/songs/{sheet_name}.rumu"))?; let mut sheet: rumu::sheet::Sheet = source.parse()?; let wave: rumu::Wave = (&mut sheet).into(); let rate: rumu::Samples = 44100f64.into(); match encoder { "opus" => { if !cfg!(feature = "ffmpeg") { return Err( "To use the opus encoder one has to enable the \"ffmpeg\" feature.".into(), ); } #[cfg(feature = "ffmpeg")] { let output = rumu::output::ffmpeg_output::OpusOutput::default(); output.save(wave, rate, &output_name)?; } } "mp3" => { if !cfg!(feature = "ffmpeg") { return Err( "To use the mp3 encoder one has to enable the \"ffmpeg\" feature.".into(), ); } #[cfg(feature = "ffmpeg")] { let output = rumu::output::ffmpeg_output::MP3Output::default(); output.save(wave, rate, &output_name)?; } } "aac" => { if !cfg!(feature = "ffmpeg") { return Err( "To use the aac encoder one has to enable the \"ffmpeg\" feature.".into(), ); } #[cfg(feature = "ffmpeg")] { let output = rumu::output::ffmpeg_output::AACOutput::default(); output.save(wave, rate, &output_name)?; } } "plain" => { let output = rumu::output::PlainOutput::default(); output.save(wave, rate, &output_name)?; } _ => { return Err("Unrecognized encoder: {encoder}".into()); } } Ok(()) }