#!/usr/bin/env python3 """Classroom DVD control. Discs are never played automatically. Inserting a disc only produces a notification and changes the dock icon; playback always starts from a deliberate press of the DVD button. """ import argparse import os import shutil import subprocess import sys sys.path.insert(0, "/usr/local/lib/ekklesia-classroom") sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "lib"), ) import classroom_optical as optical # noqa: E402 from classroom_vlc import PLAYER # noqa: E402 SESSION_TOOL = "/usr/local/bin/classroom-dvd-session" def notify(title, message, urgency="normal"): try: subprocess.Popen( [ "notify-send", "--app-name=DVD", f"--urgency={urgency}", "--", title, message, ], start_new_session=True, ) except OSError: print(f"{title}: {message}", file=sys.stderr) def play(device): """Hand the disc to DVD mode. 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. Started directly, with nothing arranging windows on the way. A second session cannot happen — the session takes an exclusive lock on dvd.lock and exits if it cannot get it — and bringing an existing one back to the front is the panel's job, not this command's. That is what replaced the window helper. """ if shutil.which(PLAYER) is None: notify( "DVD", "The DVD player is not installed on this classroom computer.", ) return 1 subprocess.Popen([SESSION_TOOL], start_new_session=True) return 0 def action_toggle(force_play=False): device = optical.default_device() if device is None: notify("DVD", "No DVD drive is connected to this classroom computer.") return 1 status = optical.drive_status(device) if status == optical.CDS_DISC_OK: return play(device) if status == optical.CDS_DRIVE_NOT_READY: notify("DVD", "Reading the disc. Please try again in a moment.") return 1 if status == optical.CDS_TRAY_OPEN: notify("DVD", "The disc tray is open. Insert a disc to get started.") return 1 if force_play: return play(device) notify("DVD", "No disc is in the drive. Insert a disc to get started.") return 1 def action_status(): device = optical.default_device() if device is None: print("drive: none") return 1 status = optical.drive_status(device) print(f"drive: {device}") print(f"status: {optical.describe(status)}") print(f"player: {shutil.which(PLAYER) or 'not installed'}") if status == optical.CDS_DISC_OK: print(f"disc: {optical.disc_status(device)}") return 0 return 1 def action_eject(): device = optical.default_device() if device is None: notify("DVD", "No DVD drive is connected to this classroom computer.") return 1 if not optical.eject(device): notify("DVD", "The disc could not be ejected. It may still be playing.") return 1 return 0 def main(): parser = argparse.ArgumentParser(description="Classroom DVD control.") subparsers = parser.add_subparsers(dest="action", required=True) subparsers.add_parser("toggle", help="Dock button behaviour") subparsers.add_parser("play", help="Start playback even if the drive is unsure") subparsers.add_parser("status", help="Report drive and disc state") subparsers.add_parser("eject", help="Open the disc tray") arguments = parser.parse_args() if arguments.action == "toggle": return action_toggle() if arguments.action == "play": return action_toggle(force_play=True) if arguments.action == "status": return action_status() return action_eject() if __name__ == "__main__": sys.exit(main())