Files
wldash/src/widgets/battery.rs
T

128 lines
3.5 KiB
Rust
Raw Normal View History

2023-01-11 00:28:54 +01:00
use std::{
2023-01-12 00:13:27 +01:00
sync::{Arc, Mutex},
2023-01-11 00:28:54 +01:00
thread,
2023-02-02 23:52:59 +01:00
error::Error,
2023-01-11 23:54:39 +01:00
};
2023-01-11 00:28:54 +01:00
use crate::{
color::Color,
2023-02-02 23:52:59 +01:00
event::{Event, Events},
fonts::FontMap,
2023-01-12 00:13:27 +01:00
widgets::bar_widget::{BarWidget, BarWidgetImpl},
2023-01-11 00:28:54 +01:00
};
2023-02-02 23:52:59 +01:00
use upower_dbus::BatteryState;
2023-01-11 00:28:54 +01:00
struct InnerBattery {
value: f32,
2023-02-02 23:52:59 +01:00
state: BatteryState,
2023-01-16 00:25:34 +01:00
dirty: bool,
2023-01-11 00:28:54 +01:00
}
2023-02-02 23:52:59 +01:00
async fn monitor(inner: Arc<Mutex<InnerBattery>>, events: Arc<Mutex<Events>>) -> Result<(), Box<dyn Error>> {
use zbus::Connection;
use upower_dbus::UPowerProxy;
use tokio_stream::StreamExt;
let conn = Connection::system().await?;
let proxy = UPowerProxy::new(&conn).await?;
let device = proxy.get_display_device().await?;
let local_inner = inner.clone();
let local_events = events.clone();
let mut percent_stream = device.receive_percentage_changed().await;
let a = tokio::spawn(async move {
while let Some(percent) = percent_stream.next().await {
let percent = percent.get().await.unwrap() as f32 / 100.;
let mut inner = local_inner.lock().unwrap();
inner.value = percent;
inner.dirty = true;
drop(inner);
let mut events = local_events.lock().unwrap();
events.add_event(Event::PowerUpdate);
}
});
let local_inner = inner.clone();
let local_events = events.clone();
let mut state_stream = device.receive_state_changed().await;
let b = tokio::spawn(async move {
while let Some(state) = state_stream.next().await {
let state = state.get().await.unwrap();
let mut inner = local_inner.lock().unwrap();
inner.state = state;
inner.dirty = true;
drop(inner);
let mut events = local_events.lock().unwrap();
events.add_event(Event::PowerUpdate);
}
});
a.await?;
b.await?;
Ok(())
}
2023-01-16 00:25:34 +01:00
fn start_monitor(inner: Arc<Mutex<InnerBattery>>, events: Arc<Mutex<Events>>) {
2023-02-02 23:52:59 +01:00
use tokio::runtime;
2023-01-11 23:54:39 +01:00
thread::Builder::new()
.name("battmon".to_string())
.spawn(move || {
2023-02-02 23:52:59 +01:00
let rt = runtime::Builder::new_current_thread()
.enable_io()
.build()
2023-01-12 00:13:27 +01:00
.unwrap();
2023-02-02 23:52:59 +01:00
rt.block_on(async move { monitor(inner, events).await }).unwrap();
2023-01-12 00:13:27 +01:00
})
.unwrap();
2023-01-11 00:28:54 +01:00
}
pub struct Battery {
inner: Arc<Mutex<InnerBattery>>,
}
impl Battery {
2023-02-02 23:52:59 +01:00
pub fn new(events: Arc<Mutex<Events>>, fm: &mut FontMap, font: &'static str, size: f32) -> BarWidget {
2023-01-12 00:13:27 +01:00
let battery = Battery {
inner: Arc::new(Mutex::new(InnerBattery {
2023-01-11 00:28:54 +01:00
value: 0.,
2023-02-02 23:52:59 +01:00
state: BatteryState::Unknown,
2023-01-16 00:25:34 +01:00
dirty: false,
2023-01-11 00:28:54 +01:00
})),
};
2023-01-16 00:25:34 +01:00
start_monitor(battery.inner.clone(), events);
2023-02-02 23:52:59 +01:00
BarWidget::new(Box::new(battery), fm, font, size)
2023-01-11 00:28:54 +01:00
}
}
impl BarWidgetImpl for Battery {
fn get_dirty(&self) -> bool {
2023-01-16 00:25:34 +01:00
self.inner.lock().unwrap().dirty
2023-01-11 00:28:54 +01:00
}
fn name(&self) -> &'static str {
"battery"
}
fn value(&self) -> f32 {
2023-01-16 00:25:34 +01:00
let mut inner = self.inner.lock().unwrap();
inner.dirty = false;
2023-01-11 00:28:54 +01:00
inner.value
}
fn color(&self) -> Color {
let inner = self.inner.lock().unwrap();
match inner.state {
2023-02-02 23:52:59 +01:00
BatteryState::Charging | BatteryState::FullyCharged => Color::LIGHTGREEN,
BatteryState::PendingCharge => Color::LIGHTRED,
_ => if inner.value > 0.25 {
Color::WHITE
} else if inner.value > 0.1 {
Color::DARKORANGE
} else {
Color::RED
2023-01-11 00:28:54 +01:00
}
}
}
}