Files
Classroom_Desktop/docs/dvd.md
T
ekklesiaandClaude Opus 5 37f8166401 fix: hold the DVD cover until the disc menu is actually showing
The readiness condition was playback state alone, and on a real disc
VLC reports playing well before its window has taken the screen. The
cover came off onto VLC's ordinary tiled startup window — black, sized
to everything except the dock's reserved strip — and the disc menu only
arrived afterwards. Exactly the state the cover exists to hide.

Ask sway instead. VLC only takes the display when its window goes
fullscreen, and the tree says when that happens. The cover now comes off
when VLC reports playing or paused, its window is fullscreen, and 800ms
have passed for the menu to draw its first frames. The playback check
runs first because it is local and cheap; the tree is only walked once
VLC claims to be playing something.

The twenty second deadline is unchanged: a cover with nothing behind it
is still the one outcome DVD mode must never produce.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-04 23:17:37 -05:00

189 lines
7.1 KiB
Markdown

# DVD support
DVD support is optional per classroom and off by default.
## Enabling a room
Edit `/etc/ekklesia-classroom/device.conf` on that endpoint:
```
DVD_ENABLED=true
```
Then restart the session (reboot, or restart `classroom-dock`).
With `DVD_ENABLED=false`, or the key absent, the DVD button is not built
at all and no drive polling happens. Older endpoints get a commented
`DVD_ENABLED=false` appended on upgrade so the option is discoverable,
which leaves their behaviour unchanged.
## Behaviour
The dock polls the drive every two seconds with the `CDROM_DRIVE_STATUS`
ioctl. That is a status query, so it does not spin the disc up.
| State | Dock icon | Clicking the button |
| --- | --- | --- |
| No drive connected | DVD logo held back at 55% | "No DVD drive is connected to this classroom computer." |
| Drive present, no disc | DVD logo held back at 55% | "No disc is in the drive. Insert a disc to get started." |
| Tray open | held back | "The disc tray is open. Insert a disc to get started." |
| Disc still being read | held back | "Reading the disc. Please try again in a moment." |
| Disc ready | DVD logo at full strength | Plays the disc |
When a disc becomes ready, a **DVD Ready** notification is shown once.
Discs never play on their own; playback always needs a button press.
The first poll after login only records what is already in the drive, so
a disc left in over the week does not announce itself at every boot.
## Playback: DVD mode
Pressing DVD does not open a media player. It enters **DVD mode**: a
full-screen playback surface the classroom owns, with VLC decoding the
disc behind it.
`classroom-dvd-session` runs the whole thing:
```
loading surface layer-shell OVERLAY, the whole display including the
dock, taken down once playback is on screen
VLC fullscreen, drawn above the top layer by sway
control bar layer-shell OVERLAY, the one layer sway draws above a
fullscreen window
```
### Loading
Pressing DVD covers the entire display immediately — before VLC is even
started — with a black surface carrying a spinner and *Loading DVD…* on
the same translucent rounded card the dock uses. The wallpaper, the dock
and the clock are all gone from the moment the button is pressed.
It is on the **overlay** layer rather than the top layer, because the
dock is a top-layer surface and DVD mode has to cover it. Its exclusive
zone is `-1`, which tells sway not to move it out of the way of the
strip the dock reserves.
It comes down only when **all three** of these hold:
1. VLC reports playing or paused, and
2. VLC's window is fullscreen in the sway tree, and
3. 800ms have passed since both became true.
Playback state alone is not enough, and used to be the whole condition.
VLC reports playing while its window is still the ordinary tiled one
sway gave it — which is exactly the black startup window the cover
exists to hide. It only takes the display when it goes fullscreen, and
the sway tree is what says so. The final hold gives the disc menu time
to draw its first frames, so the handover lands on the menu rather than
on VLC's black.
A twenty second deadline takes the cover down regardless: a cover with
nothing behind it is the one outcome DVD mode must never produce.
VLC is still the backend because its `dvdnav` module is what decodes
disc menus, and nothing else on Debian does that reliably. But nothing
of VLC's own interface is exposed: no menu bar, no panels, no
fullscreen controller, no cone, and no sway title bar.
### The control bar
Move the mouse to the bottom of the screen and a bar slides up. It is
the same dark translucent rounded surface as the dock, drawn from the
same stylesheet at the same UI scale, so DVD mode feels like the same
room. It hides again a second after the pointer leaves it, or after four
seconds without movement.
| Control | Does |
| --- | --- |
| ⏮ | Previous chapter |
| ▶ / ⏸ | Play or pause, showing which one it will do |
| ⏭ | Next chapter |
| ☰ | Back to the disc menu |
| ⏏ | Ejects the disc and leaves DVD mode |
| ✕ | Leaves DVD mode |
While the bar is hidden it only accepts the pointer in a thin strip
along the very bottom edge, so a click anywhere else goes to the disc
menu rather than to an invisible bar.
The bar reaches VLC over an HTTP control interface on the loopback
address, behind a password generated for that session alone. Commands
are sent as VLC hotkey **actions** by name, which is why they keep
working even though every key has been unbound.
### The keyboard
All 108 hotkeys VLC 3.0.23 defines are unset, then these are bound:
| Key | Does |
| --- | --- |
| Space | Play / pause |
| Esc | Leaves DVD mode |
| Arrow keys | Move around a disc menu |
| Enter | Choose the highlighted menu item |
Nothing else responds. A volunteer cannot land on crop, aspect ratio,
subtitle tracks, audio tracks or deinterlacing by pressing a key at
random, and **the arrow keys no longer change VLC's volume** — the
television owns volume.
Esc quits rather than leaving fullscreen. DVD mode is the whole screen,
so there is nothing to leave, and leaving it used to strand people on a
black VLC window with no way back.
There is no fullscreen toggle, because DVD mode is not a window.
### Leaving
Close, Eject and Esc all do the same thing: ask VLC to quit, and if it
does not, escalate to SIGTERM and then SIGKILL. When VLC exits — however
it exits, including a crash — the session ends and the classroom desktop
and dock come straight back. Nothing can leave a black window behind.
Only one DVD session can run at a time, however fast the button is
pressed.
## Commercial (CSS encrypted) discs
Most retail DVDs are CSS encrypted, and Debian cannot ship the
decryption library. Unencrypted discs — curriculum discs, home-burned
video — play without any extra work.
**This is automatic.** On any classroom with `DVD_ENABLED=true`, the
provisioning service installs the codecs after the next boot. See
[provisioning.md](provisioning.md).
To do it by hand, or to watch it happen:
```
sudo classroom-dvd-css-setup
classroom-dvd-css-setup --status
```
It enables the Debian `contrib` component in whichever APT source format
the machine uses, installs `libdvd-pkg`, answers its debconf questions
and builds `libdvdcss`. It only ever adds a missing component to an
existing Debian entry, so repeated runs cannot produce a duplicate
repository or a duplicate component, and third-party repositories such
as Google Chrome's are never touched.
It needs the network and it compiles a package, which is why it runs
from the provisioning service rather than the package `postinst`: the
postinst executes while dpkg is still holding the apt lock.
## Command line
```
classroom-dvd status # drive node, drive state, whether VLC is installed
classroom-dvd toggle # what the dock button does
classroom-dvd play # start playback even if the drive is unsure
classroom-dvd eject # open the tray
```
## Permissions
Reading the drive needs group `cdrom`. The postinst adds the `classroom`
user to it; that takes effect at the next login, which the OTA reboot
provides. Without it the drive reads as absent.