PRESENTATIONS_ENABLED, off by default, independent of everything else. A teacher downloads a session in ordinary Chrome and it is on the Presentations screen a few seconds later, ready for the television. No file manager, no import button, no Impress. WHY NOTHING LAUNCHES A DOCUMENT APPLICATION. The brief was to use existing presentation software, so the existing software was tried first, on Debian 13, before any of this was designed. `soffice --show` does start a real fullscreen slideshow — and needs XDG_SESSION_TYPE plus a VCL plugin or it dies with "Failed to open display", shows a splash, opened a "Tip of the Day: 1/225" dialog over the slides, and leaves the Impress editor when the show ends. `okular --presentation` opens THREE windows: the presentation, the ordinary document window behind it, and an information dialog. zathura is not a presenter. pdfpc is the closest and is another dependency with a presenter-console model. Every one of them leaves an application on screen that can open any file on the machine, and none of them knows there is a library to go back to. So LibreOffice converts once, headless, at import, with no window on any screen; poppler renders the pages; the classroom shows the pictures. Measured: 0.34s for a ten-slide PPTX, 0.03s for its ten thumbnails, 0.10s for one slide at 1920px. That is not a new renderer — it is the same engine Impress would have used live — and it means Escape is ours, presenting is instant, and a PDF exported from Google Slides skips the conversion entirely and keeps the appearance Google gave it. THE THREE THINGS KEPT APART. The library thumbnail, the starting slide and the retention clock are independent, because the first slide of a Bible study session is a generic opening shared by every session and the one that names it is usually the second. Quick Look chooses the picture; it does not change where the slideshow starts and it does not count as having presented anything. mark_presented() is called when a slide is actually drawn, not when Present is pressed: an intention is not a presentation, and a viewer that failed to start must not buy another thirty days. IMPORTING. The teacher's download is copied, never moved, renamed or deleted. A file with a .crdownload beside it is still arriving. Wonder Ink's own folder is not looked at. Two downloads of the same name are two presentations, the second titled (2) — found in the lab, where a PDF and a PPTX of one session both came out with the same name because the import being named was excluded from the taken-titles set BY TITLE, and a set holds one copy of a repeated string. Metadata is written saying "importing" before any work, so a reboot mid-conversion leaves a directory the next startup sweeps and imports again. A file that cannot be converted gets a card saying so, offering only Remove, with the teacher's download untouched. Retention: 180 days never presented, 30 days from the last presentation, every presentation starting the thirty over. The cleanup never touches a presentation being shown, never leaves the library directory, and never looks at Downloads. The dock order is unchanged: Presentations is appended after the disc player, so Wonder Ink, the browser and the player keep the places teachers have been reaching for. There is a test for exactly that. classroom-wonderink now asks feature() rather than carrying its own copy of the default, so the panel and the command cannot disagree. Co-Authored-By: Claude Opus 5 <[email protected]>
221 lines
9.6 KiB
Markdown
221 lines
9.6 KiB
Markdown
# Presentations
|
|
|
|
Optional per device, off by default. `PRESENTATIONS_ENABLED=true` in
|
|
`/etc/ekklesia-classroom/device.conf` puts a **Presentations** button on
|
|
the bar and starts the importer; nothing else in the room changes.
|
|
|
|
It depends on nothing else. A machine may have Presentations with no
|
|
Wonder Ink, no drive, no Parent Call, on Wi-Fi or a cable, as a laptop or
|
|
a tower. The Bible study laptop is the first installation.
|
|
|
|
## What was measured before any of this was designed
|
|
|
|
The brief was to use existing presentation software. So the existing
|
|
presentation software was tried first, on Debian 13 in the Plasma lab,
|
|
against a ten-slide deck in both PPTX and PDF. **The critical
|
|
requirement is that a teacher who ends or cancels a slideshow lands back
|
|
in the library and never in an editor.**
|
|
|
|
| Tried | What it actually did |
|
|
| --- | --- |
|
|
| `soffice --show deck.pptx` | Starts a real fullscreen slideshow — `app_id=libreoffice-impress`, `"Presenting: session7"`, `fullscreen=1`. But it needs `XDG_SESSION_TYPE=wayland` **and** `libreoffice-gtk3`/`-qt6`, or it dies with *"Failed to open display"*; it shows the LibreOffice splash on the way up; and a **"Tip of the Day: 1/225"** dialog opened on top of the slideshow on first run. Ending the show leaves the Impress editor. |
|
|
| `okular --presentation deck.pdf` | Opens **three** windows: the presentation, the ordinary Okular document window behind it, and an **"Information — Okular"** dialog. The full viewer UI — File, Open, Settings — sits behind the slides. |
|
|
| `zathura deck.pdf` | Opens windowed, not fullscreen. A document reader, not a presenter. |
|
|
| `pdfpc deck.pdf` | Single fullscreen window, the closest of the four. With `--single-screen` it came up windowed, and in the lab it did not respond to Right, Escape or `q`. A presenter-console tool with notes and a timer, and another dependency. |
|
|
|
|
None of them returns a teacher to a library, because none of them knows
|
|
there is one. Every one of them leaves an application on the screen that
|
|
can open any file on the machine.
|
|
|
|
### What was chosen instead
|
|
|
|
**LibreOffice converts once, headless, at import. Poppler renders the
|
|
pages. The classroom shows the pictures.**
|
|
|
|
```
|
|
Session 7.pptx --soffice --headless --convert-to pdf--> slides.pdf
|
|
slides.pdf --pdftoppm -png -scale-to-x 1920--------> page-001.png ...
|
|
```
|
|
|
|
Measured on the same deck:
|
|
|
|
| Step | Time |
|
|
| --- | --- |
|
|
| PPTX → PDF, ten slides | 0.34 s |
|
|
| All ten pages → PNG | 0.03 s |
|
|
| One page at 1920px | 0.10 s |
|
|
|
|
Fonts embed correctly (`BAAAAA+LiberationSans`, subset, embedded) and the
|
|
text survives, which is where a title comes from when the filename is a
|
|
hash.
|
|
|
|
This is not a new renderer. LibreOffice does exactly the rendering
|
|
Impress would have done live — it is the same engine — and poppler does
|
|
what every PDF viewer does. The classroom's own code displays a PNG.
|
|
What it buys:
|
|
|
|
* **A teacher can never reach an editor**, because no editor ever runs
|
|
interactively. `soffice` runs once, with no window, at import.
|
|
* **Escape is ours.** The presenter is a window of the library's own
|
|
process, so ending a slideshow is the library raising itself, not a
|
|
second program being asked to exit.
|
|
* **Presenting is instant.** The pictures already exist; there is no
|
|
LibreOffice to start in front of a room.
|
|
* **PDF is first class.** A session exported from Google Slides as PDF
|
|
skips the conversion entirely and keeps exactly the appearance Google
|
|
gave it. PPT and PPTX join that path rather than having one of their
|
|
own.
|
|
* **Offline by construction.** Nothing after the download touches the
|
|
network.
|
|
|
|
`libreoffice-gtk3` is deliberately *not* a dependency: nothing
|
|
interactive runs, so no UI integration package is needed.
|
|
|
|
## Where things are
|
|
|
|
```
|
|
~/Downloads/ the teacher's own download. NEVER touched.
|
|
~/Downloads/Wonder Ink/ Wonder Ink's worksheets. NEVER touched.
|
|
|
|
~/.local/share/ekklesia-classroom/presentations/
|
|
imported.json which downloads have been dealt with
|
|
<id>/
|
|
presentation.json title, pages, thumbnail slide, timers
|
|
Session 7 - Romans.pptx the managed copy, original name kept
|
|
slides.pdf what everything is rendered from
|
|
pages/page-001.png ... one per slide, 1920px wide
|
|
thumbnail.png the card picture, from the chosen slide
|
|
```
|
|
|
|
## Importing
|
|
|
|
`ekklesia-classroom-presentations.service` (user) runs
|
|
`classroom-presentation-import`, which looks at `~/Downloads` every four
|
|
seconds. Polling, not inotify: a teacher waits the same few seconds
|
|
either way, and this cannot miss an event across a restart.
|
|
|
|
A file is imported when **all** of these hold:
|
|
|
|
* its extension is `.pdf`, `.pptx` or `.ppt`;
|
|
* it is not inside the `Wonder Ink` directory;
|
|
* there is no `.crdownload`, `.part`, `.partial`, `.download` or `.tmp`
|
|
sibling — Chrome writes `Session 7.pptx.crdownload` and renames it when
|
|
the transfer finishes, so that sibling is the authoritative "still
|
|
arriving";
|
|
* it has not changed for six seconds, which catches a copy from a USB
|
|
stick that has no `.crdownload` to go by;
|
|
* it is not empty; and
|
|
* its fingerprint — path, size, modification time — is not already in
|
|
`imported.json`.
|
|
|
|
Two downloads of the same name are two presentations. The second gets
|
|
`(2)` after its title; neither overwrites the other.
|
|
|
|
**Crash safety.** The metadata is written saying `importing` *before* any
|
|
work, and the fingerprint is recorded at the same moment so a file that
|
|
crashes the converter cannot be retried forever. On startup the importer
|
|
sweeps every directory still saying `importing`, deletes it and forgets
|
|
its fingerprint, so an import interrupted by a reboot simply happens
|
|
again. A presentation becomes visible to a teacher only once every file
|
|
it needs is on disk.
|
|
|
|
A file that cannot be converted gets a card saying so, offering only
|
|
**Remove**. The teacher's download is untouched, which is what the card
|
|
says.
|
|
|
|
## The three things kept apart
|
|
|
|
This is the part most worth not breaking.
|
|
|
|
| | Changed by | Never changed by |
|
|
| --- | --- | --- |
|
|
| **Library thumbnail** | *Use this slide as the picture* in Quick Look | presenting, importing |
|
|
| **Starting slide** | nothing — always slide 1 | choosing a thumbnail |
|
|
| **Retention** | a slide actually reaching the screen | Quick Look, opening the library, choosing a thumbnail, preview generation, a viewer that failed to start |
|
|
|
|
The first slide of a Bible study session is a generic opening shared by
|
|
every session; the one that names the session is usually the second. So
|
|
the thumbnail defaults to slide 1 and Quick Look exists to change it, and
|
|
changing it must not be mistaken for having presented anything.
|
|
|
|
`Presenter.show_page` calls `mark_presented()` at the moment the first
|
|
slide is drawn, and not before. Pressing **Present** is an intention; a
|
|
picture on the screen is a presentation.
|
|
|
|
## Retention
|
|
|
|
| State | Kept |
|
|
| --- | --- |
|
|
| Never presented | 180 days from import |
|
|
| Presented | 30 days from the **last** presentation |
|
|
|
|
Every presentation restarts the thirty days. No teacher-facing setting.
|
|
|
|
The cleanup runs hourly in the importer and:
|
|
|
|
* never removes a presentation whose id is in
|
|
`$XDG_RUNTIME_DIR/ekklesia-classroom-presenting` — the lock the
|
|
presenter holds while a slide is on the screen. In the runtime
|
|
directory so a crash cannot make a presentation permanently
|
|
un-removable;
|
|
* only ever removes a directory under the library root;
|
|
* never touches `~/Downloads`, and therefore never a Wonder Ink
|
|
worksheet;
|
|
* tolerates a directory that is already half gone.
|
|
|
|
## The presenter
|
|
|
|
A fullscreen `Gtk.Window` in the library's own process showing one
|
|
pre-rendered page at a time, letterboxed — never cropped, never
|
|
stretched.
|
|
|
|
| Key | Does |
|
|
| --- | --- |
|
|
| Space, →, ↓, Page Down, Return, `n` | Next slide |
|
|
| ←, ↑, Page Up, Backspace, `p` | Previous slide |
|
|
| Home / End | First / last slide |
|
|
| Escape, `q`, F5 | Finish, back to the library |
|
|
|
|
Page Up and Page Down are what the clicker in the cupboard sends.
|
|
|
|
Going past the last slide finishes, rather than showing a black "click to
|
|
exit" slide.
|
|
|
|
**Fullscreen is re-asserted, not assumed.** Measured in the lab: focusing
|
|
another window on the same workspace dropped the slideshow to half the
|
|
screen with the library beside it. `window-state-event` puts it back for
|
|
as long as the presentation is running, and stops the moment Escape is
|
|
pressed so it can never fight the teacher's way out.
|
|
|
|
## Fonts
|
|
|
|
The pastor's material comes from Google Slides. These are all in Debian
|
|
main and install without a question:
|
|
|
|
| Package | Covers |
|
|
| --- | --- |
|
|
| `fonts-liberation2` | Arial, Times New Roman, Courier New — metric compatible |
|
|
| `fonts-crosextra-carlito` | Calibri |
|
|
| `fonts-crosextra-caladea` | Cambria |
|
|
| `fonts-croscore` | the same three under their Chrome OS names |
|
|
| `fonts-liberation-sans-narrow` | Arial Narrow |
|
|
| `fonts-roboto`, `fonts-open-sans`, `fonts-lato`, `fonts-montserrat` | the web fonts Google Slides offers |
|
|
| `fonts-urw-base35` | the PostScript standard 35 |
|
|
|
|
`ttf-mscorefonts-installer` is deliberately **absent**. It is in contrib,
|
|
it downloads from a third party at install time, and it shows an EULA
|
|
prompt — which an unattended classroom upgrade cannot answer.
|
|
|
|
## Checking a machine
|
|
|
|
```
|
|
classroom-presentation-import --status what the library holds
|
|
classroom-presentation-import --once one pass, then stop
|
|
classroom-presentation-import --cleanup apply retention now
|
|
classroom-manual --features which manual pages this device shows
|
|
```
|
|
|
|
`--status` prints titles, slide counts, the chosen thumbnail slide, both
|
|
timers and the expiry date. It is the fastest way to answer "why has this
|
|
gone" and "why has this not appeared".
|