#!/usr/bin/env bash # Hardware sign-off for Linux: run from a real desktop session (Hyprland, # another Wayland compositor, or X11) on the machine being validated. # # scripts/validate/linux-hardware.sh [output-dir] # # Records at 1440p60 with every usable hardware codec, checks the segments, # confirms the portal restores its selection without asking again, and # records a window. Writes report.txt in the output directory. set -uo pipefail repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" out="${1:-${TMPDIR:-/tmp}/clipbin-hardware}" probe="${repo}/target/debug/clipbin-probe" report="${out}/report.txt" rm -rf "${out}" && mkdir -p "${out}" format=(--width 2560 --height 1440 --fps 60 --bitrate 40000) cargo build --locked -p clipbin-probe --manifest-path "${repo}/Cargo.toml" || exit 1 log() { echo "$*" | tee -a "${report}"; } ask() { local answer read -r -p "$1 [y/n] " answer log "answer: $1 -> ${answer}" } log "Clipbin hardware validation $(date -Is)" log "host: $(uname -r) session=${XDG_SESSION_TYPE:-?} desktop=${XDG_CURRENT_DESKTOP:-?}" log "gpu: $(lspci 2>/dev/null | grep -iE 'vga|display' | cut -d: -f3- | xargs)" "${probe}" encoders --verify "${format[@]}" --out "${out}/encoders" > "${out}/encoders.log" 2> "${out}/encoders.obs.log" log "$(grep -E '^(obs_version|usable\.|verify\.)' "${out}/encoders.log")" token="" for codec in h264 hevc av1; do if grep -q "^usable\.${codec}=none" "${out}/encoders.log"; then log "SKIP ${codec}: no usable hardware encoder" continue fi if [[ -z "${token}" ]]; then echo echo "Recording a monitor for 20 seconds with ${codec}. The portal will ask" echo "you to pick a monitor: pick one and keep some motion on screen." fi dir="${out}/monitor-${codec}" restore=() [[ -n "${token}" ]] && restore=(--restore-token "${token}") "${probe}" record --target monitor --codec "${codec}" "${restore[@]}" --seconds 20 "${format[@]}" \ --out "${dir}" > "${dir}.log" 2> "${dir}.obs.log" record_exit=$? "${probe}" check --codec "${codec}" --out "${dir}" >> "${dir}.log" 2>&1 check_exit=$? log "monitor-${codec}: record_exit=${record_exit} check_exit=${check_exit} $(grep -E '^(encoder|recorded|check)=' "${dir}.log" | tr '\n' ' ')" log "$(grep -E 'status=' "${dir}.log" | tr '\n' ' ')" if [[ -z "${token}" ]]; then token="$(sed -n 's/^restore_token=//p' "${dir}.log")" log "restore token received: $([[ -n "${token}" ]] && echo yes || echo no)" else ask "Did ${codec} start WITHOUT showing the portal picker again?" fi done echo echo "Now recording a window for 20 seconds. Start a game (or any moving" echo "window) first, then pick it in the portal." read -r -p "Press Enter when ready. " _ dir="${out}/window-h264" "${probe}" record --target window --seconds 20 "${format[@]}" --out "${dir}" > "${dir}.log" 2> "${dir}.obs.log" record_exit=$? "${probe}" check --out "${dir}" >> "${dir}.log" 2>&1 log "window-h264: record_exit=${record_exit} check_exit=$? $(grep -E '^(recorded|check)=' "${dir}.log" | tr '\n' ' ')" echo echo "Last: source loss. Record a window again, then close that window" echo "about 5 seconds in. The probe should report a failure." read -r -p "Press Enter when ready. " _ dir="${out}/window-closed" "${probe}" record --target window --seconds 20 "${format[@]}" --out "${dir}" > "${dir}.log" 2> "${dir}.obs.log" log "window-closed: exit=$? $(grep -E 'status=failed' "${dir}.log" | head -1)" echo echo "Report: ${report}" echo "Recordings and logs: ${out}"