diff --git a/.gitignore b/.gitignore index 6985cf1..3ae9ed4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,11 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +# Stuff from various IDEs +.idea/ +*.kate-swp + +# Flamegraph things +flamegraph.svg +perf.data* diff --git a/minidisc-rs/src/lib.rs b/minidisc-rs/src/lib.rs index 2a4ca9f..3eb0d66 100644 --- a/minidisc-rs/src/lib.rs +++ b/minidisc-rs/src/lib.rs @@ -1,8 +1,7 @@ -//! This crate is an interface in rust to control NetMD and Hi-MD minidisc devices. -//! -//! Documentation coming soon +/*! + * This crate is an interface in rust to control NetMD and Hi-MD minidisc devices. + * + * Documentation coming soon + */ -/// This is a test pub mod netmd; - -use netmd::interface::NetMDInterface; diff --git a/minidisc-rs/src/netmd/interface.rs b/minidisc-rs/src/netmd/interface.rs index 03725a4..d4ff8cf 100644 --- a/minidisc-rs/src/netmd/interface.rs +++ b/minidisc-rs/src/netmd/interface.rs @@ -938,6 +938,47 @@ impl NetMDInterface { .into()) } + pub fn all_track_titles(&self, wchar: bool) -> Result, Box> { + let wchar_value = match wchar { + true => 3, + false => 2, + }; + + let descriptor_type = match wchar { + true => Descriptor::AudioUTOC4TD, + false => Descriptor::AudioUTOC1TD, + }; + + self.change_descriptor_state(&descriptor_type, &DescriptorAction::OpenRead); + + let mut track_titles: Vec = vec![]; + for i in 0..self.track_count().unwrap() { + + let mut query = format_query( + "1806 022018%b %w 3000 0a00 ff00 00000000".to_string(), + vec![QueryValue::Number(wchar_value), QueryValue::Number(i as i64)], + ) + .unwrap(); + + let reply = self.send_query(&mut query, false, false)?; + + let res = scan_query( + reply, + "1806 022018%? %?%? %?%? %?%? 1000 00%?0000 00%?000a %x".to_string(), + ) + .unwrap(); + + track_titles.push(encoding_rs::SHIFT_JIS + .decode(&res[0].to_vec().unwrap()) + .0 + .into()) + } + + self.change_descriptor_state(&descriptor_type, &DescriptorAction::Close); + + Ok(track_titles) + } + // Sets the title of the disc pub fn set_disc_title(&self, title: String, wchar: bool) -> Result<(), Box> { let current_title = self._disc_title(wchar)?; @@ -1086,11 +1127,42 @@ impl NetMDInterface { let reply = self.send_query(&mut query, false, false)?; let res = scan_query(reply, "1806 02201001 %?%? %?%? %?%? 1000 00%?0000 %x".to_string())?; - self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead); + self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::Close); return Ok(res[0].to_vec().unwrap()); } + pub fn all_track_length(&self) -> Result, Box> { + let mut times: Vec = vec![]; + + self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead); + for track in 0..self.track_count()? { + let mut query = format_query( + "1806 02201001 %w %w %w ff00 00000000".to_string(), + vec![ + QueryValue::Number(track as i64), + QueryValue::Number(0x3000), + QueryValue::Number(0x0100), + ], + )?; + + let reply = self.send_query(&mut query, false, false)?; + + let res = scan_query(reply, "1806 02201001 %?%? %?%? %?%? 1000 00%?0000 %x".to_string())?; + + let result = scan_query(res[0].to_vec().unwrap(), "01 0006 0000 %B %B %B %B".to_string())?; + + let times_num: Vec = result.into_iter().map(|v| v.to_i64().unwrap() as u64).collect(); + + let time_micros = (times_num[0] * 3600000000) + (times_num[1] * 60000000) + (times_num[2] * 1000000) + (times_num[3] * 11600); + times.push(std::time::Duration::from_micros(time_micros)); + } + + self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::Close); + + Ok(times) + } + /// Gets the length of a track as a `std::time::Duration` pub fn track_length(&self, track_number: u16) -> Result> { let raw_value = self._get_track_info(track_number, 0x3000, 0x0100)?; diff --git a/minidisc-rs/src/netmd/mod.rs b/minidisc-rs/src/netmd/mod.rs index ecfc941..af8d317 100644 --- a/minidisc-rs/src/netmd/mod.rs +++ b/minidisc-rs/src/netmd/mod.rs @@ -1,3 +1,9 @@ +/*! + * This crate is an interface in rust to control NetMD and Hi-MD minidisc devices. + * + * Documentation coming soon + */ + mod base; pub mod interface; mod query_utils; diff --git a/minidisc-rs/src/netmd/query_utils.rs b/minidisc-rs/src/netmd/query_utils.rs index 0dce538..611ab51 100644 --- a/minidisc-rs/src/netmd/query_utils.rs +++ b/minidisc-rs/src/netmd/query_utils.rs @@ -3,17 +3,7 @@ use once_cell::sync::Lazy; use std::collections::hash_map::HashMap; use std::error::Error; -// prettier-ignore -const FORMAT_TYPE_LEN_DICT: Lazy> = Lazy::new(|| { - HashMap::from([ - ('b', 1), // byte - ('w', 2), // word - ('d', 4), // doubleword - ('q', 8), // quadword - ]) -}); - -/* +/** %b, w, d, q - explained above (can have endiannes overriden by '>' and '<' operators, f. ex. %>d %> = Lazy::new(|| { %W - BCD-encoded 2-byte number */ +const FORMAT_TYPE_LEN_DICT: Lazy> = Lazy::new(|| { + HashMap::from([ + ('b', 1), // byte + ('w', 2), // word + ('d', 4), // doubleword + ('q', 8), // quadword + ]) +}); + const DEBUG: bool = false; #[derive(Clone, Debug)] diff --git a/minidisc-rs/src/netmd/utils.rs b/minidisc-rs/src/netmd/utils.rs index f7f46d3..23fa35c 100644 --- a/minidisc-rs/src/netmd/utils.rs +++ b/minidisc-rs/src/netmd/utils.rs @@ -107,6 +107,8 @@ pub fn sanitize_half_width_title(mut title: String) -> Vec { title = hira2kata(&title); title = combine(&title); + println!("{}", title); + let new_title: String = title .chars() .map(|c| { diff --git a/src/main.rs b/src/main.rs index 73c2df0..c572242 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,34 +27,49 @@ fn main() { Err(_) => continue }; + println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); println!( "Player Model: {}", player_controller.net_md_device.device_name().clone().unwrap() ); - println!("Track Count: {:?}", player_controller.track_count().unwrap()); + //println!("TEST CASE: {:?}", player_controller.set_track_title(3, "初音ミクの消失".to_string(), false).unwrap()); - println!("TEST CASE: {:?}", player_controller.disc_capacity().unwrap()); + let now = std::time::SystemTime::now(); + let times = player_controller.all_track_length().unwrap(); + let titles_hw = player_controller.all_track_titles(false).unwrap(); + let titles_fw = player_controller.all_track_titles(true).unwrap(); + + /* + let now = std::time::SystemTime::now(); + for i in 0..player_controller.track_count().unwrap() { + player_controller.track_length(i as u16); + player_controller.track_title(i as u16, false); + player_controller.track_title(i as u16, true); + } + println!("Individual: {}ms", now.elapsed().unwrap().as_millis()); + */ println!( - "Disc Title: {: >18} | {}\n-----------------------------------------------------------------", + "━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━ + Tracks: │ {: <21} │ + Disc Title: │ {: >21} │ {} +────┬──────────┼───────────────────────┼─────────────────────────", + player_controller.track_count().unwrap(), player_controller.disc_title(false).unwrap(), player_controller.disc_title(true).unwrap() ); - let mut total = 0; for i in 0..player_controller.track_count().unwrap() { println!( - "{: >2} | {:0>2}:{:0>2}:{:0>2} | {:?} : {: >21} | {}", + " {: >2} │ {:0>2}:{:0>2}:{:0>2} │ {: >21} │ {}", i + 1, - (player_controller.track_length(i as u16).unwrap().as_secs() / 60) / 60, - (player_controller.track_length(i as u16).unwrap().as_secs() / 60) % 60, - player_controller.track_length(i as u16).unwrap().as_secs() % 60, - player_controller.track_encoding(i as u16).unwrap(), - player_controller.track_title(i as u16, false).unwrap(), - player_controller.track_title(i as u16, true).unwrap() + (times[i as usize].as_secs() / 60) / 60, + (times[i as usize].as_secs() / 60) % 60, + times[i as usize].as_secs() % 60, + titles_hw[i as usize], + titles_fw[i as usize] ); - total += player_controller.track_length(i as u16).unwrap().as_secs(); } - println!("{}", total); + println!("────┴──────────┴───────────────────────┴─────────────────────────\nFinished in: [{}ms]", now.elapsed().unwrap().as_millis()); } }