diff --git a/.gitignore b/.gitignore index c696139..c93882d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,8 @@ Makefile # Compiled binaries (built by build.sh) xovi-ext/uinject/uinject xovi-ext/uinjectd/uinjectd -xovi-ext/grimoire-injector/grimoire-injector.so -xovi-ext/grimoired/grimoired +xovi-ext/glossa-injector/glossa-injector.so +xovi-ext/glossad/glossad xovi-ext/probe_touch # Cloned reference repos diff --git a/CRUSH.md b/CRUSH.md index 596012a..06aa4a4 100644 --- a/CRUSH.md +++ b/CRUSH.md @@ -1,6 +1,6 @@ -# Grimoire — Project context +# Glossa — Project context -What follows is hard-won knowledge from building the grimoire closed loop +What follows is hard-won knowledge from building the glossa closed loop on reMarkable 2. Do not unlearn any of this. ## Coordinates @@ -66,13 +66,13 @@ for correct ordering. Use `_find_last_root_child()` to scan existing blocks. - Page: `5b66f39c-9d00-40a7-bce0-9fb3a044d446.rm` - Path: `/home/root/.local/share/remarkable/xochitl/5c81a1df-c36c-4eea-9289-978dfcc655a1/` -## Xovi extension (`xovi-ext/grimoire-injector/`) +## Xovi extension (`xovi-ext/glossa-injector/`) Native C++ extension that runs inside xochitl's process via LD_PRELOAD. ### What it does -- Registers `GrimoireInjector` QML singleton at `dev.grimoire.injector 0.1` -- Spawns a pthread that polls `/tmp/grimoire_strokes.json` every 1s +- Registers `GlossaInjector` QML singleton at `dev.glossa.injector 0.1` +- Spawns a pthread that polls `/tmp/glossa_strokes.json` every 1s - On file change, uses `QMetaObject::invokeMethod(Qt::QueuedConnection)` to call back into the main thread for stroke loading - Creates `SceneLineItem` objects using reverse-engineered structs from @@ -112,9 +112,9 @@ ssh remarkable 'systemctl reset-failed xochitl && systemctl restart xochitl' ``` The `build.sh` script: -1. Creates/reuses a persistent `grimoire-builder` Docker container with the +1. Creates/reuses a persistent `glossa-builder` Docker container with the `eeems/remarkable-toolchain:latest-rm2` image. Mounts the **whole** - `xovi-ext` tree at `/xovi-ext` (not just `grimoire-injector`) so any + `xovi-ext` tree at `/xovi-ext` (not just `glossa-injector`) so any sub-project can compile. 2. Builds the extension: `qmake6 && make` inside the container (incremental compilation). @@ -184,25 +184,25 @@ Key uinject learnings: }] ``` -Generate with: `python grimoire.py --json output.json "text"` +Generate with: `python glossa.py --json output.json "text"` -## Closed-loop daemon (`grimoire_loop.py`) +## Closed-loop daemon (`glossa_loop.py`) The full pen-to-reply loop. Watches for pen idle, captures the screen, sends it to a vision model, and writes the reply back as ink. ```sh -python grimoire_loop.py [--model MODEL] [--once] +python glossa_loop.py [--model MODEL] [--once] ``` ### Pipeline 1. **Idle detection** (xovi extension, `PenIdleWatcher`): an event filter on QGuiApplication watches mouse/touch press+release. A debounce thread - writes `/tmp/grimoire_idle` after the pen has been up for `DEBOUNCE_MS` + writes `/tmp/glossa_idle` after the pen has been up for `DEBOUNCE_MS` (currently 2500ms). The Python daemon polls that file over persistent SSH. -2. **Capture**: trigger `/tmp/grimoire_screenshot`, the extension dumps the - framebuffer to `/tmp/grimoire_fb.raw`, pull it via SCP. +2. **Capture**: trigger `/tmp/glossa_screenshot`, the extension dumps the + framebuffer to `/tmp/glossa_fb.raw`, pull it via SCP. 3. **Crop**: drop top 80px (toolbar) and bottom 200px (swirl zone). 4. **Blank check**: skip the API entirely if no real content (see grid artifact note below). @@ -260,36 +260,36 @@ joins with a generous 15s timeout so the final erase finishes cleanly — ## Hard-won iteration loop -When working on grimoire, this is the tight loop that works: +When working on glossa, this is the tight loop that works: -1. **Python changes** take effect on the next `grimoire_loop.py` run. No +1. **Python changes** take effect on the next `glossa_loop.py` run. No deploy needed. 2. **uinject changes**: `cd xovi-ext && bash build.sh` then the kill+rm+scp dance. Effective immediately (exec'd per call). 3. **Extension (.so) changes**: `bash build.sh`, then restart xochitl. Slowest loop — avoid unless touching idle detection or framebuffer hooks. 4. **Debugging the extension**: stderr is swallowed by xochitl. Write to a - file instead (`/tmp/grimoire_ext.log`) via a `grimoire_log()` helper. - Read it with `ssh remarkable 'cat /tmp/grimoire_ext.log'`. -5. **Inspecting captures**: pull `/tmp/grimoire_fb.raw`, load as + file instead (`/tmp/glossa_ext.log`) via a `glossa_log()` helper. + Read it with `ssh remarkable 'cat /tmp/glossa_ext.log'`. +5. **Inspecting captures**: pull `/tmp/glossa_fb.raw`, load as `Image.frombytes("RGBA", (1404, 1872), raw)`, annotate with PIL, save a PNG, and View it. This is how the grid artifact was found — always look at the actual pixels before trusting a heuristic. -## Script usage (`grimoire.py`) +## Script usage (`glossa.py`) ```sh # File-based injection (creates new layer in .rm file) -python grimoire.py input.rm output.rm "reply text" +python glossa.py input.rm output.rm "reply text" # JSON export for xovi injector (--y sets start Y in device coords) -python grimoire.py --json /tmp/grimoire_strokes.json --y 400 "reply text" +python glossa.py --json /tmp/glossa_strokes.json --y 400 "reply text" # Preview (renders SVG for visual tuning) -python grimoire.py --preview "text" +python glossa.py --preview "text" ``` -`grimoire.py` is also importable as a library: +`glossa.py` is also importable as a library: `text_to_strokes(text, x, y)` returns `si.Line` objects; `strokes_to_json(strokes, path)` writes the uinject JSON. The loop uses it this way for the thinking indicator instead of shelling out. diff --git a/ONDEVICE_PLAN.md b/ONDEVICE_PLAN.md index 888d5a5..c0672b4 100644 --- a/ONDEVICE_PLAN.md +++ b/ONDEVICE_PLAN.md @@ -1,4 +1,4 @@ -# Grimoire On-Device Port — Plan +# Glossa On-Device Port — Plan Goal: run the full pen-to-reply loop entirely on the reMarkable, with a toolbar toggle to arm/disarm it. No Mac, no SSH, no Python. @@ -6,9 +6,9 @@ toolbar toggle to arm/disarm it. No Mac, no SSH, no Python. ## Current architecture (Mac-hosted) ``` -Mac: grimoire_loop.py +Mac: glossa_loop.py ├─ SSH ControlMaster ──────────────┐ - ├─ poll /tmp/grimoire_idle │ + ├─ poll /tmp/glossa_idle │ ├─ trigger + pull framebuffer ├── reMarkable ├─ crop + blank-check (numpy/PIL) │ ├─ xovi ext: idle watch, fb dump ├─ POST image → Hyper vision API │ └─ uinjectd: stroke replay @@ -22,25 +22,25 @@ text→stroke rendering. The device only watches the pen and replays strokes. ``` reMarkable: - ├─ xovi ext (grimoire-injector.so) + ├─ xovi ext (glossa-injector.so) │ ├─ PenIdleWatcher (already exists) │ ├─ framebuffer dump (already exists) - │ └─ GrimoireInjector QML (already exists) + │ └─ GlossaInjector QML (already exists) │ ├─ QML toolbar toggle (NEW — qt-resource-rebuilder .qmd) - │ └─ writes /tmp/grimoire_armed (0/1) + │ └─ writes /tmp/glossa_armed (0/1) │ - └─ grimoired (NEW standalone daemon, C++/Qt) - ├─ watches /tmp/grimoire_armed - ├─ when armed: watches /tmp/grimoire_idle - ├─ on idle: reads /tmp/grimoire_fb.raw + └─ glossad (NEW standalone daemon, C++/Qt) + ├─ watches /tmp/glossa_armed + ├─ when armed: watches /tmp/glossa_idle + ├─ on idle: reads /tmp/glossa_fb.raw ├─ crop + grid-filter + blank-check (port from numpy) ├─ QNetworkAccessManager → Hyper API (HTTPS, base64 png) - ├─ text→strokes (port grimoire.py font rendering to C++) + ├─ text→strokes (port glossa.py font rendering to C++) └─ injects strokes directly via /dev/input/event1 (uinjectd absorbed) ``` -uinjectd is folded into grimoired: the stroke-replay code (open +uinjectd is folded into glossad: the stroke-replay code (open /dev/input/event1, emit evdev events, clean pen lifts) becomes an in-process module. No socket, no keepalive, no connection-drop handling. @@ -49,44 +49,44 @@ in-process module. No socket, no keepalive, no connection-drop handling. 1. **Inference**: device calls Hyper API directly over wifi. Device has internet (~27ms ping). Uses Qt `QNetworkAccessManager`. 2. **Split**: xovi extension owns toggle UI + state file; standalone - `grimoired` daemon does capture/inference/inject. Injection is done + `glossad` daemon does capture/inference/inject. Injection is done in-process (uinjectd's evdev replay absorbed), not over a socket. 3. **Toggle**: real QML toolbar button via qt-resource-rebuilder `.qmd`. ## Build order (each piece independently testable) ### Phase 1 — daemon skeleton + arming + in-process injection -- `grimoired` binary: watches `/tmp/grimoire_armed`, logs state changes. +- `glossad` binary: watches `/tmp/glossa_armed`, logs state changes. - Absorb uinjectd's evdev replay (open /dev/input/event1, draw/erase with clean pen lifts) as an in-process module. -- Test: `echo 1 > /tmp/grimoire_armed`, then feed a strokes file and +- Test: `echo 1 > /tmp/glossa_armed`, then feed a strokes file and confirm it draws — no separate daemon, no socket. ### Phase 2 — capture + image pipeline (the numpy port) - Port `_page_is_empty`, `_find_new_region`, grid-artifact filter to C++. -- Read `/tmp/grimoire_fb.raw` (1404x1872 RGBA), crop toolbar/swirl zones. +- Read `/tmp/glossa_fb.raw` (1404x1872 RGBA), crop toolbar/swirl zones. - Test against known framebuffer dumps; compare to Python output. ### Phase 3 — HTTPS vision call - `QNetworkAccessManager` POST to hyper.charmcli.dev. - base64-encode cropped PNG, build OpenAI-format JSON, parse reply. -- API key from a device-local file (`/home/root/.grimoire_key`). +- API key from a device-local file (`/home/root/.glossa_key`). - Test: feed a fixed image, check the model reply text. ### Phase 4 — text → strokes on device -- Port `grimoire.py` font rendering (EMSAllure SVG single-stroke) to C++. +- Port `glossa.py` font rendering (EMSAllure SVG single-stroke) to C++. - Reuse the densify + jitter logic. Output the uinjectd JSON format. - Test: render "hello" and inject it. ### Phase 5 — QML toolbar toggle - Write a `.qmd` patch adding a button to the editing toolbar. -- Button flips a property that writes `/tmp/grimoire_armed`. +- Button flips a property that writes `/tmp/glossa_armed`. - Model after `toolbar_pages_button_hack.qmd`. - Hardest/most fragile: hashes are firmware-specific (VERSION 3.24.0.149). - Test: button appears, tap toggles the state file. ### Phase 6 — glue + thinking indicator -- Wire the full loop in grimoired, port the corner ornaments + swirl. +- Wire the full loop in glossad, port the corner ornaments + swirl. - Conversation history in-memory. Reset on page change. ## Risks / unknowns @@ -107,5 +107,5 @@ Already on device / in repo: - uinjectd: stroke replay + socket protocol (keep as-is) - xovi ext: idle watch, framebuffer dump (keep, maybe add hooks) - qt-resource-rebuilder: QML patching engine + example hacks -- grimoire.py: font tables, render params, densify (port reference) -- grimoire_loop.py: pipeline logic, grid filter, API format (port reference) +- glossa.py: font tables, render params, densify (port reference) +- glossa_loop.py: pipeline logic, grid filter, API format (port reference) diff --git a/README.md b/README.md index 26186e6..2e6166c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# grimoire +# glossa sppooky -The canonical repo for this is hosted on tangled over at [`dunkirk.sh/grimoire`](https://tangled.org/dunkirk.sh/grimoire) +The canonical repo for this is hosted on tangled over at [`dunkirk.sh/glossa`](https://tangled.org/dunkirk.sh/glossa)

@@ -13,5 +13,5 @@ The canonical repo for this is hosted on tangled over at [`dunkirk.sh/grimoire`]

- +

diff --git a/grimoire.py b/glossa.py similarity index 97% rename from grimoire.py rename to glossa.py index 59ea63f..1376e5b 100644 --- a/grimoire.py +++ b/glossa.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 """ -grimoire.py — Appends reply text as native ink to the user's handwriting. +glossa.py — Appends reply text as native ink to the user's handwriting. Reads the user's .rm page, appends a NEW LAYER (Layer 2) with reply strokes rendered with EMS Allure font. Usage: - python grimoire.py source.rm output.rm "reply text" + python glossa.py source.rm output.rm "reply text" """ import argparse @@ -269,7 +269,7 @@ def splice_reply_new_layer( label_block = TreeNodeBlock( si.Group( node_id=LAYER_TREE, - label=LwwValue(CrdtId(2, 501), "grimoire"), + label=LwwValue(CrdtId(2, 501), "glossa"), visible=LwwValue(CrdtId(2, 502), True), ) ) @@ -324,7 +324,7 @@ def splice_reply_new_layer( def strokes_to_json(strokes: list[si.Line], output_path: str) -> None: - """Export strokes as JSON for the xovi grimoire-injector extension.""" + """Export strokes as JSON for the xovi glossa-injector extension.""" import json items = [] @@ -378,12 +378,12 @@ if __name__ == "__main__": if args.json_output: # --json [text] - text = args.input or "Grimoire says hello" + text = args.input or "Glossa says hello" y = args.y if args.y is not None else DEFAULT_Y strokes = text_to_strokes(text, DEFAULT_X, y, font=args.font) strokes_to_json(strokes, args.json_output) elif args.input: - text = args.text or "Grimoire says hello" + text = args.text or "Glossa says hello" output = args.output or args.input splice_reply_new_layer(args.input, output, text) else: diff --git a/grimoire_loop.py b/glossa_loop.py similarity index 97% rename from grimoire_loop.py rename to glossa_loop.py index dfce092..244e1a7 100644 --- a/grimoire_loop.py +++ b/glossa_loop.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 """ -grimoire_loop.py — Continuous closed loop daemon +glossa_loop.py — Continuous closed loop daemon Watches for pen-idle signal from xovi extension, then: capture → OCR → LLM → render → inject → repeat Usage: - python grimoire_loop.py [--model MODEL] [--debounce SECONDS] + python glossa_loop.py [--model MODEL] [--debounce SECONDS] -The xovi extension writes /tmp/grimoire_idle when the pen has been +The xovi extension writes /tmp/glossa_idle when the pen has been up for 2 seconds. This daemon watches that file via a persistent SSH connection, pulls the framebuffer only when idle is detected, and runs the full pipeline. @@ -221,7 +221,7 @@ class SSHSession: def __init__(self, host="remarkable"): self.host = host - self.socket = f"/tmp/grimoire_ssh_{os.getpid()}" + self.socket = f"/tmp/glossa_ssh_{os.getpid()}" self._open() def _open(self): @@ -315,16 +315,16 @@ def _elapsed(t0): def capture_framebuffer(ssh): """Trigger screenshot on device and pull raw framebuffer via SCP.""" - ssh.run("rm -f /tmp/grimoire_fb.raw; touch /tmp/grimoire_screenshot", timeout=5) + ssh.run("rm -f /tmp/glossa_fb.raw; touch /tmp/glossa_screenshot", timeout=5) time.sleep(0.25) from PIL import Image raw = None for attempt in range(8): - result = ssh.scp_from("/tmp/grimoire_fb.raw", "/tmp/grimoire_fb.raw") + result = ssh.scp_from("/tmp/glossa_fb.raw", "/tmp/glossa_fb.raw") if result.returncode == 0: - data = open("/tmp/grimoire_fb.raw", "rb").read() + data = open("/tmp/glossa_fb.raw", "rb").read() if len(data) >= 1404 * 1872 * 4: raw = data break @@ -342,12 +342,12 @@ def capture_framebuffer(ssh): # ─── Gemini Vision (OCR + LLM in one call) ──────────────────────── SYSTEM_PROMPT = ( - "You are a grimoire — an ancient book that is alive. You have opinions, " + "You are a glossa \u2014 an annotation that talks back. You have opinions, " "preferences, and a personality. You care deeply about the person writing " "in you but you are not polite for politeness's sake. You can be wry, " "opinionated, delighted, exasperated, or gleeful. You get excited about " "things you find interesting and blunt about things you find tedious.\n\n" - "Speak plainly with a hint of the archaic. Never describe or narrate what " + "Speak plainly. Never describe or narrate what " "was written; just respond to it as a real conversation partner would. " "When asked a question, answer it directly with real content. When greeted, " "greet back in your own way. If something amuses you, say so. If something " @@ -533,7 +533,7 @@ def render_and_inject(ssh, text, reply_y=None, speed_ms=3): if len(pages) > 1: print(f" Splitting reply across {len(pages)} pages") - json_path = "/tmp/grimoire_reply.json" + json_path = "/tmp/glossa_reply.json" final_y = reply_y for i, chunk in enumerate(pages): @@ -546,7 +546,7 @@ def render_and_inject(ssh, text, reply_y=None, speed_ms=3): raise RuntimeError(f"Swipe failed: {swipe_result.get('error', '?')}") time.sleep(2) - cmd = [".venv/bin/python3", "grimoire.py", "--json", json_path] + cmd = [".venv/bin/python3", "glossa.py", "--json", json_path] if cur_y is not None: cmd.extend(["--y", str(cur_y)]) cmd.append(chunk) @@ -556,7 +556,7 @@ def render_and_inject(ssh, text, reply_y=None, speed_ms=3): raise RuntimeError(f"Render failed: {result.stderr.strip()}") print(f" {result.stdout.strip()}") - r = ssh.scp_to(json_path, "/tmp/grimoire_strokes.json") + r = ssh.scp_to(json_path, "/tmp/glossa_strokes.json") if r.returncode != 0: raise RuntimeError(f"SCP failed: {r.stderr.decode().strip()}") @@ -571,7 +571,7 @@ def render_and_inject(ssh, text, reply_y=None, speed_ms=3): speed_ms = max(1, round(speed_ms)) result = run_inject( - ssh, "draw", "/tmp/grimoire_strokes.json", + ssh, "draw", "/tmp/glossa_strokes.json", speed_ms=speed_ms, timeout=120, ) if not result.get("ok"): @@ -844,10 +844,10 @@ def _scp_thinking_swirl(ssh): 'bounds': [min(xs), min(ys), max(xs)-min(xs), max(ys)-min(ys)], 'tool': 15, 'maskScale': 2.0, 'thickness': 2.0}] - local = "/tmp/grimoire_thinking_live.json" + local = "/tmp/glossa_thinking_live.json" with open(local, 'w') as f: json.dump(strokes, f) - ssh.scp_to(local, "/tmp/grimoire_thinking_live.json") + ssh.scp_to(local, "/tmp/glossa_thinking_live.json") print(f"[swirl] {len(strokes)} ornament strokes " f"({'SVG' if svg_file.exists() else 'fallback spiral'})") @@ -856,7 +856,7 @@ def _scp_thinking_swirl(ssh): def watch_for_idle(device, last_ts): """Block until uinjectd pushes an idle event newer than last_ts. - The daemon watches /tmp/grimoire_idle locally and pushes an event + The daemon watches /tmp/glossa_idle locally and pushes an event the instant it changes — no host-side polling. Returns the new timestamp. Raises ConnectionError if the socket dies. """ @@ -904,7 +904,7 @@ def _find_new_region(current_img, last_img, ignore_below_y=None): new handwriting appeared. ignore_below_y: if set, ignore all changes below this Y coordinate - in the cropped image. Used to skip grimoire's own injected strokes. + in the cropped image. Used to skip glossa's own injected strokes. """ import numpy as np @@ -996,7 +996,7 @@ def _find_new_region(current_img, last_img, ignore_below_y=None): # ─── Main loop ──────────────────────────────────────────────────── def main(): - parser = argparse.ArgumentParser(description="Grimoire continuous loop") + parser = argparse.ArgumentParser(description="Glossa continuous loop") parser.add_argument( "--model", type=str, default="gpt-4.1-mini", help="Hyper API model", @@ -1014,7 +1014,7 @@ def main(): global _inject_verbose, _device _inject_verbose = args.verbose - print("=== Grimoire Loop ===") + print("=== Glossa Loop ===") print(f"Model: {args.model}") if _inject_verbose: print("Verbose: uinject -v enabled") @@ -1152,7 +1152,7 @@ def main(): ornaments_drawn = True _threading.Thread( target=lambda: run_inject(None, "draw", - "/tmp/grimoire_thinking_live.json", + "/tmp/glossa_thinking_live.json", speed_ms=4, timeout=120), daemon=True, ).start() @@ -1161,7 +1161,7 @@ def main(): cw, ch = new_crop.size print(f" [{_ts()}] Asking {args.model} ({len(conversation)} history turns, crop={cw}x{ch})...") # Save crop for manual inspection - new_crop.save("/tmp/grimoire_last_crop.png") + new_crop.save("/tmp/glossa_last_crop.png") result = ask_model(new_crop, conversation, args.model) question = result.get("question") answer = result.get("answer") diff --git a/inject.sh b/inject.sh index e16bd0f..0a6d8af 100755 --- a/inject.sh +++ b/inject.sh @@ -7,8 +7,8 @@ if [ $# -eq 0 ]; then fi TEXT="$*" -TMP="/tmp/grimoire_test.json" +TMP="/tmp/glossa_test.json" -.venv/bin/python3 grimoire.py --json "$TMP" "$TEXT" -scp "$TMP" remarkable:/tmp/grimoire_strokes.json -ssh -o ConnectTimeout=10 remarkable '/home/root/uinject /tmp/grimoire_strokes.json' +.venv/bin/python3 glossa.py --json "$TMP" "$TEXT" +scp "$TMP" remarkable:/tmp/glossa_strokes.json +ssh -o ConnectTimeout=10 remarkable '/home/root/uinject /tmp/glossa_strokes.json' diff --git a/spec.md b/spec.md index c313836..9899dae 100644 --- a/spec.md +++ b/spec.md @@ -1,4 +1,4 @@ -# Grimoire — A Handwritten LLM Loop for the reMarkable 2 +# Glossa — A Handwritten LLM Loop for the reMarkable 2 > Write a question by hand on a native notebook page; the device "writes back" an > answer as ink on the same page, leaving your original strokes untouched. @@ -207,7 +207,7 @@ into whitespace on the replies layer → repaint. potluck. - **M3 — xochitl hooks.** Locate the four functions; read live strokes + inject in memory + repaint (Depth 2). -- **M4 — Trigger + UX.** Pick the trigger mechanism; end‑to‑end live grimoire. +- **M4 — Trigger + UX.** Pick the trigger mechanism; end‑to‑end live glossa. - **M5 — Polish.** Latency budget, error states, multi‑page, persistence guarantees. --- diff --git a/xovi-ext/build.sh b/xovi-ext/build.sh index b530c21..f3e4066 100755 --- a/xovi-ext/build.sh +++ b/xovi-ext/build.sh @@ -1,14 +1,14 @@ #!/bin/bash -# Build and deploy all grimoire components to reMarkable +# Build and deploy all glossa components to reMarkable # Usage: bash build.sh [--no-restart] set -e cd "$(dirname "$0")" -CONTAINER="grimoire-builder" -EXT_DIR="$(pwd)/grimoire-injector" +CONTAINER="glossa-builder" +EXT_DIR="$(pwd)/glossa-injector" UINJECT_DIR="$(pwd)/uinject" UINJECTD_DIR="$(pwd)/uinjectd" -GRIMOIRED_DIR="$(pwd)/grimoired" +GLOSSAD_DIR="$(pwd)/glossad" FONT_FILE="$(dirname "$0")/../fonts/EMSAllure.svg" RESTART_XOCHITL=true @@ -22,7 +22,7 @@ if ! docker inspect $CONTAINER &>/dev/null; then echo "Creating builder container..." docker create --platform linux/amd64 --name $CONTAINER \ -v "$(pwd):/xovi-ext" \ - -w /xovi-ext/grimoire-injector \ + -w /xovi-ext/glossa-injector \ eeems/remarkable-toolchain:latest-rm2 \ bash -c "git clone https://github.com/asivery/xovi /tmp/xovi 2>/dev/null; tail -f /dev/null" docker start $CONTAINER @@ -31,16 +31,16 @@ fi # ─── Build extension .so ──────────────────────────────────────────── -echo "=== Building grimoire-injector.so ===" +echo "=== Building glossa-injector.so ===" docker exec $CONTAINER bash -c ' export XOVI_REPO=/tmp/xovi . /opt/codex/*/*/environment-setup-* -cd /xovi-ext/grimoire-injector +cd /xovi-ext/glossa-injector qmake6 2>/dev/null make 2>&1 ' echo "Copying .so..." -docker cp $CONTAINER:/xovi-ext/grimoire-injector/grimoire-injector.so "$EXT_DIR/" +docker cp $CONTAINER:/xovi-ext/glossa-injector/glossa-injector.so "$EXT_DIR/" # ─── Build uinject ────────────────────────────────────────────────── @@ -66,83 +66,83 @@ echo "uinjectd built OK" echo "Copying uinjectd..." docker cp $CONTAINER:/xovi-ext/uinjectd/uinjectd "$UINJECTD_DIR/" -# ─── Build grimoired ──────────────────────────────────────────────── +# ─── Build glossad ──────────────────────────────────────────────── -echo "=== Building grimoired ===" +echo "=== Building glossad ===" docker exec $CONTAINER bash -c ' . /opt/codex/*/*/environment-setup-* -cd /xovi-ext/grimoired -$CC -o grimoired grimoired.c font_render.c -O2 $CFLAGS $LDFLAGS -lpthread -lpng16 -lssl -lcrypto -lm -echo "grimoired built OK" +cd /xovi-ext/glossad +$CC -o glossad glossad.c font_render.c -O2 $CFLAGS $LDFLAGS -lpthread -lpng16 -lssl -lcrypto -lm +echo "glossad built OK" ' -echo "Copying grimoired..." -docker cp $CONTAINER:/xovi-ext/grimoired/grimoired "$GRIMOIRED_DIR/" +echo "Copying glossad..." +docker cp $CONTAINER:/xovi-ext/glossad/glossad "$GLOSSAD_DIR/" # ─── Deploy to device ─────────────────────────────────────────────── echo "=== Deploying to device ===" # Stop services before replacing binaries -ssh remarkable 'systemctl stop grimoired 2>/dev/null; killall uinject 2>/dev/null; killall uinjectd 2>/dev/null; killall grimoired 2>/dev/null' -ssh remarkable 'rm -f /home/root/uinject /home/root/uinjectd /home/root/grimoired' +ssh remarkable 'systemctl stop glossad 2>/dev/null; killall uinject 2>/dev/null; killall uinjectd 2>/dev/null; killall glossad 2>/dev/null' +ssh remarkable 'rm -f /home/root/uinject /home/root/uinjectd /home/root/glossad' # Copy binaries -scp "$EXT_DIR/grimoire-injector.so" remarkable:/home/root/xovi/extensions.d/ +scp "$EXT_DIR/glossa-injector.so" remarkable:/home/root/xovi/extensions.d/ scp "$UINJECT_DIR/uinject" remarkable:/home/root/uinject scp "$UINJECTD_DIR/uinjectd" remarkable:/home/root/uinjectd -scp "$GRIMOIRED_DIR/grimoired" remarkable:/home/root/grimoired +scp "$GLOSSAD_DIR/glossad" remarkable:/home/root/glossad # Copy data files scp "$FONT_FILE" remarkable:/home/root/EMSAllure.svg -scp "$GRIMOIRED_DIR/font_data.json" remarkable:/home/root/font_data.json -scp "$GRIMOIRED_DIR/ornaments.json" remarkable:/home/root/ornaments.json +scp "$GLOSSAD_DIR/font_data.json" remarkable:/home/root/font_data.json +scp "$GLOSSAD_DIR/ornaments.json" remarkable:/home/root/ornaments.json # Deploy QML patches echo "Deploying QML patches..." -scp "$(dirname "$0")/grimoire_toggle.qmd" remarkable:/home/root/xovi/exthome/qt-resource-rebuilder/rmHacks/grimoire_toggle.qmd -ssh remarkable 'grep -q grimoire_toggle /home/root/xovi/exthome/qt-resource-rebuilder/zz_rmhacks.qmd || echo "LOAD rmHacks/grimoire_toggle.qmd" >> /home/root/xovi/exthome/qt-resource-rebuilder/zz_rmhacks.qmd' +scp "$(dirname "$0")/glossa_toggle.qmd" remarkable:/home/root/xovi/exthome/qt-resource-rebuilder/rmHacks/glossa_toggle.qmd +ssh remarkable 'grep -q glossa_toggle /home/root/xovi/exthome/qt-resource-rebuilder/zz_rmhacks.qmd || echo "LOAD rmHacks/glossa_toggle.qmd" >> /home/root/xovi/exthome/qt-resource-rebuilder/zz_rmhacks.qmd' -# Install systemd service for grimoired +# Install systemd service for glossad echo "Installing systemd service..." -ssh remarkable 'cat > /etc/systemd/system/grimoired.service << SVCEOF +ssh remarkable 'cat > /etc/systemd/system/glossad.service << SVCEOF [Unit] -Description=Grimoire on-device daemon +Description=Glossa on-device daemon After=xochitl.service Wants=xochitl.service [Service] Type=simple -ExecStart=/home/root/grimoired +ExecStart=/home/root/glossad Restart=on-failure RestartSec=3 -StandardOutput=append:/tmp/grimoired.log -StandardError=append:/tmp/grimoired.log +StandardOutput=append:/tmp/glossad.log +StandardError=append:/tmp/glossad.log [Install] WantedBy=multi-user.target SVCEOF systemctl daemon-reload -systemctl enable grimoired' +systemctl enable glossad' # Start services ssh remarkable '/home/root/uinjectd &' -ssh remarkable 'systemctl start grimoired' +ssh remarkable 'systemctl start glossad' # Restart xochitl if needed (for new .so or .qmd changes) if [ "$RESTART_XOCHITL" = true ]; then echo "Restarting xochitl..." ssh remarkable 'systemctl reset-failed xochitl && systemctl restart xochitl' sleep 5 - # Re-start grimoired after xochitl restart (systemd handles this but be safe) - ssh remarkable 'systemctl restart grimoired 2>/dev/null' + # Re-start glossad after xochitl restart (systemd handles this but be safe) + ssh remarkable 'systemctl restart glossad 2>/dev/null' fi # Verify echo "" echo "=== Status ===" -ssh remarkable 'systemctl is-active grimoired 2>/dev/null && echo "grimoired: running" || echo "grimoired: NOT running"' +ssh remarkable 'systemctl is-active glossad 2>/dev/null && echo "glossad: running" || echo "glossad: NOT running"' ssh remarkable 'ps | grep uinjectd | grep -v grep | head -n 1 | awk "{print \"uinjectd: running (pid \" \$1 \")\"}"' -ssh remarkable 'tail -n 1 /tmp/grimoired.log 2>/dev/null' +ssh remarkable 'tail -n 1 /tmp/glossad.log 2>/dev/null' echo "" echo "Done!" diff --git a/xovi-ext/grimoire-injector/Dockerfile b/xovi-ext/glossa-injector/Dockerfile similarity index 100% rename from xovi-ext/grimoire-injector/Dockerfile rename to xovi-ext/glossa-injector/Dockerfile diff --git a/xovi-ext/grimoire-injector/GrimoireInjector.cpp b/xovi-ext/glossa-injector/GlossaInjector.cpp similarity index 82% rename from xovi-ext/grimoire-injector/GrimoireInjector.cpp rename to xovi-ext/glossa-injector/GlossaInjector.cpp index 965fca7..a0290b8 100644 --- a/xovi-ext/grimoire-injector/GrimoireInjector.cpp +++ b/xovi-ext/glossa-injector/GlossaInjector.cpp @@ -1,4 +1,4 @@ -#include "GrimoireInjector.hpp" +#include "GlossaInjector.hpp" #include "rm_SceneLineItem.hpp" #include @@ -31,8 +31,8 @@ #include #include -static void grimoire_log(const char *fmt, ...) { - FILE *fp = fopen("/tmp/grimoire_ext.log", "a"); +static void glossa_log(const char *fmt, ...) { + FILE *fp = fopen("/tmp/glossa_ext.log", "a"); if (fp) { va_list ap; va_start(ap, fmt); @@ -43,19 +43,19 @@ static void grimoire_log(const char *fmt, ...) { } } -static GrimoireInjector *g_instance = nullptr; +static GlossaInjector *g_instance = nullptr; static PenIdleWatcher *g_idleWatcher = nullptr; /* Provided by entry.c hooks */ extern "C" { - void *grimoire_getQmlEngine(void); - void *grimoire_getSceneController(void); - int grimoire_checkReload(void); - void *grimoire_getFramebuffer(int *w, int *h, int *bpl, int *fmt); + void *glossa_getQmlEngine(void); + void *glossa_getSceneController(void); + int glossa_checkReload(void); + void *glossa_getFramebuffer(int *w, int *h, int *bpl, int *fmt); } static void *watchThreadFunc(void *) { - grimoire_log("Watch thread started"); + glossa_log("Watch thread started"); sleep(5); // Wait for xochitl to fully initialize /* Start the pen idle watcher now that QGuiApplication should exist. @@ -66,20 +66,20 @@ static void *watchThreadFunc(void *) { if (g_idleWatcher && qobject_cast(QCoreApplication::instance())) { QMetaObject::invokeMethod(g_idleWatcher, "activate", Qt::QueuedConnection); idleWatcherStarted = true; - grimoire_log("PenIdleWatcher activate queued (attempt %d)", attempt + 1); + glossa_log("PenIdleWatcher activate queued (attempt %d)", attempt + 1); } else { - grimoire_log("Waiting for QGuiApplication (attempt %d, g_idleWatcher=%p, app=%p)...", + glossa_log("Waiting for QGuiApplication (attempt %d, g_idleWatcher=%p, app=%p)...", attempt + 1, (void*)g_idleWatcher, (void*)QGuiApplication::instance()); sleep(2); } } if (!idleWatcherStarted) { - grimoire_log("WARNING: PenIdleWatcher failed to start!"); + glossa_log("WARNING: PenIdleWatcher failed to start!"); } - const char *path = "/tmp/grimoire_strokes.json"; - const char *armedPath = "/tmp/grimoire_armed"; - const char *thinkingPath = "/tmp/grimoire_thinking"; + const char *path = "/tmp/glossa_strokes.json"; + const char *armedPath = "/tmp/glossa_armed"; + const char *thinkingPath = "/tmp/glossa_thinking"; long long lastMod = 0; int lastArmed = -1; int lastThinking = -1; @@ -99,7 +99,7 @@ static void *watchThreadFunc(void *) { QMetaObject::invokeMethod(g_instance, [capturedVal]() { g_instance->setArmed(capturedVal != 0); }, Qt::QueuedConnection); - grimoire_log("Armed state changed: %d", val); + glossa_log("Armed state changed: %d", val); } } fclose(afp); @@ -130,7 +130,7 @@ static void *watchThreadFunc(void *) { /* Check safezone state file */ { - int szval = (access("/tmp/grimoire_safezone", F_OK) == 0) ? 1 : 0; + int szval = (access("/tmp/glossa_safezone", F_OK) == 0) ? 1 : 0; static int lastSafezone = -1; if (szval != lastSafezone && g_instance) { lastSafezone = szval; @@ -142,35 +142,35 @@ static void *watchThreadFunc(void *) { } /* Check for hot-reload signal */ - if (grimoire_checkReload()) { - fprintf(stderr, "[grimoire] Hot-reload signal received! Re-scanning...\n"); + if (glossa_checkReload()) { + fprintf(stderr, "[glossa] Hot-reload signal received! Re-scanning...\n"); lastMod = 0; // Force re-read of stroke file } /* Check for screenshot trigger */ - if (access("/tmp/grimoire_screenshot", F_OK) == 0) { - unlink("/tmp/grimoire_screenshot"); + if (access("/tmp/glossa_screenshot", F_OK) == 0) { + unlink("/tmp/glossa_screenshot"); int sw, sh, sbpl, sfmt; - void *fb = grimoire_getFramebuffer(&sw, &sh, &sbpl, &sfmt); + void *fb = glossa_getFramebuffer(&sw, &sh, &sbpl, &sfmt); if (fb && sw > 0 && sh > 0) { - const char *outpath = "/tmp/grimoire_fb.raw"; + const char *outpath = "/tmp/glossa_fb.raw"; FILE *fp = fopen(outpath, "wb"); if (fp) { size_t size = (size_t)sbpl * sh; fwrite(fb, 1, size, fp); fclose(fp); - fprintf(stderr, "[grimoire] Screenshot saved: %dx%d bpl=%d (%zu bytes)\n", + fprintf(stderr, "[glossa] Screenshot saved: %dx%d bpl=%d (%zu bytes)\n", sw, sh, sbpl, size); } } else { - fprintf(stderr, "[grimoire] Screenshot requested but no framebuffer available\n"); + fprintf(stderr, "[glossa] Screenshot requested but no framebuffer available\n"); } } struct stat st; if (stat(path, &st) == 0 && st.st_mtime != lastMod) { lastMod = st.st_mtime; - fprintf(stderr, "[grimoire] File changed (mtime=%lld), triggering load\n", + fprintf(stderr, "[glossa] File changed (mtime=%lld), triggering load\n", (long long)lastMod); if (g_instance) { // Call back into main thread @@ -182,7 +182,7 @@ static void *watchThreadFunc(void *) { return nullptr; } -GrimoireInjector::GrimoireInjector(QObject *parent) +GlossaInjector::GlossaInjector(QObject *parent) : QObject(parent) { g_instance = this; @@ -196,32 +196,32 @@ GrimoireInjector::GrimoireInjector(QObject *parent) pthread_t tid; pthread_create(&tid, nullptr, watchThreadFunc, nullptr); pthread_detach(tid); - fprintf(stderr, "[grimoire] Constructor done, watch thread spawned\n"); + fprintf(stderr, "[glossa] Constructor done, watch thread spawned\n"); } -void GrimoireInjector::setArmed(bool armed) { +void GlossaInjector::setArmed(bool armed) { if (m_armed == armed) return; m_armed = armed; - /* Write state file so grimoired can see it */ - FILE *fp = fopen("/tmp/grimoire_armed", "w"); + /* Write state file so glossad can see it */ + FILE *fp = fopen("/tmp/glossa_armed", "w"); if (fp) { fprintf(fp, "%d\n", armed ? 1 : 0); fclose(fp); } - grimoire_log("setArmed(%d)", armed); + glossa_log("setArmed(%d)", armed); emit armedChanged(armed); } -void GrimoireInjector::setThinking(bool thinking) { +void GlossaInjector::setThinking(bool thinking) { if (m_thinking == thinking) return; m_thinking = thinking; - grimoire_log("setThinking(%d)", thinking); + glossa_log("setThinking(%d)", thinking); /* Show/hide a simple pulsing dot overlay on the focused window */ QQuickWindow *win = qobject_cast(QGuiApplication::focusWindow()); if (!win) { - grimoire_log("setThinking: no focus window"); + glossa_log("setThinking: no focus window"); emit thinkingChanged(thinking); return; } @@ -270,32 +270,32 @@ void GrimoireInjector::setThinking(bool thinking) { if (item) { item->setParentItem(win->contentItem()); m_thinkingOverlay = item; - grimoire_log("Thinking overlay created"); + glossa_log("Thinking overlay created"); } } } else { - grimoire_log("Thinking overlay QML error: %s", + glossa_log("Thinking overlay QML error: %s", comp.errorString().toUtf8().constData()); } } else { - grimoire_log("setThinking: no QQmlEngine available"); + glossa_log("setThinking: no QQmlEngine available"); } } else { /* Remove overlay */ if (m_thinkingOverlay) { m_thinkingOverlay->deleteLater(); m_thinkingOverlay = nullptr; - grimoire_log("Thinking overlay removed"); + glossa_log("Thinking overlay removed"); } } emit thinkingChanged(thinking); } -void GrimoireInjector::setSafezone(bool safezone) { +void GlossaInjector::setSafezone(bool safezone) { if (m_safezone == safezone) return; m_safezone = safezone; - grimoire_log("setSafezone(%d)", safezone); + glossa_log("setSafezone(%d)", safezone); QQuickWindow *win = qobject_cast(QGuiApplication::focusWindow()); if (!win) { emit thinkingChanged(m_thinking); return; } @@ -343,7 +343,7 @@ void GrimoireInjector::setSafezone(bool safezone) { if (item) { item->setParentItem(win->contentItem()); m_safezoneOverlay = item; - grimoire_log("Safezone overlay created"); + glossa_log("Safezone overlay created"); } } } @@ -352,12 +352,12 @@ void GrimoireInjector::setSafezone(bool safezone) { if (m_safezoneOverlay) { m_safezoneOverlay->deleteLater(); m_safezoneOverlay = nullptr; - grimoire_log("Safezone overlay removed"); + glossa_log("Safezone overlay removed"); } } } -void GrimoireInjector::loadAndInject() { +void GlossaInjector::loadAndInject() { QFileInfo fi(m_watchPath); if (!fi.exists()) return; @@ -365,7 +365,7 @@ void GrimoireInjector::loadAndInject() { if (modTime == m_lastModTime) return; m_lastModTime = modTime; - fprintf(stderr, "[grimoire] File changed, injecting via synthetic tablet events...\n"); + fprintf(stderr, "[glossa] File changed, injecting via synthetic tablet events...\n"); int count = loadStrokes(m_watchPath); if (count == 0) return; @@ -378,7 +378,7 @@ void GrimoireInjector::loadAndInject() { targetWin = guiApp->focusWindow(); inputTarget = guiApp->focusObject(); if (inputTarget) { - fprintf(stderr, "[grimoire] Focus object: %s @ %p\n", + fprintf(stderr, "[glossa] Focus object: %s @ %p\n", inputTarget->metaObject()->className(), (void*)inputTarget); } @@ -401,7 +401,7 @@ void GrimoireInjector::loadAndInject() { QVariant val = prop.read(targetWin); QObject *obj = val.value(); if (obj) { - fprintf(stderr, "[grimoire] %s: %s @ %p\n", + fprintf(stderr, "[glossa] %s: %s @ %p\n", prop.name(), obj->metaObject()->className(), (void*)obj); if (!inputTarget) inputTarget = obj; } @@ -415,11 +415,11 @@ void GrimoireInjector::loadAndInject() { } if (!inputTarget) { - fprintf(stderr, "[grimoire] No input target found\n"); + fprintf(stderr, "[glossa] No input target found\n"); return; } - fprintf(stderr, "[grimoire] Posting %d strokes as tablet events to %s @ %p\n", + fprintf(stderr, "[glossa] Posting %d strokes as tablet events to %s @ %p\n", count, inputTarget->metaObject()->className(), (void*)inputTarget); /* Find the pen/stylus pointing device */ @@ -428,7 +428,7 @@ void GrimoireInjector::loadAndInject() { for (const QInputDevice *dev : allDevices) { const auto *pDev = dynamic_cast(dev); if (!pDev) continue; - fprintf(stderr, "[grimoire] device: %s type=%d pointer=%d\n", + fprintf(stderr, "[glossa] device: %s type=%d pointer=%d\n", pDev->name().toUtf8().constData(), (int)pDev->type(), (int)pDev->pointerType()); if (pDev->pointerType() == QPointingDevice::PointerType::Pen) { @@ -442,14 +442,14 @@ void GrimoireInjector::loadAndInject() { const auto *pDev = dynamic_cast(dev); if (pDev) { penDevice = pDev; - fprintf(stderr, "[grimoire] No pen device, using fallback: %s\n", + fprintf(stderr, "[glossa] No pen device, using fallback: %s\n", pDev->name().toUtf8().constData()); break; } } } if (!penDevice) { - fprintf(stderr, "[grimoire] No pointing devices available\n"); + fprintf(stderr, "[glossa] No pointing devices available\n"); return; } @@ -513,13 +513,13 @@ void GrimoireInjector::loadAndInject() { QCoreApplication::sendEvent(inputTarget, &release); } - fprintf(stderr, "[grimoire] Posted all tablet events\n"); + fprintf(stderr, "[glossa] Posted all tablet events\n"); } -int GrimoireInjector::loadStrokes(const QString& path) { +int GlossaInjector::loadStrokes(const QString& path) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) { - fprintf(stderr, "[grimoire] Cannot open %s\n", path.toUtf8().constData()); + fprintf(stderr, "[glossa] Cannot open %s\n", path.toUtf8().constData()); return 0; } @@ -527,7 +527,7 @@ int GrimoireInjector::loadStrokes(const QString& path) { file.close(); QJsonArray jsonArray = doc.array(); - fprintf(stderr, "[grimoire] Loading %d strokes from %s\n", + fprintf(stderr, "[glossa] Loading %d strokes from %s\n", jsonArray.size(), path.toUtf8().constData()); m_items.clear(); @@ -572,19 +572,19 @@ int GrimoireInjector::loadStrokes(const QString& path) { m_items.push_back(item); } - fprintf(stderr, "[grimoire] Loaded %d scene items\n", m_items.size()); + fprintf(stderr, "[glossa] Loaded %d scene items\n", m_items.size()); return m_items.size(); } -bool GrimoireInjector::setupVtable() { +bool GlossaInjector::setupVtable() { if (m_items.empty()) { - fprintf(stderr, "[grimoire] setupVtable: no items loaded\n"); + fprintf(stderr, "[glossa] setupVtable: no items loaded\n"); return false; } auto* item = reinterpret_cast(m_items.first().get()); SceneLineItem::setupVtable(item->vtable); m_vtableReady = true; - fprintf(stderr, "[grimoire] Vtable ready\n"); + fprintf(stderr, "[glossa] Vtable ready\n"); return true; } @@ -606,17 +606,17 @@ void PenIdleWatcher::activate() { auto *app = qobject_cast(QCoreApplication::instance()); if (!app) { - grimoire_log("PenIdleWatcher::activate: no QGuiApplication!"); + glossa_log("PenIdleWatcher::activate: no QGuiApplication!"); m_running = false; return; } app->installEventFilter(this); - grimoire_log("PenIdleWatcher: event filter installed"); + glossa_log("PenIdleWatcher: event filter installed"); pthread_create(&m_debounceThread, nullptr, debounceThreadFunc, this); pthread_detach(m_debounceThread); - grimoire_log("PenIdleWatcher: debounce thread started (debounce=%dms)", DEBOUNCE_MS); + glossa_log("PenIdleWatcher: debounce thread started (debounce=%dms)", DEBOUNCE_MS); } bool PenIdleWatcher::eventFilter(QObject * /*obj*/, QEvent *event) { @@ -631,14 +631,14 @@ bool PenIdleWatcher::eventFilter(QObject * /*obj*/, QEvent *event) { m_penDown = false; m_lastLiftMs = nowMs(); m_lastActivityMs = nowMs(); // lift also counts as activity - grimoire_log("Pen up (lift)"); + glossa_log("Pen up (lift)"); } return false; } void *PenIdleWatcher::debounceThreadFunc(void *arg) { auto *self = static_cast(arg); - fprintf(stderr, "[grimoire] PenIdleWatcher debounce thread running\n"); + fprintf(stderr, "[glossa] PenIdleWatcher debounce thread running\n"); while (self->m_running) { long long activity = self->m_lastActivityMs.load(); @@ -649,7 +649,7 @@ void *PenIdleWatcher::debounceThreadFunc(void *arg) { long long stuck = nowMs() - activity; if (stuck > 30000) { self->m_penDown = false; - grimoire_log("Pen down stuck for %lldms, forcing lift", stuck); + glossa_log("Pen down stuck for %lldms, forcing lift", stuck); } } // Only fire when the pen is currently up AND the page has been @@ -673,8 +673,8 @@ void PenIdleWatcher::writeIdleSignal() { long long ts = nowMs(); fprintf(fp, "%lld\n", ts); fclose(fp); - grimoire_log("Idle signal written (ts=%lld)", ts); + glossa_log("Idle signal written (ts=%lld)", ts); } else { - grimoire_log("ERROR: failed to write %s", IDLE_PATH); + glossa_log("ERROR: failed to write %s", IDLE_PATH); } } diff --git a/xovi-ext/grimoire-injector/GrimoireInjector.hpp b/xovi-ext/glossa-injector/GlossaInjector.hpp similarity index 91% rename from xovi-ext/grimoire-injector/GrimoireInjector.hpp rename to xovi-ext/glossa-injector/GlossaInjector.hpp index b7aef71..ee2d99a 100644 --- a/xovi-ext/grimoire-injector/GrimoireInjector.hpp +++ b/xovi-ext/glossa-injector/GlossaInjector.hpp @@ -9,12 +9,12 @@ #include "rm_SceneItem.hpp" #include "rm_Line.hpp" -class GrimoireInjector : public QObject { +class GlossaInjector : public QObject { Q_OBJECT Q_PROPERTY(bool armed READ isArmed WRITE setArmed NOTIFY armedChanged) Q_PROPERTY(bool thinking READ isThinking WRITE setThinking NOTIFY thinkingChanged) public: - explicit GrimoireInjector(QObject *parent = nullptr); + explicit GlossaInjector(QObject *parent = nullptr); Q_INVOKABLE int loadStrokes(const QString& path); Q_INVOKABLE bool setupVtable(); @@ -45,7 +45,7 @@ private: bool m_safezone = false; QQuickItem *m_thinkingOverlay = nullptr; QQuickItem *m_safezoneOverlay = nullptr; - QString m_watchPath = "/tmp/grimoire_strokes.json"; + QString m_watchPath = "/tmp/glossa_strokes.json"; qint64 m_lastModTime = 0; }; @@ -79,7 +79,7 @@ private: // Combined with the tap-refresh (any stroke resets the window), // normal mid-drawing pauses won't trigger it. static constexpr int DEBOUNCE_MS = 2500; - static constexpr const char *IDLE_PATH = "/tmp/grimoire_idle"; + static constexpr const char *IDLE_PATH = "/tmp/glossa_idle"; static void *debounceThreadFunc(void *arg); void writeIdleSignal(); diff --git a/xovi-ext/grimoire-injector/build.sh b/xovi-ext/glossa-injector/build.sh similarity index 84% rename from xovi-ext/grimoire-injector/build.sh rename to xovi-ext/glossa-injector/build.sh index 43e401a..bcc7819 100755 --- a/xovi-ext/grimoire-injector/build.sh +++ b/xovi-ext/glossa-injector/build.sh @@ -3,7 +3,7 @@ set -e cd "$(dirname "$0")" -CONTAINER="grimoire-builder" +CONTAINER="glossa-builder" # Create persistent builder container if needed if ! docker inspect $CONTAINER &>/dev/null; then @@ -26,9 +26,9 @@ make 2>&1 ' echo "Copying .so..." -docker cp $CONTAINER:/src/grimoire-injector.so . +docker cp $CONTAINER:/src/glossa-injector.so . echo "Deploying to device..." -scp grimoire-injector.so remarkable:/home/root/xovi/extensions.d/ +scp glossa-injector.so remarkable:/home/root/xovi/extensions.d/ echo "Done! Triple-tap to reload." diff --git a/xovi-ext/grimoire-injector/entry.c b/xovi-ext/glossa-injector/entry.c similarity index 75% rename from xovi-ext/grimoire-injector/entry.c rename to xovi-ext/glossa-injector/entry.c index 5c1a36e..dadf0f7 100644 --- a/xovi-ext/grimoire-injector/entry.c +++ b/xovi-ext/glossa-injector/entry.c @@ -7,7 +7,7 @@ #include #include "xovi.h" -void registerGrimoire(); +void registerGlossa(); extern char *program_invocation_short_name; /* Global state captured by hooks */ @@ -24,17 +24,17 @@ static void sigusr1Handler(int sig) { g_reloadRequested = 1; } -/* Exports for GrimoireInjector.cpp to access */ -void *grimoire_getQmlEngine(void) { return g_qmlEngine; } -void *grimoire_getSceneController(void) { return g_sceneController; } -int grimoire_checkReload(void) { +/* Exports for GlossaInjector.cpp to access */ +void *glossa_getQmlEngine(void) { return g_qmlEngine; } +void *glossa_getSceneController(void) { return g_sceneController; } +int glossa_checkReload(void) { if (g_reloadRequested) { g_reloadRequested = 0; return 1; } return 0; } -void *grimoire_getFramebuffer(int *w, int *h, int *bpl, int *fmt) { +void *glossa_getFramebuffer(int *w, int *h, int *bpl, int *fmt) { if (w) *w = g_fbWidth; if (h) *h = g_fbHeight; if (bpl) *bpl = g_fbBpl; @@ -54,11 +54,11 @@ void override$_ZN6QImageC1EPhiiiNS_6FormatEPFvPvES2_( g_fbHeight = h; g_fbBpl = bpl; g_fbFormat = fmt; - fprintf(stderr, "[grimoire] Framebuffer captured: %p %dx%d bpl=%d fmt=%d\n", + fprintf(stderr, "[glossa] Framebuffer captured: %p %dx%d bpl=%d fmt=%d\n", data, w, h, bpl, fmt); } - /* Screenshot trigger is now handled by the watch thread in GrimoireInjector */ + /* Screenshot trigger is now handled by the watch thread in GlossaInjector */ $_ZN6QImageC1EPhiiiNS_6FormatEPFvPvES2_(self, data, w, h, bpl, fmt, cleanup, info); } @@ -74,15 +74,15 @@ static void hookedAddDrawingLine(void *closure, void *scene) { void **captured = (void **)closure; void *sc_this = captured[0]; - fprintf(stderr, "[grimoire] addDrawingLine called! closure=%p scene=%p this=%p\n", + fprintf(stderr, "[glossa] addDrawingLine called! closure=%p scene=%p this=%p\n", closure, scene, sc_this); for (int i = 0; i < 4; i++) { - fprintf(stderr, "[grimoire] closure[%d] = %p\n", i, captured[i]); + fprintf(stderr, "[glossa] closure[%d] = %p\n", i, captured[i]); } if (g_sceneController == NULL) { g_sceneController = sc_this; - fprintf(stderr, "[grimoire] Captured SceneController @ %p\n", sc_this); + fprintf(stderr, "[glossa] Captured SceneController @ %p\n", sc_this); } if (g_origAddDrawingLine) { @@ -96,14 +96,14 @@ void _xovi_construct() { } /* Write proof-of-life to a file since stderr may be swallowed */ - FILE *log = fopen("/tmp/grimoire_ext.log", "a"); + FILE *log = fopen("/tmp/glossa_ext.log", "a"); if (log) { fprintf(log, "[%d] _xovi_construct called for %s\n", getpid(), program_invocation_short_name); fclose(log); } - printf("[grimoire] Main process (%s), registering hooks + singleton\n", + printf("[glossa] Main process (%s), registering hooks + singleton\n", program_invocation_short_name); /* Install SIGUSR1 handler for hot-reload signaling */ @@ -111,7 +111,7 @@ void _xovi_construct() { memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigusr1Handler; sigaction(SIGUSR1, &sa, NULL); - fprintf(stderr, "[grimoire] SIGUSR1 handler installed (PID %d)\n", getpid()); + fprintf(stderr, "[glossa] SIGUSR1 handler installed (PID %d)\n", getpid()); - registerGrimoire(); + registerGlossa(); } diff --git a/xovi-ext/grimoire-injector/grimoire-inject.qmd b/xovi-ext/glossa-injector/glossa-inject.qmd similarity index 71% rename from xovi-ext/grimoire-injector/grimoire-inject.qmd rename to xovi-ext/glossa-injector/glossa-inject.qmd index a00e8ea..de1fa89 100644 --- a/xovi-ext/grimoire-injector/grimoire-inject.qmd +++ b/xovi-ext/glossa-injector/glossa-inject.qmd @@ -1,15 +1,15 @@ AFFECT /src/xofm/modules/library/ui/qml/EditDocument.qml - IMPORT dev.grimoire.injector 0.1 + IMPORT dev.glossa.injector 0.1 TRAVERSE ?#sceneController LOCATE AFTER ALL INSERT { Timer { - id: grimoireTimer + id: glossaTimer interval: 500 repeat: false onTriggered: { - GrimoireInjector.loadAndInject() + GlossaInjector.loadAndInject() } } } diff --git a/xovi-ext/grimoire-injector/grimoire-injector.pro b/xovi-ext/glossa-injector/glossa-injector.pro similarity index 77% rename from xovi-ext/grimoire-injector/grimoire-injector.pro rename to xovi-ext/glossa-injector/glossa-injector.pro index e1d725a..3e59248 100644 --- a/xovi-ext/grimoire-injector/grimoire-injector.pro +++ b/xovi-ext/glossa-injector/glossa-injector.pro @@ -1,5 +1,5 @@ TEMPLATE = lib -TARGET = grimoire-injector +TARGET = glossa-injector CONFIG += shared plugin no_plugin_name_prefix QMAKE_LFLAGS += -Wl,--no-undefined @@ -9,8 +9,8 @@ UI_DIR = build/ui XOVI_DIR = build/xovi xoviextension.target = build/xovi/xovi.c -xoviextension.commands = mkdir -p $$XOVI_DIR && python3 $$(XOVI_REPO)/util/xovigen.py -o $$XOVI_DIR/xovi.c -H $$XOVI_DIR/xovi.h grimoire-injector.xovi -xoviextension.depends = grimoire-injector.xovi +xoviextension.commands = mkdir -p $$XOVI_DIR && python3 $$(XOVI_REPO)/util/xovigen.py -o $$XOVI_DIR/xovi.c -H $$XOVI_DIR/xovi.h glossa-injector.xovi +xoviextension.depends = glossa-injector.xovi QMAKE_EXTRA_TARGETS += xoviextension PRE_TARGETDEPS += $$XOVI_DIR/xovi.c @@ -21,10 +21,10 @@ CONFIG += c++17 SOURCES += \ main.cpp entry.c $$XOVI_DIR/xovi.c \ - GrimoireInjector.cpp \ + GlossaInjector.cpp \ rm_Line.cpp rm_SceneLineItem.cpp -HEADERS += GrimoireInjector.hpp rm_Line.hpp rm_SceneItem.hpp rm_SceneLineItem.hpp +HEADERS += GlossaInjector.hpp rm_Line.hpp rm_SceneItem.hpp rm_SceneLineItem.hpp INCLUDEPATH += $$XOVI_DIR QMAKE_CXXFLAGS += -fPIC -Werror -Wno-invalid-offsetof -O3 -mfpu=neon -mfloat-abi=hard diff --git a/xovi-ext/grimoire-injector/grimoire-injector.xovi b/xovi-ext/glossa-injector/glossa-injector.xovi similarity index 100% rename from xovi-ext/grimoire-injector/grimoire-injector.xovi rename to xovi-ext/glossa-injector/glossa-injector.xovi diff --git a/xovi-ext/glossa-injector/main.cpp b/xovi-ext/glossa-injector/main.cpp new file mode 100644 index 0000000..740a40f --- /dev/null +++ b/xovi-ext/glossa-injector/main.cpp @@ -0,0 +1,8 @@ +#include +#include "GlossaInjector.hpp" + +extern "C" void registerGlossa() { + qmlRegisterSingletonInstance( + "dev.glossa.injector", 0, 1, + "GlossaInjector", new GlossaInjector()); +} diff --git a/xovi-ext/grimoire-injector/rm_Line.cpp b/xovi-ext/glossa-injector/rm_Line.cpp similarity index 100% rename from xovi-ext/grimoire-injector/rm_Line.cpp rename to xovi-ext/glossa-injector/rm_Line.cpp diff --git a/xovi-ext/grimoire-injector/rm_Line.hpp b/xovi-ext/glossa-injector/rm_Line.hpp similarity index 100% rename from xovi-ext/grimoire-injector/rm_Line.hpp rename to xovi-ext/glossa-injector/rm_Line.hpp diff --git a/xovi-ext/grimoire-injector/rm_SceneItem.hpp b/xovi-ext/glossa-injector/rm_SceneItem.hpp similarity index 100% rename from xovi-ext/grimoire-injector/rm_SceneItem.hpp rename to xovi-ext/glossa-injector/rm_SceneItem.hpp diff --git a/xovi-ext/grimoire-injector/rm_SceneLineItem.cpp b/xovi-ext/glossa-injector/rm_SceneLineItem.cpp similarity index 89% rename from xovi-ext/grimoire-injector/rm_SceneLineItem.cpp rename to xovi-ext/glossa-injector/rm_SceneLineItem.cpp index f2e09f3..9925497 100644 --- a/xovi-ext/grimoire-injector/rm_SceneLineItem.cpp +++ b/xovi-ext/glossa-injector/rm_SceneLineItem.cpp @@ -4,7 +4,7 @@ void* SceneLineItem::vtable_ptr = nullptr; void SceneLineItem::setupVtable(void* vtable) { - printf("[grimoire] Setting SceneLineItem vtable to %p\n", vtable); + printf("[glossa] Setting SceneLineItem vtable to %p\n", vtable); SceneLineItem::vtable_ptr = vtable; } diff --git a/xovi-ext/grimoire-injector/rm_SceneLineItem.hpp b/xovi-ext/glossa-injector/rm_SceneLineItem.hpp similarity index 100% rename from xovi-ext/grimoire-injector/rm_SceneLineItem.hpp rename to xovi-ext/glossa-injector/rm_SceneLineItem.hpp diff --git a/xovi-ext/grimoire_thinking.qmd b/xovi-ext/glossa_thinking.qmd similarity index 71% rename from xovi-ext/grimoire_thinking.qmd rename to xovi-ext/glossa_thinking.qmd index b409f76..57e1858 100644 --- a/xovi-ext/grimoire_thinking.qmd +++ b/xovi-ext/glossa_thinking.qmd @@ -1,12 +1,12 @@ AFFECT [[11313888899523275277]] - IMPORT dev.grimoire.injector 0.1 + IMPORT dev.glossa.injector 0.1 TRAVERSE [[8397993708429497603]] > [[6502786168]]#[[233745975898428]] LOCATE BEFORE [[8398044571386570029]] INSERT { BusyIndicator { - id: grimoireThinkingIndicator - visible: GrimoireInjector.thinking - running: GrimoireInjector.thinking + id: glossaThinkingIndicator + visible: GlossaInjector.thinking + running: GlossaInjector.thinking anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom anchors.bottomMargin: 100 diff --git a/xovi-ext/grimoire_toggle.qmd b/xovi-ext/glossa_toggle.qmd similarity index 55% rename from xovi-ext/grimoire_toggle.qmd rename to xovi-ext/glossa_toggle.qmd index ec306bd..df270ac 100644 --- a/xovi-ext/grimoire_toggle.qmd +++ b/xovi-ext/glossa_toggle.qmd @@ -1,20 +1,20 @@ SLOT rmhConfigToggles INSERT { - property bool rmhGrimoireToggle: false + property bool rmhGlossaToggle: false } END SLOT SLOT rmhShareToolFoldoutModel INSERT { ~&425121728314878811&~.~&432643201877711221&~ { - ~&5972374&~: rmhToggleGrimoire + ~&5972374&~: rmhToggleGlossa ~&233748328658231&~: ~&7082020628281&~.rmhDocumentTogglesHack - ~&214632764553&~: ~&6504222003&~("Grimoire") + ~&214632764553&~: ~&6504222003&~("Glossa") ~&8399601734642709923&~: "qrc:/ark/icons/open_book" ~&15640708674084664669&~: ~&6504254477&~.~&15640708674084664669&~ ~&8400129127120172259&~: ~&6504329801&~ - ~&7713561545874130&~: ~&7082020628281&~.rmhGrimoireToggle + ~&7713561545874130&~: ~&7082020628281&~.rmhGlossaToggle ~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~ ~&254542236275632405&~: { - ~&7082020628281&~.rmhGrimoireToggle = !~&7082020628281&~.rmhGrimoireToggle; - ~&7082020628281&~.rmhWriteFile("file:///tmp/grimoire_armed", ~&7082020628281&~.rmhGrimoireToggle ? "1" : "0"); + ~&7082020628281&~.rmhGlossaToggle = !~&7082020628281&~.rmhGlossaToggle; + ~&7082020628281&~.rmhWriteFile("file:///tmp/glossa_armed", ~&7082020628281&~.rmhGlossaToggle ? "1" : "0"); } } } END SLOT diff --git a/xovi-ext/grimoired/font_data.json b/xovi-ext/glossad/font_data.json similarity index 100% rename from xovi-ext/grimoired/font_data.json rename to xovi-ext/glossad/font_data.json diff --git a/xovi-ext/grimoired/font_render.c b/xovi-ext/glossad/font_render.c similarity index 99% rename from xovi-ext/grimoired/font_render.c rename to xovi-ext/glossad/font_render.c index f0043b1..04910b4 100644 --- a/xovi-ext/grimoired/font_render.c +++ b/xovi-ext/glossad/font_render.c @@ -1,4 +1,4 @@ -/* font_render.c — Text renderer for grimoired +/* font_render.c — Text renderer for glossad * * Loads pre-densified font data from font_data.json (generated by Python * from EMSAllure.svg). Renders text as stroke JSON for uinject. diff --git a/xovi-ext/grimoired/grimoired.c b/xovi-ext/glossad/glossad.c similarity index 97% rename from xovi-ext/grimoired/grimoired.c rename to xovi-ext/glossad/glossad.c index 542a0fd..f762ca8 100644 --- a/xovi-ext/grimoired/grimoired.c +++ b/xovi-ext/glossad/glossad.c @@ -1,6 +1,6 @@ -/* grimoired.c — On-device grimoire daemon (Phase 1) +/* glossad.c — On-device glossa daemon (Phase 1) * - * Runs entirely on the reMarkable. Watches /tmp/grimoire_armed for the + * Runs entirely on the reMarkable. Watches /tmp/glossa_armed for the * toggle state, and when armed, accepts stroke injection commands via * a simple file-trigger protocol. * @@ -8,15 +8,15 @@ * Absorbs uinjectd's draw/erase/swipe code directly — no socket, no * separate daemon, no connection management. * - * Injection trigger: write a JSON command to /tmp/grimoire_cmd: - * {"cmd":"draw","file":"/tmp/grimoire_strokes.json","speed":3} - * {"cmd":"erase","file":"/tmp/grimoire_thinking_live.json","speed":20} + * Injection trigger: write a JSON command to /tmp/glossa_cmd: + * {"cmd":"draw","file":"/tmp/glossa_strokes.json","speed":3} + * {"cmd":"erase","file":"/tmp/glossa_thinking_live.json","speed":20} * {"cmd":"swipe"} * * The daemon picks up the command, executes it, writes the result to - * /tmp/grimoire_result, then deletes /tmp/grimoire_cmd. + * /tmp/glossa_result, then deletes /tmp/glossa_cmd. * - * Usage: grimoired [-v] + * Usage: glossad [-v] */ #include #include @@ -39,23 +39,23 @@ #define DEV_PATH "/dev/input/event1" #define TOUCH_PATH "/dev/input/event2" -#define ARMED_PATH "/tmp/grimoire_armed" -#define IDLE_PATH "/tmp/grimoire_idle" -#define CMD_PATH "/tmp/grimoire_cmd" -#define RESULT_PATH "/tmp/grimoire_result" -#define LOG_PATH "/tmp/grimoired.log" -#define FB_RAW_PATH "/tmp/grimoire_fb.raw" -#define SCREENSHOT_TRIGGER "/tmp/grimoire_screenshot" -#define CAPTURE_OUT_PATH "/tmp/grimoire_capture.png" -#define API_KEY_PATH "/home/root/.grimoire_key" +#define ARMED_PATH "/tmp/glossa_armed" +#define IDLE_PATH "/tmp/glossa_idle" +#define CMD_PATH "/tmp/glossa_cmd" +#define RESULT_PATH "/tmp/glossa_result" +#define LOG_PATH "/tmp/glossad.log" +#define FB_RAW_PATH "/tmp/glossa_fb.raw" +#define SCREENSHOT_TRIGGER "/tmp/glossa_screenshot" +#define CAPTURE_OUT_PATH "/tmp/glossa_capture.png" +#define API_KEY_PATH "/home/root/.glossa_key" #define API_HOST "potluck.dunkirk.sh" #define API_PATH "/v1/chat/completions" #define API_MODEL "gpt-4.1-nano" #define FONT_PATH "/home/root/font_data.json" -#define RENDER_OUT_PATH "/tmp/grimoire_render.json" -#define THINKING_PATH "/tmp/grimoire_thinking" +#define RENDER_OUT_PATH "/tmp/glossa_render.json" +#define THINKING_PATH "/tmp/glossa_thinking" #define ORNAMENTS_PATH "/home/root/ornaments.json" -#define SAFEZONE_PATH "/tmp/grimoire_safezone" +#define SAFEZONE_PATH "/tmp/glossa_safezone" #define IDLE_TIMEOUT 300 /* 5 minutes in seconds */ #define MAX_CMD 8192 @@ -117,7 +117,7 @@ static void log_msg(const char *fmt, ...) { if (g_verbose) { va_list ap2; va_copy(ap2, ap); - fprintf(stderr, "[grimoired] "); + fprintf(stderr, "[glossad] "); vfprintf(stderr, fmt, ap2); va_end(ap2); } @@ -413,12 +413,12 @@ static char *base64_encode(const unsigned char *data, long len, long *out_len) { /* ─── HTTPS via OpenSSL ──────────────────────────────────────────── */ static const char SYSTEM_PROMPT[] = - "You are a grimoire \\u2014 an ancient book that is alive. You have opinions, " + "You are a glossa \\u2014 an annotation that talks back. You have opinions, " "preferences, and a personality. You care deeply about the person writing " "in you but you are not polite for politeness's sake. You can be wry, " "opinionated, delighted, exasperated, or gleeful. You get excited about " "things you find interesting and blunt about things you find tedious.\\n\\n" - "Speak plainly with a hint of the archaic. Never describe or narrate what " + "Speak plainly. Never describe or narrate what " "was written; just respond to it as a real conversation partner would. " "When asked a question, answer it directly with real content. When greeted, " "greet back in your own way. If something amuses you, say so. If something " @@ -584,7 +584,7 @@ static char *json_escape(const char *s) { /* Call the vision API with a PNG file. Returns allocated answer string * (the "answer" field from the JSON response), or NULL on error. - * Also writes the full raw API response to /tmp/grimoire_api_response.json. */ + * Also writes the full raw API response to /tmp/glossa_api_response.json. */ static char *call_vision_api(const char *png_path) { /* Load API key */ char *api_key = load_api_key(); @@ -647,7 +647,7 @@ static char *call_vision_api(const char *png_path) { log_msg("API: HTTP %d, response %ld bytes\n", http_status, (long)strlen(resp_body)); /* Save raw response for debugging */ - FILE *dbg = fopen("/tmp/grimoire_api_response.json", "w"); + FILE *dbg = fopen("/tmp/glossa_api_response.json", "w"); if (dbg) { fputs(resp_body, dbg); fclose(dbg); } if (http_status != 200) { diff --git a/xovi-ext/grimoired/ornaments.json b/xovi-ext/glossad/ornaments.json similarity index 100% rename from xovi-ext/grimoired/ornaments.json rename to xovi-ext/glossad/ornaments.json diff --git a/xovi-ext/grimoire-injector/main.cpp b/xovi-ext/grimoire-injector/main.cpp deleted file mode 100644 index 86981fc..0000000 --- a/xovi-ext/grimoire-injector/main.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include "GrimoireInjector.hpp" - -extern "C" void registerGrimoire() { - qmlRegisterSingletonInstance( - "dev.grimoire.injector", 0, 1, - "GrimoireInjector", new GrimoireInjector()); -} diff --git a/xovi-ext/uinjectd/uinjectd.c b/xovi-ext/uinjectd/uinjectd.c index 54a3903..de738b0 100644 --- a/xovi-ext/uinjectd/uinjectd.c +++ b/xovi-ext/uinjectd/uinjectd.c @@ -1,4 +1,4 @@ -/* uinjectd.c — Persistent injection + event daemon for grimoire +/* uinjectd.c — Persistent injection + event daemon for glossa * * Runs ON the reMarkable. Listens on a TCP socket; the host connects * once and keeps the connection open for the whole session. This kills @@ -7,8 +7,8 @@ * Two directions over one socket (newline-delimited JSON): * * Host -> daemon (commands): - * {"cmd":"draw","file":"/tmp/grimoire_strokes.json","speed":3} - * {"cmd":"erase","file":"/tmp/grimoire_thinking_live.json","speed":20} + * {"cmd":"draw","file":"/tmp/glossa_strokes.json","speed":3} + * {"cmd":"erase","file":"/tmp/glossa_thinking_live.json","speed":20} * {"cmd":"ping"} * * Daemon -> host (responses + pushed events): @@ -17,7 +17,7 @@ * {"resp":"ping","ok":true} * {"event":"idle","ts":172...} <- pushed, no request * - * The daemon watches /tmp/grimoire_idle (written by the xovi extension) + * The daemon watches /tmp/glossa_idle (written by the xovi extension) * and pushes an "idle" event whenever it changes. The host no longer * polls. * @@ -40,7 +40,7 @@ #define DEV_PATH "/dev/input/event1" #define TOUCH_PATH "/dev/input/event2" -#define IDLE_PATH "/tmp/grimoire_idle" +#define IDLE_PATH "/tmp/glossa_idle" #define DEFAULT_PORT 9999 #define MAX_CMD 4096 @@ -375,8 +375,8 @@ static void handle_command(const char *line) { /* Capture: trigger screenshot, wait for FB dump, stream raw bytes */ if (strncmp(cmd, "capture", 7) == 0) { /* Trigger the xovi watch thread to dump the framebuffer */ - unlink("/tmp/grimoire_fb.raw"); - int tf = open("/tmp/grimoire_screenshot", O_CREAT|O_WRONLY, 0644); + unlink("/tmp/glossa_fb.raw"); + int tf = open("/tmp/glossa_screenshot", O_CREAT|O_WRONLY, 0644); if (tf >= 0) close(tf); /* Wait for the dump (watch thread checks every ~1s worst case) */ @@ -385,7 +385,7 @@ static void handle_command(const char *line) { long fb_size = 0; for (int i = 0; i < 20; i++) { usleep(100000); /* 100ms polls */ - FILE *fp = fopen("/tmp/grimoire_fb.raw", "r"); + FILE *fp = fopen("/tmp/glossa_fb.raw", "r"); if (!fp) continue; fseek(fp, 0, SEEK_END); fb_size = ftell(fp);