From 975f2937ad5bc59c918f21e965c7216bc1ab1331 Mon Sep 17 00:00:00 2001 From: Lennard Kittner Date: Fri, 21 Mar 2025 22:01:14 +0100 Subject: [PATCH] Add setter to CLI app --- Cargo.toml | 3 +- src/bin/cli_app.rs | 101 +++++++++++++++++++++++++++++++++++++++++++++ src/devices/mod.rs | 11 +++-- 3 files changed, 108 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed13281..f553b23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4.5.32", features = ["derive"] } hidapi = "2.3.3" thistermination = "1.0.0" [target.'cfg(target_os = "linux")'.dependencies] -ksni = "0.2.0" \ No newline at end of file +ksni = "0.2.0" diff --git a/src/bin/cli_app.rs b/src/bin/cli_app.rs index f52233e..db9d6ae 100644 --- a/src/bin/cli_app.rs +++ b/src/bin/cli_app.rs @@ -1,6 +1,52 @@ +use std::time::Duration; + +use clap::{Arg, Command}; use hyper_x_cloud_ii_wireless::devices::{cloud_ii_wireless_dts::CloudIIWirelessDTS, Device}; fn main() { + let matches = Command::new(env!("CARGO_PKG_NAME")) + .version(env!("CARGO_PKG_VERSION")) + .author(env!("CARGO_PKG_AUTHORS")) + .about(env!("CARGO_PKG_DESCRIPTION")) + .arg( + Arg::new("automatic_shutdown") + .long("automatic_shutdown") + .required(false) + .help( + "Set the delay in minutes after which the headset will automatically shutdown.", + ) + .value_parser(clap::value_parser!(u8)), + ) + .arg( + Arg::new("mute") + .long("mute") + .required(false) + .help("Mute or un mute the headset.") + .value_parser(clap::value_parser!(bool)), + ) + .arg( + Arg::new("enable_side_tone") + .long("enable_side_tone") + .required(false) + .help("Enable or disable side tone.") + .value_parser(clap::value_parser!(bool)), + ) + .arg( + Arg::new("side_tone_volume") + .long("side_tone_volume") + .required(false) + .help("Set the side tone volume.") + .value_parser(clap::value_parser!(u8)), + ) + .arg( + Arg::new("enable_voice_prompt") + .long("enable_voice_prompt") + .required(false) + .help("Enable voice prompt. This may not be supported on your device.") + .value_parser(clap::value_parser!(bool)), + ) + .get_matches(); + let mut device = match CloudIIWirelessDTS::new() { Ok(device) => device, Err(error) => { @@ -9,6 +55,61 @@ fn main() { } }; + if let Some(delay) = matches.get_one::("automatic_shutdown") { + let delay = *delay as u64; + if let Some(packet) = + device.set_automatic_shut_down_packet(Duration::from_secs(delay * 60u64)) + { + if let Err(err) = device.get_device_state().hid_device.write(&packet) { + println!("Failed to set automatic shutdown with error: {:?}", err) + } + } else { + println!("Automatic shutdown can't be enabled on this device") + } + } + + if let Some(mute) = matches.get_one::("mute") { + if let Some(packet) = device.set_mute_packet(*mute) { + if let Err(err) = device.get_device_state().hid_device.write(&packet) { + println!("Failed to mute with error: {:?}", err) + } + } else { + println!("Can't mute this device") + } + } + + if let Some(enable) = matches.get_one::("enable_side_tone") { + if let Some(packet) = device.set_side_tone_packet(*enable) { + if let Err(err) = device.get_device_state().hid_device.write(&packet) { + println!("Failed to enable side tone with error: {:?}", err) + } + } else { + println!("Can't enable side tone on this device") + } + } + + if let Some(volume) = matches.get_one::("side_tone_volume") { + if let Some(packet) = device.set_side_tone_volume_packet(*volume) { + if let Err(err) = device.get_device_state().hid_device.write(&packet) { + println!("Failed to set side tone volume with error: {:?}", err) + } + } else { + println!("Can't set side tone volume on this device") + } + } + + if let Some(enable) = matches.get_one::("enable_voice_prompt") { + if let Some(packet) = device.set_voice_prompt_packet(*enable) { + if let Err(err) = device.get_device_state().hid_device.write(&packet) { + println!("Failed to enable voice prompt with error: {:?}", err) + } + } else { + println!("Can't enable voice prompt on this device") + } + } + + std::thread::sleep(Duration::from_secs_f64(0.5)); + if let Err(error) = device.refresh_state() { eprintln!("{error}"); std::process::exit(1); diff --git a/src/devices/mod.rs b/src/devices/mod.rs index bd41da8..bf13f4d 100644 --- a/src/devices/mod.rs +++ b/src/devices/mod.rs @@ -5,10 +5,9 @@ use std::{fmt::Display, time::Duration}; use thistermination::TerminationFull; //TODO: connect to rest of code base - #[derive(Debug)] pub struct DeviceState { - hid_device: HidDevice, + pub hid_device: HidDevice, pub battery_level: Option, pub charging: Option, pub muted: Option, @@ -222,13 +221,13 @@ pub trait Device { fn get_side_tone_packet(&self) -> Option>; fn set_side_tone_packet(&self, side_tone_on: bool) -> Option>; fn get_side_tone_volume_packet(&self) -> Option>; - fn set_side_tone_volume_packet(&self) -> Option>; + fn set_side_tone_volume_packet(&self, volume: u8) -> Option>; fn get_voice_prompt_packet(&self) -> Option>; fn set_voice_prompt_packet(&self, enable: bool) -> Option>; fn get_wireless_connected_status_packet(&self) -> Option>; fn get_event_from_device_response(&self, response: &[u8]) -> Option; - fn get_device_state(&mut self) -> &mut DeviceState; - + fn get_device_state(&self) -> &DeviceState; + fn get_device_state_mut(&mut self) -> &mut DeviceState; fn wait_for_updates(&mut self, duration: Duration) -> Option { let mut buf = [0u8; 8]; let res = self @@ -264,7 +263,7 @@ pub trait Device { if let Some(packet) = packet { self.get_device_state().hid_device.write(&packet)?; if let Some(event) = self.wait_for_updates(Duration::from_secs(1)) { - self.get_device_state().update_self_with_event(&event); + self.get_device_state_mut().update_self_with_event(&event); responded = true; } if !self.get_device_state().connected.map_or(true, |c| c) {