Repository navigation
Tests
plot::step is pure, so a display is not required to lock a scene.
Each case under testdata/frames/ in the glass repo is one recorded step: the SkinDesc and Input that went in and the Scene that came out. The plot test recorded_frames_replay runs step on every *.json file there and compares. expose has pixel tests of its own, among them that painting only what changed equals painting everything.
On a player with the tap's ring live:
glass --once --headless --record testdata/frames/<name>.json
The file is JSON with three keys, skin, input and scene. Name it after what it shows, for example custom3-quiet.json or custom3-loud-left.json. Commit it with test:.
GLASS_PROFILE=1 glass prints a line every 60 frames with the frames a second achieved and the average time of one frame's parts in microseconds: the poll (the ring and the channel), the plot step, the raster with its two stages (prep, where what moves is advanced, type is set and the changed boxes are found, and paint, where those boxes are painted), and the show, the upload to the window. Compare runs on the same device, theme and frame rate. The Performance page has the figures.
glass reads the player's installed configuration; the review flags stand in for its theme, meter and rotation for one run and change nothing on the player. Run them on the device as the volumio user with something playing, so the meters and texts carry real values.
| Command | Shows |
|---|---|
glass --list |
Every theme folder under the configured base.folder with the meters in its meters.txt. |
glass --theme 1280x720_g5_710_Turntables --meter "141G5_01_Vertere Turn" |
One meter of one theme in the window until the window closes or the run flag is removed. |
glass --theme 1280x720_custom_3 --meter random --interval 10 |
Every meter of the theme in random order, ten seconds each. A comma list plays in order. |
glass --headless --theme 1280x720_custom_3 --snapshot /tmp/snap --settle 4 |
Each meter of the theme for four seconds, then /tmp/snap/1280x720_custom_3/<meter>.png of the settled frame, and leaves. Add --meter a,b for a subset. Without --headless the window shows the walk too. |
glass --theme ... --meter ... --output /tmp/frame.png |
Every frame written as a PNG, for a still of a moving meter. |
glass --fps 60 --theme ... --meter ... |
The same meter at 60 frames a second for one run; the player's own frame.rate stays. Pair with GLASS_PROFILE=1 to see whether a frame fits its 16.7 ms. |
glass --threads 1 --theme ... --meter ... |
Paint every frame on one thread (or on N). Without the flag a frame takes from one thread up to one a core as it needs; the profile line's painters field shows how many it settled on. |
GLASS_PROFILE=1 glass ... |
Besides the timings, the profile line says how much of the frame the last frames painted and in how many boxes: a still player paints nothing, a needle meter a few percent, a turning record its own box. |
GLASS_PROFILE=1 glass ... |
Two memory lines: what the meter's pictures and fonts hold once loaded, printed once at the start, and what moves between frames (the canvas, turned pictures, lines of text, album art, layers, fanart, record and reels), printed every sixty frames, in kB by store. Fonts are mapped files: only the pages the glyphs touch are resident. |
glass --once --headless --record /tmp/step.json on a player |
While the plugin runs, the run prints glass: channel /tmp/glass_channel when GLASS_LOG=verbose is set, and the recorded input's metadata is what the channel pushed, infinity included; without the plugin the player is asked over HTTP and infinity stays false. |
scripts/tap_exact.sh [libglasstap.so] [tapdump] |
Plays three megabytes of random frames as S16, S24_3LE, S32 and DSD_U32 through a type glasstap PCM into a file and compares: every byte must come out as it went in. Needs aplay; CI runs it on the x64 build after the cross builds. |
tapdump 2 on a player while FM or DAB plays |
The ring named by the radio's own aplay process shows moving peaks: every source that plays through volumio meters, in both audio selections. |
glass --headless --snapshot /tmp/snap --thumb 320 --theme ... --settle 0.5 |
Every meter of the theme as a PNG and a 320 px thumbnail beside it, in under a second a meter on a Pi 5; what the manager runs for its previews. |
node --test plugin/manager/test/*.test.js |
The manager's tests: the zip reader against zips built in the test (the four layouts, twins, escapes and links left out, checksums, replacement of an installed folder), the release check and its digests, Car Dash's clock and sun, the fonts, the logging gate, the performance profiles, the track files, the face's feed against a stand-in daemon socket (the headers, the plugin's last lines replayed, hops fanned out, a page that leaves), the catalog's downloads, the glass-evo component and which Glass it goes with, who owns the screen and the way back, the screen's facts read from texts captured on a player, the diagnosis and the capture behind a report, the face's look and the look panel's model, the views, the previews read from the pictures a render wrote, the queue and the state as the channel carries them, the wait between relaunches, the player's facts, the tailor, and the old plugin's leavings. scripts/check.sh runs it (through docker when node is absent). |
cargo test --workspace |
The crates' own tests, beside the recorded frames: lead's parsers and file helpers (the analyser's look and demand among them), plot's scene (a button's state by its action, the analyser's bands on the bar scale), expose's raster and text placement and its analyser (bars from the palette over the background, a peak that holds then falls, a mirror's symmetry, and four timing tests, that a dense luminance, outlined, graph and radial frame each stay under 8 ms in release), bank (a demand cleaned and its window chosen, a tone landing in its band on every scale, the edges partitioning the range, bands that share bins told apart, the hold's half-life, a raw spectrum projected, an onset on a rise after quiet), tap (a frame published is the frame read, a ring of the previous version read as a raw spectrum, a stereo bank across the wire within a quarter decibel, the demand file seen once, the legacy regrouping, a full-scale sine reading one, linear and one-bit audio measured, the relay's order), controls (a finger on the nearest control, a drag's cadence, a button pressed), intake's wire hops, wants and configuration rewriting, its channel (lines arriving whole or in pieces, a missing socket tried again, a remote's hello over TCP, the queue and the persist line decoded) and what a remote brings from its player, overlay (the time of day in its zone and the calendar's edges, a face laid on its copy and not drawn again while it and the picture stand), pane (a finger as a window pixel, a turned picture and a turned finger, a fitted frame), logline's levels and gate, the browser module (a theme from the table painted, a finger along a bar, the state kept across a meter change, the type icon found and painted, the album art and the fanart set wanted from the page and drawn once put), the frames daemon's pages socket, the tailor and the package, and the display's own loop: its governor, its remote configuration, what the window is given of a frame, the standing rate, and the launcher's word that the screen is the display's own. |
scripts/check.sh |
Besides the Rust checks (format, lints with warnings denied, tests): the browser module linted and built for its target, the documentation built with warnings denied, the ALSA templates checked (scripts/asound_check.sh), the shell scripts parsed, the plugin's JSON files parsed, a key written twice in one object refused and each file ending with one newline, the inline scripts of the manager's page, the Anymote page and the remote's page parsed with node along with the face's scripts, the Windows installer run in its check mode against the release archive's layout, the checkout's and the bundle's (glass-evo.exe), and refused for a layout with neither display, the manager's tests, and the plugin's scripts and the pages' inline scripts linted for names nothing defines, with one pinned ESLint fetched for the run. |
glass --record without --once keeps only the last step: the file is written again at every frame.
--settle covers the fade in, the level ramp, the album art fetch and the fanart answer; make it longer for themes that fetch art over the network on a slow link. Snapshots are the frame as rendered, alpha included, at the theme's size. Copy them off the device with scp (quote names with spaces) or look at them in the browser through the player's own file share.
The fade lock glass_fade_lock in the temp directory is shared by every display on the machine: two starts within a fade's time plus a second show no second fade, which is expected.
CI and the release run the check, the cross builds and the Windows build in one image, ghcr.io/foonerd/glass-builder: Ubuntu 24.04 with the cross compilers, MinGW-w64, the libraries the host build links against, Node, PowerShell and the Rust toolchain rust-toolchain.toml names. It is described by scripts/builder/Dockerfile, pushed by the builder workflow when that file or the toolchain changes, and named in ci.yml and release.yml by its digest, so a build installs no system package while it runs. The Android app is the exception: it is built on the runner itself, whose SDK it uses. glass-evo builds in the same image.
CI runs on every push to main and evo and on every pull request; the Windows and Android builds run on main only, and the build caches are written from main only and read by every branch and by the release.
What a build downloads goes through scripts/fetch.sh URL FILE [SHA256]: a connection that fails or stalls is tried again, up to five times, and the file appears under its name only when it is whole and, with a digest given, only when it is the file expected.
The same image runs every script on a machine that has Docker and none of the compilers:
docker build -t glass-builder -f scripts/builder/Dockerfile .
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/glass" -w /glass glass-builder scripts/check.sh
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/glass" -w /glass glass-builder scripts/ship.shA release is five jobs: the check, the Linux builds with the plugin zip and the remotes' archives, the Windows build and the Android app side by side, then one job that signs the Windows files and publishes the release as a pre-release (from the release after 0.8.5; it is made the latest by hand once it has been tried, with gh release edit <tag> --prerelease=false --latest, see Test releases on the Manager page). It refuses a tag that does not name the workspace's version, and run by hand (workflow_dispatch) it builds everything and publishes nothing.
- Home
- Quick-Start
- Settings
- Manager
- Manager-API
- Screen
- Artwork
- Catalog
- Backups
- Remotes
- Anymote
- Performance
- Troubleshooting
- Logging
Themes
Developers
The Glass interface