mirror of
https://github.com/MichaelScottsman/LiquidAss-Frame.git
synced 2026-10-17 20:01:00 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
313d043115 | ||
|
|
7d7f55a5b4 | ||
|
|
d9d73383c2 |
No files matched your search
@@ -58,7 +58,7 @@ The [uninstall](#uninstall) command (or `python glass.py uninstall`) removes all
|
||||
## From the PC
|
||||
|
||||
```bash
|
||||
python glass.py install # copy this checkout to the headset and add the launcher (for development)
|
||||
python glass.py install # copy this checkout to the headset, set up glassd and add the launcher (for development)
|
||||
python glass.py on | off | toggle | status
|
||||
python glass.py dial 0.7 # glass intensity: 0 = clearest, 1 = most opaque (saved with your glass settings)
|
||||
python glass.py uninstall
|
||||
@@ -66,6 +66,8 @@ python glass.py uninstall
|
||||
|
||||
On the headset itself, `~/.local/share/glass-shell/device/lgs on|off|toggle|status|dial V` does the same.
|
||||
|
||||
Native glass works out of the box. Releases ship glassd built for the Frame (`native/glassd/prebuilt/glassd`), and the installer puts it in place. `python glass.py install` does the same, then rebuilds glassd from the checkout's sources over it (if that build fails, the shipped binary stays). The daemon also puts the shipped binary in place whenever glassd is missing, so the LiquidAss toggle never starts CSS-only. Native mode is on by default (`device/defaults.json`).
|
||||
|
||||
## How it works
|
||||
|
||||
| Piece | Role |
|
||||
|
||||
+39
-3
@@ -77,6 +77,7 @@ import collections # noqa: E402
|
||||
import hashlib # noqa: E402
|
||||
import json # noqa: E402
|
||||
import os # noqa: E402
|
||||
import shutil # noqa: E402
|
||||
import signal # noqa: E402
|
||||
import subprocess # noqa: E402
|
||||
import time # noqa: E402
|
||||
@@ -930,7 +931,7 @@ class Shell:
|
||||
self.native_enabled, self.css_reason = False, css_reason_for(self.native_req, self.native_src)
|
||||
elif not self.glassd_path:
|
||||
self.native_enabled, self.css_reason = False, "glassd disabled"
|
||||
elif not os.access(self.glassd_path, os.X_OK):
|
||||
elif not os.access(self.glassd_path, os.X_OK) and not ensure_glassd(self.glassd_path):
|
||||
self.native_enabled, self.css_reason = False, "no glassd binary at start; python glass.py native-build"
|
||||
else:
|
||||
self.native_enabled, self.css_reason = True, None
|
||||
@@ -2699,8 +2700,18 @@ class Shell:
|
||||
if self.gseq and not self.g_files_removed: # native mode ended mid-session
|
||||
self.g_files_removed = True
|
||||
remove_glassd_files()
|
||||
# only the binary was missing (an install swapping the folder under us, a toggle run before the
|
||||
# install finished): native comes back as soon as a glassd is in place again
|
||||
if self.native_requested and self.glassd_path and str(self.css_reason or "").startswith(
|
||||
("glassd binary removed", "no glassd binary at start")) and ensure_glassd(self.glassd_path):
|
||||
log("glassd: binary in place again; native layer back on")
|
||||
self.native_enabled, self.css_reason = True, None
|
||||
self.g_files_removed = False
|
||||
self.g_given_up = False
|
||||
self.tasks.append(asyncio.create_task(self.glassd_loop()))
|
||||
self.changed.set()
|
||||
return
|
||||
if not os.access(self.glassd_path, os.X_OK):
|
||||
if not os.access(self.glassd_path, os.X_OK) and not ensure_glassd(self.glassd_path):
|
||||
self.disable_native("glassd binary removed")
|
||||
await self.kill_glassd()
|
||||
return
|
||||
@@ -2748,7 +2759,7 @@ class Shell:
|
||||
return
|
||||
temp_streak = 0
|
||||
while not self.stopping and self.native_possible():
|
||||
if not os.access(self.glassd_path, os.X_OK):
|
||||
if not os.access(self.glassd_path, os.X_OK) and not ensure_glassd(self.glassd_path):
|
||||
self.disable_native("glassd binary removed")
|
||||
return
|
||||
# glassd needs SteamVR and something to cover (and the theme on: not dormant)
|
||||
@@ -3362,6 +3373,29 @@ def core_args(argv):
|
||||
return out
|
||||
|
||||
|
||||
GLASSD_PREBUILT = os.path.join(lgs.ROOT, "native", "glassd", "prebuilt", "glassd")
|
||||
|
||||
|
||||
def ensure_glassd(path=GLASSD_BIN):
|
||||
"""The shipped glassd (native/glassd/prebuilt/glassd) in place when no build is there yet, so native
|
||||
glass works out of the box and a Liquid Glass toggle that runs before a build finishes is never stuck
|
||||
CSS-only. True when an executable glassd is in place."""
|
||||
if os.access(path, os.X_OK):
|
||||
return True
|
||||
if path != GLASSD_BIN or not os.access(GLASSD_PREBUILT, os.R_OK):
|
||||
return False
|
||||
try:
|
||||
tmp = path + ".tmp"
|
||||
shutil.copyfile(GLASSD_PREBUILT, tmp)
|
||||
os.chmod(tmp, 0o755)
|
||||
os.replace(tmp, path)
|
||||
log("glassd: no build here; the shipped binary is in place")
|
||||
return True
|
||||
except OSError as e:
|
||||
log(f"glassd: could not put the shipped binary in place: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def start(glassd=GLASSD_BIN, stay=False, glassd_args=None, native=None, test_report=None, assume_caps=None):
|
||||
"""Start the unit. Also resumes SteamVR page theming that a lab "--theme
|
||||
off" on a vr: page paused.
|
||||
@@ -3379,6 +3413,8 @@ def start(glassd=GLASSD_BIN, stay=False, glassd_args=None, native=None, test_rep
|
||||
loser's systemd-run fail with "already loaded" although a unit ran (review
|
||||
R1 m5); if the lock cannot be had in 60 s, it goes on and treats that
|
||||
error as running."""
|
||||
if glassd and glassd != "none":
|
||||
ensure_glassd(glassd)
|
||||
try:
|
||||
lk = FileLock(START_LOCK, 60).__enter__()
|
||||
except (OSError, TimeoutError):
|
||||
|
||||
@@ -161,12 +161,13 @@ def sync(client, only=None):
|
||||
for f in sorted(p.rglob("*")):
|
||||
if f.is_dir() or "__pycache__" in f.parts or f.suffix == ".pyc":
|
||||
continue
|
||||
# native/: sources only; builds happen on the Frame
|
||||
if sub == "native" and ("build" in f.parts or f.suffix in (".o", ".so", ".png", ".jpg")
|
||||
or (f.suffix == "" and f.name not in ("Makefile",))):
|
||||
# native/: sources only (builds happen on the Frame), plus the shipped glassd binary
|
||||
prebuilt = sub == "native" and "prebuilt" in f.parts
|
||||
if sub == "native" and not prebuilt and ("build" in f.parts or f.suffix in (".o", ".so", ".png", ".jpg")
|
||||
or (f.suffix == "" and f.name not in ("Makefile",))):
|
||||
continue
|
||||
ti = tar.gettarinfo(str(f), arcname=str(f.relative_to(ROOT)).replace("\\", "/"))
|
||||
ti.mode = 0o755 if f.suffix in (".py", ".sh") or f.name == "lgs" else 0o644
|
||||
ti.mode = 0o755 if f.suffix in (".py", ".sh") or f.name == "lgs" or prebuilt else 0o644
|
||||
ti.uid = ti.gid = 1000
|
||||
ti.uname = ti.gname = "steamos"
|
||||
with open(f, "rb") as fh:
|
||||
@@ -207,6 +208,21 @@ def native_build(client, fake=False):
|
||||
return code
|
||||
|
||||
|
||||
def install_glassd(client):
|
||||
"""glassd for native mode: the shipped binary (native/glassd/prebuilt/glassd), then a build from
|
||||
the synced sources over it. Exit code 0 when a working glassd is in place."""
|
||||
d = f"{REMOTE}/native/glassd"
|
||||
code, _, _ = sh(client, f"test -x {d}/prebuilt/glassd && install -m755 {d}/prebuilt/glassd {d}/glassd "
|
||||
f"&& echo 'glassd: shipped binary in place'", timeout=60)
|
||||
if native_build(client):
|
||||
print("glassd: the build from source failed; the shipped binary stays")
|
||||
code, _, _ = sh(client, f"{d}/glassd --help >/dev/null 2>&1; test -x {d}/glassd && echo 'glassd: ready ({d}/glassd)'",
|
||||
timeout=60)
|
||||
if code:
|
||||
print("glassd: no working binary; native glass is off until `python glass.py native-build` succeeds")
|
||||
return code
|
||||
|
||||
|
||||
def lgs(client, *args):
|
||||
q = " ".join(shlex.quote(a) for a in args)
|
||||
code, _, _ = sh(client, f"{PY} {REMOTE}/device/lgs.py {q}", timeout=120)
|
||||
@@ -1136,6 +1152,11 @@ def main(argv):
|
||||
sync(c, only=rest or None)
|
||||
elif cmd == "install":
|
||||
sync(c)
|
||||
# native glass out of the box: the shipped glassd goes in place first (the Liquid Glass toggle
|
||||
# may run at once), then a build from these sources replaces it; a failed build keeps it
|
||||
code = install_glassd(c)
|
||||
if code:
|
||||
return code
|
||||
sh(c, f"install -Dm644 {REMOTE}/device/glass-shell.desktop {DESKTOP} && "
|
||||
f"chmod 755 {REMOTE}/device/lgs {REMOTE}/device/lgs.py && "
|
||||
f"(update-desktop-database ~/.local/share/applications >/dev/null 2>&1 || true) && "
|
||||
|
||||
+19
-2
@@ -68,12 +68,26 @@ install_app() {
|
||||
tar -xzf "$tmp/$ASSET" -C "$tmp/new"
|
||||
[ -f "$tmp/new/device/lgs.py" ] || die "the archive is not a LiquidAss release"
|
||||
|
||||
# A running LiquidAss is stopped for the swap (its files, glassd's binary included, vanish for a moment)
|
||||
# and started again after it, on the new version.
|
||||
was_on=0
|
||||
if command -v systemctl >/dev/null 2>&1 && systemctl --user is-active --quiet lgs-shell 2>/dev/null && [ -f "$DEST/device/lgs.py" ]; then
|
||||
was_on=1
|
||||
say "turning LiquidAss off for the update"
|
||||
py "$DEST/device/lgs.py" off --quiet >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# Swap the whole folder so files a release dropped do not linger; keep a glassd built on this headset.
|
||||
mkdir -p "$(dirname "$DEST")"
|
||||
if [ -f "$DEST/native/glassd/glassd" ] && [ ! -e "$tmp/new/native/glassd/glassd" ]; then
|
||||
mkdir -p "$tmp/new/native/glassd"
|
||||
cp -p "$DEST/native/glassd/glassd" "$tmp/new/native/glassd/glassd"
|
||||
fi
|
||||
# Native glass out of the box: the release's shipped glassd (built for the Frame) when none was kept
|
||||
if [ ! -e "$tmp/new/native/glassd/glassd" ] && [ -f "$tmp/new/native/glassd/prebuilt/glassd" ]; then
|
||||
cp "$tmp/new/native/glassd/prebuilt/glassd" "$tmp/new/native/glassd/glassd"
|
||||
chmod 755 "$tmp/new/native/glassd/glassd"
|
||||
fi
|
||||
rm -rf "$DEST.old"
|
||||
[ -d "$DEST" ] && mv "$DEST" "$DEST.old"
|
||||
mv "$tmp/new" "$DEST"
|
||||
@@ -88,8 +102,11 @@ install_app() {
|
||||
|
||||
v=$(cat "$DEST/VERSION" 2>/dev/null || echo "")
|
||||
say "installed ${v:+$v }in $DEST"
|
||||
say "turn it on: dashboard bar > + > Launch Program > LiquidAss"
|
||||
say "(already on? launch LiquidAss twice to load the new version)"
|
||||
if [ "$was_on" = 1 ]; then
|
||||
py "$DEST/device/lgs.py" on --quiet >/dev/null 2>&1 && say "LiquidAss is back on (the new version)" || say "could not turn LiquidAss back on: launch it from + > Launch Program > LiquidAss"
|
||||
else
|
||||
say "turn it on: dashboard bar > + > Launch Program > LiquidAss"
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_app() {
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user