use ini::Ini; use anyhow::Result; use crate::model::profile::Keyboard; macro_rules! parse_int_field { ($section:expr,$sgt:expr,$sl:expr) => { if let Some(field) = $section.get($sgt) { let field = &field[0..field.chars().position(|c| c == ';').unwrap_or(field.len())].trim(); log::debug!("loading {}={}", $sgt, field); let res = if field.starts_with("0x") { i32::from_str_radix(&field.trim()[2..], 16) } else { field.trim().parse::() }; match res { Ok(v) => $sl = v, Err(e) => log::warn!("unable to read a segatools.ini field key={} value={}: {:?}", $sgt, field.trim(), e) }; } else { log::debug!("unable to load {}", $sgt); } } } impl Keyboard { pub fn load_from_ini(&mut self, ini: &Ini) -> Result<()> { log::debug!("loading kb"); match self { Keyboard::Ongeki(kb) => { if let Some(s) = ini.section(Some("io4")) { parse_int_field!(s, "test", kb.test); parse_int_field!(s, "service", kb.svc); parse_int_field!(s, "coin", kb.coin); parse_int_field!(s, "left1", kb.l1); parse_int_field!(s, "left2", kb.l2); parse_int_field!(s, "left3", kb.l3); parse_int_field!(s, "right1", kb.r1); parse_int_field!(s, "right2", kb.r2); parse_int_field!(s, "right3", kb.r3); parse_int_field!(s, "leftMenu", kb.lmenu); parse_int_field!(s, "rightMenu", kb.rmenu); parse_int_field!(s, "leftSide", kb.lwad); parse_int_field!(s, "rightSide", kb.rwad); let mut mouse: i32 = 1; parse_int_field!(s, "mouse", mouse); kb.use_mouse = if mouse == 1 { true } else { false }; } } Keyboard::Chunithm(kb) => { if let Some(s) = ini.section(Some("io3")) { parse_int_field!(s, "test", kb.test); parse_int_field!(s, "service", kb.svc); parse_int_field!(s, "coin", kb.coin); } if let Some(s) = ini.section(Some("slider")) { for i in 0..kb.cell.len() { parse_int_field!(s, format!("cell{}", i + 1), kb.cell[i]); } } if let Some(s) = ini.section(Some("ir")) { for i in 0..kb.ir.len() { parse_int_field!(s, format!("ir{}", i + 1), kb.ir[i]); } } } } Ok(()) } // This is assumed to run in sync after the segatools module pub fn line_up(&self, ini: &mut Ini) -> Result<()> { match self { Keyboard::Ongeki(kb) => { if kb.enabled { ini.with_section(Some("io4")) .set("test", kb.test.to_string()) .set("service", kb.svc.to_string()) .set("coin", kb.coin.to_string()) .set("left1", kb.l1.to_string()) .set("left2", kb.l2.to_string()) .set("left3", kb.l3.to_string()) .set("right1", kb.r1.to_string()) .set("right2", kb.r2.to_string()) .set("right3", kb.r3.to_string()) .set("leftSide", kb.lwad.to_string()) .set("rightSide", kb.rwad.to_string()) .set("leftMenu", kb.lmenu.to_string()) .set("rightMenu", kb.rmenu.to_string()) .set("mouse", if kb.use_mouse { "1" } else { "0" }); } else { ini.with_section(Some("io4")) .set("test", "0") .set("service", "0") .set("coin", "0") .set("left1", "0") .set("left2", "0") .set("left3", "0") .set("right1", "0") .set("right2", "0") .set("right3", "0") .set("leftSide", "0") .set("rightSide", "0") .set("leftMenu", "0") .set("rightMenu", "0"); } } Keyboard::Chunithm(kb) => { if kb.enabled { for (i, cell) in kb.cell.iter().enumerate() { ini.with_section(Some("slider")).set(format!("cell{}", i + 1), cell.to_string()); } for (i, ir) in kb.ir.iter().enumerate() { ini.with_section(Some("ir")).set(format!("ir{}", i + 1), ir.to_string()); } ini.with_section(Some("io3")) .set("test", kb.test.to_string()) .set("service", kb.svc.to_string()) .set("coin", kb.coin.to_string()); } else { for (i, _) in kb.cell.iter().enumerate() { ini.with_section(Some("slider")).set(format!("cell{}", i + 1), "0"); } for (i, _) in kb.ir.iter().enumerate() { ini.with_section(Some("ir")).set(format!("ir{}", i + 1), "0"); } ini.with_section(Some("io3")) .set("test", "0") .set("service", "0") .set("coin", "0"); } ini.with_section(Some("io3")) .set("ir", "0"); } } Ok(()) } }