feat: make DVD playback a classroom surface, not a media player

Pressing DVD now enters DVD mode rather than opening VLC. VLC is still
the backend, because its dvdnav module is what decodes disc menus and
nothing else on Debian does that reliably, but nothing a person can see
or press belongs to it any more.

classroom-dvd-session owns the whole thing. It puts a full-screen black
layer-shell surface up the moment the button is pressed, starts VLC
behind it, and drops it once playback is actually on screen — so the
harsh cut from wallpaper to VLC's black window is gone, and no partial
VLC window or reserved dock strip is ever visible. A deadline drops the
surface regardless, because DVD mode must never leave a black screen
with nothing behind it.

The controls are a classroom bar on the overlay layer, the one layer
sway draws above a fullscreen window. It slides up when the pointer
reaches the bottom of the screen and hides again shortly after it
leaves. It is drawn from the dock's own stylesheet at the room's UI
scale, so it is the same surface, the same radius and the same white
icons. While hidden it only accepts the pointer in a thin strip along
the bottom edge, so a click on a disc menu goes to the disc.

The bar reaches VLC through an HTTP interface on loopback behind a
password generated per session, sending hotkey *actions* by name. That
is what makes the next part possible.

All 108 hotkeys VLC 3.0.23 defines are unset, then Space, Esc and the
arrow keys plus Enter are bound. Crop, aspect ratio, subtitles, audio
tracks and deinterlacing are no longer reachable by pressing a key at
random, and the arrow keys no longer change VLC's volume — the
television owns volume, and CEC will own it properly later.

Esc quits instead of leaving fullscreen. There is nothing to leave, and
leaving it was what stranded people on a black VLC window. Close, Eject
and Esc all ask VLC to quit and escalate to SIGTERM then SIGKILL if it
does not; when VLC exits by any route, including a crash, the session
ends and the classroom desktop comes back.

Verified against VLC 3.0.23 on Trixie: every argument accepted, every
control action accepted over the control interface, a wrong password
refused, and quit exiting cleanly. The surfaces were rendered under a
headless sway and screenshotted to check the bar against the dock.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
ekklesia
2026-09-04 22:33:53 -05:00
co-authored by Claude Opus 5
parent 3e69f3f05c
commit f8ddfbe345
17 changed files with 961 additions and 88 deletions
+11 -44
View File
@@ -20,9 +20,10 @@ sys.path.insert(
)
import classroom_optical as optical # noqa: E402
from classroom_vlc import PLAYER # noqa: E402
PLAYER = "vlc"
WINDOW_TOOL = "/usr/local/bin/classroom-window"
SESSION_TOOL = "/usr/local/bin/classroom-dvd-session"
def notify(title, message, urgency="normal"):
@@ -42,49 +43,15 @@ def notify(title, message, urgency="normal"):
print(f"{title}: {message}", file=sys.stderr)
def player_command(device):
"""VLC, dressed down to look like an appliance rather than a desktop app.
All of these are documented VLC 3.x options, verified against the
3.0.23 build in Debian Trixie. No skin is involved: skins replace the
interface wholesale and break DVD menu input, which is the one thing
that has to keep working.
Note that --no-qt-updates-notif, which earlier builds passed, is not
an option in Debian's VLC and made it refuse to start at all.
"""
return [
PLAYER,
# Fullscreen first: the disc opens straight onto the TV.
"--fullscreen",
# No menu bar or extended panels, and a dark window instead of
# the default light grey one.
"--qt-minimal-view",
"--qt-dark-palette",
# No orange cone, and no album-art panel, behind the video.
"--no-qt-bgcone",
# Nothing that behaves like a desktop application.
"--no-qt-system-tray",
"--no-qt-name-in-title",
"--no-qt-video-autoresize",
"--qt-notification=0",
# Never offer to resume, and never accumulate a list of the
# discs a classroom has played.
"--qt-continue=0",
"--no-qt-recentplay",
# No first-run privacy dialog, no title banner over the video.
"--no-qt-privacy-ask",
"--no-video-title-show",
# dvd:// selects VLC's dvdnav module, which is what provides the
# disc menus. The Qt interface is kept for exactly that reason:
# --intf dummy would be cleaner still but takes the keyboard and
# mouse handling that menu navigation depends on with it.
f"dvd://{device}",
]
def play(device):
"""Hand the disc to the player through the normal window toggle."""
"""Hand the disc to DVD mode through the normal window toggle.
classroom-dvd-session owns the player from here: it puts a black
surface up immediately, starts VLC behind it, and provides the
classroom's own controls. Going through classroom-window keeps the
dock button behaving like every other one — focus if it is already
up, rather than starting a second session.
"""
if shutil.which(PLAYER) is None:
notify(
"DVD",
@@ -99,7 +66,7 @@ def play(device):
"--match",
"(?i)vlc",
"--",
*player_command(device),
SESSION_TOOL,
]
)