use std::sync::{Arc, atomic};
use clap::{Args, Parser};
use scdsu_core::devices;
#[derive(Parser)]
#[command(version)]
pub struct CliArguments {
#[arg(long, default_value_t = false)]
pub debug: bool,
#[arg(long, default_value = "0.0.0.0")]
pub bind_addr: String,
#[arg(long, default_value_t = 26760)]
pub port: u16,
#[arg(long, default_value_t = false)]
pub invert_pitch: bool,
#[arg(long, default_value_t = 0)]
pub slot: u8,
#[arg(long)]
pub device_path: Option<String>,
#[arg(short = 'L', long, default_value_t = false)]
pub no_enable_lizard_mode_on_close: bool,
#[command(flatten)]
gyro_opts: GyroOptions,
}
#[derive(Args)]
#[group(required = false, multiple = true)]
#[command(next_help_heading = "Gyro Options")]
struct GyroOptions {
#[arg(short = 'b', long, value_delimiter = ',')]
gyro_activation_buttons: Vec<devices::DeviceButton>,
#[arg(long, default_value_t = devices::GyroActivationMode::default())]
gyro_activation_mode: devices::GyroActivationMode,
#[arg(long, default_value_t = 0.0)]
gyro_deadzone: f32,
#[arg(long, default_value_t = 1.0)]
gyro_pitch_scale: f32,
#[arg(long, default_value_t = 1.0)]
gyro_yaw_scale: f32,
#[arg(long, default_value_t = 1.0)]
gyro_roll_scale: f32,
}
pub fn entrypoint() -> i32 {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.target(env_logger::Target::Stdout)
.init();
let running = Arc::new(atomic::AtomicBool::new(true));
let running_signal = running.clone();
if let Err(err) = ctrlc::set_handler(move || {
log::info!("Got a shutdown signal...");
running_signal.store(false, atomic::Ordering::SeqCst);
}) {
log::error!("Failed to set ctrlc signal handler: {err}");
return 1;
};
let args = CliArguments::parse();
if args.slot > 3 {
log::error!("Invalid slot: {}. Slot must be between 0 and 3.", args.slot);
return 1;
}
let device_config = scdsu_core::devices::DeviceConfig {
no_enable_lizard_mode_on_close: args.no_enable_lizard_mode_on_close,
gyro_activation_inputs: args.gyro_opts.gyro_activation_buttons,
gyro_activation_mode: args.gyro_opts.gyro_activation_mode,
gyro_deadzone: args.gyro_opts.gyro_deadzone,
gyro_pitch_scale: args.gyro_opts.gyro_pitch_scale,
gyro_yaw_scale: args.gyro_opts.gyro_yaw_scale,
gyro_roll_scale: args.gyro_opts.gyro_roll_scale,
};
if args.debug {
if let Err(err) =
scdsu_core::run_debug_dump(running, args.device_path.as_deref(), Some(device_config))
{
log::error!("Error from run_debug_dump: {err}");
}
return 1;
}
let config = scdsu_core::ServerConfig {
bind_addr: args.bind_addr,
port: args.port,
invert_pitch: args.invert_pitch,
slot: args.slot,
device_path: args.device_path,
};
log::debug!("Server configuration from cli args: {config:?}");
if let Err(err) = scdsu_core::run_server(running, config, device_config) {
log::error!("Error from run_server: {err}");
return 1;
}
0
}
fn main() {
let return_code = entrypoint();
std::process::exit(return_code);
}