Initial commit: Chatter — assistive-writing app for reMarkable Paper Pro Move
Direct-framebuffer ink pipeline (stock-quality strokes), finger-wipe erase, growable scrolling canvas with color-ghost cleanup, bidirectional toggle with a persistent 4-finger return launcher, instant button feedback. Includes prebuilt aarch64 binaries (dist/), build/deploy/install scripts, a user guide, and a complete technical reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
scripts/build.sh
Executable file
28
scripts/build.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Cross-build Chatter with the reMarkable Paper Pro Move (Chiappa) SDK.
|
||||
#
|
||||
# Usage: scripts/build.sh [extra cmake args]
|
||||
# Override SDK location with CHATTER_SDK=...
|
||||
set -euo pipefail
|
||||
|
||||
SDK="${CHATTER_SDK:-/home/ack/external/remarkable-sdk/chiappa-3.27.0.97}"
|
||||
ENV="$SDK/environment-setup-cortexa55-remarkable-linux"
|
||||
[ -f "$ENV" ] || { echo "SDK env-setup not found: $ENV"; exit 1; }
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# Yocto SDKs refuse to operate with LD_LIBRARY_PATH set (Jatke sets it globally).
|
||||
unset LD_LIBRARY_PATH
|
||||
# shellcheck disable=SC1090
|
||||
. "$ENV"
|
||||
|
||||
cmake -S . -B build "$@"
|
||||
cmake --build build -j"$(nproc)"
|
||||
echo "built: build/chatter"
|
||||
|
||||
# The return-to-Chatter launcher is a tiny standalone C daemon (not part of the
|
||||
# CMake target). Build it here too so install-launcher.sh has its binary.
|
||||
# $CC carries flags (mcpu, sysroot, …) so it must stay UNquoted.
|
||||
# shellcheck disable=SC2086
|
||||
$CC -O2 -o tools/chatter-launcher tools/chatter_launcher.c
|
||||
echo "built: tools/chatter-launcher"
|
||||
13
scripts/chatter-launcher.service
Normal file
13
scripts/chatter-launcher.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Chatter launcher (multi-finger gesture watcher)
|
||||
After=home.mount data.mount multi-user.target
|
||||
# Binary + scripts live on the persistent /home volume.
|
||||
RequiresMountsFor=/home/root/chatter
|
||||
|
||||
[Service]
|
||||
ExecStart=/home/root/chatter/chatter-launcher
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
51
scripts/deploy-and-run.sh
Executable file
51
scripts/deploy-and-run.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy the chatter binary to the tablet and run it on the e-paper display.
|
||||
#
|
||||
# Usage: scripts/deploy-and-run.sh [path-to-binary]
|
||||
# default binary: build/chatter
|
||||
#
|
||||
# Requires: `ssh chatter` working (see doc/tablet_access.md).
|
||||
#
|
||||
# IMPORTANT lessons baked in here:
|
||||
# * The e-paper framebuffer is a singleton guarded by an flock
|
||||
# (/tmp/epframebuffer.lock). Only ONE process may hold it. A stranded
|
||||
# instance blanks the panel for everyone, so we always stop the previous
|
||||
# chatter unit first.
|
||||
# * Launch as a transient systemd service (systemd-run), NOT an ssh background
|
||||
# job: that detaches cleanly (no held SSH channel) and is stoppable via
|
||||
# `systemctl stop chatter`.
|
||||
# * xochitl owns the display while running, so stop it first (pre-authorized
|
||||
# during development). Run scripts/restore-xochitl.sh to bring it back.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
HOST="chatter"
|
||||
DEST="/home/root/chatter" # under /home, NOT the nearly-full rootfs
|
||||
|
||||
# Use an explicit binary if given; else a fresh local build; else the prebuilt.
|
||||
BIN="${1:-}"
|
||||
if [ -z "$BIN" ]; then
|
||||
if [ -f build/chatter ]; then BIN=build/chatter; else BIN=dist/chatter; fi
|
||||
fi
|
||||
[ -f "$BIN" ] || { echo "binary not found: $BIN (build it, or use the prebuilt dist/chatter)"; exit 1; }
|
||||
|
||||
echo ">> stopping any previous chatter + xochitl (release the panel lock)"
|
||||
ssh "$HOST" 'systemctl stop chatter 2>/dev/null; systemctl reset-failed chatter 2>/dev/null; systemctl stop xochitl 2>/dev/null; sleep 1'
|
||||
|
||||
echo ">> deploying $(basename "$BIN") to $HOST:$DEST"
|
||||
ssh "$HOST" "mkdir -p $DEST"
|
||||
scp "$BIN" "$HOST:$DEST/"
|
||||
|
||||
echo ">> launching chatter as a transient systemd service"
|
||||
# LD_LIBRARY_PATH lets the loader resolve libqsgepaper.so (linked for the private
|
||||
# EPScreenModeItem type), which lives in the scenegraph plugin dir.
|
||||
ssh "$HOST" "systemd-run --unit=chatter --collect \
|
||||
--setenv=QT_QUICK_BACKEND=epaper \
|
||||
--setenv=LD_LIBRARY_PATH=/usr/lib/plugins/scenegraph \
|
||||
--working-directory=$DEST \
|
||||
$DEST/$(basename "$BIN") -platform epaper"
|
||||
|
||||
sleep 4
|
||||
ssh "$HOST" 'echo "chatter: $(systemctl is-active chatter)"'
|
||||
echo ">> logs: ssh chatter 'journalctl -u chatter -f'"
|
||||
echo ">> stop: ssh chatter 'systemctl stop chatter' (then scripts/restore-xochitl.sh)"
|
||||
34
scripts/install-launcher.sh
Normal file
34
scripts/install-launcher.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
# Persistently install the chatter-launcher systemd service ON THE DEVICE.
|
||||
#
|
||||
# Why this is needed: on the reMarkable Paper Pro Move, /etc and /run are
|
||||
# VOLATILE overlays (upperdir on tmpfs) — units placed there are lost on reboot.
|
||||
# The root partition is read-only but persistent, so we remount it rw and place
|
||||
# the unit (and its enable symlink) under /usr/lib/systemd/system, which survives
|
||||
# reboots. (An OS update replaces the rootfs and would require re-running this.)
|
||||
#
|
||||
# Uses the prebuilt dist/chatter-launcher if present, else a locally built one.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
HOST="${1:-chatter}"
|
||||
|
||||
LAUNCHER=dist/chatter-launcher
|
||||
[ -f "$LAUNCHER" ] || LAUNCHER=tools/chatter-launcher
|
||||
[ -f "$LAUNCHER" ] || { echo "launcher binary not found (dist/ or tools/) — run scripts/build.sh"; exit 1; }
|
||||
|
||||
scp -q "$LAUNCHER" "$HOST:/home/root/chatter/chatter-launcher"
|
||||
scp -q scripts/to-chatter.sh scripts/chatter-launcher.service "$HOST:/home/root/chatter/"
|
||||
|
||||
ssh "$HOST" '
|
||||
set -e
|
||||
chmod +x /home/root/chatter/chatter-launcher /home/root/chatter/to-chatter.sh
|
||||
mount -o remount,rw /
|
||||
cp /home/root/chatter/chatter-launcher.service /usr/lib/systemd/system/chatter-launcher.service
|
||||
mkdir -p /usr/lib/systemd/system/multi-user.target.wants
|
||||
ln -sf ../chatter-launcher.service /usr/lib/systemd/system/multi-user.target.wants/chatter-launcher.service
|
||||
sync
|
||||
mount -o remount,ro /
|
||||
systemctl daemon-reload
|
||||
systemctl restart chatter-launcher.service
|
||||
echo "launcher: $(systemctl is-active chatter-launcher)"
|
||||
'
|
||||
5
scripts/restore-xochitl.sh
Executable file
5
scripts/restore-xochitl.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring the standard reMarkable GUI back after running Chatter.
|
||||
set -euo pipefail
|
||||
ssh chatter 'systemctl stop chatter 2>/dev/null; systemctl reset-failed chatter 2>/dev/null; systemctl start xochitl'
|
||||
echo "chatter stopped; xochitl restarted — standard GUI restored."
|
||||
12
scripts/to-chatter.sh
Normal file
12
scripts/to-chatter.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
# Switch from the standard interface to Chatter (invoked by the launcher daemon
|
||||
# on the multi-finger gesture). Lives on the device at /home/root/chatter/.
|
||||
systemctl stop xochitl 2>/dev/null
|
||||
systemctl stop chatter 2>/dev/null
|
||||
systemctl reset-failed chatter 2>/dev/null
|
||||
sleep 1
|
||||
systemd-run --unit=chatter --collect \
|
||||
--setenv=QT_QUICK_BACKEND=epaper \
|
||||
--setenv=LD_LIBRARY_PATH=/usr/lib/plugins/scenegraph \
|
||||
--working-directory=/home/root/chatter \
|
||||
/home/root/chatter/chatter -platform epaper
|
||||
Reference in New Issue
Block a user