Skip to content

Commit

Permalink
add createdvd/extractdvd support for chdman
Browse files Browse the repository at this point in the history
  • Loading branch information
alucryd committed Mar 30, 2024
1 parent 3265f05 commit 273c86d
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.env
.env.*
!.env.example
.idea
.vscode

# rust
Expand All @@ -14,6 +15,7 @@ target
lcov.info
dist
*.profraw
.cargo

# javascript
node_modules
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Add a `-n` flag to `import-dats` to override the system name
- Enhance the rom matching algorithm in `import-roms` to reduce prompts when multiple matches are found
- Use `createcd/createdvd` and `extractcd/extractdvd` appropriately for CDs and DVDs

# 0.18.0

Expand Down
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@ wiremock = "0.6.0"
[[bin]]
name = "oxyromon"
path = "src/main.rs"

[profile.dev]
debug = 0

[profile.release]
lto = true
codegen-units = 1
panic = "abort"
106 changes: 85 additions & 21 deletions src/chdman.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use super::common::*;
use super::config::*;
use super::model::*;
use super::progress::*;
use super::util::*;
use super::SimpleResult;
use std::path::{Path, PathBuf};
use std::time::Duration;

use indicatif::ProgressBar;
use regex::Regex;
use sqlx::SqliteConnection;
use std::path::{Path, PathBuf};
use std::time::Duration;
use tokio::io;
use tokio::io::AsyncReadExt;
use tokio::process::Command;

use super::common::*;
use super::config::*;
use super::model::*;
use super::progress::*;
use super::SimpleResult;
use super::util::*;

const CHDMAN: &str = "chdman";

pub const MIN_DREAMCAST_VERSION: &str = "0.262";
Expand All @@ -21,6 +23,12 @@ lazy_static! {
static ref VERSION_REGEX: Regex = Regex::new(r"\d+\.\d+").unwrap();
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum MediaType {
Cd,
Dvd,
}

pub struct ChdRomfile {
pub path: PathBuf,
pub cue_path: Option<PathBuf>,
Expand Down Expand Up @@ -81,6 +89,7 @@ pub trait ToChd {
progress_bar: &ProgressBar,
destination_directory: &P,
cue_romfile: &Option<&CommonRomfile>,
media_type: &MediaType,
) -> SimpleResult<ChdRomfile>;
}

Expand All @@ -90,8 +99,15 @@ impl ToChd for CueBinRomfile {
progress_bar: &ProgressBar,
destination_directory: &P,
cue_romfile: &Option<&CommonRomfile>,
media_type: &MediaType,
) -> SimpleResult<ChdRomfile> {
let path = create_chd(progress_bar, &self.cue_romfile.path, destination_directory).await?;
let path = create_chd(
progress_bar,
&self.cue_romfile.path,
destination_directory,
media_type,
)
.await?;
Ok(ChdRomfile {
path,
cue_path: cue_romfile.map(|romfile| romfile.path.clone()),
Expand All @@ -105,8 +121,9 @@ impl ToChd for IsoRomfile {
progress_bar: &ProgressBar,
destination_directory: &P,
cue_romfile: &Option<&CommonRomfile>,
media_type: &MediaType,
) -> SimpleResult<ChdRomfile> {
let path = create_chd(progress_bar, &self.path, destination_directory).await?;
let path = create_chd(progress_bar, &self.path, destination_directory, media_type).await?;
Ok(ChdRomfile {
path,
cue_path: cue_romfile.map(|romfile| romfile.path.clone()),
Expand Down Expand Up @@ -261,6 +278,7 @@ async fn create_chd<P: AsRef<Path>, Q: AsRef<Path>>(
progress_bar: &ProgressBar,
romfile_path: &P,
destination_directory: &Q,
media_type: &MediaType,
) -> SimpleResult<PathBuf> {
progress_bar.set_message("Creating chd");
progress_bar.set_style(get_none_progress_style());
Expand All @@ -277,7 +295,10 @@ async fn create_chd<P: AsRef<Path>, Q: AsRef<Path>>(
));

let output = Command::new(CHDMAN)
.arg("createcd")
.arg(match media_type {
MediaType::Cd => "createcd",
MediaType::Dvd => "createdvd",
})
.arg("-i")
.arg(romfile_path.as_ref())
.arg("-o")
Expand Down Expand Up @@ -306,40 +327,83 @@ async fn extract_chd<P: AsRef<Path>, Q: AsRef<Path>>(
progress_bar.set_style(get_none_progress_style());
progress_bar.enable_steady_tick(Duration::from_millis(100));

let media_type = parse(progress_bar, path).await?;

let cue_path = destination_directory
.as_ref()
.join(format!(
".{}",
path.as_ref().file_name().unwrap().to_str().unwrap()
))
.with_extension(CUE_EXTENSION);
let bin_path = destination_directory
let iso_bin_path = destination_directory
.as_ref()
.join(path.as_ref().file_name().unwrap())
.with_extension(extension);

let mut command = Command::new(CHDMAN);
command
.arg(match media_type {
MediaType::Cd => "extractcd",
MediaType::Dvd => "extractdvd",
})
.arg("-i")
.arg(path.as_ref());
match media_type {
MediaType::Cd => command
.arg("-o")
.arg(&cue_path)
.arg("-ob")
.arg(&iso_bin_path),
MediaType::Dvd => command.arg("-o").arg(&iso_bin_path),
};
let output = command.output().await.expect("Failed to extract chd");

if media_type == MediaType::Cd {
remove_file(progress_bar, &cue_path, true).await?;
}

if !output.status.success() {
bail!(String::from_utf8(output.stderr).unwrap().as_str());
}

progress_bar.set_message("");
progress_bar.disable_steady_tick();

Ok(iso_bin_path)
}

async fn parse<P: AsRef<Path>>(progress_bar: &ProgressBar, path: &P) -> SimpleResult<MediaType> {
progress_bar.set_message("Parsing chd");
progress_bar.set_style(get_none_progress_style());
progress_bar.enable_steady_tick(Duration::from_millis(100));

let output = Command::new(CHDMAN)
.arg("extractcd")
.arg("info")
.arg("-i")
.arg(path.as_ref())
.arg("-o")
.arg(&cue_path)
.arg("-ob")
.arg(&bin_path)
.output()
.await
.expect("Failed to extract chd");

remove_file(progress_bar, &cue_path, true).await?;
.expect("Failed to parse chd");

if !output.status.success() {
bail!(String::from_utf8(output.stderr).unwrap().as_str());
}

let stdout = String::from_utf8(output.stdout).unwrap();
let metadata: &str = stdout
.lines()
.find(|&line| line.starts_with("Metadata:"))
.unwrap();

progress_bar.set_message("");
progress_bar.disable_steady_tick();

Ok(bin_path)
Ok(if metadata.contains("DVD") {
MediaType::Dvd
} else {
MediaType::Cd
})
}

pub async fn get_version() -> SimpleResult<String> {
Expand Down
22 changes: 14 additions & 8 deletions src/convert_roms.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::chdman;
use super::chdman::{AsChd, ToChd};
use super::chdman::{AsChd, MediaType, ToChd};
use super::common::*;
use super::config::*;
use super::database::*;
Expand Down Expand Up @@ -1253,7 +1253,7 @@ async fn to_chd(
}
}

let (cue_roms, bin_roms): (Vec<&Rom>, Vec<&Rom>) = roms
let (cue_roms, bin_iso_roms): (Vec<&Rom>, Vec<&Rom>) = roms
.into_par_iter()
.partition(|rom| rom.name.ends_with(CUE_EXTENSION));

Expand All @@ -1267,9 +1267,9 @@ async fn to_chd(
);
}

let mut bin_romfiles: Vec<CommonRomfile> = Vec::new();
for rom in &bin_roms {
bin_romfiles.push(
let mut bin_iso_romfiles: Vec<CommonRomfile> = Vec::new();
for rom in &bin_iso_roms {
bin_iso_romfiles.push(
romfile
.as_archive(rom)?
.to_common(progress_bar, &tmp_directory.path())
Expand All @@ -1281,7 +1281,7 @@ async fn to_chd(
Some(cue_romfile) => {
cue_romfile
.as_cue_bin(
&bin_romfiles
&bin_iso_romfiles
.iter()
.map(|bin_iso_romfile| &bin_iso_romfile.path)
.collect::<Vec<&PathBuf>>(),
Expand All @@ -1290,18 +1290,20 @@ async fn to_chd(
progress_bar,
&romfile.as_common()?.path.parent().unwrap(),
&Some(cue_romfile),
&MediaType::Cd,
)
.await?
}
None => {
bin_romfiles
bin_iso_romfiles
.first()
.unwrap()
.as_iso()?
.to_chd(
progress_bar,
&romfile.as_common()?.path.parent().unwrap(),
&None,
&MediaType::Dvd,
)
.await?
}
Expand All @@ -1313,7 +1315,7 @@ async fn to_chd(
&mut transaction,
progress_bar,
&None,
&bin_roms,
&bin_iso_roms,
hash_algorithm,
)
.await
Expand Down Expand Up @@ -1403,6 +1405,7 @@ async fn to_chd(
progress_bar,
&cue_romfile.as_common()?.path.parent().unwrap(),
&Some(&cue_romfile.as_common()?),
&MediaType::Cd,
)
.await?;

Expand Down Expand Up @@ -1462,6 +1465,7 @@ async fn to_chd(
progress_bar,
&romfile.as_common()?.path.parent().unwrap(),
&None,
&MediaType::Dvd,
)
.await?;
if check
Expand Down Expand Up @@ -1511,6 +1515,7 @@ async fn to_chd(
progress_bar,
&romfile.as_common()?.path.parent().unwrap(),
&None,
&MediaType::Dvd,
)
.await?;
if check
Expand Down Expand Up @@ -1560,6 +1565,7 @@ async fn to_chd(
progress_bar,
&romfile.as_common()?.path.parent().unwrap(),
&None,
&MediaType::Dvd,
)
.await?;
if diff {
Expand Down
Loading

0 comments on commit 273c86d

Please sign in to comment.