screentinker/server
ScreenTinker 141deb97a5 screen_off must tear the video down — a DOM overlay cannot cover a hardware plane
Blanking the screen took three attempts on real hardware, and each failure was
the same lesson from a different angle:

  1. black overlay        -> the video played straight THROUGH it. With hwz
                             enabled the widget decodes onto a hardware plane and
                             the graphics plane sits behind it; z-index is
                             irrelevant across planes.
  2. pause + hide element -> playback stopped and the LAST DECODED FRAME stayed
                             on screen. Hiding a DOM element does nothing to the
                             plane, which is not part of the DOM.
  3. pause + remove src   -> releases the plane. Black.
     + load()

Coming back re-mounts through nextItem(), because a torn-down element cannot be
resurrected. The playlist keeps advancing while the screen is off, so each newly
started item is torn down as well — caught on 'play' in the capture phase, or the
next video lights the panel back up a few seconds later.

CEC is now explicitly not load-bearing. Our XT245 logs "failed to get cec clock"
and does not respond to it at all, which is precisely why blanking cannot depend
on a cooperative display: plenty ignore broadcast CEC or need direct addressing.
displayPower() stays as opportunistic best-effort alongside the teardown.

Verified on hardware: not black, then frozen frame, then black.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL
2026-08-05 09:40:17 -05:00
..
config fix(logging): gate CF-Connecting-IP on a Cloudflare peer, not any trusted proxy 2026-07-26 10:23:04 -05:00
db Keep a workspace on schedules that outlive their device group 2026-07-30 20:53:21 -05:00
lib Finish the BrightSign port: native sync, offline fallback, multicast guard 2026-08-04 21:43:42 -05:00
middleware Merge branch 'fix/recovery-grants' into release/auth-campaign 2026-07-26 16:22:59 -05:00
player screen_off must tear the video down — a DOM overlay cannot cover a hardware plane 2026-08-05 09:40:17 -05:00
routes Make a content-only schedule actually put that content on the screen 2026-07-30 22:26:58 -05:00
scripts fix(content+android): rotation-aware media — portrait upright on dashboard AND player (#170) (#172) 2026-07-12 22:05:11 -05:00
services Make a recurring schedule respect its start and end dates 2026-07-30 22:22:59 -05:00
test BrightSign: real display power, reboot and volume — command parity 2026-08-05 09:26:23 -05:00
ws Stamp the authenticated device on relayed playback progress 2026-07-30 22:41:06 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js Add an operator override for self-update on MDM-managed panels 2026-07-28 23:07:30 -05:00
package-lock.json chore(release): v1.9.29-rc2 2026-08-05 00:06:20 -05:00
package.json chore(release): v1.9.29-rc2 2026-08-05 00:06:20 -05:00
server.js Finish the BrightSign port: native sync, offline fallback, multicast guard 2026-08-04 21:43:42 -05:00
smoke-ui.js Keep the smoke test out of npm test, and update the lockfile 2026-07-28 20:34:34 -05:00
version.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00