use clap::{Parser, Subcommand};
use df_ddc::list_monitors;
use df_ddc::ddc_types::{PowerState, VcpCode, InputSource};
use df_ddc::error::DdcError;
use df_ddc::ddc_trait::DisplayDevice;
#[derive(Parser)]
#[command(name = "monmgr", version = "1.0", about = "DDC/CI Monitor Manager")]
struct Cli {
#[arg(short, long, default_value_t = 0)]
id: usize,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
List,
Brightness { value: u32 },
Contrast { value: u32 },
Volume { value: u32 },
Power { state: String },
Input { source: String },
}
fn main() {
let cli = Cli::parse();
let monitors = list_monitors();
if monitors.is_empty() {
eprintln!("Error: No DDC/CI capable monitors found.");
return;
}
let display = monitors.get(cli.id).unwrap_or_else(|| {
eprintln!("Error: Monitor index {} not found.", cli.id);
std::process::exit(1);
});
match &cli.command {
Commands::List => {
for (i, m) in monitors.iter().enumerate() {
println!("[{}] {}", i, m.info);
}
}
Commands::Brightness { value } => {
apply_vcp(display, VcpCode::Brightness, *value);
}
Commands::Contrast { value } => {
apply_vcp(display, VcpCode::Contrast, *value);
}
Commands::Volume { value } => {
apply_vcp(display, VcpCode::Volume, *value);
}
Commands::Power { state } => {
let p = if state == "off" { PowerState::Off } else { PowerState::On };
if let Err(e) = display.inner.set_power(p) {
handle_ddc_error(e);
} else {
println!("Power set to {}", state);
}
}
Commands::Input { source } => {
let src = match source.as_str() {
"hdmi1" => InputSource::Hdmi1,
"hdmi2" => InputSource::Hdmi2,
"dp1" => InputSource::DisplayPort1,
"dp2" => InputSource::DisplayPort2,
_ => { eprintln!("Error: Unknown input source."); return; }
};
if let Err(e) = display.inner.set_input(src) {
handle_ddc_error(e);
} else {
println!("Input switched to {}", source);
}
}
}
}
fn apply_vcp(display: &DisplayDevice, code: VcpCode, value: u32) {
let val = value.min(100); if let Err(e) = display.inner.set_vcp_feature(code as u8, val) {
handle_ddc_error(e);
} else {
println!("Successfully set {:?} to {}", code, val);
}
}
fn handle_ddc_error(err: DdcError) {
match err {
DdcError::AccessDenied => eprintln!("Error: Access denied. Check I2C permissions (or run as admin/root)."),
DdcError::CommunicationFailed { reason } => eprintln!("Error: Hardware communication failed: {}", reason),
DdcError::UnsupportedFeature => eprintln!("Error: Feature not supported by this monitor."),
_ => eprintln!("An unexpected error occurred: {:?}", err),
}
}