Merge branch 'main' into feat/stardust

This commit is contained in:
Gabriele Musco 2024-01-27 18:09:59 +01:00
commit 1f37b27de0
No known key found for this signature in database
GPG key ID: 1068D795C80E51DE
9 changed files with 192 additions and 88 deletions

View file

@ -1,4 +1,4 @@
image: "debian:testing"
image: "debian:unstable"
stages:
- check

View file

@ -12,7 +12,7 @@ Also consider that due to the unstable nature of the app, it's possible to encou
UI for building, configuring and running Monado, the open source OpenXR runtime.
Download the latest AppImage snapshot: [GitLab Pipelines](https://gitlab.com/gabmus/envision/-/pipelines)
Download the latest AppImage snapshot: [GitLab Pipelines](https://gitlab.com/gabmus/envision/-/pipelines?page=1&scope=all&ref=main)
## Running

View file

@ -1,8 +0,0 @@
#[macro_export]
macro_rules! checkerr {
($ex:expr) => {
if $ex.is_err() {
return Err(());
}
};
}

View file

@ -1,5 +1,4 @@
use crate::{
checkerr,
file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
paths::{get_backup_dir, get_xdg_config_dir, get_xdg_data_dir, SYSTEM_PREFIX},
profile::{Profile, XRServiceType},
@ -97,9 +96,9 @@ fn build_steam_active_runtime() -> ActiveRuntime {
}
}
pub fn set_current_active_runtime_to_steam() -> Result<(), ()> {
checkerr!(set_file_readonly(&get_active_runtime_json_path(), false));
checkerr!(dump_current_active_runtime(&build_steam_active_runtime()));
pub fn set_current_active_runtime_to_steam() -> anyhow::Result<()> {
set_file_readonly(&get_active_runtime_json_path(), false)?;
dump_current_active_runtime(&build_steam_active_runtime())?;
Ok(())
}
@ -156,9 +155,9 @@ fn relativize_active_runtime_lib_path(ar: &ActiveRuntime, dest: &str) -> ActiveR
res
}
pub fn set_current_active_runtime_to_profile(profile: &Profile) -> Result<(), ()> {
pub fn set_current_active_runtime_to_profile(profile: &Profile) -> anyhow::Result<()> {
let dest = get_active_runtime_json_path();
checkerr!(set_file_readonly(&dest, false));
set_file_readonly(&dest, false)?;
backup_steam_active_runtime();
let pfx = profile.clone().prefix;
let mut ar = build_profile_active_runtime(profile);
@ -166,8 +165,8 @@ pub fn set_current_active_runtime_to_profile(profile: &Profile) -> Result<(), ()
if pfx == SYSTEM_PREFIX {
ar = relativize_active_runtime_lib_path(&ar, &dest);
}
checkerr!(dump_current_active_runtime(&ar));
checkerr!(set_file_readonly(&dest, true));
dump_current_active_runtime(&ar)?;
set_file_readonly(&dest, true)?;
Ok(())
}

View file

@ -1,5 +1,4 @@
use crate::{
checkerr,
file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
paths::{get_backup_dir, get_xdg_config_dir, get_xdg_data_dir},
profile::Profile,
@ -94,9 +93,9 @@ fn build_steam_openvrpaths() -> OpenVrPaths {
}
}
pub fn set_current_openvrpaths_to_steam() -> Result<(), ()> {
checkerr!(set_file_readonly(&get_openvrpaths_vrpath_path(), false));
checkerr!(dump_current_openvrpaths(&build_steam_openvrpaths()));
pub fn set_current_openvrpaths_to_steam() -> anyhow::Result<()> {
set_file_readonly(&get_openvrpaths_vrpath_path(), false)?;
dump_current_openvrpaths(&build_steam_openvrpaths())?;
Ok(())
}
@ -115,14 +114,12 @@ pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths {
}
}
pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> Result<(), ()> {
pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<()> {
let dest = get_openvrpaths_vrpath_path();
checkerr!(set_file_readonly(&dest, false));
set_file_readonly(&dest, false)?;
backup_steam_openvrpaths();
checkerr!(dump_current_openvrpaths(&build_profile_openvrpaths(
profile
)));
checkerr!(set_file_readonly(&dest, true));
dump_current_openvrpaths(&build_profile_openvrpaths(profile))?;
set_file_readonly(&dest, true)?;
Ok(())
}

View file

@ -9,39 +9,56 @@ pub enum LinuxDistro {
Debian,
Fedora,
Gentoo,
// TODO: add Nix,
Suse,
}
pub fn get_distro() -> Option<LinuxDistro> {
if let Some(mut reader) = get_reader("/etc/issue") {
let mut buf = String::default();
if reader.read_to_string(&mut buf).is_ok() {
buf = buf.trim().to_lowercase();
if buf.contains("arch linux")
|| buf.contains("manjaro")
|| buf.contains("steamos")
|| buf.contains("steam os")
{
return Some(LinuxDistro::Arch);
}
if buf.contains("debian")
|| buf.contains("ubuntu")
|| buf.contains("mint")
|| buf.contains("elementary")
|| buf.contains("pop")
{
return Some(LinuxDistro::Debian);
}
if buf.contains("fedora") || buf.contains("nobara") {
return Some(LinuxDistro::Fedora);
}
if buf.contains("gentoo") {
return Some(LinuxDistro::Gentoo);
}
if buf.contains("alpine") || buf.contains("postmarket") {
return Some(LinuxDistro::Alpine);
impl LinuxDistro {
pub fn get() -> Option<Self> {
if let Some(mut reader) = get_reader("/etc/issue") {
let mut buf = String::default();
if reader.read_to_string(&mut buf).is_ok() {
buf = buf.trim().to_lowercase();
if buf.contains("arch linux")
|| buf.contains("manjaro")
|| buf.contains("steamos")
|| buf.contains("steam os")
{
return Some(Self::Arch);
}
if buf.contains("debian")
|| buf.contains("ubuntu")
|| buf.contains("mint")
|| buf.contains("elementary")
|| buf.contains("pop")
{
return Some(Self::Debian);
}
if buf.contains("fedora") || buf.contains("nobara") {
return Some(Self::Fedora);
}
if buf.contains("gentoo") {
return Some(Self::Gentoo);
}
if buf.contains("alpine") || buf.contains("postmarket") {
return Some(Self::Alpine);
}
// TODO: detect suse, sles, rhel, nix
}
}
None
}
None
pub fn install_command(&self, packages: &[String]) -> String {
match self {
Self::Arch => format!("sudo pacman -Syu {}", packages.join(" ")),
Self::Alpine => format!("sudo apk add {}", packages.join(" ")),
Self::Debian => format!("sudo apt install {}", packages.join(" ")),
Self::Fedora => format!("sudo dnf install {}", packages.join(" ")),
Self::Gentoo => format!("sudo emerge {}", packages.join(" ")),
Self::Suse => format!("sudo zypper install {}", packages.join(" ")),
}
}
}

View file

@ -15,7 +15,6 @@ use ui::app::{App, AppInit};
pub mod adb;
pub mod build_tools;
pub mod builders;
pub mod checkerr;
pub mod cmd_runner;
pub mod config;
pub mod constants;
@ -49,7 +48,7 @@ fn restore_steam_xr_files() {
if !file_builders::active_runtime_json::is_steam(&ar) {
match set_current_active_runtime_to_steam() {
Ok(_) => {}
Err(_) => println!("Warning: failed to restore active runtime to steam!"),
Err(e) => eprintln!("Warning: failed to restore active runtime to steam: {e}"),
};
}
}
@ -57,7 +56,7 @@ fn restore_steam_xr_files() {
if !file_builders::openvrpaths_vrpath::is_steam(&ovrp) {
match set_current_openvrpaths_to_steam() {
Ok(_) => {}
Err(_) => println!("Warning: failed to restore openvrpaths to steam!"),
Err(e) => eprintln!("Warning: failed to restore openvrpaths to steam: {e}"),
};
}
}

View file

@ -1,7 +1,10 @@
use gtk::traits::{GtkApplicationExt, GtkWindowExt};
use gtk::{
prelude::IsA,
traits::{GtkApplicationExt, GtkWindowExt},
};
use relm4::{adw::traits::MessageDialogExt, prelude::*};
pub fn alert(title: &str, msg: Option<&str>, parent: Option<&gtk::Window>) {
fn alert_base(title: &str, msg: Option<&str>, parent: Option<&gtk::Window>) -> adw::MessageDialog {
let d = adw::MessageDialog::builder()
.modal(true)
.heading(title)
@ -15,5 +18,23 @@ pub fn alert(title: &str, msg: Option<&str>, parent: Option<&gtk::Window>) {
d.set_transient_for(gtk::Application::default().active_window().as_ref());
}
d.add_response("ok", "_Ok");
d
}
pub fn alert(title: &str, msg: Option<&str>, parent: Option<&gtk::Window>) {
let d = alert_base(title, msg, parent);
d.present();
}
pub fn alert_w_widget(
title: &str,
msg: Option<&str>,
widget: Option<&gtk::Widget>,
parent: Option<&gtk::Window>,
) {
let d = alert_base(title, msg, parent);
if let Some(w) = widget {
d.set_extra_child(Some(w));
}
d.present();
}

View file

@ -1,5 +1,5 @@
use super::about_dialog::AboutDialog;
use super::alert::alert;
use super::alert::{alert, alert_w_widget};
use super::build_window::{BuildStatus, BuildWindow};
use super::debug_view::{DebugView, DebugViewMsg};
use super::fbt_config_editor::{FbtConfigEditor, FbtConfigEditorInit, FbtConfigEditorMsg};
@ -8,7 +8,7 @@ use super::job_worker::job::WorkerJob;
use super::job_worker::JobWorker;
use super::libsurvive_setup_window::LibsurviveSetupWindow;
use super::main_view::MainViewMsg;
use super::util::open_with_default_handler;
use super::util::{copy_text, open_with_default_handler};
use super::wivrn_conf_editor::{WivrnConfEditor, WivrnConfEditorInit, WivrnConfEditorMsg};
use crate::builders::build_basalt::get_build_basalt_jobs;
use crate::builders::build_libsurvive::get_build_libsurvive_jobs;
@ -34,7 +34,7 @@ use crate::file_builders::openvrpaths_vrpath::{
set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam,
};
use crate::file_utils::setcap_cap_sys_nice_eip;
use crate::linux_distro::get_distro;
use crate::linux_distro::LinuxDistro;
use crate::log_parser::MonadoLog;
use crate::paths::{get_data_dir, get_ipc_file_path};
use crate::profile::{Profile, XRServiceType};
@ -162,18 +162,22 @@ impl App {
pub fn start_xrservice(&mut self, sender: ComponentSender<Self>, debug: bool) {
let prof = self.get_selected_profile();
if set_current_active_runtime_to_profile(&prof).is_err() {
if let Err(e) = set_current_active_runtime_to_profile(&prof) {
alert(
"Failed to start XR Service",
Some("Error setting current active runtime to profile"),
Some(&format!(
"Error setting current active runtime to profile: {e}"
)),
Some(&self.app_win.clone().upcast::<gtk::Window>()),
);
return;
}
if set_current_openvrpaths_to_profile(&prof).is_err() {
if let Err(e) = set_current_openvrpaths_to_profile(&prof) {
alert(
"Failed to start XR Service",
Some("Error setting current openvrpaths file to profile"),
Some(&format!(
"Error setting current openvrpaths file to profile: {e}"
)),
Some(&self.app_win.clone().upcast::<gtk::Window>()),
);
return;
@ -218,17 +222,17 @@ impl App {
}
pub fn restore_openxr_openvr_files(&self) {
if set_current_active_runtime_to_steam().is_err() {
if let Err(e) = set_current_active_runtime_to_steam() {
alert(
"Could not restore Steam active runtime",
None,
Some(&format!("{e}")),
Some(&self.app_win.clone().upcast::<gtk::Window>()),
);
}
if set_current_openvrpaths_to_steam().is_err() {
if let Err(e) = set_current_openvrpaths_to_steam() {
alert(
"Could not restore Steam openvrpaths",
None,
Some(&format!("{e}")),
Some(&self.app_win.clone().upcast::<gtk::Window>()),
);
};
@ -466,26 +470,101 @@ impl SimpleComponent for App {
if !missing_deps.is_empty() {
missing_deps.sort_unstable();
missing_deps.dedup(); // dedup only works if sorted, hence the above
let distro = get_distro();
alert(
"Missing dependencies:",
Some(
let distro = LinuxDistro::get();
let (missing_package_list, install_missing_widget): (
String,
Option<gtk::Widget>,
) = if let Some(d) = distro {
(
missing_deps
.iter()
.map(|dep| {
if let Some(d) = distro {
return dep
.packages
.get(&d)
.unwrap_or_else(|| &dep.name)
.clone();
}
dep.name.clone()
dep.packages.get(&d).unwrap_or_else(|| &dep.name).clone()
})
.collect::<Vec<String>>()
.join(", ")
.as_str(),
),
.join(", "),
{
let packages = missing_deps
.iter()
.filter_map(|dep| {
dep.packages.get(&d).and_then(|s| Some(s.clone()))
})
.collect::<Vec<String>>();
if packages.is_empty() {
None
} else {
let cmd = d.install_command(&packages);
{
let container = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.spacing(6)
.build();
let btn = gtk::Button::builder()
.css_classes(["flat", "circular"])
.tooltip_text("Copy")
.icon_name("edit-copy-symbolic")
.vexpand(false)
.hexpand(false)
.valign(gtk::Align::Center)
.halign(gtk::Align::Center)
.build();
btn.connect_clicked(
clone!(@strong cmd => move |_| copy_text(&cmd)),
);
container.append(
&gtk::ScrolledWindow::builder()
.vscrollbar_policy(gtk::PolicyType::Never)
.hscrollbar_policy(gtk::PolicyType::Automatic)
.css_classes(["card"])
.overflow(gtk::Overflow::Hidden)
.child(
&gtk::TextView::builder()
.hexpand(true)
.vexpand(false)
.monospace(true)
.editable(false)
.left_margin(6)
.right_margin(6)
.top_margin(6)
.bottom_margin(18)
.buffer(
&gtk::TextBuffer::builder()
.text(&cmd)
.enable_undo(false)
.build(),
)
.build(),
)
.build(),
);
container.append(&btn);
Some(container.upcast())
}
}
},
)
} else {
(
missing_deps
.iter()
.map(|dep| dep.name.clone())
.collect::<Vec<String>>()
.join(", "),
None,
)
};
alert_w_widget(
"Missing dependencies:",
Some(&format!(
"{}{}",
missing_package_list,
if install_missing_widget.is_some() {
"\n\nYou can install them with the following command:"
} else {
""
}
)),
install_missing_widget.as_ref(),
Some(&self.app_win.clone().upcast::<gtk::Window>()),
);
return;