feat: debug info in about dialog

This commit is contained in:
Gabriele Musco 2024-07-29 16:31:55 +02:00
parent 0c3f6e98f5
commit 56f2e0b0d6
9 changed files with 159 additions and 9 deletions

10
Cargo.lock generated
View file

@ -32,6 +32,15 @@ version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "ash"
version = "0.38.0+1.3.281"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
dependencies = [
"libloading 0.8.5",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -271,6 +280,7 @@ name = "envision"
version = "0.1.0"
dependencies = [
"anyhow",
"ash",
"gettext-rs",
"git2",
"gtk4",

View file

@ -29,3 +29,4 @@ xdg = "2.5.2"
openxr = { git = "https://github.com/galister/openxrs", rev = "af4a55d", features = [
"linked",
] }
ash = "0.38.0"

View file

@ -13,7 +13,7 @@ base_id = 'org.gabmus.envision'
pretty_name = 'Envision'
upstream_repo = 'https://gitlab.com/gabmus/envision'
author = 'The Envision Team'
description = 'GUI for Monado' # temporary
description = 'Orchestrator for the free XR stack' # temporary
dependency('glib-2.0', version: '>= 2.66')
dependency('gio-2.0', version: '>= 2.66')
@ -55,8 +55,10 @@ endif
meson.add_dist_script(
'build-aux/dist-vendor.sh',
meson.project_build_root() / 'meson-dist' / meson.project_name() + '-' + version,
meson.project_source_root()
meson.project_build_root() / 'meson-dist' / meson.project_name()
+ '-'
+ version,
meson.project_source_root(),
)
global_conf = configuration_data()
@ -71,6 +73,11 @@ global_conf.set('AUTHOR', author)
global_conf.set('PRETTY_NAME', pretty_name)
global_conf.set('CMD_NAME', meson.project_name())
global_conf.set('REPO_URL', upstream_repo)
global_conf.set('ISSUES_URL', upstream_repo + '/-/issues')
global_conf.set(
'BUILD_DATETIME',
run_command('date', '-Iseconds', '--utc', check: true).stdout().strip(),
)
subdir('data')
subdir('po')

View file

@ -9,11 +9,13 @@ pub const PKG_DATA_DIR: &str = "@PKGDATADIR@";
pub const RESOURCES: &str = concat!("@PKGDATADIR@", "/resources.gresource");
pub const CMD_NAME: &str = "@CMD_NAME@";
pub const VERSION: &str = "@VERSION@";
pub const REPO_URL: &str = "@UPSTREAM_REPO_URL@";
pub const REPO_URL: &str = "@REPO_URL@";
pub const ISSUES_URL: &str = "@ISSUES_URL@";
pub const SINGLE_DEVELOPER: &str = "@AUTHOR@";
pub const GETTEXT_PACKAGE: &str = "@GETTEXT_PACKAGE@";
pub const LOCALE_DIR: &str = "@LOCALEDIR@";
pub const BUILD_PROFILE: &str = "@PROFILE@";
pub const BUILD_DATETIME: &str = "@BUILD_DATETIME@";
pub fn get_developers() -> Vec<String> {
vec!["Gabriele Musco <gabmus@disroot.org>".to_string()]

View file

@ -1,5 +1,6 @@
use crate::file_utils::get_reader;
use std::{
fmt::Display,
io::{BufRead, Read},
path::Path,
};
@ -15,6 +16,19 @@ pub enum LinuxDistro {
Suse,
}
impl Display for LinuxDistro {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Alpine => "Alpine",
Self::Arch => "Arch",
Self::Debian => "Debian",
Self::Fedora => "Fedora",
Self::Gentoo => "Gentoo",
Self::Suse => "Suse",
})
}
}
impl LinuxDistro {
pub fn get() -> Option<Self> {
Self::get_from_etc_os_release().or_else(Self::get_from_etc_issue)
@ -24,12 +38,40 @@ impl LinuxDistro {
Self::get_from_etc_os_release_file(Path::new("/etc/os-release"))
}
// does it make sense to be here?
pub fn get_specific_distro() -> Option<String> {
let mut name: Option<String> = None;
if let Some(mut reader) = get_reader(Path::new("/etc/os-release")) {
let mut buf = String::new();
loop {
match reader.read_line(&mut buf) {
Ok(0) | Err(_) => break,
Ok(_) if buf.starts_with("PRETTY_NAME=\"") => {
return buf
.split('=')
.last()
.map(|b| b.trim().trim_matches('"').trim().to_string());
}
Ok(_) if buf.starts_with("NAME=\"") => {
name = buf
.split('=')
.last()
.map(|b| b.trim().trim_matches('"').trim().to_string());
}
_ => {}
};
buf.clear();
}
}
name
}
fn get_from_etc_os_release_file(fp: &Path) -> Option<Self> {
if let Some(mut reader) = get_reader(fp) {
let mut buf = String::new();
loop {
match reader.read_line(&mut buf) {
Ok(0) => break,
Ok(0) | Err(_) => break,
Ok(_) => {
if buf.starts_with("NAME=\"")
|| buf.starts_with("ID=\"")
@ -39,7 +81,7 @@ impl LinuxDistro {
.split('=')
.last()
.unwrap_or_default()
.to_string()
.trim()
.trim_matches('"')
.to_lowercase();
let res = Self::name_matcher(&name);
@ -48,8 +90,8 @@ impl LinuxDistro {
}
}
}
Err(_) => break,
}
buf.clear();
}
}
None

View file

@ -44,6 +44,7 @@ pub mod steam_linux_runtime_injector;
pub mod steamvr_utils;
pub mod termcolor;
pub mod ui;
pub mod vulkaninfo;
pub mod xdg;
pub mod xr_devices;

View file

@ -1,5 +1,14 @@
use crate::constants::{get_developers, APP_ID, APP_NAME, REPO_URL, SINGLE_DEVELOPER, VERSION};
use crate::{
constants::{
get_developers, APP_ID, APP_NAME, BUILD_DATETIME, ISSUES_URL, REPO_URL, SINGLE_DEVELOPER,
VERSION,
},
linux_distro::LinuxDistro,
vulkaninfo::gpu_names,
xdg::XDG,
};
use relm4::prelude::*;
use std::env;
pub fn create_about_dialog() -> adw::AboutDialog {
adw::AboutDialog::builder()
@ -8,7 +17,55 @@ pub fn create_about_dialog() -> adw::AboutDialog {
.license_type(gtk::License::Agpl30)
.version(VERSION)
.website(REPO_URL)
.issue_url(ISSUES_URL)
.developer_name(SINGLE_DEVELOPER)
.developers(get_developers())
.build()
}
pub fn populate_debug_info(dialog: &adw::AboutDialog) {
if dialog.debug_info().len() > 0 {
return;
}
let distro_family = LinuxDistro::get();
let distro = LinuxDistro::get_specific_distro();
dialog.set_debug_info(
&[
format!("Version: {VERSION}"),
format!("Build time: {BUILD_DATETIME}"),
format!(
"Operating system: {d} ({f})",
d = distro.unwrap_or("unknown".into()),
f = distro_family
.map(|f| f.to_string())
.unwrap_or("unknown".into())
),
format!(
"Session type: {}",
env::var("XDG_SESSION_TYPE").unwrap_or("unknown".into())
),
format!(
"Desktop: {}",
env::var("XDG_CURRENT_DESKTOP").unwrap_or("unknown".into())
),
format!(
"GPUs: {}",
unsafe { gpu_names() }
.ok()
.map(|names| names.join(", "))
.unwrap_or("unknown".into())
),
format!(
"Steam found: {}",
if XDG.get_data_home().join("Steam").is_dir()
|| XDG.get_data_home().join("steam").is_dir()
{
"yes"
} else {
"no"
}
),
]
.join("\n"),
);
}

View file

@ -41,7 +41,7 @@ use crate::stateless_action;
use crate::steam_linux_runtime_injector::{
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
};
use crate::ui::about_dialog::create_about_dialog;
use crate::ui::about_dialog::{create_about_dialog, populate_debug_info};
use crate::ui::build_window::{BuildWindowInit, BuildWindowMsg, BuildWindowOutMsg};
use crate::ui::debug_view::{DebugViewInit, DebugViewOutMsg};
use crate::ui::libsurvive_setup_window::LibsurviveSetupMsg;
@ -942,6 +942,7 @@ impl SimpleComponent for App {
#[strong(rename_to = app_win)]
model.app_win,
move |_| {
populate_debug_info(&about_dialog);
about_dialog.present(Some(&app_win));
}
)

29
src/vulkaninfo.rs Normal file
View file

@ -0,0 +1,29 @@
use ash::{
vk::{ApplicationInfo, InstanceCreateInfo},
Entry,
};
/// # Safety
///
/// Dlopens the vulkan library, so this is inherently unsafe. Should be fine in
/// most circumstances
pub unsafe fn gpu_names() -> anyhow::Result<Vec<String>> {
let entry = Entry::load()?;
let instance = entry.create_instance(
&InstanceCreateInfo::default().application_info(&ApplicationInfo::default()),
None,
)?;
let names = instance
.enumerate_physical_devices()?
.into_iter()
.filter_map(|d| {
instance
.get_physical_device_properties(d)
.device_name_as_c_str()
.ok()
.map(|cs| cs.to_string_lossy().to_string())
})
.collect();
instance.destroy_instance(None);
Ok(names)
}