feat: move steam library folders parser to own module; function to find steam openxr json; format
Some checks failed
/ cargo-fmtcheck (push) Has been cancelled
/ cargo-clippy (push) Has been cancelled
/ cargo-test (push) Has been cancelled
/ appimage (push) Has been cancelled

This commit is contained in:
Gabriele Musco 2024-12-02 18:25:00 +01:00
parent 61f13dbd8f
commit a9fa4f8cf4
15 changed files with 119 additions and 93 deletions

View file

@ -1,7 +1,10 @@
use crate::{
paths::{get_backup_dir, SYSTEM_PREFIX},
profile::Profile,
util::file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
util::{
file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
steam_library_folder::SteamLibraryFolder,
},
xdg::XDG,
};
use serde::{Deserialize, Serialize};
@ -9,6 +12,7 @@ use std::{
fs::remove_file,
path::{Path, PathBuf},
};
use tracing::error;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ActiveRuntimeInnerRuntime {
@ -38,6 +42,23 @@ pub fn is_steam(active_runtime: &ActiveRuntime) -> bool {
matches!(active_runtime.runtime.valve_runtime_is_steamvr, Some(true))
}
pub const STEAMVR_STEAM_APPID: u32 = 250820;
pub fn find_steam_openxr_json() -> Option<PathBuf> {
match SteamLibraryFolder::get_folders() {
Ok(libraryfolders) => libraryfolders
.iter()
.find(|(_, folder)| folder.apps.contains_key(&STEAMVR_STEAM_APPID))
.map(|(_, folder)| {
PathBuf::from(&folder.path).join("steamapps/common/SteamVR/steamxr_linux64.json")
}),
Err(e) => {
error!("unable to find steam openxr json: unable to load steam libraryfolders: {e}");
None
}
}
}
fn get_backup_steam_active_runtime_path() -> PathBuf {
get_backup_dir().join("active_runtime.json.steam.bak")
}

View file

@ -5,7 +5,6 @@ use file_builders::{
openvrpaths_vrpath::{get_current_openvrpaths, set_current_openvrpaths_to_steam},
};
use gettextrs::LocaleCategory;
use tracing::warn;
use relm4::{
adw,
gtk::{self, gdk, gio, glib, prelude::*},
@ -13,6 +12,7 @@ use relm4::{
};
use std::env;
use steam_linux_runtime_injector::restore_runtime_entrypoint;
use tracing::warn;
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
use ui::{
app::{App, AppInit, Msg},

View file

@ -1,76 +1,33 @@
use crate::{
paths::{get_backup_dir, get_home_dir},
paths::get_backup_dir,
profile::Profile,
util::file_utils::{copy_file, get_writer},
util::{
file_utils::{copy_file, get_writer},
steam_library_folder::SteamLibraryFolder,
},
};
use anyhow::bail;
use lazy_static::lazy_static;
use tracing::error;
use serde::Deserialize;
use std::{
collections::HashMap,
fs::read_to_string,
io::Write,
path::{Path, PathBuf},
};
#[derive(Deserialize)]
struct LibraryFolder {
pub path: String,
pub apps: HashMap<u32, usize>,
}
use tracing::error;
pub const PRESSURE_VESSEL_STEAM_APPID: u32 = 1628350;
fn get_steam_main_dir_path() -> anyhow::Result<PathBuf> {
let steam_root: PathBuf = get_home_dir().join(".steam/root");
if steam_root.is_symlink() {
Ok(steam_root.read_link()?)
} else if steam_root.is_dir() {
Ok(steam_root)
} else {
bail!(
"Canonical steam root '{}' is not a dir nor a symlink!",
steam_root.to_string_lossy()
)
}
}
fn parse_steam_libraryfolders_vdf(path: &Path) -> anyhow::Result<HashMap<u32, LibraryFolder>> {
Ok(keyvalues_serde::from_str(read_to_string(path)?.as_str())?)
}
fn get_runtime_entrypoint_path() -> Option<PathBuf> {
match get_steam_main_dir_path() {
Ok(steam_root) => {
let steam_libraryfolders_path = steam_root.join("steamapps/libraryfolders.vdf");
if !steam_libraryfolders_path.is_file() {
error!(
"Steam libraryfolders.vdf does not exist in its canonical location {}",
steam_libraryfolders_path.to_string_lossy()
);
return None;
}
let libraryfolders: HashMap<u32, LibraryFolder> =
parse_steam_libraryfolders_vdf(&steam_libraryfolders_path).ok()?;
libraryfolders
.iter()
.find(|(_, libraryfolder)| {
libraryfolder
.apps
.contains_key(&PRESSURE_VESSEL_STEAM_APPID)
})
.map(|(_, libraryfolder)| {
PathBuf::from(&libraryfolder.path)
.join("steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point")
})
}
match SteamLibraryFolder::get_folders() {
Ok(libraryfolders) => libraryfolders
.iter()
.find(|(_, folder)| folder.apps.contains_key(&PRESSURE_VESSEL_STEAM_APPID))
.map(|(_, folder)| {
PathBuf::from(&folder.path)
.join("steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point")
}),
Err(e) => {
error!("Error getting steam root path: {e}");
error!("unable to get runtime entrypoint path: {e}");
None
}
}
@ -126,22 +83,3 @@ pub fn set_runtime_entrypoint_launch_opts_from_profile(profile: &Profile) -> any
}
bail!("Could not find valid runtime entrypoint");
}
#[cfg(test)]
mod tests {
use std::path::Path;
use super::parse_steam_libraryfolders_vdf;
#[test]
fn deserialize_steam_libraryfolders_vdf() {
let lf = parse_steam_libraryfolders_vdf(Path::new("./test/files/steam_libraryfolders.vdf"))
.unwrap();
assert_eq!(lf.len(), 1);
let first = lf.get(&0).unwrap();
assert_eq!(first.path, "/home/gabmus/.local/share/Steam");
assert_eq!(first.apps.len(), 10);
assert_eq!(first.apps.get(&228980).unwrap(), &29212173);
assert_eq!(first.apps.get(&632360).unwrap(), &0);
}
}

View file

@ -47,7 +47,6 @@ use crate::{
};
use adw::{prelude::*, ResponseAppearance};
use gtk::glib::{self, clone};
use tracing::error;
use notify_rust::NotificationHandle;
use relm4::{
actions::{AccelsPlus, ActionGroupName, RelmAction, RelmActionGroup},
@ -55,6 +54,7 @@ use relm4::{
prelude::*,
};
use std::{collections::VecDeque, fs::remove_file, time::Duration};
use tracing::error;
pub struct App {
application: adw::Application,

View file

@ -6,9 +6,9 @@ use crate::{
profile::{Profile, XRServiceType},
};
use gtk::prelude::*;
use tracing::error;
use relm4::{new_action_group, new_stateless_action, prelude::*};
use std::fs::remove_file;
use tracing::error;
const WIVRN_LATEST_RELEASE_APK_URL: &str =
"https://github.com/WiVRn/WiVRn/releases/latest/download/WiVRn-standard-release.apk";
@ -185,10 +185,7 @@ impl AsyncComponent for InstallWivrnBox {
let existing = cache_file_path(WIVRN_LATEST_RELEASE_APK_URL, Some("apk"));
if existing.is_file() {
if let Err(e) = remove_file(&existing) {
error!(
"failed to remove file {}: {e}",
existing.to_string_lossy()
);
error!("failed to remove file {}: {e}", existing.to_string_lossy());
}
}
sender.input(Self::Input::DoInstall(WIVRN_LATEST_RELEASE_APK_URL.into()));

View file

@ -4,7 +4,6 @@ use self::{
state::JobWorkerState,
};
use crate::profile::Profile;
use tracing::{error, warn};
use nix::sys::signal::{
kill,
Signal::{SIGKILL, SIGTERM},
@ -16,6 +15,7 @@ use std::{
thread::{self, sleep},
time::Duration,
};
use tracing::{error, warn};
pub mod internal_worker;
pub mod job;

View file

@ -30,13 +30,13 @@ use crate::{
};
use adw::{prelude::*, ResponseAppearance};
use gtk::glib::clone;
use tracing::{error, warn};
use relm4::{
actions::{ActionGroupName, RelmAction, RelmActionGroup},
new_action_group, new_stateless_action,
prelude::*,
};
use std::{fs::read_to_string, io::Write};
use tracing::{error, warn};
#[tracker::track]
pub struct MainView {

View file

@ -1,9 +1,9 @@
use crate::{constants::APP_NAME, xdg::XDG};
use tracing::{debug, error};
use relm4::{
gtk::{self, prelude::*},
ComponentParts, ComponentSender, SimpleComponent,
};
use tracing::{debug, error};
#[tracker::track]
pub struct OpenHmdCalibrationBox {

View file

@ -4,7 +4,6 @@ use super::job_worker::{
JobWorker,
};
use crate::paths::get_steamvr_bin_dir_path;
use tracing::error;
use relm4::{
gtk::{self, prelude::*},
ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent,
@ -15,6 +14,7 @@ use std::{
thread::sleep,
time::Duration,
};
use tracing::error;
#[tracker::track]
pub struct SteamVrCalibrationBox {

View file

@ -20,8 +20,8 @@ use crate::{
};
use adw::prelude::*;
use gtk::glib::clone;
use tracing::error;
use relm4::{factory::AsyncFactoryVecDeque, prelude::*};
use tracing::error;
#[tracker::track]
pub struct WivrnConfEditor {

View file

@ -6,8 +6,8 @@ use crate::{
profile::{Profile, XRServiceType},
};
use gtk::prelude::*;
use tracing::error;
use relm4::prelude::*;
use tracing::error;
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum StartClientStatus {

View file

@ -1,6 +1,5 @@
use crate::{async_process::async_process, profile::Profile};
use anyhow::bail;
use tracing::{debug, error};
use nix::{
errno::Errno,
sys::statvfs::{statvfs, FsFlags},
@ -10,6 +9,7 @@ use std::{
io::{BufReader, BufWriter},
path::Path,
};
use tracing::{debug, error};
pub fn get_writer(path: &Path) -> anyhow::Result<BufWriter<std::fs::File>> {
if let Some(parent) = path.parent() {

View file

@ -1,3 +1,4 @@
pub mod file_utils;
pub mod hash;
pub mod steam_library_folder;
pub mod steamvr_utils;

View file

@ -0,0 +1,69 @@
use crate::paths::get_home_dir;
use anyhow::bail;
use serde::Deserialize;
use std::{
collections::HashMap,
fs::read_to_string,
path::{Path, PathBuf},
};
#[derive(Deserialize)]
pub struct SteamLibraryFolder {
pub path: String,
pub apps: HashMap<u32, usize>,
}
fn get_steam_main_dir_path() -> anyhow::Result<PathBuf> {
let steam_root: PathBuf = get_home_dir().join(".steam/root");
if steam_root.is_symlink() {
Ok(steam_root.read_link()?)
} else if steam_root.is_dir() {
Ok(steam_root)
} else {
bail!(
"Canonical steam root '{}' is not a dir nor a symlink!",
steam_root.to_string_lossy()
)
}
}
impl SteamLibraryFolder {
pub fn get_folders() -> anyhow::Result<HashMap<u32, Self>> {
let libraryfolders_path = get_steam_main_dir_path()?.join("steamapps/libraryfolders.vdf");
if !libraryfolders_path.is_file() {
bail!(
"Steam libraryfolders.vdf does not exist in its canonical location {}",
libraryfolders_path.to_string_lossy()
);
}
Self::get_folders_from_path(&libraryfolders_path)
}
/// Do not use this: use get_folders() instead as it always uses Steam's
/// canonical root path. This is intended to be directly used only for
/// unit tests
pub fn get_folders_from_path(p: &Path) -> anyhow::Result<HashMap<u32, Self>> {
Ok(keyvalues_serde::from_str(read_to_string(p)?.as_str())?)
}
}
#[cfg(test)]
mod tests {
use super::SteamLibraryFolder;
use std::path::Path;
#[test]
fn deserialize_steam_libraryfolders_vdf() {
let lf = SteamLibraryFolder::get_folders_from_path(Path::new(
"./test/files/steam_libraryfolders.vdf",
))
.unwrap();
assert_eq!(lf.len(), 1);
let first = lf.get(&0).unwrap();
assert_eq!(first.path, "/home/gabmus/.local/share/Steam");
assert_eq!(first.apps.len(), 10);
assert_eq!(first.apps.get(&228980).unwrap(), &29212173);
assert_eq!(first.apps.get(&632360).unwrap(), &0);
}
}

View file

@ -1,6 +1,6 @@
use libmonado::{self, BatteryStatus, DeviceRole};
use tracing::error;
use std::{collections::HashMap, fmt::Display, slice::Iter};
use tracing::error;
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum XRDeviceRole {