Files
DarkRoom/tools/manual
dtourolle b53d4dc391
Benchmarks / CPU and I/O (per commit) (push) Waiting to run
Benchmarks / Frame budget (on demand) (push) Waiting to run
Build and test / Desktop (Linux) (push) Waiting to run
Build and test / Android (aarch64) (push) Blocked by required conditions
Build and test / Windows (x86_64, cross) (push) Blocked by required conditions
Build and test / Layer separation (push) Waiting to run
Build and test / Publish the release (push) Blocked by required conditions
Build and test / android-image (push) Waiting to run
🐳 Android image / Build and push (push) Waiting to run
Build and test / windows-image (push) Waiting to run
🐳 Windows image / Build and push (push) Waiting to run
Manual pages / Publish the manual (push) Waiting to run
Traceability / Requirement traces (push) Waiting to run
Offer the manual as PDF and EPUB, laid out for print
The page gains a print stylesheet: A4 with a cover, a contents page whose
entries carry their page numbers, a chapter to a page with its name at the
head of each page and the page count at the foot, figures and table rows
never split, and the light palette. A line above the title links the PDF
and the EPUB on the published site, absolutely, since an installed copy
has none beside it.

The Manual pages workflow makes both: tools/manual/pdf.py renders the page
with WeasyPrint from JPEG copies of its pictures, which takes the PDF from
28 MB to 8, and pandoc makes the EPUB from the Markdown.
2026-10-08 22:41:07 -04:00
..

tools/manual — the pictures in docs/manual

record.sh drives the desktop build on a private X server and records the scenes in scenes.py into docs/manual/media/:

tools/manual/record.sh /var/tmp/dr-demo/library              # every scene
tools/manual/record.sh /var/tmp/dr-demo/library develop_zoom # one, and what it needs
tools/manual/record.sh --changed /var/tmp/dr-demo/library    # those whose sources moved
tools/manual/record.sh --check                               # the manual and the scenes agree
tools/manual/record.sh --list

Set DR_LIBRARY_SNAPSHOT to a pristine copy of the library: a recording rates, files and merges, and the snapshot is copied over the library first. Each run starts from a fresh profile under DR_HOME.

Controls by name

The binary is built with --features automation, which lets the app answer "where is the control labelled Exposure?" over the Unix socket named by DR_AUTOMATION (ui/dr-ui/src/automation.rs). No other build has the feature, and a build that has it listens only when the variable is set. The names are the accessible labels a screen reader reads, so a scene says click_on('Select@Button') or slide('Exposure', 24) rather than a pixel, and survives a panel that moves. The pointer itself is still xdotool.

DR_HOME=/var/tmp/x tools/manual/drive.py launch /some/folder   # a feature build in DR_BIN
tools/manual/drive.py labels                 # every name on screen
tools/manual/drive.py click-on 'Settings@Button'
tools/manual/drive.py ids canvas             # things with no name: id:canvas-image
tools/manual/drive.py stop

Grid cells are named by file (_MG_8393@ListItem), rating stars 1 star to 5 stars. What a scene cannot name — a point on the photograph, the crop rectangle's corner — it places relative to something it can (drive.photo(fx, fy), id:move-area).

Scenes and the manual

Each scene in scenes.py declares the pictures it makes, as the manual names them, and the globs of the sources that could change them. --check fails when the manual shows a picture no scene makes, or a scene makes one the manual does not show; it reads two files and runs in CI. --changed re-records a scene when one of its sources, or its own code, has changed since the commit that last touched its pictures.

GIFs are made at 960 px and ten frames a second. A scene whose film does not compress at that size says otherwise in GIF_SIZE, which record.sh reads through scenes.py gif NAME. giant_pano borrows a 500 MB panorama from outside the library (DR_GIANT_DNG, by default /var/tmp/dr-dng/IMG_4181-Pano.dng) and removes it again, so it runs last.

Two things the scripts know that are not obvious: a Slint TouchArea wants a held press, not xdotool's click; and the app is driven on Xvfb rather than the desktop because under XWayland at scale 2 a pointer warp lands at twice the coordinate asked for.