From e954df3f896bd18494cd27d77b26bbb2005de8a7 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Wed, 24 Aug 2022 23:54:13 +0800 Subject: First commit Now the project is in a somewhat complete state, ready for future enhancements. --- src/main.rs | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ef4b93f --- /dev/null +++ b/src/main.rs @@ -0,0 +1,214 @@ +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(()) +} -- cgit v1.2.3-18-g5258