Added disc information getting, ran cargo fmt

This commit is contained in:
G2-Games 2023-09-23 19:39:51 -05:00
parent 4a76d96341
commit d65b859886
5 changed files with 261 additions and 38 deletions

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
bcd-numbers = "1.0.11" bcd-numbers = "1.0.11"
encoding_rs = "0.8.33"
nofmt = "1.0.0" nofmt = "1.0.0"
once_cell = "1.18.0" once_cell = "1.18.0"
rusb = "0.9.3" rusb = "0.9.3"

View file

@ -32,20 +32,10 @@ fn main() {
player_controller.net_md_device.device_name().unwrap() player_controller.net_md_device.device_name().unwrap()
); );
println!("{:?}", player_controller.get_position()); println!("Disc Flags? {:?}", player_controller.disc_flags());
println!("{:?}", player_controller.go_to_time(0, 0, 2, 0, 0)); println!("Track Count: {:?}", player_controller.track_count());
let _ = player_controller.play(); println!("Disc Title: {:?}", player_controller.disc_title(false));
thread::sleep(Duration::from_secs(5)); println!("Track Group List: {:?}", player_controller.track_group_list());
println!("{:?}", player_controller.get_position());
println!("{:?}", player_controller.go_to_time(10, 0, 1, 15, 0));
println!("{:?}", player_controller.get_position());
thread::sleep(Duration::from_secs(10));
println!("{:?}", player_controller.get_position());
thread::sleep(Duration::from_secs(5));
let _ = player_controller.stop();
/* /*
let mut request: [u8; 19] = [0x00, 0x18, 0x06, 0x02, 0x20, 0x18, let mut request: [u8; 19] = [0x00, 0x18, 0x06, 0x02, 0x20, 0x18,

View file

@ -160,7 +160,6 @@ impl NetMD {
}; };
let length_bytes = [poll_result[2], poll_result[3]]; let length_bytes = [poll_result[2], poll_result[3]];
println!("Poll result: {}", u16::from_le_bytes(length_bytes));
Ok((u16::from_le_bytes(length_bytes), poll_result)) Ok((u16::from_le_bytes(length_bytes), poll_result))
} }
@ -209,13 +208,20 @@ impl NetMD {
self._read_reply(false, override_length) self._read_reply(false, override_length)
} }
pub fn read_factory_reply(&self, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> { pub fn read_factory_reply(
&self,
override_length: Option<i32>,
) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(true, override_length) self._read_reply(true, override_length)
} }
/// Poll to see if a message is ready, /// Poll to see if a message is ready,
/// and if so, recieve it /// and if so, recieve it
fn _read_reply(&self, use_factory_command: bool, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> { fn _read_reply(
&self,
use_factory_command: bool,
override_length: Option<i32>,
) -> Result<Vec<u8>, Box<dyn Error>> {
let mut length = self.poll()?.0; let mut length = self.poll()?.0;
let mut current_attempt = 0; let mut current_attempt = 0;
@ -230,7 +236,7 @@ impl NetMD {
match override_length { match override_length {
Some(value) => length = value as u16, Some(value) => length = value as u16,
None => () None => (),
} }
let request = match use_factory_command { let request = match use_factory_command {

View file

@ -1,7 +1,10 @@
use crate::netmd::utils; use crate::netmd::utils;
use crate::NetMD; use crate::NetMD;
use encoding_rs::*;
use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::fmt;
use super::utils::half_width_to_full_width_range;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum Action { enum Action {
@ -411,15 +414,33 @@ impl NetMDInterface {
} }
fn acquire(&self) -> Result<(), Box<dyn Error>> { fn acquire(&self) -> Result<(), Box<dyn Error>> {
let mut query = vec![0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; let mut query = vec![
0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
];
let reply = self.send_query(&mut query, false, false)?; let reply = self.send_query(&mut query, false, false)?;
utils::check_result(reply, &[0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) utils::check_result(
reply,
&[
0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
],
)
} }
fn release(&self) -> Result<(), Box<dyn Error>> { fn release(&self) -> Result<(), Box<dyn Error>> {
let mut query = vec![0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; let mut query = vec![
0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
];
let reply = self.send_query(&mut query, false, false)?; let reply = self.send_query(&mut query, false, false)?;
utils::check_result(reply, &[0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) utils::check_result(
reply,
&[
0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
],
)
} }
fn status(&self) -> Result<Vec<u8>, Box<dyn Error>> { fn status(&self) -> Result<Vec<u8>, Box<dyn Error>> {
@ -504,18 +525,18 @@ impl NetMDInterface {
self.playback_status_query([0x88, 0x02], [0x88, 0x06]) self.playback_status_query([0x88, 0x02], [0x88, 0x06])
} }
pub fn get_position(&self) -> Result<[u16; 5], Box<dyn Error>> { pub fn position(&self) -> Result<[u16; 5], Box<dyn Error>> {
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead); self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead);
let mut query = vec![ let mut query = vec![
0x18, 0x09, 0x80, 0x01, 0x04, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30, 0x18, 0x09, 0x80, 0x01, 0x04, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30,
0x00, 0x03, 0x00, 0x30, 0x00, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x03, 0x00, 0x30, 0x00, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let reply = match self.send_query(&mut query, false, false) { let reply = match self.send_query(&mut query, false, false) {
Ok(result) => result, Ok(result) => result,
Err(e) if e.to_string() == "Rejected" => Vec::new(), Err(e) if e.to_string() == "Rejected" => Vec::new(),
Err(e) => return Err(e) Err(e) => return Err(e),
}; };
let track_number = u16::from_be_bytes([reply[35], reply[36]]); let track_number = u16::from_be_bytes([reply[35], reply[36]]);
@ -525,7 +546,13 @@ impl NetMDInterface {
let second = utils::byte_from_bcd(reply[39])?; let second = utils::byte_from_bcd(reply[39])?;
let frame = utils::byte_from_bcd(reply[40])?; let frame = utils::byte_from_bcd(reply[40])?;
let final_result = [track_number, hour as u16, minute as u16, second as u16, frame as u16]; let final_result = [
track_number,
hour as u16,
minute as u16,
second as u16,
frame as u16,
];
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close); self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close);
@ -542,13 +569,14 @@ impl NetMDInterface {
let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00]; let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00];
match self.send_query(&mut query, true, false) { match self.send_query(&mut query, true, false) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(error) => Err(error) Err(error) => Err(error),
} }
} }
/* Track control */
pub fn go_to_track(&self, track_number: u16) -> Result<u16, Box<dyn Error>> { pub fn go_to_track(&self, track_number: u16) -> Result<u16, Box<dyn Error>> {
let mut query = vec![0x18, 0x50, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, let mut query = vec![0x18, 0x50, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00];
0b00, 0b00];
let bytes = track_number.to_le_bytes(); let bytes = track_number.to_le_bytes();
@ -560,9 +588,17 @@ impl NetMDInterface {
Ok(u16::from_be_bytes([reply[8], reply[9]])) Ok(u16::from_be_bytes([reply[8], reply[9]]))
} }
pub fn go_to_time(&self, track_number: u16, hour: u8, minute: u8, second: u8, frame: u8) -> Result<u16, Box<dyn Error>> { pub fn go_to_time(
let mut query = vec![0x18, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, &self,
0b00, 0b00, 0b00, 0b00, 0b00, 0b00]; track_number: u16,
hour: u8,
minute: u8,
second: u8,
frame: u8,
) -> Result<u16, Box<dyn Error>> {
let mut query = vec![
0x18, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00, 0b00, 0b00, 0b00, 0b00,
];
let bytes = track_number.to_le_bytes(); let bytes = track_number.to_le_bytes();
query[8] = bytes[1]; query[8] = bytes[1];
@ -579,8 +615,7 @@ impl NetMDInterface {
} }
fn _track_change(&self, direction: Track) -> Result<(), Box<dyn Error>> { fn _track_change(&self, direction: Track) -> Result<(), Box<dyn Error>> {
let mut query = vec![0x18, 0x50, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, let mut query = vec![0x18, 0x50, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00];
0b00, 0b00];
let direction_number = direction as u16; let direction_number = direction as u16;
let direction_bytes = direction_number.to_le_bytes(); let direction_bytes = direction_number.to_le_bytes();
@ -604,4 +639,171 @@ impl NetMDInterface {
pub fn restart_track(&self) -> Result<(), Box<dyn Error>> { pub fn restart_track(&self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next) self._track_change(Track::Next)
} }
/* Content access and control */
pub fn erase_disc(&self) -> Result<(), Box<dyn Error>> {
let mut query = vec![0x18, 0x40, 0xff, 0x00, 0x00];
let reply = self.send_query(&mut query, false, false)?;
utils::check_result(reply, &[0x18, 0x40, 0x00, 0x00, 0x00])
}
// TODO: Ensure this is returning the correct value, it
// looks like it actually might be a 16 bit integer
pub fn disc_flags(&self) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(Descriptor::RootTD, DescriptorAction::OpenRead);
let mut query = vec![
0x18, 0x06, 0x01, 0x10, 0x10, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x0b,
];
let reply = self.send_query(&mut query, false, false)?;
let flags = reply[12];
self.change_descriptor_state(Descriptor::RootTD, DescriptorAction::Close);
Ok(flags)
}
pub fn track_count(&self) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(Descriptor::AudioContentsTD, DescriptorAction::OpenRead);
let mut query = vec![
0x18, 0x06, 0x02, 0x10, 0x10, 0x01, 0x30, 0x00, 0x10, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let reply = self.send_query(&mut query, false, false)?;
let track_count = reply[24];
self.change_descriptor_state(Descriptor::AudioContentsTD, DescriptorAction::Close);
Ok(track_count)
}
fn _disc_title(&self, wchar: bool) -> Result<String, Box<dyn Error>> {
self.change_descriptor_state(Descriptor::AudioContentsTD, DescriptorAction::OpenRead);
self.change_descriptor_state(Descriptor::DiscTitleTD, DescriptorAction::OpenRead);
let mut done: u16 = 0;
let mut remaining: u16 = 0;
let mut total = 1;
let mut result: Vec<String> = Vec::new();
let mut chunksize = 0;
let mut chunk = String::new();
while done < total {
let mut query = vec![
0x18, 0x06, 0x02, 0x20, 0x18, 0x01, 0x00, 0b00, 0x30, 0x00, 0x0a, 0x00, 0xff, 0x00,
0b00, 0b00, 0b00, 0b00,
];
query[7] = match wchar {
true => 1,
false => 0,
};
let remain_bytes = remaining.to_le_bytes();
query[14] = remain_bytes[0];
query[15] = remain_bytes[1];
let done_bytes = done.to_le_bytes();
query[16] = done_bytes[0];
query[17] = done_bytes[1];
let reply = self.send_query(&mut query, false, false)?;
if remaining == 0 {
chunksize = u16::from_le_bytes([reply[13], reply[14]]);
total = u16::from_le_bytes([reply[22], reply[23]]);
chunk = SHIFT_JIS.decode(&reply[25..]).0.into();
chunksize -= 6;
} else {
chunksize = u16::from_le_bytes([reply[13], reply[14]]);
chunk = SHIFT_JIS.decode(&reply[18..]).0.into();
}
result.push(chunk);
done += chunksize;
remaining = total - done;
}
let final_result = result.join("");
Ok(final_result)
}
pub fn disc_title(&self, wchar: bool) -> Result<String, Box<dyn Error>> {
let mut title = self._disc_title(wchar)?;
let delim = match wchar {
true => "",
false => "//",
};
let title_marker = match wchar {
true => "",
false => "0;",
};
if title.ends_with(delim) {
let first_entry = title.split(delim).collect::<Vec<&str>>()[0];
if first_entry.starts_with(title_marker) {
title = first_entry[title_marker.len()..].to_string();
} else {
title = String::new();
}
}
Ok(title)
}
pub fn track_group_list(&self) -> Result<(), Box<dyn Error>> {
let raw_title = self._disc_title(false)?;
let group_list = raw_title.split("//");
let mut track_dict: HashMap<u16, (String, u16)> = HashMap::new();
let track_count = self.track_count();
let result: Vec<(String, String, u16)> = Vec::new();
let raw_full_title = self._disc_title(true)?;
let mut full_width_group_list = raw_full_title.split("");
for (i, group) in group_list.enumerate() {
if group == "" {
continue;
}
if group.starts_with("0;") || group.find(";") == None || raw_title.find("//") == None {
continue;
}
let track_range: String = match group.split_once(";") {
Some(string) => string.0.to_string(),
None => return Err("No groups were found".into()),
};
if track_range.len() == 0 {
continue;
}
let group_name = &group[track_range.len() + 1..];
println!("{}", group_name);
let full_width_range = utils::half_width_to_full_width_range(track_range);
//println!("{:?}", full_width_group_list);
let full_width_group_name = full_width_group_list
.find(|n| n.starts_with(&full_width_range))
.unwrap()
.split_once("")
.unwrap()
.1;
println!("{}", full_width_group_name);
}
Ok(())
}
} }

View file

@ -1,3 +1,4 @@
use std::collections::hash_map::HashMap;
use std::error::Error; use std::error::Error;
pub fn check_result(result: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn Error>> { pub fn check_result(result: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn Error>> {
@ -12,11 +13,11 @@ pub fn byte_from_bcd(byte: u8) -> Result<u8, Box<dyn Error>> {
let lower = byte & 0x0F; let lower = byte & 0x0F;
if upper >= 10 { if upper >= 10 {
return Err("Upper nybble out of range [0..9]".into()) return Err("Upper nybble out of range [0..9]".into());
} }
if lower >= 10 { if lower >= 10 {
return Err("Lower nybble out of range [0..9]".into()) return Err("Lower nybble out of range [0..9]".into());
} }
Ok(upper * 10 + lower) Ok(upper * 10 + lower)
@ -33,3 +34,26 @@ pub fn bcd_from_byte(byte: u8) -> Result<u8, Box<dyn Error>> {
Ok(new_byte) Ok(new_byte)
} }
pub fn half_width_to_full_width_range(range: String) -> String {
let mappings: HashMap<char, char> = HashMap::from([
('0', ''),
('1', ''),
('2', ''),
('3', ''),
('4', ''),
('5', ''),
('6', ''),
('7', ''),
('8', ''),
('9', ''),
('-', ''),
('/', ''),
(';', ''),
]);
range
.chars()
.map(|char| mappings.get(&char).unwrap())
.collect()
}