battery: Use cosmic-settings-subscriptions for upower subscriptions

These should be useful in `cosmic-osd` as well.
This commit is contained in:
Ian Douglas Scott 2024-06-13 15:50:04 -07:00 committed by Ian Douglas Scott
parent 4e3eb0a396
commit 901a70d7a1
6 changed files with 21 additions and 230 deletions

16
Cargo.lock generated
View file

@ -950,6 +950,7 @@ dependencies = [
name = "cosmic-applet-battery" name = "cosmic-applet-battery"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmic-settings-subscriptions",
"cosmic-time", "cosmic-time",
"drm", "drm",
"futures", "futures",
@ -1320,6 +1321,21 @@ dependencies = [
"zbus 4.2.2", "zbus 4.2.2",
] ]
[[package]]
name = "cosmic-settings-subscriptions"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-settings-subscriptions#a223eb4d32773e7b1170696f8b2d2d7ab54fa2e1"
dependencies = [
"futures",
"iced_futures",
"libpulse-binding",
"log",
"rustix 0.38.34",
"tokio",
"upower_dbus",
"zbus 4.2.2",
]
[[package]] [[package]]
name = "cosmic-text" name = "cosmic-text"
version = "0.11.2" version = "0.11.2"

View file

@ -21,3 +21,4 @@ udev = "0.8"
zbus.workspace = true zbus.workspace = true
# TODO branch # TODO branch
upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", branch = "upower" } upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", branch = "upower" }
cosmic-settings-subscriptions = { git = "https://github.com/pop-os/cosmic-settings-subscriptions" }

View file

@ -8,10 +8,6 @@ use crate::backlight::{
use crate::config; use crate::config;
use crate::dgpu::{dgpu_subscription, Entry, GpuUpdate}; use crate::dgpu::{dgpu_subscription, Entry, GpuUpdate};
use crate::fl; use crate::fl;
use crate::upower_device::{device_subscription, DeviceDbusEvent};
use crate::upower_kbdbacklight::{
kbd_backlight_subscription, KeyboardBacklightRequest, KeyboardBacklightUpdate,
};
use cosmic::applet::cosmic_panel_config::PanelAnchor; use cosmic::applet::cosmic_panel_config::PanelAnchor;
use cosmic::applet::token::subscription::{ use cosmic::applet::token::subscription::{
activation_token_subscription, TokenRequest, TokenUpdate, activation_token_subscription, TokenRequest, TokenUpdate,
@ -32,6 +28,10 @@ use cosmic::iced_widget::{Column, Row};
use cosmic::widget::{divider, horizontal_space, icon, scrollable, vertical_space}; use cosmic::widget::{divider, horizontal_space, icon, scrollable, vertical_space};
use cosmic::Command; use cosmic::Command;
use cosmic::{Element, Theme}; use cosmic::{Element, Theme};
use cosmic_settings_subscriptions::upower::{
device::{device_subscription, DeviceDbusEvent},
kbdbacklight::{kbd_backlight_subscription, KeyboardBacklightRequest, KeyboardBacklightUpdate},
};
use cosmic_time::{anim, chain, id, once_cell::sync::Lazy, Instant, Timeline}; use cosmic_time::{anim, chain, id, once_cell::sync::Lazy, Instant, Timeline};
use std::collections::HashMap; use std::collections::HashMap;

View file

@ -8,8 +8,6 @@ mod backend;
mod config; mod config;
mod dgpu; mod dgpu;
mod localize; mod localize;
mod upower_device;
mod upower_kbdbacklight;
use localize::localize; use localize::localize;

View file

@ -1,131 +0,0 @@
//! # DBus interface proxy for: `org.freedesktop.UPower.Device`
//!
//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
//! Source: `Interface '/org/freedesktop/UPower/devices/DisplayDevice' from service 'org.freedesktop.UPower' on system bus`.
use cosmic::iced::{
self,
futures::{SinkExt, StreamExt},
subscription,
};
use std::{fmt::Debug, hash::Hash};
use upower_dbus::{BatteryType, DeviceProxy, UPowerProxy};
pub fn device_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
id: I,
) -> iced::Subscription<DeviceDbusEvent> {
subscription::channel(id, 50, move |mut output| async move {
let mut state = State::Ready;
loop {
state = start_listening(state, &mut output).await;
}
})
}
#[derive(Debug)]
pub enum State {
Ready,
Waiting(UPowerProxy<'static>, DeviceProxy<'static>),
Finished,
}
async fn display_device() -> zbus::Result<(UPowerProxy<'static>, DeviceProxy<'static>)> {
let connection = zbus::Connection::system().await?;
let upower: UPowerProxy<'_> = UPowerProxy::new(&connection).await?;
let device_path = upower.get_display_device().await?;
Ok((upower, device_path))
}
async fn start_listening(
state: State,
output: &mut futures::channel::mpsc::Sender<DeviceDbusEvent>,
) -> State {
match state {
State::Ready => {
if let Ok((upower, device)) = display_device().await {
if let Ok(devices) = upower.enumerate_devices().await {
let mut has_battery = false;
for device in devices {
let Ok(d) = DeviceProxy::builder(upower.inner().connection()).path(device)
else {
continue;
};
let Ok(d) = d.build().await else {
continue;
};
if d.type_().await == Ok(BatteryType::Battery)
&& d.power_supply().await.unwrap_or_default()
{
has_battery = true;
break;
}
}
if !has_battery {
std::process::exit(0);
}
}
_ = output
.send(DeviceDbusEvent::Update {
on_battery: upower
.cached_on_battery()
.unwrap_or_default()
.unwrap_or_default(),
percent: device
.cached_percentage()
.unwrap_or_default()
.unwrap_or_default(),
time_to_empty: device
.cached_time_to_empty()
.unwrap_or_default()
.unwrap_or_default(),
})
.await;
return State::Waiting(upower, device);
}
State::Finished
}
State::Waiting(upower, device) => {
let mut stream = futures::stream_select!(
upower.receive_on_battery_changed().await.map(|_| ()),
device.receive_percentage_changed().await.map(|_| ()),
device.receive_time_to_empty_changed().await.map(|_| ()),
);
match stream.next().await {
Some(_) => {
_ = output
.send(DeviceDbusEvent::Update {
on_battery: upower
.cached_on_battery()
.unwrap_or_default()
.unwrap_or_default(),
percent: device
.cached_percentage()
.unwrap_or_default()
.unwrap_or_default(),
time_to_empty: device
.cached_time_to_empty()
.unwrap_or_default()
.unwrap_or_default(),
})
.await;
State::Waiting(upower, device)
}
None => State::Finished,
}
}
State::Finished => iced::futures::future::pending().await,
}
}
#[derive(Debug, Clone)]
pub enum DeviceDbusEvent {
Update {
on_battery: bool,
percent: f64,
time_to_empty: i64,
},
}

View file

@ -1,93 +0,0 @@
//! # DBus interface proxy for: `org.freedesktop.UPower.KbdBacklight`
//!
//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
//! Source: `Interface '/org/freedesktop/UPower/KbdBacklight' from service 'org.freedesktop.UPower' on system bus`.
use cosmic::iced::{self, futures::SinkExt, subscription};
use std::{fmt::Debug, hash::Hash};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
use upower_dbus::KbdBacklightProxy;
pub fn kbd_backlight_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
id: I,
) -> iced::Subscription<KeyboardBacklightUpdate> {
subscription::channel(id, 50, move |mut output| async move {
let mut state = State::Ready;
loop {
state = start_listening(state, &mut output).await;
}
})
}
#[derive(Debug)]
pub enum State {
Ready,
Waiting(
KbdBacklightProxy<'static>,
UnboundedReceiver<KeyboardBacklightRequest>,
),
Finished,
}
async fn get_brightness(kbd_proxy: &KbdBacklightProxy<'_>) -> zbus::Result<f64> {
Ok(kbd_proxy.get_brightness().await? as f64 / kbd_proxy.get_max_brightness().await? as f64)
}
async fn start_listening(
state: State,
output: &mut futures::channel::mpsc::Sender<KeyboardBacklightUpdate>,
) -> State {
match state {
State::Ready => {
let conn = match zbus::Connection::system().await {
Ok(conn) => conn,
Err(_) => return State::Finished,
};
let kbd_proxy = match KbdBacklightProxy::builder(&conn).build().await {
Ok(p) => p,
Err(_) => return State::Finished,
};
let (tx, rx) = unbounded_channel();
let b = get_brightness(&kbd_proxy).await.ok();
_ = output.send(KeyboardBacklightUpdate::Sender(tx)).await;
_ = output.send(KeyboardBacklightUpdate::Brightness(b)).await;
State::Waiting(kbd_proxy, rx)
}
State::Waiting(proxy, mut rx) => match rx.recv().await {
Some(req) => match req {
KeyboardBacklightRequest::Get => {
let b = get_brightness(&proxy).await.ok();
_ = output.send(KeyboardBacklightUpdate::Brightness(b)).await;
State::Waiting(proxy, rx)
}
KeyboardBacklightRequest::Set(value) => {
if let Ok(max_brightness) = proxy.get_max_brightness().await {
let value = value.clamp(0., 1.) * (max_brightness as f64);
let value = value.round() as i32;
let _ = proxy.set_brightness(value).await;
}
State::Waiting(proxy, rx)
}
},
None => State::Finished,
},
State::Finished => iced::futures::future::pending().await,
}
}
#[derive(Debug, Clone)]
pub enum KeyboardBacklightUpdate {
Sender(UnboundedSender<KeyboardBacklightRequest>),
Brightness(Option<f64>),
}
#[derive(Debug, Clone)]
pub enum KeyboardBacklightRequest {
Get,
Set(f64),
}