mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-04-20 11:35:48 +00:00
feat: move steam library folders parser to own module; function to find steam openxr json; format
This commit is contained in:
parent
61f13dbd8f
commit
a9fa4f8cf4
15 changed files with 119 additions and 93 deletions
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod file_utils;
|
||||
pub mod hash;
|
||||
pub mod steam_library_folder;
|
||||
pub mod steamvr_utils;
|
||||
|
|
69
src/util/steam_library_folder.rs
Normal file
69
src/util/steam_library_folder.rs
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue