Compare commits
6
Commits
a4ba6c296e
...
v2.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61b38fe6b8 | ||
|
|
cf6b6733e4 | ||
|
|
5f93be4325 | ||
|
|
e655cbceea | ||
|
|
1acd08934e | ||
|
|
874d6454ec |
@@ -1,20 +1,18 @@
|
|||||||
# Playtube
|
# Playtube
|
||||||
|
|
||||||
Eigenstaendige Desktop-App für YouTube & YouTube Music (kein Browser-Fenster, keine
|
Eigenständige Desktop-App für YouTube & YouTube Music (kein Browser-Fenster, keine
|
||||||
Erweiterung) mit:
|
Erweiterung) mit:
|
||||||
|
|
||||||
- **Zwei Tabs** – YouTube und YouTube Music laufen parallel, Musik spielt im
|
- **Zwei Tabs** – YouTube und YouTube Music laufen parallel, Musik spielt im
|
||||||
Hintergrund weiter wenn du zu Videos wechselst.
|
Hintergrund weiter wenn du zu Videos wechselst.
|
||||||
- **Login/Premium** – eigenes, persistentes Profil (`%APPDATA%\Playtube`, im
|
- **Login/Premium** – eigenes, persistentes Profil (`%APPDATA%\Playtube`), einmal bei
|
||||||
Entwicklungsmodus `%APPDATA%\PlaytubeDev` – bewusst getrennt, damit sich lokale
|
Google anmelden reicht für beide Dienste.
|
||||||
Test-Builds nie mit einer installierten Version in die Quere kommen), einmal bei
|
|
||||||
Google anmelden reicht fuer beide Dienste.
|
|
||||||
- **Discord Rich Presence** – zeigt Titel, Kanal/Interpret, Fortschrittsbalken und
|
- **Discord Rich Presence** – zeigt Titel, Kanal/Interpret, Fortschrittsbalken und
|
||||||
einen Link-Button in deinem Discord-Profil, sobald etwas laeuft.
|
einen Link-Button in deinem Discord-Profil, sobald etwas läuft.
|
||||||
- **System-Tray** – Fenster schliessen minimiert nur (Musik laeuft weiter), Rechtsklick
|
- **System-Tray** – Fenster schliessen minimiert nur (Musik läuft weiter), Rechtsklick
|
||||||
aufs Tray-Icon zum Beenden, Play/Pause/Skip direkt aus dem Menue.
|
aufs Tray-Icon zum Beenden, Play/Pause/Skip direkt aus dem Menü.
|
||||||
- **Eigener Name** – erscheint als "Playtube" im Taskmanager, Fenstertitel, Alt-Tab
|
- **Eigener Name** – erscheint als "Playtube" im Taskmanager, Fenstertitel, Alt-Tab
|
||||||
und (nach dem Packaging, siehe unten) im Lautstaerkemixer statt als "python".
|
und (nach dem Packaging, siehe unten) im Lautstärkemixer statt als "python".
|
||||||
|
|
||||||
## Installation (Windows)
|
## Installation (Windows)
|
||||||
|
|
||||||
@@ -22,20 +20,20 @@ Lade auf der [Releases-Seite](https://github.com/fojadrachi/Playtube/releases)
|
|||||||
`Playtube-Setup-vX.Y.Z.exe` herunter und starte sie. Der Installer
|
`Playtube-Setup-vX.Y.Z.exe` herunter und starte sie. Der Installer
|
||||||
|
|
||||||
- installiert Playtube **pro Benutzer** nach `%LOCALAPPDATA%\Programs\Playtube` (keine
|
- installiert Playtube **pro Benutzer** nach `%LOCALAPPDATA%\Programs\Playtube` (keine
|
||||||
Admin-Rechte noetig) und legt Startmenue-Eintrag (optional Desktop-Verknuepfung) an,
|
Admin-Rechte nötig) und legt Startmenü-Eintrag (optional Desktop-Verknüpfung) an,
|
||||||
- ersetzt bei jeder spaeteren Ausfuehrung die vorhandene Installation **an Ort und
|
- ersetzt bei jeder späteren Ausführung die vorhandene Installation **an Ort und
|
||||||
Stelle** (feste Installer-ID) - es gibt also immer genau EINE installierte Version, nie
|
Stelle** (feste Installer-ID) - es gibt also immer genau EINE installierte Version, nie
|
||||||
mehrere nebeneinander,
|
mehrere nebeneinander,
|
||||||
- beendet dafuer ein noch laufendes Playtube selbst und raeumt den alten Programmordner
|
- beendet dafür ein noch laufendes Playtube selbst und räumt den alten Programmordner
|
||||||
auf, damit keine Reste alter Versionen uebrig bleiben,
|
auf, damit keine Reste alter Versionen übrig bleiben,
|
||||||
- laesst Login und Einstellungen (`%APPDATA%\Playtube`) unangetastet; beim Deinstallieren
|
- lässt Login und Einstellungen (`%APPDATA%\Playtube`) unangetastet; beim Deinstallieren
|
||||||
ueber "Apps & Features" wird gefragt, ob sie mitgeloescht werden sollen.
|
über "Apps & Features" wird gefragt, ob sie mitgelöscht werden sollen.
|
||||||
|
|
||||||
Ab dann aktualisiert sich Playtube selbst (siehe "Automatische Updates") - die
|
Ab dann aktualisiert sich Playtube selbst (siehe "Automatische Updates") - die
|
||||||
Setup-Datei wird dafuer nicht erneut von Hand gebraucht. Das ZIP-Paket
|
Setup-Datei wird dafür nicht erneut von Hand gebraucht. Das ZIP-Paket
|
||||||
(`Playtube-vX.Y.Z-win64.zip`) bleibt als portable Variante ohne Installation erhalten;
|
(`Playtube-vX.Y.Z-win64.zip`) bleibt als portable Variante ohne Installation erhalten;
|
||||||
Playtube bietet einer portablen Kopie beim naechsten Update automatisch an, in die
|
Playtube bietet einer portablen Kopie beim nächsten Update automatisch an, in die
|
||||||
regulaere Installation zu wechseln (danach kann der alte Ordner geloescht werden).
|
reguläre Installation zu wechseln (danach kann der alte Ordner gelöscht werden).
|
||||||
|
|
||||||
## Schnellstart (Entwicklung)
|
## Schnellstart (Entwicklung)
|
||||||
|
|
||||||
@@ -52,24 +50,24 @@ Login bleibt danach dauerhaft gespeichert.
|
|||||||
## Discord Rich Presence einrichten
|
## Discord Rich Presence einrichten
|
||||||
|
|
||||||
Die Client-ID ist bereits in `config.json` eingetragen (`discord.client_id`). Falls du
|
Die Client-ID ist bereits in `config.json` eingetragen (`discord.client_id`). Falls du
|
||||||
sie aendern oder eine eigene Anwendung nutzen willst:
|
sie ändern oder eine eigene Anwendung nutzen willst:
|
||||||
|
|
||||||
1. Auf https://discord.com/developers/applications eine neue Application anlegen.
|
1. Auf https://discord.com/developers/applications eine neue Application anlegen.
|
||||||
2. Die **Application ID** in `config.json` unter `discord.client_id` eintragen.
|
2. Die **Application ID** in `config.json` unter `discord.client_id` eintragen.
|
||||||
3. Optional, fuer eigene Icons: unter *Rich Presence → Art Assets* zwei Bilder mit den
|
3. Optional, für eigene Icons: unter *Rich Presence → Art Assets* zwei Bilder mit den
|
||||||
exakten Schluesseln `youtube_logo` und `music_logo` hochladen (Playtube nutzt genau
|
exakten Schlüsseln `youtube_logo` und `music_logo` hochladen (Playtube nutzt genau
|
||||||
diese Keys automatisch). Ohne hochgeladene Assets funktioniert die Presence trotzdem,
|
diese Keys automatisch). Ohne hochgeladene Assets funktioniert die Presence trotzdem,
|
||||||
nur ohne Bild.
|
nur ohne Bild.
|
||||||
4. Discord muss auf demselben Rechner laufen, damit die Presence angezeigt wird.
|
4. Discord muss auf demselben Rechner laufen, damit die Presence angezeigt wird.
|
||||||
|
|
||||||
In `config.json` lassen sich zudem `update_interval_seconds` (Mindestabstand zwischen
|
In `config.json` lassen sich zudem `update_interval_seconds` (Mindestabstand zwischen
|
||||||
Updates) und `show_idle_presence` (Status anzeigen, wenn gerade nichts laeuft) anpassen.
|
Updates) und `show_idle_presence` (Status anzeigen, wenn gerade nichts läuft) anpassen.
|
||||||
|
|
||||||
## App als eigenstaendige Playtube.exe packen
|
## App als eigenständige Playtube.exe packen
|
||||||
|
|
||||||
Fuer die volle Taskmanager-/Audiomixer-Markierung wird die App als eigene .exe gebaut
|
Für die volle Taskmanager-/Audiomixer-Markierung wird die App als eigene .exe gebaut
|
||||||
(ein via `python main.py` gestarteter Prozess heisst in Windows immer "python.exe" -
|
(ein via `python main.py` gestarteter Prozess heisst in Windows immer "python.exe" -
|
||||||
nur eine kompilierte .exe mit eigenem Namen und eigener Versionsinfo kann das aendern):
|
nur eine kompilierte .exe mit eigenem Namen und eigener Versionsinfo kann das ändern):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.venv\Scripts\pip install pyinstaller
|
.venv\Scripts\pip install pyinstaller
|
||||||
@@ -80,61 +78,61 @@ Ergebnis liegt danach unter `dist\Playtube\Playtube.exe`. Ist
|
|||||||
[Inno Setup 6](https://jrsoftware.org/isinfo.php) installiert
|
[Inno Setup 6](https://jrsoftware.org/isinfo.php) installiert
|
||||||
(`winget install --id JRSoftware.InnoSetup -e`), baut das Skript daraus ausserdem den
|
(`winget install --id JRSoftware.InnoSetup -e`), baut das Skript daraus ausserdem den
|
||||||
Installer `dist\installer\Playtube-Setup-vX.Y.Z.exe` (Skript:
|
Installer `dist\installer\Playtube-Setup-vX.Y.Z.exe` (Skript:
|
||||||
[packaging/playtube.iss](packaging/playtube.iss); mit `-SkipInstaller` ueberspringbar).
|
[packaging/playtube.iss](packaging/playtube.iss); mit `-SkipInstaller` überspringbar).
|
||||||
Eine portable, nicht per Setup installierte `.exe` legt beim ersten Start automatisch eine
|
Eine portable, nicht per Setup installierte `.exe` legt beim ersten Start automatisch eine
|
||||||
Verknuepfung im Windows-Startmenue an - eine per Setup installierte Kopie hat den
|
Verknüpfung im Windows-Startmenü an - eine per Setup installierte Kopie hat den
|
||||||
Eintrag bereits vom Installer.
|
Eintrag bereits vom Installer.
|
||||||
|
|
||||||
Das Build-Skript benennt
|
Das Build-Skript benennt
|
||||||
zusaetzlich den QtWebEngine-Hilfsprozess (der den eigentlichen Ton ausgibt) zu
|
zusätzlich den QtWebEngine-Hilfsprozess (der den eigentlichen Ton ausgibt) zu
|
||||||
`PlaytubeHelper.exe` um, damit er im Taskmanager nicht als `QtWebEngineProcess`
|
`PlaytubeHelper.exe` um, damit er im Taskmanager nicht als `QtWebEngineProcess`
|
||||||
auftaucht. Fuer eine vollstaendige Umbenennung inkl. Icon/Versionsinfo dieses
|
auftaucht. Für eine vollständige Umbenennung inkl. Icon/Versionsinfo dieses
|
||||||
Hilfsprozesses (relevant fuer den Lautstaerkemixer) zusaetzlich
|
Hilfsprozesses (relevant für den Lautstärkemixer) zusätzlich
|
||||||
[rcedit](https://github.com/electron/rcedit/releases) als `packaging\rcedit.exe`
|
[rcedit](https://github.com/electron/rcedit/releases) als `packaging\rcedit.exe`
|
||||||
ablegen - das Skript nutzt es automatisch, wenn vorhanden. Ohne rcedit funktioniert
|
ablegen - das Skript nutzt es automatisch, wenn vorhanden. Ohne rcedit funktioniert
|
||||||
alles genauso, nur zeigt der Lautstaerkemixer fuer den Ton-Unterprozess je nach
|
alles genauso, nur zeigt der Lautstärkemixer für den Ton-Unterprozess je nach
|
||||||
Windows-Version eventuell weiterhin "QtWebEngineProcess" statt "Playtube" (rein
|
Windows-Version eventuell weiterhin "QtWebEngineProcess" statt "Playtube" (rein
|
||||||
kosmetisch - Namensgebung von Chromium-Hilfsprozessen ist ein bekanntes,
|
kosmetisch - Namensgebung von Chromium-Hilfsprozessen ist ein bekanntes,
|
||||||
Windows-versionsabhaengiges Verhalten, das selbst grosse Electron-Apps nur mit rcedit
|
Windows-versionsabhängiges Verhalten, das selbst grosse Electron-Apps nur mit rcedit
|
||||||
o.ae. umgehen).
|
o.ä. umgehen).
|
||||||
|
|
||||||
## Automatische Updates
|
## Automatische Updates
|
||||||
|
|
||||||
Playtube prueft beim Start und danach alle `updates.check_interval_hours` Stunden
|
Playtube prüft beim Start und danach alle `updates.check_interval_hours` Stunden
|
||||||
(Standard 6, im **Einstellungen-Tab** oder in `config.json` einstellbar) die
|
(Standard 6, im **Einstellungen-Tab** oder in `config.json` einstellbar) die
|
||||||
[GitHub Releases](https://github.com/fojadrachi/Playtube/releases) des Projekts. Im
|
[GitHub Releases](https://github.com/fojadrachi/Playtube/releases) des Projekts. Im
|
||||||
Einstellungen-Tab gibt es zusaetzlich einen "Jetzt nach Updates suchen"-Button mit
|
Einstellungen-Tab gibt es zusätzlich einen "Jetzt nach Updates suchen"-Button mit
|
||||||
Status-Anzeige und Fortschrittsbalken fuer den Download. Gibt es eine neuere Version,
|
Status-Anzeige und Fortschrittsbalken für den Download. Gibt es eine neuere Version,
|
||||||
fragt ein Dialog, ob sie installiert werden soll:
|
fragt ein Dialog, ob sie installiert werden soll:
|
||||||
|
|
||||||
- **Windows, per Setup installiert** (siehe "Installation"): laedt bevorzugt das kleine
|
- **Windows, per Setup installiert** (siehe "Installation"): lädt bevorzugt das kleine
|
||||||
**Patch-Paket** herunter (nur die `Playtube.exe` mit unserem Anwendungscode, ca. 2-3 MB)
|
**Patch-Paket** herunter (nur die `Playtube.exe` mit unserem Anwendungscode, ca. 2-3 MB)
|
||||||
und ueberschreibt damit die Datei im Installationsordner - der riesige PySide6/
|
und überschreibt damit die Datei im Installationsordner - der riesige PySide6/
|
||||||
QtWebEngine-Laufzeitordner (`_internal/`) bleibt unangetastet, da er sich zwischen
|
QtWebEngine-Laufzeitordner (`_internal/`) bleibt unangetastet, da er sich zwischen
|
||||||
normalen Patch-Releases nicht aendert. Die PySide6-Version steht im Dateinamen des
|
normalen Patch-Releases nicht ändert. Die PySide6-Version steht im Dateinamen des
|
||||||
Patches (`...-pyside6.11.2-patch.play`); weicht sie von der installierten Laufzeit ab,
|
Patches (`...-pyside6.11.2-patch.play`); weicht sie von der installierten Laufzeit ab,
|
||||||
ist ein reines .exe-Patch nicht mehr passend und Playtube nimmt stattdessen den
|
ist ein reines .exe-Patch nicht mehr passend und Playtube nimmt stattdessen den
|
||||||
**Setup-Installer**, der alles (auch die Laufzeit) an Ort und Stelle erneuert und
|
**Setup-Installer**, der alles (auch die Laufzeit) an Ort und Stelle erneuert und
|
||||||
Playtube danach wieder startet. Der Versionseintrag in "Apps & Features" wird nach
|
Playtube danach wieder startet. Der Versionseintrag in "Apps & Features" wird nach
|
||||||
einem Patch ebenfalls nachgezogen.
|
einem Patch ebenfalls nachgezogen.
|
||||||
- **Windows, portable Kopie** (aus dem ZIP entpackt, z.B. in Downloads): laedt den
|
- **Windows, portable Kopie** (aus dem ZIP entpackt, z.B. in Downloads): lädt den
|
||||||
**Setup-Installer** und fuehrt ihn still aus. Playtube liegt danach in der regulaeren
|
**Setup-Installer** und führt ihn still aus. Playtube liegt danach in der regulären
|
||||||
Installation - Startmenue-Eintrag und Dateizuordnung zeigen dorthin, die alte portable
|
Installation - Startmenü-Eintrag und Dateizuordnung zeigen dorthin, die alte portable
|
||||||
Kopie ist nicht mehr noetig (und kann geloescht werden). So entstehen nicht laenger
|
Kopie ist nicht mehr nötig (und kann gelöscht werden). So entstehen nicht länger
|
||||||
versionierte Ordner nebeneinander. Gibt es (bei aelteren Releases) keinen Installer,
|
versionierte Ordner nebeneinander. Gibt es (bei älteren Releases) keinen Installer,
|
||||||
wird wie frueher das volle ZIP ueber den vorhandenen Ordner kopiert.
|
wird wie früher das volle ZIP über den vorhandenen Ordner kopiert.
|
||||||
- **Linux** (`Playtube`-Binary): Patch-Paket (nur das Binary) bzw. volles `.tar.gz`.
|
- **Linux** (`Playtube`-Binary): Patch-Paket (nur das Binary) bzw. volles `.tar.gz`.
|
||||||
Die App startet sich in allen Faellen danach selbst neu.
|
Die App startet sich in allen Fällen danach selbst neu.
|
||||||
- **Entwicklungsmodus** (`python main.py`): fuehrt `git pull` + `pip install -r
|
- **Entwicklungsmodus** (`python main.py`): führt `git pull` + `pip install -r
|
||||||
requirements.txt` aus und startet den Python-Prozess neu.
|
requirements.txt` aus und startet den Python-Prozess neu.
|
||||||
|
|
||||||
Auto-Update laesst sich im Einstellungen-Tab oder in `config.json` unter
|
Auto-Update lässt sich im Einstellungen-Tab oder in `config.json` unter
|
||||||
`updates.enabled` deaktivieren.
|
`updates.enabled` deaktivieren.
|
||||||
|
|
||||||
Nach einem erkannten Update wird beim naechsten Start automatisch der QtWebEngine-
|
Nach einem erkannten Update wird beim nächsten Start automatisch der QtWebEngine-
|
||||||
HTTP-Cache geleert (`webprofile/cache`) - alte Cache-Eintraege koennen sonst nicht mehr
|
HTTP-Cache geleert (`webprofile/cache`) - alte Cache-Einträge können sonst nicht mehr
|
||||||
zum neuen Code passen (fruehere Ursache fuer fehlende Icons). Der Login bleibt davon
|
zum neuen Code passen (frühere Ursache für fehlende Icons). Der Login bleibt davon
|
||||||
unberuehrt, da Cookies/LocalStorage in einem komplett getrennten Ordner
|
unberührt, da Cookies/LocalStorage in einem komplett getrennten Ordner
|
||||||
(`webprofile/storage`) liegen.
|
(`webprofile/storage`) liegen.
|
||||||
|
|
||||||
### Patch-Dateien manuell installieren (`.play`)
|
### Patch-Dateien manuell installieren (`.play`)
|
||||||
@@ -143,11 +141,11 @@ Windows-Patch-Pakete tragen die eigene Dateiendung `.play` statt `.zip` (technis
|
|||||||
weiterhin ein ganz normales ZIP-Archiv). Playtube registriert `.play` beim ersten Start
|
weiterhin ein ganz normales ZIP-Archiv). Playtube registriert `.play` beim ersten Start
|
||||||
automatisch als Windows-Dateizuordnung - eine manuell heruntergeladene
|
automatisch als Windows-Dateizuordnung - eine manuell heruntergeladene
|
||||||
`Playtube-vX.Y.Z-win64-patch.play` (z.B. von der
|
`Playtube-vX.Y.Z-win64-patch.play` (z.B. von der
|
||||||
[Releases-Seite](https://github.com/fojadrachi/Playtube/releases)) laesst sich also
|
[Releases-Seite](https://github.com/fojadrachi/Playtube/releases)) lässt sich also
|
||||||
einfach per Doppelklick installieren, ohne dass Playtube selbst etwas herunterladen
|
einfach per Doppelklick installieren, ohne dass Playtube selbst etwas herunterladen
|
||||||
muss.
|
muss.
|
||||||
|
|
||||||
### Eine neue Version veroeffentlichen
|
### Eine neue Version veröffentlichen
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell -ExecutionPolicy Bypass -File packaging\release.ps1 -Version 1.1.0
|
powershell -ExecutionPolicy Bypass -File packaging\release.ps1 -Version 1.1.0
|
||||||
@@ -155,13 +153,13 @@ powershell -ExecutionPolicy Bypass -File packaging\release.ps1 -Version 1.1.0
|
|||||||
|
|
||||||
Das Skript setzt die Versionsnummer, committet, erstellt Git-Tag `v1.1.0` und pusht zu
|
Das Skript setzt die Versionsnummer, committet, erstellt Git-Tag `v1.1.0` und pusht zu
|
||||||
`origin` (dein Repo unter https://github.com/fojadrachi/Playtube). Der gepushte Tag
|
`origin` (dein Repo unter https://github.com/fojadrachi/Playtube). Der gepushte Tag
|
||||||
loest automatisch die GitHub-Actions-Pipeline
|
löst automatisch die GitHub-Actions-Pipeline
|
||||||
([.github/workflows/release.yml](.github/workflows/release.yml)) aus, die **sowohl
|
([.github/workflows/release.yml](.github/workflows/release.yml)) aus, die **sowohl
|
||||||
eine Windows- als auch eine Linux-Version baut** und beide als Assets an einem GitHub
|
eine Windows- als auch eine Linux-Version baut** und beide als Assets an einem GitHub
|
||||||
Release veroeffentlicht - Fortschritt unter
|
Release veröffentlicht - Fortschritt unter
|
||||||
https://github.com/fojadrachi/Playtube/actions.
|
https://github.com/fojadrachi/Playtube/actions.
|
||||||
|
|
||||||
Fuer Windows entstehen dabei drei Dateien: `Playtube-Setup-vX.Y.Z.exe` (Installer, fuer
|
Für Windows entstehen dabei drei Dateien: `Playtube-Setup-vX.Y.Z.exe` (Installer, für
|
||||||
Neueinsteiger und volle Updates), `Playtube-vX.Y.Z-win64.zip` (portabel) und das kleine
|
Neueinsteiger und volle Updates), `Playtube-vX.Y.Z-win64.zip` (portabel) und das kleine
|
||||||
`...-pyside<Version>-patch.play` (schnelles Update). Der Installer bekommt seine
|
`...-pyside<Version>-patch.play` (schnelles Update). Der Installer bekommt seine
|
||||||
Versionsnummer aus `playtube/__init__.py` (das `release.ps1` vor dem Tag setzt).
|
Versionsnummer aus `playtube/__init__.py` (das `release.ps1` vor dem Tag setzt).
|
||||||
@@ -171,11 +169,11 @@ neue Version danach automatisch angeboten.
|
|||||||
|
|
||||||
## Native Linux-Version
|
## Native Linux-Version
|
||||||
|
|
||||||
Playtube laeuft genauso unter Linux (gleicher Code, gleiches PySide6/QtWebEngine) und
|
Playtube läuft genauso unter Linux (gleicher Code, gleiches PySide6/QtWebEngine) und
|
||||||
wird bei jedem Release automatisch als `Playtube-vX.Y.Z-linux-x86_64.tar.gz` unter
|
wird bei jedem Release automatisch als `Playtube-vX.Y.Z-linux-x86_64.tar.gz` unter
|
||||||
https://github.com/fojadrachi/Playtube/releases mitgebaut.
|
https://github.com/fojadrachi/Playtube/releases mitgebaut.
|
||||||
|
|
||||||
**Fertiges Release installieren** (richtet Startmenue-Eintrag + Icon ein):
|
**Fertiges Release installieren** (richtet Startmenü-Eintrag + Icon ein):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
tar -xzf Playtube-vX.Y.Z-linux-x86_64.tar.gz
|
tar -xzf Playtube-vX.Y.Z-linux-x86_64.tar.gz
|
||||||
@@ -183,7 +181,7 @@ cd Playtube
|
|||||||
sh install-linux.sh
|
sh install-linux.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Danach ist Playtube ueber das Anwendungsmenue oder den Befehl `playtube` startbar.
|
Danach ist Playtube über das Anwendungsmenü oder den Befehl `playtube` startbar.
|
||||||
|
|
||||||
**Aus dem Quellcode starten:**
|
**Aus dem Quellcode starten:**
|
||||||
|
|
||||||
@@ -193,31 +191,31 @@ python3 -m venv .venv
|
|||||||
.venv/bin/python main.py
|
.venv/bin/python main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
QtWebEngine benoetigt unter Linux ein paar System-Bibliotheken (auf Debian/Ubuntu):
|
QtWebEngine benötigt unter Linux ein paar System-Bibliotheken (auf Debian/Ubuntu):
|
||||||
`sudo apt install libxkbcommon0 libegl1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2t64 libatk-bridge2.0-0 libcups2` (siehe auch die vollstaendige Liste in
|
`sudo apt install libxkbcommon0 libegl1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2t64 libatk-bridge2.0-0 libcups2` (siehe auch die vollstaendige Liste in
|
||||||
[.github/workflows/release.yml](.github/workflows/release.yml)).
|
[.github/workflows/release.yml](.github/workflows/release.yml)).
|
||||||
|
|
||||||
## Hinweise
|
## Hinweise
|
||||||
|
|
||||||
- **"Dieser Browser ist unter Umstaenden nicht sicher" beim Google-Login:** Playtube
|
- **"Dieser Browser ist unter Umständen nicht sicher" beim Google-Login:** Playtube
|
||||||
setzt einen echten Chrome-User-Agent inkl. passender `Sec-CH-UA`-Header, damit Google
|
setzt einen echten Chrome-User-Agent inkl. passender `Sec-CH-UA`-Header, damit Google
|
||||||
das eingebettete Chromium (QtWebEngine) nicht als unsicheres WebView erkennt. Sollte
|
das eingebettete Chromium (QtWebEngine) nicht als unsicheres WebView erkennt. Sollte
|
||||||
die Meldung dennoch erscheinen: alle Playtube-Fenster/-Prozesse schliessen und neu
|
die Meldung dennoch erscheinen: alle Playtube-Fenster/-Prozesse schliessen und neu
|
||||||
starten (die Header greifen erst ab dem naechsten Prozessstart), notfalls einmal den
|
starten (die Header greifen erst ab dem nächsten Prozessstart), notfalls einmal den
|
||||||
Profilordner `%APPDATA%\Playtube\webprofile` (bzw. `PlaytubeDev` im
|
Profilordner `%APPDATA%\Playtube\webprofile` (bzw. `PlaytubeDev` im
|
||||||
Entwicklungsmodus) loeschen und neu anmelden.
|
Entwicklungsmodus) löschen und neu anmelden.
|
||||||
- **Auf YouTube/YouTube Music fehlen alle Icons (Play/Pause, Suche, Menue ...):** Fast
|
- **Auf YouTube/YouTube Music fehlen alle Icons (Play/Pause, Suche, Menü ...):** Fast
|
||||||
sicher laufen zwei Playtube-Prozesse gleichzeitig auf demselben Browser-Profil - die
|
sicher laufen zwei Playtube-Prozesse gleichzeitig auf demselben Browser-Profil - die
|
||||||
zweite Instanz rendert dann keine Icons mehr. Passiert leicht, weil das Schliessen des
|
zweite Instanz rendert dann keine Icons mehr. Passiert leicht, weil das Schliessen des
|
||||||
Fensters Playtube nur in den Tray minimiert: eine aeltere Version laeuft unsichtbar
|
Fensters Playtube nur in den Tray minimiert: eine ältere Version läuft unsichtbar
|
||||||
weiter, waehrend eine neu heruntergeladene zusaetzlich gestartet wird. Abhilfe: alle
|
weiter, während eine neu heruntergeladene zusätzlich gestartet wird. Abhilfe: alle
|
||||||
Playtube-Instanzen ueber das Tray-Icon (Rechtsklick -> Beenden) bzw. im Taskmanager
|
Playtube-Instanzen über das Tray-Icon (Rechtsklick -> Beenden) bzw. im Taskmanager
|
||||||
beenden und nur EINE neu starten. Ab der Version mit
|
beenden und nur EINE neu starten. Ab der Version mit
|
||||||
[playtube/single_instance.py](playtube/single_instance.py) verhindert Playtube den
|
[playtube/single_instance.py](playtube/single_instance.py) verhindert Playtube den
|
||||||
Doppelstart selbst (ein zweiter Start holt das laufende Fenster nach vorn); eine
|
Doppelstart selbst (ein zweiter Start holt das laufende Fenster nach vorn); eine
|
||||||
aeltere Instanz ohne diesen Schutz wird dabei nicht erkannt und muss einmalig manuell
|
ältere Instanz ohne diesen Schutz wird dabei nicht erkannt und muss einmalig manuell
|
||||||
beendet werden.
|
beendet werden.
|
||||||
- 4K/Premium-Videoqualitaet kann eingeschraenkt sein, da die Open-Source-Variante von
|
- 4K/Premium-Videoqualität kann eingeschränkt sein, da die Open-Source-Variante von
|
||||||
QtWebEngine kein Widevine-DRM mitbringt (Standard-Qualitaeten funktionieren normal).
|
QtWebEngine kein Widevine-DRM mitbringt (Standard-Qualitäten funktionieren normal).
|
||||||
- Icon/Branding-Bilder liegen unter `assets/` und wurden mit `tools/generate_icon.py`
|
- Icon/Branding-Bilder liegen unter `assets/` und wurden mit `tools/generate_icon.py`
|
||||||
erzeugt (Pillow) - bei Bedarf einfach eigenes `icon.ico`/`icon.png` dort ersetzen.
|
erzeugt (Pillow) - bei Bedarf einfach eigenes `icon.ico`/`icon.png` dort ersetzen.
|
||||||
|
|||||||
+40
-6
@@ -98,27 +98,61 @@ begin
|
|||||||
Result := ExpandConstant('{param:RELAUNCH|0}') = '1';
|
Result := ExpandConstant('{param:RELAUNCH|0}') = '1';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure StopRunningPlaytube();
|
function PowerShellPath(): String;
|
||||||
|
begin
|
||||||
|
Result := ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure WaitForOldInstance();
|
||||||
|
var
|
||||||
|
OldPid, ResultCode: Integer;
|
||||||
|
begin
|
||||||
|
{ Playtubes Updater startet Setup aus der laufenden App heraus und uebergibt deren
|
||||||
|
Prozess-ID (/WAITPID=...). Setup wartet, bis sich diese Instanz selbst beendet hat,
|
||||||
|
statt sie hart abzuschiessen (max. 20 s). Ohne Angabe (Setup per Doppelklick) passiert
|
||||||
|
hier nichts. }
|
||||||
|
OldPid := StrToIntDef(ExpandConstant('{param:WAITPID|0}'), 0);
|
||||||
|
if OldPid > 0 then
|
||||||
|
Exec(PowerShellPath(),
|
||||||
|
'-NoProfile -NonInteractive -WindowStyle Hidden -Command "Wait-Process -Id ' + IntToStr(OldPid) + ' -Timeout 20 -ErrorAction SilentlyContinue"',
|
||||||
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure StopLeftoverProcesses();
|
||||||
var
|
var
|
||||||
ResultCode: Integer;
|
ResultCode: Integer;
|
||||||
begin
|
begin
|
||||||
{ /T beendet auch die Kindprozesse (QtWebEngine); der Hilfsprozess wird zusaetzlich
|
{ WICHTIG: bewusst OHNE "/T" (Prozessbaum mitbeenden). Der Updater startet Setup aus
|
||||||
einzeln beendet, falls er als Waise ueberlebt hat. }
|
Playtube.exe heraus - Setup ist also ein Kindprozess. Solange Playtube noch beendet
|
||||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /T /IM {#AppExeName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
wird, wuerde "/T" den Installer selbst mit abschiessen, bevor er etwas installiert hat
|
||||||
|
(so ging frueher ein Update still verloren: kein Kopieren, kein Neustart). }
|
||||||
|
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /IM {#AppExeName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /IM {#AppHelperName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /IM {#AppHelperName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
|
||||||
|
{ QtWebEngine-Kindprozesse, die nach dem Ende von Playtube noch aus dem
|
||||||
|
Installationsordner laufen, wuerden Dateien sperren - gezielt nach Pfad beenden
|
||||||
|
(nicht per Namen: QtWebEngineProcess.exe heisst auch bei anderen Qt-Programmen). }
|
||||||
|
if DirExists(ExpandConstant('{app}')) then
|
||||||
|
Exec(PowerShellPath(),
|
||||||
|
'-NoProfile -NonInteractive -WindowStyle Hidden -Command "$d = ''' + ExpandConstant('{app}') + '\''; ' +
|
||||||
|
'Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -and $_.ExecutablePath.StartsWith($d, [StringComparison]::OrdinalIgnoreCase) } | ' +
|
||||||
|
'ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }"',
|
||||||
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
|
||||||
{ Dateisperren freigeben lassen, bevor kopiert wird. }
|
{ Dateisperren freigeben lassen, bevor kopiert wird. }
|
||||||
Sleep(800);
|
Sleep(800);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||||
begin
|
begin
|
||||||
StopRunningPlaytube();
|
WaitForOldInstance();
|
||||||
|
StopLeftoverProcesses();
|
||||||
Result := '';
|
Result := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function InitializeUninstall(): Boolean;
|
function InitializeUninstall(): Boolean;
|
||||||
begin
|
begin
|
||||||
StopRunningPlaytube();
|
StopLeftoverProcesses();
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Playtube - ein eigenstaendiger YouTube- & YouTube-Music-Player mit Discord Rich Presence."""
|
"""Playtube - ein eigenstaendiger YouTube- & YouTube-Music-Player mit Discord Rich Presence."""
|
||||||
|
|
||||||
__app_name__ = "Playtube"
|
__app_name__ = "Playtube"
|
||||||
__version__ = "2.3.2"
|
__version__ = "2.4.0"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -28,6 +29,15 @@ from .updater import UpdateChecker, UpdateInstaller
|
|||||||
ASSETS_DIR = Path(__file__).resolve().parent.parent / "assets"
|
ASSETS_DIR = Path(__file__).resolve().parent.parent / "assets"
|
||||||
|
|
||||||
|
|
||||||
|
def _force_exit_after(seconds: float) -> None:
|
||||||
|
"""Beendet den Prozess nach `seconds` hart (os._exit), falls das normale Beenden bis
|
||||||
|
dahin noch nicht durch ist. Der Timer laeuft als Daemon-Thread und stoert das
|
||||||
|
normale, schnelle Beenden nicht."""
|
||||||
|
timer = threading.Timer(seconds, os._exit, args=(0,))
|
||||||
|
timer.daemon = True
|
||||||
|
timer.start()
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self, config: dict[str, Any]):
|
def __init__(self, config: dict[str, Any]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -359,6 +369,10 @@ class MainWindow(QMainWindow):
|
|||||||
"Installation abgeschlossen. Playtube wird neu gestartet …"
|
"Installation abgeschlossen. Playtube wird neu gestartet …"
|
||||||
)
|
)
|
||||||
self._tray.setToolTip(f"{APP_NAME} – wird neu gestartet …")
|
self._tray.setToolTip(f"{APP_NAME} – wird neu gestartet …")
|
||||||
|
# Haengt sich Qt/QtWebEngine beim Beenden auf, wuerde der Update-Helfer (bzw.
|
||||||
|
# Setup, siehe /WAITPID) ewig auf das Ende dieses Prozesses warten - und die
|
||||||
|
# alte Version bliebe einfach weiterlaufen. Nach 8 s hart beenden.
|
||||||
|
_force_exit_after(8.0)
|
||||||
self._quit()
|
self._quit()
|
||||||
else:
|
else:
|
||||||
QMessageBox.information(
|
QMessageBox.information(
|
||||||
|
|||||||
+11
-2
@@ -466,7 +466,12 @@ rm -rf "{staging}"
|
|||||||
packaging/playtube.iss) und startet Playtube dank /RELAUNCH=1 danach neu. Die
|
packaging/playtube.iss) und startet Playtube dank /RELAUNCH=1 danach neu. Die
|
||||||
laufende App beendet sich direkt nach diesem Aufruf (siehe MainWindow), muss
|
laufende App beendet sich direkt nach diesem Aufruf (siehe MainWindow), muss
|
||||||
hier also nicht auf Setup warten. Setup wird abgekoppelt gestartet, damit es das
|
hier also nicht auf Setup warten. Setup wird abgekoppelt gestartet, damit es das
|
||||||
Beenden dieses Prozesses ueberlebt."""
|
Beenden dieses Prozesses ueberlebt.
|
||||||
|
|
||||||
|
/WAITPID=<eigene PID>: Setup wartet, bis sich diese App wirklich beendet hat,
|
||||||
|
bevor es Dateien tauscht. /LOG (ohne Pfad): Setup schreibt ein Protokoll nach
|
||||||
|
%TEMP% ("Setup Log ....txt") - so laesst sich ein fehlgeschlagenes Update
|
||||||
|
nachtraeglich nachvollziehen, obwohl die Installation selbst still laeuft."""
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
[
|
[
|
||||||
str(setup_path),
|
str(setup_path),
|
||||||
@@ -475,6 +480,8 @@ rm -rf "{staging}"
|
|||||||
"/NORESTART",
|
"/NORESTART",
|
||||||
"/NOCANCEL",
|
"/NOCANCEL",
|
||||||
"/RELAUNCH=1",
|
"/RELAUNCH=1",
|
||||||
|
f"/WAITPID={os.getpid()}",
|
||||||
|
"/LOG",
|
||||||
],
|
],
|
||||||
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
|
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
|
||||||
close_fds=True,
|
close_fds=True,
|
||||||
@@ -497,7 +504,9 @@ $form.Refresh()
|
|||||||
# Ueber Start-Process (statt direktem Aufruf) gestartet und per Polling statt -Wait
|
# Ueber Start-Process (statt direktem Aufruf) gestartet und per Polling statt -Wait
|
||||||
# abgewartet, damit die Fensternachrichtenschleife per DoEvents() weiterlaeuft -
|
# abgewartet, damit die Fensternachrichtenschleife per DoEvents() weiterlaeuft -
|
||||||
# sonst wuerde Windows das Fenster waehrend robocopy als "Keine Rueckmeldung" anzeigen.
|
# sonst wuerde Windows das Fenster waehrend robocopy als "Keine Rueckmeldung" anzeigen.
|
||||||
$roboArgs = @("{source_dir}", "{install_dir}", "/MIR", "/NFL", "/NDL", "/NJH", "/NJS", "/NC", "/NS", "/NP")
|
# /R:3 /W:2 begrenzt die Wiederholungen bei gesperrten Dateien (Standard: praktisch endlos,
|
||||||
|
# das Update haengt dann sichtbar "fuer immer" im Fortschrittsfenster).
|
||||||
|
$roboArgs = @("{source_dir}", "{install_dir}", "/MIR", "/R:3", "/W:2", "/NFL", "/NDL", "/NJH", "/NJS", "/NC", "/NS", "/NP")
|
||||||
$roboProc = Start-Process -FilePath "robocopy" -ArgumentList $roboArgs -WindowStyle Hidden -PassThru
|
$roboProc = Start-Process -FilePath "robocopy" -ArgumentList $roboArgs -WindowStyle Hidden -PassThru
|
||||||
while (-not $roboProc.HasExited) {{
|
while (-not $roboProc.HasExited) {{
|
||||||
Start-Sleep -Milliseconds 200
|
Start-Sleep -Milliseconds 200
|
||||||
|
|||||||
Reference in New Issue
Block a user