#!/usr/bin/env bash # Regenerates the images in docs/images. # # Two kinds of picture, and the difference matters: # # * The control page is captured with headless Chrome, because the operator # window shows exactly this page and a browser capture is reproducible in a # way that driving the macOS window server is not. # # * The output frames are captured by tools/ndi_probe — a separate receiver — # straight off the network and converted back to RGB. They are genuinely # what a receiver got, not a screenshot of a browser, which is the whole # point of showing them. # # macOS only as written: it uses sips to convert PPM to PNG. set -euo pipefail cd "$(dirname "$0")/.." ROOT="$PWD" OUT="$ROOT/docs/images" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT APP="$ROOT/build/Release/WebLinked.app/Contents/MacOS/WebLinked" CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" NDI_INC="/Library/NDI SDK for Apple/include" NDI_LIB="/Library/NDI SDK for Apple/lib/macOS/libndi.dylib" PORT=7654 SOURCE_NAME="WebLinkedShots" CLOCK_NAME="WebLinkedShotsClock" for required in "$APP" "$CHROME" "$NDI_LIB"; do [ -e "$required" ] || { echo "missing: $required" >&2; exit 1; } done mkdir -p "$OUT" echo "==> building ndi_probe" clang++ -std=c++20 -O1 -I"$NDI_INC" tools/ndi_probe.cpp "$NDI_LIB" \ -Wl,-rpath,"$(dirname "$NDI_LIB")" -o "$WORK/ndi_probe" # CEF refuses to start a second instance against the same profile, so make sure # nothing else is holding it. pkill -f "WebLinked.app/Contents/MacOS/WebLinked" 2>/dev/null || true sleep 2 # Two sources rather than one, because the control page's source strip only # appears when there is more than one — and the strip is the thing the pictures # now have to show. It also removes the mid-run URL switch the old script needed # to get a second output frame: both are simply on air at once. cat >"$WORK/shots.json" < starting WebLinked with two sources" WEBLINKED_LOG_DIR="$WORK/logs" "$APP" \ --config "$WORK/shots.json" --headless >"$WORK/app.log" 2>&1 & APP_PID=$! trap 'kill -TERM $APP_PID 2>/dev/null || true; rm -rf "$WORK"' EXIT # Give Chromium time to load the page and paint it. sleep 16 capture_gui() { # capture_gui [view] # ?view= exists so each tab is capturable without driving a window server; # the page applies it once the first state has arrived, which is why the # virtual time budget is generous. local view="${2:-control}" "$CHROME" --headless --disable-gpu --hide-scrollbars \ --screenshot="$1" --window-size=1360,940 --virtual-time-budget=6000 \ "http://127.0.0.1:$PORT/?view=$view" >/dev/null 2>&1 } capture_frame() { # capture_frame # --save-after skips the first frames so the page has settled. "$WORK/ndi_probe" --source "$2" --frames 30 \ --save "$WORK/frame.ppm" --save-after 20 --timeout 25 >/dev/null sips -s format png "$WORK/frame.ppm" --out "$1" >/dev/null } echo "==> capturing the three views" capture_gui "$OUT/control-page.png" control capture_gui "$OUT/settings-page.png" settings capture_gui "$OUT/diagnostics-page.png" diagnostics echo "==> capturing both outputs, straight off the network" capture_frame "$OUT/output-github.png" "$SOURCE_NAME" capture_frame "$OUT/output-clock.png" "$CLOCK_NAME" echo echo "wrote:" ls -la "$OUT"