Extract audio and cue sheet from an NRG audio CD image.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.3 KiB

  1. // This file is part of the NRGrip project.
  2. //
  3. // Copyright (c) 2016 Matteo Cypriani <mcy@lm7.fr>
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. use std::env;
  23. use std::fs::File;
  24. use std::process;
  25. extern crate getopts;
  26. use getopts::Options;
  27. extern crate nrgrip;
  28. use nrgrip::metadata;
  29. use nrgrip::cue_sheet;
  30. use nrgrip::raw_audio;
  31. fn main() {
  32. process::exit(main_main());
  33. }
  34. fn main_main() -> i32 {
  35. let args: Vec<String> = env::args().collect();
  36. let prog_name = &args.first().expect("Can't retrieve program's name");
  37. let mut opts = Options::new();
  38. opts.optflag("i", "info",
  39. "display the image's metadata (default action)");
  40. opts.optflag("x", "extract",
  41. "same as --extract-cue --extract-raw");
  42. opts.optflag("c", "extract-cue",
  43. "extract cue sheet from the NRG metadata");
  44. opts.optflag("r", "extract-raw",
  45. "extract the raw audio tracks");
  46. opts.optflag("h", "help",
  47. "print this help message");
  48. let options = match opts.parse(&args[1..]) {
  49. Ok(options) => options,
  50. Err(_) => {
  51. print_usage(&prog_name, &opts);
  52. return 1;
  53. },
  54. };
  55. if options.opt_present("help") {
  56. print_usage(&prog_name, &opts);
  57. return 0;
  58. }
  59. // Get input NRG image name
  60. if options.free.len() != 1 {
  61. // We need exactly one input file!
  62. print_usage(&prog_name, &opts);
  63. return 1;
  64. }
  65. let img_path = &options.free[0];
  66. println!("NRG image path: \"{}\"", img_path);
  67. // See what actions are to be taken on that file
  68. let action_cue =
  69. options.opt_present("extract-cue") || options.opt_present("extract");
  70. let action_raw =
  71. options.opt_present("extract-raw") || options.opt_present("extract");
  72. let action_info =
  73. options.opt_present("info") || !(action_cue || action_raw);
  74. // Open the image file
  75. let mut fd = match File::open(&img_path) {
  76. Ok(fd) => fd,
  77. Err(err) => {
  78. println!("Can't open image file \"{}\": {}", img_path, err);
  79. return 1;
  80. },
  81. };
  82. // Read the image's metadata
  83. let metadata = match metadata::read_nrg_metadata(&mut fd) {
  84. Ok(metadata) => metadata,
  85. Err(err) => {
  86. println!("Error reading \"{}\": {}", img_path, err);
  87. return 1;
  88. },
  89. };
  90. // Display metadata if requested
  91. if action_info {
  92. println!("\n{}", metadata);
  93. }
  94. // Read and write the cue sheet
  95. if action_cue {
  96. println!("\nExtracting cue sheet...");
  97. if let Err(err) = cue_sheet::write_cue_sheet(&img_path, &metadata) {
  98. println!("Error writing cue sheet: {}", err);
  99. return 1;
  100. }
  101. println!("OK!");
  102. }
  103. // Extract raw audio data
  104. if action_raw {
  105. println!("\nExtracting raw audio data...");
  106. if let Err(err) = raw_audio::extract_nrg_raw_audio(&mut fd, &img_path,
  107. &metadata) {
  108. println!("Error extracting raw audio data: {}", err);
  109. }
  110. println!("OK!");
  111. }
  112. 0
  113. }
  114. fn print_usage(prog_name: &str, opts: &Options) {
  115. let brief = format!("NRGrip - rip Nero Burning ROM audio images
  116. Usage:
  117. {prog} [-icrx] [options] <image.nrg>
  118. {prog} -h", prog = prog_name);
  119. print!("{}", opts.usage(&brief));
  120. }