Support CDDA alignment; Update XML tag names
This commit is contained in:
parent
73bbe0e805
commit
a792a3f2ac
|
@ -8,11 +8,22 @@ pub enum LZ4State {
|
|||
Compress,
|
||||
}
|
||||
|
||||
pub struct CDAudioFile {
|
||||
pub file_path: PathBuf,
|
||||
pub align: bool,
|
||||
}
|
||||
|
||||
impl CDAudioFile {
|
||||
pub fn new(file_path: PathBuf, align: bool) -> CDAudioFile {
|
||||
CDAudioFile{file_path, align}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Configuration {
|
||||
pub publisher: Option<String>,
|
||||
pub license_path: Option<PathBuf>,
|
||||
pub root: Directory,
|
||||
pub cd_audio_files: Vec<PathBuf>,
|
||||
pub cd_audio_files: Vec<CDAudioFile>,
|
||||
pub lead_out_sectors: Option<usize>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use attribute_names::LBA_SOURCE;
|
||||
use cdtypes::types::time::Time;
|
||||
use std::path::PathBuf;
|
||||
use tool_helper::{format_if_error, path_with_env_from, print_warning, string_with_env_from};
|
||||
use tool_helper::{format_if_error, path_with_env_from, string_with_env_from};
|
||||
use crate::config_reader::Directory;
|
||||
|
||||
use super::{CommonProperties, Configuration, Error, File, FileKind, LZ4State};
|
||||
use super::{CDAudioFile, CommonProperties, Configuration, Error, File, FileKind, LZ4State};
|
||||
|
||||
mod attribute_names {
|
||||
pub const NAME: &'static str = "name";
|
||||
|
@ -14,39 +14,45 @@ mod attribute_names {
|
|||
pub const LZ4_STATE: &'static str = "lz4";
|
||||
}
|
||||
|
||||
mod tag_names {
|
||||
pub const ROOT: &'static str = "PSXCD";
|
||||
pub const TRACK: &'static str = "Filesystem";
|
||||
pub const INTERLEAVED: &'static str = "InterleavedFile";
|
||||
pub const CDDA: &'static str = "AudioTrack";
|
||||
}
|
||||
|
||||
pub fn parse(xml: String) -> Result<Configuration, Error> {
|
||||
let mut config = Configuration::new();
|
||||
let parser = format_if_error!(roxmltree::Document::parse(xml.as_str()), "Parsing XML file failed with: {error_text}")?;
|
||||
let children = parser.root().children();
|
||||
|
||||
for node in children {
|
||||
if node.is_element() && node.tag_name().name() == "ISO_Project" {
|
||||
parse_iso_project(node, &mut config)?;
|
||||
if node.is_element() && node.tag_name().name() == tag_names::ROOT {
|
||||
parse_root(node, &mut config)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn parse_iso_project(iso_project: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> {
|
||||
fn parse_root(root: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> {
|
||||
let mut parsed_track = false;
|
||||
|
||||
for node in iso_project.children() {
|
||||
for node in root.children() {
|
||||
if node.is_element() {
|
||||
match node.tag_name().name() {
|
||||
"Description" => parse_description(node, config),
|
||||
"Track" => {
|
||||
"Description" => parse_description(node, config),
|
||||
tag_names::TRACK => {
|
||||
if !parsed_track {
|
||||
parsed_track = true;
|
||||
parse_track(node, config)
|
||||
}
|
||||
|
||||
else {
|
||||
print_warning("Found more than 1 track. Multi-Tracks are not supported yet. Track will be ignored".to_owned());
|
||||
Ok(())
|
||||
Err(Error::from_text(format!("Found more than 1 filesystem. Multi filesystem discs are not supported")))
|
||||
}
|
||||
},
|
||||
"CD_Audio" => parse_cd_audio(node, config),
|
||||
tag_names::CDDA => parse_cd_audio(node, config),
|
||||
_ => Ok(())
|
||||
}?;
|
||||
}
|
||||
|
@ -109,8 +115,8 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(),
|
|||
Ok(File{common, path, kind: FileKind::Overlay(PathBuf::from(lba_source))})
|
||||
}
|
||||
|
||||
fn parse_xa_audio(file: roxmltree::Node, is_hidden: bool) -> Result<File, Error> {
|
||||
// v Never compress XA-Audio
|
||||
fn parse_interleaved(file: roxmltree::Node, is_hidden: bool) -> Result<File, Error> {
|
||||
// v Never compress interleaved files
|
||||
let common = read_common_properties(&file, is_hidden, Some(LZ4State::None))?;
|
||||
let channel = {
|
||||
let mut channel = Vec::new();
|
||||
|
@ -130,11 +136,11 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(),
|
|||
for node in cur_node.children() {
|
||||
if node.is_element() {
|
||||
match node.tag_name().name() {
|
||||
"File" => root.add_file(parse_regular_file(node, is_hidden)?),
|
||||
"Main" => root.add_file(parse_main_file(node)?),
|
||||
"Overlay" => root.add_file(parse_overlay_file(node, is_hidden)?),
|
||||
"XA-Audio" => root.add_file(parse_xa_audio(node, is_hidden)?),
|
||||
"Directory" => {
|
||||
"File" => root.add_file(parse_regular_file(node, is_hidden)?),
|
||||
"Main" => root.add_file(parse_main_file(node)?),
|
||||
"Overlay" => root.add_file(parse_overlay_file(node, is_hidden)?),
|
||||
tag_names::INTERLEAVED => root.add_file(parse_interleaved(node, is_hidden)?),
|
||||
"Directory" => {
|
||||
is_hidden |= parse_boolean_attribute(&node, attribute_names::HIDDEN)?;
|
||||
let mut new_dir = Directory::new(node.attribute(attribute_names::NAME).unwrap_or_default(), is_hidden);
|
||||
|
||||
|
@ -158,7 +164,7 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(),
|
|||
fn parse_split<'a>(who: &'a str, str_opt: Option<&'a str>) -> Result<u8, Error> {
|
||||
match str_opt.unwrap_or("0").parse::<u8>() {
|
||||
Ok(num) => Ok(num),
|
||||
Err(error) => Err(Error::from_text(format!("Failed converting \"{}\" option for \"Track\" attribute \"{}\": {}", who, ATTRIBUTE_NAME, error)))
|
||||
Err(error) => Err(Error::from_text(format!("Failed converting \"{}\" option for \"{}\" attribute \"{}\": {}", who, tag_names::TRACK, ATTRIBUTE_NAME, error)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +191,7 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(),
|
|||
}
|
||||
|
||||
fn parse_cd_audio(cdda: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> {
|
||||
config.cd_audio_files.push(path_from_node(&cdda, "CD Audio file")?);
|
||||
config.cd_audio_files.push(CDAudioFile::new(path_from_node(&cdda, "CD Audio file")?, parse_boolean_attribute(&cdda, "align")?));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ pub mod types;
|
|||
|
||||
use crate::types::RawData;
|
||||
use cdtypes::types::sector::AudioSample;
|
||||
use config_reader::LZ4State;
|
||||
use config_reader::{CDAudioFile, LZ4State};
|
||||
use encoder::{cd::{self, calculate_lbas, calculate_length_for}, SizeInfo};
|
||||
use tool_helper::{format_if_error, Output, read_file};
|
||||
use types::{layout::Layout, CDDATrack, CDDesc, Directory, File, FileType, FileSystemMap, Properties, SharedPtr};
|
||||
|
@ -204,7 +204,7 @@ fn parse_configuration(config: config_reader::Configuration) -> Result<(CDDesc,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_cd_da(cd_da_tracks: &mut Vec<CDDATrack>, cd_da_files: Vec<PathBuf>) -> Result<(), Error> {
|
||||
fn parse_cd_da(cd_da_tracks: &mut Vec<CDDATrack>, cd_da_files: Vec<CDAudioFile>) -> Result<(), Error> {
|
||||
fn convert_into_16<R:std::io::Read, S:hound::Sample>(samples: hound::WavSamples<R,S>, file_path: &PathBuf) -> Result<Vec<AudioSample>, Error> {
|
||||
let mut sample_buffer = 0;
|
||||
let mut sample_id = 0;
|
||||
|
@ -233,18 +233,18 @@ fn parse_configuration(config: config_reader::Configuration) -> Result<(CDDesc,
|
|||
}
|
||||
|
||||
for cd_da_file in cd_da_files {
|
||||
let mut audio_io = hound::WavReader::open(&cd_da_file)?;
|
||||
let mut audio_io = hound::WavReader::open(&cd_da_file.file_path)?;
|
||||
let header = audio_io.spec();
|
||||
|
||||
if header.sample_format != hound::SampleFormat::Int {
|
||||
return Err(Error::from_text(format!("{}: Only integer WAV format (PCM) is supported for Audio tracks", cd_da_file.display())));
|
||||
return Err(Error::from_text(format!("{}: Only integer WAV format (PCM) is supported for Audio tracks", cd_da_file.file_path.display())));
|
||||
}
|
||||
|
||||
if header.sample_rate != 44_100 {
|
||||
return Err(Error::from_text(format!("{}: Only a sampling rate of 44.1kHz is supported for Audio tracks", cd_da_file.display())));
|
||||
return Err(Error::from_text(format!("{}: Only a sampling rate of 44.1kHz is supported for Audio tracks", cd_da_file.file_path.display())));
|
||||
}
|
||||
|
||||
cd_da_tracks.push(CDDATrack::new(convert_into_16(audio_io.samples::<i16>(), &cd_da_file)?, false));
|
||||
cd_da_tracks.push(CDDATrack::new(convert_into_16(audio_io.samples::<i16>(), &cd_da_file.file_path)?, cd_da_file.align));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue