feat: Playtube Edge 1.0.0 - WebView2 statt QtWebEngine (eigene Musik/AAC abspielbar)
Eigene Anwendung neben der Qt-Version: PlaytubeEdge.exe, eigene Installer-ID, eigener Datenordner, Updates nur ueber Releases mit Tag *-edge.
This commit is contained in:
+7
-56
@@ -1,19 +1,11 @@
|
||||
# Baut Playtube.exe mit PyInstaller und sorgt dafuer, dass auch der QtWebEngine-
|
||||
# Hilfsprozess (der eigentlich den Ton ausgibt) den Namen "Playtube" traegt, damit er
|
||||
# im Taskmanager und - so weit von der jeweiligen Windows-Version respektiert - im
|
||||
# Lautstaerkemixer nicht als "QtWebEngineProcess" auftaucht.
|
||||
# Baut PlaytubeEdge.exe (Playtube mit Microsoft-Edge-Engine / WebView2) mit PyInstaller und
|
||||
# danach den Setup-Installer (Inno Setup 6).
|
||||
#
|
||||
# Aufruf (im Projekt-Root, mit aktivierter venv):
|
||||
# powershell -ExecutionPolicy Bypass -File packaging\build.ps1
|
||||
#
|
||||
# Optional: rcedit (https://github.com/electron/rcedit) im PATH oder unter
|
||||
# packaging\rcedit.exe ablegen, dann werden Icon + Versionsinfo des umbenannten
|
||||
# Hilfsprozesses ebenfalls auf "Playtube" gesetzt (sonst bleibt intern "QtWebEngineProcess"
|
||||
# stehen, nur der Dateiname aendert sich - Windows zeigt dann meist trotzdem den
|
||||
# Dateinamen "PlaytubeHelper" an).
|
||||
|
||||
param(
|
||||
# Ueberspringt den Bau des Setup-Installers (Playtube-Setup-vX.Y.Z.exe, benoetigt Inno Setup 6).
|
||||
# Ueberspringt den Bau des Setup-Installers (PlaytubeEdge-Setup-vX.Y.Z.exe, benoetigt Inno Setup 6).
|
||||
[switch]$SkipInstaller
|
||||
)
|
||||
|
||||
@@ -21,53 +13,13 @@ $ErrorActionPreference = "Stop"
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
Set-Location $root
|
||||
|
||||
Write-Host "==> Baue Playtube.exe mit PyInstaller ..." -ForegroundColor Cyan
|
||||
Write-Host "==> Baue PlaytubeEdge.exe mit PyInstaller ..." -ForegroundColor Cyan
|
||||
pyinstaller packaging\playtube.spec --noconfirm --distpath dist --workpath build
|
||||
if ($LASTEXITCODE -ne 0) { throw "PyInstaller-Build fehlgeschlagen." }
|
||||
|
||||
$distDir = Join-Path $root "dist\Playtube"
|
||||
$internalDir = Join-Path $distDir "_internal"
|
||||
$searchRoot = if (Test-Path $internalDir) { $internalDir } else { $distDir }
|
||||
|
||||
$engineProcess = Get-ChildItem -Path $searchRoot -Recurse -Filter "QtWebEngineProcess.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if (-not $engineProcess) {
|
||||
Write-Warning "QtWebEngineProcess.exe wurde im Build nicht gefunden - Audio-/Taskmanager-Branding des Hilfsprozesses wird uebersprungen."
|
||||
} else {
|
||||
$helperPath = Join-Path $engineProcess.Directory.FullName "PlaytubeHelper.exe"
|
||||
Copy-Item $engineProcess.FullName $helperPath -Force
|
||||
Write-Host "==> Hilfsprozess kopiert nach $helperPath" -ForegroundColor Cyan
|
||||
|
||||
$rcedit = Get-Command rcedit -ErrorAction SilentlyContinue
|
||||
$rceditLocal = Join-Path $PSScriptRoot "rcedit.exe"
|
||||
if ($rcedit) {
|
||||
$rceditExe = $rcedit.Source
|
||||
} elseif (Test-Path $rceditLocal) {
|
||||
$rceditExe = $rceditLocal
|
||||
} else {
|
||||
$rceditExe = $null
|
||||
}
|
||||
|
||||
if ($rceditExe) {
|
||||
Write-Host "==> Patche Icon/Versionsinfo des Hilfsprozesses mit rcedit ..." -ForegroundColor Cyan
|
||||
& $rceditExe $helperPath --set-icon "$root\assets\icon.ico"
|
||||
& $rceditExe $helperPath --set-version-string "FileDescription" "Playtube"
|
||||
& $rceditExe $helperPath --set-version-string "ProductName" "Playtube"
|
||||
& $rceditExe $helperPath --set-version-string "CompanyName" "Playtube"
|
||||
& $rceditExe $helperPath --set-version-string "OriginalFilename" "PlaytubeHelper.exe"
|
||||
} else {
|
||||
Write-Host "Hinweis: rcedit nicht gefunden - Hilfsprozess heisst jetzt 'PlaytubeHelper.exe'," -ForegroundColor Yellow
|
||||
Write-Host "seine interne Versionsinfo/Icon bleibt aber 'QtWebEngineProcess'. Fuer volles" -ForegroundColor Yellow
|
||||
Write-Host "Branding: rcedit von https://github.com/electron/rcedit/releases laden und" -ForegroundColor Yellow
|
||||
Write-Host "als packaging\rcedit.exe ablegen, dann dieses Skript erneut ausfuehren." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Fertig! Die App liegt unter dist\Playtube\Playtube.exe" -ForegroundColor Green
|
||||
Write-Host "Fertig! Die App liegt unter dist\PlaytubeEdge\PlaytubeEdge.exe" -ForegroundColor Green
|
||||
|
||||
# --- Setup-Installer (Inno Setup) ------------------------------------------------------
|
||||
# Baut aus dist\Playtube den Installer dist\installer\Playtube-Setup-vX.Y.Z.exe. Ein und
|
||||
# derselbe Installer richtet Playtube erstmalig ein UND aktualisiert spaeter eine
|
||||
# Ein und derselbe Installer richtet Playtube Edge erstmalig ein UND aktualisiert spaeter eine
|
||||
# vorhandene Installation an Ort und Stelle (feste AppId) - es gibt nie mehrere Versionen.
|
||||
if (-not $SkipInstaller) {
|
||||
$versionLine = Select-String -Path (Join-Path $root "playtube\__init__.py") -Pattern '__version__\s*=\s*"([^"]+)"' | Select-Object -First 1
|
||||
@@ -86,12 +38,11 @@ if (-not $SkipInstaller) {
|
||||
Write-Host ""
|
||||
Write-Host "Hinweis: Inno Setup 6 nicht gefunden - Setup-Installer wird uebersprungen." -ForegroundColor Yellow
|
||||
Write-Host "Installieren: winget install --id JRSoftware.InnoSetup -e" -ForegroundColor Yellow
|
||||
Write-Host "(oder mit -SkipInstaller diesen Schritt bewusst auslassen)" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host ""
|
||||
Write-Host "==> Baue Setup-Installer (Version $version) mit Inno Setup ..." -ForegroundColor Cyan
|
||||
& $iscc "/DAppVersion=$version" (Join-Path $PSScriptRoot "playtube.iss")
|
||||
if ($LASTEXITCODE -ne 0) { throw "Inno-Setup-Build fehlgeschlagen." }
|
||||
Write-Host "Fertig! Installer: dist\installer\Playtube-Setup-v$version.exe" -ForegroundColor Green
|
||||
Write-Host "Fertig! Installer: dist\installer\PlaytubeEdge-Setup-v$version.exe" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
+34
-51
@@ -1,18 +1,19 @@
|
||||
; Inno-Setup-Skript fuer den Playtube-Windows-Installer (Playtube-Setup-vX.Y.Z.exe).
|
||||
; Inno-Setup-Skript fuer den Playtube-Edge-Windows-Installer (PlaytubeEdge-Setup-vX.Y.Z.exe).
|
||||
;
|
||||
; Bauen (Inno Setup 6.3+ noetig, https://jrsoftware.org/isinfo.php):
|
||||
; ISCC.exe /DAppVersion=2.4.0 packaging\playtube.iss
|
||||
; Voraussetzung: dist\Playtube\ existiert bereits (PyInstaller-Build, siehe build.ps1).
|
||||
; Ergebnis: dist\installer\Playtube-Setup-v2.4.0.exe
|
||||
; ISCC.exe /DAppVersion=1.0.0 packaging\playtube.iss
|
||||
; Voraussetzung: dist\PlaytubeEdge\ existiert bereits (PyInstaller-Build, siehe build.ps1).
|
||||
; Ergebnis: dist\installer\PlaytubeEdge-Setup-v1.0.0.exe
|
||||
;
|
||||
; Wichtig fuer "es soll nie mehrere Versionen geben":
|
||||
; - Feste AppId (unten): jede neue Setup-Version erkennt darueber die vorhandene
|
||||
; Installation und ueberschreibt sie im SELBEN Ordner (statt eine zweite anzulegen).
|
||||
; - Installiert pro Benutzer nach %LOCALAPPDATA%\Programs\Playtube (keine Admin-Rechte
|
||||
; noetig, Ordner ist fuer Playtubes eigenen Updater beschreibbar).
|
||||
; - Laufende Playtube-Prozesse werden vor dem Kopieren beendet, der alte Programmordner
|
||||
; (_internal) wird vor dem Kopieren geleert, damit keine Reste alter Versionen bleiben.
|
||||
; - Login/Einstellungen liegen in %APPDATA%\Playtube und bleiben bei Updates erhalten.
|
||||
; Playtube Edge ist bewusst eine EIGENE Anwendung neben der Qt-Version von Playtube:
|
||||
; - Eigene AppId, eigener Installationsordner (%LOCALAPPDATA%\Programs\PlaytubeEdge), eigener
|
||||
; Datenordner (%APPDATA%\PlaytubeEdge), eigene Exe (PlaytubeEdge.exe). Beide Versionen koennen
|
||||
; parallel installiert sein; keine ueberschreibt die andere.
|
||||
; - Feste AppId: jede neue Edge-Setup-Version erkennt darueber die vorhandene Edge-Installation
|
||||
; und ueberschreibt sie im SELBEN Ordner. Muss mit _INNO_APP_ID in playtube/updater.py
|
||||
; uebereinstimmen.
|
||||
; - Keine ".play"-Dateizuordnung und kein Beenden von Playtube.exe / PlaytubeHelper.exe - das
|
||||
; gehoert alles der Qt-Version.
|
||||
;
|
||||
; Hinweis zur Datei: bewusst reines ASCII (kein BOM), damit die Umlaute-Kodierung von
|
||||
; Inno Setup nicht ins Spiel kommt.
|
||||
@@ -21,14 +22,13 @@
|
||||
#define AppVersion "0.0.0"
|
||||
#endif
|
||||
|
||||
#define AppName "Playtube"
|
||||
#define AppExeName "Playtube.exe"
|
||||
#define AppHelperName "PlaytubeHelper.exe"
|
||||
#define AppName "Playtube Edge"
|
||||
#define AppDirName "PlaytubeEdge"
|
||||
#define AppExeName "PlaytubeEdge.exe"
|
||||
|
||||
[Setup]
|
||||
; NIEMALS aendern - identifiziert die Installation ueber alle Versionen hinweg. Muss mit
|
||||
; _INNO_APP_ID in playtube/updater.py uebereinstimmen.
|
||||
AppId={{87FBA502-2B84-4C42-A66B-2F03F490912D}
|
||||
; NIEMALS aendern - identifiziert die Edge-Installation ueber alle Versionen hinweg.
|
||||
AppId={{4F0F3698-DAF3-4028-B0A4-896D31292C28}
|
||||
AppName={#AppName}
|
||||
AppVersion={#AppVersion}
|
||||
AppVerName={#AppName} {#AppVersion}
|
||||
@@ -37,22 +37,21 @@ AppPublisherURL=https://github.com/fojadrachi/Playtube
|
||||
AppSupportURL=https://github.com/fojadrachi/Playtube/issues
|
||||
AppUpdatesURL=https://github.com/fojadrachi/Playtube/releases
|
||||
VersionInfoVersion={#AppVersion}
|
||||
DefaultDirName={localappdata}\Programs\{#AppName}
|
||||
DefaultDirName={localappdata}\Programs\{#AppDirName}
|
||||
DisableProgramGroupPage=yes
|
||||
PrivilegesRequired=lowest
|
||||
ArchitecturesAllowed=x64compatible
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
OutputDir=..\dist\installer
|
||||
OutputBaseFilename=Playtube-Setup-v{#AppVersion}
|
||||
OutputBaseFilename=PlaytubeEdge-Setup-v{#AppVersion}
|
||||
SetupIconFile=..\assets\icon.ico
|
||||
UninstallDisplayIcon={app}\{#AppExeName}
|
||||
UninstallDisplayName={#AppName}
|
||||
Compression=lzma2/max
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
; Prozesse beenden wir selbst (siehe [Code]) - Playtube versteckt sich beim Schliessen des
|
||||
; Fensters nur im Tray und reagiert daher nicht zuverlaessig auf die Aufforderung, sich zu
|
||||
; schliessen, die Inno per CloseApplications senden wuerde.
|
||||
; Prozesse beenden wir selbst (siehe [Code]) - Playtube Edge versteckt sich beim Schliessen des
|
||||
; Fensters nur im Tray und reagiert daher nicht zuverlaessig auf CloseApplications.
|
||||
CloseApplications=no
|
||||
RestartApplications=no
|
||||
|
||||
@@ -69,27 +68,16 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
Type: filesandordirs; Name: "{app}\_internal"
|
||||
|
||||
[Files]
|
||||
Source: "..\dist\Playtube\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "..\dist\PlaytubeEdge\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Icons]
|
||||
; {autoprograms} = %APPDATA%\Microsoft\Windows\Start Menu\Programs - derselbe Pfad, den die
|
||||
; App frueher selbst fuer eine portable Kopie angelegt hat; eine alte Verknuepfung, die
|
||||
; noch auf einen Downloads-Ordner zeigt, wird dadurch ersetzt.
|
||||
Name: "{autoprograms}\{#AppName}"; Filename: "{app}\{#AppExeName}"
|
||||
Name: "{autodesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Registry]
|
||||
; Dateizuordnung fuer ".play" (Playtube-Patchdateien, siehe playtube/shortcuts.py).
|
||||
Root: HKCU; Subkey: "Software\Classes\.play"; ValueType: string; ValueName: ""; ValueData: "{#AppName}.PatchFile"; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "Software\Classes\{#AppName}.PatchFile"; ValueType: string; ValueName: ""; ValueData: "{#AppName}-Patchdatei"; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "Software\Classes\{#AppName}.PatchFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppExeName}"
|
||||
Root: HKCU; Subkey: "Software\Classes\{#AppName}.PatchFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppExeName}"" ""%1"""
|
||||
|
||||
[Run]
|
||||
; Normale (sichtbare) Installation: Haekchen "Playtube jetzt starten" am Ende.
|
||||
; Normale (sichtbare) Installation: Haekchen "Playtube Edge jetzt starten" am Ende.
|
||||
Filename: "{app}\{#AppExeName}"; Description: "{#AppName} jetzt starten"; Flags: nowait postinstall skipifsilent
|
||||
; Stilles Update durch Playtubes eigenen Updater (/RELAUNCH=1): App danach automatisch
|
||||
; wieder starten.
|
||||
; Stilles Update durch den eigenen Updater (/RELAUNCH=1): App danach automatisch wieder starten.
|
||||
Filename: "{app}\{#AppExeName}"; Flags: nowait; Check: ShouldRelaunch
|
||||
|
||||
[Code]
|
||||
@@ -107,10 +95,8 @@ 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. }
|
||||
{ Der Updater startet Setup aus der laufenden App heraus und uebergibt deren Prozess-ID
|
||||
(/WAITPID=...). Setup wartet, bis sich diese Instanz selbst beendet hat (max. 20 s). }
|
||||
OldPid := StrToIntDef(ExpandConstant('{param:WAITPID|0}'), 0);
|
||||
if OldPid > 0 then
|
||||
Exec(PowerShellPath(),
|
||||
@@ -122,16 +108,13 @@ procedure StopLeftoverProcesses();
|
||||
var
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
{ WICHTIG: bewusst OHNE "/T" (Prozessbaum mitbeenden). Der Updater startet Setup aus
|
||||
Playtube.exe heraus - Setup ist also ein Kindprozess. Solange Playtube noch beendet
|
||||
wird, wuerde "/T" den Installer selbst mit abschiessen, bevor er etwas installiert hat
|
||||
(so ging frueher ein Update still verloren: kein Kopieren, kein Neustart). }
|
||||
{ WICHTIG: bewusst OHNE "/T" - der Updater startet Setup aus PlaytubeEdge.exe heraus, Setup ist
|
||||
also ein Kindprozess; "/T" wuerde den Installer selbst mit abschiessen. Es wird nur
|
||||
PlaytubeEdge.exe beendet, NIE Playtube.exe der Qt-Version. }
|
||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/F /IM {#AppExeName}', '', 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). }
|
||||
{ WebView2-Kindprozesse (msedgewebview2.exe), die noch aus dem Installationsordner laufen,
|
||||
wuerden Dateien sperren - gezielt nach Pfad beenden. }
|
||||
if DirExists(ExpandConstant('{app}')) then
|
||||
Exec(PowerShellPath(),
|
||||
'-NoProfile -NonInteractive -WindowStyle Hidden -Command "$d = ''' + ExpandConstant('{app}') + '\''; ' +
|
||||
@@ -161,8 +144,8 @@ begin
|
||||
if (CurUninstallStep = usPostUninstall) and (not UninstallSilent()) then
|
||||
begin
|
||||
if MsgBox('Sollen auch die Einstellungen und der gespeicherte Login von {#AppName} geloescht werden?' + #13#10 +
|
||||
'(Ordner: ' + ExpandConstant('{userappdata}\{#AppName}') + ')',
|
||||
'(Ordner: ' + ExpandConstant('{userappdata}\{#AppDirName}') + ')',
|
||||
mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
|
||||
DelTree(ExpandConstant('{userappdata}\{#AppName}'), True, True, True);
|
||||
DelTree(ExpandConstant('{userappdata}\{#AppDirName}'), True, True, True);
|
||||
end;
|
||||
end;
|
||||
|
||||
+15
-6
@@ -4,22 +4,31 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
block_cipher = None
|
||||
|
||||
ROOT = Path(SPECPATH).resolve().parent
|
||||
|
||||
# Edge-Variante: pythonnet + clr_loader (bringen Python.Runtime.dll/ClrLoader.dll mit) und die
|
||||
# Microsoft-WebView2-DLLs aus vendor/webview2 (siehe playtube/webview2_runtime.py).
|
||||
pythonnet_datas, pythonnet_binaries, pythonnet_hidden = collect_all("pythonnet")
|
||||
clr_datas, clr_binaries, clr_hidden = collect_all("clr_loader")
|
||||
|
||||
a = Analysis(
|
||||
[str(ROOT / "main.py")],
|
||||
pathex=[str(ROOT)],
|
||||
binaries=[],
|
||||
binaries=pythonnet_binaries + clr_binaries,
|
||||
datas=[
|
||||
(str(ROOT / "assets"), "assets"),
|
||||
(str(ROOT / "config.json"), "."),
|
||||
],
|
||||
hiddenimports=["pypresence"],
|
||||
(str(ROOT / "vendor" / "webview2"), "vendor/webview2"),
|
||||
] + pythonnet_datas + clr_datas,
|
||||
hiddenimports=["pypresence", "clr"] + pythonnet_hidden + clr_hidden,
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
# Kein QtWebEngine mehr (WebView2 statt dessen) - haelt das Paket klein.
|
||||
excludes=["PySide6.QtWebEngineCore", "PySide6.QtWebEngineWidgets", "PySide6.QtWebEngineQuick"],
|
||||
noarchive=False,
|
||||
)
|
||||
|
||||
@@ -29,7 +38,7 @@ pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
# Linux/macOS gibt es diese Konzepte fuer ELF-Binaries nicht, deshalb nur dort setzen.
|
||||
exe_kwargs = dict(
|
||||
exclude_binaries=True,
|
||||
name="Playtube",
|
||||
name="PlaytubeEdge",
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
@@ -49,5 +58,5 @@ coll = COLLECT(
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=False,
|
||||
name="Playtube",
|
||||
name="PlaytubeEdge",
|
||||
)
|
||||
|
||||
@@ -19,12 +19,12 @@ VSVersionInfo(
|
||||
StringTable(
|
||||
u'040704B0',
|
||||
[StringStruct(u'CompanyName', u'Playtube'),
|
||||
StringStruct(u'FileDescription', u'Playtube'),
|
||||
StringStruct(u'FileDescription', u'Playtube Edge'),
|
||||
StringStruct(u'FileVersion', u'1.0.0.0'),
|
||||
StringStruct(u'InternalName', u'Playtube'),
|
||||
StringStruct(u'InternalName', u'PlaytubeEdge'),
|
||||
StringStruct(u'LegalCopyright', u''),
|
||||
StringStruct(u'OriginalFilename', u'Playtube.exe'),
|
||||
StringStruct(u'ProductName', u'Playtube'),
|
||||
StringStruct(u'OriginalFilename', u'PlaytubeEdge.exe'),
|
||||
StringStruct(u'ProductName', u'Playtube Edge'),
|
||||
StringStruct(u'ProductVersion', u'1.0.0.0')])
|
||||
]),
|
||||
VarFileInfo([VarStruct(u'Translation', [1031, 1200])])
|
||||
|
||||
Reference in New Issue
Block a user