use std::collections::HashSet;
use clap::Parser;
use ppd::PpdProxyBlocking;
mod args;
use args::{Args, Commands};
use ppd::error::{PpdError, Result};
use zbus::blocking::Connection;
fn main() -> Result<()> {
let cli = Args::parse();
let connection = Connection::system()?;
let proxy = PpdProxyBlocking::new(&connection)?;
match cli.command {
Some(c) => match c {
Commands::Get => print_profile(&proxy)?,
Commands::List => list(&proxy)?,
Commands::ListHolds => Err(PpdError::Unimplemented("ListHolds command".to_string()))?,
Commands::Set { profile } => set(&proxy, profile)?,
Commands::ListActions => list_actions(&proxy)?,
Commands::Launch {
arguments: _,
profile: _,
reason: _,
appid: _,
} => Err(PpdError::Unimplemented("Launch command".to_string()))?,
Commands::QueryBatteryAware => query_battery_aware(&proxy)?,
Commands::ConfigureAction {
action: _,
enable: _,
disable: _,
} => Err(PpdError::Unimplemented(
"ConfigureAction command".to_string(),
))?,
Commands::ConfigureBatteryAware { enable, disable } => {
configure_battery_aware(&proxy, enable, disable)?
}
Commands::Watch => watch(&proxy)?,
},
_ => list(&proxy)?,
};
Ok(())
}
fn print_profile(proxy: &PpdProxyBlocking) -> Result<()> {
let reply = proxy.active_profile()?;
println!("{reply}");
Ok(())
}
fn list(proxy: &PpdProxyBlocking) -> Result<()> {
let current = proxy.active_profile()?;
let profiles = proxy.profiles()?;
let degraded = proxy
.performance_degraded()?
.as_ref()
.unwrap_or(&String::from("no"))
.to_string();
let mut profiles_iter = profiles.into_iter().rev().peekable();
while let Some(profile) = profiles_iter.next() {
let degraded_string = if profile.profile == "performance" {
Some(degraded.clone())
} else {
None
};
let current_marker = if current == profile.profile { "*" } else { " " };
println!("{} {}:", current_marker, profile.profile);
if let Some(s) = profile.cpu_driver.clone() {
println!(" CpuDriver:\t{}", s);
}
if let Some(s) = profile.platform_driver.clone() {
println!(" PlatformDriver:\t{}", s);
}
if let Some(s) = degraded_string {
println!(" Degraded: {}", s);
}
if profiles_iter.peek().is_some() {
println!();
}
}
Ok(())
}
fn watch(proxy: &PpdProxyBlocking) -> Result<()> {
println!("{}", proxy.active_profile()?);
let signal = proxy.receive_active_profile_changed();
for p in signal {
let name = p.get()?;
println!("{name}");
}
Ok(())
}
fn set(proxy: &PpdProxyBlocking, profile: String) -> Result<()> {
let profiles_names: HashSet<_> = proxy
.profiles()?
.iter()
.map(|x| x.profile.clone())
.collect();
if profiles_names.contains(&profile) {
proxy.set_active_profile(profile)?;
Ok(())
} else {
Err(PpdError::InvalidProfile(profile))
}
}
fn query_battery_aware(proxy: &PpdProxyBlocking) -> Result<()> {
let ba = proxy.battery_aware()?;
println!("Dynamic changes from charger and battery events: {}", ba);
Ok(())
}
fn list_actions(proxy: &PpdProxyBlocking) -> Result<()> {
for action in proxy.actions_info()? {
println!("Name: {}", action.name);
println!("Description: {}", action.description);
println!("Enabled: {}", action.enabled);
}
Ok(())
}
fn configure_battery_aware(proxy: &PpdProxyBlocking, enable: bool, disable: bool) -> Result<()> {
if enable && disable {
Err(PpdError::InvalidConfig(
"can't set both enable and disable".to_string(),
))
} else if !(enable || disable) {
Err(PpdError::InvalidConfig(
"enable or disable is required".to_string(),
))
} else {
proxy.set_battery_aware(enable)?;
Ok(())
}
}