battery/dgpu: Add connected outputs to list
This commit is contained in:
parent
8472f1f358
commit
2a47cde1b4
4 changed files with 101 additions and 17 deletions
46
Cargo.lock
generated
46
Cargo.lock
generated
|
|
@ -844,6 +844,7 @@ name = "cosmic-applet-battery"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cosmic-time",
|
"cosmic-time",
|
||||||
|
"drm 0.11.1",
|
||||||
"futures",
|
"futures",
|
||||||
"i18n-embed 0.13.9",
|
"i18n-embed 0.13.9",
|
||||||
"i18n-embed-fl 0.6.7",
|
"i18n-embed-fl 0.6.7",
|
||||||
|
|
@ -1606,21 +1607,44 @@ checksum = "97fb1b703ffbc7ebd216eba7900008049a56ace55580ecb2ee7fa801e8d8be87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"drm-ffi",
|
"drm-ffi 0.6.0",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
"nix 0.27.1",
|
"nix 0.27.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0f8a69e60d75ae7dab4ef26a59ca99f2a89d4c142089b537775ae0c198bdcde"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.2",
|
||||||
|
"bytemuck",
|
||||||
|
"drm-ffi 0.7.1",
|
||||||
|
"drm-fourcc",
|
||||||
|
"rustix 0.38.30",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "drm-ffi"
|
name = "drm-ffi"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba7d1c19c4b6270e89d59fb27dc6d02a317c658a8a54e54781e1db9b5947595d"
|
checksum = "ba7d1c19c4b6270e89d59fb27dc6d02a317c658a8a54e54781e1db9b5947595d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"drm-sys",
|
"drm-sys 0.5.0",
|
||||||
"nix 0.27.1",
|
"nix 0.27.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm-ffi"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6"
|
||||||
|
dependencies = [
|
||||||
|
"drm-sys 0.6.1",
|
||||||
|
"rustix 0.38.30",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "drm-fourcc"
|
name = "drm-fourcc"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
|
@ -1633,6 +1657,16 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a4f1c0468062a56cd5705f1e3b5409eb286d5596a2028ec8e947595d7e715ae"
|
checksum = "3a4f1c0468062a56cd5705f1e3b5409eb286d5596a2028ec8e947595d7e715ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm-sys"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d09ff881f92f118b11105ba5e34ff8f4adf27b30dae8f12e28c193af1c83176"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
|
@ -3241,6 +3275,12 @@ version = "0.4.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0b5399f6804fbab912acbd8878ed3532d506b7c951b8f9f164ef90fef39e3f4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "locale_config"
|
name = "locale_config"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
@ -4804,7 +4844,7 @@ dependencies = [
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"drm",
|
"drm 0.10.0",
|
||||||
"fastrand 2.0.1",
|
"fastrand 2.0.1",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@ i18n-embed-fl = "0.6.4"
|
||||||
rust-embed = "6.3.0"
|
rust-embed = "6.3.0"
|
||||||
tokio = { version = "1.17.0", features = ["sync", "rt", "rt-multi-thread", "fs", "macros"] }
|
tokio = { version = "1.17.0", features = ["sync", "rt", "rt-multi-thread", "fs", "macros"] }
|
||||||
udev = "0.8"
|
udev = "0.8"
|
||||||
|
drm = "0.11.1"
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::backlight::{
|
||||||
screen_backlight_subscription, ScreenBacklightRequest, ScreenBacklightUpdate,
|
screen_backlight_subscription, ScreenBacklightRequest, ScreenBacklightUpdate,
|
||||||
};
|
};
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::dgpu::{dgpu_subscription, App, GpuUpdate};
|
use crate::dgpu::{dgpu_subscription, Entry, GpuUpdate};
|
||||||
use crate::fl;
|
use crate::fl;
|
||||||
use crate::power_daemon::{
|
use crate::power_daemon::{
|
||||||
power_profile_subscription, Power, PowerProfileRequest, PowerProfileUpdate,
|
power_profile_subscription, Power, PowerProfileRequest, PowerProfileUpdate,
|
||||||
|
|
@ -65,7 +65,7 @@ static MAX_CHARGE: Lazy<id::Toggler> = Lazy::new(id::Toggler::unique);
|
||||||
struct GPUData {
|
struct GPUData {
|
||||||
name: String,
|
name: String,
|
||||||
toggled: bool,
|
toggled: bool,
|
||||||
app_list: Option<Vec<App>>,
|
app_list: Option<Vec<Entry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
|
@ -159,7 +159,7 @@ enum Message {
|
||||||
UpdateScreenBrightness(f64),
|
UpdateScreenBrightness(f64),
|
||||||
InitKbdBacklight(UnboundedSender<KeyboardBacklightRequest>, f64),
|
InitKbdBacklight(UnboundedSender<KeyboardBacklightRequest>, f64),
|
||||||
InitScreenBacklight(UnboundedSender<ScreenBacklightRequest>, f64),
|
InitScreenBacklight(UnboundedSender<ScreenBacklightRequest>, f64),
|
||||||
GpuOn(PathBuf, String, Option<Vec<App>>),
|
GpuOn(PathBuf, String, Option<Vec<Entry>>),
|
||||||
GpuOff(PathBuf),
|
GpuOff(PathBuf),
|
||||||
ToggleGpuApps(PathBuf),
|
ToggleGpuApps(PathBuf),
|
||||||
Errored(String),
|
Errored(String),
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,13 @@ use std::{
|
||||||
fmt::{self, Debug},
|
fmt::{self, Debug},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
io,
|
io,
|
||||||
os::fd::AsRawFd,
|
os::fd::{AsFd, AsRawFd},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use cosmic::iced::{self, subscription};
|
use cosmic::iced::{self, subscription};
|
||||||
|
use drm::control::Device as ControlDevice;
|
||||||
use futures::{FutureExt, SinkExt};
|
use futures::{FutureExt, SinkExt};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::unix::AsyncFd,
|
io::unix::AsyncFd,
|
||||||
|
|
@ -126,7 +127,7 @@ impl GpuMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct App {
|
pub struct Entry {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
pub secondary: String,
|
pub secondary: String,
|
||||||
|
|
@ -140,7 +141,45 @@ pub struct RunningApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
async fn app_list(&self, running_apps: &[RunningApp]) -> Option<Vec<App>> {
|
async fn connected_outputs(&self) -> Option<Vec<Entry>> {
|
||||||
|
let path = self.path.clone();
|
||||||
|
spawn_blocking(move || {
|
||||||
|
struct Device(std::fs::File);
|
||||||
|
impl AsFd for Device {
|
||||||
|
fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl drm::Device for Device {}
|
||||||
|
impl ControlDevice for Device {}
|
||||||
|
|
||||||
|
let device = Device(std::fs::File::open(path).ok()?);
|
||||||
|
let resources = device.resource_handles().ok()?;
|
||||||
|
|
||||||
|
let outputs = resources
|
||||||
|
.connectors
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|conn| device.get_connector(conn, false).ok())
|
||||||
|
.filter(|info| info.state() == drm::control::connector::State::Connected)
|
||||||
|
.map(|info| Entry {
|
||||||
|
name: format!(
|
||||||
|
"Output @ {}:{}",
|
||||||
|
info.interface().as_str(),
|
||||||
|
info.interface_id()
|
||||||
|
),
|
||||||
|
icon: Some("display-symbolic".to_string()),
|
||||||
|
secondary: String::new(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// TODO read and parse edid with libdisplay-info and display output manufacture/model
|
||||||
|
|
||||||
|
Some(outputs)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.ok()?
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn app_list(&self, running_apps: &[RunningApp]) -> Option<Vec<Entry>> {
|
||||||
match self.driver.as_ref().and_then(|s| s.to_str()) {
|
match self.driver.as_ref().and_then(|s| s.to_str()) {
|
||||||
Some("nvidia") => {
|
Some("nvidia") => {
|
||||||
// figure out bus path for calling nvidia-smi
|
// figure out bus path for calling nvidia-smi
|
||||||
|
|
@ -190,13 +229,13 @@ impl Gpu {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|running_app| running_app.executable_name == process_name)
|
.find(|running_app| running_app.executable_name == process_name)
|
||||||
{
|
{
|
||||||
App {
|
Entry {
|
||||||
name: application.name.clone(),
|
name: application.name.clone(),
|
||||||
icon: application.icon.clone(),
|
icon: application.icon.clone(),
|
||||||
secondary: String::new(),
|
secondary: String::new(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
App {
|
Entry {
|
||||||
name: process_name.to_string(),
|
name: process_name.to_string(),
|
||||||
icon: None,
|
icon: None,
|
||||||
secondary: pid.to_string(),
|
secondary: pid.to_string(),
|
||||||
|
|
@ -235,13 +274,13 @@ impl Gpu {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|running_app| running_app.executable_name == executable)
|
.find(|running_app| running_app.executable_name == executable)
|
||||||
{
|
{
|
||||||
Some(App {
|
Some(Entry {
|
||||||
name: application.name.clone(),
|
name: application.name.clone(),
|
||||||
icon: application.icon.clone(),
|
icon: application.icon.clone(),
|
||||||
secondary: String::new(),
|
secondary: String::new(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Some(App {
|
Some(Entry {
|
||||||
name: executable,
|
name: executable,
|
||||||
icon: None,
|
icon: None,
|
||||||
secondary: pid.to_string(),
|
secondary: pid.to_string(),
|
||||||
|
|
@ -351,7 +390,7 @@ pub enum State {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GpuUpdate {
|
pub enum GpuUpdate {
|
||||||
Off(PathBuf),
|
Off(PathBuf),
|
||||||
On(PathBuf, String, Option<Vec<App>>),
|
On(PathBuf, String, Option<Vec<Entry>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_listening(
|
async fn start_listening(
|
||||||
|
|
@ -440,8 +479,12 @@ async fn start_listening(
|
||||||
}
|
}
|
||||||
|
|
||||||
if enabled {
|
if enabled {
|
||||||
let app_list = gpu.app_list(&[]).await;
|
let mut list = gpu.connected_outputs().await.unwrap_or_default();
|
||||||
if output.send(GpuUpdate::On(gpu.path.clone(), gpu.name.clone(), app_list)).await.is_err() {
|
if let Some(mut apps) = gpu.app_list(&[]).await {
|
||||||
|
apps.retain(|app| app.name != "cosmic-comp");
|
||||||
|
list.extend(apps);
|
||||||
|
}
|
||||||
|
if output.send(GpuUpdate::On(gpu.path.clone(), gpu.name.clone(), (!list.is_empty()).then_some(list))).await.is_err() {
|
||||||
return State::Finished;
|
return State::Finished;
|
||||||
}
|
}
|
||||||
} else if output.send(GpuUpdate::Off(gpu.path.clone())).await.is_err() {
|
} else if output.send(GpuUpdate::Off(gpu.path.clone())).await.is_err() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue