#!/usr/bin/env python3 import os import tkinter as tk import subprocess import time import threading from threading import Timer from PIL import Image # Verzeichnisse PDF_DIR = "/var/spool/cups-pdf/ANONYMOUS" OUTPUT_DIR = "/tmp/pdf_display" # Dateien & Skalierung PRINTER_BG = os.path.join(os.path.dirname(__file__), "druckerbild.png") PRINTER_SCALE = 0.6 # z. B. 0.5 = 50% der Bildschirmhöhe # DISPLAY-Variable setzen, falls nicht vorhanden if "DISPLAY" not in os.environ: os.environ["DISPLAY"] = ":0" os.makedirs(OUTPUT_DIR, exist_ok=True) # Bildschirmgröße ermitteln def get_screen_size(): output = subprocess.check_output("xdpyinfo | grep dimensions", shell=True).decode() width, height = map(int, output.split()[1].split("x")) return width, height # Druckerbild über gesamte Breite anzeigen def display_printer(): screen_width, screen_height = get_screen_size() scaled_height = int(screen_height * PRINTER_SCALE) subprocess.Popen([ "feh", "--no-fehbg", "--borderless", "--image-bg", "#000000", "--geometry", f"{screen_width}x{scaled_height}+0+0", PRINTER_BG ]) # PDF in Bild umwandeln (erste Seite) und runterskalieren def pdf_to_image(pdf_path, breite=300): basename = os.path.basename(pdf_path).replace(".pdf", "") img_path = os.path.join(OUTPUT_DIR, f"{basename}.png") subprocess.run(["pdftoppm", "-png", "-singlefile", "-f", "1", pdf_path, img_path.replace(".png", "")]) img = Image.open(img_path) width, height = img.size new_height = int((breite / width) * height) img = img.resize((breite, new_height), Image.ANTIALIAS) img.save(img_path) return img_path # Perspektivische Verzerrung auf das Bild anwenden def distort_image(img_path): output_img = img_path.replace(".png", "_distorted.png") subprocess.run([ "convert", img_path, "-matte", "-virtual-pixel", "transparent", "-background", "none", "-wave", "5x200" , output_img ]) return output_img # PDF-Bild zentriert am unteren Rand anzeigen (skaliert) def display_image(image_path, scale=0.6): screen_width, screen_height = get_screen_size() # Bildgröße auslesen img = Image.open(image_path) img_width, img_height = img.size # Neue Größe berechnen (an Bildschirmhöhe anpassen) scaled_height = int(screen_height * scale) scale_factor = scaled_height / img_height scaled_width = int(img_width * scale_factor) # Position berechnen (zentriert, am unteren Rand) x_offset = 0 y_offset = screen_height - scaled_height # Bild mit feh anzeigen subprocess.Popen([ "feh", "-x", "-B", "#000000", "--geometry", f"{screen_width}x{scaled_height}+{x_offset}+{y_offset}", image_path ]) # PDF-Verzeichnis mit inotify überwachen def monitor_folder(): print(f"Überwache {PDF_DIR} auf neue PDFs...") # Druckerbild direkt beim Start anzeigen display_printer() process = subprocess.Popen(["inotifywait", "-m", "-e", "close_write", PDF_DIR], stdout=subprocess.PIPE) for line in process.stdout: parts = line.decode().strip().split() if len(parts) == 3 and parts[2].endswith(".pdf"): pdf_path = os.path.join(PDF_DIR, parts[2]) print(f"Neues PDF erkannt: {pdf_path}") # PDF konvertieren und anzeigen image_path = pdf_to_image(pdf_path) distorted_path = distort_image(image_path) display_image(distorted_path) # Funktion zum Herunterfahren des Rechners def shutdown_printer(): os.system("shutdown now") # Button "Drucker ausschalten" anzeigen def show_shutdown_button(): root = tk.Tk() root.title("Druckersteuerung") # Fenstergröße und Position (unten rechts) screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() window_width = 64 window_height = 64 x_position = screen_width - window_width - 10 y_position = screen_height - window_height - 10 root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}") # Fenster ohne Rahmen und transparent root.overrideredirect(True) # Entfernt den Fensterrahmen root.attributes("-topmost", True) # Immer im Vordergrund root.attributes("-alpha", 0.9) root.configure(bg="black") # Icon laden icon_path = os.path.join(os.path.dirname(__file__), "poweroff.png") icon = tk.PhotoImage(file=icon_path) # Button mit Icon erstellen button = tk.Button(root, image=icon, command=shutdown_printer, bg="black", width=icon.width(), height=icon.height(), borderwidth=0) button.image = icon # Referenz speichern, damit das Bild nicht vom Garbage Collector entfernt wird button.pack(expand=True, fill="both", padx=0, pady=0) # GUI starten root.mainloop() def start_monitor_thread(): # Funktion, um die Überwachung in einem separaten Thread zu starten monitor_thread = threading.Thread(target=monitor_folder, daemon=True) monitor_thread.start() if __name__ == "__main__": start_monitor_thread() show_shutdown_button()