From f8e65dc1389cacbaa4cf628085f52f9fcfb38aa1 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Wed, 24 Dec 2025 22:21:26 -0500 Subject: [PATCH] Change to Inno Setup for Windows WiX 3 is EOL and is one of the blockers for arm64 builds. --- .github/workflows/build-windows.yml | 12 +- CMakeModules/WindowsInstaller.cmake | 202 ++++++--------------- bundle/win/Bundle.wxs | 270 ---------------------------- bundle/win/ControlPanel.wxi | 15 -- bundle/win/Global.wxi | 11 -- bundle/win/HyperlinkTheme.wxl | 50 ------ bundle/win/JMP.wxs | 139 -------------- bundle/win/JellyfinDesktop.iss.in | 193 ++++++++++++++++++++ bundle/win/Version.wxi.in | 6 - bundle/win/WindowsSign.cmd | 105 ----------- bundle/win/jellyfin-chevron-85.png | Bin 2746 -> 0 bytes bundle/win/pmstheme.xml | 68 ------- bundle/win/progress-bar.png | Bin 99 -> 0 bytes bundle/win/wizard-image.png | Bin 0 -> 17827 bytes bundle/win/wizard-small-image.png | Bin 0 -> 10317 bytes 15 files changed, 251 insertions(+), 820 deletions(-) delete mode 100644 bundle/win/Bundle.wxs delete mode 100644 bundle/win/ControlPanel.wxi delete mode 100644 bundle/win/Global.wxi delete mode 100644 bundle/win/HyperlinkTheme.wxl delete mode 100644 bundle/win/JMP.wxs create mode 100644 bundle/win/JellyfinDesktop.iss.in delete mode 100644 bundle/win/Version.wxi.in delete mode 100644 bundle/win/WindowsSign.cmd delete mode 100644 bundle/win/jellyfin-chevron-85.png delete mode 100644 bundle/win/pmstheme.xml delete mode 100644 bundle/win/progress-bar.png create mode 100644 bundle/win/wizard-image.png create mode 100644 bundle/win/wizard-small-image.png diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 0ad5feb..197bbc3 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -20,7 +20,7 @@ jobs: vc_redist_arch: x64 vcvars: vcvars64.bat machine: X64 - # ARM64 disabled - requires WiX 4+ for installer support + # ARM64 disabled - requires qt webengine builds # - artifact: windows-arm64 # qt_arch: win64_msvc2022_arm64 # mpv_arch: aarch64 @@ -38,11 +38,13 @@ jobs: version: "${{ env.QT_VERSION }}" arch: "${{ matrix.qt_arch }}" modules: "qtwebengine qtwebchannel qtpositioning" + - name: Install Inno Setup + run: | + choco install innosetup -y + shell: powershell - name: Install dependencies run: | mkdir build - curl -L https://aka.ms/vs/17/release/vc_redist.${{ matrix.vc_redist_arch }}.exe > vc_redist.${{ matrix.vc_redist_arch }}.exe - sed -i 's#C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Redist\\MSVC\\v142\\vcredist_x64.exe#'"$(readlink -f vc_redist.${{ matrix.vc_redist_arch }}.exe | sed 's#/\([a-z]\)/#\1:\\#g' | tr '/' '\\' | sed 's/\\/\\\\/g')#g" bundle/win/Bundle.wxs curl -L https://sourceforge.net/projects/mpv-player-windows/files/libmpv/mpv-dev-${{ matrix.mpv_arch }}-${{ env.MPV_VERSION }}.7z/download > mpv.7z 7z x mpv.7z mkdir mpv @@ -57,12 +59,10 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\${{ matrix.vcvars }}" cd build - set PATH=%PATH%;C:\Program Files (x86)\WiX Toolset v3.11\bin;%CD% + set PATH=%PATH%;C:\Program Files (x86)\Inno Setup 6;%CD% cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=output -DQTROOT=%QT_ROOT_DIR% -DMPV_INCLUDE_DIR=mpv/include -DMPV_LIBRARY=mpv/libmpv-2.dll -DCHECK_FOR_UPDATES=ON -DUSE_STATIC_MPVQT=ON .. lib /def:mpv\mpv.def /out:mpv\libmpv-2.dll.lib /MACHINE:${{ matrix.machine }} ninja - mkdir output 2>nul - copy ..\vc_redist.${{ matrix.vc_redist_arch }}.exe output\ ninja windows_package shell: cmd - name: Archive production artifacts diff --git a/CMakeModules/WindowsInstaller.cmake b/CMakeModules/WindowsInstaller.cmake index 05defea..abe5086 100644 --- a/CMakeModules/WindowsInstaller.cmake +++ b/CMakeModules/WindowsInstaller.cmake @@ -1,160 +1,62 @@ -find_program(WIX_HEAT heat) -find_program(WIX_CANDLE candle) -find_program(WIX_LIGHT light) -find_program(WIX_INSIGNIA insignia) - -get_filename_component(WIX_BIN_DIR ${WIX_CANDLE} DIRECTORY) - -configure_file(${PROJECT_SOURCE_DIR}/bundle/win/Version.wxi.in Version.wxi) - -set(WIX_VARIABLES -dDeploymentPath="${CMAKE_INSTALL_PREFIX}" -dOutputPath="${CMAKE_INSTALL_PREFIX}" -dBuildPath="${CMAKE_BINARY_DIR}") - -include(CMakeParseArguments) - -function(wix_harvest_directory dir fragment) - set(ARGS REFVARIABLE CGROUP DEPENDS) - cmake_parse_arguments(_WHD "" "${ARGS}" "" ${ARGN}) - - if(NOT _WHD_REFVARIABLE) - set(_WHD_REFVARIABLE INSTALLLOCATION) - endif() - - if(_WHD_CGROUP) - set(CGROUP -cg ${_WHD_CGROUP}) - endif() - - add_custom_command(OUTPUT ${fragment} - DEPENDS ${_WHD_DEPENDS} - COMMAND ${WIX_HEAT} dir "${dir}" -srd -nologo -sw5150 ${CGROUP} -dr ${_WHD_REFVARIABLE} -ag -out ${fragment} -var var.DeploymentPath - COMMENT "Harvesting dir ${dir} to ${fragment}") - add_custom_target(heat_${fragment} DEPENDS ${fragment}) - -endfunction() - -function(wix_get_extension VARIABLE) - foreach(f ${ARGN}) - find_file(${f}_PATH ${f}.dll PATHS ${WIX_BIN_DIR}) - set(EXTS ${EXTS} -ext ${${f}_PATH}) - endforeach() - - set(${VARIABLE} ${EXTS} PARENT_SCOPE) -endfunction() - -function(wix_candle wsxfile) - set(ARGS OUTPUT ARCH) - set(MARGS EXTENSIONS) - cmake_parse_arguments(_WC "" "${ARGS}" "${MARGS}" ${ARGN}) - - if(NOT _WC_OUTPUT) - get_filename_component(WC_BASENAME ${wsxfile} NAME_WE) - set(_WC_OUTPUT ${WC_BASENAME}.wixobj) - endif() - - if(NOT _WC_ARCH) - set(_WC_ARCH x64) - endif() - - if(_WC_EXTENSIONS) - wix_get_extension(WIX_EXTENSIONS ${_WC_EXTENSIONS}) - endif() - - add_custom_command(OUTPUT ${_WC_OUTPUT} - DEPENDS ${wsxfile} - COMMAND ${WIX_CANDLE} -nologo ${WIX_VARIABLES} -I${CMAKE_CURRENT_BINARY_DIR} -arch ${_WC_ARCH} ${wsxfile} ${WIX_EXTENSIONS} -out ${_WC_OUTPUT} - COMMENT "Candle file ${_WC_OUTPUT}" - ) -endfunction() - -function(wix_light) - set(MARGS OBJS DEPENDS EXTENSIONS) - set(ARGS OUTPUT BASEDIR TARGET) - cmake_parse_arguments(_WL "" "${ARGS}" "${MARGS}" ${ARGN}) - - if(NOT _WL_OUTPUT) - message(FATAL_ERROR "Need OUTPUT") - endif() - - if(_WL_EXTENSIONS) - wix_get_extension(WIX_EXTENSIONS ${_WL_EXTENSIONS}) - endif() - - if(_WL_BASEDIR) - set(_WL_BASEDIR -b ${_WL_BASEDIR}) - endif() - - if(NOT _WL_TARGET) - set(_WL_TARGET wix_${_WL_OUTPUT}) - endif() - - - add_custom_command(OUTPUT ${_WL_OUTPUT} - DEPENDS ${_WL_OBJS} ${_WL_DEPENDS} - COMMAND ${WIX_LIGHT} -nologo ${_WL_BASEDIR} ${_WL_OBJS} ${WIX_VARIABLES} ${WIX_EXTENSIONS} -out ${_WL_OUTPUT} - COMMENT "Light it up: ${_WL_OUTPUT}") - - - add_custom_target(${_WL_TARGET} DEPENDS ${_WL_OUTPUT}) - - if(CODE_SIGN) - if(_WL_OUTPUT MATCHES ".*exe") - add_custom_command(TARGET ${_WL_TARGET} POST_BUILD - COMMAND ${WIX_INSIGNIA} -ib ${_WL_OUTPUT} -o engine.exe - COMMAND ${CMAKE_SOURCE_DIR}/bundle/win/WindowsSign.cmd engine.exe - COMMAND ${WIX_INSIGNIA} -ab engine.exe ${_WL_OUTPUT} -o ${_WL_OUTPUT} - COMMENT "Doing insignia dance" - ) - endif() - add_custom_command(TARGET ${_WL_TARGET} POST_BUILD - COMMAND ${CMAKE_SOURCE_DIR}/bundle/win/WindowsSign.cmd ${_WL_OUTPUT} - COMMENT Signing ${_WL_OUTPUT} - ) - endif() -endfunction() - -function(wix_create_installer output) - set(MARGS WXS_FILES EXTENSIONS DEPENDS) - set(ARGS ARCH BASEDIR TARGET) - cmake_parse_arguments(_WCI "" "${ARGS}" "${MARGS}" ${ARGN}) - - foreach(wxs ${_WCI_WXS_FILES}) - get_filename_component(WXSBASE ${wxs} NAME_WE) - wix_candle(${wxs} OUTPUT ${WXSBASE}.wixobj EXTENSIONS ${_WCI_EXTENSIONS} ARCH ${_WCI_ARCH}) - list(APPEND WIXOBJS ${WXSBASE}.wixobj) - endforeach() - - wix_light(OBJS ${WIXOBJS} - EXTENSIONS ${_WCI_EXTENSIONS} - OUTPUT ${output} - DEPENDS ${_WCI_DEPENDS} - BASEDIR ${_WCI_BASEDIR} - TARGET ${_WCI_TARGET}) -endfunction() - -add_custom_target(wix_install - COMMAND ${CMAKE_COMMAND} -P cmake_install.cmake - COMMENT "Copying files..." - DEPENDS JellyfinDesktop) - -wix_harvest_directory("${CMAKE_INSTALL_PREFIX}" files.wxs CGROUP ProgramFilesComponentGroup DEPENDS wix_install) - -wix_create_installer(PMP.msi - WXS_FILES files.wxs "${PROJECT_SOURCE_DIR}/bundle/win/JMP.wxs" - EXTENSIONS WixUtilExtension WixFirewallExtension - BASEDIR "${PROJECT_SOURCE_DIR}/bundle/win" +# Find Inno Setup Compiler +find_program(ISCC iscc + PATHS + "$ENV{ProgramFiles\(x86\)}/Inno Setup 6" + "$ENV{ProgramFiles}/Inno Setup 6" + "C:/Program Files (x86)/Inno Setup 6" + "C:/Program Files/Inno Setup 6" + DOC "Inno Setup Compiler" ) -if (CMAKE_SIZEOF_VOID_P MATCHES 8) +if(NOT ISCC) + message(WARNING "Inno Setup Compiler (iscc) not found. Windows installer will not be built.") + return() +endif() + +message(STATUS "Found Inno Setup: ${ISCC}") + +# Configure the Inno Setup script with version and paths +configure_file( + ${PROJECT_SOURCE_DIR}/bundle/win/JellyfinDesktop.iss.in + ${CMAKE_CURRENT_BINARY_DIR}/JellyfinDesktop.iss + @ONLY +) + +# Create install target that copies files to CMAKE_INSTALL_PREFIX +add_custom_target(innosetup_install + COMMAND ${CMAKE_COMMAND} -P cmake_install.cmake + COMMENT "Copying files for installer..." + DEPENDS JellyfinDesktop +) + +# Determine architecture string for output filename +if(CMAKE_SIZEOF_VOID_P MATCHES 8) set(INSTALLER_ARCH_STR windows-x64) else() set(INSTALLER_ARCH_STR windows-x86) endif() -wix_create_installer(JellyfinDesktop-${VERSION_STRING}-${INSTALLER_ARCH_STR}.exe - TARGET JellyfinDesktopInstaller - WXS_FILES "${PROJECT_SOURCE_DIR}/bundle/win/Bundle.wxs" - EXTENSIONS WixUtilExtension WixBalExtension - DEPENDS wix_PMP.msi - BASEDIR "${PROJECT_SOURCE_DIR}/bundle/win" +set(INSTALLER_BASE_NAME "JellyfinDesktop-${VERSION_STRING}-${INSTALLER_ARCH_STR}") +set(INSTALLER_OUTPUT_NAME "${INSTALLER_BASE_NAME}.exe") + +# Create the installer using Inno Setup +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER_OUTPUT_NAME} + DEPENDS innosetup_install ${CMAKE_CURRENT_BINARY_DIR}/JellyfinDesktop.iss + COMMAND ${ISCC} + /O${CMAKE_CURRENT_BINARY_DIR} + /F${INSTALLER_BASE_NAME} + ${CMAKE_CURRENT_BINARY_DIR}/JellyfinDesktop.iss + COMMENT "Building Inno Setup installer: ${INSTALLER_OUTPUT_NAME}" + VERBATIM ) +# Target to build the installer +add_custom_target(JellyfinDesktopInstaller + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER_OUTPUT_NAME} +) + +# Alias target for convenience add_custom_target(windows_package DEPENDS JellyfinDesktopInstaller) + +message(STATUS "Windows installer target configured: windows_package") diff --git a/bundle/win/Bundle.wxs b/bundle/win/Bundle.wxs deleted file mode 100644 index 8fa29ab..0000000 --- a/bundle/win/Bundle.wxs +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - = v6.1]]> - - - - - - - - - 112 AND KB2919355_amd64 <> 112))]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bundle/win/ControlPanel.wxi b/bundle/win/ControlPanel.wxi deleted file mode 100644 index 5637bb7..0000000 --- a/bundle/win/ControlPanel.wxi +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/bundle/win/Global.wxi b/bundle/win/Global.wxi deleted file mode 100644 index 09686ce..0000000 --- a/bundle/win/Global.wxi +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/bundle/win/HyperlinkTheme.wxl b/bundle/win/HyperlinkTheme.wxl deleted file mode 100644 index 1c38768..0000000 --- a/bundle/win/HyperlinkTheme.wxl +++ /dev/null @@ -1,50 +0,0 @@ - - - [WixBundleName] Setup - [WixBundleName] - Welcome - Setup will install [WixBundleName] on your computer. Click Install to continue, Options to set the install directory or Close to exit. - Version [WixBundleTag] - Setup will repair or uninstall [WixBundleName] from your computer. - Are you sure you want to cancel? - Setup Help - - /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. - - /passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. - - /norestart - suppress any attempts to restart. By default UI will prompt before restart. - - /log log.txt - logs to a specific file. By default a log file is created in %TEMP%. - - &Close - [WixBundleName] <a href="#">license terms</a>. - I &agree to the license terms and conditions - &Options - &Install - &Close - Setup Options - Install location: - &Browse... - &OK - &Cancel - Setup Progress - Processing: - Initializing... - &Cancel - Modify Setup - &Repair - &Uninstall - &Close - Setup Successful - &Launch - You must restart your computer before you can use the software. - &Restart - &Close - Setup Failed - One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. - You must restart your computer to complete the rollback of the software. - &Restart - &Close - Desktop Shortcut - \ No newline at end of file diff --git a/bundle/win/JMP.wxs b/bundle/win/JMP.wxs deleted file mode 100644 index 8b1a81b..0000000 --- a/bundle/win/JMP.wxs +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - = 601]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NEWERPRODUCTFOUND - - Installed AND NOT UPGRADINGPRODUCTCODE - PREVIOUSVERSIONINSTALLED - - - WINDOWSTYPE~="Server" - - - - - - - - - - - - - - - - - ADDDESKTOPSHORTCUT=1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bundle/win/JellyfinDesktop.iss.in b/bundle/win/JellyfinDesktop.iss.in new file mode 100644 index 0000000..4e786b8 --- /dev/null +++ b/bundle/win/JellyfinDesktop.iss.in @@ -0,0 +1,193 @@ +; Jellyfin Desktop Installer Script for Inno Setup +; Based on WiX configuration from JMP.wxs and Bundle.wxs +; +; NOTE: Media Feature Pack downloads for Windows N editions are not included in this +; Inno Setup version as they require MSU package handling that was specific to WiX Bundle. +; Users on Windows N editions will need to install Media Feature Pack manually if needed. + +#define MyAppName "Jellyfin Desktop" +#define MyAppVersion "@VERSION_STRING@" +#define MyAppPublisher "jellyfin.org" +#define MyAppURL "https://jellyfin.org" +#define MyAppExeName "Jellyfin Desktop.exe" +#define MyAppGUID "{{a78bea4a-5bd0-4aa3-bdf3-579b4f58a921}" +#define DeployPath "@CMAKE_INSTALL_PREFIX@" +#define VCRedistURL "https://aka.ms/vs/17/release/vc_redist.x64.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +AppId={#MyAppGUID} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +AppComments=Jellyfin desktop client +AppContact={#MyAppPublisher} +DefaultDirName={autopf}\Jellyfin Desktop +DisableProgramGroupPage=yes +; Require Windows 10 or newer +MinVersion=10.0 +ArchitecturesInstallIn64BitMode=x64compatible +ArchitecturesAllowed=x64compatible +PrivilegesRequired=admin +OutputDir=. +OutputBaseFilename=JellyfinDesktop-{#MyAppVersion}-windows-x64 +SetupIconFile=@PROJECT_SOURCE_DIR@/bundle/win/jellyfin.ico +UninstallDisplayIcon={app}\{#MyAppExeName} +Compression=lzma2/ultra64 +SolidCompression=yes +WizardStyle=modern +WizardImageFile=@PROJECT_SOURCE_DIR@/bundle/win/wizard-image.png +WizardSmallImageFile=@PROJECT_SOURCE_DIR@/bundle/win/wizard-small-image.png +DisableWelcomePage=no +LicenseFile= +DisableDirPage=no +DisableReadyPage=no +CloseApplications=yes +RestartApplications=no + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" + +[Files] +Source: "{#DeployPath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +[Icons] +Name: "{autoprograms}\Jellyfin Desktop"; Filename: "{app}\{#MyAppExeName}"; Comment: "Jellyfin desktop client"; WorkingDir: "{app}" +Name: "{autodesktop}\Jellyfin Desktop"; Filename: "{app}\{#MyAppExeName}"; Comment: "Jellyfin desktop client"; WorkingDir: "{app}"; Tasks: desktopicon + +[Run] +; Install VCRedist - will be downloaded if needed +Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/install /passive /norestart"; StatusMsg: "Installing Visual C++ Redistributable..."; Flags: waituntilterminated; Check: VCRedistNeedsInstall +; Launch app after install +Filename: "{app}\{#MyAppExeName}"; Description: "Launch Jellyfin Desktop"; Flags: nowait postinstall skipifsilent + +[Code] +const + PF_AVX2_INSTRUCTIONS_AVAILABLE = 40; + +var + VCRedistNeedsInstallFlag: Boolean; + +function IsProcessorFeaturePresent(ProcessorFeature: DWORD): BOOL; + external 'IsProcessorFeaturePresent@kernel32.dll stdcall'; + +function VCRedistNeedsInstall: Boolean; +begin + Result := VCRedistNeedsInstallFlag; +end; + +function CheckVCRedist(): Boolean; +var + UCRTBasePath: String; + MSVCPPath: String; +begin + UCRTBasePath := ExpandConstant('{sys}\ucrtbase.dll'); + MSVCPPath := ExpandConstant('{sys}\msvcp140.dll'); + + // Good if ucrtbase.dll exists + if FileExists(UCRTBasePath) then + begin + Result := True; + Log('VCRedist OK: ucrtbase.dll found'); + end + // Bad if msvcp140.dll exists but ucrtbase.dll doesn't (corrupted install) + else if FileExists(MSVCPPath) then + begin + Result := False; + Log('Bad VCRedist: msvcp140.dll exists but ucrtbase.dll missing'); + end + else + begin + Result := False; + Log('VCRedist not installed'); + end; +end; + + +function InitializeSetup(): Boolean; +begin + Result := True; + + // Check for AVX2 support (required for x86_64-v3 build) + if not IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE) then + begin + MsgBox('Jellyfin Desktop requires a CPU with AVX2 support.' + #13#10 + #13#10 + + 'Your processor does not support AVX2 instructions.', mbError, MB_OK); + Result := False; + Exit; + end; + + // Check VCRedist and set flag for download + VCRedistNeedsInstallFlag := not CheckVCRedist(); + + if VCRedistNeedsInstallFlag then + Log('VCRedist will be installed during setup'); +end; + +function PrepareToInstall(var NeedsRestart: Boolean): String; +var + DownloadPage: TDownloadWizardPage; + VCRedistPath: String; +begin + Result := ''; + NeedsRestart := False; + + // Download VCRedist if needed + if VCRedistNeedsInstallFlag then + begin + VCRedistPath := ExpandConstant('{tmp}\vcredist_x64.exe'); + + if not FileExists(VCRedistPath) then + begin + DownloadPage := CreateDownloadPage('Downloading Dependencies', 'Downloading required dependencies...', nil); + DownloadPage.Clear; + DownloadPage.Add('{#VCRedistURL}', 'vcredist_x64.exe', ''); + DownloadPage.Show; + try + DownloadPage.Download; + except + Result := 'Failed to download Visual C++ Redistributable.' + #13#10 + + 'Please check your internet connection and try again.'; + Exit; + finally + DownloadPage.Hide; + end; + end; + end; +end; + +var + RemoveUserData: Boolean; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + DataDir: String; + CacheDir: String; +begin + if CurUninstallStep = usUninstall then + begin + DataDir := ExpandConstant('{localappdata}\Jellyfin Desktop'); + CacheDir := ExpandConstant('{localappdata}\cache\Jellyfin Desktop'); + + if DirExists(DataDir) or DirExists(CacheDir) then + RemoveUserData := MsgBox('Do you want to remove your Jellyfin Desktop user data?', + mbConfirmation, MB_YESNO) = IDYES; + end + else if CurUninstallStep = usPostUninstall then + begin + if RemoveUserData then + begin + DataDir := ExpandConstant('{localappdata}\Jellyfin Desktop'); + CacheDir := ExpandConstant('{localappdata}\cache\Jellyfin Desktop'); + DelTree(DataDir, True, True, True); + DelTree(CacheDir, True, True, True); + end; + end; +end; diff --git a/bundle/win/Version.wxi.in b/bundle/win/Version.wxi.in deleted file mode 100644 index b10dcc5..0000000 --- a/bundle/win/Version.wxi.in +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/bundle/win/WindowsSign.cmd b/bundle/win/WindowsSign.cmd deleted file mode 100644 index db37e99..0000000 --- a/bundle/win/WindowsSign.cmd +++ /dev/null @@ -1,105 +0,0 @@ -@echo off - -rem -rem Usage - Sign.cmd -rem - -setlocal - -echo --- BEGIN: sign.bat ------------------------------------- - -set TargetFile=%~1 -if not exist "%TargetFile%" ( - echo FATAL ERROR - %TargetFile% does not exist and cannot be signed - echo --- END: sign.bat ------------------------------------- - exit /b 1 -) -for %%i in ("%TargetFile%") do set TargetFileExtension="%%~xi" - -if "%SigningCertSha256%" == "" ( - set SigningCertSha256=%~dp0PlexOfficialSPC_sha256.pfx -) -if not exist "%SigningCertSha256%" ( - set SigningCertSha256=%~dp0PlexTestSPC.pfx -) -echo Signing with %SigningCertSha256% -set TimestampErrors=0 - -rem Create timestamp server lists... All servers on this list support both RFC 3161 and non-RFC variants -set ServerListRfc3161=(http://timestamp.digicert.com,http://timestamp.globalsign.com/scripts/timestamp.dll,http://timestamp.comodoca.com) - -rem Signing files SHA256 with the SHA256 cert -echo Adding SHA256 signature to %TargetFile%... -call :SignFile "%SigningCertSha256%" "%SigningCertPasswordSha256%" sha256 0 "%TargetFile%" "%ServerListRfc3161%" sha256 -if errorlevel 1 goto SignFailed - -echo Verifying signature... -signtool.exe verify /pa "%TargetFile%" -if errorlevel 1 ( - echo FATAL ERROR - could not verify signature for %TargetFile%. There were %TimestampErrors% timestamping errors. - echo --- END: sign.bat ------------------------------------------------------------ - exit /b 1 -) else ( - echo --- END: sign.bat ------------------------------------------------------------ - exit /b 0 -) - -:SignFailed - REM return an error code... - echo FAILED: FATAL ERROR - signing %TargetFile% failed. There were %TimestampErrors% timestamping errors. - echo --- END: sign.bat ------------------------------------------------------------- - exit /b 1 - -rem When timestamping a file, signtool will fail when the timestamp server doesn't respond. So we retry in a loop, in an attempt to reduce spurious failures. -rem When running signtool, we redirect output to null because signtool.exe may inadvertently output the word "error", causing msbuild to fail the build. -:SignFile - - setlocal - set CertFilePath=%1 - set CertPassword=%~2 - set SignatureHashAlgorithm=%3 - set AppendSignature=%4 - set TargetFilePath=%5 - set TimestampServerList=%~6 - set Rfc3161HashAlgorithm=%7 - - rem Compute password args - if "%CertPassword%" neq "" ( - set PasswordArgs=/p %CertPassword% - ) else ( - set PasswordArgs= - ) - - rem Compute append args - if "%AppendSignature%" == "1" ( - set AppendSignatureArgs=/as - ) else ( - set AppendSignatureArgs= - ) - - rem Compute timestamp server args - set TimestampArg1=/tr - set TimestampArg2=/td %Rfc3161HashAlgorithm% - - for /L %%a in (1,1,300) do ( - for %%s in %TimestampServerList% do ( - - rem echo signtool.exe sign %AppendSignatureArgs% /fd %SignatureHashAlgorithm% %TimestampArg1% %%s %TimestampArg2% /f %CertFilePath% %PasswordArgs% %TargetFilePath% - signtool.exe sign %AppendSignatureArgs% /fd %SignatureHashAlgorithm% %TimestampArg1% %%s %TimestampArg2% /f %CertFilePath% %PasswordArgs% %TargetFilePath% > NUL 2>&1 - if errorlevel 0 if not errorlevel 1 goto SignFileSuccess - - echo Signing attempt %%a failed. Probably cannot find the timestamp server at %%s - set /a TimestampErrors+=1 - ) - - echo Waiting 1 second... - choice /N /T:1 /D:Y >NUL - ) - - endlocal - exit /b 1 - -:SignFileSuccess - echo Signing succeeded - endlocal - exit /b 0 diff --git a/bundle/win/jellyfin-chevron-85.png b/bundle/win/jellyfin-chevron-85.png deleted file mode 100644 index a238119c4efdb04e492a19eca7b7aa21bf1ba6e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmV;r3PtsaP)`3?>sx*Ggy))iqo5~5K~HF5!9Q0GzBW=9j{pInu%LuR zBW|2_**||5{+AX0Yn)-WQsu)T-~ccnjG*(|;RSPN47#eH`(Ivo`DnvTL{S_<90H8M zNr3|dh%PZqpImx*zx6*gbJ56*DS+rM=g{@WQ*eL)Kr~&NJ8NkE%6{m-BzDA%yrmSa zbQtckEk&UV!O)^bnMou2mH*_xN&(y`#Kq^29DY@w z_dhsp-004n2NW^sN`X5I1rDR!>?tWJT!V{B+;@Ki*esIw7Xu{2N_x;;4zYfybl(k7-2wq@si&n3&;@ zc>osSePtV7{NWmKXxs5m7fpO9O+Q#j!BHlJPr~efkh5=nlwP5Rx!(!p(ige@7!Efp%V&Lmic1qi}mfN;4Ctkj;-JHyp^>RWIP4R$1i`(pZkFS znVBo}A?bYFAf&MK%+5ge`24moJ9#6q+W4_q-0$i{*{PL8| zW^rUqB&6UQ6rD5W=3eSwA80Tp3?gkjX>!q)r9YQu{l$xKMW!r-tqdcwflIcq#Z&^m45KDUgUpF z%FG0*nrF6|zux`^h%~(LkEtnxImG`lKw|RXqEd+_cgN39+pT88l&7Fg$PO=@-CO)m z$e4i;A~lb1V0V|TJ9>HxxGF9p-&inLkkXuEKPsh+Sbe;loq2TzNn9SiI((%vlW-KjkbAc{i z@tNuYW4-NvRK{dX)8duR@w(k0Qc3PYtu|7S?Fj|mj39#|@DGYjG)mMqQ`s)@TmWcA z$j~`n^=}9*NC`Dya9?KFIQ#njpMyx*>7zJ8N}2+8r4XAv3Ph^h^e)S?7{HB!e^LPz zpW{9MV>4$elq&HuquO*#(C`t31nYk@3>Qj46PW@cwIAQq_UkdyGVo^&sC|P*F7}@P zw8$LEmCp8K5@oL>Z?RJCOa54j0w%3EQy={2imc%qrJJsRC&5=+mW>|uX%o% zX`l4YtLgA&LB~ZXDB}%OR2E!}5L~4GXuNJ{#v~R2ixBIu-SssEX4Z1`OC#Z86rC`H zRnh=}?biD8O>i;Fd|)T2eVt)&2v|Oh<~46y-oD*~`%isDmSCkr)|E}I^>C4@tymA2 zDrS`T~pRj{o%FoN!&df&Dug{EdmP4$RvnO^OXPM? zlEG8{L$%TTkPo?1KuRCqIis$dHtdFQRXBJ|s_^izg?Gm_2; z5Jp~%e|bIvP^qXE8A}^uH#@H1e5n8}MbWgs4$}(SSEKaT(VAe&Uq`7mw4a7msvPAFame*`DR9O^ z>apX`EO*R>6T7?F|8V`R#X~RW4POKWmf}M^d+3h1U3&^*m^X%ykOKK*5e3^zH{f;e zck}Vj*xE3Fc+^S8_^yK;?(9Q8QR_y!K=F{z?LtdjdR>}P=bNpg`_KQ)72mZmEfV)_ zBWViKLq51b3a-sHAXf^=l>#CZ0NA!>*!-nO^54$~KeBKPAGZVr@73_^ zSd{HKLIDT`JHvhVhNtrXS9@N3`McYW)$L}16WptdB$gSX@fN{EC|uYTF-TLuZWK7q zerlinnd{)Q$358p@2^?Y`IeJBCRaZqIx@>&8|92!a;1aMM*&|51$1r-*w#>ED?h;Q z_zrLT%1ifu?mP8E=Nka%qf3&LO2WeQT3w9VKUksmyC4d19tzyKC}2C&&a^bx8mg_; zN7;iL@!?HysY1}LiipUMj>`!QidP2&s(f_{Uri?w@bRY$_bN~PV07*qoM6N<$g5bYD A00000 diff --git a/bundle/win/pmstheme.xml b/bundle/win/pmstheme.xml deleted file mode 100644 index 202bd4d..0000000 --- a/bundle/win/pmstheme.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - #(loc.Caption) - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI - - #(loc.Title) - - - - #(loc.HelpHeader) - #(loc.HelpText) - - - - #(loc.InstallHeader) - #(loc.InstallMessage) - - #(loc.InstallLicenseLinkText) - #(loc.InstallVersion) - #(loc.InstallAcceptCheckbox) - - - - - #(loc.DesktopShortcutCheckbox) - - - #(loc.OptionsHeader) - #(loc.OptionsLocationLabel) - - - - - - - #(loc.ProgressHeader) - #(loc.ProgressLabel) - #(loc.OverallProgressPackageText) - - - - - #(loc.ModifyHeader) - #(loc.ModifyMessage) - - - - - - #(loc.SuccessHeader) - - #(loc.SuccessRestartText) - - - - - #(loc.FailureHeader) - One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. - #(loc.FailureRestartText) - - - - \ No newline at end of file diff --git a/bundle/win/progress-bar.png b/bundle/win/progress-bar.png deleted file mode 100644 index cc3ea0d96409b860a9196fe4adab58d8dcab1f10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c9!2~3ILVmsiQk(@Ik;M!QddeWoSh3W;3@9k- t>EaktaVwdjNwv`3t67Xe(s?p7gI1LOlB2qO?|}*!JYD@<);T3K0RWpn71#g( diff --git a/bundle/win/wizard-image.png b/bundle/win/wizard-image.png new file mode 100644 index 0000000000000000000000000000000000000000..b76a0cfc3d5b6ca218ba0b2a54c5ca570eb7cb54 GIT binary patch literal 17827 zcmd741$11^vMwfO$zrAvGfNgTOBORTGc#FiFc%#0RUWRbsI9xao5D-KuNl_&b5HL&-5b$>xFyJpsVtpIH zFIWdjO=l1gI_WfIMP^faD^Bpo0YngDAj&P(gtFvn>etOB)0Z^dIg2y!9XL ze?0mh?f(x+0lNkc;Qx**IM9D%fd6fzLO}i^yT8clZ(RLN4gWQu|4_?c2Ke7aii(Wz zztHfn*#ZvZA87cyu>Qst5KaF?$6w_Bw-NrGln3Mg^Jo5*RQ_Ld4>Jh<|9cI+g8v_} z@J}HFmGZA(^%s4igZ(du)xYBEZ&3KRxKhDlXKbvwkjo~TTC2Xza$7(!FWw&x;}rz> z6qB`Bm3bdH++VxApIdC5J8ZohT>1H5`FY<~HkC61_yPP7AP_ltPaHvk2F7~o^2<6Z zkEGu2$>eP_kf5CTxt?+}OrH^0SwDKd1FvPjYmQFj8_ZL34^T6T5c8z6A8ap<<=ow4 z1wZtlJ{Li}s?)-iyCq(=M3aqRZTLKO7&r40KMD2zTiHQaD zfLxG3VKRr8^tqNS4`)+*(uoOt0F*(W#ml|#G(lEdR4x?=4HgVYxt-7y0JEjUp7VbA z_w`%a!NdfL(OLxg1A&L{>a2*W920s_ISJixdK&(Tj`wad0V|dPKP#(5_|4Aw8)Max z9r8^hr-UddY>^9fHV1A2)|t1_$Z1Gg*dID)b?baD`g#j`SUZ8?*!e+ZBKpMP8P`YqjH3?x^CAGrtpvFNy>2wPg-GIZNv1Da;>@VFG5yMgWd!}ku z)s7|+)z$cvGQgRZus7ZI7cj=e$Qo*V|4usS#=zrq6sj!+7s(t41}>S0dLaW6Dcnuz zUz%*I*K9FY_EmoV4PA6CnMokp(`S#pS@=M(#Th@lG#nI(Qgod`Y1lLrllyy3wB zJt>htUvp#qqnd#S*yk#qoHSf(cw|*VSmdHKXoUr0;^d}nRg&{EOmdLAm`T1>`*dw@ zFf%g|G=Q4%+Y0?dmCbaqA?F7tJ*AXFX|)jdRl+R&9G=A6Q%;!Q>*bj7ijgBAdFCakr4y1!C#_%;8 z_XZ98<*#+BxZb;2Nz9U29x3@G(LW<-!h{Jj$a)d+7?x|_Nz#Bihw^}^zgs6)rmesc z7Zie+v+meRK>k#CJz1Dm0@IKuc|7tK_dOISdJ|*y%FRQ!cmDm z$N_3G0I?_-of1Nr9Wh6aO@?(va z&yl3hK_wm<>h@(fd?Xw>q>>tD*{`t9r-|ry=UMt5?SqlRpAj+W`p?PQqxpS+VZ3i& z1SM(CO5|V2JKtSv_{uMR$Y%NfuCd7)(z@x59~q%+=lu8%e1?Nz#nb8e`t_yn-8^6+ zRzFMkRdp|_;KTc($D2^>R{!bkruX&q2h`=0eg3Wf1C4d)#+UC_RZDdbc0D`RW-)O$ zYrFQRS&%O1V~a!jU(B{)nT5d|`@kUFQ)*B9+dFC*%-8npeO}x(-GSHic6%#NFfy?u z@AvA9?1>}ya!SGW0&wM?Idi!)rVO?OFWrkSZ+(jiE=cvTR$jj=!E~$~4v19dV79NI z+Gb<69qRJh_rD%)a&)`fTARCvQ}g;wHBi<1nZQ4tpk1xpvL()0D|t<6%tC-t=J;HL zPdW}^s0RlJE1($}8J)N8#E5+KJZ$)XgrksBaZ1X`G0@TR?nJRxcbvDEDVMxI^n48E z^!mTw_jskr~BX_{h(UQnU&jREVSvWz2lUls+0_>S6!&a&PytHK$!s z;ijmNkdVOQdA(a(%S261009`>9{OfJktP&IZ`bnja?vwVEfHq&a(^a4;HsjjiKB_b z=XHyv?;|vMH7moo=C*3Y|$<~#*4JDCAcFP)6L$%MIGl!#}NYa16XYT z6-`aec}XLq?L>M0?N4rDi2t zEPo^PC94v>4Ekht*%7Pe8^`NL>k!Z-$1!+DiHB4j6!t??E zugxk_@5)uSDvw_~P&k7^(yjrYci^ZU#gZA!Zqt(zxH8#r5of4NGOq{G=+zsdZ|T5 z9vt-IzUrDwn>uE_mX_B*uw?6-j01=edY>}i9>t4?#Z8g0GJGukW|gg>xm(_Ve%O5e zfyxU;V7;QR{eF}g_Mn;^@4Wx$e)0NmGJT5 z-QAnF(pm?ro&k_Cvpfyz9iYHk(meWdwtnpN_UneRxM6r_E!qpHjM(OM>uu_3!tgPD;EeFDrNs8!El_UGVW- zk!{W`Vbg1UbZZKa|jd?_dkKaoUJSd30hg`QC?Z|7BFeH_<#7(?e+mk zd_uwHFY`r4TPMc2uDTG#S|vI;(A0W~kJODf8m)&I$Jg`Sa(y1!A)WQuD)xdv76s;c zRODzhz_;#qW4il`Br2_gLjB&J;}M(f*5LHr>qn|}I~cldXKylgfUAj>g+;CbP%VR_ zc8NDrDP;5ey7zhg>6Dr9s8-R1?cK)}A@YmA)D>T9&7QC_eqo@c3NBH6OZVc3^9v&z zD!!MY=gekH-z4Va%d)xbgC^?5$gyd#S+1|?d4JCM`c+@I%ZnY7i#s?sa-Ezv8`qLM zBjvRV{mD4ra!L>0fmKR z^+KzuKY;dbm*N&DUTqLmgfGZpcasdY0$%FpbNvvjy1($5>`=GuxBX68VJ8*RZ*`Gm zduj{sJC{p#MBa3B{LtC;k^uk(qL0k z^BT?_7ultqI_+C3b(-j?PG2um7L$&!)Sd;x8hrw>tXiHShPVXR}|YQ)ZwgV zkKdbp&s%8ZNu%W)4K3}F1IR)7%XvqQ`E>T=aXXREWnXg^P7L*)|LYD>K|#T487VCb z%k_8jY_41V!Ave^gZaagTA%~t|2&rig@7#>2BD1d$F(UQC<{fza~mOWH@Mvb2;;sZ zwDAsb&{JkQfSDw~e9~=qvE-nt)~Ewh_2r$+y{?f55KJoKjFgC$+)P==L5PB3{VMKh zHz`2b07JdKNa>u=J0}R4Id7 z-|koCxsM9-F%3&HW7tTW@A5^QX2h_rhO^@0K)SpXopWoj`a;t|j$R6-5+jkO1|!g} z%GcLJu=K(MZXb7IcTyej-25aUAt77V-0<>8fp#t{Bcnn@awHx<*~?{$de(k3%%N_# z-)NU1T!72{Z1KdM&gyD9qNB(OaX`DpWw;>@KfO=3+?_mxsS;C9hb7`PCFl1CnNv6g zDe2CP1d-S}h_|Sb5lIsmS<@dc()WJZ+@>F;RuJLps3a!=Q9KH}PyVo~L?V_@g2mh>M-GposO$1W2m%Qq)dxg{#-Z(ErN%>C+Fia+WYM{z;HM7dKTj()#t}& zGn!d)*crBOkcAFUg9&S4IVX-R`nq370&xg@NbG16dL)@a}QCREJ(Vkt5*0)gNN=bxw{4 zkxzKuDlU%eX*ZGjQLuCv6zmfwsYHy;K-(2?nsD?dAOX%oh#hs-H4V=lhB&i);WMIO zQB2aVjMrj9zHz*XPT~Ci=u{M`x%TL9V{Y+|1)x#NMMue!h0Uv7XtKYUavVbb(9j_| zT|3d10Sju!%*M@*6ABXr&nf!6?g8G6dB)8K#-6aK=N(P71&-*_ozE-7F*-hu$M3`0 zl>YwqVyvR#a350O8Mq^%9oU1ODTch}3S)`&>_VUs$1AGp1-~AYJh`Zli71q%`0|#p z*eMRqRcQad8~>G&^*|Z+Yw$&G;(XIX>y^7VZ~Sgt0((!AZTf;J%53YUZsbD;S*kq& zDq%9qweT!{W@958n}XZK6EOn=(wb07wigW~St&>!l~GA^7&>ng?kkr=KT~P1F@*Ht zJW}r&1(ri^t;9m#QEeU!e)C*Y=DU1zJp#y=P7Fbrm zvg55~V;3SOGx}0vW!Ku`wP;T(KpZwGN{$uXKD2WcZ3rD1Dgw8`^VAi4vApQmG2cy4 z(L(p4l|Z(2Erx^{PSxbnV^2d(*0>se(>Qw>aJ(Tw=o#$HLVzQ7>8lxxqRoNJNO0Pw(Bw zS-TLaFgTyLR~U4?N*nl+-gMJ-+l)4UjwdF(#EJZx_HAgdkFwXpsCirvTe|)xIlLPk zF-9n^#`du8&B%5jxA#-K+2-kPQ9n=8|7P;DB7l*BAvCo$Y1Z=dl)%T6{2&t?li5^e zo5>hzJ*ZZM*3PLD&~TiTeK`|VQ^SN}IYyo}i;@$dpy!aFPfo;PEle1{KD*En+tBJZ zJ8!SSCsKULOiyI~Wo1MDcnH3vM9#)*cDRHmGGH_c+mzhFG3Bj3Bj$twfz?6^zwtCM z-wLzkL>~J+KL&M1klcOEbur%7?fiEH3)KA=l`ofGPry~s|LragS@jQQlv%Syzo{TTnyUN+oem&NGT#XPJS_e*Vx(GM7-Tl(eGbscC*OKI^LzbWlp2i%p z9~C;yeDZtTf_{zn^FfxDmOgd)xov;2^Y!ZnWB*6D?@Q@TX?6AcZlb({OK+XWe5oQD zg=|2O@9p7?Ms71`2{?k3OZoC(k2ny)0g9GriTO(8j?L0*4uK&2vBGlin_AlK27Aq# zyAY#LBS;-kRcdC}(h0~`69#v!+>m@VoAXJHfL#cC-^pjq8m}>h{)EWd7y*>mx()#SHy}g?^6eP-0?;)%MKbTIMGRfH zoES>!$f>^F>%J_M#^YX{<&5$E%)rB`TrAu6@&58uQ@Im(u*7wc`8E6clfbLP*-Dd# z$rVQsy+@uyr2b(72P5P2v`uv8ew2O`g=Rm0eeDfS_6j!AWb5Z{_erQnU!S2NMr zptSX!2ubZUg91vtq~zqhCsg^em`L)=3PJQbE({E9vK9_Vq@{6$fm%}JEi(%VC*($^ zCG-j7gr_`6%zM5qaI{0vJh)&+N`eGPc+6hMgQ8SDlGR?k#wIaW0^wm(S-Ei86tYPl zBnE!u%b^4C4K0Rsozuqn&j1GJrC#_V?!xAy-!x4}YLb4@C+VpIo3bUwh@YoC=a`No z=4+@WB`uR9(s~&6bqA9Nz~2( zRKv*`5w35wri_ZNB72RhM4a>Kp;1(woNR3Am0YwO#`aze0H^P0{4l$SysR96Zsmjn?x4X-itvf(g)Yfn`XS~2@whsrv>_>firvw zJ$-L?S0Nw}SxHe*XcCmwSmFg8RX?rYXk$Z7{((Y?cJ8z<2P8N$TcSg4glj zm})!n;v;MVy6Mhst!dd|+qK$w9Ylk6F>G8*#d5#d>_ z2S3=kwuiF3xV?v7+^Z$Wqe0#BlQZ*cmswWS%pxn5Cx~~?JB3ikUhr+RxLc5M8Ls|z z?{ZB}0I`PEPh&Ri_Wb4~_l6ov6fujg|#m@RXD) z%W(}Ar_aiff;$D^_s6PiRxlRXT==Wg&wrdCv#{72xmZ*#Ul)3zaFA4%5xS}9e4MS9 z6YK`}y-meLNvg1_;D4e+%YP)!mu+IX5JhE}iy||>^fW}O+LYP%|EZvE`NiZZIzQpH z%OhRww3b!W0s<1p_xUyuX*ot1J7cY|xz|jc9G_a@pacZm>vQA6icNixV4)@#4BIP* z2v&tdj0*9ig=u>H3M_%}c0by%iR`w5kZ`GxCIJmO`q9Qa?ubO(VCw|GXJU~8huzj^ z@JLEgcBB1D&V=tXVh+dDyxhzMA7i`0>AD$i^lx%i=W&cGkFgkA7YtX&a$}$RzlKlF zGpWEk;Q5r$w{C^v+2ArdO#yNR<PyguMr(W>mY7yTw#SU0-Qfu0eOhv%r{egK2S^$_GaDC$B>pR>Q+N6zJMw;cL|_ggW>%7ls!nj-M79SIfsEKC=Y{lxwz#l(Rs2o4#r$7)542hsvN>EA^ zm9u~9EZ1wx998m_*w2GgQr*9W*;Z^XDWv{vSR*opi=yDH^F!CLs$0a2y<4I$BHqz* zH@N0&WHZ0W}yKlL1wY>T$pE|xup;-5nbAI@o zK00o4oYtl+sgi1Yxlw`ThD;^c7HR4?NwzNzA$Rx~>C6E^UjwQHrKvqz6+r5p_N1{H zS5U%pJ5tjFaIoEWi8=j=Eyc5ffC^ui3R%ADYJJ_r;z(*WieRQ~o@AibmytV6W(Ac% zW=T{hg{Koo|43%wuCN9j-&=A z+I9>!@NEZFfveWpBR3EVPjVUjDcGc81`_~*2_m;gTq!9*AIwb%lt053ZiXlC72s<$ zx+fZzG-ME(#4L~d+Tw0-_$5P^Qw%daeNYntlwQCrGu?#6f@{ovKp!I z+9f-wr=3w)47`2Sb4Bx%7>-6YRx`mVX$AU;1Y2Ghyb0UT4j|m z!C=bpT1;psWFCK>_PBM+L*xX4jgH(CVmDL>sQ3gU)csHf)xgov`XW3xIugoVv#97u z>HQi@7!gMq^wSQp?j{^bn9CNsCwYlLQlS>MrHJksu}eNRyUGyuXJ(kjMrXBZeQtUD%*6wYvpn<`TQ279FB{bpq;=E3Ve)fUC#lj z=DoqV`m`JTFB0q*yf14)G`a{7Nr<;QLXbF9!0@V*AfhHm$s?l(~D$MSD3@2 zV`I%RwtyLlO>5yv&}psgU+Xi#S%MSK59mj;#Sl#6s-R$8T1@|P?Vhwqt&(Q^ zkBZLy7(CGL!OY4!R}78PGFF}?7EbGyuFR!iIq%2O>c@o|PFx0gfyQ%yNBCY244@Ve zdXscApN`IJF(2lLaAD&FWA9r^%K5Y38g+I^8K$6?U9Bx?-$*ptly25M2dHWT z<;8`BK$mk13n7L+)z@3hknG-`%?EEaN~VJ&7Ob_qR%Br#D4XC*7)QGQ)$s5IN7aRHe5DXV4LNmx=Lf>CKW)ymepx|?<V~(|HOo8OS}t|MBW2?~%oNoGby*GaaR2Zydn_;=dnVpg~LLu&V z?7^2Zjm{%;C&}0(;Vrm2t&R#Y$n{4qClIyZQcMbl?k-YX-p26gFi9k3d5@2G2{N6posuetCyXWPcr@n8DGG{{g7IJp;@Bn zP+TNb9aF>jNHG7+bN2d?SoMgey28Xg)^yJKIi2F^h-e1!R+V4dkTFY`o^w%nbp+Ed7WBW2VJ z>MlR8*wWIE@#T7$l<6`4);N`xcD}%uOsq| z?}VOn&ySx;qo#@Z&E^}W@zz$;J89Oh5!D3&a`9wN#di%WL(_p*GVa3h_f5;}* z4qV&()FA)9_3X0puys7pZ3(N=n_K_}lEbowMTyP~y*A;cNt&7VLrQ zxNb$)I447W)2}NU*y~vTjJ8FHmo*niE%=SJVmAFN&$7K=`{+` zy_*^~8b9qNfO+giMSoy`D6D#;zj|Pw{%w!ZzwM&? zKHJc~(0l@>!hlr;i9pH6P_lE7Qs&k4{rGfZcRt{S40fhUrEy3xsDUjoH{{SWc2E7}=#Y&@KcR$xxsT z=q{YI(FFn?L6!h*KZcliOu#A5X65sqvApR~iY{%L7@LRn0fWch&a_<`|65(v>b|P# z8O7KtvwdIpH_8x=@zZX+9Z*2wu`r#oW!K#TMo~rcl%Mr-#^=iC%TKDN)@7!W1!i}$ z+s4rx z{jfh+Yg_txVDLtp^BN9;i4;!Y^!OQKs(%r^%88#d=r|poG!GXCw_0Zm4GD_t4kDL| zo5meUu($x$Uq7AfJ)m19UB*$DL!9CI zJ1&3Vm{-NVYtm!e#MQI1211IJ=7*?GIUxM;QYeye=%RI>wyi^0bZc;cHh44s{(jYd zqsL!hdB0`DPXrOl6@|gcg$#Q(j02S0CNKnHN)K4?!^~yA-szbMJ$HyaJA-h{FCOS(S(2nG(s3y z(H(9;h!Zpc179()*atB?yiAPue#!Xo#Ylb_3B-t7Qd~p8|1oF+nAU;UcJMiByv+jY z;WT(1R*^bVAdD>|cL_7~b#FWRbfu?gT^lP3VDf@XJuiSCSaC&A0b6kKMVY`7S#iS= z{gO_*86jpH*{{WniIdydNo5zA%#iB3!VA;iVVc12TYOSd4iDb!GEe0d>bVz zl`Di;F`QUnB;-k5DrId2OR;y=YB3*Q!4J#))fjCtIP=A@P( zASs(H{O|1Gq)omQDQf4n*KTgNd!fl-^zp&4Fo>C9DG4g+==cCr(S5#!jg3iKi0X?d zaS8-N4pyW+I4=INAB18Yb*@sb9%0>{n-1+ z$|HrVgxYj9xGqBr3s|rZcDGjDlbrH}_6CELP~`DBk_I>FQtYh$>NG#C=hrbb={wi? zY)R@6WN2Cy19-h2KRzYdT9qK5PfZY3<_`GZ`F*(&DvM>mgO&LJEA*@(mg4$aHrrM$ z2B*~W{bZ|@db7vn2uiMxE3Q9FQ z!w_X|{%B_?T9Nhr47sa7(ixaH!NS1UlHFnRyA+4=9_e9+ZU<3ma9KDf)a>pdKqdR7 z0BV(JjF}()<=Y0mcC*6j6%axnRa}?y<1+#oSv>CRKu^-Yp%2s+(m*w!r`7D^S6oDq zT7U}`zGTMRi`WhnBnSxuLkw8JV|cYYIv+X)W=SM8qOz$ijL^P6u8-`NI_ilGR_EPL z7rIaIJuU&?o?o_3ka}(_F1+52sNUBR6Ihh%z7OHZjiOxWP+iSvmy2}*Wtb}wP#(Pv z00;mXr#V6VvZ2fK#>{UR0qXJ~ph2v`$=9ZpihV0s0+*itl+1dlvb2`LB&(&*nwUP{ zn%$qgR$AtKgVp!8d~%LD4cRb$Ylq?Tb3bZyDjCx7V9j8TjY>F-`% z1)aNPxDGhgpyE~`DbZu8xBnwUi_iMc-Wf-o!7uQR4+eWFpU(V-OIC@lid+5h6Rt~h z@>9&=O*qXw0gW0g1A3x-!~q1@RV$9PxSAZSw(O97U|=CG$uHcrUC02OS|?<`p8n3p zh*@_jT14xGY_u4k&4Kf~_pr5>uPwYsu+Xm?bwx^upS2`asE`Pi_@4aMV*Mm88u&M^ zdezazW1JFQ5Oa^O7zRr;0?QvzBo}17HAex&y=GZ!`y4HnGVu1Fx^$ z;>MuX7^qkUPTqC)l}sKMj)#}qkB*KHOg|R(Zdu_`db*Xyy3@3^%FfdYGvHVYBExd=>aHR^3zhV7gWVMLQ(=IY5-$H~FgjnRD ztwhmvD&X&cyBqktDLLfi?K9GrY^LXwSC7B3-aY#?FxOaJ3W%!E$&{fcmxtVU3r{=L zxi|jgL4Alp_YyDEnG=qent-|-aj;9Jx(KjHAFViAyE)I0_DWSrOs(IVJ(kGs0~-hk z0KUz<1HJF($45@B0Q$A20Kkt_4MU}6GXtk(xDALi0iXqIC z%lSto!E=q2-2_;n$Ln^g(&9ke+tzeFz_N5S{#BUA0#KD@X!&BvpH6U7*y=+I89k*@EW)<7DO;h0-vj4`hZTp&H9HInBm&ehW8 z-xV>t@tFNI6$h@xBS)V}5waY%~V2dJddzukoYe8A3x6;~}d z^>ru}_FPWyVa=SdkAQGiZgS_RS!n?WJqZBV$UpY=39YKkVD8#4)fyTZ39IgK65`_4 z(@=0cI^NDmv@n1g(Y{ty;;3PP0x*r92F9wC)GxBMnPGkIoQC5<9Cy$&H$yLOdU9WYJGd@RD+RcXqRq3AiGH3_8jY6TF%{JU9H z>`)@S&08bg5_*c4LaD@ixdW=YdJgz5G#OIuT`RP=Hb5}G_}w?;0EkUYs9`So+g9q>??Irx;X$ILsVB1uC+({7?R+fd3d4T{K}D)hby z5e6Il8)}d3N+VikP@YNwl97F<59CtDd~*Y59U6wXQzj_j4x+r_^<@%g<8k=2QWF!g z!l;$e!>Jqp8gDWZ@hT| zKNz?^J17Nd8zC_U|J}XKx<0{-n zc2!R766J)ITegD%x{eBEkGjjz3UQQXTP!$UC=xb(IMKJ@r>-H2#$#%S3kpg|Kch0RhM5Kc|md4C?X0i3f5VBJyYnR%4~xhC_~w>zF;CfEX<(DGU~8A3lNhz3-E% zq%;j%LL5Yfvt+x(5bG@K8nMThDQdeSnc~L*uEf+-00t*!lIRet`&fYF>?Cc-0QuGM zcu{viKtPHJagFbpbu_aE=^xwdxxub}&N)4%Hv4vT7wH9R<;dy_0E3Z1ik8OBXYxza zLg0$PkHc5_O~ULkHYnZF>pODEB8tA;3NJ_$-sg59D9*?di2zyiJBv*<=F77f@-(6n zlQR5!QE^h`5kz<-8D^m-W7ZWs1Vm$~!24A!qemZnWi9hBB%sx1`?AxL>f`EU*Rsf| z3xUb-jd&Fr>s^8jm76vyBtTo$?oo&gM{tncF6sWMXzIZfQk^sUk_5T@HC#6FJE=>W zg+P(G0406bscFY@CwNi6Q$z1hA@<(TPGcME6IN+|KzfFHo6Bi{R{7#Jc%;OY*M$1x2l`TdbFU-uN`MmmIMda&tltd(i z2=)uDlI#Uo2DolS=3`}b3@i`qvgNvq3*+6b@qeQQ1N&9kD@C}c^ipT+&b<}af%rfG z8&Q^XIBr-bU6`*&O;j45+>I_iQ^uGugA_klA0h=sGTahpmqhOmzrl>`FZat&4}|%R zzC0XN+~u^S;!%Y29$nLbL}GkU*+elhemcL8Pa7WVwaw$lLjeIEa&1gU!0*@n&n?0f zlvysbOG_H^^77u^-eoFE3n3wpGI$;C7v0xCXsaI2%YbENzzsA8Vh|AMwG_-foW4`+ zJ)9ry8&S7JzNdliI7HlaCC;LNw#_ygW7zktR@}-7gARmqp_yFB19JpvCnb~XzIm=W z6}|WnW(>uvn<%b6k{%w)Z8{0Ck0J*y(FFA|nxD?7@yk+e_d$=Z8$+o%0A=smbCi5s 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 V1iM{O%>VZNWF?g(YQ=s8{~v4YfRz9M literal 0 HcmV?d00001