feat: add bindings for the switcheroo dbus service

This commit is contained in:
Ashley Wulber 2024-01-23 16:21:13 -05:00 committed by Ashley Wulber
parent 3644bc9099
commit 5dea929b73
4 changed files with 156 additions and 0 deletions

View file

@ -6,6 +6,7 @@ members = [
"cosmic-settings-daemon",
"mpris2",
"networkmanager",
"switcheroo-control",
"timedate",
"upower",
]

View file

@ -0,0 +1,15 @@
[package]
name = "switcheroo-control"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
zbus.workspace = true
[dev-dependencies]
futures = "0.3"
tokio = { version = "1", features = ["full"] }
zbus.workspace = true
zbus.features = ["tokio"]

View file

@ -0,0 +1,12 @@
#[tokio::main]
async fn main() -> zbus::Result<()> {
let connection = zbus::Connection::system().await?;
let proxy = switcheroo_control::SwitcherooControlProxy::new(&connection).await?;
println!("GPUs: {:?}", proxy.get_gpus().await?);
println!("HasDualGpu: {}", proxy.has_dual_gpu().await?);
println!("NumGPUs: {}", proxy.num_gpus().await?);
Ok(())
}

View file

@ -0,0 +1,128 @@
//! # DBus interface proxy for: `net.hadess.SwitcherooControl`
//!
//! This code was generated by `zbus-xmlgen` `3.1.1` from DBus introspection data.
//! Source: `Interface '/net/hadess/SwitcherooControl' from service 'net.hadess.SwitcherooControl' on system bus`.
//!
//! You may prefer to adapt it, instead of using it verbatim.
//!
//! More information can be found in the
//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation.
//!
//! This DBus object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//!
//! * [`zbus::fdo::PropertiesProxy`]
//! * [`zbus::fdo::IntrospectableProxy`]
//! * [`zbus::fdo::PeerProxy`]
//!
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
use std::collections::HashMap;
use zbus::{
dbus_proxy,
zvariant::{self, OwnedValue},
};
#[dbus_proxy(
interface = "net.hadess.SwitcherooControl",
default_service = "net.hadess.SwitcherooControl",
default_path = "/net/hadess/SwitcherooControl"
)]
trait SwitcherooControl {
/// GPUs property
#[dbus_proxy(property, name = "GPUs")]
fn gpus(
&self,
) -> zbus::Result<Vec<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>>;
/// HasDualGpu property
#[dbus_proxy(property)]
fn has_dual_gpu(&self) -> zbus::Result<bool>;
/// NumGPUs property
#[dbus_proxy(property, name = "NumGPUs")]
fn num_gpus(&self) -> zbus::Result<u32>;
}
impl<'a> SwitcherooControlProxy<'a> {
pub fn get_cached_gpus(&self) -> zbus::Result<Vec<Gpu>> {
let res = self.cached_gpus().map_err(|err| zbus::Error::from(err))?;
if let Some(res) = res {
convert_gpus(res)
} else {
Err(zbus::Error::FDO(Box::new(zbus::fdo::Error::Failed(
"No cached GPUs".into(),
))))
}
}
pub async fn get_gpus(&self) -> zbus::Result<Vec<Gpu>> {
convert_gpus(self.gpus().await?)
}
}
impl<'a> SwitcherooControlProxyBlocking<'a> {
pub fn get_cached_gpus(&self) -> zbus::Result<Vec<Gpu>> {
let res = self.cached_gpus().map_err(|err| zbus::Error::from(err))?;
if let Some(res) = res {
convert_gpus(res)
} else {
Err(zbus::Error::FDO(Box::new(zbus::fdo::Error::Failed(
"No cached GPUs".into(),
))))
}
}
pub fn get_gpus(&self) -> zbus::Result<Vec<Gpu>> {
convert_gpus(self.gpus()?)
}
}
impl TryFrom<HashMap<String, OwnedValue>> for Gpu {
type Error = zvariant::Error;
fn try_from(value: HashMap<String, OwnedValue>) -> Result<Self, Self::Error> {
let name = value
.get("Name")
.ok_or(zvariant::Error::IncorrectType)?
.to_owned()
.try_into()?;
let environment: Vec<String> = value
.get("Environment")
.ok_or(zvariant::Error::IncorrectType)?
.to_owned()
.try_into()?;
let environment: HashMap<String, String> = environment
.chunks_exact(2)
.map(|chunk| (chunk[0].clone(), chunk[1].clone()))
.collect();
let default = value
.get("Default")
.ok_or(zvariant::Error::IncorrectType)?
.try_into()?;
Ok(Self {
name,
environment,
default,
})
}
}
fn convert_gpus(gpus: Vec<HashMap<String, OwnedValue>>) -> zbus::Result<Vec<Gpu>> {
let mut graphics = Vec::with_capacity(gpus.len());
for gpu in gpus {
graphics.push(gpu.try_into()?);
}
Ok(graphics)
}
#[derive(Debug, Clone)]
pub struct Gpu {
pub name: String,
pub environment: HashMap<String, String>,
pub default: bool,
}