feat: try to connect to openxr service to verify it's running

This commit is contained in:
GabMus 2024-07-25 16:03:10 +00:00
commit adbeffaba1
7 changed files with 202 additions and 27 deletions

View file

@ -23,7 +23,7 @@ cargo:clippy:
RUSTFLAGS: "-Dwarnings"
script:
- apt-get update
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev curl -y
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev libopenxr-dev curl -y
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh
- chmod +x /tmp/rustup.sh
- /tmp/rustup.sh -y
@ -38,7 +38,7 @@ cargo:test:
stage: check
script:
- apt-get update
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev curl -y
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev libopenxr-dev curl -y
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh
- chmod +x /tmp/rustup.sh
- /tmp/rustup.sh -y
@ -55,7 +55,7 @@ appimage:
stage: deploy
script:
- apt-get update
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev curl -y
- apt-get install libgtk-4-dev libadwaita-1-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev libopenxr-dev curl -y
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh
- chmod +x /tmp/rustup.sh
- /tmp/rustup.sh -y

38
Cargo.lock generated
View file

@ -191,7 +191,7 @@ checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
"libloading",
"libloading 0.7.4",
]
[[package]]
@ -278,6 +278,7 @@ dependencies = [
"libadwaita",
"libmonado-rs",
"nix",
"openxr",
"phf",
"phf_macros",
"relm4",
@ -1075,6 +1076,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.48.5",
]
[[package]]
name = "libmonado-rs"
version = "0.1.0"
@ -1254,6 +1265,12 @@ dependencies = [
"tempfile",
]
[[package]]
name = "ndk-context"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
[[package]]
name = "nix"
version = "0.29.0"
@ -1374,6 +1391,25 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "openxr"
version = "0.18.0"
source = "git+https://github.com/galister/openxrs?rev=af4a55d#af4a55df60125491c80c61464c824219c6019b76"
dependencies = [
"libc",
"libloading 0.8.5",
"ndk-context",
"openxr-sys",
]
[[package]]
name = "openxr-sys"
version = "0.10.0"
source = "git+https://github.com/galister/openxrs?rev=af4a55d#af4a55df60125491c80c61464c824219c6019b76"
dependencies = [
"libc",
]
[[package]]
name = "pango"
version = "0.19.5"

View file

@ -26,3 +26,6 @@ tracker = "0.2.1"
uuid = { version = "1.8.0", features = ["v4", "fast-rng"] }
vte4 = { version = "0.7.1", features = ["v0_72"] }
xdg = "2.5.2"
openxr = { git = "https://github.com/galister/openxrs", rev = "af4a55d", features = [
"linked",
] }

View file

@ -34,6 +34,7 @@ pub mod linux_distro;
pub mod log_level;
pub mod log_parser;
pub mod monado_utils;
pub mod openxr_prober;
pub mod paths;
pub mod profile;
pub mod profiles;

39
src/openxr_prober.rs Normal file
View file

@ -0,0 +1,39 @@
// gracefully stolen from https://github.com/galister/wlx-overlay-s/blob/main/src/backend/openxr/helpers.rs#L9
// original code licensed gpl 3
use openxr as xr;
use crate::constants::CMD_NAME;
pub fn is_openxr_ready() -> bool {
let entry = xr::Entry::linked();
if entry.enumerate_extensions().is_err() {
return false;
};
let enabled_extensions = xr::ExtensionSet::default();
let layers = [];
let Ok(xr_instance) = entry.create_instance(
&xr::ApplicationInfo {
application_name: &format!("{}-openxr-prober", CMD_NAME),
application_version: 0,
engine_name: CMD_NAME,
engine_version: 0,
},
&enabled_extensions,
&layers,
) else {
return false;
};
if xr_instance
.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY)
.is_err()
{
return false;
};
true
}

View file

@ -4,7 +4,7 @@ use super::build_window::{BuildStatus, BuildWindow};
use super::cmdline_opts::CmdLineOpts;
use super::debug_view::{DebugView, DebugViewMsg};
use super::job_worker::internal_worker::JobWorkerOut;
use super::job_worker::job::WorkerJob;
use super::job_worker::job::{FuncWorkerOut, WorkerJob};
use super::job_worker::JobWorker;
use super::libsurvive_setup_window::LibsurviveSetupWindow;
use super::main_view::MainViewMsg;
@ -35,6 +35,7 @@ use crate::file_builders::openvrpaths_vrpath::{
use crate::file_utils::setcap_cap_sys_nice_eip;
use crate::is_appimage::IS_APPIMAGE;
use crate::linux_distro::LinuxDistro;
use crate::openxr_prober::is_openxr_ready;
use crate::paths::{get_data_dir, get_ipc_file_path};
use crate::profile::{Profile, XRServiceType};
use crate::stateless_action;
@ -111,6 +112,9 @@ pub struct App {
wivrn_appimage_warn_shown: bool,
#[tracker::do_not_track]
configure_wivrn_action: gtk::gio::SimpleAction,
#[tracker::do_not_track]
openxr_prober_worker: Option<JobWorker>,
}
#[derive(Debug)]
@ -139,6 +143,9 @@ pub enum Msg {
DebugCopyEnvVars,
OpenWivrnConfig,
HandleCommandLine(CmdLineOpts),
StartProber,
OnProberExit(bool),
NoOp,
}
impl App {
@ -203,23 +210,6 @@ impl App {
debug,
);
worker.start();
if let Some(autostart_cmd) = &prof.autostart_command {
let autostart_worker = JobWorker::new_with_timer(
Duration::from_secs(5),
WorkerJob::new_cmd(
Some(prof.environment.clone()),
"sh".into(),
Some(vec!["-c".into(), autostart_cmd.clone()]),
),
sender.input_sender(),
|msg| match msg {
JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows),
JobWorkerOut::Exit(code) => Msg::OnAutostartExit(code),
},
);
autostart_worker.start();
self.autostart_worker = Some(autostart_worker)
}
self.xrservice_worker = Some(worker);
self.main_view
.sender()
@ -233,6 +223,7 @@ impl App {
.sender()
.emit(DebugViewMsg::XRServiceActiveChanged(true));
self.set_inhibit_session(true);
sender.input(Msg::StartProber);
} else {
alert(
"Failed to start profile",
@ -245,6 +236,24 @@ impl App {
}
}
pub fn run_autostart(&mut self, sender: ComponentSender<Self>) {
let prof = self.get_selected_profile();
if let Some(autostart_cmd) = &prof.autostart_command {
let mut jobs = VecDeque::new();
jobs.push_back(WorkerJob::new_cmd(
Some(prof.environment.clone()),
"sh".into(),
Some(vec!["-c".into(), autostart_cmd.clone()]),
));
let autostart_worker = JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows),
JobWorkerOut::Exit(code) => Msg::OnAutostartExit(code),
});
autostart_worker.start();
self.autostart_worker = Some(autostart_worker);
}
}
pub fn restore_openxr_openvr_files(&self) {
restore_runtime_entrypoint();
if let Err(e) = set_current_active_runtime_to_steam() {
@ -264,6 +273,11 @@ impl App {
}
pub fn shutdown_xrservice(&mut self) {
if let Some(w) = self.openxr_prober_worker.as_ref() {
w.stop();
// this can cause threads to remain hanging...
self.openxr_prober_worker = None;
}
self.set_inhibit_session(false);
if let Some(worker) = self.xrservice_worker.as_ref() {
worker.stop();
@ -331,6 +345,7 @@ impl SimpleComponent for App {
self.reset();
match message {
Msg::NoOp => {}
Msg::OnServiceLog(rows) => {
if !rows.is_empty() {
self.debug_view
@ -727,6 +742,50 @@ impl SimpleComponent for App {
self.skip_depcheck = true;
}
}
Msg::StartProber => {
if self
.openxr_prober_worker
.as_ref()
.is_some_and(|w| w.exit_code().is_none())
{
eprintln!(">>>>>>>>>>>>>>> prober already running!");
// prober already running
return;
}
let worker = JobWorker::new_with_timer(
Duration::from_millis(500),
WorkerJob::new_func(Box::new(move || {
println!(">>>>>>>>>>>>>>> probing now <<<<<<<<<<<<<<<<<<");
let ready = is_openxr_ready();
println!(">>>>>>>>>>>>>>> ready? {}", ready);
FuncWorkerOut {
success: ready,
..Default::default()
}
})),
sender.input_sender(),
|msg| match msg {
JobWorkerOut::Exit(code) => Self::Input::OnProberExit(code == 0),
_ => Self::Input::NoOp,
},
);
worker.start();
self.openxr_prober_worker = Some(worker);
}
Msg::OnProberExit(success) => {
self.main_view
.sender()
.emit(MainViewMsg::UpdateXrServiceReady(success));
if success {
self.run_autostart(sender.clone());
} else if self
.xrservice_worker
.as_ref()
.is_some_and(|w| w.exit_code().is_none())
{
sender.input(Msg::StartProber);
}
}
}
}
@ -875,6 +934,7 @@ impl SimpleComponent for App {
skip_depcheck: false,
wivrn_appimage_warn_shown: false,
configure_wivrn_action,
openxr_prober_worker: None,
};
let widgets = view_output!();

View file

@ -8,7 +8,7 @@ use crate::config::Config;
use crate::dependencies::common::dep_pkexec;
use crate::file_utils::mount_has_nosuid;
use crate::gpu_profile::{get_amd_gpu_power_profile, GpuPowerProfile};
use crate::profile::{LighthouseDriver, Profile};
use crate::profile::{LighthouseDriver, Profile, XRServiceType};
use crate::steamvr_utils::chaperone_info_exists;
use crate::ui::app::{
AboutAction, BuildProfileAction, BuildProfileCleanAction, ConfigureWivrnAction,
@ -48,6 +48,7 @@ pub struct MainView {
steamvr_calibration_box: Controller<SteamVrCalibrationBox>,
#[tracker::do_not_track]
root_win: gtk::Window,
xrservice_ready: bool,
}
#[derive(Debug)]
@ -67,6 +68,7 @@ pub enum MainViewMsg {
DuplicateProfile,
SaveProfile(Profile),
UpdateDevices(Vec<XRDevice>),
UpdateXrServiceReady(bool),
}
#[derive(Debug)]
@ -180,6 +182,32 @@ impl SimpleComponent for MainView {
},
},
},
adw::Bin {
#[track = "model.changed(Self::xrservice_active())"]
set_visible: model.xrservice_active,
add_css_class: "card",
gtk::Label {
#[track = "model.changed(Self::xrservice_active()) || model.changed(Self::xrservice_ready())"]
set_label: if model.xrservice_ready {
"Service ready, you can launch XR apps"
} else {
match model.selected_profile.xrservice_type {
XRServiceType::Monado =>
"Starting…",
XRServiceType::Wivrn =>
"Starting, please connect your client device…",
}
},
set_margin_all: 18,
add_css_class: "heading",
add_css_class: "success",
add_css_class: "warning",
#[track = "model.changed(Self::xrservice_active()) || model.changed(Self::xrservice_ready())"]
set_class_active: ("warning", !model.xrservice_ready),
set_wrap: true,
set_justify: gtk::Justification::Center,
},
},
model.devices_box.widget(),
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
@ -424,6 +452,9 @@ impl SimpleComponent for MainView {
.expect("Sender output failed");
}
Self::Input::XRServiceActiveChanged(active, profile, show_launch_opts) => {
if !active {
self.set_xrservice_ready(false);
}
self.set_xrservice_active(active);
self.steamvr_calibration_box
.sender()
@ -536,10 +567,14 @@ impl SimpleComponent for MainView {
);
}
}
Self::Input::UpdateDevices(devs) => self
.devices_box
.sender()
.emit(DevicesBoxMsg::UpdateDevices(devs)),
Self::Input::UpdateDevices(devs) => {
self.devices_box
.sender()
.emit(DevicesBoxMsg::UpdateDevices(devs));
}
Self::Input::UpdateXrServiceReady(ready) => {
self.set_xrservice_ready(ready);
}
}
}
@ -621,6 +656,7 @@ impl SimpleComponent for MainView {
root_win: init.root_win.clone(),
steamvr_calibration_box,
profile_editor: None,
xrservice_ready: false,
tracker: 0,
};
let widgets = view_output!();