From 72e13b92f9ac4503776f0df03d4aa451c3389459 Mon Sep 17 00:00:00 2001 From: G2-Games Date: Tue, 28 May 2024 22:02:16 -0500 Subject: [PATCH] Ran `cargo fmt` --- src/lib.rs | 1 - src/netmd/base.rs | 297 ++++++++++++++++++++++++++++++++------- src/netmd/commands.rs | 212 +++++++++++++++++----------- src/netmd/encryption.rs | 2 - src/netmd/interface.rs | 83 +++++++---- src/netmd/query_utils.rs | 26 ++-- src/netmd/utils.rs | 76 +++++++--- 7 files changed, 490 insertions(+), 207 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8318a73..1c64b5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/netmd/base.rs b/src/netmd/base.rs index d76aeaa..63fa07c 100644 --- a/src/netmd/base.rs +++ b/src/netmd/base.rs @@ -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> = Lazy::new(|| { - DEVICE_IDS.iter().map(|d|{ - cross_usb::device_filter! { - vendor_id: d.vendor_id, - product_id: d.product_id, - } - }).collect() + DEVICE_IDS + .iter() + .map(|d| { + cross_usb::device_filter! { + vendor_id: d.vendor_id, + product_id: d.product_id, + } + }) + .collect() }); /// The current status of the Minidisc device @@ -311,7 +498,9 @@ impl NetMD { chunksize: usize, progress_callback: Option, ) -> Result, 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) } diff --git a/src/netmd/commands.rs b/src/netmd/commands.rs index 1d6eb9c..6c01299 100644 --- a/src/netmd/commands.rs +++ b/src/netmd/commands.rs @@ -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 { - 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, - { - if group.tracks.len() - 1 != 0 { - format!("-{}", max_group_index + 1) - } else { - String::from("") - } + 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 { let interface = NetMDInterface::new(device).await?; - Ok(Self { - interface, - }) + Ok(Self { interface }) } /// Change to the next track (skip forward) @@ -313,27 +340,23 @@ 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 { - index: *track, - title, - full_width_title, - duration, - channel, - encoding, - protected: TrackFlag::from_u8(flags).unwrap(), - } - ) + tracks.push(Track { + index: *track, + title, + full_width_title, + duration, + channel, + encoding, + protected: TrackFlag::from_u8(flags).unwrap(), + }) } - groups.push( - Group { - index: index as u16, - title: group.0.clone(), - full_width_title: group.1.clone(), - tracks - } - ) + groups.push(Group { + index: index as u16, + title: group.0.clone(), + full_width_title: group.1.clone(), + 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> { + pub async fn rename_disc( + &mut self, + new_name: &str, + new_fw_name: Option<&str>, + ) -> Result<(), Box> { 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( - &old_raw_fw_name, - if !new_fw_name.as_ref().unwrap().is_empty() { - format!("0;{}//", new_fw_name.unwrap()) - } else { - String::new() - } - ).into() + 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() } 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( - &old_raw_name, - if !new_name.is_empty() { - format!("0;{}//", new_name) - } else { - String::new() - } - ).into() + new_name_with_groups = re + .replace_all( + &old_raw_name, + if !new_name.is_empty() { + format!("0;{}//", new_name) + } else { + String::new() + }, + ) + .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( &mut self, track: u16, - progress_callback: Option + progress_callback: Option, ) -> Result<(DiscFormat, Vec), Box> { 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> { while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains( - &self.device_status() + &self + .device_status() .await? .state .unwrap_or(OperatingStatus::NoDisc), diff --git a/src/netmd/encryption.rs b/src/netmd/encryption.rs index d51bd1c..285dc6c 100644 --- a/src/netmd/encryption.rs +++ b/src/netmd/encryption.rs @@ -73,7 +73,5 @@ pub fn new_thread_encryptor( } }); - - rx } diff --git a/src/netmd/interface.rs b/src/netmd/interface.rs index 09bd860..4430ebb 100644 --- a/src/netmd/interface.rs +++ b/src/netmd/interface.rs @@ -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, test: bool) -> Result<(), InterfaceError> { + async fn send_command( + &mut self, + query: &mut Vec, + 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 { - InterfaceError::Rejected(_) => Vec::new(), - _ => return Err(e) - } + Err(e) => match e { + InterfaceError::Rejected(_) => Vec::new(), + _ => return Err(e), }, }; @@ -1000,9 +1005,10 @@ impl NetMDInterface { let mut track_list: Vec = 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 { + pub async fn track_length(&mut self, track: u16) -> Result { 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( &mut self, track: u16, - progress_callback: Option + progress_callback: Option, ) -> Result<(DiscFormat, u16, Vec), 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, ) -> Result, 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 diff --git a/src/netmd/query_utils.rs b/src/netmd/query_utils.rs index 9be698e..f9aeb96 100644 --- a/src/netmd/query_utils.rs +++ b/src/netmd/query_utils.rs @@ -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 = phf::phf_map!{ +static FORMAT_TYPE_LEN_DICT: phf::Map = 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"), - 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"), - 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 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) -> Result, Qu } /// Scans a result using a standard input to recieve from the player -pub fn scan_query( - query_result: Vec, - format: String, -) -> Result, QueryError> { +pub fn scan_query(query_result: Vec, format: String) -> Result, QueryError> { let mut result: Vec = 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; diff --git a/src/netmd/utils.rs b/src/netmd/utils.rs index 26cd0c2..1b7ed77 100644 --- a/src/netmd/utils.rs +++ b/src/netmd/utils.rs @@ -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 { } 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 { header.write_u32::(2048).unwrap(); header.write_all(encoded_name).unwrap(); - header.write_all(&vec![0; 256 - encoded_name.len()]).unwrap(); - header.write_u32::(options.sound_groups as u32).unwrap(); + header + .write_all(&vec![0; 256 - encoded_name.len()]) + .unwrap(); + header + .write_u32::(options.sound_groups as u32) + .unwrap(); header.write_all(&[options.channels as u8, 0]).unwrap(); // Write the flags - header.write_u32::(options.flags[0] as u32).unwrap(); - header.write_u32::(options.flags[1] as u32).unwrap(); - header.write_u32::(options.flags[2] as u32).unwrap(); - header.write_u32::(options.flags[3] as u32).unwrap(); - header.write_u32::(options.flags[4] as u32).unwrap(); - header.write_u32::(options.flags[5] as u32).unwrap(); - header.write_u32::(options.flags[6] as u32).unwrap(); - header.write_u32::(options.flags[7] as u32).unwrap(); + header + .write_u32::(options.flags[0] as u32) + .unwrap(); + header + .write_u32::(options.flags[1] as u32) + .unwrap(); + header + .write_u32::(options.flags[2] as u32) + .unwrap(); + header + .write_u32::(options.flags[3] as u32) + .unwrap(); + header + .write_u32::(options.flags[4] as u32) + .unwrap(); + header + .write_u32::(options.flags[5] as u32) + .unwrap(); + header + .write_u32::(options.flags[6] as u32) + .unwrap(); + header + .write_u32::(options.flags[7] as u32) + .unwrap(); header.write_u32::(0).unwrap(); - header.write_u32::(options.encrypted as u32).unwrap(); - header.write_u32::(options.group_start as u32).unwrap(); + header + .write_u32::(options.encrypted as u32) + .unwrap(); + header + .write_u32::(options.group_start as u32) + .unwrap(); // return the header header @@ -223,7 +252,7 @@ pub fn create_wav_header(format: DiscFormat, bytes: u32) -> Vec { 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 { header.write_u16::(2).unwrap(); // Stereo header.write_u32::(44100).unwrap(); header.write_u32::(bytes_per_second).unwrap(); - header.write_u16::(bytes_per_frame as u16 * 2).unwrap(); + header + .write_u16::(bytes_per_frame as u16 * 2) + .unwrap(); header.write_all(&[0, 0]).unwrap(); @@ -273,7 +304,10 @@ impl Into 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), ) }