diff --git a/HMS-Mac-Install.command b/HMS-Mac-Install.command index 7c505f3..c9ec32e 100755 --- a/HMS-Mac-Install.command +++ b/HMS-Mac-Install.command @@ -1,38 +1,35 @@ #!/bin/bash # HMS MediaEngine – macOS-Installation per Doppelklick (Finder) -# Ablauf: brew pruefen/installieren -> python3+tk pruefen -> -# GUI-Installer starten (Passwort-Dialog kommt von macOS selbst). -# Kein Tippen im Terminal noetig: Passwort-Eingabe laeuft ueber den -# nativen macOS-Dialog (osascript administrator privileges). +# Ablauf: Homebrew pruefen -> Installationsumfang waehlen (Festplatte!) +# -> installieren -> Cache-Aufraeumen anbieten -> GUI-Installer. +# Alle Abfragen kommen als native macOS-Fenster (Buttons), das +# Administrator-Passwort fragt macOS selbst ab - kein Terminal-Tippen. cd "$(dirname "$0")" echo "==================================================" echo " HMS MediaEngine – Installation" -echo " (Dieses Fenster zeigt nur den Fortschritt an –" -echo " alle Abfragen kommen als eigene macOS-Fenster)" +echo " Fortschritt siehst du hier; alle Abfragen kommen als" +echo " eigene macOS-Fenster mit Klick-Buttons." echo "==================================================" echo "" -# Dialog mit Buttons: gibt nur bei 'Weiter' true zurueck eingabe() { local antwort antwort=$(osascript -e 'display alert "'$1'" message "'$2'" buttons {"Abbrechen","Weiter"} default button "Weiter" as informational' 2>/dev/null) echo "$antwort" | grep -q "Weiter" } -# --- Homebrew --- +# --- 1) Homebrew --- BREW="" for p in /opt/homebrew/bin/brew /usr/local/bin/brew; do if [ -x "$p" ]; then BREW="$p"; break; fi done if [ -z "$BREW" ]; then - if eingabe "Homebrew installieren?" "HMS MediaEngine benoetigt Homebrew (Paketmanager fuer macOS). Die Installation dauert einige Minuten – danach geht es automatisch weiter. Das Passwort wird im naechsten Fenster von macOS abgefragt."; then - echo "" - echo ">> Installiere Homebrew (macOS fragt nach deinem Administrator-Passwort)..." - osascript -e 'do shell script "NONINTERACTIVE=1 /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" with administrator privileges with prompt "Homebrew fuer HMS MediaEngine installieren"' >/dev/null 2>&1 - if [ $? -ne 0 ]; then - osascript -e 'display alert "Homebrew-Installation fehlgeschlagen" message "Bitte das Fenster nochmal versuchen oder Meldung an den Support schicken." as critical' >/dev/null 2>&1 + if eingabe "Homebrew installieren?" "HMS MediaEngine benoetigt Homebrew (Paketmanager fuer macOS). Die Installation dauert einige Minuten. Dein Administrator-Passwort wird im naechsten Fenster von macOS abgefragt."; then + echo ">> Installiere Homebrew (macOS fragt nach deinem Passwort)..." + if ! osascript -e 'do shell script "NONINTERACTIVE=1 /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" with administrator privileges with prompt "Homebrew fuer HMS MediaEngine installieren"' >/dev/null 2>&1; then + osascript -e 'display alert "Homebrew-Installation fehlgeschlagen" message "Bitte erneut versuchen oder die Meldung an den Support schicken." as critical' >/dev/null 2>&1 exit 1 fi BREW=/opt/homebrew/bin/brew @@ -42,35 +39,46 @@ if [ -z "$BREW" ]; then exit 1 fi fi +echo ">> Homebrew: $BREW" -echo ">> Homebrew gefunden: $BREW" +# --- 2) Installationsumfang (Festplatte) waehlen --- +VARIANTE=$(osascript -e 'display alert "Welcher Installationsumfang?" message "Vollstaendig: alle 21 Effekte. GStreamer belegt dann ca. 1,5-2,5 GB." & linefeed & linefeed & "Kompakt: 15 Effekte, belegt nur ca. 0,5-1 GB. Verzichtet auf Blur/Schaerfen, Solarize, Brennen, Dilate und Exclusion." & linefeed & linefeed & "Beide Varianten spielen alle Videos und Bilder vollstaendig ab - der Unterschied liegt nur in 6 wenigen Effekten." buttons {"Abbrechen","Kompakt","Vollstaendig"} default button "Vollstaendig" as informational' 2>/dev/null) +case "$VARIANTE" in + *Kompakt*) + PKGS="python@3.12 python-tk gstreamer gst-plugins-base gst-plugins-good gst-libav pygobject" + echo ">> Gewaehlt: Kompakt (spart ca. 1-1,5 GB)" + ;; + *Abbrechen*|"") + exit 1 + ;; + *) + PKGS="python@3.12 python-tk gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav pygobject" + echo ">> Gewaehlt: Vollstaendig (alle Effekte)" + ;; +esac -# --- Python 3.12 + tkinter --- -if ! "$BREW" list --versions python-tk >/dev/null 2>&1; then - if eingabe "Python-Komponenten installieren?" "python@3.12 mit tkinter (grafische Oberflaeche) wird installiert."; then - echo "" - echo ">> Installiere Python + tkinter..." - "$BREW" install python@3.12 python-tk - fi +# --- 3) Installation --- +echo "" +echo ">> Installiere Komponenten per Homebrew (dauert einige Minuten)..." +if ! "$BREW" install $PKGS; then + osascript -e 'display alert "Problem bei der Installation" message "Homebrew meldete einen Fehler. Der grafische Installer prueft jetzt, was trotzdem angekommen ist." as warning' >/dev/null 2>&1 fi -# --- GStreamer --- -if ! "$BREW" list --versions gstreamer >/dev/null 2>&1; then - if eingabe "GStreamer installieren?" "GStreamer mit allen Video-/Audio-Plugins wird installiert (ca. 5-10 Minuten, je nach Internet)."; then - echo "" - echo ">> Installiere GStreamer + Plugins..." - "$BREW" install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav pygobject - fi +# --- 4) Homebrew-Cache aufräumen (optional, gibt 0,5-2 GB frei) --- +if osascript -e 'display alert "Homebrew-Cache aufraeumen?" message "Loescht die heruntergeladenen Installationspakete und gibt etwa 0,5-2 GB Festplatte frei. Die Installation selbst bleibt unveraendert." buttons {"Nein","Ja"} default button "Ja" as informational' 2>/dev/null | grep -q "Ja"; then + echo ">> Raeume Homebrew-Cache auf..." + "$BREW" cleanup --prune=all >/dev/null 2>&1 + echo ">> Cache freigegeben." fi -# --- GUI-Installer starten --- +# --- 5) GUI-Installer starten (verifiziert und startet die App) --- PY=/opt/homebrew/bin/python3 -if [ ! -x "$PY" ]; then PY=/usr/local/bin/python3; fi -if [ ! -x "$PY" ]; then PY=python3; fi +[ -x "$PY" ] || PY=/usr/local/bin/python3 +[ -x "$PY" ] || PY=python3 echo "" echo ">> Starte grafischen Installer (Fenster oeffnet sich)..." "$PY" installer_gui.py echo "" -echo "Fertig. Ab jetzt genuegt: 'HMS MediaEngine.app' doppelklicken." +echo "Fertig. Ab jetzt genuegt: HMS MediaEngine.app doppelklicken." diff --git a/installer_gui.py b/installer_gui.py index 00b409f..347af61 100644 --- a/installer_gui.py +++ b/installer_gui.py @@ -34,11 +34,19 @@ IS_WIN = sys.platform == "win32" GST_MSI = ("https://gstreamer.freedesktop.org/data/pkg/windows/" "1.28.4/msvc/gstreamer-1.0-msvc-x86_64-1.28.4.msi") PY_EXE = "https://www.python.org/ftp/python/3.13.2/python-3.13.2-amd64.exe" -BREW_PKGS = [ +BREW_PKGS_FULL = [ "python@3.12", "python-tk", "gstreamer", "gst-plugins-base", "gst-plugins-good", "gst-plugins-bad", "gst-plugins-ugly", "gst-libav", "pygobject", ] +# Kompakt: ohne gst-plugins-bad/ugly. Spart ca. 1-1,5 GB; Effekte +# sinken von 21 auf 15 (Blur/Schaerfen/Solarize/Burn/Dilate/Exclusion +# stecken in gst-plugins-bad). Videowiedergabe (libav), Compositor +# und 15 Effekte bleiben voll nutzbar. +BREW_PKGS_COMPACT = [ + "python@3.12", "python-tk", "gstreamer", "gst-plugins-base", + "gst-plugins-good", "gst-libav", "pygobject", +] def brew_path() -> str | None: @@ -128,6 +136,19 @@ class InstallerApp: tk.Label(self.root, textvariable=self.status_var, bg="#16181d", fg="#c8ccd4").pack(fill="x", padx=16) + var_row = tk.Frame(self.root, bg="#16181d") + var_row.pack(fill="x", padx=16, pady=(0, 2)) + tk.Label(var_row, text="Installationsumfang:", + bg="#16181d", fg="#8a8f9a").pack(side="left") + self.variant = tk.StringVar( + value="Vollständig (alle 21 Effekte)") + ttk.Combobox( + var_row, textvariable=self.variant, state="readonly", + width=38, values=( + "Vollständig (alle 21 Effekte)", + "Kompakt (15 Effekte, spart ca. 1,5 GB)") + ).pack(side="left", padx=8) + self.bar = ttk.Progressbar(self.root, mode="determinate", length=640) self.bar.pack(fill="x", padx=16, pady=8) @@ -212,16 +233,20 @@ class InstallerApp: def start_install(self): self.install_btn.config(state="disabled") - threading.Thread(target=self._install_worker, daemon=True).start() + variant = self.variant.get() # tk-Variable im Hauptthread lesen + threading.Thread(target=self._install_worker, args=(variant,), + daemon=True).start() - def _install_worker(self): + def _install_worker(self, variant: str): try: if IS_MAC: - self._install_mac() + self._install_mac(variant) elif IS_WIN: self._install_win() self.on_log("") self.on_log("Installation abgeschlossen.") + if IS_MAC: + self.root.after(0, self._offer_cleanup) self.on_log("Falls gerade etwas installiert wurde, das Python " "betrifft: dieses Fenster einmal schließen und " "die App erneut starten.") @@ -243,7 +268,7 @@ class InstallerApp: raise RuntimeError(r.stderr.strip() or "osascript fehlgeschlagen") return r.stdout - def _install_mac(self): + def _install_mac(self, variant: str): self.on_status("macOS: Installation läuft (Passwort-Dialog folgt)…") lines = ["set -e"] brew = brew_path() @@ -259,7 +284,10 @@ class InstallerApp: 'if [ -x /opt/homebrew/bin/brew ]; then ' 'BREW=/opt/homebrew/bin/brew; ' 'else BREW=/usr/local/bin/brew; fi') - lines.append('"$BREW" install ' + " ".join(BREW_PKGS)) + pkgs = (BREW_PKGS_FULL if variant.startswith("Voll") + else BREW_PKGS_COMPACT) + self.on_log("Variante: " + variant) + lines.append('"$BREW" install ' + " ".join(pkgs)) script = "\n".join(lines) with tempfile.NamedTemporaryFile("w", suffix=".sh", delete=False) as f: @@ -300,6 +328,26 @@ class InstallerApp: "Fenster schließen und HMS-Start.vbs erneut " "doppelklicken.") + def _offer_cleanup(self): + """Homebrew-Cache aufräumen – gibt ca. 0,5-2 GB frei.""" + try: + if messagebox.askyesno( + "HMS MediaEngine", + "Homebrew-Cache jetzt aufräumen?\n\n" + "Löscht heruntergeladene Installationspakete und " + "gibt etwa 0,5-2 GB Festplatte frei.\n" + "Die Installation selbst bleibt unverändert.", + parent=self.root): + brew = brew_path() or "/opt/homebrew/bin/brew" + self.on_log("Räume Homebrew-Cache auf…") + r = subprocess.run([brew, "cleanup", "--prune=all"], + capture_output=True, timeout=600) + self.on_log( + "Cache aufgeräumt." if r.returncode == 0 + else f"cleanup endete mit Code {r.returncode}") + except Exception as e: # noqa: BLE001 + self.on_log(f"cleanup übersprungen: {e}") + # ---------- Start ---------- def start_engine(self):