config_io: Support wayvr.conf.d directory, refactoring (#139)
This commit is contained in:
@@ -13,7 +13,7 @@ use ovr_overlay::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{Haptics, TrackedDevice, TrackedDeviceRole},
|
backend::input::{Haptics, TrackedDevice, TrackedDeviceRole},
|
||||||
config_io::CONFIG_ROOT_PATH,
|
config_io,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -325,7 +325,7 @@ fn get_tracked_device(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
|
pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
|
||||||
let action_path = CONFIG_ROOT_PATH.join("actions.json");
|
let action_path = config_io::get_config_root().join("actions.json");
|
||||||
|
|
||||||
if let Err(e) = File::create(&action_path)
|
if let Err(e) = File::create(&action_path)
|
||||||
.and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json")))
|
.and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json")))
|
||||||
@@ -333,19 +333,19 @@ pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
|
|||||||
log::warn!("Could not write action manifest: {}", e);
|
log::warn!("Could not write action manifest: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json");
|
let binding_path = config_io::get_config_root().join("actions_binding_knuckles.json");
|
||||||
if !binding_path.is_file() {
|
if !binding_path.is_file() {
|
||||||
File::create(&binding_path)?
|
File::create(&binding_path)?
|
||||||
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
|
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json");
|
let binding_path = config_io::get_config_root().join("actions_binding_vive.json");
|
||||||
if !binding_path.is_file() {
|
if !binding_path.is_file() {
|
||||||
File::create(&binding_path)?
|
File::create(&binding_path)?
|
||||||
.write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
|
.write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json");
|
let binding_path = config_io::get_config_root().join("actions_binding_oculus.json");
|
||||||
if !binding_path.is_file() {
|
if !binding_path.is_file() {
|
||||||
File::create(&binding_path)?
|
File::create(&binding_path)?
|
||||||
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
|
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ use anyhow::bail;
|
|||||||
use json::{array, object};
|
use json::{array, object};
|
||||||
use ovr_overlay::applications::ApplicationsManager;
|
use ovr_overlay::applications::ApplicationsManager;
|
||||||
|
|
||||||
use crate::config_io::CONFIG_ROOT_PATH;
|
use crate::config_io;
|
||||||
|
|
||||||
const APP_KEY: &str = "galister.wlxoverlay-s";
|
const APP_KEY: &str = "galister.wlxoverlay-s";
|
||||||
|
|
||||||
pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
|
pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
|
||||||
let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest");
|
let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest");
|
||||||
|
|
||||||
let appimage_path = std::env::var("APPIMAGE");
|
let appimage_path = std::env::var("APPIMAGE");
|
||||||
let executable_pathbuf = std::env::current_exe()?;
|
let executable_pathbuf = std::env::current_exe()?;
|
||||||
@@ -76,7 +76,7 @@ pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
|
pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
|
||||||
let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest");
|
let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest");
|
||||||
|
|
||||||
if let Ok(true) = app_mgr.is_application_installed(APP_KEY) {
|
if let Ok(true) = app_mgr.is_application_installed(APP_KEY) {
|
||||||
if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) {
|
if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts},
|
backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts},
|
||||||
config_io::CONFIG_ROOT_PATH,
|
config_io,
|
||||||
graphics::{dds::WlxCommandBufferDds, format_is_srgb, WlxCommandBuffer},
|
graphics::{dds::WlxCommandBufferDds, format_is_srgb, WlxCommandBuffer},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
@@ -35,7 +35,7 @@ impl Skybox {
|
|||||||
break 'custom_tex;
|
break 'custom_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
let real_path = CONFIG_ROOT_PATH.join(&*app.session.config.skybox_texture);
|
let real_path = config_io::get_config_root().join(&*app.session.config.skybox_texture);
|
||||||
let Ok(f) = File::open(real_path) else {
|
let Ok(f) = File::open(real_path) else {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"Could not open custom skybox texture at: {}",
|
"Could not open custom skybox texture at: {}",
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ use std::path::PathBuf;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::config_io;
|
use crate::config_io;
|
||||||
use crate::config_io::get_conf_d_path;
|
|
||||||
use crate::config_io::CONFIG_ROOT_PATH;
|
|
||||||
use crate::gui::modular::ModularUiConfig;
|
use crate::gui::modular::ModularUiConfig;
|
||||||
use crate::overlays::toast::DisplayMethod;
|
use crate::overlays::toast::DisplayMethod;
|
||||||
use crate::overlays::toast::ToastTopic;
|
use crate::overlays::toast::ToastTopic;
|
||||||
@@ -390,14 +388,20 @@ pub fn load_custom_ui(name: &str) -> anyhow::Result<ModularUiConfig> {
|
|||||||
Ok(serde_yaml::from_str(&yaml_data)?)
|
Ok(serde_yaml::from_str(&yaml_data)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_general() -> GeneralConfig {
|
pub fn load_config_with_conf_d<ConfigData>(
|
||||||
|
root_config_filename: &str,
|
||||||
|
ctype: config_io::ConfigRoot,
|
||||||
|
) -> ConfigData
|
||||||
|
where
|
||||||
|
ConfigData: for<'de> Deserialize<'de>,
|
||||||
|
{
|
||||||
let mut settings_builder = Config::builder();
|
let mut settings_builder = Config::builder();
|
||||||
|
|
||||||
// Add files from conf.d directory
|
// Add files from conf.d directory
|
||||||
let path_conf_d = get_conf_d_path();
|
let path_conf_d = ctype.get_conf_d_path();
|
||||||
|
|
||||||
for mut base_conf in [CONFIG_ROOT_PATH.clone(), path_conf_d.clone()] {
|
for mut base_conf in [config_io::get_config_root(), path_conf_d.clone()] {
|
||||||
base_conf.push("config.yaml");
|
base_conf.push(root_config_filename);
|
||||||
if base_conf.exists() {
|
if base_conf.exists() {
|
||||||
log::info!("Loading config file: {}", base_conf.to_string_lossy());
|
log::info!("Loading config file: {}", base_conf.to_string_lossy());
|
||||||
settings_builder = settings_builder.add_source(File::from(base_conf));
|
settings_builder = settings_builder.add_source(File::from(base_conf));
|
||||||
@@ -423,7 +427,7 @@ pub fn load_general() -> GeneralConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match settings_builder.build() {
|
match settings_builder.build() {
|
||||||
Ok(settings) => match settings.try_deserialize::<GeneralConfig>() {
|
Ok(settings) => match settings.try_deserialize::<ConfigData>() {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
panic!("Failed to deserialize settings: {}", e);
|
panic!("Failed to deserialize settings: {}", e);
|
||||||
@@ -435,6 +439,10 @@ pub fn load_general() -> GeneralConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_general() -> GeneralConfig {
|
||||||
|
load_config_with_conf_d::<GeneralConfig>("config.yaml", config_io::ConfigRoot::Generic)
|
||||||
|
}
|
||||||
|
|
||||||
// Config that is saved from the settings panel
|
// Config that is saved from the settings panel
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -452,10 +460,11 @@ pub struct AutoSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_settings_path() -> PathBuf {
|
fn get_settings_path() -> PathBuf {
|
||||||
let mut path = config_io::get_conf_d_path();
|
config_io::ConfigRoot::Generic
|
||||||
path.push("zz-saved-config.json5");
|
.get_conf_d_path()
|
||||||
path
|
.join("zz-saved-config.json5")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
||||||
let conf = AutoSettings {
|
let conf = AutoSettings {
|
||||||
watch_pos: config.watch_pos,
|
watch_pos: config.watch_pos,
|
||||||
@@ -486,9 +495,9 @@ pub struct AutoState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_state_path() -> PathBuf {
|
fn get_state_path() -> PathBuf {
|
||||||
let mut path = config_io::get_conf_d_path();
|
config_io::ConfigRoot::Generic
|
||||||
path.push("zz-saved-state.json5");
|
.get_conf_d_path()
|
||||||
path
|
.join("zz-saved-state.json5")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_layout(config: &GeneralConfig) -> anyhow::Result<()> {
|
pub fn save_layout(config: &GeneralConfig) -> anyhow::Result<()> {
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
use log::error;
|
use log::error;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::{
|
use std::path::PathBuf;
|
||||||
fs::{self, create_dir},
|
|
||||||
path::PathBuf,
|
pub enum ConfigRoot {
|
||||||
};
|
Generic,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
WayVR,
|
||||||
|
}
|
||||||
|
|
||||||
const FALLBACK_CONFIG_PATH: &str = "/tmp/wlxoverlay";
|
const FALLBACK_CONFIG_PATH: &str = "/tmp/wlxoverlay";
|
||||||
|
|
||||||
pub static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
|
static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
|
||||||
if let Ok(xdg_dirs) = xdg::BaseDirectories::new() {
|
if let Ok(xdg_dirs) = xdg::BaseDirectories::new() {
|
||||||
let mut dir = xdg_dirs.get_config_home();
|
let mut dir = xdg_dirs.get_config_home();
|
||||||
dir.push("wlxoverlay");
|
dir.push("wlxoverlay");
|
||||||
@@ -21,33 +24,38 @@ pub static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
|
|||||||
PathBuf::from(FALLBACK_CONFIG_PATH)
|
PathBuf::from(FALLBACK_CONFIG_PATH)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn get_conf_d_path() -> PathBuf {
|
pub fn get_config_root() -> PathBuf {
|
||||||
let mut config_root = CONFIG_ROOT_PATH.clone();
|
CONFIG_ROOT_PATH.clone()
|
||||||
config_root.push("conf.d");
|
}
|
||||||
config_root
|
|
||||||
|
impl ConfigRoot {
|
||||||
|
pub fn get_conf_d_path(&self) -> PathBuf {
|
||||||
|
get_config_root().join(match self {
|
||||||
|
ConfigRoot::Generic => "conf.d",
|
||||||
|
ConfigRoot::WayVR => "wayvr.conf.d",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure config directory is present and return root config path
|
// Make sure config directory is present and return root config path
|
||||||
pub fn ensure_config_root() -> PathBuf {
|
pub fn ensure_dir(&self) -> PathBuf {
|
||||||
let path = CONFIG_ROOT_PATH.clone();
|
let path = get_config_root();
|
||||||
let _ = create_dir(&path);
|
let _ = std::fs::create_dir(&path);
|
||||||
|
|
||||||
let path_conf_d = get_conf_d_path();
|
let path_conf_d = self.get_conf_d_path();
|
||||||
let _ = create_dir(path_conf_d);
|
let _ = std::fs::create_dir(path_conf_d);
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config_file_path(filename: &str) -> PathBuf {
|
pub fn get_config_file_path(filename: &str) -> PathBuf {
|
||||||
let mut config_root = CONFIG_ROOT_PATH.clone();
|
get_config_root().join(filename)
|
||||||
config_root.push(filename);
|
|
||||||
config_root
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(filename: &str) -> Option<String> {
|
pub fn load(filename: &str) -> Option<String> {
|
||||||
let path = get_config_file_path(filename);
|
let path = get_config_file_path(filename);
|
||||||
log::info!("Loading config {}", path.to_string_lossy());
|
log::info!("Loading config: {}", path.to_string_lossy());
|
||||||
|
|
||||||
if let Ok(data) = fs::read_to_string(path) {
|
if let Ok(data) = std::fs::read_to_string(path) {
|
||||||
Some(data)
|
Some(data)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ use crate::{
|
|||||||
task::{TaskContainer, TaskType},
|
task::{TaskContainer, TaskType},
|
||||||
wayvr,
|
wayvr,
|
||||||
},
|
},
|
||||||
config::{load_known_yaml, ConfigType},
|
config::load_config_with_conf_d,
|
||||||
|
config_io,
|
||||||
gui::modular::button::WayVRAction,
|
gui::modular::button::WayVRAction,
|
||||||
overlays::wayvr::WayVRData,
|
overlays::wayvr::WayVRData,
|
||||||
};
|
};
|
||||||
@@ -120,7 +121,7 @@ pub struct WayVRConfig {
|
|||||||
pub run_compositor_at_start: bool,
|
pub run_compositor_at_start: bool,
|
||||||
pub catalogs: HashMap<String, WayVRCatalog>,
|
pub catalogs: HashMap<String, WayVRCatalog>,
|
||||||
pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically
|
pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically
|
||||||
pub dashboard: WayVRDashboard,
|
pub dashboard: Option<WayVRDashboard>,
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
#[serde(default = "def_true")]
|
||||||
pub auto_hide: bool,
|
pub auto_hide: bool,
|
||||||
@@ -212,7 +213,15 @@ impl WayVRConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_wayvr() -> WayVRConfig {
|
pub fn load_wayvr() -> WayVRConfig {
|
||||||
let config = load_known_yaml::<WayVRConfig>(ConfigType::WayVR);
|
let config_root_path = config_io::ConfigRoot::WayVR.ensure_dir();
|
||||||
|
log::info!("WayVR Config root path: {:?}", config_root_path);
|
||||||
|
log::info!(
|
||||||
|
"WayVR conf.d path: {:?}",
|
||||||
|
config_io::ConfigRoot::WayVR.get_conf_d_path()
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = load_config_with_conf_d::<WayVRConfig>("wayvr.yaml", config_io::ConfigRoot::WayVR);
|
||||||
|
|
||||||
if config.version != 1 {
|
if config.version != 1 {
|
||||||
panic!("WayVR config version {} is not supported", config.version);
|
panic!("WayVR config version {} is not supported", config.version);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use serde::Deserialize;
|
|||||||
use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
|
use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::common::OverlaySelector, config::AStrMapExt, config_io::CONFIG_ROOT_PATH,
|
backend::common::OverlaySelector, config::AStrMapExt, config_io,
|
||||||
graphics::dds::WlxCommandBufferDds, state::AppState,
|
graphics::dds::WlxCommandBufferDds, state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ fn sprite_from_path(path: Arc<str>, app: &mut AppState) -> anyhow::Result<Arc<Im
|
|||||||
return Ok(view.clone());
|
return Ok(view.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let real_path = CONFIG_ROOT_PATH.join(&*path);
|
let real_path = config_io::get_config_root().join(&*path);
|
||||||
|
|
||||||
let Ok(f) = File::open(real_path) else {
|
let Ok(f) = File::open(real_path) else {
|
||||||
anyhow::bail!("Could not open custom sprite at: {}", path);
|
anyhow::bail!("Could not open custom sprite at: {}", path);
|
||||||
|
|||||||
@@ -751,7 +751,7 @@ pub struct TokenConf {
|
|||||||
|
|
||||||
#[cfg(feature = "pipewire")]
|
#[cfg(feature = "pipewire")]
|
||||||
fn get_pw_token_path() -> PathBuf {
|
fn get_pw_token_path() -> PathBuf {
|
||||||
let mut path = config_io::get_conf_d_path();
|
let mut path = config_io::ConfigRoot::Generic.get_conf_d_path();
|
||||||
path.push("pw_tokens.yaml");
|
path.push("pw_tokens.yaml");
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,6 +244,10 @@ where
|
|||||||
{
|
{
|
||||||
let conf_dash = &app.session.wayvr_config.dashboard;
|
let conf_dash = &app.session.wayvr_config.dashboard;
|
||||||
|
|
||||||
|
let Some(conf_dash) = &conf_dash else {
|
||||||
|
anyhow::bail!("Dashboard is not configured");
|
||||||
|
};
|
||||||
|
|
||||||
if !wayvr.dashboard_executed && !executable_exists_in_path(&conf_dash.exec) {
|
if !wayvr.dashboard_executed && !executable_exists_in_path(&conf_dash.exec) {
|
||||||
anyhow::bail!("Executable \"{}\" not found", &conf_dash.exec);
|
anyhow::bail!("Executable \"{}\" not found", &conf_dash.exec);
|
||||||
}
|
}
|
||||||
@@ -280,7 +284,9 @@ where
|
|||||||
overlay.state.z_order = Z_ORDER_DASHBOARD;
|
overlay.state.z_order = Z_ORDER_DASHBOARD;
|
||||||
overlay.state.reset(app, true);
|
overlay.state.reset(app, true);
|
||||||
|
|
||||||
let conf_dash = &app.session.wayvr_config.dashboard;
|
let Some(conf_dash) = &app.session.wayvr_config.dashboard else {
|
||||||
|
unreachable!(); /* safe, not possible to trigger */
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: overlay curvature needs to be dispatched for some unknown reason, this value is not set otherwise
|
// FIXME: overlay curvature needs to be dispatched for some unknown reason, this value is not set otherwise
|
||||||
app.tasks.enqueue(TaskType::Overlay(
|
app.tasks.enqueue(TaskType::Overlay(
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ pub struct AppSession {
|
|||||||
|
|
||||||
impl AppSession {
|
impl AppSession {
|
||||||
pub fn load() -> Self {
|
pub fn load() -> Self {
|
||||||
let config_root_path = config_io::ensure_config_root();
|
let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
|
||||||
log::info!("Config root path: {}", config_root_path.to_string_lossy());
|
log::info!("Config root path: {:?}", config_root_path);
|
||||||
let config = GeneralConfig::load_from_disk();
|
let config = GeneralConfig::load_from_disk();
|
||||||
|
|
||||||
let mut toast_topics = IdMap::new();
|
let mut toast_topics = IdMap::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user