mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-04-19 03:32:53 -05:00
Ran cargo fmt
This commit is contained in:
parent
52b067ddbc
commit
72e13b92f9
7 changed files with 490 additions and 207 deletions
|
@ -1,5 +1,4 @@
|
|||
/// A crate for controlling NetMD and Hi-MD devices.
|
||||
///
|
||||
/// To use this library, first you need to get a device from [cross-usb] and then open [netmd::interface::NetMDInterface]
|
||||
|
||||
pub mod netmd;
|
||||
|
|
|
@ -7,7 +7,7 @@ use thiserror::Error;
|
|||
// USB stuff
|
||||
use cross_usb::prelude::*;
|
||||
use cross_usb::usb::{ControlIn, ControlOut, ControlType, Recipient, UsbError};
|
||||
use cross_usb::{Interface, Descriptor};
|
||||
use cross_usb::{Descriptor, Interface};
|
||||
|
||||
use super::utils::cross_sleep;
|
||||
|
||||
|
@ -15,61 +15,248 @@ const BULK_WRITE_ENDPOINT: u8 = 0x02;
|
|||
const BULK_READ_ENDPOINT: u8 = 0x81;
|
||||
|
||||
pub static DEVICE_IDS: &[DeviceId] = &[
|
||||
DeviceId {vendor_id: 0x04dd, product_id: 0x7202, name: Some("Sharp IM-MT899H")},
|
||||
DeviceId {vendor_id: 0x04dd, product_id: 0x9013, name: Some("Sharp IM-DR400")},
|
||||
DeviceId {vendor_id: 0x04dd, product_id: 0x9014, name: Some("Sharp IM-DR80")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0034, name: Some("Sony PCLK-XX")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0036, name: Some("Sony")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0075, name: Some("Sony MZ-N1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x007c, name: Some("Sony")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0080, name: Some("Sony LAM-1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0081, name: Some("Sony MDS-JB980/MDS-NT1/MDS-JE780")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0084, name: Some("Sony MZ-N505")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0085, name: Some("Sony MZ-S1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0086, name: Some("Sony MZ-N707")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x008e, name: Some("Sony CMT-C7NT")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0097, name: Some("Sony PCGA-MDN1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00ad, name: Some("Sony CMT-L7HD")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00c6, name: Some("Sony MZ-N10")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00c7, name: Some("Sony MZ-N910")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00c8, name: Some("Sony MZ-N710/NF810")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00c9, name: Some("Sony MZ-N510/N610")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00ca, name: Some("Sony MZ-NE410/NF520D")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00e7, name: Some("Sony CMT-M333NT/M373NT")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x00eb, name: Some("Sony MZ-NE810/NE910")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0101, name: Some("Sony LAM")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0113, name: Some("Aiwa AM-NX1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x013f, name: Some("Sony MDS-S500")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x014c, name: Some("Aiwa AM-NX9")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x017e, name: Some("Sony MZ-NH1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0180, name: Some("Sony MZ-NH3D")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0182, name: Some("Sony MZ-NH900")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0184, name: Some("Sony MZ-NH700/NH800")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0186, name: Some("Sony MZ-NH600")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0187, name: Some("Sony MZ-NH600D")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0188, name: Some("Sony MZ-N920")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x018a, name: Some("Sony LAM-3")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x01e9, name: Some("Sony MZ-DH10P")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0219, name: Some("Sony MZ-RH10")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x021b, name: Some("Sony MZ-RH710/MZ-RH910")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x021d, name: Some("Sony CMT-AH10")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x022c, name: Some("Sony CMT-AH10")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x023c, name: Some("Sony DS-HMD1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0286, name: Some("Sony MZ-RH1")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x011a, name: Some("Sony CMT-SE7")},
|
||||
DeviceId {vendor_id: 0x054c, product_id: 0x0148, name: Some("Sony MDS-A1")},
|
||||
DeviceId {vendor_id: 0x0b28, product_id: 0x1004, name: Some("Kenwood MDX-J9")},
|
||||
DeviceId {vendor_id: 0x04da, product_id: 0x23b3, name: Some("Panasonic SJ-MR250")},
|
||||
DeviceId {vendor_id: 0x04da, product_id: 0x23b6, name: Some("Panasonic SJ-MR270")},
|
||||
DeviceId {
|
||||
vendor_id: 0x04dd,
|
||||
product_id: 0x7202,
|
||||
name: Some("Sharp IM-MT899H"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x04dd,
|
||||
product_id: 0x9013,
|
||||
name: Some("Sharp IM-DR400"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x04dd,
|
||||
product_id: 0x9014,
|
||||
name: Some("Sharp IM-DR80"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0034,
|
||||
name: Some("Sony PCLK-XX"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0036,
|
||||
name: Some("Sony"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0075,
|
||||
name: Some("Sony MZ-N1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x007c,
|
||||
name: Some("Sony"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0080,
|
||||
name: Some("Sony LAM-1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0081,
|
||||
name: Some("Sony MDS-JB980/MDS-NT1/MDS-JE780"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0084,
|
||||
name: Some("Sony MZ-N505"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0085,
|
||||
name: Some("Sony MZ-S1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0086,
|
||||
name: Some("Sony MZ-N707"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x008e,
|
||||
name: Some("Sony CMT-C7NT"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0097,
|
||||
name: Some("Sony PCGA-MDN1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00ad,
|
||||
name: Some("Sony CMT-L7HD"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00c6,
|
||||
name: Some("Sony MZ-N10"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00c7,
|
||||
name: Some("Sony MZ-N910"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00c8,
|
||||
name: Some("Sony MZ-N710/NF810"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00c9,
|
||||
name: Some("Sony MZ-N510/N610"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00ca,
|
||||
name: Some("Sony MZ-NE410/NF520D"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00e7,
|
||||
name: Some("Sony CMT-M333NT/M373NT"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x00eb,
|
||||
name: Some("Sony MZ-NE810/NE910"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0101,
|
||||
name: Some("Sony LAM"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0113,
|
||||
name: Some("Aiwa AM-NX1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x013f,
|
||||
name: Some("Sony MDS-S500"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x014c,
|
||||
name: Some("Aiwa AM-NX9"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x017e,
|
||||
name: Some("Sony MZ-NH1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0180,
|
||||
name: Some("Sony MZ-NH3D"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0182,
|
||||
name: Some("Sony MZ-NH900"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0184,
|
||||
name: Some("Sony MZ-NH700/NH800"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0186,
|
||||
name: Some("Sony MZ-NH600"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0187,
|
||||
name: Some("Sony MZ-NH600D"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0188,
|
||||
name: Some("Sony MZ-N920"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x018a,
|
||||
name: Some("Sony LAM-3"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x01e9,
|
||||
name: Some("Sony MZ-DH10P"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0219,
|
||||
name: Some("Sony MZ-RH10"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x021b,
|
||||
name: Some("Sony MZ-RH710/MZ-RH910"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x021d,
|
||||
name: Some("Sony CMT-AH10"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x022c,
|
||||
name: Some("Sony CMT-AH10"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x023c,
|
||||
name: Some("Sony DS-HMD1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0286,
|
||||
name: Some("Sony MZ-RH1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x011a,
|
||||
name: Some("Sony CMT-SE7"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x054c,
|
||||
product_id: 0x0148,
|
||||
name: Some("Sony MDS-A1"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x0b28,
|
||||
product_id: 0x1004,
|
||||
name: Some("Kenwood MDX-J9"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x04da,
|
||||
product_id: 0x23b3,
|
||||
name: Some("Panasonic SJ-MR250"),
|
||||
},
|
||||
DeviceId {
|
||||
vendor_id: 0x04da,
|
||||
product_id: 0x23b6,
|
||||
name: Some("Panasonic SJ-MR270"),
|
||||
},
|
||||
];
|
||||
|
||||
pub static DEVICE_IDS_CROSSUSB: Lazy<Box<[cross_usb::DeviceFilter]>> = Lazy::new(|| {
|
||||
DEVICE_IDS.iter().map(|d|{
|
||||
DEVICE_IDS
|
||||
.iter()
|
||||
.map(|d| {
|
||||
cross_usb::device_filter! {
|
||||
vendor_id: d.vendor_id,
|
||||
product_id: d.product_id,
|
||||
}
|
||||
}).collect()
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
/// The current status of the Minidisc device
|
||||
|
@ -311,7 +498,9 @@ impl NetMD {
|
|||
chunksize: usize,
|
||||
progress_callback: Option<F>,
|
||||
) -> Result<Vec<u8>, NetMDError> {
|
||||
let result = self.read_bulk_to_array(length, chunksize, progress_callback).await?;
|
||||
let result = self
|
||||
.read_bulk_to_array(length, chunksize, progress_callback)
|
||||
.await?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
#![cfg_attr(debug_assertions, allow(dead_code))]
|
||||
use cross_usb::Descriptor;
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use regex::Regex;
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use cross_usb::Descriptor;
|
||||
|
||||
use crate::netmd::interface::DiscFlag;
|
||||
use crate::netmd::utils::{create_aea_header, create_wav_header, AeaOptions, RawTime};
|
||||
|
||||
use super::interface::{Channels, Direction, DiscFormat, Encoding, InterfaceError, MDSession, MDTrack, NetMDInterface, TrackFlag};
|
||||
use super::utils::{cross_sleep, half_width_title_length, half_width_to_full_width_range, sanitize_full_width_title, sanitize_half_width_title};
|
||||
use super::interface::{
|
||||
Channels, Direction, DiscFormat, Encoding, InterfaceError, MDSession, MDTrack, NetMDInterface,
|
||||
TrackFlag,
|
||||
};
|
||||
use super::utils::{
|
||||
cross_sleep, half_width_title_length, half_width_to_full_width_range,
|
||||
sanitize_full_width_title, sanitize_half_width_title,
|
||||
};
|
||||
|
||||
#[derive(FromPrimitive, PartialEq, Eq)]
|
||||
pub enum OperatingStatus {
|
||||
|
@ -53,7 +59,7 @@ impl Track {
|
|||
pub fn cells_for_title(&self) -> (usize, usize) {
|
||||
let encoding_name_correction = match self.encoding {
|
||||
Encoding::SP => 0,
|
||||
_ => 1
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
let full_width_length = chars_to_cells(self.full_width_title.len() * 2);
|
||||
|
@ -87,19 +93,22 @@ pub struct Disc {
|
|||
|
||||
impl Disc {
|
||||
pub fn track_count(&self) -> u16 {
|
||||
self.groups.iter()
|
||||
self.groups
|
||||
.iter()
|
||||
.map(|g| g.tracks.len())
|
||||
.reduce(|acc, s| acc + s)
|
||||
.unwrap() as u16
|
||||
}
|
||||
|
||||
pub fn tracks(&self) -> Vec<Track> {
|
||||
self.groups.iter()
|
||||
.flat_map(|g| g.tracks.clone())
|
||||
.collect()
|
||||
self.groups.iter().flat_map(|g| g.tracks.clone()).collect()
|
||||
}
|
||||
|
||||
fn remaining_characters_for_titles(&self, ignore_disc_titles: bool, include_groups: bool) -> (usize, usize) {
|
||||
fn remaining_characters_for_titles(
|
||||
&self,
|
||||
ignore_disc_titles: bool,
|
||||
include_groups: bool,
|
||||
) -> (usize, usize) {
|
||||
const CELL_LIMIT: usize = 255;
|
||||
|
||||
let groups = self.groups.iter().filter(|g| g.title.is_some());
|
||||
|
@ -119,17 +128,13 @@ impl Disc {
|
|||
let min_group_index = indices.iter().min().unwrap();
|
||||
let max_group_index = indices.iter().max().unwrap();
|
||||
|
||||
let range = format!(
|
||||
"{}{}",
|
||||
min_group_index + 1,
|
||||
{
|
||||
let range = format!("{}{}", min_group_index + 1, {
|
||||
if group.tracks.len() - 1 != 0 {
|
||||
format!("-{}", max_group_index + 1)
|
||||
} else {
|
||||
String::from("")
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
fw_title.push_str((group.full_width_title.clone().unwrap() + &range).as_str());
|
||||
hw_title.push_str((group.title.clone().unwrap() + &range).as_str());
|
||||
|
@ -150,16 +155,26 @@ impl Disc {
|
|||
|
||||
(
|
||||
usize::max(CELL_LIMIT - used_full_width_cells, 0) * 7,
|
||||
usize::max(CELL_LIMIT - used_half_width_cells, 0) * 7
|
||||
usize::max(CELL_LIMIT - used_half_width_cells, 0) * 7,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn compile_disc_titles(&self) -> (String, String) {
|
||||
let (available_full_width, available_half_width) = self.remaining_characters_for_titles(true, false);
|
||||
let (available_full_width, available_half_width) =
|
||||
self.remaining_characters_for_titles(true, false);
|
||||
|
||||
let use_full_width =
|
||||
self.groups.iter().filter(|n| n.full_width_title.as_ref().is_some_and(|t| !t.is_empty())).count() > 0 ||
|
||||
self.tracks().iter().filter(|t| !t.full_width_title.is_empty()).count() > 0;
|
||||
let use_full_width = self
|
||||
.groups
|
||||
.iter()
|
||||
.filter(|n| n.full_width_title.as_ref().is_some_and(|t| !t.is_empty()))
|
||||
.count()
|
||||
> 0
|
||||
|| self
|
||||
.tracks()
|
||||
.iter()
|
||||
.filter(|t| !t.full_width_title.is_empty())
|
||||
.count()
|
||||
> 0;
|
||||
|
||||
let mut new_raw_title = String::new();
|
||||
let mut new_raw_full_width_title = String::new();
|
||||
|
@ -176,23 +191,36 @@ impl Disc {
|
|||
continue;
|
||||
}
|
||||
|
||||
let min_group_index = group.tracks.iter().map(|t| t.index).min().unwrap_or_default();
|
||||
let min_group_index = group
|
||||
.tracks
|
||||
.iter()
|
||||
.map(|t| t.index)
|
||||
.min()
|
||||
.unwrap_or_default();
|
||||
let mut range = format!("{}", min_group_index + 1);
|
||||
|
||||
if group.tracks.len() != 1 {
|
||||
range.push_str(&format!("-{}", min_group_index as usize + group.tracks.len()));
|
||||
range.push_str(&format!(
|
||||
"-{}",
|
||||
min_group_index as usize + group.tracks.len()
|
||||
));
|
||||
}
|
||||
|
||||
let new_raw_title_after_group = new_raw_title.clone() + &format!("{};{}//", range, group.title.as_ref().unwrap());
|
||||
let new_raw_full_width_title_after_group =
|
||||
new_raw_full_width_title.clone() +
|
||||
&half_width_to_full_width_range(&range) +
|
||||
&format!(";{}//", group.full_width_title.as_ref().unwrap_or(&String::new()));
|
||||
let new_raw_title_after_group =
|
||||
new_raw_title.clone() + &format!("{};{}//", range, group.title.as_ref().unwrap());
|
||||
let new_raw_full_width_title_after_group = new_raw_full_width_title.clone()
|
||||
+ &half_width_to_full_width_range(&range)
|
||||
+ &format!(
|
||||
";{}//",
|
||||
group.full_width_title.as_ref().unwrap_or(&String::new())
|
||||
);
|
||||
|
||||
let half_width_titles_length_in_toc = chars_to_cells(half_width_title_length(&new_raw_title_after_group));
|
||||
let half_width_titles_length_in_toc =
|
||||
chars_to_cells(half_width_title_length(&new_raw_title_after_group));
|
||||
|
||||
if use_full_width {
|
||||
let full_width_titles_length_in_toc = chars_to_cells(new_raw_full_width_title_after_group.len() * 2) * 7;
|
||||
let full_width_titles_length_in_toc =
|
||||
chars_to_cells(new_raw_full_width_title_after_group.len() * 2) * 7;
|
||||
if available_full_width as isize - full_width_titles_length_in_toc as isize >= 0 {
|
||||
new_raw_full_width_title = new_raw_full_width_title_after_group
|
||||
}
|
||||
|
@ -203,7 +231,8 @@ impl Disc {
|
|||
}
|
||||
}
|
||||
|
||||
let half_width_titles_length_in_toc = chars_to_cells(half_width_title_length(&new_raw_title)) * 7;
|
||||
let half_width_titles_length_in_toc =
|
||||
chars_to_cells(half_width_title_length(&new_raw_title)) * 7;
|
||||
let full_width_titles_length_in_toc = chars_to_cells(new_raw_full_width_title.len() * 2);
|
||||
|
||||
if (available_half_width as isize - half_width_titles_length_in_toc as isize) < 0 {
|
||||
|
@ -219,7 +248,7 @@ impl Disc {
|
|||
new_raw_full_width_title
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -233,9 +262,7 @@ impl NetMDContext {
|
|||
pub async fn new(device: Descriptor) -> Result<Self, InterfaceError> {
|
||||
let interface = NetMDInterface::new(device).await?;
|
||||
|
||||
Ok(Self {
|
||||
interface,
|
||||
})
|
||||
Ok(Self { interface })
|
||||
}
|
||||
|
||||
/// Change to the next track (skip forward)
|
||||
|
@ -313,8 +340,7 @@ impl NetMDContext {
|
|||
let title = self.interface.track_title(*track, false).await?;
|
||||
let full_width_title = self.interface.track_title(*track, true).await?;
|
||||
|
||||
tracks.push(
|
||||
Track {
|
||||
tracks.push(Track {
|
||||
index: *track,
|
||||
title,
|
||||
full_width_title,
|
||||
|
@ -322,18 +348,15 @@ impl NetMDContext {
|
|||
channel,
|
||||
encoding,
|
||||
protected: TrackFlag::from_u8(flags).unwrap(),
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
groups.push(
|
||||
Group {
|
||||
groups.push(Group {
|
||||
index: index as u16,
|
||||
title: group.0.clone(),
|
||||
full_width_title: group.1.clone(),
|
||||
tracks
|
||||
}
|
||||
)
|
||||
tracks,
|
||||
})
|
||||
}
|
||||
|
||||
let disc = Disc {
|
||||
|
@ -345,7 +368,7 @@ impl NetMDContext {
|
|||
left: frames_left,
|
||||
total: frames_total,
|
||||
track_count,
|
||||
groups
|
||||
groups,
|
||||
};
|
||||
|
||||
Ok(disc)
|
||||
|
@ -355,12 +378,18 @@ impl NetMDContext {
|
|||
let (new_raw_title, new_raw_full_width_title) = disc.compile_disc_titles();
|
||||
|
||||
self.interface.set_disc_title(&new_raw_title, false).await?;
|
||||
self.interface.set_disc_title(&new_raw_full_width_title, false).await?;
|
||||
self.interface
|
||||
.set_disc_title(&new_raw_full_width_title, false)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn rename_disc(&mut self, new_name: &str, new_fw_name: Option<&str>) -> Result<(), Box<dyn Error>> {
|
||||
pub async fn rename_disc(
|
||||
&mut self,
|
||||
new_name: &str,
|
||||
new_fw_name: Option<&str>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let new_name = sanitize_half_width_title(new_name);
|
||||
let new_fw_name = if let Some(name) = new_fw_name {
|
||||
Some(sanitize_full_width_title(name))
|
||||
|
@ -384,40 +413,47 @@ impl NetMDContext {
|
|||
if has_fw_groups {
|
||||
if has_fw_groups_and_title {
|
||||
let re = Regex::new("/^0;.*?///").unwrap();
|
||||
new_fw_name_with_groups = re.replace_all(
|
||||
new_fw_name_with_groups = re
|
||||
.replace_all(
|
||||
&old_raw_fw_name,
|
||||
if !new_fw_name.as_ref().unwrap().is_empty() {
|
||||
format!("0;{}//", new_fw_name.unwrap())
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
).into()
|
||||
},
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
new_fw_name_with_groups = format!(r"0;{}//{}", new_fw_name.unwrap(), old_raw_fw_name);
|
||||
new_fw_name_with_groups =
|
||||
format!(r"0;{}//{}", new_fw_name.unwrap(), old_raw_fw_name);
|
||||
}
|
||||
} else {
|
||||
new_fw_name_with_groups = new_fw_name.unwrap();
|
||||
}
|
||||
|
||||
self.interface.set_disc_title(&new_fw_name_with_groups, true).await?;
|
||||
self.interface
|
||||
.set_disc_title(&new_fw_name_with_groups, true)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if new_name == old_name {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let new_name_with_groups;
|
||||
if has_groups {
|
||||
if has_groups_and_title {
|
||||
let re = Regex::new(r"/^0;.*?\/\//").unwrap();
|
||||
new_name_with_groups = re.replace_all(
|
||||
new_name_with_groups = re
|
||||
.replace_all(
|
||||
&old_raw_name,
|
||||
if !new_name.is_empty() {
|
||||
format!("0;{}//", new_name)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
).into()
|
||||
},
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
new_name_with_groups = format!("0;{}//{}", new_name, old_raw_name);
|
||||
}
|
||||
|
@ -425,7 +461,9 @@ impl NetMDContext {
|
|||
new_name_with_groups = new_name
|
||||
}
|
||||
|
||||
self.interface.set_disc_title(&new_name_with_groups, false).await?;
|
||||
self.interface
|
||||
.set_disc_title(&new_name_with_groups, false)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -433,10 +471,13 @@ impl NetMDContext {
|
|||
pub async fn upload<F: Fn(usize, usize)>(
|
||||
&mut self,
|
||||
track: u16,
|
||||
progress_callback: Option<F>
|
||||
progress_callback: Option<F>,
|
||||
) -> Result<(DiscFormat, Vec<u8>), Box<dyn Error>> {
|
||||
let mut output_vec = Vec::new();
|
||||
let (format, _frames, result) = self.interface.save_track_to_array(track, progress_callback).await?;
|
||||
let (format, _frames, result) = self
|
||||
.interface
|
||||
.save_track_to_array(track, progress_callback)
|
||||
.await?;
|
||||
|
||||
let header;
|
||||
match format {
|
||||
|
@ -448,10 +489,10 @@ impl NetMDContext {
|
|||
..Default::default()
|
||||
};
|
||||
header = create_aea_header(aea_options);
|
||||
},
|
||||
}
|
||||
DiscFormat::LP2 | DiscFormat::LP4 => {
|
||||
header = create_wav_header(format, result.len() as u32);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
output_vec.extend_from_slice(&header);
|
||||
|
@ -462,7 +503,8 @@ impl NetMDContext {
|
|||
|
||||
pub async fn prepare_download(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(
|
||||
&self.device_status()
|
||||
&self
|
||||
.device_status()
|
||||
.await?
|
||||
.state
|
||||
.unwrap_or(OperatingStatus::NoDisc),
|
||||
|
|
|
@ -73,7 +73,5 @@ pub fn new_thread_encryptor(
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
rx
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ use crate::netmd::base;
|
|||
use crate::netmd::query_utils::{format_query, scan_query, QueryValue};
|
||||
use crate::netmd::utils::{
|
||||
half_width_to_full_width_range, length_after_encoding_to_sjis, sanitize_full_width_title,
|
||||
sanitize_half_width_title,
|
||||
RawTime,
|
||||
sanitize_half_width_title, RawTime,
|
||||
};
|
||||
use cbc::cipher::block_padding::NoPadding;
|
||||
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit};
|
||||
|
@ -12,9 +11,9 @@ use encoding_rs::SHIFT_JIS;
|
|||
use num_derive::FromPrimitive;
|
||||
use rand::RngCore;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
use std::error::Error;
|
||||
use tokio::sync::mpsc::UnboundedReceiver;
|
||||
|
||||
use super::base::NetMD;
|
||||
|
@ -318,7 +317,8 @@ impl NetMDInterface {
|
|||
self.change_descriptor_state(
|
||||
&Descriptor::DiscSubunitIdentifier,
|
||||
&DescriptorAction::OpenRead,
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut query = format_query("1809 00 ff00 0000 0000".to_string(), vec![])?;
|
||||
|
||||
|
@ -450,7 +450,11 @@ impl NetMDInterface {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
async fn send_command(&mut self, query: &mut Vec<u8>, test: bool) -> Result<(), InterfaceError> {
|
||||
async fn send_command(
|
||||
&mut self,
|
||||
query: &mut Vec<u8>,
|
||||
test: bool,
|
||||
) -> Result<(), InterfaceError> {
|
||||
let status_byte = match test {
|
||||
true => NetmdStatus::GeneralInquiry,
|
||||
false => NetmdStatus::Control,
|
||||
|
@ -479,7 +483,9 @@ impl NetMDInterface {
|
|||
NetmdStatus::NotImplemented => {
|
||||
return Err(InterfaceError::NotImplemented(format!("{:02X?}", data)))
|
||||
}
|
||||
NetmdStatus::Rejected => return Err(InterfaceError::Rejected(format!("{:02X?}", data))),
|
||||
NetmdStatus::Rejected => {
|
||||
return Err(InterfaceError::Rejected(format!("{:02X?}", data)))
|
||||
}
|
||||
NetmdStatus::Interim if !accept_interim => {
|
||||
let sleep_time = Self::INTERIM_RESPONSE_RETRY_INTERVAL
|
||||
* (u32::pow(2, current_attempt as u32) - 1);
|
||||
|
@ -571,7 +577,8 @@ impl NetMDInterface {
|
|||
self.change_descriptor_state(
|
||||
&Descriptor::OperatingStatusBlock,
|
||||
&DescriptorAction::OpenRead,
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut query = format_query(
|
||||
"1809 8001 0230 8800 0030 8804 00 ff00 00000000".to_string(),
|
||||
|
@ -693,11 +700,9 @@ impl NetMDInterface {
|
|||
|
||||
let reply = match self.send_query(&mut query, false, false).await {
|
||||
Ok(result) => result,
|
||||
Err(e) => {
|
||||
match e {
|
||||
Err(e) => match e {
|
||||
InterfaceError::Rejected(_) => Vec::new(),
|
||||
_ => return Err(e)
|
||||
}
|
||||
_ => return Err(e),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1000,9 +1005,10 @@ impl NetMDInterface {
|
|||
let mut track_list: Vec<u16> = Vec::new();
|
||||
for track in track_min - 1..track_max {
|
||||
if track_dict.contains_key(&track) {
|
||||
return Err(
|
||||
InterfaceError::GroupError(format!("track {} is in 2 groups", track))
|
||||
);
|
||||
return Err(InterfaceError::GroupError(format!(
|
||||
"track {} is in 2 groups",
|
||||
track
|
||||
)));
|
||||
}
|
||||
track_dict.insert(track, (String::from(group_name), i as u16));
|
||||
track_list.push(track);
|
||||
|
@ -1313,15 +1319,15 @@ impl NetMDInterface {
|
|||
}
|
||||
|
||||
/// Gets the length of a track as a raw duration
|
||||
pub async fn track_length(
|
||||
&mut self,
|
||||
track: u16,
|
||||
) -> Result<RawTime, InterfaceError> {
|
||||
pub async fn track_length(&mut self, track: u16) -> Result<RawTime, InterfaceError> {
|
||||
Ok(self.track_lengths([track].into()).await?[0])
|
||||
}
|
||||
|
||||
/// Gets the encoding of a track (SP, LP2, LP4)
|
||||
pub async fn track_encoding(&mut self, track_number: u16) -> Result<(Encoding, Channels), InterfaceError> {
|
||||
pub async fn track_encoding(
|
||||
&mut self,
|
||||
track_number: u16,
|
||||
) -> Result<(Encoding, Channels), InterfaceError> {
|
||||
let raw_value = self.raw_track_info(track_number, 0x3080, 0x0700).await?;
|
||||
let result = scan_query(raw_value, "07 0004 0110 %b %b".to_string())?;
|
||||
|
||||
|
@ -1421,7 +1427,7 @@ impl NetMDInterface {
|
|||
pub async fn save_track_to_array<F: Fn(usize, usize)>(
|
||||
&mut self,
|
||||
track: u16,
|
||||
progress_callback: Option<F>
|
||||
progress_callback: Option<F>,
|
||||
) -> Result<(DiscFormat, u16, Vec<u8>), InterfaceError> {
|
||||
let mut query = format_query(
|
||||
"1800 080046 f003010330 ff00 1001 %w".to_string(),
|
||||
|
@ -1439,7 +1445,10 @@ impl NetMDInterface {
|
|||
let codec = res[1].to_i64().unwrap() as u8;
|
||||
let length = res[2].to_i64().unwrap() as usize;
|
||||
|
||||
let result = self.device.read_bulk(length, 0x10000, progress_callback).await?;
|
||||
let result = self
|
||||
.device
|
||||
.read_bulk(length, 0x10000, progress_callback)
|
||||
.await?;
|
||||
|
||||
scan_query(
|
||||
self.read_reply(false).await?,
|
||||
|
@ -1545,7 +1554,10 @@ impl NetMDInterface {
|
|||
hostnonce: Vec<u8>,
|
||||
) -> Result<Vec<u8>, InterfaceError> {
|
||||
if hostnonce.len() != 8 {
|
||||
return Err(EncryptionError::InvalidLength("host nonce", hostnonce.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"host nonce",
|
||||
hostnonce.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
let mut query = format_query(
|
||||
|
@ -1576,13 +1588,22 @@ impl NetMDInterface {
|
|||
hex_session_key: &[u8],
|
||||
) -> Result<(), InterfaceError> {
|
||||
if contentid.len() != 20 {
|
||||
return Err(EncryptionError::InvalidLength("content ID", contentid.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"content ID",
|
||||
contentid.len(),
|
||||
))?;
|
||||
}
|
||||
if keyenckey.len() != 8 {
|
||||
return Err(EncryptionError::InvalidLength("key encryption", keyenckey.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"key encryption",
|
||||
keyenckey.len(),
|
||||
))?;
|
||||
}
|
||||
if hex_session_key.len() != 8 {
|
||||
return Err(EncryptionError::InvalidLength("session key", hex_session_key.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"session key",
|
||||
hex_session_key.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
let mut message = [vec![1, 1, 1, 1], contentid.to_vec(), keyenckey.to_vec()].concat();
|
||||
|
@ -1608,7 +1629,10 @@ impl NetMDInterface {
|
|||
hex_session_key: &[u8],
|
||||
) -> Result<(), InterfaceError> {
|
||||
if hex_session_key.len() != 8 {
|
||||
return Err(EncryptionError::InvalidLength("hex session key", hex_session_key.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"hex session key",
|
||||
hex_session_key.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
let mut message = [0u8; 8];
|
||||
|
@ -1647,7 +1671,10 @@ impl NetMDInterface {
|
|||
F: Fn(usize, usize),
|
||||
{
|
||||
if hex_session_key.len() != 8 {
|
||||
return Err(EncryptionError::InvalidLength("hex session key", hex_session_key.len()))?;
|
||||
return Err(EncryptionError::InvalidLength(
|
||||
"hex session key",
|
||||
hex_session_key.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
// Sharps are slow
|
||||
|
|
|
@ -8,7 +8,7 @@ use thiserror::Error;
|
|||
/// %* - raw Uint8Array
|
||||
/// %B - BCD-encoded 1-byte number
|
||||
/// %W - BCD-encoded 2-byte number
|
||||
static FORMAT_TYPE_LEN_DICT: phf::Map<char, i32> = phf::phf_map!{
|
||||
static FORMAT_TYPE_LEN_DICT: phf::Map<char, i32> = phf::phf_map! {
|
||||
'b' => 1, // byte
|
||||
'w' => 2, // word
|
||||
'd' => 4, // doubleword
|
||||
|
@ -26,10 +26,7 @@ pub enum QueryValue {
|
|||
#[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum ValueError {
|
||||
#[error("type mismatch: expected {expected}, got {actual}")]
|
||||
TypeMismatch {
|
||||
expected: String,
|
||||
actual: String
|
||||
}
|
||||
TypeMismatch { expected: String, actual: String },
|
||||
}
|
||||
|
||||
impl QueryValue {
|
||||
|
@ -45,10 +42,10 @@ impl QueryValue {
|
|||
array[i] = *byte
|
||||
}
|
||||
Ok(array)
|
||||
},
|
||||
}
|
||||
_ => Err(ValueError::TypeMismatch {
|
||||
expected: String::from("Vec<u8>"),
|
||||
actual: format!("{:?}", self)
|
||||
actual: format!("{:?}", self),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +55,7 @@ impl QueryValue {
|
|||
QueryValue::Array(a) => Ok(a.to_vec()),
|
||||
_ => Err(ValueError::TypeMismatch {
|
||||
expected: String::from("Vec<u8>"),
|
||||
actual: format!("{:?}", self)
|
||||
actual: format!("{:?}", self),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +65,7 @@ impl QueryValue {
|
|||
QueryValue::Number(a) => Ok(*a),
|
||||
_ => Err(ValueError::TypeMismatch {
|
||||
expected: String::from("i64"),
|
||||
actual: format!("{:?}", self)
|
||||
actual: format!("{:?}", self),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +79,7 @@ impl TryInto<i64> for QueryValue {
|
|||
QueryValue::Number(a) => Ok(a),
|
||||
_ => Err(ValueError::TypeMismatch {
|
||||
expected: String::from("i64"),
|
||||
actual: format!("{:?}", self)
|
||||
actual: format!("{:?}", self),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +96,7 @@ pub enum QueryError {
|
|||
expected: u8,
|
||||
actual: u8,
|
||||
format_string: String,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/// Formats a query using a standard input to send to the player
|
||||
|
@ -198,10 +195,7 @@ pub fn format_query(format: String, args: Vec<QueryValue>) -> Result<Vec<u8>, Qu
|
|||
}
|
||||
|
||||
/// Scans a result using a standard input to recieve from the player
|
||||
pub fn scan_query(
|
||||
query_result: Vec<u8>,
|
||||
format: String,
|
||||
) -> Result<Vec<QueryValue>, QueryError> {
|
||||
pub fn scan_query(query_result: Vec<u8>, format: String) -> Result<Vec<QueryValue>, QueryError> {
|
||||
let mut result: Vec<QueryValue> = Vec::new();
|
||||
|
||||
let initial_length = query_result.len();
|
||||
|
@ -307,7 +301,7 @@ pub fn scan_query(
|
|||
index: i,
|
||||
expected: format_value,
|
||||
actual: input_value,
|
||||
format_string: format
|
||||
format_string: format,
|
||||
});
|
||||
}
|
||||
half = None;
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
use crate::netmd::mappings::{ALLOWED_HW_KANA, MAPPINGS_DE, MAPPINGS_HW, MAPPINGS_JP, MAPPINGS_RU};
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use diacritics;
|
||||
use encoding_rs::SHIFT_JIS;
|
||||
use regex::Regex;
|
||||
use std::{error::Error, io::Write, time::Duration, vec::IntoIter};
|
||||
use unicode_normalization::UnicodeNormalization;
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
extern crate kana;
|
||||
use kana::*;
|
||||
|
||||
use super::{interface::DiscFormat, mappings::{HW_TO_FW_RANGE_MAP, MULTI_BYTE_CHARS}};
|
||||
use super::{
|
||||
interface::DiscFormat,
|
||||
mappings::{HW_TO_FW_RANGE_MAP, MULTI_BYTE_CHARS},
|
||||
};
|
||||
|
||||
/// Sleep for a specified [Duration] on any platform
|
||||
pub async fn cross_sleep(duration: Duration) {
|
||||
|
@ -87,9 +90,11 @@ fn check(string: String) -> Option<String> {
|
|||
}
|
||||
|
||||
pub fn half_width_title_length(title: &str) -> usize {
|
||||
let multibyte_len = title.chars()
|
||||
let multibyte_len = title
|
||||
.chars()
|
||||
.map(|c| (*MULTI_BYTE_CHARS.get(&c).unwrap_or(&0) as usize))
|
||||
.reduce(|a, b| a + b).unwrap_or_default();
|
||||
.reduce(|a, b| a + b)
|
||||
.unwrap_or_default();
|
||||
|
||||
title.len() + multibyte_len
|
||||
}
|
||||
|
@ -174,7 +179,7 @@ pub struct AeaOptions<'a> {
|
|||
pub flags: &'a [u8],
|
||||
}
|
||||
|
||||
impl <'a> Default for AeaOptions<'a> {
|
||||
impl<'a> Default for AeaOptions<'a> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: "",
|
||||
|
@ -182,7 +187,7 @@ impl <'a> Default for AeaOptions<'a> {
|
|||
sound_groups: 1,
|
||||
group_start: 0,
|
||||
encrypted: 0,
|
||||
flags: &[0, 0, 0, 0, 0, 0, 0, 0]
|
||||
flags: &[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,24 +199,48 @@ pub fn create_aea_header(options: AeaOptions) -> Vec<u8> {
|
|||
|
||||
header.write_u32::<LittleEndian>(2048).unwrap();
|
||||
header.write_all(encoded_name).unwrap();
|
||||
header.write_all(&vec![0; 256 - encoded_name.len()]).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.sound_groups as u32).unwrap();
|
||||
header
|
||||
.write_all(&vec![0; 256 - encoded_name.len()])
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.sound_groups as u32)
|
||||
.unwrap();
|
||||
header.write_all(&[options.channels as u8, 0]).unwrap();
|
||||
|
||||
// Write the flags
|
||||
header.write_u32::<LittleEndian>(options.flags[0] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[1] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[2] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[3] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[4] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[5] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[6] as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.flags[7] as u32).unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[0] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[1] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[2] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[3] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[4] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[5] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[6] as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.flags[7] as u32)
|
||||
.unwrap();
|
||||
|
||||
header.write_u32::<LittleEndian>(0).unwrap();
|
||||
|
||||
header.write_u32::<LittleEndian>(options.encrypted as u32).unwrap();
|
||||
header.write_u32::<LittleEndian>(options.group_start as u32).unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.encrypted as u32)
|
||||
.unwrap();
|
||||
header
|
||||
.write_u32::<LittleEndian>(options.group_start as u32)
|
||||
.unwrap();
|
||||
|
||||
// return the header
|
||||
header
|
||||
|
@ -223,7 +252,7 @@ pub fn create_wav_header(format: DiscFormat, bytes: u32) -> Vec<u8> {
|
|||
let (joint_stereo, bytes_per_frame) = match format {
|
||||
DiscFormat::LP4 => (192, 0),
|
||||
DiscFormat::LP2 => (96, 1),
|
||||
_ => unreachable!("Cannot create WAV header for disc type {:?}", format)
|
||||
_ => unreachable!("Cannot create WAV header for disc type {:?}", format),
|
||||
};
|
||||
|
||||
let bytes_per_second = (bytes_per_frame * 44100) / 512;
|
||||
|
@ -236,7 +265,9 @@ pub fn create_wav_header(format: DiscFormat, bytes: u32) -> Vec<u8> {
|
|||
header.write_u16::<LittleEndian>(2).unwrap(); // Stereo
|
||||
header.write_u32::<LittleEndian>(44100).unwrap();
|
||||
header.write_u32::<LittleEndian>(bytes_per_second).unwrap();
|
||||
header.write_u16::<LittleEndian>(bytes_per_frame as u16 * 2).unwrap();
|
||||
header
|
||||
.write_u16::<LittleEndian>(bytes_per_frame as u16 * 2)
|
||||
.unwrap();
|
||||
|
||||
header.write_all(&[0, 0]).unwrap();
|
||||
|
||||
|
@ -273,7 +304,10 @@ impl Into<Duration> for RawTime {
|
|||
impl RawTime {
|
||||
pub fn as_duration(&self) -> Duration {
|
||||
std::time::Duration::from_micros(
|
||||
(self.hours * 3600000000) + (self.minutes * 60000000) + (self.seconds * 1000000) + (self.frames * 11600),
|
||||
(self.hours * 3600000000)
|
||||
+ (self.minutes * 60000000)
|
||||
+ (self.seconds * 1000000)
|
||||
+ (self.frames * 11600),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue