mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-04-20 11:35:48 +00:00
feat!: refactor around pathbuf
This commit is contained in:
parent
ec191b4e60
commit
b01eaf69f6
41 changed files with 461 additions and 412 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -289,6 +289,7 @@ dependencies = [
|
|||
"tracker",
|
||||
"uuid",
|
||||
"vte4",
|
||||
"xdg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2528,3 +2529,9 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "2.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
||||
|
|
|
@ -40,3 +40,4 @@ serde_json = "1.0.106"
|
|||
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"
|
||||
|
|
10
src/adb.rs
10
src/adb.rs
|
@ -1,12 +1,12 @@
|
|||
use crate::cmd_runner::CmdRunner;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_adb_install_runner(apk_path: &String) -> CmdRunner {
|
||||
let path = Path::new(apk_path);
|
||||
use crate::cmd_runner::CmdRunner;
|
||||
|
||||
pub fn get_adb_install_runner(path: &PathBuf) -> CmdRunner {
|
||||
path.try_exists().expect("APK file provided does not exist");
|
||||
CmdRunner::new(
|
||||
None,
|
||||
"adb".into(),
|
||||
vec!["install".into(), path.to_str().unwrap().to_string()],
|
||||
vec!["install".into(), path.to_string_lossy().to_string()],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::ui::job_worker::job::WorkerJob;
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cmake {
|
||||
pub build_dir: String,
|
||||
pub source_dir: String,
|
||||
pub build_dir: PathBuf,
|
||||
pub source_dir: PathBuf,
|
||||
pub vars: Option<HashMap<String, String>>,
|
||||
pub env: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ impl Cmake {
|
|||
pub fn get_prepare_job(&self) -> WorkerJob {
|
||||
let mut args = vec![
|
||||
"-B".into(),
|
||||
self.build_dir.clone(),
|
||||
self.build_dir.to_string_lossy().to_string(),
|
||||
"-G".into(),
|
||||
"Ninja".into(),
|
||||
];
|
||||
|
@ -29,7 +29,7 @@ impl Cmake {
|
|||
}
|
||||
}
|
||||
}
|
||||
args.push(self.source_dir.clone());
|
||||
args.push(self.source_dir.to_string_lossy().to_string());
|
||||
WorkerJob::new_cmd(self.env.clone(), "cmake".into(), Some(args))
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,10 @@ impl Cmake {
|
|||
WorkerJob::new_cmd(
|
||||
self.env.clone(),
|
||||
"cmake".into(),
|
||||
Some(vec!["--build".into(), self.build_dir.clone()]),
|
||||
Some(vec![
|
||||
"--build".into(),
|
||||
self.build_dir.to_string_lossy().to_string(),
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -45,7 +48,10 @@ impl Cmake {
|
|||
WorkerJob::new_cmd(
|
||||
self.env.clone(),
|
||||
"cmake".into(),
|
||||
Some(vec!["--install".into(), self.build_dir.clone()]),
|
||||
Some(vec![
|
||||
"--install".into(),
|
||||
self.build_dir.to_string_lossy().to_string(),
|
||||
]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use crate::ui::job_worker::job::{FuncWorkerOut, WorkerJob};
|
||||
use git2::Repository;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Git {
|
||||
pub repo: String,
|
||||
pub dir: String,
|
||||
pub dir: PathBuf,
|
||||
pub branch: String,
|
||||
}
|
||||
|
||||
impl Git {
|
||||
fn cmd(&self, args: Vec<String>) -> WorkerJob {
|
||||
let mut nargs = vec!["-C".into(), self.dir.clone()];
|
||||
let mut nargs = vec!["-C".into(), self.dir.to_string_lossy().to_string()];
|
||||
nargs.extend(args);
|
||||
WorkerJob::new_cmd(None, "git".into(), Some(nargs))
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ impl Git {
|
|||
Some(vec![
|
||||
"clone".into(),
|
||||
self.get_repo(),
|
||||
self.dir.clone(),
|
||||
self.dir.to_string_lossy().to_string(),
|
||||
"--recurse-submodules".into(),
|
||||
]),
|
||||
)
|
||||
|
@ -101,8 +101,7 @@ impl Git {
|
|||
}
|
||||
|
||||
pub fn clone_exists(&self) -> bool {
|
||||
let path_s = format!("{}/.git", self.dir.clone());
|
||||
Path::new(&path_s).is_dir()
|
||||
self.dir.join(".git").is_dir()
|
||||
}
|
||||
|
||||
pub fn get_pre_build_jobs(&self, pull_on_build: bool) -> Vec<WorkerJob> {
|
||||
|
|
|
@ -4,10 +4,7 @@ use crate::{
|
|||
profile::Profile,
|
||||
ui::job_worker::job::WorkerJob,
|
||||
};
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
path::Path,
|
||||
};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<WorkerJob> {
|
||||
let mut jobs = VecDeque::<WorkerJob>::new();
|
||||
|
@ -32,16 +29,19 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!("{}/build", profile.features.basalt.path.as_ref().unwrap());
|
||||
let build_dir = profile.features.basalt.path.as_ref().unwrap().join("build");
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert("BUILD_TESTS".into(), "OFF".into());
|
||||
cmake_vars.insert("BASALT_INSTANTIATIONS_DOUBLE".into(), "OFF".into());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_LIBDIR".into(),
|
||||
format!("{}/lib", profile.prefix),
|
||||
profile.prefix.join("lib").to_string_lossy().to_string(),
|
||||
);
|
||||
|
||||
let mut cmake_env: HashMap<String, String> = HashMap::new();
|
||||
|
@ -56,7 +56,7 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
build_dir: build_dir.clone(),
|
||||
};
|
||||
|
||||
if !Path::new(&build_dir).is_dir() || clean_build {
|
||||
if !build_dir.is_dir() || clean_build {
|
||||
rm_rf(&build_dir);
|
||||
jobs.push_back(cmake.get_prepare_job());
|
||||
}
|
||||
|
@ -68,10 +68,11 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
"mkdir".into(),
|
||||
Some(vec![
|
||||
"-p".into(),
|
||||
format!(
|
||||
"{}/share/basalt/thirdparty/basalt-headers/thirdparty",
|
||||
profile.prefix
|
||||
),
|
||||
profile
|
||||
.prefix
|
||||
.join("share/basalt/thirdparty/basalt-headers/thirdparty")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
]),
|
||||
));
|
||||
jobs.push_back(WorkerJob::new_cmd(
|
||||
|
@ -79,11 +80,20 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
"cp".into(),
|
||||
Some(vec![
|
||||
"-Ra".into(),
|
||||
format!(
|
||||
"{}/thirdparty/basalt-headers/thirdparty/eigen",
|
||||
profile.features.basalt.path.as_ref().unwrap().clone()
|
||||
),
|
||||
format!("{}/share/basalt/thirdparty", profile.prefix),
|
||||
profile
|
||||
.features
|
||||
.basalt
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.join("thirdparty/basalt-headers/thirdparty/eigen")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
profile
|
||||
.prefix
|
||||
.join("share/basalt/thirdparty")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
]),
|
||||
));
|
||||
|
||||
|
|
|
@ -32,20 +32,26 @@ pub fn get_build_libsurvive_jobs(profile: &Profile, clean_build: bool) -> VecDeq
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!(
|
||||
"{}/build",
|
||||
profile.features.libsurvive.path.as_ref().unwrap()
|
||||
);
|
||||
let build_dir = profile
|
||||
.features
|
||||
.libsurvive
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.join("build");
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
cmake_vars.insert("ENABLE_api_example".into(), "OFF".into());
|
||||
cmake_vars.insert("USE_HIDAPI".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_SKIP_INSTALL_RPATH".into(), "YES".into());
|
||||
cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_LIBDIR".into(),
|
||||
format!("{}/lib", profile.prefix),
|
||||
profile.prefix.join("lib").to_string_lossy().to_string(),
|
||||
);
|
||||
|
||||
let cmake = Cmake {
|
||||
|
|
|
@ -5,10 +5,13 @@ use crate::{
|
|||
pub fn get_build_mercury_job(profile: &Profile) -> WorkerJob {
|
||||
WorkerJob::new_cmd(
|
||||
None,
|
||||
format!(
|
||||
"{sysdata}/scripts/build_mercury.sh",
|
||||
sysdata = pkg_data_dir()
|
||||
),
|
||||
Some(vec![profile.prefix.clone(), get_cache_dir()]),
|
||||
pkg_data_dir()
|
||||
.join("scripts/build_mercury.sh")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
Some(vec![
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
get_cache_dir().to_string_lossy().to_string(),
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -28,25 +28,41 @@ pub fn get_build_monado_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!("{}/build", profile.xrservice_path);
|
||||
let build_dir = profile.xrservice_path.join("build");
|
||||
let mut env: HashMap<String, String> = HashMap::new();
|
||||
env.insert(
|
||||
"PKG_CONFIG_PATH".into(),
|
||||
format!("{}/lib/pkgconfig", profile.prefix),
|
||||
profile
|
||||
.prefix
|
||||
.join("lib/pkgconfig")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
);
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
cmake_vars.insert("XRT_HAVE_SYSTEM_CJSON".into(), "NO".into());
|
||||
cmake_vars.insert("CMAKE_LIBDIR".into(), format!("{}/lib", profile.prefix));
|
||||
cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_LIBDIR".into(),
|
||||
profile.prefix.join("lib").to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert(
|
||||
"CMAKE_C_FLAGS".into(),
|
||||
format!("-Wl,-rpath='{}/lib'", profile.prefix,),
|
||||
format!(
|
||||
"-Wl,-rpath='{}/lib'",
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
),
|
||||
);
|
||||
cmake_vars.insert(
|
||||
"CMAKE_CXX_FLAGS".into(),
|
||||
format!("-Wl,-rpath='{}/lib'", profile.prefix,),
|
||||
format!(
|
||||
"-Wl,-rpath='{}/lib'",
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
),
|
||||
);
|
||||
profile.xrservice_cmake_flags.iter().for_each(|(k, v)| {
|
||||
if k == "CMAKE_C_FLAGS" || k == "CMAKE_CXX_FLAGS" {
|
||||
|
|
|
@ -28,7 +28,7 @@ pub fn get_build_opencomposite_jobs(profile: &Profile, clean_build: bool) -> Vec
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!("{}/build", profile.opencomposite_path);
|
||||
let build_dir = profile.opencomposite_path.join("build");
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
|
|
|
@ -32,14 +32,23 @@ pub fn get_build_openhmd_jobs(profile: &Profile, clean_build: bool) -> VecDeque<
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!("{}/build", profile.features.openhmd.path.as_ref().unwrap());
|
||||
let build_dir = profile
|
||||
.features
|
||||
.openhmd
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.join("build");
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_LIBDIR".into(),
|
||||
format!("{}/lib", profile.prefix),
|
||||
profile.prefix.join("lib").to_string_lossy().to_string(),
|
||||
);
|
||||
cmake_vars.insert("OPENHMD_DRIVER_OCULUS_RIFT_S".into(), "OFF".into());
|
||||
|
||||
|
|
|
@ -28,13 +28,16 @@ pub fn get_build_wivrn_jobs(profile: &Profile, clean_build: bool) -> VecDeque<Wo
|
|||
|
||||
jobs.extend(git.get_pre_build_jobs(profile.pull_on_build));
|
||||
|
||||
let build_dir = format!("{}/build", profile.xrservice_path);
|
||||
let build_dir = profile.xrservice_path.join("build");
|
||||
let mut cmake_vars: HashMap<String, String> = HashMap::new();
|
||||
cmake_vars.insert("CMAKE_EXPORT_COMPILE_COMMANDS".into(), "ON".into());
|
||||
cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "RelWithDebInfo".into());
|
||||
cmake_vars.insert("XRT_HAVE_SYSTEM_CJSON".into(), "NO".into());
|
||||
cmake_vars.insert("WIVRN_BUILD_CLIENT".into(), "OFF".into());
|
||||
cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone());
|
||||
cmake_vars.insert(
|
||||
"CMAKE_INSTALL_PREFIX".into(),
|
||||
profile.prefix.to_string_lossy().to_string(),
|
||||
);
|
||||
|
||||
profile.xrservice_cmake_flags.iter().for_each(|(k, v)| {
|
||||
cmake_vars.insert(k.clone(), v.clone());
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
io::{BufRead, BufReader, Write},
|
||||
path::PathBuf,
|
||||
process::{Child, Command, Stdio},
|
||||
sync::{
|
||||
mpsc::{sync_channel, Receiver, SyncSender},
|
||||
|
@ -99,9 +100,11 @@ impl CmdRunner {
|
|||
Self::new(
|
||||
Some(env),
|
||||
match profile.xrservice_type {
|
||||
XRServiceType::Monado => format!("{pfx}/bin/monado-service", pfx = profile.prefix),
|
||||
XRServiceType::Wivrn => format!("{pfx}/bin/wivrn-server", pfx = profile.prefix),
|
||||
},
|
||||
XRServiceType::Monado => profile.prefix.join("bin/monado-service"),
|
||||
XRServiceType::Wivrn => profile.prefix.join("bin/wivrn-server"),
|
||||
}
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
vec![],
|
||||
)
|
||||
}
|
||||
|
@ -171,13 +174,13 @@ impl CmdRunner {
|
|||
}
|
||||
}
|
||||
|
||||
fn save_log(path_s: String, log: &[String]) -> Result<(), std::io::Error> {
|
||||
let mut writer = get_writer(&path_s).map_err(std::io::Error::other)?;
|
||||
fn save_log(path: &PathBuf, log: &[String]) -> Result<(), std::io::Error> {
|
||||
let mut writer = get_writer(path).map_err(std::io::Error::other)?;
|
||||
let log_s = log.concat();
|
||||
writer.write_all(log_s.as_ref())
|
||||
}
|
||||
|
||||
pub fn save_output(&mut self, path: String) -> Result<(), std::io::Error> {
|
||||
pub fn save_output(&mut self, path: &PathBuf) -> Result<(), std::io::Error> {
|
||||
CmdRunner::save_log(path, &self.output)
|
||||
}
|
||||
}
|
||||
|
@ -251,14 +254,14 @@ mod tests {
|
|||
}
|
||||
|
||||
runner
|
||||
.save_output("./target/testout/testlog".into())
|
||||
.save_output(&"./target/testout/testlog".into())
|
||||
.expect("Failed to save output file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_create_from_profile() {
|
||||
CmdRunner::xrservice_runner_from_profile(&Profile::load_profile(
|
||||
&"./test/files/profile.json".to_string(),
|
||||
&"./test/files/profile.json".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use serde::{de::Error, Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
constants::CMD_NAME,
|
||||
device_prober::get_xr_usb_devices,
|
||||
|
@ -9,8 +11,7 @@ use crate::{
|
|||
survive::survive_profile, wivrn::wivrn_profile, wmr::wmr_profile,
|
||||
},
|
||||
};
|
||||
use serde::{ser::Error, Deserialize, Serialize};
|
||||
use std::{fs::File, io::BufReader};
|
||||
use std::{fs::File, io::BufReader, path::PathBuf};
|
||||
|
||||
fn default_win_size() -> [i32; 2] {
|
||||
[360, 400]
|
||||
|
@ -56,16 +57,12 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn config_file_path() -> String {
|
||||
format!(
|
||||
"{config}/{name}.json",
|
||||
config = get_config_dir(),
|
||||
name = CMD_NAME
|
||||
)
|
||||
pub fn config_file_path() -> PathBuf {
|
||||
get_config_dir().join(format!("{CMD_NAME}.json"))
|
||||
}
|
||||
|
||||
fn from_path(path_s: String) -> Self {
|
||||
match File::open(path_s) {
|
||||
fn from_path(path: &PathBuf) -> Self {
|
||||
match File::open(path) {
|
||||
Ok(file) => {
|
||||
let reader = BufReader::new(file);
|
||||
match serde_json::from_reader(reader) {
|
||||
|
@ -77,8 +74,8 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn save_to_path(&self, path_s: &String) -> Result<(), serde_json::Error> {
|
||||
let writer = get_writer(path_s).map_err(serde_json::Error::custom)?;
|
||||
fn save_to_path(&self, path: &PathBuf) -> Result<(), serde_json::Error> {
|
||||
let writer = get_writer(path).map_err(serde_json::Error::custom)?;
|
||||
serde_json::to_writer_pretty(writer, self)
|
||||
}
|
||||
|
||||
|
@ -88,7 +85,7 @@ impl Config {
|
|||
}
|
||||
|
||||
pub fn get_config() -> Self {
|
||||
Self::from_path(Self::config_file_path())
|
||||
Self::from_path(&Self::config_file_path())
|
||||
}
|
||||
|
||||
pub fn set_profiles(&mut self, profiles: &[Profile]) {
|
||||
|
@ -117,7 +114,7 @@ mod tests {
|
|||
#[test]
|
||||
fn will_load_default_if_config_does_not_exist() {
|
||||
assert_eq!(
|
||||
Config::from_path("/non/existing/file.json".into()).debug_view_enabled,
|
||||
Config::from_path(&"/non/existing/file.json".into()).debug_view_enabled,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::paths::get_exec_prefix;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const APP_NAME: &str = "@PRETTY_NAME@";
|
||||
pub const APP_ID: &str = "@APP_ID@";
|
||||
pub const RESOURCES_BASE_PATH: &str = "@RESOURCES_BASE_PATH@";
|
||||
|
@ -17,10 +19,10 @@ pub fn get_developers() -> Vec<String> {
|
|||
vec!["Gabriele Musco <gabmus@disroot.org>".to_string()]
|
||||
}
|
||||
|
||||
pub fn pkg_data_dir() -> String {
|
||||
format!("{}/share/{}", get_exec_prefix(), CMD_NAME)
|
||||
pub fn pkg_data_dir() -> PathBuf {
|
||||
get_exec_prefix().join("share").join(CMD_NAME)
|
||||
}
|
||||
|
||||
pub fn resources() -> String {
|
||||
format!("{}/resources.gresource", pkg_data_dir())
|
||||
format!("{}/resources.gresource", pkg_data_dir().to_string_lossy().to_string())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use reqwest::{
|
|||
header::{HeaderMap, USER_AGENT},
|
||||
Method,
|
||||
};
|
||||
use std::{io::prelude::*, thread::JoinHandle};
|
||||
use std::{io::prelude::*, path::PathBuf, thread::JoinHandle};
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
@ -23,7 +23,7 @@ fn client() -> reqwest::blocking::Client {
|
|||
.expect("Failed to build reqwest::Client")
|
||||
}
|
||||
|
||||
pub fn download_file(url: String, path: String) -> JoinHandle<Result<(), reqwest::Error>> {
|
||||
pub fn download_file(url: String, path: PathBuf) -> JoinHandle<Result<(), reqwest::Error>> {
|
||||
thread::spawn(move || {
|
||||
let client = client();
|
||||
match client.request(Method::GET, url).send() {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
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},
|
||||
paths::{get_backup_dir, SYSTEM_PREFIX},
|
||||
profile::{Profile, XRServiceType},
|
||||
xdg::XDG,
|
||||
};
|
||||
use serde::{ser::Error, Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -10,9 +11,9 @@ use std::path::{Path, PathBuf};
|
|||
pub struct ActiveRuntimeInnerRuntime {
|
||||
#[serde(rename = "VALVE_runtime_is_steamvr")]
|
||||
pub valve_runtime_is_steamvr: Option<bool>,
|
||||
pub library_path: String,
|
||||
#[serde(rename = "MND_libmonado_path")]
|
||||
pub libmonado_path: Option<PathBuf>,
|
||||
pub library_path: PathBuf,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -22,26 +23,20 @@ pub struct ActiveRuntime {
|
|||
pub runtime: ActiveRuntimeInnerRuntime,
|
||||
}
|
||||
|
||||
pub fn get_openxr_conf_dir() -> String {
|
||||
format!("{config}/openxr", config = get_xdg_config_dir())
|
||||
pub fn get_openxr_conf_dir() -> PathBuf {
|
||||
XDG.get_config_home().join("openxr")
|
||||
}
|
||||
|
||||
fn get_active_runtime_json_path() -> String {
|
||||
format!(
|
||||
"{config}/1/active_runtime.json",
|
||||
config = get_openxr_conf_dir()
|
||||
)
|
||||
fn get_active_runtime_json_path() -> PathBuf {
|
||||
get_openxr_conf_dir().join("1/active_runtime.json")
|
||||
}
|
||||
|
||||
pub fn is_steam(active_runtime: &ActiveRuntime) -> bool {
|
||||
matches!(active_runtime.runtime.valve_runtime_is_steamvr, Some(true))
|
||||
}
|
||||
|
||||
fn get_backup_steam_active_runtime_path() -> String {
|
||||
format!(
|
||||
"{backup}/active_runtime.json.steam.bak",
|
||||
backup = get_backup_dir()
|
||||
)
|
||||
fn get_backup_steam_active_runtime_path() -> PathBuf {
|
||||
get_backup_dir().join("active_runtime.json.steam.bak")
|
||||
}
|
||||
|
||||
fn get_backed_up_steam_active_runtime() -> Option<ActiveRuntime> {
|
||||
|
@ -59,8 +54,8 @@ fn backup_steam_active_runtime() {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_active_runtime_from_path(path_s: &String) -> Option<ActiveRuntime> {
|
||||
deserialize_file(path_s)
|
||||
fn get_active_runtime_from_path(path: &PathBuf) -> Option<ActiveRuntime> {
|
||||
deserialize_file(path)
|
||||
}
|
||||
|
||||
pub fn get_current_active_runtime() -> Option<ActiveRuntime> {
|
||||
|
@ -69,9 +64,9 @@ pub fn get_current_active_runtime() -> Option<ActiveRuntime> {
|
|||
|
||||
fn dump_active_runtime_to_path(
|
||||
active_runtime: &ActiveRuntime,
|
||||
path_s: &String,
|
||||
path: &PathBuf,
|
||||
) -> Result<(), serde_json::Error> {
|
||||
let writer = get_writer(path_s).map_err(serde_json::Error::custom)?;
|
||||
let writer = get_writer(path).map_err(serde_json::Error::custom)?;
|
||||
serde_json::to_writer_pretty(writer, active_runtime)
|
||||
}
|
||||
|
||||
|
@ -89,11 +84,10 @@ fn build_steam_active_runtime() -> ActiveRuntime {
|
|||
file_format_version: "1.0.0".into(),
|
||||
runtime: ActiveRuntimeInnerRuntime {
|
||||
valve_runtime_is_steamvr: Some(true),
|
||||
library_path: format!(
|
||||
"{data}/Steam/steamapps/common/SteamVR/bin/linux64/vrclient.so",
|
||||
data = get_xdg_data_dir()
|
||||
),
|
||||
libmonado_path: None,
|
||||
library_path: XDG
|
||||
.get_data_home()
|
||||
.join("Steam/steamapps/common/SteamVR/bin/linux64/vrclient.so"),
|
||||
name: Some("SteamVR".into()),
|
||||
},
|
||||
}
|
||||
|
@ -144,26 +138,25 @@ pub fn build_profile_active_runtime(profile: &Profile) -> ActiveRuntime {
|
|||
name: None,
|
||||
valve_runtime_is_steamvr: None,
|
||||
libmonado_path: monado_so,
|
||||
library_path: oxr_so.to_string_lossy().into_owned(),
|
||||
library_path: oxr_so,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// for system installs
|
||||
fn relativize_active_runtime_lib_path(ar: &ActiveRuntime, dest: &str) -> ActiveRuntime {
|
||||
fn relativize_active_runtime_lib_path(ar: &ActiveRuntime, path: &PathBuf) -> ActiveRuntime {
|
||||
let mut res = ar.clone();
|
||||
let path = Path::new(dest);
|
||||
let mut rel_chain = path
|
||||
.components()
|
||||
.map(|_| String::from(".."))
|
||||
.collect::<Vec<String>>();
|
||||
rel_chain.pop();
|
||||
rel_chain.pop();
|
||||
res.runtime.library_path = format!(
|
||||
res.runtime.library_path = PathBuf::from(format!(
|
||||
"{rels}{fullpath}",
|
||||
rels = rel_chain.join("/"),
|
||||
fullpath = ar.runtime.library_path
|
||||
);
|
||||
fullpath = ar.runtime.library_path.to_string_lossy()
|
||||
));
|
||||
res
|
||||
}
|
||||
|
||||
|
@ -174,7 +167,7 @@ pub fn set_current_active_runtime_to_profile(profile: &Profile) -> anyhow::Resul
|
|||
let pfx = profile.clone().prefix;
|
||||
let mut ar = build_profile_active_runtime(profile);
|
||||
// hack: relativize libopenxr_monado.so path for system installs
|
||||
if pfx == SYSTEM_PREFIX {
|
||||
if pfx == PathBuf::from(SYSTEM_PREFIX) {
|
||||
ar = relativize_active_runtime_lib_path(&ar, &dest);
|
||||
}
|
||||
dump_current_active_runtime(&ar)?;
|
||||
|
@ -184,6 +177,8 @@ pub fn set_current_active_runtime_to_profile(profile: &Profile) -> anyhow::Resul
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::{
|
||||
dump_active_runtime_to_path, get_active_runtime_from_path,
|
||||
relativize_active_runtime_lib_path, ActiveRuntime, ActiveRuntimeInnerRuntime,
|
||||
|
@ -197,7 +192,9 @@ mod tests {
|
|||
assert!(ar.runtime.valve_runtime_is_steamvr.unwrap());
|
||||
assert_eq!(
|
||||
ar.runtime.library_path,
|
||||
"/home/user/.local/share/Steam/steamapps/common/SteamVR/bin/linux64/vrclient.so"
|
||||
PathBuf::from(
|
||||
"/home/user/.local/share/Steam/steamapps/common/SteamVR/bin/linux64/vrclient.so"
|
||||
)
|
||||
);
|
||||
assert_eq!(ar.runtime.name.unwrap(), "SteamVR");
|
||||
}
|
||||
|
@ -232,10 +229,14 @@ mod tests {
|
|||
};
|
||||
let relativized = relativize_active_runtime_lib_path(
|
||||
&ar,
|
||||
"/home/user/.config/openxr/1/active_runtime.json",
|
||||
&PathBuf::from("/home/user/.config/openxr/1/active_runtime.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
relativized.runtime.library_path,
|
||||
relativized
|
||||
.runtime
|
||||
.library_path
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
"../../../../../usr/lib64/libopenxr_monado.so"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
file_utils::{deserialize_file, get_writer},
|
||||
paths::get_xdg_config_dir,
|
||||
xdg::XDG,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -28,15 +30,12 @@ impl Default for MonadoAutorunConfig {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_monado_autorun_config_path() -> String {
|
||||
format!(
|
||||
"{config}/monado/autorun_v0.json",
|
||||
config = get_xdg_config_dir()
|
||||
)
|
||||
fn get_monado_autorun_config_path() -> PathBuf {
|
||||
XDG.get_config_home().join("monado/autorun_v0.json")
|
||||
}
|
||||
|
||||
fn get_monado_autorun_config_from_path(path_s: &String) -> Option<MonadoAutorunConfig> {
|
||||
deserialize_file(path_s)
|
||||
fn get_monado_autorun_config_from_path(path: &PathBuf) -> Option<MonadoAutorunConfig> {
|
||||
deserialize_file(path)
|
||||
}
|
||||
|
||||
pub fn get_monado_autorun_config() -> MonadoAutorunConfig {
|
||||
|
@ -44,8 +43,8 @@ pub fn get_monado_autorun_config() -> MonadoAutorunConfig {
|
|||
.unwrap_or(MonadoAutorunConfig::default())
|
||||
}
|
||||
|
||||
fn dump_monado_autorun_config_to_path(config: &MonadoAutorunConfig, path_s: &String) {
|
||||
let writer = get_writer(path_s).expect("Unable to save Monado Autorun config");
|
||||
fn dump_monado_autorun_config_to_path(config: &MonadoAutorunConfig, path: &PathBuf) {
|
||||
let writer = get_writer(path).expect("Unable to save Monado Autorun config");
|
||||
serde_json::to_writer_pretty(writer, config).expect("Unable to save Monado Autorun config");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,43 +1,41 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
|
||||
paths::{get_backup_dir, get_xdg_config_dir, get_xdg_data_dir},
|
||||
paths::get_backup_dir,
|
||||
profile::Profile,
|
||||
xdg::XDG,
|
||||
};
|
||||
use serde::{ser::Error, Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct OpenVrPaths {
|
||||
config: Vec<String>,
|
||||
config: Vec<PathBuf>,
|
||||
external_drivers: Option<Vec<String>>, // never seen it populated
|
||||
jsonid: String,
|
||||
log: Vec<String>,
|
||||
runtime: Vec<String>,
|
||||
log: Vec<PathBuf>,
|
||||
runtime: Vec<PathBuf>,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
pub fn get_openvr_conf_dir() -> String {
|
||||
format!("{config}/openvr", config = get_xdg_config_dir())
|
||||
pub fn get_openvr_conf_dir() -> PathBuf {
|
||||
XDG.get_config_home().join("openvr")
|
||||
}
|
||||
|
||||
fn get_openvrpaths_vrpath_path() -> String {
|
||||
format!(
|
||||
"{config}/openvrpaths.vrpath",
|
||||
config = get_openvr_conf_dir()
|
||||
)
|
||||
fn get_openvrpaths_vrpath_path() -> PathBuf {
|
||||
get_openvr_conf_dir().join("openvrpaths.vrpath")
|
||||
}
|
||||
|
||||
pub fn is_steam(ovr_paths: &OpenVrPaths) -> bool {
|
||||
ovr_paths.runtime.iter().any(|rt| {
|
||||
rt.to_lowercase()
|
||||
rt.to_string_lossy()
|
||||
.to_lowercase()
|
||||
.ends_with("/steam/steamapps/common/steamvr")
|
||||
})
|
||||
}
|
||||
|
||||
fn get_backup_steam_openvrpaths_path() -> String {
|
||||
format!(
|
||||
"{backup}/openvrpaths.vrpath.steam.bak",
|
||||
backup = get_backup_dir()
|
||||
)
|
||||
fn get_backup_steam_openvrpaths_path() -> PathBuf {
|
||||
get_backup_dir().join("openvrpaths.vrpath.steam.bak")
|
||||
}
|
||||
|
||||
fn get_backed_up_steam_openvrpaths() -> Option<OpenVrPaths> {
|
||||
|
@ -55,8 +53,8 @@ fn backup_steam_openvrpaths() {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_openvrpaths_from_path(path_s: &String) -> Option<OpenVrPaths> {
|
||||
deserialize_file(path_s)
|
||||
fn get_openvrpaths_from_path(path: &PathBuf) -> Option<OpenVrPaths> {
|
||||
deserialize_file(path)
|
||||
}
|
||||
|
||||
pub fn get_current_openvrpaths() -> Option<OpenVrPaths> {
|
||||
|
@ -65,9 +63,9 @@ pub fn get_current_openvrpaths() -> Option<OpenVrPaths> {
|
|||
|
||||
fn dump_openvrpaths_to_path(
|
||||
ovr_paths: &OpenVrPaths,
|
||||
path_s: &String,
|
||||
path: &PathBuf,
|
||||
) -> Result<(), serde_json::Error> {
|
||||
let writer = get_writer(path_s).map_err(serde_json::Error::custom)?;
|
||||
let writer = get_writer(path).map_err(serde_json::Error::custom)?;
|
||||
serde_json::to_writer_pretty(writer, ovr_paths)
|
||||
}
|
||||
|
||||
|
@ -79,16 +77,13 @@ fn build_steam_openvrpaths() -> OpenVrPaths {
|
|||
if let Some(backup) = get_backed_up_steam_openvrpaths() {
|
||||
return backup;
|
||||
}
|
||||
let datadir = get_xdg_data_dir();
|
||||
let datadir = XDG.get_data_home();
|
||||
OpenVrPaths {
|
||||
config: vec![format!("{data}/Steam/config", data = datadir)],
|
||||
config: vec![datadir.join("Steam/config")],
|
||||
external_drivers: None,
|
||||
jsonid: "vrpathreg".into(),
|
||||
log: vec![format!("{data}/Steam/logs", data = datadir)],
|
||||
runtime: vec![format!(
|
||||
"{data}/Steam/steamapps/common/SteamVR",
|
||||
data = datadir
|
||||
)],
|
||||
log: vec![datadir.join("Steam/logs")],
|
||||
runtime: vec![datadir.join("Steam/steamapps/common/SteamVR")],
|
||||
version: 1,
|
||||
}
|
||||
}
|
||||
|
@ -100,16 +95,13 @@ pub fn set_current_openvrpaths_to_steam() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths {
|
||||
let datadir = get_xdg_data_dir();
|
||||
let datadir = XDG.get_data_home();
|
||||
OpenVrPaths {
|
||||
config: vec![format!("{data}/Steam/config", data = datadir)],
|
||||
config: vec![datadir.join("Steam/config")],
|
||||
external_drivers: None,
|
||||
jsonid: "vrpathreg".into(),
|
||||
log: vec![format!("{data}/Steam/logs", data = datadir)],
|
||||
runtime: vec![format!(
|
||||
"{opencomp_dir}/build",
|
||||
opencomp_dir = profile.opencomposite_path
|
||||
)],
|
||||
log: vec![datadir.join("Steam/logs")],
|
||||
runtime: vec![profile.opencomposite_path.join("build")],
|
||||
version: 1,
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +117,8 @@ pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::{dump_openvrpaths_to_path, get_openvrpaths_from_path, OpenVrPaths};
|
||||
|
||||
#[test]
|
||||
|
@ -133,7 +127,7 @@ mod tests {
|
|||
assert_eq!(ovrp.config.len(), 1);
|
||||
assert_eq!(
|
||||
ovrp.config.get(0).unwrap(),
|
||||
"/home/user/.local/share/Steam/config"
|
||||
&PathBuf::from("/home/user/.local/share/Steam/config")
|
||||
);
|
||||
assert_eq!(ovrp.external_drivers, None);
|
||||
assert_eq!(ovrp.jsonid, "vrpathreg");
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
file_utils::{deserialize_file, get_writer},
|
||||
paths::get_xdg_config_dir,
|
||||
xdg::XDG,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fmt::Display, slice::Iter};
|
||||
use std::{fmt::Display, path::PathBuf, slice::Iter};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
|
@ -123,20 +123,20 @@ impl Default for WivrnConfig {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_wivrn_config_path() -> String {
|
||||
format!("{config}/wivrn/config.json", config = get_xdg_config_dir())
|
||||
fn get_wivrn_config_path() -> PathBuf {
|
||||
XDG.get_config_home().join("wivrn/config.json")
|
||||
}
|
||||
|
||||
fn get_wivrn_config_from_path(path_s: &String) -> Option<WivrnConfig> {
|
||||
deserialize_file(path_s)
|
||||
fn get_wivrn_config_from_path(path: &PathBuf) -> Option<WivrnConfig> {
|
||||
deserialize_file(path)
|
||||
}
|
||||
|
||||
pub fn get_wivrn_config() -> WivrnConfig {
|
||||
get_wivrn_config_from_path(&get_wivrn_config_path()).unwrap_or(WivrnConfig::default())
|
||||
}
|
||||
|
||||
fn dump_wivrn_config_to_path(config: &WivrnConfig, path_s: &String) {
|
||||
let writer = get_writer(path_s).expect("Unable to save WiVRn config");
|
||||
fn dump_wivrn_config_to_path(config: &WivrnConfig, path: &PathBuf) {
|
||||
let writer = get_writer(path).expect("Unable to save WiVRn config");
|
||||
serde_json::to_writer_pretty(writer, config).expect("Unable to save WiVRn config");
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,10 @@ use nix::{
|
|||
use std::{
|
||||
fs::{self, copy, create_dir_all, remove_dir_all, File, OpenOptions},
|
||||
io::{BufReader, BufWriter},
|
||||
path::Path,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
pub fn get_writer(path_s: &str) -> anyhow::Result<BufWriter<std::fs::File>> {
|
||||
let path = Path::new(path_s);
|
||||
pub fn get_writer(path: &PathBuf) -> anyhow::Result<BufWriter<std::fs::File>> {
|
||||
if let Some(parent) = path.parent() {
|
||||
if !parent.is_dir() {
|
||||
create_dir_all(parent)?;
|
||||
|
@ -24,26 +23,25 @@ pub fn get_writer(path_s: &str) -> anyhow::Result<BufWriter<std::fs::File>> {
|
|||
Ok(BufWriter::new(file))
|
||||
}
|
||||
|
||||
pub fn get_reader(path_s: &str) -> Option<BufReader<File>> {
|
||||
let path = Path::new(&path_s);
|
||||
pub fn get_reader(path: &PathBuf) -> Option<BufReader<File>> {
|
||||
if !(path.is_file() || path.is_symlink()) {
|
||||
return None;
|
||||
}
|
||||
match File::open(path) {
|
||||
Err(e) => {
|
||||
println!("Error opening {}: {}", path_s, e);
|
||||
println!("Error opening {}: {}", path.to_string_lossy(), e);
|
||||
None
|
||||
}
|
||||
Ok(fd) => Some(BufReader::new(fd)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize_file<T: serde::de::DeserializeOwned>(path_s: &String) -> Option<T> {
|
||||
match get_reader(path_s) {
|
||||
pub fn deserialize_file<T: serde::de::DeserializeOwned>(path: &PathBuf) -> Option<T> {
|
||||
match get_reader(path) {
|
||||
None => None,
|
||||
Some(reader) => match serde_json::from_reader(reader) {
|
||||
Err(e) => {
|
||||
println!("Failed to deserialize {}: {}", path_s, e);
|
||||
println!("Failed to deserialize {}: {}", path.to_string_lossy(), e);
|
||||
None
|
||||
}
|
||||
Ok(res) => Some(res),
|
||||
|
@ -51,8 +49,7 @@ pub fn deserialize_file<T: serde::de::DeserializeOwned>(path_s: &String) -> Opti
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_file_readonly(path_s: &str, readonly: bool) -> Result<(), std::io::Error> {
|
||||
let path = Path::new(&path_s);
|
||||
pub fn set_file_readonly(path: &PathBuf, readonly: bool) -> Result<(), std::io::Error> {
|
||||
if !path.is_file() {
|
||||
println!("WARN: trying to set readonly on a file that does not exist");
|
||||
return Ok(());
|
||||
|
@ -64,38 +61,45 @@ pub fn set_file_readonly(path_s: &str, readonly: bool) -> Result<(), std::io::Er
|
|||
fs::set_permissions(path, perms)
|
||||
}
|
||||
|
||||
pub fn setcap_cap_sys_nice_eip(file: String) {
|
||||
pub fn setcap_cap_sys_nice_eip(file: &PathBuf) {
|
||||
let mut runner = CmdRunner::new(
|
||||
None,
|
||||
"pkexec".into(),
|
||||
vec!["setcap".into(), "CAP_SYS_NICE=eip".into(), file],
|
||||
vec![
|
||||
"setcap".into(),
|
||||
"CAP_SYS_NICE=eip".into(),
|
||||
file.to_string_lossy().to_string(),
|
||||
],
|
||||
);
|
||||
runner.start();
|
||||
runner.join();
|
||||
}
|
||||
|
||||
pub fn rm_rf(path_s: &String) {
|
||||
if remove_dir_all(path_s).is_err() {
|
||||
println!("Failed to remove path {}", path_s);
|
||||
pub fn rm_rf(path: &PathBuf) {
|
||||
if remove_dir_all(path).is_err() {
|
||||
println!("Failed to remove path {}", path.to_string_lossy());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_file(source_s: &str, dest_s: &str) {
|
||||
let source = Path::new(source_s);
|
||||
let dest = Path::new(dest_s);
|
||||
pub fn copy_file(source: &PathBuf, dest: &PathBuf) {
|
||||
if let Some(parent) = dest.parent() {
|
||||
if !parent.is_dir() {
|
||||
create_dir_all(parent)
|
||||
.unwrap_or_else(|_| panic!("Failed to create dir {}", parent.to_str().unwrap()));
|
||||
}
|
||||
}
|
||||
set_file_readonly(dest_s, false)
|
||||
.unwrap_or_else(|_| panic!("Failed to set file {} as rw", dest_s));
|
||||
copy(source, dest).unwrap_or_else(|_| panic!("Failed to copy {} to {}", source_s, dest_s));
|
||||
set_file_readonly(dest, false)
|
||||
.unwrap_or_else(|_| panic!("Failed to set file {} as rw", dest.to_string_lossy()));
|
||||
copy(source, dest).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Failed to copy {} to {}",
|
||||
source.to_string_lossy(),
|
||||
dest.to_string_lossy()
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn mount_has_nosuid(path_s: &str) -> Result<bool, Errno> {
|
||||
let path = Path::new(path_s);
|
||||
pub fn mount_has_nosuid(path: &PathBuf) -> Result<bool, Errno> {
|
||||
match statvfs(path) {
|
||||
Ok(fstats) => Ok(fstats.flags().contains(FsFlags::ST_NOSUID)),
|
||||
Err(e) => Err(e),
|
||||
|
@ -104,10 +108,12 @@ pub fn mount_has_nosuid(path_s: &str) -> Result<bool, Errno> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::file_utils::mount_has_nosuid;
|
||||
|
||||
#[test]
|
||||
fn can_get_nosuid() {
|
||||
mount_has_nosuid("/tmp").expect("Error running statvfs");
|
||||
mount_has_nosuid(&PathBuf::from("/tmp")).expect("Error running statvfs");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use crate::file_utils::get_reader;
|
||||
use std::{error::Error, fmt::Display, io::Read, str::FromStr};
|
||||
use std::{error::Error, fmt::Display, io::Read, path::PathBuf, str::FromStr};
|
||||
|
||||
// const POW_PROF_PATH: &str = "/sys/class/drm/card0/device/pp_power_profile_mode";
|
||||
|
||||
fn power_profile_mode_file(card_dir: &str) -> String {
|
||||
format!("{}/device/pp_power_profile_mode", card_dir)
|
||||
fn power_profile_mode_file(card_dir: &PathBuf) -> PathBuf {
|
||||
card_dir.join("device/pp_power_profile_mode")
|
||||
}
|
||||
|
||||
pub fn get_set_amd_vr_pow_prof_cmd(card_dir: &str) -> String {
|
||||
pub fn get_set_amd_vr_pow_prof_cmd(card_dir: &PathBuf) -> String {
|
||||
format!(
|
||||
"sudo sh -c \"echo '4' > {}\"",
|
||||
power_profile_mode_file(card_dir)
|
||||
power_profile_mode_file(card_dir).to_string_lossy()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -93,10 +93,10 @@ const AMD_VENDOR_ID: &str = "0x1002";
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum GpuSysDrm {
|
||||
Amd(String),
|
||||
Intel(String),
|
||||
Nvidia(String),
|
||||
Other(String),
|
||||
Amd(PathBuf),
|
||||
Intel(PathBuf),
|
||||
Nvidia(PathBuf),
|
||||
Other(PathBuf),
|
||||
}
|
||||
|
||||
fn list_gpus() -> Vec<GpuSysDrm> {
|
||||
|
@ -104,8 +104,8 @@ fn list_gpus() -> Vec<GpuSysDrm> {
|
|||
|
||||
for i in 0..5 {
|
||||
// arbitrary range, find a better way
|
||||
let card_dir = format!("/sys/class/drm/card{}", i);
|
||||
let vendor_file = format!("{}/device/vendor", card_dir);
|
||||
let card_dir = PathBuf::from(format!("/sys/class/drm/card{}", i));
|
||||
let vendor_file = card_dir.join("device/vendor");
|
||||
if let Some(mut reader) = get_reader(&vendor_file) {
|
||||
let mut buf = String::new();
|
||||
if reader.read_to_string(&mut buf).is_ok() {
|
||||
|
@ -131,7 +131,7 @@ pub fn get_first_amd_gpu() -> Option<GpuSysDrm> {
|
|||
pub fn get_amd_gpu_power_profile() -> Option<GpuPowerProfile> {
|
||||
let amd_gpu = get_first_amd_gpu();
|
||||
if let Some(GpuSysDrm::Amd(card_dir)) = amd_gpu {
|
||||
if let Some(mut reader) = get_reader(&power_profile_mode_file(card_dir.as_str())) {
|
||||
if let Some(mut reader) = get_reader(&power_profile_mode_file(&card_dir)) {
|
||||
let mut txt = String::new();
|
||||
reader.read_to_string(&mut txt).ok()?;
|
||||
for line in txt.split('\n') {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::file_utils::get_reader;
|
||||
use std::io::{BufRead, Read};
|
||||
use std::{
|
||||
io::{BufRead, Read},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum LinuxDistro {
|
||||
|
@ -18,10 +21,10 @@ impl LinuxDistro {
|
|||
}
|
||||
|
||||
fn get_from_etc_os_release() -> Option<Self> {
|
||||
Self::get_from_etc_os_release_file("/etc/os-release")
|
||||
Self::get_from_etc_os_release_file(&"/etc/os-release".into())
|
||||
}
|
||||
|
||||
fn get_from_etc_os_release_file(fp: &str) -> Option<Self> {
|
||||
fn get_from_etc_os_release_file(fp: &PathBuf) -> Option<Self> {
|
||||
if let Some(mut reader) = get_reader(fp) {
|
||||
let mut buf = String::new();
|
||||
loop {
|
||||
|
@ -47,7 +50,7 @@ impl LinuxDistro {
|
|||
}
|
||||
|
||||
fn get_from_etc_issue() -> Option<Self> {
|
||||
if let Some(mut reader) = get_reader("/etc/issue") {
|
||||
if let Some(mut reader) = get_reader(&"/etc/issue".into()) {
|
||||
let mut buf = String::new();
|
||||
if reader.read_to_string(&mut buf).is_ok() {
|
||||
buf = buf.trim().to_lowercase();
|
||||
|
@ -111,7 +114,7 @@ mod tests {
|
|||
#[test]
|
||||
fn can_detect_arch_linux_from_etc_os_release() {
|
||||
assert_eq!(
|
||||
LinuxDistro::get_from_etc_os_release_file("./test/files/archlinux-os-release"),
|
||||
LinuxDistro::get_from_etc_os_release_file(&"./test/files/archlinux-os-release".into()),
|
||||
Some(LinuxDistro::Arch)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ pub mod runner_pipeline;
|
|||
pub mod steam_linux_runtime_injector;
|
||||
pub mod steamvr_utils;
|
||||
pub mod ui;
|
||||
pub mod xdg;
|
||||
pub mod xr_devices;
|
||||
|
||||
fn restore_steam_xr_files() {
|
||||
|
|
124
src/paths.rs
124
src/paths.rs
|
@ -1,32 +1,36 @@
|
|||
use crate::{constants::CMD_NAME, profile::XRServiceType};
|
||||
use std::{env, fs::create_dir_all, path::Path};
|
||||
use crate::{constants::CMD_NAME, profile::XRServiceType, xdg::XDG};
|
||||
use std::{
|
||||
env,
|
||||
fs::create_dir_all,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
pub fn data_opencomposite_path() -> String {
|
||||
format!("{data}/opencomposite", data = get_data_dir())
|
||||
pub fn data_opencomposite_path() -> PathBuf {
|
||||
get_data_dir().join("opencomposite")
|
||||
}
|
||||
|
||||
pub fn data_monado_path() -> String {
|
||||
format!("{data}/monado", data = get_data_dir())
|
||||
pub fn data_monado_path() -> PathBuf {
|
||||
get_data_dir().join("monado")
|
||||
}
|
||||
|
||||
pub fn data_wivrn_path() -> String {
|
||||
format!("{data}/wivrn", data = get_data_dir())
|
||||
pub fn data_wivrn_path() -> PathBuf {
|
||||
get_data_dir().join("wivrn")
|
||||
}
|
||||
|
||||
pub fn data_libsurvive_path() -> String {
|
||||
format!("{data}/libsurvive", data = get_data_dir())
|
||||
pub fn data_libsurvive_path() -> PathBuf {
|
||||
get_data_dir().join("libsurvive")
|
||||
}
|
||||
|
||||
pub fn data_openhmd_path() -> String {
|
||||
format!("{data}/openhmd", data = get_data_dir())
|
||||
pub fn data_openhmd_path() -> PathBuf {
|
||||
get_data_dir().join("openhmd")
|
||||
}
|
||||
|
||||
pub fn data_basalt_path() -> String {
|
||||
format!("{data}/basalt", data = get_data_dir())
|
||||
pub fn data_basalt_path() -> PathBuf {
|
||||
get_data_dir().join("basalt")
|
||||
}
|
||||
|
||||
pub fn wivrn_apk_download_path() -> String {
|
||||
format!("{cache}/wivrn.apk", cache = get_cache_dir())
|
||||
pub fn wivrn_apk_download_path() -> PathBuf {
|
||||
get_cache_dir().join("wivrn.apk")
|
||||
}
|
||||
|
||||
pub const SYSTEM_PREFIX: &str = "/usr";
|
||||
|
@ -34,58 +38,24 @@ pub const SYSTEM_PREFIX: &str = "/usr";
|
|||
/** System prefix inside a bubblewrap environment (flatpak or pressure vessel) */
|
||||
pub const BWRAP_SYSTEM_PREFIX: &str = "/run/host/usr";
|
||||
|
||||
pub fn get_home_dir() -> String {
|
||||
env::var("HOME").expect("HOME env var not defined")
|
||||
pub fn get_home_dir() -> PathBuf {
|
||||
env::var("HOME").expect("HOME env var not defined").into()
|
||||
}
|
||||
|
||||
pub fn get_xdg_config_dir() -> String {
|
||||
match env::var("XDG_CONFIG_HOME") {
|
||||
Ok(conf_home) => conf_home,
|
||||
Err(_) => format!("{home}/.config", home = get_home_dir()),
|
||||
}
|
||||
pub fn get_config_dir() -> PathBuf {
|
||||
XDG.get_config_home().join(CMD_NAME)
|
||||
}
|
||||
|
||||
pub fn get_xdg_data_dir() -> String {
|
||||
match env::var("XDG_DATA_HOME") {
|
||||
Ok(data_home) => data_home,
|
||||
Err(_) => format!("{home}/.local/share", home = get_home_dir()),
|
||||
}
|
||||
pub fn get_data_dir() -> PathBuf {
|
||||
XDG.get_data_home().join(CMD_NAME)
|
||||
}
|
||||
|
||||
pub fn get_xdg_cache_dir() -> String {
|
||||
match env::var("XDG_CACHE_HOME") {
|
||||
Ok(cache_home) => cache_home,
|
||||
Err(_) => format!("{home}/.cache", home = get_home_dir()),
|
||||
}
|
||||
pub fn get_cache_dir() -> PathBuf {
|
||||
XDG.get_cache_home().join(CMD_NAME)
|
||||
}
|
||||
|
||||
pub fn get_xdg_runtime_dir() -> String {
|
||||
env::var("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR is not set")
|
||||
}
|
||||
|
||||
pub fn get_config_dir() -> String {
|
||||
format!(
|
||||
"{config}/{name}",
|
||||
config = get_xdg_config_dir(),
|
||||
name = CMD_NAME
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_data_dir() -> String {
|
||||
format!("{data}/{name}", data = get_xdg_data_dir(), name = CMD_NAME)
|
||||
}
|
||||
|
||||
pub fn get_cache_dir() -> String {
|
||||
format!(
|
||||
"{cache}/{name}",
|
||||
cache = get_xdg_cache_dir(),
|
||||
name = CMD_NAME
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_backup_dir() -> String {
|
||||
let p_s = format!("{data}/backups", data = get_data_dir());
|
||||
let p = Path::new(&p_s);
|
||||
pub fn get_backup_dir() -> PathBuf {
|
||||
let p = get_data_dir().join("backups");
|
||||
if !p.is_dir() {
|
||||
if p.is_file() {
|
||||
panic!(
|
||||
|
@ -93,12 +63,12 @@ pub fn get_backup_dir() -> String {
|
|||
p.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
create_dir_all(p).expect("Failed to create backups dir");
|
||||
create_dir_all(&p).expect("Failed to create backups dir");
|
||||
}
|
||||
p.to_str().unwrap().to_string()
|
||||
p
|
||||
}
|
||||
|
||||
pub fn get_exec_prefix() -> String {
|
||||
pub fn get_exec_prefix() -> PathBuf {
|
||||
let p = Path::new("/proc/self/exe");
|
||||
if !p.is_symlink() {
|
||||
panic!("/proc/self/exe is not a symlink!");
|
||||
|
@ -110,25 +80,19 @@ pub fn get_exec_prefix() -> String {
|
|||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn get_ipc_file_path(xrservice_type: &XRServiceType) -> String {
|
||||
format!(
|
||||
"{runtime}/{xrservice}_comp_ipc",
|
||||
runtime = get_xdg_runtime_dir(),
|
||||
xrservice = match xrservice_type {
|
||||
XRServiceType::Monado => "monado",
|
||||
XRServiceType::Wivrn => "wivrn",
|
||||
}
|
||||
)
|
||||
pub fn get_ipc_file_path(xrservice_type: &XRServiceType) -> PathBuf {
|
||||
XDG.get_runtime_directory()
|
||||
.expect("XDG runtime directory is not available")
|
||||
.join(match xrservice_type {
|
||||
XRServiceType::Monado => "monado_comp_ipc",
|
||||
XRServiceType::Wivrn => "wivrn_comp_ipc",
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_steamvr_bin_dir_path() -> String {
|
||||
format!(
|
||||
"{data}/Steam/steamapps/common/SteamVR/bin/linux64",
|
||||
data = get_xdg_data_dir()
|
||||
)
|
||||
pub fn get_steamvr_bin_dir_path() -> PathBuf {
|
||||
XDG.get_data_home()
|
||||
.join("Steam/steamapps/common/SteamVR/bin/linux64")
|
||||
}
|
||||
|
|
122
src/profile.rs
122
src/profile.rs
|
@ -2,8 +2,16 @@ use crate::{
|
|||
file_utils::get_writer,
|
||||
paths::{get_data_dir, get_ipc_file_path, BWRAP_SYSTEM_PREFIX, SYSTEM_PREFIX},
|
||||
};
|
||||
use nix::NixPath;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt::Display, fs::File, io::BufReader, path::Path, slice::Iter};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::BufReader,
|
||||
path::{Path, PathBuf},
|
||||
slice::Iter,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
@ -85,7 +93,7 @@ impl Display for ProfileFeatureType {
|
|||
pub struct ProfileFeature {
|
||||
pub feature_type: ProfileFeatureType,
|
||||
pub enabled: bool,
|
||||
pub path: Option<String>,
|
||||
pub path: Option<PathBuf>,
|
||||
pub repo: Option<String>,
|
||||
pub branch: Option<String>,
|
||||
}
|
||||
|
@ -207,18 +215,18 @@ pub struct Profile {
|
|||
pub uuid: String,
|
||||
pub name: String,
|
||||
pub xrservice_type: XRServiceType,
|
||||
pub xrservice_path: String,
|
||||
pub xrservice_path: PathBuf,
|
||||
pub xrservice_repo: Option<String>,
|
||||
pub xrservice_branch: Option<String>,
|
||||
#[serde(default = "HashMap::<String, String>::default")]
|
||||
pub xrservice_cmake_flags: HashMap<String, String>,
|
||||
pub opencomposite_path: String,
|
||||
pub opencomposite_path: PathBuf,
|
||||
pub opencomposite_repo: Option<String>,
|
||||
pub opencomposite_branch: Option<String>,
|
||||
pub features: ProfileFeatures,
|
||||
pub environment: HashMap<String, String>,
|
||||
/** Install prefix */
|
||||
pub prefix: String,
|
||||
pub prefix: PathBuf,
|
||||
pub can_be_built: bool,
|
||||
pub editable: bool,
|
||||
pub pull_on_build: bool,
|
||||
|
@ -239,10 +247,10 @@ impl Display for Profile {
|
|||
impl Default for Profile {
|
||||
fn default() -> Self {
|
||||
let uuid = Uuid::new_v4().to_string();
|
||||
let profile_dir = format!("{}/{}", get_data_dir(), uuid);
|
||||
let profile_dir = get_data_dir().join(&uuid);
|
||||
Self {
|
||||
name: "Default profile name".into(),
|
||||
xrservice_path: format!("{}/xrservice", profile_dir),
|
||||
xrservice_path: profile_dir.join("xrservice"),
|
||||
xrservice_type: XRServiceType::Monado,
|
||||
xrservice_repo: None,
|
||||
xrservice_branch: None,
|
||||
|
@ -250,21 +258,21 @@ impl Default for Profile {
|
|||
features: ProfileFeatures {
|
||||
libsurvive: ProfileFeature {
|
||||
enabled: false,
|
||||
path: Some(format!("{}/libsurvive", profile_dir)),
|
||||
path: Some(profile_dir.join("libsurvive")),
|
||||
repo: None,
|
||||
branch: None,
|
||||
feature_type: ProfileFeatureType::Libsurvive,
|
||||
},
|
||||
basalt: ProfileFeature {
|
||||
enabled: false,
|
||||
path: Some(format!("{}/basalt", profile_dir)),
|
||||
path: Some(profile_dir.join("basalt")),
|
||||
repo: None,
|
||||
branch: None,
|
||||
feature_type: ProfileFeatureType::Basalt,
|
||||
},
|
||||
openhmd: ProfileFeature {
|
||||
enabled: false,
|
||||
path: Some(format!("{}/openhmd", profile_dir)),
|
||||
path: Some(profile_dir.join("openhmd")),
|
||||
repo: None,
|
||||
branch: None,
|
||||
feature_type: ProfileFeatureType::OpenHmd,
|
||||
|
@ -272,10 +280,10 @@ impl Default for Profile {
|
|||
mercury_enabled: false,
|
||||
},
|
||||
environment: HashMap::new(),
|
||||
prefix: format!("{}/prefixes/{}", get_data_dir(), uuid),
|
||||
prefix: get_data_dir().join("prefixes").join(&uuid),
|
||||
can_be_built: true,
|
||||
pull_on_build: true,
|
||||
opencomposite_path: format!("{}/opencomposite", profile_dir),
|
||||
opencomposite_path: profile_dir.join("opencomposite"),
|
||||
opencomposite_repo: None,
|
||||
opencomposite_branch: None,
|
||||
editable: true,
|
||||
|
@ -291,7 +299,7 @@ impl Profile {
|
|||
pub fn xr_runtime_json_env_var(&self) -> String {
|
||||
format!(
|
||||
"XR_RUNTIME_JSON=\"{prefix}/share/openxr/1/openxr_{runtime}.json\"",
|
||||
prefix = match self.prefix.as_str() {
|
||||
prefix = match self.prefix.to_string_lossy().to_string().as_str() {
|
||||
SYSTEM_PREFIX => BWRAP_SYSTEM_PREFIX,
|
||||
other => other,
|
||||
},
|
||||
|
@ -312,7 +320,7 @@ impl Profile {
|
|||
self.xr_runtime_json_env_var(),
|
||||
format!(
|
||||
"PRESSURE_VESSEL_FILESYSTEMS_RW=\"{path}\"",
|
||||
path = get_ipc_file_path(&self.xrservice_type),
|
||||
path = get_ipc_file_path(&self.xrservice_type).to_string_lossy(),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
@ -332,22 +340,22 @@ impl Profile {
|
|||
vars.join(" ")
|
||||
}
|
||||
|
||||
pub fn get_survive_cli_path(&self) -> Option<String> {
|
||||
let path_s = format!("{pfx}/bin/survive-cli", pfx = self.prefix);
|
||||
if Path::new(&path_s).is_file() {
|
||||
return Some(path_s);
|
||||
pub fn get_survive_cli_path(&self) -> Option<PathBuf> {
|
||||
let path = self.prefix.join("bin/survive-cli");
|
||||
if path.is_file() {
|
||||
return Some(path);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn load_profile(path: &String) -> Self {
|
||||
pub fn load_profile(path: &PathBuf) -> Self {
|
||||
let file = File::open(path).expect("Unable to open profile");
|
||||
let reader = BufReader::new(file);
|
||||
serde_json::from_reader(reader).expect("Faiuled to deserialize profile")
|
||||
}
|
||||
|
||||
pub fn dump_profile(&self, path_s: &String) {
|
||||
let writer = get_writer(path_s).expect("Could not write profile");
|
||||
pub fn dump_profile(&self, path: &PathBuf) {
|
||||
let writer = get_writer(path).expect("Could not write profile");
|
||||
serde_json::to_writer_pretty(writer, self).expect("Could not write profile")
|
||||
}
|
||||
|
||||
|
@ -398,53 +406,46 @@ impl Profile {
|
|||
&& !self.xrservice_path.is_empty()
|
||||
&& !self.prefix.is_empty()
|
||||
&& (!self.features.libsurvive.enabled
|
||||
|| !self
|
||||
|| self
|
||||
.features
|
||||
.libsurvive
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap_or(&"".to_string())
|
||||
.is_empty())
|
||||
.is_some_and(|p| !p.is_empty()))
|
||||
&& (!self.features.basalt.enabled
|
||||
|| !self
|
||||
|| self
|
||||
.features
|
||||
.basalt
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap_or(&"".to_string())
|
||||
.is_empty())
|
||||
.is_some_and(|p| !p.is_empty()))
|
||||
&& (!self.features.openhmd.enabled
|
||||
|| !self
|
||||
|| self
|
||||
.features
|
||||
.openhmd
|
||||
.path
|
||||
.as_ref()
|
||||
.unwrap_or(&"".to_string())
|
||||
.is_empty())
|
||||
.is_some_and(|p| !p.is_empty()))
|
||||
}
|
||||
|
||||
pub fn xrservice_binary(&self) -> String {
|
||||
format!(
|
||||
"{}/bin/{}",
|
||||
self.prefix,
|
||||
match self.xrservice_type {
|
||||
XRServiceType::Monado => "monado-service",
|
||||
XRServiceType::Wivrn => "wivrn-server",
|
||||
}
|
||||
)
|
||||
pub fn xrservice_binary(&self) -> PathBuf {
|
||||
self.prefix.join("bin").join(match self.xrservice_type {
|
||||
XRServiceType::Monado => "monado-service",
|
||||
XRServiceType::Wivrn => "wivrn-server",
|
||||
})
|
||||
}
|
||||
|
||||
pub fn can_start(&self) -> bool {
|
||||
Path::new(&self.xrservice_binary()).is_file()
|
||||
}
|
||||
|
||||
pub fn libmonado_so(&self) -> Option<String> {
|
||||
let mut res = format!("{}/lib/libmonado.so", self.prefix);
|
||||
if Path::new(&res).is_file() {
|
||||
pub fn libmonado_so(&self) -> Option<PathBuf> {
|
||||
let res = self.prefix.join("lib/libmonado.so");
|
||||
if res.is_file() {
|
||||
return Some(res);
|
||||
}
|
||||
res = format!("{}/lib64/libmonado.so", self.prefix);
|
||||
if Path::new(&res).is_file() {
|
||||
let res = self.prefix.join("lib64/libmonado.so");
|
||||
if res.is_file() {
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
|
@ -458,7 +459,7 @@ impl Profile {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::profile::{ProfileFeature, ProfileFeatureType, ProfileFeatures, XRServiceType};
|
||||
|
||||
|
@ -466,14 +467,17 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn profile_can_be_loaded() {
|
||||
let profile = Profile::load_profile(&"./test/files/profile.json".to_string());
|
||||
let profile = Profile::load_profile(&"./test/files/profile.json".into());
|
||||
assert_eq!(profile.name, "Demo profile");
|
||||
assert_eq!(profile.xrservice_path, "/home/user/monado");
|
||||
assert_eq!(profile.opencomposite_path, "/home/user/opencomposite");
|
||||
assert_eq!(profile.prefix, "/home/user/envisionprefix");
|
||||
assert_eq!(profile.xrservice_path, PathBuf::from("/home/user/monado"));
|
||||
assert_eq!(
|
||||
profile.features.libsurvive.path.as_deref(),
|
||||
Some("/home/user/libsurvive")
|
||||
profile.opencomposite_path,
|
||||
PathBuf::from("/home/user/opencomposite")
|
||||
);
|
||||
assert_eq!(profile.prefix, PathBuf::from("/home/user/envisionprefix"));
|
||||
assert_eq!(
|
||||
profile.features.libsurvive.path,
|
||||
Some(PathBuf::from("/home/user/libsurvive"))
|
||||
);
|
||||
assert_eq!(profile.features.basalt.path, None);
|
||||
assert_eq!(profile.features.libsurvive.enabled, true);
|
||||
|
@ -496,14 +500,14 @@ mod tests {
|
|||
let p = Profile {
|
||||
uuid: "demo".into(),
|
||||
name: "Demo profile".into(),
|
||||
xrservice_path: String::from("/home/user/monado"),
|
||||
xrservice_path: PathBuf::from("/home/user/monado"),
|
||||
xrservice_type: XRServiceType::Monado,
|
||||
opencomposite_path: String::from("/home/user/opencomposite"),
|
||||
opencomposite_path: PathBuf::from("/home/user/opencomposite"),
|
||||
features: ProfileFeatures {
|
||||
libsurvive: ProfileFeature {
|
||||
feature_type: ProfileFeatureType::Libsurvive,
|
||||
enabled: true,
|
||||
path: Some(String::from("/home/user/libsurvive")),
|
||||
path: Some(PathBuf::from("/home/user/libsurvive")),
|
||||
repo: None,
|
||||
branch: None,
|
||||
},
|
||||
|
@ -512,17 +516,17 @@ mod tests {
|
|||
mercury_enabled: false,
|
||||
},
|
||||
environment: env,
|
||||
prefix: String::from("/home/user/envisionprefix"),
|
||||
prefix: PathBuf::from("/home/user/envisionprefix"),
|
||||
editable: true,
|
||||
..Default::default()
|
||||
};
|
||||
let fpath = String::from("./target/testout/testprofile.json");
|
||||
let fpath = PathBuf::from("./target/testout/testprofile.json");
|
||||
p.dump_profile(&fpath);
|
||||
let loaded = Profile::load_profile(&fpath);
|
||||
assert_eq!(loaded.name, "Demo profile");
|
||||
assert_eq!(
|
||||
loaded.features.libsurvive.path,
|
||||
Some(String::from("/home/user/libsurvive"))
|
||||
Some(PathBuf::from("/home/user/libsurvive"))
|
||||
);
|
||||
assert_eq!(
|
||||
loaded
|
||||
|
@ -534,6 +538,6 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn prepare_ld_library_path(prefix: &str) -> String {
|
||||
format!("{pfx}/lib:{pfx}/lib64", pfx = prefix)
|
||||
pub fn prepare_ld_library_path(prefix: &PathBuf) -> String {
|
||||
format!("{pfx}/lib:{pfx}/lib64", pfx = prefix.to_string_lossy())
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn lighthouse_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/lighthouse_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/lighthouse_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("XRT_JSON_LOG".into(), "1".into());
|
||||
environment.insert("XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), "140".into());
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn openhmd_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/openhmd_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/openhmd_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("XRT_JSON_LOG".into(), "1".into());
|
||||
environment.insert("XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), "140".into());
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn simulated_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/simulated_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/simulated_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("QWERTY_ENABLE".into(), "1".into());
|
||||
environment.insert("XRT_JSON_LOG".into(), "1".into());
|
||||
|
@ -18,7 +18,7 @@ pub fn simulated_profile() -> Profile {
|
|||
environment.insert("U_PACING_APP_USE_MIN_FRAME_PERIOD".into(), "1".into());
|
||||
environment.insert(
|
||||
"LD_LIBRARY_PATH".into(),
|
||||
format!("{pfx}/lib:{pfx}/lib64", pfx = prefix),
|
||||
format!("{pfx}/lib:{pfx}/lib64", pfx = prefix.to_string_lossy()),
|
||||
);
|
||||
Profile {
|
||||
uuid: "simulated-default".into(),
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn survive_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/survive_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/survive_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("XRT_JSON_LOG".into(), "1".into());
|
||||
environment.insert("XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), "140".into());
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn wivrn_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/wivrn_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/wivrn_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("LD_LIBRARY_PATH".into(), prepare_ld_library_path(&prefix));
|
||||
environment.insert("XRT_DEBUG_GUI".into(), "1".into());
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::collections::HashMap;
|
|||
|
||||
pub fn wmr_profile() -> Profile {
|
||||
let data_dir = get_data_dir();
|
||||
let prefix = format!("{data}/prefixes/wmr_default", data = data_dir);
|
||||
let prefix = data_dir.join("prefixes/wmr_default");
|
||||
let mut environment: HashMap<String, String> = HashMap::new();
|
||||
environment.insert("XRT_JSON_LOG".into(), "1".into());
|
||||
environment.insert("XRT_COMPOSITOR_SCALE_PERCENTAGE".into(), "140".into());
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
use crate::{
|
||||
file_utils::{copy_file, get_writer},
|
||||
paths::{get_backup_dir, get_home_dir, get_xdg_data_dir},
|
||||
paths::{get_backup_dir, get_home_dir},
|
||||
profile::Profile,
|
||||
};
|
||||
use anyhow::bail;
|
||||
use std::{fs::read_to_string, io::Write, path::Path};
|
||||
use std::{
|
||||
fs::read_to_string,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
fn get_runtime_entrypoint_path() -> Option<String> {
|
||||
vec![format!(
|
||||
"{home}/.steam/steam/steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point",
|
||||
home = get_home_dir(),
|
||||
)]
|
||||
fn get_runtime_entrypoint_path() -> Option<PathBuf> {
|
||||
vec![get_home_dir()
|
||||
.join(".steam/steam/steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point")]
|
||||
.iter()
|
||||
.find(|path| Path::new(&path).is_file())
|
||||
.find(|p| p.is_file())
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn get_backup_runtime_entrypoint_location() -> String {
|
||||
format!("{backup}/_v2-entry-point.bak", backup = get_backup_dir())
|
||||
fn get_backup_runtime_entrypoint_location() -> PathBuf {
|
||||
get_backup_dir().join("_v2-entry-point.bak")
|
||||
}
|
||||
|
||||
fn backup_runtime_entrypoint(path: &str) {
|
||||
fn backup_runtime_entrypoint(path: &PathBuf) {
|
||||
copy_file(&path, &get_backup_runtime_entrypoint_location());
|
||||
}
|
||||
|
||||
|
@ -33,7 +35,7 @@ pub fn restore_runtime_entrypoint() {
|
|||
}
|
||||
}
|
||||
|
||||
fn append_to_runtime_entrypoint(data: &str, path: &str) -> anyhow::Result<()> {
|
||||
fn append_to_runtime_entrypoint(data: &str, path: &PathBuf) -> anyhow::Result<()> {
|
||||
let existing = read_to_string(path)?;
|
||||
let new = existing.replace(
|
||||
"exec \"${here}/${run}\" \"$@\"\nexit 125",
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
use crate::paths::get_home_dir;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn chaperone_info_exists() -> bool {
|
||||
let path_s = format!(
|
||||
"{}/.steam/steam/config/chaperone_info.vrchap",
|
||||
get_home_dir()
|
||||
);
|
||||
let path = Path::new(&path_s);
|
||||
path.is_file()
|
||||
get_home_dir()
|
||||
.join(".steam/steam/config/chaperone_info.vrchap")
|
||||
.is_file()
|
||||
}
|
||||
|
|
|
@ -644,10 +644,7 @@ impl SimpleComponent for App {
|
|||
println!("pkexec not found, skipping setcap");
|
||||
} else {
|
||||
let profile = self.get_selected_profile();
|
||||
setcap_cap_sys_nice_eip(format!(
|
||||
"{pfx}/bin/monado-service",
|
||||
pfx = profile.prefix
|
||||
));
|
||||
setcap_cap_sys_nice_eip(&profile.prefix.join("bin/monado-service"));
|
||||
}
|
||||
}
|
||||
Msg::ProfileSelected(prof) => {
|
||||
|
@ -692,12 +689,12 @@ impl SimpleComponent for App {
|
|||
self.application.quit();
|
||||
}
|
||||
Msg::DebugOpenData => {
|
||||
open_with_default_handler(&format!("file://{}", get_data_dir()));
|
||||
open_with_default_handler(&format!("file://{}", get_data_dir().to_string_lossy()));
|
||||
}
|
||||
Msg::DebugOpenPrefix => {
|
||||
open_with_default_handler(&format!(
|
||||
"file://{}",
|
||||
self.get_selected_profile().prefix
|
||||
self.get_selected_profile().prefix.to_string_lossy()
|
||||
));
|
||||
}
|
||||
Msg::DebugCopyEnvVars => {
|
||||
|
|
|
@ -196,14 +196,21 @@ impl InternalJobWorker {
|
|||
match launch_opts.contains(LAUNCH_OPTS_CMD_PLACEHOLDER) {
|
||||
true => launch_opts.replacen(
|
||||
LAUNCH_OPTS_CMD_PLACEHOLDER,
|
||||
prof.xrservice_binary().as_str(),
|
||||
&prof.xrservice_binary().to_string_lossy().to_string(),
|
||||
1,
|
||||
),
|
||||
false => format!("{} {}", prof.xrservice_binary(), launch_opts),
|
||||
false => format!(
|
||||
"{} {}",
|
||||
prof.xrservice_binary().to_string_lossy(),
|
||||
launch_opts
|
||||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
true => (prof.xrservice_binary(), vec![]),
|
||||
true => (
|
||||
prof.xrservice_binary().to_string_lossy().to_string(),
|
||||
vec![],
|
||||
),
|
||||
};
|
||||
let data = CmdWorkerData {
|
||||
environment: env,
|
||||
|
|
|
@ -7,7 +7,13 @@ use crate::{
|
|||
use adw::prelude::*;
|
||||
use gtk::glib;
|
||||
use relm4::prelude::*;
|
||||
use std::{cell::Cell, collections::HashMap, path::Path, rc::Rc, time::Duration};
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
const NO_FILE_MSG: &str = "(No file selected)";
|
||||
const CALIBRATION_RUN_TIME_SECONDS: f64 = 30.0;
|
||||
|
@ -57,7 +63,7 @@ pub enum LibsurviveSetupMsg {
|
|||
}
|
||||
|
||||
impl LibsurviveSetupWindow {
|
||||
fn create_calibration_runner(&mut self, survive_cli_path: String) -> CmdRunner {
|
||||
fn create_calibration_runner(&mut self, survive_cli_path: &PathBuf) -> CmdRunner {
|
||||
let lh_path = self.steam_lighthouse_path.clone();
|
||||
let mut env = HashMap::new();
|
||||
let profile_prefix = &self.profile.as_ref().unwrap().prefix;
|
||||
|
@ -67,7 +73,7 @@ impl LibsurviveSetupWindow {
|
|||
);
|
||||
CmdRunner::new(
|
||||
Some(env),
|
||||
survive_cli_path,
|
||||
survive_cli_path.to_string_lossy().to_string(),
|
||||
vec!["--steamvr-calibration".into(), lh_path],
|
||||
)
|
||||
}
|
||||
|
@ -369,7 +375,7 @@ impl SimpleComponent for LibsurviveSetupWindow {
|
|||
if let Some(survive_cli_path) =
|
||||
self.profile.as_ref().unwrap().get_survive_cli_path()
|
||||
{
|
||||
let mut runner = self.create_calibration_runner(survive_cli_path);
|
||||
let mut runner = self.create_calibration_runner(&survive_cli_path);
|
||||
self.calibration_running.set(true);
|
||||
self.first_run_done = false;
|
||||
self.calibration_seconds_elapsed = 0.0;
|
||||
|
@ -444,7 +450,8 @@ impl SimpleComponent for LibsurviveSetupWindow {
|
|||
let runner = self.calibration_runner.as_mut().unwrap();
|
||||
runner.terminate();
|
||||
let mut n_runner = self.create_calibration_runner(
|
||||
self.profile
|
||||
&self
|
||||
.profile
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_survive_cli_path()
|
||||
|
|
|
@ -188,13 +188,13 @@ impl SimpleComponent for MainView {
|
|||
add_css_class: "card",
|
||||
add_css_class: "padded",
|
||||
#[track = "model.changed(Self::selected_profile())"]
|
||||
set_visible: match mount_has_nosuid(model.selected_profile.prefix.as_str()) {
|
||||
set_visible: match mount_has_nosuid(&model.selected_profile.prefix) {
|
||||
Ok(b) => b,
|
||||
Err(_) => {
|
||||
// TODO: handle this error better
|
||||
println!(
|
||||
eprintln!(
|
||||
"Warning: could not get stat on path {}",
|
||||
model.selected_profile.prefix);
|
||||
model.selected_profile.prefix.to_string_lossy());
|
||||
false
|
||||
},
|
||||
},
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
use adw::prelude::*;
|
||||
use gtk::glib::clone;
|
||||
use relm4::{factory::AsyncFactoryVecDeque, prelude::*};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::{cell::RefCell, path::PathBuf, rc::Rc};
|
||||
|
||||
#[tracker::track]
|
||||
pub struct ProfileEditor {
|
||||
|
@ -110,10 +110,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
add: &path_row(
|
||||
"Install Prefix",
|
||||
None,
|
||||
Some(model.profile.borrow().prefix.clone()),
|
||||
Some(model.profile.borrow().prefix.to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().prefix = n_path.unwrap_or_default()
|
||||
prof.borrow_mut().prefix = n_path.unwrap_or_default().into();
|
||||
}),
|
||||
),
|
||||
add: &entry_row("Autostart Command",
|
||||
|
@ -171,10 +171,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
add: &path_row(
|
||||
"XR Service Path",
|
||||
None,
|
||||
Some(model.profile.borrow().xrservice_path.clone()),
|
||||
Some(model.profile.borrow().xrservice_path.clone().to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().xrservice_path = n_path.unwrap_or_default()
|
||||
prof.borrow_mut().xrservice_path = n_path.unwrap_or_default().into();
|
||||
}),
|
||||
),
|
||||
add: &entry_row(
|
||||
|
@ -200,10 +200,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
set_description: Some("OpenVR driver built on top of OpenXR"),
|
||||
add: &path_row(
|
||||
"OpenComposite Path", None,
|
||||
Some(model.profile.borrow().opencomposite_path.clone()),
|
||||
Some(model.profile.borrow().opencomposite_path.clone().to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().opencomposite_path = n_path.unwrap_or_default();
|
||||
prof.borrow_mut().opencomposite_path = n_path.unwrap_or_default().into();
|
||||
})
|
||||
),
|
||||
add: &entry_row(
|
||||
|
@ -236,10 +236,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
),
|
||||
add: &path_row(
|
||||
"Libsurvive Path", None,
|
||||
model.profile.borrow().features.libsurvive.path.clone(),
|
||||
model.profile.borrow().features.libsurvive.path.clone().map(|p| p.to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().features.libsurvive.path = n_path;
|
||||
prof.borrow_mut().features.libsurvive.path = n_path.map(PathBuf::from);
|
||||
})
|
||||
),
|
||||
add: &entry_row(
|
||||
|
@ -272,10 +272,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
),
|
||||
add: &path_row(
|
||||
"OpenHMD Path", None,
|
||||
model.profile.borrow().features.openhmd.path.clone(),
|
||||
model.profile.borrow().features.openhmd.path.clone().map(|p| p.to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().features.openhmd.path = n_path;
|
||||
prof.borrow_mut().features.openhmd.path = n_path.map(PathBuf::from);
|
||||
})
|
||||
),
|
||||
add: &entry_row(
|
||||
|
@ -308,10 +308,10 @@ impl SimpleComponent for ProfileEditor {
|
|||
),
|
||||
add: &path_row(
|
||||
"Basalt Path", None,
|
||||
model.profile.borrow().features.basalt.path.clone(),
|
||||
model.profile.borrow().features.basalt.path.clone().map(|p| p.to_string_lossy().to_string()),
|
||||
Some(init.root_win.clone()),
|
||||
clone!(@strong prof => move |n_path| {
|
||||
prof.borrow_mut().features.basalt.path = n_path;
|
||||
prof.borrow_mut().features.basalt.path = n_path.map(PathBuf::from);
|
||||
})
|
||||
),
|
||||
add: &entry_row(
|
||||
|
|
|
@ -5,7 +5,6 @@ use super::job_worker::{
|
|||
};
|
||||
use crate::paths::get_steamvr_bin_dir_path;
|
||||
use relm4::{
|
||||
binding::{Binding, ConnectBinding, StringBinding},
|
||||
gtk::{self, prelude::*},
|
||||
ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent,
|
||||
};
|
||||
|
@ -145,7 +144,7 @@ impl SimpleComponent for SteamVrCalibrationBox {
|
|||
}
|
||||
Self::Input::RunCalibration => {
|
||||
self.set_calibration_result(None);
|
||||
let steamvr_bin_dir = get_steamvr_bin_dir_path();
|
||||
let steamvr_bin_dir = get_steamvr_bin_dir_path().to_string_lossy().to_string();
|
||||
if !Path::new(&steamvr_bin_dir).is_dir() {
|
||||
self.set_calibration_success(false);
|
||||
self.set_calibration_result(Some("SteamVR not found".into()));
|
||||
|
@ -154,7 +153,7 @@ impl SimpleComponent for SteamVrCalibrationBox {
|
|||
let mut env: HashMap<String, String> = HashMap::new();
|
||||
env.insert("LD_LIBRARY_PATH".into(), steamvr_bin_dir.clone());
|
||||
let vrcmd = format!("{steamvr_bin_dir}/vrcmd");
|
||||
let mut server_worker = {
|
||||
let server_worker = {
|
||||
let mut jobs: VecDeque<WorkerJob> = VecDeque::new();
|
||||
jobs.push_back(WorkerJob::new_cmd(
|
||||
Some(env.clone()),
|
||||
|
@ -166,7 +165,7 @@ impl SimpleComponent for SteamVrCalibrationBox {
|
|||
JobWorkerOut::Exit(code) => Self::Input::OnServerWorkerExit(code),
|
||||
})
|
||||
};
|
||||
let mut cal_worker = {
|
||||
let cal_worker = {
|
||||
let mut jobs: VecDeque<WorkerJob> = VecDeque::new();
|
||||
jobs.push_back(WorkerJob::new_func(Box::new(move || {
|
||||
sleep(Duration::from_secs(2));
|
||||
|
|
7
src/xdg.rs
Normal file
7
src/xdg.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use lazy_static::lazy_static;
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref XDG: BaseDirectories =
|
||||
BaseDirectories::new().expect("Failed to get XDG base directories");
|
||||
}
|
Loading…
Add table
Reference in a new issue