XR for Universal Blue and Fedora Atomic Desktops

Compare changes

Choose any two refs to compare.

-38
install.nu
··· 1 - #!/usr/bin/env nu 2 - # SPDX-License-Identifier: AGPL-3.0-only 3 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 - 5 - use std log 6 - 7 - const self: path = path self . 8 - 9 - def main [ 10 - prefix: string = "~/.local" 11 - --install-library (-l) 12 - --force (-f) # Overwrite existing files 13 - ] { 14 - let prefix = $prefix | path expand 15 - log debug $"Install prefix: ($prefix)" 16 - let lib_dir = $prefix | path join "share" "atomic-xr" "lib" 17 - let axr = open ($self | path join 'src' 'axr.nu.in') --raw 18 - | str replace -a "/@AXR_LIB@/" $"use ($lib_dir)/atomic-xr" 19 - let bin = $prefix | path join "bin" "axr" 20 - 21 - if $force { 22 - rm -rf ($lib_dir | path join "atomic-xr") 23 - rm -f $bin 24 - } 25 - 26 - mkdir $lib_dir 27 - cp -r ($self | path join 'src' 'atomic-xr') $lib_dir 28 - if $install_library { 29 - if $force {rm -f ($NU_LIB_DIRS | first | path join "atomic-xr")} 30 - ln -s ($lib_dir | path join "atomic-xr") ($NU_LIB_DIRS | first) 31 - } 32 - 33 - mkdir ($bin | path dirname) 34 - $axr | save $bin 35 - chmod +x $bin 36 - 37 - log info "AtomicXR CLI has been installed, use `axr -l` for a list of commands." 38 - }
-12
install.sh
··· 1 - #!/usr/bin/bash 2 - # SPDX-License-Identifier: AGPL-3.0-only 3 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 - 5 - if ! nu -v $>/dev/null; then 6 - brew install nushell \ 7 - || echo -e "\e[35mFailed to install Nushell using Homebrew. Please install Nushell or Homebrew, then re-run this script.\e[0m" 8 - fi 9 - 10 - if nu -v $>/dev/null; then 11 - nu ./install.nu 12 - fi
-119
src/atomic-xr/_debug.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - 6 - export def main [ 7 - output?: path 8 - --base64 # Output base64 instead of creating a file 9 - --full (-f) # Include extra debug information 10 - ] { 11 - let output = $output | default (mktemp -t --suffix .msgpackz) | path expand 12 - 13 - log info "Gathering debug information" 14 - 15 - let flatpak_installed = flatpak list --columns application | lines 16 - let sys = if $full { 17 - { 18 - host: (sys host | reject hostname) 19 - cpu: (sys cpu) 20 - mem: (sys mem) 21 - temp: (sys temp) 22 - disks: (sys disks) 23 - } 24 - } else { 25 - { 26 - host: (sys host | reject hostname) 27 - } 28 - } 29 - 30 - { 31 - debug_version: "1.0.0" 32 - sys: $sys 33 - brew: { 34 - installed: (which brew | is-not-empty) 35 - doctor: (try {brew doctor o+e>| $in}) 36 - atomicxr_installed: (try { 37 - brew list --full-name 38 - | find -n matrixfurry.com/atomicxr/ 39 - | each {|| brew info --json $in | from json} 40 - | flatten 41 - }) 42 - } 43 - distrobox: { 44 - installed: (which distrobox | is-not-empty) 45 - } 46 - envision: { 47 - container: (try { 48 - distrobox ls --no-color 49 - | parse -r '(?P<id>.*)\s\|\s(?P<name>.*)\s\|\s(?P<status>.*)\s\|\s(?P<image>.*)' 50 - | str trim 51 - | skip 1 52 - | where name == envision 53 - }) 54 - paths_exist: { 55 - bin: ("~/.local/bin/envision" | path exists) 56 - devel_desktop: ("~/.local/share/applications/org.gabmus.envision.Devel.desktop" | path exists) 57 - desktop: ("~/.local/share/applications/org.gabmus.envision.desktop" | path exists) 58 - localshare_bin: ("~/.local/share/bin/envision" | path exists) 59 - config: ("~/.config/envision/envision.json" | path exists) 60 - } 61 - config: (try {open ~/.config/envision/envision.json}) 62 - } 63 - paths_exist: { 64 - local: { 65 - _self: ("~/.local" | path exists) 66 - share: { 67 - _self: ("~/.local/share" | path exists) 68 - applications: ("~/.local/share/applications" | path exists) 69 - } 70 - bin: ("~/.local/bin" | path exists) 71 - } 72 - } 73 - steam: { 74 - paths: { 75 - dotsteam: (try {ls -lD ~/.steam}) 76 - localshare: (try {ls -lD ~/.local/share/Steam}) 77 - flatpak: ("~/.var/app/com.valvesoftware.Steam" | path exists) 78 - } 79 - } 80 - rpm-ostree: { 81 - requested: (rpm-ostree status --json | from json | get deployments | first | get requested-packages) 82 - } 83 - flatpak: { 84 - installed: { 85 - steam: ($flatpak_installed has "com.valvesoftware.Steam") 86 - gaiasky: ($flatpak_installed has "space.gaiasky.GaiaSky") 87 - } 88 - } 89 - } 90 - | to msgpackz 91 - | if $base64 { 92 - print (ansi cyan) 93 - $in | encode base64 | print 94 - print (ansi reset) 95 - } else { 96 - save -f $output 97 - log info $"Successfully created debug file. It has been saved to ($output)" 98 - } 99 - 100 - if $base64 { 101 - log info $"If you'd like to check what info that contains, use `axr '_debug decode --base64 {base64}'`" 102 - } else { 103 - log info $"If you'd like to check what info it contains, use `axr _debug decode ($output)`" 104 - } 105 - } 106 - 107 - export def decode [ 108 - input # Base64 or file to decode 109 - --base64 110 - --explore (-e) # Explore output 111 - ] { 112 - if $base64 { 113 - $input | decode base64 114 - } else { 115 - open $input 116 - } 117 - | from msgpackz 118 - | if $explore {explore} else {$in} 119 - }
-35
src/atomic-xr/_migrate.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - use envision.nu 6 - 7 - # Migrate from version 1.x.x to 2.x.x 8 - export def "v1" [] { 9 - log info "Starting migration: 1.x.x -> 2.x.x" 10 - 11 - log info "Updating Envision config" 12 - do { 13 - const envision_config_path = "~/.config/envision/envision.json" | path expand 14 - 15 - let envision_config = try {open $envision_config_path} catch { 16 - log info "Envision config not found, no config migration nessesary" 17 - return 18 - } 19 - let plugins = $envision_config.plugins 20 - | reject -o ...("cc.dwagon.atomic-xr.{wlx-overlay-s,motoc,oscavmgr.project-babble,oscavmgr.wivrn}" | str expand) 21 - 22 - $envision_config 23 - | merge {plugins: $plugins} 24 - | save -f $envision_config_path 25 - log info "Envision plugins unregistered successfully" 26 - } 27 - 28 - if ("~/.local/bin/envision" | path exists) { 29 - envision upgrade 30 - } else { 31 - log info "Envision is not installed, no upgrade nessesary" 32 - } 33 - 34 - log info "Migration completed: 1.x.x -> 2.x.x" 35 - }
-12
src/atomic-xr/bin/oscavmgr-launch.sh
··· 1 - #!/usr/bin/env bash 2 - # SPDX-License-Identifier: AGPL-3.0-only 3 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 - # 5 - # Portions of this file are derived from OscAvMgr, which is licensed under the MIT License 6 - # Copyright (c) 2023 galister 7 - 8 - trap 'jobs -p | xargs kill' EXIT 9 - 10 - VrcAdvert OscAvMgr 9402 9002 --tracking & 11 - 12 - oscavmgr "${@}"
-118
src/atomic-xr/envision.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - const repo = "~/.local/share/atomic-xr/envision" | path expand 5 - const envision_config_path = "~/.config/envision/envision.json" | path expand 6 - 7 - const self = path self . 8 - 9 - use std log 10 - use runtime.nu 11 - 12 - export def install [ 13 - --no-monado (-m) # Don't install runtime deps for Monado 14 - ] { 15 - runtime install xr (if not $no_monado {"monado"}) 16 - 17 - distrobox create envision --no-entry -Y -i registry.fedoraproject.org/fedora-toolbox:42 18 - distrobox enter envision -- sudo dnf install -y nu 19 - upgrade 20 - log info "Successfully installed Envision" 21 - } 22 - 23 - export def uninstall [] { 24 - try {distrobox rm -f envision} 25 - log info "Removing files" 26 - rm -f ~/.local/bin/envision ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/applications/org.gabmus.envision.desktop ~/.local/share/bin/envision 27 - log info "Successfully uninstalled Envision" 28 - } 29 - 30 - export def upgrade [] { 31 - distrobox upgrade envision 32 - 33 - mkdir ($repo | path dirname) 34 - if ($repo | path exists) { 35 - cd $repo 36 - git reset --hard # Reset patches 37 - git switch main 38 - git pull 39 - } else { 40 - git clone "https://gitlab.com/gabmus/envision.git" $repo 41 - cd $repo 42 - } 43 - git switch --detach (git tag -l --sort=v:refname | lines | last) 44 - 45 - let patches = $self | path join patches envision 46 - 47 - ls $patches 48 - | get name 49 - | each {|patch| 50 - git apply $patch 51 - } 52 - 53 - { 54 - if (rpm -q rpmfusion-free-release | complete | get exit_code) != 0 { 55 - sudo dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-(rpm -E %fedora).noarch.rpm 56 - sudo dnf swap -y ffmpeg-free ffmpeg --allowerasing 57 - } 58 - 59 - sudo dnf builddep -y envision 60 - 61 - # TODO: Only install dependencies required for the requested profiles 62 - [ 63 - # WiVRn 64 - envision-wivrn 65 - avahi-devel 66 - avahi-glib-devel 67 - cli11-devel 68 - glslang-devel 69 - glslc 70 - gstreamer1-plugins-base-devel 71 - gstreamer1-devel 72 - ffmpeg-devel 73 - libnotify-devel 74 - libva-devel 75 - json-devel 76 - x264-devel 77 - pipewire-devel 78 - cmake 79 - gcc-c++ 80 - clang19-devel 81 - openxr-devel 82 - android-tools 83 - librsvg2-devel 84 - libarchive-devel 85 - 86 - # Monado 87 - envision-monado 88 - cmake 89 - gcc-c++ 90 - glslang-devel 91 - glslc 92 - libbsd-devel 93 - libusb1 94 - libusb1-devel 95 - SDL2-devel 96 - wayland-protocols-devel 97 - openxr-devel 98 - 99 - # WMR 100 - fmt-devel 101 - fmt-devel 102 - git-lfs 103 - glew-devel 104 - glew-devel 105 - gtest-devel 106 - jq 107 - lz4-devel 108 - tbb-devel 109 - ] | sudo dnf install -y ...$in 110 - 111 - meson setup build -Dprefix=($env.HOME)/.local --reconfigure 112 - ninja -C build 113 - ninja -C build install 114 - } 115 - | distrobox enter envision -- nu -c $"do (view source $in)" 116 - 117 - log info "Successfully upgraded Envision" 118 - }
-91
src/atomic-xr/flatpak.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - 6 - const xr_permissions = { 7 - filesystem: [ 8 - "xdg-data/envision:ro" 9 - "xdg-run/monado_comp_ipc" 10 - "/var/lib/flatpak/app/io.github.wivrn.wivrn:ro" 11 - "~/.var/app/io.github.wivrn.wivrn:ro" 12 - "xdg-run/wivrn" 13 - "xdg-config/openxr:ro" 14 - "xdg-config/openvr:ro" 15 - ] 16 - } 17 - 18 - def "permissions allow" [appid: string] { 19 - flatpak override --user ...( 20 - $"--filesystem={($xr_permissions.filesystem | str join ',')}" | str expand 21 - ) $appid 22 - } 23 - 24 - def "permissions revoke" [appid: string] { 25 - flatpak override --user ...( 26 - $"--nofilesystem={($xr_permissions.filesystem | str replace -r ':.*' '' | str join ',')}" | str expand 27 - ) $appid 28 - } 29 - 30 - export module steam { 31 - # Enable XR support for Steam Flatpak 32 - export def enable-xr [] { 33 - permissions allow com.valvesoftware.Steam 34 - 35 - if not ("~/.steam" | path exists) { 36 - ln -s ~/.var/app/com.valvesoftware.Steam/.steam ~/ 37 - log debug "Symlinked Steam Flatpak's .steam directory to ~/.steam." 38 - } else if (ls -lD ~/.steam).0.target != ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 39 - error make { 40 - msg: "Could not link Steam Flatpak's .steam directory to ~/.steam." 41 - help: "Back up or remove your existing ~/.steam directory, then run this command again." 42 - } 43 - } 44 - 45 - log info "Successfully set up Steam Flatpak XR." 46 - } 47 - 48 - # Disable XR support for Steam Flatpak 49 - export def disable-xr [] { 50 - permissions revoke com.valvesoftware.Steam 51 - 52 - if not ("~/.steam" | path exists) { 53 - log debug "~/.steam does not exist." 54 - } else if (ls -lD ~/.steam).0.target == ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 55 - rm ~/.steam 56 - if ("~/.steam.bak-axr" | path exists) { 57 - mv ~/.steam.bak-axr ~/.steam 58 - } 59 - } 60 - 61 - log info "Successfully reset Steam Flatpak XR." 62 - } 63 - } 64 - 65 - export module gaiasky { 66 - # Enable VR mode for Gaia Sky 67 - export def enable-vr [] { 68 - permissions allow space.gaiasky.GaiaSky 69 - [ 70 - (open /var/lib/flatpak/app/space.gaiasky.GaiaSky/current/active/export/share/applications/space.gaiasky.GaiaSky.desktop 71 - | str replace "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky -vr") 72 - "Actions=DesktopMode;" 73 - "" 74 - "[Desktop Action DesktopMode]" 75 - "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" 76 - "Name=Launch in Desktop Mode" 77 - ] 78 - | str join "\n" 79 - | save -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 80 - 81 - log info "Successfully enabled Gaia Sky's VR mode." 82 - } 83 - 84 - # Disable VR mode for Gaia Sky 85 - export def disable-vr [] { 86 - permissions revoke space.gaiasky.GaiaSky 87 - rm -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 88 - 89 - log info "Successfully disabled Gaia Sky's VR mode." 90 - } 91 - }
-12
src/atomic-xr/homebrew.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - # Tap AtomicXR Homebrew 5 - export def tap [] { 6 - brew tap matrixfurry.com/atomicxr https://tangled.sh/@matrixfurry.com/homebrew-atomicxr 7 - } 8 - 9 - # Untap AtomicXR Homebrew 10 - export def untap [] { 11 - brew untap shiloh/atomicxr 12 - }
-12
src/atomic-xr/mod.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - export use _debug.nu 5 - export use _migrate.nu 6 - export use envision.nu 7 - export use flatpak.nu 8 - export use homebrew.nu 9 - export use oscavmgr.nu 10 - export use runtime.nu 11 - export use steamvr-lh.nu 12 - export use wayvr.nu
-18
src/atomic-xr/oscavmgr.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - const self = path self . 5 - 6 - # Start OSC Avatar Manager and advertise it using VrcAdvert 7 - export def start [ 8 - module: string # babble, openxr (WiVRn), alvr 9 - ] { 10 - if (which oscavmgr | length) == 0 or (which VrcAdvert | length) == 0 { 11 - error make -u { 12 - msg: "OscAvMgr and VrcAdvert are not installed" 13 - help: "Use `brew install oscavmgr vrc-advert` to install them" 14 - } 15 - } 16 - 17 - exec ($self | path join 'bin' 'oscavmgr-launch.sh') $module 18 - }
-25
src/atomic-xr/patches/envision/0001-Add-build-mode-to-desktop-entry.patch
··· 1 - From d2359c7ad267214a1bc63775c5d95a5a09cd19cb Mon Sep 17 00:00:00 2001 2 - From: "@matrixfurry.com" <did:plc:zmjoeu3stwcn44647rhxa44o> 3 - Date: Fri, 5 Sep 2025 13:38:33 -0500 4 - Subject: [PATCH 1/4] Add build mode to desktop entry 5 - 6 - --- 7 - data/org.gabmus.envision.desktop.in.in | 5 +++++ 8 - 1 file changed, 5 insertions(+) 9 - 10 - diff --git a/data/org.gabmus.envision.desktop.in.in b/data/org.gabmus.envision.desktop.in.in 11 - index 31ac287..394ff19 100644 12 - --- a/data/org.gabmus.envision.desktop.in.in 13 - +++ b/data/org.gabmus.envision.desktop.in.in 14 - @@ -12,3 +12,8 @@ Keywords=vr;virtual;reality;monado; 15 - Icon=@APP_ID@ 16 - StartupNotify=true 17 - X-GNOME-UsesNotifications=true 18 - +Actions=BuildMode; 19 - + 20 - +[Desktop Action BuildMode] 21 - +Exec=distrobox enter envision -- @CMD_NAME@ 22 - +Name=Launch in Build Mode 23 - -- 24 - 2.51.0 25 -
-35
src/atomic-xr/patches/envision/0002-Replace-plugin-manifests.patch
··· 1 - From 7e56cd4c602069392be88e2ecd87dff6bf993f60 Mon Sep 17 00:00:00 2001 2 - From: "@matrixfurry.com" <did:plc:zmjoeu3stwcn44647rhxa44o> 3 - Date: Fri, 5 Sep 2025 13:45:50 -0500 4 - Subject: [PATCH 2/4] Replace plugin manifests 5 - 6 - --- 7 - src/ui/plugins/mod.rs | 12 ++++++++---- 8 - 1 file changed, 8 insertions(+), 4 deletions(-) 9 - 10 - diff --git a/src/ui/plugins/mod.rs b/src/ui/plugins/mod.rs 11 - index cb18440..c4902fe 100644 12 - --- a/src/ui/plugins/mod.rs 13 - +++ b/src/ui/plugins/mod.rs 14 - @@ -163,10 +163,14 @@ impl Plugin { 15 - 16 - /// urls to manifest json files representing plugins. 17 - /// each manifest should be json and the link should always point to the latest version 18 - -const MANIFESTS: [&str;3] = [ 19 - - "https://github.com/galister/wlx-overlay-s/raw/refs/heads/meta/com.github.galister.wlx-overlay-s.json", 20 - - "https://github.com/StardustXR/telescope/raw/refs/heads/main/envision/org.stardustxr.telescope.json", 21 - - "https://github.com/olekolek1000/wayvr-dashboard/raw/refs/heads/meta/dev.oo8.wayvr_dashboard.json", 22 - +const MANIFESTS: [&str;7] = [ 23 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/wlx-overlay-s.json", 24 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/wayvr-dashboard.json", 25 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/lovr-playspace.json", 26 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/motoc.json", 27 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/oscavmgr.openxr.json", 28 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/oscavmgr.babble.json", 29 - + "https://tangled.org/matrixfurry.com/atomic-xr/raw/main/data/envision-plugins/manifest/index-camera-passthrough.json", 30 - ]; 31 - 32 - pub async fn refresh_plugins() -> anyhow::Result<Vec<anyhow::Result<Plugin>>> { 33 - -- 34 - 2.51.0 35 -
-31
src/atomic-xr/patches/envision/0003-Modify-plugin-download-error-message.patch
··· 1 - From e8f9266d41e4e9275b5031c63a017255749fefb1 Mon Sep 17 00:00:00 2001 2 - From: "@matrixfurry.com" <did:plc:zmjoeu3stwcn44647rhxa44o> 3 - Date: Fri, 5 Sep 2025 23:07:27 -0500 4 - Subject: [PATCH 3/4] Modify plugin download error message 5 - 6 - --- 7 - src/ui/plugins/store.rs | 8 ++------ 8 - 1 file changed, 2 insertions(+), 6 deletions(-) 9 - 10 - diff --git a/src/ui/plugins/store.rs b/src/ui/plugins/store.rs 11 - index 0faf99a..17d1534 100644 12 - --- a/src/ui/plugins/store.rs 13 - +++ b/src/ui/plugins/store.rs 14 - @@ -357,12 +357,8 @@ impl AsyncComponent for PluginStore { 15 - None => { 16 - alert( 17 - "Download failed", 18 - - Some(&format!( 19 - - "Downloading {} {} failed:\n\nNo executable url provided for this plugin, this is likely a bug!", 20 - - plugin.name, 21 - - plugin.version.as_ref().unwrap_or(&"(no version)".to_string())) 22 - - ), 23 - - Some(&self.win.as_ref().unwrap().clone().upcast::<gtk::Window>()) 24 - + Some("Please use Homebrew to install plugins."), 25 - + Some(&self.win.as_ref().unwrap().clone().upcast::<gtk::Window>()), 26 - ); 27 - } 28 - }; 29 - -- 30 - 2.51.0 31 -
-27
src/atomic-xr/patches/envision/0004-Add-plugin-to-config-when-enabled.patch
··· 1 - From 39e8a8787ef0b0bb69c8754a880bb6bc4b2fe707 Mon Sep 17 00:00:00 2001 2 - From: "@matrixfurry.com" <did:plc:zmjoeu3stwcn44647rhxa44o> 3 - Date: Sat, 6 Sep 2025 01:13:52 -0500 4 - Subject: [PATCH 4/4] Add plugin to config when enabled 5 - 6 - --- 7 - src/ui/plugins/store.rs | 4 ++++ 8 - 1 file changed, 4 insertions(+) 9 - 10 - diff --git a/src/ui/plugins/store.rs b/src/ui/plugins/store.rs 11 - index 17d1534..c8f989d 100644 12 - --- a/src/ui/plugins/store.rs 13 - +++ b/src/ui/plugins/store.rs 14 - @@ -413,6 +413,10 @@ impl AsyncComponent for PluginStore { 15 - self.set_locked(false); 16 - } 17 - Self::Input::SetEnabled(signal_sender, plugin, enabled) => { 18 - + // HACK: I'm sure there's a much better way to do this, but I'm not a Rust 19 - + // HACK: ...developer, and this seems to work fine. 20 - + self.add_plugin_to_config(&sender, plugin.clone()); 21 - + 22 - if let Some(cp) = self.config_plugins.get_mut(&plugin.appid) { 23 - if let Err(e) = plugin.set_enabled(enabled) { 24 - error!( 25 - -- 26 - 2.51.0 27 -
-113
src/atomic-xr/runtime.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - 6 - const runtime_deps = { 7 - xr: [openxr-libs openvr-api] 8 - monado: [ 9 - libuvc 10 - openhmd 11 - opencv 12 - onnxruntime 13 - librealsense 14 - opencv-video 15 - ] 16 - } 17 - 18 - # Install runtime dependencies 19 - export def install [ 20 - ...groups: string # Package groups to install 21 - ] { 22 - ensure-installed (get-packages $groups) 23 - } 24 - 25 - # Uninstall runtime dependencies 26 - export def uninstall [ 27 - ...groups: string # Package groups to install 28 - ] { 29 - ensure-not-installed (get-packages $groups) 30 - } 31 - 32 - def get-packages [ 33 - groups: list<string> 34 - ] { 35 - if ($groups | is-empty) { 36 - $runtime_deps 37 - | transpose group packages 38 - } else { 39 - validate $groups 40 - 41 - $runtime_deps 42 - | transpose group packages 43 - | where group in $groups 44 - } 45 - | get packages 46 - | flatten 47 - } 48 - 49 - def validate [ 50 - groups: list<string> 51 - ] { 52 - let avaliable_groups = $runtime_deps 53 - | transpose group packages 54 - | get group 55 - 56 - $groups 57 - | each {|group| 58 - if $group not-in $avaliable_groups { 59 - error make { 60 - msg: "Unknown package group" 61 - label: { 62 - span: (metadata $group).span 63 - text: $"Unknown package group: ($group)" 64 - } 65 - help: $"Avaliable groups: ($avaliable_groups | str join ', ')" 66 - } 67 - } 68 - } 69 - } 70 - 71 - def ensure-installed [ 72 - packages: list<string> 73 - ] { 74 - let missing_packages = $packages 75 - | each {|package| 76 - if (rpm -q $package | complete | get exit_code) != 0 { 77 - $package 78 - } 79 - } 80 - 81 - if ($missing_packages | is-not-empty) { 82 - rpm-ostree install ...$missing_packages 83 - job spawn { 84 - match (notify-send -u critical "Package(s) installed" "Please reboot or use `rpm-ostree ex apply-live` to apply changes." -A reboot="Reboot" -A live="Apply Changes Live") { 85 - "reboot" => (systemctl reboot) 86 - "live" => (pkexec rpm-ostree ex apply-live) 87 - } 88 - } 89 - null 90 - } 91 - } 92 - 93 - def ensure-not-installed [ 94 - packages: list<string> 95 - ] { 96 - let installed_packages = $packages 97 - | each {|package| 98 - if (rpm -q $package | complete | get exit_code) == 0 { 99 - $package 100 - } 101 - } 102 - 103 - if ($installed_packages | is-not-empty) { 104 - rpm-ostree remove ...$installed_packages 105 - job spawn { 106 - match (notify-send -u critical "Package(s) removed" "Please reboot or use `rpm-ostree ex apply-live` to apply changes." -A reboot="Reboot" -A live="Apply Changes Live") { 107 - "reboot" => (systemctl reboot) 108 - "live" => (pkexec rpm-ostree ex apply-live --allow-replacement) 109 - } 110 - } 111 - null 112 - } 113 - }
-92
src/atomic-xr/steamvr-lh.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - 6 - def "ask yn" [prompt: string] { 7 - loop { 8 - match (input -n 1 $"($prompt) [y/n]: " | str downcase) { 9 - "y" => (return true) 10 - "n" => (return false) 11 - _ => (log error "Invalid option, please choose `y` or `n`.") 12 - } 13 - } 14 - } 15 - 16 - # SteamVR Quick Calibration 17 - export def calibrate [] { 18 - # TODO: Support using native steam installation 19 - log warning "This is intended for Flatpak Steam, if you're using native Steam, please use Envision instead." 20 - log warning "If you'd like to use this feature with native Steam, please open an issue on Tangled." 21 - 22 - if (ask yn "Do you own a lighthouse-tracked HMD? (e.g. Index, Vive Pro)") { 23 - input -sn 1 "Please connect your headset and place it on the floor, then press any key to start the calibration." 24 - 25 - log info "Starting SteamVR Lighthouse calibration" 26 - 27 - let vrcmd_bin: path = $"($env.HOME)/.steam/root/steamapps/common/SteamVR/bin/linux64/vrcmd" 28 - let environment = $"LD_LIBRARY_PATH=('~/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/common/SteamVR/bin/linux64' | path expand)" 29 - 30 - let server = job spawn {flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --pollposes} 31 - sleep 2sec # TODO: detect when the server is ready 32 - try { 33 - flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --resetroomsetup 34 - } catch {|err| 35 - job kill $server 36 - error make $err 37 - } 38 - 39 - job kill $server 40 - log info "Calibration finished" 41 - } else { 42 - log info "Creating default Lighthouse Database" 43 - 44 - if not ("~/.steam/root/config/lighthouse/" | path exists) { 45 - error make { 46 - msg: "Could not find lighthouse configuration directory." 47 - help: "Make sure you have SteamVR installed, and .steam points to the correct location. You may need to run `axr flatpak steam enable-xr` if you're using the Steam Flatpak." 48 - } 49 - } 50 - 51 - { 52 - base_stations: [] 53 - known_objects: [] 54 - known_universes: [] 55 - revision: 1 56 - } 57 - | save -f ~/.steam/root/config/lighthouse/lighthousedb.json 58 - 59 - log info "Created default Lighthouse Database" 60 - } 61 - } 62 - 63 - # Run lighthouse console natively or via flatpak depending on which is installed 64 - def lh-console [...args]: any -> any { 65 - if (which lighthouse_console | length) > 0 { 66 - log debug "Running lighthouse_console from PATH" 67 - run-external lighthouse_console 68 - } else if not ("~/.steam" | path exists) and ( 69 - "~/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console" 70 - | path exists 71 - ) or (ls -lD ~/.steam).0.target == ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 72 - log debug "Running lighthouse_console from steam flatpak" 73 - flatpak run --command=$"($env.HOME)/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console" com.valvesoftware.Steam ...$args 74 - } else if ("~/.steam" | path exists) { 75 - log debug "Running lighthouse_console from steam native" 76 - run-external $"($env.HOME)/.steam/root/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console" ...$args 77 - } else { 78 - error make { 79 - msg: "Could not find lighthouse_console" 80 - help: "Please make sure SteamVR is installed" 81 - } 82 - } 83 - } 84 - 85 - # Open SteamVR's lighthouse_console 86 - # 87 - # Useful for pairing, dumping device configs, etc. 88 - export def console [ 89 - ...args # Arguments to pass to lighthouse_console 90 - ] { 91 - lh-console ...$args 92 - }
-20
src/atomic-xr/wayvr.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - # Enable WayVR Dashboard 5 - export def "dashboard enable" [] { 6 - mkdir ~/.config/wlxoverlay/wayvr.conf.d 7 - 8 - {dashboard: { 9 - exec: /home/linuxbrew/.linuxbrew/bin/wayvr-dashboard 10 - args: '' 11 - env: [] 12 - }} 13 - | to yaml 14 - | save ~/.config/wlxoverlay/wayvr.conf.d/dashboard.yaml 15 - } 16 - 17 - # Disable WayVR Dashboard 18 - export def "dashboard disable" [] { 19 - rm ~/.config/wlxoverlay/wayvr.conf.d/dashboard.yaml 20 - }
-63
src/axr.nu.in
··· 1 - #!/usr/bin/env nu 2 - # SPDX-License-Identifier: AGPL-3.0-only 3 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 - 5 - use std log 6 - /@AXR_LIB@/ 7 - 8 - def main [ 9 - # TODO: --choose (-c) # Interactively choose a function 10 - --list (-l) # List avaliable commands 11 - --interactive (-i) # Enter interactive shell with the module loaded 12 - ...function 13 - ] { 14 - let function = $function | str join ' ' 15 - if $interactive { 16 - exec nu -e "/@AXR_LIB@/; print $'(ansi yellow)AtomicXR module loaded.(ansi reset)'" 17 - } else if $list or ($function | is-empty) { 18 - print-functions 19 - } else { 20 - # Make sure the function is valid to avoid unhelpful error messages 21 - # This regex checks if $function starts with anything in get-functions 22 - if $function like $"^\(?:(get-functions | str join '|')\)" { 23 - nu -c $"/@AXR_LIB@/; atomic-xr ($function)" 24 - } else { 25 - log error $"Invalid function: `($function)`" 26 - print-functions 27 - } 28 - } 29 - } 30 - 31 - def get-functions [] { 32 - scope modules 33 - | where name == atomic-xr 34 - | get 0.commands.name 35 - } 36 - 37 - def print-functions [] { 38 - get-functions 39 - | where not ($it starts-with "_") 40 - | each {|function| 41 - let help = help atomic-xr $function | lines 42 - 43 - let short_description = $help 44 - | first 45 - | if $in == $"(ansi green)Usage(ansi reset):" { 46 - null 47 - } else { 48 - $in 49 - } 50 - 51 - # let usage = $help 52 - # | get ( 53 - # ($help | enumerate | where item == $"(ansi green)Usage(ansi reset):").0.index + 1 54 - # ) 55 - # | str trim 56 - 57 - { 58 - command: $"(ansi cyan)($function)(ansi reset)" 59 - description: $"(ansi lp)($short_description)(ansi reset)" 60 - } 61 - } 62 - | table --index false --theme rounded 63 - }