summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2022-08-24 23:54:13 +0800
committerJSDurand <mmemmew@gmail.com>2022-08-24 23:54:13 +0800
commite954df3f896bd18494cd27d77b26bbb2005de8a7 (patch)
tree7c81b759e41665ffd3fcd77f2f1036b59c03bc79 /src/main.rs
First commit
Now the project is in a somewhat complete state, ready for future enhancements.
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs214
1 files changed, 214 insertions, 0 deletions
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<PathBuf> {
+ 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<dyn std::error::Error>> {
+ 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(())
+}