|  | @@ -1,3 +1,5 @@
 | 
	
		
			
				|  |  | +#nullable disable
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #pragma warning disable CS1591
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  using System;
 | 
	
	
		
			
				|  | @@ -36,7 +38,6 @@ using Emby.Server.Implementations.Playlists;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.Plugins;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.QuickConnect;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.ScheduledTasks;
 | 
	
		
			
				|  |  | -using Emby.Server.Implementations.Security;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.Serialization;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.Session;
 | 
	
		
			
				|  |  |  using Emby.Server.Implementations.SyncPlay;
 | 
	
	
		
			
				|  | @@ -57,7 +58,6 @@ using MediaBrowser.Controller.Channels;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Chapters;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Collections;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Configuration;
 | 
	
		
			
				|  |  | -using MediaBrowser.Controller.Devices;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Dlna;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Drawing;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Dto;
 | 
	
	
		
			
				|  | @@ -73,7 +73,6 @@ using MediaBrowser.Controller.Plugins;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Providers;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.QuickConnect;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Resolvers;
 | 
	
		
			
				|  |  | -using MediaBrowser.Controller.Security;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Session;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Sorting;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Subtitles;
 | 
	
	
		
			
				|  | @@ -101,7 +100,6 @@ using Microsoft.Extensions.Configuration;
 | 
	
		
			
				|  |  |  using Microsoft.Extensions.DependencyInjection;
 | 
	
		
			
				|  |  |  using Microsoft.Extensions.Logging;
 | 
	
		
			
				|  |  |  using Prometheus.DotNetRuntime;
 | 
	
		
			
				|  |  | -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
 | 
	
		
			
				|  |  |  using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace Emby.Server.Implementations
 | 
	
	
		
			
				|  | @@ -116,6 +114,11 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// The disposable parts.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        private readonly List<IDisposable> _disposableParts = new List<IDisposable>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          private readonly IFileSystem _fileSystemManager;
 | 
	
		
			
				|  |  |          private readonly IConfiguration _startupConfig;
 | 
	
		
			
				|  |  |          private readonly IXmlSerializer _xmlSerializer;
 | 
	
	
		
			
				|  | @@ -127,6 +130,62 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          private ISessionManager _sessionManager;
 | 
	
		
			
				|  |  |          private string[] _urlPrefixes;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets or sets all concrete types.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <value>All concrete types.</value>
 | 
	
		
			
				|  |  | +        private Type[] _allConcreteTypes;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private DeviceId _deviceId;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private bool _disposed = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Initializes a new instance of the <see cref="ApplicationHost"/> class.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param>
 | 
	
		
			
				|  |  | +        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
 | 
	
		
			
				|  |  | +        /// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param>
 | 
	
		
			
				|  |  | +        /// <param name="startupConfig">The <see cref="IConfiguration" /> interface.</param>
 | 
	
		
			
				|  |  | +        /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 | 
	
		
			
				|  |  | +        /// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param>
 | 
	
		
			
				|  |  | +        public ApplicationHost(
 | 
	
		
			
				|  |  | +            IServerApplicationPaths applicationPaths,
 | 
	
		
			
				|  |  | +            ILoggerFactory loggerFactory,
 | 
	
		
			
				|  |  | +            IStartupOptions options,
 | 
	
		
			
				|  |  | +            IConfiguration startupConfig,
 | 
	
		
			
				|  |  | +            IFileSystem fileSystem,
 | 
	
		
			
				|  |  | +            IServiceCollection serviceCollection)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            ApplicationPaths = applicationPaths;
 | 
	
		
			
				|  |  | +            LoggerFactory = loggerFactory;
 | 
	
		
			
				|  |  | +            _startupOptions = options;
 | 
	
		
			
				|  |  | +            _startupConfig = startupConfig;
 | 
	
		
			
				|  |  | +            _fileSystemManager = fileSystem;
 | 
	
		
			
				|  |  | +            ServiceCollection = serviceCollection;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Logger = LoggerFactory.CreateLogger<ApplicationHost>();
 | 
	
		
			
				|  |  | +            fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;
 | 
	
		
			
				|  |  | +            ApplicationVersionString = ApplicationVersion.ToString(3);
 | 
	
		
			
				|  |  | +            ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            _xmlSerializer = new MyXmlSerializer();
 | 
	
		
			
				|  |  | +            ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
 | 
	
		
			
				|  |  | +            _pluginManager = new PluginManager(
 | 
	
		
			
				|  |  | +                LoggerFactory.CreateLogger<PluginManager>(),
 | 
	
		
			
				|  |  | +                this,
 | 
	
		
			
				|  |  | +                ConfigurationManager.Configuration,
 | 
	
		
			
				|  |  | +                ApplicationPaths.PluginsPath,
 | 
	
		
			
				|  |  | +                ApplicationVersion);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Occurs when [has pending restart changed].
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public event EventHandler HasPendingRestartChanged;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets a value indicating whether this instance can self restart.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -148,13 +207,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |                      return false;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (OperatingSystem.Id == OperatingSystemId.Windows
 | 
	
		
			
				|  |  | -                    || OperatingSystem.Id == OperatingSystemId.Darwin)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    return true;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | +                return OperatingSystem.IsWindows() || OperatingSystem.IsMacOS();
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -163,11 +216,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          public INetworkManager NetManager { get; internal set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Occurs when [has pending restart changed].
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        public event EventHandler HasPendingRestartChanged;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets a value indicating whether this instance has changes that require the entire application to restart.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -195,17 +243,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// <value>The application paths.</value>
 | 
	
		
			
				|  |  |          protected IServerApplicationPaths ApplicationPaths { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets or sets all concrete types.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        /// <value>All concrete types.</value>
 | 
	
		
			
				|  |  | -        private Type[] _allConcreteTypes;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// The disposable parts.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        private readonly List<IDisposable> _disposableParts = new List<IDisposable>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets or sets the configuration manager.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -232,47 +269,55 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <inheritdoc />
 | 
	
		
			
				|  |  | +        public Version ApplicationVersion { get; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <inheritdoc />
 | 
	
		
			
				|  |  | +        public string ApplicationVersionString { get; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Initializes a new instance of the <see cref="ApplicationHost"/> class.
 | 
	
		
			
				|  |  | +        /// Gets the current application user agent.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param>
 | 
	
		
			
				|  |  | -        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
 | 
	
		
			
				|  |  | -        /// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param>
 | 
	
		
			
				|  |  | -        /// <param name="startupConfig">The <see cref="IConfiguration" /> interface.</param>
 | 
	
		
			
				|  |  | -        /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 | 
	
		
			
				|  |  | -        /// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param>
 | 
	
		
			
				|  |  | -        public ApplicationHost(
 | 
	
		
			
				|  |  | -            IServerApplicationPaths applicationPaths,
 | 
	
		
			
				|  |  | -            ILoggerFactory loggerFactory,
 | 
	
		
			
				|  |  | -            IStartupOptions options,
 | 
	
		
			
				|  |  | -            IConfiguration startupConfig,
 | 
	
		
			
				|  |  | -            IFileSystem fileSystem,
 | 
	
		
			
				|  |  | -            IServiceCollection serviceCollection)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ApplicationPaths = applicationPaths;
 | 
	
		
			
				|  |  | -            LoggerFactory = loggerFactory;
 | 
	
		
			
				|  |  | -            _startupOptions = options;
 | 
	
		
			
				|  |  | -            _startupConfig = startupConfig;
 | 
	
		
			
				|  |  | -            _fileSystemManager = fileSystem;
 | 
	
		
			
				|  |  | -            ServiceCollection = serviceCollection;
 | 
	
		
			
				|  |  | +        /// <value>The application user agent.</value>
 | 
	
		
			
				|  |  | +        public string ApplicationUserAgent { get; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Logger = LoggerFactory.CreateLogger<ApplicationHost>();
 | 
	
		
			
				|  |  | -            fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets the email address for use within a comment section of a user agent field.
 | 
	
		
			
				|  |  | +        /// Presently used to provide contact information to MusicBrainz service.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string ApplicationUserAgentAddress => "team@jellyfin.org";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;
 | 
	
		
			
				|  |  | -            ApplicationVersionString = ApplicationVersion.ToString(3);
 | 
	
		
			
				|  |  | -            ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets the current application name.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <value>The application name.</value>
 | 
	
		
			
				|  |  | +        public string ApplicationProductName { get; } = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            _xmlSerializer = new MyXmlSerializer();
 | 
	
		
			
				|  |  | -            ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
 | 
	
		
			
				|  |  | -            _pluginManager = new PluginManager(
 | 
	
		
			
				|  |  | -                LoggerFactory.CreateLogger<PluginManager>(),
 | 
	
		
			
				|  |  | -                this,
 | 
	
		
			
				|  |  | -                ConfigurationManager.Configuration,
 | 
	
		
			
				|  |  | -                ApplicationPaths.PluginsPath,
 | 
	
		
			
				|  |  | -                ApplicationVersion);
 | 
	
		
			
				|  |  | +        public string SystemId
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            get
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                return _deviceId.Value;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <inheritdoc/>
 | 
	
		
			
				|  |  | +        public string Name => ApplicationProductName;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private CertificateInfo CertificateInfo { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public X509Certificate2 Certificate { get; private set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <inheritdoc/>
 | 
	
		
			
				|  |  | +        public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public string FriendlyName =>
 | 
	
		
			
				|  |  | +            string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName)
 | 
	
		
			
				|  |  | +                ? Environment.MachineName
 | 
	
		
			
				|  |  | +                : ConfigurationManager.Configuration.ServerName;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Temporary function to migration network settings out of system.xml and into network.xml.
 | 
	
		
			
				|  |  |          /// TODO: remove at the point when a fixed migration path has been decided upon.
 | 
	
	
		
			
				|  | @@ -305,48 +350,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |                  .Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /// <inheritdoc />
 | 
	
		
			
				|  |  | -        public Version ApplicationVersion { get; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <inheritdoc />
 | 
	
		
			
				|  |  | -        public string ApplicationVersionString { get; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets the current application user agent.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        /// <value>The application user agent.</value>
 | 
	
		
			
				|  |  | -        public string ApplicationUserAgent { get; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets the email address for use within a comment section of a user agent field.
 | 
	
		
			
				|  |  | -        /// Presently used to provide contact information to MusicBrainz service.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        public string ApplicationUserAgentAddress => "team@jellyfin.org";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets the current application name.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        /// <value>The application name.</value>
 | 
	
		
			
				|  |  | -        public string ApplicationProductName { get; } = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private DeviceId _deviceId;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public string SystemId
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            get
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (_deviceId == null)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    _deviceId = new DeviceId(ApplicationPaths, LoggerFactory);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                return _deviceId.Value;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <inheritdoc/>
 | 
	
		
			
				|  |  | -        public string Name => ApplicationProductName;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Creates an instance of type and resolves all constructor dependencies.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -370,10 +373,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// <returns>System.Object.</returns>
 | 
	
		
			
				|  |  |          protected object CreateInstanceSafe(Type type)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (_creatingInstances == null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                _creatingInstances = new List<Type>();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            _creatingInstances ??= new List<Type>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (_creatingInstances.IndexOf(type) != -1)
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -467,6 +467,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Runs the startup tasks.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="cancellationToken">The cancellation token.</param>
 | 
	
		
			
				|  |  |          /// <returns><see cref="Task" />.</returns>
 | 
	
		
			
				|  |  |          public async Task RunStartupTasksAsync(CancellationToken cancellationToken)
 | 
	
		
			
				|  |  |          {
 | 
	
	
		
			
				|  | @@ -480,7 +481,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              _mediaEncoder.SetFFmpegPath();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Logger.LogInformation("ServerId: {0}", SystemId);
 | 
	
		
			
				|  |  | +            Logger.LogInformation("ServerId: {ServerId}", SystemId);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var entryPoints = GetExports<IServerEntryPoint>();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -605,8 +606,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ServiceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<EncodingHelper>();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -628,8 +627,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ServiceCollection.AddSingleton<IDeviceManager, DeviceManager>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
 | 
	
	
		
			
				|  | @@ -665,8 +662,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ServiceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
 | 
	
		
			
				|  |  | -            ServiceCollection.AddSingleton<ISessionContext, SessionContext>();
 | 
	
		
			
				|  |  | +            ServiceCollection.AddScoped<ISessionContext, SessionContext>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IAuthService, AuthService>();
 | 
	
		
			
				|  |  |              ServiceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
 | 
	
	
		
			
				|  | @@ -695,8 +691,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |              _mediaEncoder = Resolve<IMediaEncoder>();
 | 
	
		
			
				|  |  |              _sessionManager = Resolve<ISessionManager>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              SetStaticProperties();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
 | 
	
	
		
			
				|  | @@ -725,7 +719,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              logger.LogInformation("Environment Variables: {EnvVars}", relevantEnvVars);
 | 
	
		
			
				|  |  |              logger.LogInformation("Arguments: {Args}", commandLineArgs);
 | 
	
		
			
				|  |  | -            logger.LogInformation("Operating system: {OS}", OperatingSystem.Name);
 | 
	
		
			
				|  |  | +            logger.LogInformation("Operating system: {OS}", MediaBrowser.Common.System.OperatingSystem.Name);
 | 
	
		
			
				|  |  |              logger.LogInformation("Architecture: {Architecture}", RuntimeInformation.OSArchitecture);
 | 
	
		
			
				|  |  |              logger.LogInformation("64-Bit Process: {Is64Bit}", Environment.Is64BitProcess);
 | 
	
		
			
				|  |  |              logger.LogInformation("User Interactive: {IsUserInteractive}", Environment.UserInteractive);
 | 
	
	
		
			
				|  | @@ -877,10 +871,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private CertificateInfo CertificateInfo { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public X509Certificate2 Certificate { get; private set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          private IEnumerable<string> GetUrlPrefixes()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var hosts = new[] { "+" };
 | 
	
	
		
			
				|  | @@ -1102,16 +1092,14 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |                  ItemsByNamePath = ApplicationPaths.InternalMetadataPath,
 | 
	
		
			
				|  |  |                  InternalMetadataPath = ApplicationPaths.InternalMetadataPath,
 | 
	
		
			
				|  |  |                  CachePath = ApplicationPaths.CachePath,
 | 
	
		
			
				|  |  | -                OperatingSystem = OperatingSystem.Id.ToString(),
 | 
	
		
			
				|  |  | -                OperatingSystemDisplayName = OperatingSystem.Name,
 | 
	
		
			
				|  |  | +                OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
 | 
	
		
			
				|  |  | +                OperatingSystemDisplayName = MediaBrowser.Common.System.OperatingSystem.Name,
 | 
	
		
			
				|  |  |                  CanSelfRestart = CanSelfRestart,
 | 
	
		
			
				|  |  |                  CanLaunchWebBrowser = CanLaunchWebBrowser,
 | 
	
		
			
				|  |  | -                HasUpdateAvailable = HasUpdateAvailable,
 | 
	
		
			
				|  |  |                  TranscodingTempPath = ConfigurationManager.GetTranscodePath(),
 | 
	
		
			
				|  |  |                  ServerName = FriendlyName,
 | 
	
		
			
				|  |  |                  LocalAddress = GetSmartApiUrl(source),
 | 
	
		
			
				|  |  |                  SupportsLibraryMonitor = true,
 | 
	
		
			
				|  |  | -                EncoderLocation = _mediaEncoder.EncoderLocation,
 | 
	
		
			
				|  |  |                  SystemArchitecture = RuntimeInformation.OSArchitecture,
 | 
	
		
			
				|  |  |                  PackageName = _startupOptions.PackageName
 | 
	
		
			
				|  |  |              };
 | 
	
	
		
			
				|  | @@ -1122,25 +1110,22 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |                  .Select(i => new WakeOnLanInfo(i))
 | 
	
		
			
				|  |  |                  .ToList();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public PublicSystemInfo GetPublicSystemInfo(IPAddress source)
 | 
	
		
			
				|  |  | +        public PublicSystemInfo GetPublicSystemInfo(IPAddress address)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              return new PublicSystemInfo
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  Version = ApplicationVersionString,
 | 
	
		
			
				|  |  |                  ProductName = ApplicationProductName,
 | 
	
		
			
				|  |  |                  Id = SystemId,
 | 
	
		
			
				|  |  | -                OperatingSystem = OperatingSystem.Id.ToString(),
 | 
	
		
			
				|  |  | +                OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
 | 
	
		
			
				|  |  |                  ServerName = FriendlyName,
 | 
	
		
			
				|  |  | -                LocalAddress = GetSmartApiUrl(source),
 | 
	
		
			
				|  |  | +                LocalAddress = GetSmartApiUrl(address),
 | 
	
		
			
				|  |  |                  StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <inheritdoc/>
 | 
	
		
			
				|  |  | -        public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <inheritdoc/>
 | 
	
		
			
				|  |  | -        public string GetSmartApiUrl(IPAddress ipAddress, int? port = null)
 | 
	
		
			
				|  |  | +        public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              // Published server ends with a /
 | 
	
		
			
				|  |  |              if (!string.IsNullOrEmpty(PublishedServerUrl))
 | 
	
	
		
			
				|  | @@ -1149,7 +1134,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |                  return PublishedServerUrl.Trim('/');
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            string smart = NetManager.GetBindInterface(ipAddress, out port);
 | 
	
		
			
				|  |  | +            string smart = NetManager.GetBindInterface(remoteAddr, out port);
 | 
	
		
			
				|  |  |              // If the smartAPI doesn't start with http then treat it as a host or ip.
 | 
	
		
			
				|  |  |              if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -1211,27 +1196,20 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <inheritdoc/>
 | 
	
		
			
				|  |  | -        public string GetLocalApiUrl(string host, string scheme = null, int? port = null)
 | 
	
		
			
				|  |  | +        public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              // NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does
 | 
	
		
			
				|  |  |              // not. For consistency, always trim the trailing slash.
 | 
	
		
			
				|  |  |              return new UriBuilder
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp),
 | 
	
		
			
				|  |  | -                Host = host,
 | 
	
		
			
				|  |  | +                Host = hostname,
 | 
	
		
			
				|  |  |                  Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort),
 | 
	
		
			
				|  |  |                  Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl
 | 
	
		
			
				|  |  |              }.ToString().TrimEnd('/');
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public string FriendlyName =>
 | 
	
		
			
				|  |  | -            string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName)
 | 
	
		
			
				|  |  | -                ? Environment.MachineName
 | 
	
		
			
				|  |  | -                : ConfigurationManager.Configuration.ServerName;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Shuts down.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | +        /// <inheritdoc />
 | 
	
		
			
				|  |  |          public async Task Shutdown()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              if (IsShuttingDown)
 | 
	
	
		
			
				|  | @@ -1255,26 +1233,6 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          protected abstract void ShutdownInternal();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public event EventHandler HasUpdateAvailableChanged;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private bool _hasUpdateAvailable;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public bool HasUpdateAvailable
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            get => _hasUpdateAvailable;
 | 
	
		
			
				|  |  | -            set
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                var fireEvent = value && !_hasUpdateAvailable;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                _hasUpdateAvailable = value;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                if (fireEvent)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    HasUpdateAvailableChanged?.Invoke(this, EventArgs.Empty);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          public IEnumerable<Assembly> GetApiPluginAssemblies()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var assemblies = _allConcreteTypes
 | 
	
	
		
			
				|  | @@ -1289,41 +1247,7 @@ namespace Emby.Server.Implementations
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public virtual void LaunchUrl(string url)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (!CanLaunchWebBrowser)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                throw new NotSupportedException();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var process = new Process
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                StartInfo = new ProcessStartInfo
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    FileName = url,
 | 
	
		
			
				|  |  | -                    UseShellExecute = true,
 | 
	
		
			
				|  |  | -                    ErrorDialog = false
 | 
	
		
			
				|  |  | -                },
 | 
	
		
			
				|  |  | -                EnableRaisingEvents = true
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            process.Exited += (sender, args) => ((Process)sender).Dispose();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                process.Start();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (Exception ex)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Logger.LogError(ex, "Error launching url: {url}", url);
 | 
	
		
			
				|  |  | -                throw;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private bool _disposed = false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | +        /// <inheritdoc />
 | 
	
		
			
				|  |  |          public void Dispose()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              Dispose(true);
 |