#!/usr/bin/env python3 """Match the classroom's panel to the machine it is on. There is exactly one thing about the bar that depends on hardware: a room with no optical drive should not be offered a disc player. This edits the one marked line in the installed layout, and nothing else. It writes the *layout*, not the running panel. Editing plasma-org.kde.plasma.desktop-appletsrc underneath a live plasmashell was tried and it destroyed the panel: the shell owns that file and rewrites it, so an edit races with it. The layout is a file the package owns and the shell only reads, and classroom-desktop-reset makes the shell read it again at the next login. DVD_ENABLED is gone. A drive is something the machine can be asked about, and asking is more reliable than remembering to edit a file when a computer moves between rooms. """ import glob import os import re import sys LAYOUT = ( "/usr/share/plasma/look-and-feel/org.ekklesia.classroom.desktop" "/contents/layouts/org.kde.plasma.desktop-layout.js" ) MARKER = "/* CLASSROOM-DVD-LAUNCHER */" # The kernel names optical drives sr0, sr1, ... regardless of bus. DRIVE_GLOB = "/dev/sr[0-9]*" def has_optical_drive(): return bool(glob.glob(DRIVE_GLOB)) def rewrite(text, wanted): """Comment the DVD launcher in or out, idempotently.""" line = re.compile( r"^(\s*)(//\s*)?(" + re.escape(MARKER) + r'\s*"applications:ekklesia-dvd\.desktop")', re.M, ) def swap(match): indent, _, body = match.groups() return f"{indent}{'' if wanted else '// '}{body}" return line.sub(swap, text) def main(): path = sys.argv[1] if len(sys.argv) > 1 else LAYOUT try: with open(path, "r", encoding="utf-8") as handle: before = handle.read() except OSError as error: print(f"classroom-desktop-layout: {error}", file=sys.stderr) return 0 if MARKER not in before: print("classroom-desktop-layout: no DVD marker in the layout", file=sys.stderr) return 0 wanted = has_optical_drive() after = rewrite(before, wanted) if after == before: print(f"classroom-desktop-layout: DVD launcher already " f"{'present' if wanted else 'absent'}") return 0 # Replace the file rather than edit in place, so a full disk or a # crash leaves the old layout intact rather than half of a new one. temporary = f"{path}.new" try: with open(temporary, "w", encoding="utf-8") as handle: handle.write(after) os.replace(temporary, path) except OSError as error: print(f"classroom-desktop-layout: {error}", file=sys.stderr) return 1 print(f"classroom-desktop-layout: DVD launcher " f"{'added' if wanted else 'removed'}") return 0 if __name__ == "__main__": sys.exit(main())