2
0
Эх сурвалжийг харах

Merge branch 'dev' into fix-issue-320

Joshua M. Boniface 6 жил өмнө
parent
commit
64a1a7560e

+ 0 - 68
Build-JellyFin.ps1

@@ -1,68 +0,0 @@
-[CmdletBinding()]
-param(
-    [switch]$InstallFFMPEG,
-    [switch]$GenerateZip,
-    [string]$InstallLocation = "$Env:AppData/JellyFin-Server/",
-    [ValidateSet('Debug','Release')][string]$BuildType = 'Release',
-    [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal',
-    [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win',
-    [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64'
-)
-function Build-JellyFin {
-    if($Architecture -eq 'arm64'){
-        if($WindowsVersion -ne 'win10'){
-            Write-Error "arm64 only supported with Windows10 Version"
-            exit
-        }
-    }
-    if($Architecture -eq 'arm'){
-        if($WindowsVersion -notin @('win10','win81','win8')){
-            Write-Error "arm only supported with Windows 8 or higher"
-            exit
-        }
-    }
-    dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity
-}
-
-function Install-FFMPEG {
-    param(
-        [string]$InstallLocation,
-        [string]$Architecture
-    )
-    Write-Verbose "Checking Architecture"
-    if($Architecture -notin @('x86','x64')){
-        Write-Warning "No builds available for your selected architecture of $Architecture"
-        Write-Warning "FFMPEG will not be installed" 
-    }elseif($Architecture -eq 'x64'){
-         Write-Verbose "Downloading 64 bit FFMPEG"
-         Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$env:TEMP/fmmpeg.zip" | Write-Verbose
-    }else{
-         Write-Verbose "Downloading 32 bit FFMPEG"
-         Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$env:TEMP/fmmpeg.zip" | Write-Verbose
-    }
-   
-    Expand-Archive "$env:TEMP/fmmpeg.zip" -DestinationPath "$env:TEMP/ffmpeg/" | Write-Verbose
-    if($Architecture -eq 'x64'){
-        Write-Verbose "Copying Binaries to Jellyfin location"
-        Get-ChildItem "$env:temp/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object {
-            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
-        }
-    }else{
-        Write-Verbose "Copying Binaries to Jellyfin location"
-        Get-ChildItem "$env:temp/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object {
-            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
-        }
-    }
-    Remove-Item "$env:TEMP/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose
-    Remove-Item "$env:TEMP/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose
-}
-Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture"
-Build-JellyFin
-if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){
-    Write-Verbose "Starting FFMPEG Install"
-    Install-FFMPEG $InstallLocation $Architecture
-}
-if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){
-    Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force
-}
-Write-Verbose "Finished"

+ 2 - 0
CONTRIBUTORS.md

@@ -5,6 +5,8 @@
  - [JustAMan](https://github.com/JustAMan)
  - [dcrdev](https://github.com/dcrdev)
  - [EraYaN](https://github.com/EraYaN)
+ - [flemse](https://github.com/flemse)
+ - [bfayers](https://github.com/bfayers)
 
 # Emby Contributors
 

+ 30 - 5
Emby.Server.Implementations/ApplicationHost.cs

@@ -1962,6 +1962,7 @@ namespace Emby.Server.Implementations
         public async Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken)
         {
             var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
+            var wanAddress = await GetWanApiUrl(cancellationToken).ConfigureAwait(false);
 
             return new SystemInfo
             {
@@ -1984,8 +1985,7 @@ namespace Emby.Server.Implementations
                 CanSelfRestart = CanSelfRestart,
                 CanSelfUpdate = CanSelfUpdate,
                 CanLaunchWebBrowser = CanLaunchWebBrowser,
-                // TODO - remove WanAddress
-                WanAddress = "0.0.0.0",
+                WanAddress = wanAddress,
                 HasUpdateAvailable = HasUpdateAvailable,
                 SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
                 TranscodingTempPath = ApplicationPaths.TranscodingTempPath,
@@ -2012,14 +2012,13 @@ namespace Emby.Server.Implementations
         public async Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken)
         {
             var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
-
+            var wanAddress = await GetWanApiUrl(cancellationToken).ConfigureAwait(false);
             return new PublicSystemInfo
             {
                 Version = ApplicationVersion.ToString(),
                 Id = SystemId,
                 OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(),
-                // TODO - remove WanAddress
-                WanAddress = "0.0.0.0",
+                WanAddress = wanAddress,
                 ServerName = FriendlyName,
                 LocalAddress = localAddress
             };
@@ -2060,6 +2059,32 @@ namespace Emby.Server.Implementations
             return null;
         }
 
+        public async Task<string> GetWanApiUrl(CancellationToken cancellationToken)
+        {
+            var url = "http://ipv4.icanhazip.com";
+            try
+            {
+                using (var response = await HttpClient.Get(new HttpRequestOptions
+                {
+                    Url = url,
+                    LogErrorResponseBody = false,
+                    LogErrors = false,
+                    LogRequest = false,
+                    TimeoutMs = 10000,
+                    BufferContent = false,
+                    CancellationToken = cancellationToken
+                }))
+                {
+                    return GetLocalApiUrl(response.ReadToEnd().Trim());
+                }
+            }
+            catch(Exception ex)
+            {
+                Logger.ErrorException("Error getting WAN Ip address information", ex);
+            }
+            return null;
+        }
+
         public string GetLocalApiUrl(IpAddressInfo ipAddress)
         {
             if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6)

+ 8 - 5
Emby.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -112,12 +112,15 @@ namespace Emby.Server.Implementations.HttpServer
         /// </summary>
         private IHasHeaders GetHttpResult(IRequest requestContext, byte[] content, string contentType, bool addCachePrevention, IDictionary<string, string> responseHeaders = null)
         {
-            IHasHeaders result;
-
-            var compressionType = requestContext == null ? null : GetCompressionType(requestContext, content, contentType);
+            string compressionType = null;
+            bool isHeadRequest = false;
 
-            var isHeadRequest = string.Equals(requestContext.Verb, "head", StringComparison.OrdinalIgnoreCase);
+            if (requestContext != null) {
+                compressionType = GetCompressionType(requestContext, content, contentType);
+                isHeadRequest = string.Equals(requestContext.Verb, "head", StringComparison.OrdinalIgnoreCase);
+            }
 
+            IHasHeaders result;
             if (string.IsNullOrEmpty(compressionType))
             {
                 var contentLength = content.Length;
@@ -791,4 +794,4 @@ namespace Emby.Server.Implementations.HttpServer
     {
         byte[] Compress(byte[] content);
     }
-}
+}

+ 10 - 23
MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj

@@ -1,33 +1,20 @@
 <Project Sdk="Microsoft.NET.Sdk">
+
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
+
   <ItemGroup>
-    <Compile Include="..\SharedVersion.cs">
-      <Link>Properties\SharedVersion.cs</Link>
-    </Compile>
+    <Compile Include="..\SharedVersion.cs"/>
   </ItemGroup>
+
   <ItemGroup>
-    <ProjectReference Include="..\BDInfo\BDInfo.csproj">
-      <Project>{88ae38df-19d7-406f-a6a9-09527719a21e}</Project>
-      <Name>BDInfo</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
-      <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
-      <Name>MediaBrowser.Common</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
-      <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
-      <Name>MediaBrowser.Controller</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
-      <Name>MediaBrowser.Model</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\OpenSubtitlesHandler\OpenSubtitlesHandler.csproj">
-      <Project>{4a4402d4-e910-443b-b8fc-2c18286a2ca0}</Project>
-      <Name>OpenSubtitlesHandler</Name>
-    </ProjectReference>
+    <ProjectReference Include="..\BDInfo\BDInfo.csproj" />
+    <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
+    <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
+    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
+    <ProjectReference Include="..\OpenSubtitlesHandler\OpenSubtitlesHandler.csproj" />
   </ItemGroup>
+
 </Project>

+ 110 - 0
build-jellyfin.ps1

@@ -0,0 +1,110 @@
+[CmdletBinding()]
+param(
+    [switch]$InstallFFMPEG,
+    [switch]$InstallNSSM,
+    [switch]$GenerateZip,
+    [string]$InstallLocation = "$Env:AppData/Jellyfin-Server/",
+    [ValidateSet('Debug','Release')][string]$BuildType = 'Release',
+    [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal',
+    [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win',
+    [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64'
+)
+
+#PowershellCore and *nix check to make determine which temp dir to use.
+if(($PSVersionTable.PSEdition -eq 'Core') -and (-not $IsWindows)){
+    $TempDir = mktemp -d
+}else{
+    $TempDir = $env:Temp
+}
+
+function Build-JellyFin {
+    if(($Architecture -eq 'arm64') -and ($WindowsVersion -ne 'win10')){
+            Write-Error "arm64 only supported with Windows10 Version"
+            exit
+        }
+    if(($Architecture -eq 'arm') -and ($WindowsVersion -notin @('win10','win81','win8'))){
+            Write-Error "arm only supported with Windows 8 or higher"
+            exit
+        }
+    dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity
+}
+
+function Install-FFMPEG {
+    param(
+        [string]$InstallLocation,
+        [string]$Architecture
+    )
+    Write-Verbose "Checking Architecture"
+    if($Architecture -notin @('x86','x64')){
+        Write-Warning "No builds available for your selected architecture of $Architecture"
+        Write-Warning "FFMPEG will not be installed" 
+    }elseif($Architecture -eq 'x64'){
+         Write-Verbose "Downloading 64 bit FFMPEG"
+         Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
+    }else{
+         Write-Verbose "Downloading 32 bit FFMPEG"
+         Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
+    }
+   
+    Expand-Archive "$tempdir/fmmpeg.zip" -DestinationPath "$tempdir/ffmpeg/" | Write-Verbose
+    if($Architecture -eq 'x64'){
+        Write-Verbose "Copying Binaries to Jellyfin location"
+        Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object {
+            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+        }
+    }else{
+        Write-Verbose "Copying Binaries to Jellyfin location"
+        Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object {
+            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+        }
+    }
+    Remove-Item "$tempdir/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose
+    Remove-Item "$tempdir/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose
+}
+
+function Install-NSSM {
+    param(
+        [string]$InstallLocation,
+        [string]$Architecture
+    )
+    Write-Verbose "Checking Architecture"
+    if($Architecture -notin @('x86','x64')){
+        Write-Warning "No builds available for your selected architecture of $Architecture"
+        Write-Warning "NSSM will not be installed" 
+    }else{
+         Write-Verbose "Downloading NSSM"
+         Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose
+    }
+   
+    Expand-Archive "$tempdir/nssm.zip" -DestinationPath "$tempdir/nssm/" | Write-Verbose
+    if($Architecture -eq 'x64'){
+        Write-Verbose "Copying Binaries to Jellyfin location"
+        Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win64" | ForEach-Object {
+            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+        }
+    }else{
+        Write-Verbose "Copying Binaries to Jellyfin location"
+        Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win32" | ForEach-Object {
+            Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+        }
+    }
+    Remove-Item "$tempdir/nssm/" -Recurse -Force -ErrorAction Continue | Write-Verbose
+    Remove-Item "$tempdir/nssm.zip" -Force -ErrorAction Continue | Write-Verbose
+}
+
+Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture"
+Build-JellyFin
+if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){
+    Write-Verbose "Starting FFMPEG Install"
+    Install-FFMPEG $InstallLocation $Architecture
+}
+if($InstallNSSM.IsPresent -or ($InstallNSSM -eq $true)){
+    Write-Verbose "Starting NSSM Install"
+    Install-NSSM $InstallLocation $Architecture
+}
+Copy-Item .\install-jellyfin.ps1 $InstallLocation\install-jellyfin.ps1
+Copy-Item .\installjellyfin.bat $InstallLocation\installjellyfin.bat
+if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){
+    Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force
+}
+Write-Verbose "Finished"

+ 460 - 0
install-jellyfin.ps1

@@ -0,0 +1,460 @@
+[CmdletBinding()]
+
+param(
+    [Switch]$Quiet,
+    [Switch]$InstallAsService,
+    [pscredential]$ServiceUser,
+    [switch]$CreateDesktopShorcut,
+    [switch]$LaunchJellyfin,
+    [switch]$MigrateEmbyLibrary,
+    [string]$InstallLocation,
+    [string]$EmbyLibraryLocation,
+    [string]$JellyfinLibraryLocation
+)
+<# This form was created using POSHGUI.com  a free online gui designer for PowerShell
+.NAME
+    Install-Jellyfin
+#>
+
+#This doesn't need to be used by default anymore, but I am keeping it in as a function for future use.
+function Elevate-Window {
+    # Get the ID and security principal of the current user account
+    $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
+    $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
+ 
+    # Get the security principal for the Administrator role
+    $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
+ 
+    # Check to see if we are currently running "as Administrator"
+    if ($myWindowsPrincipal.IsInRole($adminRole))
+    {
+        # We are running "as Administrator" - so change the title and background color to indicate this
+        $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
+        $Host.UI.RawUI.BackgroundColor = "DarkBlue"
+        clear-host
+    }
+    else
+    {
+        # We are not running "as Administrator" - so relaunch as administrator
+   
+        # Create a new process object that starts PowerShell
+        $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
+   
+        # Specify the current script path and name as a parameter
+        $newProcess.Arguments = $myInvocation.MyCommand.Definition;
+   
+        # Indicate that the process should be elevated
+        $newProcess.Verb = "runas";
+   
+        # Start the new process
+        [System.Diagnostics.Process]::Start($newProcess);
+   
+        # Exit from the current, unelevated, process
+        exit
+    }
+}
+
+#FIXME The install methods should be a function that takes all the params, the quiet flag should be a paramset
+
+if($Quiet.IsPresent -or $Quiet -eq $true){
+    if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){
+        $Script:JellyfinDataDir = "$env:AppData\jellyfin\"
+    }else{
+        $Script:JellyfinDataDir = $JellyfinLibraryLocation
+    }
+    if([string]::IsNullOrEmpty($InstallLocation)){
+        $Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\"
+    }else{
+        $Script:DefaultJellyfinInstallDirectory = $InstallLocation
+    }
+    
+    if([string]::IsNullOrEmpty($EmbyLibraryLocation)){
+        $Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\data\"
+    }else{
+        $Script:defaultEmbyDataDir = $EmbyLibraryLocation
+    }
+    
+    if($InstallAsService.IsPresent -or $InstallAsService -eq $true){
+        $Script:InstallAsService = $true  
+    }else{$Script:InstallAsService = $false}
+    if($null -eq $ServiceUser){
+        $Script:InstallServiceAsUser = $false
+    }else{
+        $Script:InstallServiceAsUser = $true
+        $Script:UserCredentials = $ServiceUser
+        $Script:JellyfinDataDir = "C:\Users\$($Script:UserCredentials.UserName)\Appdata\Roaming\jellyfin\"}
+    if($CreateDesktopShorcut.IsPresent -or $CreateDesktopShorcut -eq $true) {$Script:CreateShortcut = $true}else{$Script:CreateShortcut = $false}
+    if($MigrateEmbyLibrary.IsPresent -or $MigrateEmbyLibrary -eq $true){$Script:MigrateLibrary = $true}else{$Script:MigrateLibrary = $false}
+    if($LaunchJellyfin.IsPresent -or $LaunchJellyfin -eq $true){$Script:StartJellyfin = $true}else{$Script:StartJellyfin = $false}
+    
+    if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){
+        mkdir $Script:DefaultJellyfinInstallDirectory
+    }
+    Copy-Item -Path $PSScriptRoot/* -DestinationPath "$Script:DefaultJellyfinInstallDirectory/" -Force -Recurse
+    if($Script:InstallAsService){
+        if($Script:InstallServiceAsUser){
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`"
+            Start-Sleep -Milliseconds 500
+            &sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)"
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START 
+        }else{
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`"
+            Start-Sleep -Milliseconds 500
+            #&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin ObjectName $Script:UserCredentials.UserName $Script:UserCredentials.GetNetworkCredential().Password
+            #Set-Service -Name Jellyfin -Credential $Script:UserCredentials
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START 
+        }
+    }
+    if($Script:MigrateLibrary){
+        Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse
+        Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse
+        Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse
+        Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse
+        Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir -force -Recurse
+    }
+    if($Script:CreateShortcut){
+        $WshShell = New-Object -comObject WScript.Shell
+        $Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk")
+        $Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe"
+        $Shortcut.Save()
+    }
+    if($Script:StartJellyfin){
+        if($Script:InstallAsService){
+            Get-Service Jellyfin | Start-Service
+        }else{
+            Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru
+        }
+    }
+}else{
+
+}
+Add-Type -AssemblyName System.Windows.Forms
+[System.Windows.Forms.Application]::EnableVisualStyles()
+
+$Script:JellyFinDataDir = "$env:AppData\jellyfin\"
+$Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\"
+$Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\"
+$Script:InstallAsService = $False
+$Script:InstallServiceAsUser = $false
+$Script:CreateShortcut = $false
+$Script:MigrateLibrary = $false
+$Script:StartJellyfin = $false
+
+function InstallJellyfin {
+    Write-Host "Install as service: $Script:InstallAsService" 
+    Write-Host "Install as serviceuser: $Script:InstallServiceAsUser"
+    Write-Host "Create Shortcut: $Script:CreateShortcut"
+    Write-Host "MigrateLibrary: $Script:MigrateLibrary"
+    $GUIElementsCollection | ForEach-Object {
+        $_.Enabled = $false
+    }
+    Write-Host "Making Jellyfin directory"
+    $ProgressBar.Minimum = 1
+    $ProgressBar.Maximum = 100
+    $ProgressBar.Value = 1
+    if($Script:DefaultJellyfinInstallDirectory -ne $InstallLocationBox.Text){
+        Write-Host "Custom Install Location Chosen: $($InstallLocationBox.Text)"
+        $Script:DefaultJellyfinInstallDirectory = $InstallLocationBox.Text
+    }
+    if($Script:JellyfinDataDir -ne $CustomLibraryBox.Text){
+        Write-Host "Custom Library Location Chosen: $($CustomLibraryBox.Text)"
+        $Script:JellyfinDataDir = $CustomLibraryBox.Text
+    }
+    if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){
+        mkdir $Script:DefaultJellyfinInstallDirectory
+    }
+    Write-Host "Copying Jellyfin Data"
+    $progressbar.Value = 10 
+    Copy-Item -Path $PSScriptRoot/* -Destination $Script:DefaultJellyfinInstallDirectory/ -Force -Recurse
+    Write-Host "Finished Copying"
+    $ProgressBar.Value = 50
+    if($Script:InstallAsService){
+        if($Script:InstallServiceAsUser){
+            Write-Host "Installing Service as user $($Script:UserCredentials.UserName)"
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`"
+            Start-Sleep -Milliseconds 2000
+            &sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)"
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START 
+        }else{
+            Write-Host "Installing Service as LocalSystem"
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`"
+            Start-Sleep -Milliseconds 2000
+            &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START 
+        }
+    }
+    $progressbar.Value = 60
+    if($Script:MigrateLibrary){
+        if($Script:defaultEmbyDataDir -ne $LibraryLocationBox.Text){
+           Write-Host "Custom location defined for emby library: $($LibraryLocationBox.Text)"
+           $Script:defaultEmbyDataDir = $LibraryLocationBox.Text
+        }
+        Write-Host "Copying emby library from $Script:defaultEmbyDataDir to $Script:JellyFinDataDir"
+        Write-Host "This could take a while depending on the size of your library. Please be patient"
+        Write-Host "Copying config"
+        Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse
+        Write-Host "Copying cache"
+        Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse
+        Write-Host "Copying data"
+        Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse
+        Write-Host "Copying metadata"
+        Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse
+        Write-Host "Copying root dir"
+        Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir  -force -Recurse
+    }
+    $progressbar.Value = 80
+    if($Script:CreateShortcut){
+        Write-Host "Creating Shortcut"
+        $WshShell = New-Object -comObject WScript.Shell
+        $Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk")
+        $Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe"
+        $Shortcut.Save()
+    }
+    $ProgressBar.Value = 90
+    if($Script:StartJellyfin){
+        if($Script:InstallAsService){
+            Write-Host "Starting Jellyfin Service"
+            Get-Service Jellyfin | Start-Service
+        }else{
+            Write-Host "Starting Jellyfin"
+            Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru
+        }
+    }
+    $progressbar.Value = 100
+    Write-Host Finished
+    $wshell = New-Object -ComObject Wscript.Shell
+    $wshell.Popup("Operation Completed",0,"Done",0x1)
+    $InstallForm.Close()
+}
+function ServiceBoxCheckChanged {
+    if($InstallAsServiceCheck.Checked){
+        $Script:InstallAsService         = $true
+        $ServiceUserLabel.Visible = $true
+        $ServiceUserLabel.Enabled = $true
+        $ServiceUserBox.Visible = $true
+        $ServiceUserBox.Enabled = $true
+    }else{
+        $Script:InstallAsService         = $false
+        $ServiceUserLabel.Visible = $false
+        $ServiceUserLabel.Enabled = $false
+        $ServiceUserBox.Visible = $false
+        $ServiceUserBox.Enabled = $false
+    }
+}
+function UserSelect {
+    if($ServiceUserBox.Text -eq 'Local System')
+    {
+        $Script:InstallServiceAsUser = $false
+         $Script:UserCredentials = $null
+         $ServiceUserBox.Items.RemoveAt(1)
+         $ServiceUserBox.Items.Add("Custom User")
+    }elseif($ServiceUserBox.Text -eq 'Custom User'){
+        $Script:InstallServiceAsUser = $true
+        $Script:UserCredentials = Get-Credential -Message "Please enter the credentials of the user you with to run Jellyfin Service as" -UserName $env:USERNAME
+        $ServiceUserBox.Items[1] = "$($Script:UserCredentials.UserName)"
+    }
+}
+function CreateShortcutBoxCheckChanged {
+    if($CreateShortcutCheck.Checked){
+        $Script:CreateShortcut = $true
+    }else{
+        $Script:CreateShortcut = $False
+    }
+}
+function StartJellyFinBoxCheckChanged {
+    if($StartProgramCheck.Checked){
+        $Script:StartJellyfin = $true
+    }else{
+        $Script:StartJellyfin = $false
+    }
+}
+
+function CustomLibraryCheckChanged {
+    if($CustomLibraryCheck.Checked){
+        $Script:UseCustomLibrary = $true
+        $CustomLibraryBox.Enabled = $true
+    }else{
+        $Script:UseCustomLibrary = $false
+        $CustomLibraryBox.Enabled = $false
+    }
+}
+
+function MigrateLibraryCheckboxChanged {
+
+    if($MigrateLibraryCheck.Checked){
+        $Script:MigrateLibrary         = $true
+        $LibraryMigrationLabel.Visible = $true
+        $LibraryMigrationLabel.Enabled = $true
+        $LibraryLocationBox.Visible = $true
+        $LibraryLocationBox.Enabled = $true
+    }else{
+        $Script:MigrateLibrary         = $false
+        $LibraryMigrationLabel.Visible = $false
+        $LibraryMigrationLabel.Enabled = $false
+        $LibraryLocationBox.Visible = $false
+        $LibraryLocationBox.Enabled = $false
+    }
+
+}
+
+
+#region begin GUI{ 
+
+$InstallForm                     = New-Object system.Windows.Forms.Form
+$InstallForm.ClientSize          = '320,240'
+$InstallForm.text                = "Terrible Jellyfin Installer"
+$InstallForm.TopMost             = $false
+
+$GUIElementsCollection = @()
+
+$InstallButton                   = New-Object system.Windows.Forms.Button
+$InstallButton.text              = "Install"
+$InstallButton.width             = 60
+$InstallButton.height            = 30
+$InstallButton.location          = New-Object System.Drawing.Point(5,5)
+$InstallButton.Font              = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $InstallButton
+
+$ProgressBar                     = New-Object system.Windows.Forms.ProgressBar
+$ProgressBar.width               = 245
+$ProgressBar.height              = 30
+$ProgressBar.location            = New-Object System.Drawing.Point(70,5)
+
+$InstallLocationLabel            = New-Object system.Windows.Forms.Label
+$InstallLocationLabel.text       = "Install Location"
+$InstallLocationLabel.TextAlign  = [System.Drawing.ContentAlignment]::MiddleLeft
+$InstallLocationLabel.AutoSize   = $true
+$InstallLocationLabel.width      = 100
+$InstallLocationLabel.height     = 20
+$InstallLocationLabel.location   = New-Object System.Drawing.Point(5,50)
+$InstallLocationLabel.Font       = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $InstallLocationLabel
+
+$InstallLocationBox              = New-Object system.Windows.Forms.TextBox
+$InstallLocationBox.multiline    = $false
+$InstallLocationBox.width        = 205
+$InstallLocationBox.height       = 20
+$InstallLocationBox.location     = New-Object System.Drawing.Point(110,50)
+$InstallLocationBox.Text            = $Script:DefaultJellyfinInstallDirectory
+$InstallLocationBox.Font         = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $InstallLocationBox
+
+$CustomLibraryCheck                       = New-Object system.Windows.Forms.CheckBox
+$CustomLibraryCheck.text                  = "Custom Library Location:"
+$CustomLibraryCheck.TextAlign  = [System.Drawing.ContentAlignment]::MiddleLeft
+$CustomLibraryCheck.AutoSize              = $false
+$CustomLibraryCheck.width                 = 180
+$CustomLibraryCheck.height                = 20
+$CustomLibraryCheck.location              = New-Object System.Drawing.Point(5,75)
+$CustomLibraryCheck.Font                  = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $CustomLibraryCheck
+
+$CustomLibraryBox              = New-Object system.Windows.Forms.TextBox
+$CustomLibraryBox.multiline    = $false
+$CustomLibraryBox.width        = 130
+$CustomLibraryBox.height       = 20
+$CustomLibraryBox.location     = New-Object System.Drawing.Point(185,75)
+$CustomLibraryBox.Text            = $Script:JellyFinDataDir
+$CustomLibraryBox.Font         = 'Microsoft Sans Serif,10'
+$CustomLibraryBox.Enabled      = $false
+$GUIElementsCollection += $CustomLibraryBox
+
+$InstallAsServiceCheck                       = New-Object system.Windows.Forms.CheckBox
+$InstallAsServiceCheck.text                  = "Install as Service"
+$InstallAsServiceCheck.AutoSize              = $false
+$InstallAsServiceCheck.width                 = 140
+$InstallAsServiceCheck.height                = 20
+$InstallAsServiceCheck.location              = New-Object System.Drawing.Point(5,125)
+$InstallAsServiceCheck.Font                  = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $InstallAsServiceCheck
+
+$ServiceUserLabel            = New-Object system.Windows.Forms.Label
+$ServiceUserLabel.text       = "Run Service As:"
+$ServiceUserLabel.AutoSize   = $true
+$ServiceUserLabel.TextAlign  = [System.Drawing.ContentAlignment]::MiddleLeft
+$ServiceUserLabel.width      = 100
+$ServiceUserLabel.height     = 20
+$ServiceUserLabel.location   = New-Object System.Drawing.Point(15,145)
+$ServiceUserLabel.Font       = 'Microsoft Sans Serif,10'
+$ServiceUserLabel.Visible    = $false
+$ServiceUserLabel.Enabled    = $false
+$GUIElementsCollection += $ServiceUserLabel
+
+$ServiceUserBox                  = New-Object system.Windows.Forms.ComboBox
+$ServiceUserBox.text             = "Run Service As"
+$ServiceUserBox.width            = 195
+$ServiceUserBox.height           = 20
+@('Local System','Custom User') | ForEach-Object {[void] $ServiceUserBox.Items.Add($_)}
+$ServiceUserBox.location         = New-Object System.Drawing.Point(120,145)
+$ServiceUserBox.Font             = 'Microsoft Sans Serif,10'
+$ServiceUserBox.Visible          = $false
+$ServiceUserBox.Enabled          = $false
+$ServiceUserBox.DropDownStyle    = [System.Windows.Forms.ComboBoxStyle]::DropDownList
+$GUIElementsCollection += $ServiceUserBox
+
+$MigrateLibraryCheck                       = New-Object system.Windows.Forms.CheckBox
+$MigrateLibraryCheck.text                  = "Import Emby Library"
+$MigrateLibraryCheck.AutoSize              = $false
+$MigrateLibraryCheck.width                 = 160
+$MigrateLibraryCheck.height                = 20
+$MigrateLibraryCheck.location              = New-Object System.Drawing.Point(5,170)
+$MigrateLibraryCheck.Font                  = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $MigrateLibraryCheck
+
+$LibraryMigrationLabel            = New-Object system.Windows.Forms.Label
+$LibraryMigrationLabel.text       = "Emby Library Path"
+$LibraryMigrationLabel.TextAlign  = [System.Drawing.ContentAlignment]::MiddleLeft
+$LibraryMigrationLabel.AutoSize   = $false
+$LibraryMigrationLabel.width      = 120
+$LibraryMigrationLabel.height     = 20
+$LibraryMigrationLabel.location   = New-Object System.Drawing.Point(15,190)
+$LibraryMigrationLabel.Font       = 'Microsoft Sans Serif,10'
+$LibraryMigrationLabel.Visible    = $false
+$LibraryMigrationLabel.Enabled    = $false
+$GUIElementsCollection += $LibraryMigrationLabel
+
+$LibraryLocationBox              = New-Object system.Windows.Forms.TextBox
+$LibraryLocationBox.multiline    = $false
+$LibraryLocationBox.width        = 175
+$LibraryLocationBox.height       = 20
+$LibraryLocationBox.location     = New-Object System.Drawing.Point(140,190)
+$LibraryLocationBox.Text            = $Script:defaultEmbyDataDir
+$LibraryLocationBox.Font         = 'Microsoft Sans Serif,10'
+$LibraryLocationBox.Visible      = $false
+$LibraryLocationBox.Enabled      = $false
+$GUIElementsCollection += $LibraryLocationBox
+
+$CreateShortcutCheck                       = New-Object system.Windows.Forms.CheckBox
+$CreateShortcutCheck.text                  = "Desktop Shortcut"
+$CreateShortcutCheck.AutoSize              = $false
+$CreateShortcutCheck.width                 = 150
+$CreateShortcutCheck.height                = 20
+$CreateShortcutCheck.location              = New-Object System.Drawing.Point(5,215)
+$CreateShortcutCheck.Font                  = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $CreateShortcutCheck
+
+$StartProgramCheck                       = New-Object system.Windows.Forms.CheckBox
+$StartProgramCheck.text                  = "Start Jellyfin"
+$StartProgramCheck.AutoSize              = $false
+$StartProgramCheck.width                 = 160
+$StartProgramCheck.height                = 20
+$StartProgramCheck.location              = New-Object System.Drawing.Point(160,215)
+$StartProgramCheck.Font                  = 'Microsoft Sans Serif,10'
+$GUIElementsCollection += $StartProgramCheck
+
+$InstallForm.controls.AddRange($GUIElementsCollection)
+$InstallForm.Controls.Add($ProgressBar)
+
+#region gui events {
+$InstallButton.Add_Click({ InstallJellyfin })
+$CustomLibraryCheck.Add_CheckedChanged({CustomLibraryCheckChanged})
+$InstallAsServiceCheck.Add_CheckedChanged({ServiceBoxCheckChanged})
+$ServiceUserBox.Add_SelectedValueChanged({ UserSelect })
+$MigrateLibraryCheck.Add_CheckedChanged({MigrateLibraryCheckboxChanged})
+$CreateShortcutCheck.Add_CheckedChanged({CreateShortcutBoxCheckChanged})
+$StartProgramCheck.Add_CheckedChanged({StartJellyFinBoxCheckChanged})
+#endregion events }
+
+#endregion GUI }
+
+
+[void]$InstallForm.ShowDialog()

+ 1 - 0
install.bat

@@ -0,0 +1 @@
+powershell.exe -executionpolicy Bypass -file install-jellyfin.ps1

+ 22 - 0
new-file-header.txt

@@ -0,0 +1,22 @@
+### This header should be used to start new files.
+### It provides an explicit per-file license reference that should be present on all new files.
+### To use this header, delete these lines and the following empty line, modify <filename> to
+### the proper full path, and then add new code following the header and a single empty line.
+
+// <filename>
+// Part of the Jellyfin project (https://jellyfin.media)
+//
+//    All copyright belongs to the Jellyfin contributors; a full list can
+//    be found in the file CONTRIBUTORS.md
+//
+//    This program is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, version 2.
+//
+//    This program is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program.  If not, see <https://www.gnu.org/licenses/>.