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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|